PDA

View Full Version : Load Mask



Susanta_bmc
4 Nov 2011, 10:13 PM
Hi when i am trying to a load mask while looping through a store for a grid, somehow i am not getting the mask, and it seems it gets kicked off after the loop is done, though i made a load mask call prior to the looping.

If i Put a debug point in between i could see the mask is being shown.
It is a MVC implementation
For example:




jobUnitSelection: function (combo, records, d) {
//Only one selection is allowed
var selectedRecord = records[0];
//doesnt kick off this event on the same selection as prev selection
/*var myMask = new Ext.LoadMask(Ext.getCmp('Demand').el, {
msg: this.xpleaseWait
});
myMask.show();*/
Ext.getCmp('Demand').el.mask(this.xpleaseWait);
this.updateGridOnJobUnitSelection(selectedRecord.get('dbVals'));
Ext.getCmp('Demand').el.unmask();
// myMask.destroy();
},
updateGridOnJobUnitSelection: function (jobunitVal) {
//check if it is FTE
var unit = 1;
if (jobunitVal === 'FTE_TO_MAN_DAYS') {
unit = 1 / parseFloat(fteToManDaysValue);

} else if (jobunitVal === 'MAN_TO_HOURS') {
unit = parseFloat(fteToManDaysValue);
}
//multiply on the unit and update
var store = Ext.getStore('DynamicStore');
var columns = Ext.getCmp('DynamicDemandGrid').columns;
var TotalColumnNumber = columns.length;
for (var i = 0; i < store.count(); i++) {
var rec = store.getAt(i);
for (var j = 2; j < TotalColumnNumber; j++) {
var valTobeUpdated = rec.get(columns[j].dataIndex);
valTobeUpdated = valTobeUpdated * unit;
if (valTobeUpdated != undefined) {
rec.set(columns[j].dataIndex, this.formatter(valTobeUpdated));
}
}
rec.commit();
}

},


Can anyone please help on this on what i could be missing.

Thanks

mitchellsimoens
5 Nov 2011, 6:04 AM
How long does it take to iterate through the Store? Could it be faster than it takes for the LoadMask to render?

Susanta_bmc
5 Nov 2011, 8:03 AM
I don't think so, as the screen freezes for almost 4s before all the data changes in the grid.
I tried Ext.Function.defer also with 500ms for the function call after i call mask, still no luck.

Please let me know if you need more information.

Susanta_bmc
5 Nov 2011, 8:44 AM
I check again, My apologies it doesn't take 4s ( it takes this much time if the connection very slow and the grid panel has many columns).

This time i reduced the columns to 5 it is pretty fast, so i used the delay function:



Ext.getCmp('Demand').el.mask(this.xpleaseWait);
var task = new Ext.util.DelayedTask(this.updateGridOnJobUnitSelection(selectedRecord.get('dbVals')));
task.delay(3000);

Ext.getCmp('Demand').el.unmask();



But the masking still don't appear and i get a java script error:

fn is undefined
chrome://firebug/content/blank.gif fn.apply(scope, args || []);

So I tried the defer again with 3 sec's


Ext.getCmp('Demand').el.mask(this.xpleaseWait);
Ext.Function.defer( this.updateGridOnJobUnitSelection(selectedRecord.get('dbVals')), 3000);
Ext.getCmp('Demand').el.unmask();



Still no luck.
Can you please suggest me what would be the best way to make sure that before this method call happens, the mask would have been rendered ?

This is something important as the columns are dynamic and when the customer looks at the screen freezing doing nothing then it gives a wrong idea, with masking at least the user will be aware of a process running.

Thanks

skirtle
5 Nov 2011, 9:52 AM
I may have misunderstood your code but...

JavaScript is single threaded and though DOM manipulation will take affect immediately it won't actually render to screen until the current thread yields control. As far as I can tell you show the load mask and remove the load mask all within the same passage of execution, without ever yielding control. So while theoretically it is present in the DOM while your loop is taking place it won't get chance to be shown.

Delays and defers do not block execution, they happen asynchronously. In other words, the code to remove the mask will run immediately after you called defer/delay, long before the delay function is called.

The way you're using a delayed task and defer is also incorrect. You need to pass it the function to invoke. What you're doing is invoking the function immediately and passing the return value to the delayed task/defer. Hence the error message.

Inserting a breakpoint interrupts the execution thread and allows rendering to occur. That fits in with all the other symptoms.

It's a little worrying that your code takes so long to do whatever it's doing. You may want to consider optimizing it a little rather than trying to gloss over the problem with a load mask. If that doesn't work out and you still need to use a load mask then you'll need to show the load mask and move the logic to hide the mask into the defer/delay as well as the main body of your logic.

In pseudo-code:


showLoadMask();

Ext.defer(function() {
doProcessing();
hideLoadMask();
}, 1);

Susanta_bmc
5 Nov 2011, 3:12 PM
Thanks you so much I tried this:



jobUnitSelection: function (combo, records, d) {
//Only one selection is allowed
var selectedRecord = records[0];
//doesnt kick off this event on the same selection as prev selection
var myMask = new Ext.LoadMask(Ext.getCmp('Demand').el, {
msg: this.xpleaseWait
});
myMask.show();
//Ext.getCmp('Demand').el.mask(this.xpleaseWait);
var me=this;
Ext.Function.defer(function(){
me.updateGridOnJobUnitSelection(selectedRecord.get('dbVals'), myMask);
myMask.hide();
}, 1);
},
updateGridOnJobUnitSelection: function (jobunitVal,myMask) {
//check if it is FTE
var unit = 1;
if (jobunitVal === 'FTE_TO_MAN_DAYS') {
unit = 1 / parseFloat(fteToManDaysValue);

} else if (jobunitVal === 'MAN_TO_HOURS') {
unit = parseFloat(fteToManDaysValue);
}
//multiply on the unit and update
var store = Ext.getStore('DynamicStore');
var columns = Ext.getCmp('DynamicDemandGrid').columns;
var TotalColumnNumber = columns.length;
for (var i = 0; i < store.count(); i++) {
var rec = store.getAt(i);
for (var j = 2; j < TotalColumnNumber; j++) {
var valTobeUpdated = rec.get(columns[j].dataIndex);
valTobeUpdated = valTobeUpdated * unit;
if (valTobeUpdated != undefined) {
rec.set(columns[j].dataIndex, this.formatter(valTobeUpdated));
}
}
rec.commit();
}
myMask.hide();
},



And worked fine.

Now to answer the optimization part. I am just going through each cell to update the values on the basis of a selction in a combo box.

To do this if you look at the code i just go through the store get the records and iterate through column to update the record values. i checked if there are 5 records and 48 columns it takes around 8 seconds to do the calc and update the records.

I need to go through each record to get the values and update. Please suggest me if there is any other way to do it.

Thanks
Susanta

skirtle
5 Nov 2011, 4:31 PM
You seem to be hiding the mask twice. It won't hurt but either one will suffice on its own.

Currently it'll be redrawing the grid after each change. You can batch changes to each record using beginEdit and endEdit. That should help performance massively, reducing it down from 240 to 5 redraws.

http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Model-method-beginEdit
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Model-method-endEdit

There are other things you could try but I'd imagine that's the single biggest improvement you could make.