qooxdoo: implementing virtual scrolling list - qooxdoo

I try to implement a virtual scrolling loading qx.ui.mobile.list.List. At least a lazy loading one. There is no event available by qooxdoo to know when the List is scrolled to the end. Is there some way to know the 'onScrollEnd' event or is there a better way?

The team added the feature in August, called waypoints. Here's the post. You need to define offsets at which you wish the event to be risen. Here's example from the post to illustrate the idea.
var scrollContainer = page._getScrollContainer();
scrollContainer.setWaypointsY(["0%", "50%", "100%", 200, ".waypoint"]);
scrollContainer.addListener("waypoint", function(evt)
{
console.log("Waypoint reached:" + evt.getData());
}, this);
Event payload has the following structure.
{
"offset" : 0,
"input" : "10%",
"index" : 0,
"element" : 0
}
There's also a complete demo in mobile showcase of lazy-loading list implemented with waypoints: showcase, code.

Related

Access Crowd HTML output results

I'm creating a website using the Crowd HTML Elements that let users/workers annotate images with the bounding box format. The form looks like this:
<crowd-form>
<crowd-bounding-box
name="annotatedResult"
labels="['Referee', 'Player']"
src="https://s3.amazonaws.com/cv-demo-images/basketball-outdoor.jpg"
header="Draw boxes around each basketball player and referee in this image"
>
<full-instructions header="Bounding Box Instructions" >
<p>Use the bounding box tool to draw boxes around the requested target of interest:</p>
<ol>
<li>Draw a rectangle using your mouse over each instance of the target.</li>
<li>Make sure the box does not cut into the target, leave a 2 - 3 pixel margin</li>
<li>
When targets are overlapping, draw a box around each object,
include all contiguous parts of the target in the box.
Do not include parts that are completely overlapped by another object.
</li>
<li>
Do not include parts of the target that cannot be seen,
even though you think you can interpolate the whole shape of the target.
</li>
<li>Avoid shadows, they're not considered as a part of the target.</li>
<li>If the target goes off the screen, label up to the edge of the image.</li>
</ol>
</full-instructions>
<short-instructions>
Draw boxes around each basketball player and referee in this image.
</short-instructions>
</crowd-bounding-box>
</crowd-form>
The results of a worker's submission looks like the following:
{
"annotatedResult": {
"boundingBoxes": [
{
"height": 3300,
"label": "Dog",
"left": 536,
"top": 154,
"width": 4361
}
],
"inputImageProperties": {
"height": 3456,
"width": 5184
}
}
}
]
I'd like to take this output and write it to a database, pass it to AWS Lambda, store it as metadata, etc. but I don't know how to access the results. Is the JSON output a property of some HTML DOM property I can grab?
I can attach a javascript function to the submit action of the crowd-form portion...
<script>
document.querySelector('crowd-form').onsubmit = function() {
???
};
</script>
...but I'm not sure what object I need to grab to get the results. Thanks for your help!
You can access the bounding boxes during the onsubmit event like this:
<script>
document.querySelector('crowd-form').onsubmit = function(e) {
const boundingBoxes = document.querySelector('crowd-bounding-box').value.boundingBoxes || document.querySelector('crowd-bounding-box')._submittableValue.boundingBoxes;
}
</script>
Here's a working jsfiddle.
Your use case sounds interesting. If you don't mind sharing, please email me at samhenry#amazon.com and I may be able to help further.
Thank you,
Amazon Mechanical Turk

Strange jump on map after click

I have a strange problem with Here maps (JS).
After catching a click event on another element in the page (ex: custom bubble or search field) the map starts to flick like in the gif below
Example : https://i.imgur.com/kKrtwMj.gif
Any idea?
Thanks
I found a temporary solution.
It consist of re-instantiate the H.mapevents.MapEvents object and the H.mapevents.Behavior at the time the bug occurs.
mapEvents.dispose();
mapEvents = new H.mapevents.MapEvents(map);
behavior = new H.mapevents.Behavior(mapEvents, { kinetics: { duration: 3, power: 1 } });

how to update google chart?

Am new to angularjs/googlecharts and learning on the job. I've the following code in my controller which renders the piechart initially and has no issues.
There is a slider directive, which when changed (basically a date range slider), should update the columnchart with new data. But I don't know how to update the piechart data. I do get the new data from the backend without any problems though.
Here is the initialization code in controller:
$scope.piechart = {};
$scope.piechart.type ='PieChart';
piechartData = response.data.piechart;
var piechartoptions = {
'min-width':800,
'max-width':320,
'is3D':true,
'pieSliceText': 'label',
'pieSliceTextStyle': {fontSize: 10},
'chartArea' : { left: 30, top: 60 },
'backgroundColor': {fill:'transparent'},
'legend': {'textStyle':{'color': 'white',
'fontSize': 12},
'position': "top",
'maxLines':10,
'alignment':"start"},
'height':500
};
$scope.piechart.data = new google.visualization.DataTable(piechartData);
$scope.piechart.options = piechartoptions;
$scope.piechart.formatters = {};
In the directive (which is used in the html that the above controller's scope resides in), I've access to the chart like the following:
scope.$parent.piechart
So in a very naive way i did this but to no avail:
scope.$parent.piechart.data = new google.visualization.DataTable(response.data.piechart)
TIA for all the help.
I bumped into this issue today. An easy quick fix is to simply write
this.chartData = Object.assign([], this.chartData) to reassign to the exposed dataset property into your component so it triggers change detection.
More information from this issue in a different library:
valor-software/ng2-charts#959 (comment)
Hope this helps weary travellers :)
To achieve this you need to create watch on your slider model so when it gets change you need to update your pie chart model so it'll automatically update.
Watch
$scope.$watch('sliderModel',function(n,o) {
// update your new pie chart data here, I think you need to update below model only
$scope.piechart.data = new google.visualization.DataTable(piechartData);
}
It just an example. You have to update it with new data for pie chart.
Proper Angular way to use google chart
You should use google-chart directives to plot pie chart so this kind of problems will be solved automatically.
Have a look here - Angular-google-chart

Sencha Touch 1.1: Focusing TextArea after show method

I am currently creating a web-based Mobile App using Phonegap 1.6.0 and Sencha Touch 1.1. The app consists of a number of panels through which the user can click.
Some of these panels have textfields or textareas in them. Upon entering the panel, we want these to automatically be focused. This seems to work with textfields but not with textareas.
I have a Panel with the following component:
xtype: 'textareafield',
cls: 'jasbackblock',
id: 'addreactiontextarea',
height: '100%',
grow: true,
listeners: {
afterrender: function(cmp) {
console.log('Component rendered.');
cmp.fieldEl.dom.focus();
}
Whenever I first open the panel, it automatically focuses, which is good. However, when I leave the panel and then return to it, I cannot think of a good way to do this with events.
I have previously tried the show listener in the panel:
listeners: {
show: function(cmp) {
Ext.get('addreactiontextarea').fieldEl.dom.focus();
}
}
This gives me the following error:
Uncaught TypeError: Cannot read property 'fieldEl' of null
It seems that I cannot access the element during the show event. Is there any other event that I could use which fires every time the panel is loaded and allows me to access the textarea?
If it is any help, this is the method we call to switch from one panel to another:
function switchScreen(from, to, newArgs) {
/* Save screen information. */
if (from != -1)
historyStack.push([from, screenArgs]);
if (currentPage > 2) {
if (to != 3)
main.getComponent(3).hide();
app.getComponent(currentPage - 3).hide();
}
else
main.getComponent(currentPage).hide();
screenArgs = newArgs;
if (to > 2) {
main.setActiveItem(3);
app.setActiveItem(to - 3);
/* setActiveItem does not fire a screen's show event if it has been
* shown before. Since we want the code in the screen's show listener to
* be executed every time we switch to the screen, we call show manually
* just to fire the event. */
main.getComponent(3).show();
app.getComponent(to - 3).show();
}
else {
main.setActiveItem(to);
main.getComponent(to).show();
}
if (to == 0 || to == 1)
adMode = to;
else
adMode = -1;
currentPage = to;
}
I solved the problem. The issue was that I was not quite aware of how DOM elements worked.
Ext.get('id') returns the DOM element of the Javascript Object with the id 'id'. It does not return the object itself.
Ext.getCmp('id') returns the Javascript object with the id 'id'. Therefore, Ext.getCmp('id').fieldEl returns the same object as Ext.get('id').
Because of a bug in Sencha Touch 1.1, we chose to use the DOM focus function rather than the Sencha focus function. One can access this function by either Ext.getCmp('id').fieldEl.dom.focus() or Ext.get('id').dom.focus(). As you can see in my question, I mixed these up. Because of my lack of experience with DOM elements, I became even more confused when I tried to use an Object function this way. (Ext.get('id').reset() is simply illogical.)
If you have any questions, feel free to message.

Extjs 4.0.7, Editor Grid - how to get updated cell value?

I need to get(retrieve) updated cell value in controller. (MVC)
So I tried this,
var modified = this.getItemGrid().getStore().getUpdatedRecords();
console.log(modified); // return [] empty array
var modified = this.getItemList_Store().getUpdatedRecords();
console.log(modified); // return [] empty array
but always it returns empty array even I updated some cell value.
anybody know what I am doing wrong?
Here is my part of view code,
Ext.define("App.view.orders.ItemList_view", {
extend: "Ext.grid.Panel",
alias: "widget.itemList_view",
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
initComponent: function () {
this.store = "ItemList_store";
this.columns = [
{
xtype: 'checkcolumn', text: "Ship", width: 50, dataIndex: "DR"
},
{ header: "test", width: 100, dataIndex: "test",
editor: {
xtype : 'textfield'
}
}
];
this.selModel = Ext.create("Ext.selection.CheckboxModel");
//this.selModel = Ext.create("Ext.selection.CellModel"); // It does not works either.
this.callParent(arguments);
},
.
.
.
Thank you!
[EDIT]
Thank you very much for your answer! I have some more question about editor grid.
Its much different from Ext3. so I'm very confusing now :(
Q1. How to collect edited record data (once click button)?
the event fired once the grid cell be changed.
but I want collect edited grid record once I click the 'Update edited cell' button, and I want to update all together at the once.
In Ext3, I did like this,
(button) click : function(){
var modified = mygridStore.getModifiedRecords();
var recordsToSend = [];
Ext.each(modified, function(record){
recordsToSend.push(record.data);
});
var grid = Ext.getCmp('grid');
grid.el.mask('Updating','x-mask-loading');
grid.stopEditing();
recordsToSend = Ext.encode(recordsToSend);
Ext.Ajax.request({
url : '/test/test',
params : {
data : recordsToSend
},
success : function(response){
grid.el.unmask();
alert(response.responseText);
mygridStore.commitChanges();
},
failure : function(response){
mygridStore.rejectChanges();
}
});
}
How can I change the code for Extjs4 ?
Q2. I don't know still how to find out for changed checkcolumn.
I tried this, but I does not work for checkcolumn (of cause I tested after change checkbox)
// grid coumn
{
xtype: 'checkcolumn', header: "My Check Column", width: 50, dataIndex: "CH"
}
-
// in control
'myGrid': {
validateedit: function (plugin, edit) {
console.log(edit);
},
checkchange: function (plugin, edit) {
console.log(edit);
console.log(edit.value);
}
}
Q3. When I click the cell to edit, the show some HTML tag in -_-;;
I really appreciate for your help. and thank you very much for your valuable time!
The editors (cell editors or row editors) do not commit their values to the store until you complete the edit - which means pressing ENTER or blurring the active cell editor by clicking elsewhere on the page, or clicking the save button on the row editor form .
If your purpose for reading the updated value in your editor is to perform some kind of validation I would suggest simply listening to the validateedit event in your grid's controller, as described here.
The second argument that this event passes to your handler contains a lot of data about the edit that you can then perform validation with. If the edit doesn't pass your validation you can return false from your handler and the value in the celleditor will revert to it's original value. The validateedit event gets fired from the editor grid itself so you would add an event handler in your controller for it like this:
Ext.define('MyApp.controller.MyController', {
init: function() {
this.control({
'mygridpanel': {
validateedit: function(plugin, edit) {
// silly validation function
if (edit.value != 'A Valid Value') {
return false;
}
},
},
});
},
});
But you should check out the link above to see all the different objects available in that second argument I named edit.
The validateedit event is fired right before the record is committed into the store - after the user has already clicked ENTER or blurred the editor, i.e., while the editor is closing.
If you are trying to get the celleditor's value before it starts to close, for some reason other than validation for example, you could get the active celleditor's value like this:
// myGrid is a reference to your Ext.grid.Panel instance
if (myGrid.editingPlugin.editing) {
var value = myGrid.editingPlugin.getActiveEditor().field.value
console.log('value: ' + value);
}
If there is no active editor then myGrid.editingPlugin.getActiveEditor().field would throw an error, that's why I wrapped a conditional around it.
One other point I should make, for validation in editor grids, I found that it is easiest to just put a validator config in the grid column's editor definition. That will give you all the handy validation CSS while the user is setting the field's value and alert him if there is a problem with the value before he tries to save it.
To get an idea of what I mean, try entering letters in the date column of this example. Mouse over the editor cell and you will get the error message.
EDIT
It seems I misunderstood you original question, I'll break down my answers to your questions above though,
Question 1
Once you have completed an edit (clicked ENTER or ), your call to mygridStore.getModifiedRecords() should be working fine because the record will have been committed to the store. I see that it was not working, I will cover that in a moment.
I should point out that ExtJS4 has a store.sync() method as covered here.
Instead of extracting the modified records from the store, encoding them, manually doing an ajax request to save them to the server and then manually committing them you can call this sync method and it will take care of all of these actions for you.
If you have different URLs to handle the different create, read, update, destroy operations fired off by your store's load and sync methods, you can use the store's proxy api config to map your URLs to these operations as covered here. Or you can set-up your server side controller to be able to differentiate between your store's load request (read operations default to HTTP GET) and it's sync requests (create, update and delete operations default as HTTP POST).
There could be many different ways to go about doing this on the server side, the way I usually do it is to have one SQL stored procedure for GET requests and one for POST requests for any given store. I include the store name as an extra param and then my server side controller runs the appropriate stored procedure based on whether it is a GET or a POST request.
Question 2
Cell editing doesn't support checkcolumn edits. You have to make a different handler to listen to changes on that, something like this:
checkchange: function (column, rowIndex, checked) {
var record = store.getAt(rowIndex),
state = checked ? 'checked' : 'unchecked'
console.log('The record:');
console.log(record)
console.log('Column: ' + column.dataIndex);
console.log('was just ' + state)
}
Your call to mygridStore.getModifiedRecords() should be able to pick up the check changes also however, they get committed to the grid's store right away after being checked. store.sync() would also pick up changes to checkcolumn.
Question 3
I can't completely tell what is causing that problem but it may be something strange going on with your validateedit event, your handler should be returning true or false.
As I said earlier, I misunderstood the reason you originally asked this question. I thought you were trying to do some kind of validation while an edit was in progress. Now I understand that you are trying to get all of the modified records from the store after all the editing is completed in order to save them to the database, I was thrown off because in ExtJS 4 a store is usually saved to the database with the sync method as I mentioned.
In other words, you don't need the validateedit event or checkchange event to get a list of modified records.
The actual problem you are having might be trouble with the store's getter methods (getModifiedRecords, getUpdatedRecords) in some 4.07 versions, take a look at this post and this one.
So with all that said, the best advice I can give you is 1) try out the stores sync method for saving modified data to the database and 2) upgrade to ExtJS 4.1, there were a lot of bugs that were straightened out between 4.07 and 4.1 which you should be able to take advantage of, I cut out about 75% of the overrides I was using to make things work when I switched over to 4.1.
EditedGrid.plugins[0].completeEdit();
This will make the active changes commit and call edit event also.
listeners: {
validateedit: function (editor, e) {
//console.log(editor);
var oldVal = editor.originalValue;
var newVal = editor.value;
}
}

Resources