PDA

View Full Version : sort cause flash player 6 to run slowly


Peter_Chea
06-19-2003, 10:01 AM
Hi Antun, I am having problem sorting.
When I click the header of departure, arrival, airline, travel time, price in order. It cause the flash player to freeze. I am not sure it is my code or a bug in laszlo.

antun
06-19-2003, 10:43 AM
Hey Peter_Chea

There is a bug in here somewhere, and I've logged it (#1586).

What I found was that if you used pooling with the datapath, the problem did not occur. Pooling basically means that the viewsystem reuses the same views for data - very practical when you have similar data in rows as in a grid. Pooling also makes the sorting drastically faster, as the viewsystem does not have to recreate the views every time you sort:

So instead of this:


<view name="data" datapath="flight:/item">


You write this:


<view name="myData">
<datapath xpath="flight:/item" pooling="true" />


(Right now there isn't a way to set the pooling attribute in the <view> tag, so you have to use the more explicit <datapath> tag as shown above.

Another change I made was to avoid naming something "data".

Finally, in your sortBy() method, I would make one more change - you don't need to call setOrder on the datapath, it just gets echoed through to the LzReplicationManger, so:


this.data.datapath.setOrder( fieldname, ord );


... gets shortened to this:


this.myData.setOrder( fieldname, ord );


-Antun

Peter_Chea
06-19-2003, 11:06 AM
Thanks Antun, it is working now. And a lot faster too.

Peter_Chea
06-26-2003, 09:59 AM
I try it with a large set of data. It doesn't seem to sort in order now.

antun
06-26-2003, 11:52 AM
Hey Peter_Chea

There were a couple of issues here:

1) Sort is alphabetical, so sorting by the price (say) would mean that you have to write a custom comparator function that turned the values into numbers before you sorted.
2) There is a bug (I've filed it: #1623) that prevents sort from being used with a text() datapath. You can use an attribute instead. This leaves you with two choices:

Either you can change the XML so that the fields are attributes, not nodes:


<item origin="SFO"
destination="MCO"
departure="6:00am"
arrival="4:06pm"
airline="American West Flight 567"
logo="americanwest.gif"
travelTime="6hr 12min"
.....
price="513">
</item>


Or, if changing the XML is not an option, you could have a method that gets called ondata, that sets an attribute in the node, just for this purpose, when each cell gets instantiated, so the data would look like this:


<item>
<origin val="SFO">SFO</origin>
<destination val="MCO">MCO</destination>
.....
<stopDescrip val="stop in PHX">stop in PHX</stopDescrip>
<price val="513">513</price>
</item>


Let me know which works better for you.

-Antun

antun
06-26-2003, 12:15 PM
OK, I spent a couple of minutes tinkering with this to get the second solution up and running. I only did it on the price column to show you the concept.

Here's where we're creating the new 'val' attribute (to get around the aforementioned bug):


<text datapath="price/text()" width="40">
<method event="ondata">
this.datapath.setNodeAttribute( 'val', data );
</method>
</text>


Now here's your new sortBy method:


<method name="sortBy" args="fieldName">
var by = fieldName + "/@val";
debug.write("sortby: " + by);
this.myData.setOrder( by, function( a , b ) {
// debug.write( 'A: ' + a + ' B: ' + b );
var returnval = Number(a) &lt; Number(b);
return returnval ? -1 : 1;
});
</method>


Notice how now we're setting the order to the value attribute (@val) instead of the text of the node (text()). Also, instead of using ascending and descending, we're writing ourown comparator function here, that first converts them into numbers (you won't want this for alphabetical sorts, so you'll have to add logic here). We also have to use the trinary operator (? -1 : 1), because the sort function in the LFC expects a 1 or a -1; not a true or false.

-Antun

Peter_Chea
06-26-2003, 12:33 PM
I am going to try a third option. I am going to do the tag content to attribute preprocessing once before using it.
By the way, how often do you put up patch for bug fixes?

antun
06-26-2003, 01:24 PM
I'm not sure of the exact date for the next release. This bugfix will likely make it in there though. It should be some time this summer.

-Antun

johnhenry
12-03-2003, 02:01 PM
I'm attempting to build a numeric table where columns can be sorted in ascending or descending order. This thread was helpful in getting basic numeric sorting to work, but when I try the opposite function:


tableparent.rows.datarow.setOrder(sXPath, function(a,b) {
debug.write('a:' + a + ' b:' + b);
returnval = Number(b) < Number(a);
debug.write(returnval);
return returnval ? -1 : 1;});


Nothing seems to happen. In fact, the debug statements seem to indicate that this line:


returnval = Number(b) < Number(a);


Is not evaluating correctly.

Can anyone provide some insight on how the setOrder() function and sortorder property work?

johnhenry
12-03-2003, 02:01 PM
I'm attempting to build a numeric table where columns can be sorted in ascending or descending order. This thread was helpful in getting basic numeric sorting to work, but when I try the opposite function:


tableparent.rows.datarow.setOrder(sXPath, function(a,b) {
debug.write('a:' + a + ' b:' + b);
returnval = Number(b) < Number(a);
debug.write(returnval);
return returnval ? -1 : 1;});


Nothing seems to happen. In fact, the debug statements seem to indicate that this line:


returnval = Number(b) < Number(a);


Is not evaluating correctly.

Can anyone provide some insight on how the setOrder() function and sortorder property work?

antun
12-03-2003, 02:04 PM
I have a sneaky suspicion that this is not a scripting issue but a compiling one. Can you post the entire <method> tag that you're executing this code in?

Please include the <method> tags themselves.

-Antun

johnhenry
12-04-2003, 05:46 AM
Sure. See attached. Thanks for your help, Antun.

Chris

antun
12-04-2003, 10:55 AM
Hi Chris

This had me baffled for some time. It seems like there's some kind of scoping issue going on here. The reason that both comparator functions are being called is actually because it appears that one of the functions is overwriting the other.

You can confirm this by writing something different out to the debugger, e.g.


debug.write( "descComparator called" );

// and

debug.write( "ascComparator called" );


... then you'll see that even though the if block that toggles between sort orders, i.e.


if (this.getAttribute('lastsortorder')=='descending')


... does the right thing, and your debug.write statement that outputs "asc" or "desc" verifies this, the same comparator function gets called.

I've filed a bug (3061) on this, and will find out more if I can. I'll keep you posted.

-Antun

antun
12-04-2003, 01:15 PM
OK this turned out to be a bug in the LFC. It will be fixed in the next release. There is a workaround which is a bit of a nuisance, but here goes. Run the code below, but only toggle one column in each session of the app:


<attribute name="flagIsSortOrderCalled" value="false" />
<method name="sort" args="columnIndex">
<![CDATA[
debug.write( columnIndex );
var rowHeadCount = 0;
var newOrderArray = new Array();
var ord = this.getAttribute('lastsortorder') == "descending" ? "ascending" : "descending";

//Update the numeric colums based on the focus column
this.setAttribute('lastsortorder', ord);
var sXPath = 'item[' + columnIndex + ']/@name';
var returnval;

this.descComparator = function(a, b) {
debug.write( "descComparator called" );
a = Number(a);
b = Number(b);
debug.write('a:' + a + ' b:' + b);
var returnval = b < a;
debug.write(returnval);
return returnval ? -1 : 1;
}
this.ascComparator = function(a,b) {
debug.write( "ascComparator called" );
a = Number(a);
b = Number(b);
debug.write('a:' + a + ' b:' + b);
var returnval = a < b;
debug.write(returnval);
return returnval ? -1 : 1;
}
//tableparent.rows.datarow.setOrder(sXPath, ord);

//TO-DO - figure out sorting crap. buggy.
if (this.getAttribute('lastsortorder')=='descending')
{
debug.write('desc');
if ( !this.flagIsSortOrderCalled ) {
Debug.write( 'setOrder method' );
tableparent.rows.datarow.setOrder(sXPath, this.descComparator);
this.flagIsSortOrderCalled = true;
} else {
Debug.write( 'setComparator method' );
tableparent.rows.datarow.setComparator(this.descCo mparator);
}
}
if (this.getAttribute('lastsortorder')=='ascending')
{
debug.write('asc');
if ( !this.flagIsSortOrderCalled ) {
Debug.write( 'setOrder method' );
tableparent.rows.datarow.setOrder(sXPath, this.ascComparator);
this.flagIsSortOrderCalled = true;
} else {
Debug.write( 'setComparator method' );
tableparent.rows.datarow.setComparator(this.ascCom parator);
}
}

debug.write('----------------------');


/* ==================================================
Once full xpath is supported by lzx, this operation
shouldn't be necessary; should be controlled by setOrder
above.
================================================== == */
for (var i=0; i < tableparent.rows.subviews.length; i++)
{
//increment rowheadcount.
rowHeadCount = rowHeadCount + 1

//reducing nodecount by 2 will give actual index.
newOrderArray[rowHeadCount] = tableparent.rows.subviews[i].datapath.getNodeOffset()-2;
}

//update the row headers based on new order.
for (var z=1; z < newOrderArray.length; z++)
{
var sDataPath = 'my_data:/items/rowHead/item[' + newOrderArray[z] + ']/@name';
tableparent.rowHeader.rowHeaderData.subviews[z-1].rowHeadText.setDataPath(sDataPath);
}
]]>
</method>


Calling setComparator directly avoids the problem, however you still have to call setOrder() the first time you do a sort for every column. That's why I added the flag variable above.

If you need this working now, then you'll need to come up with a way to record which columns have had setOrder() called once already. You could move your sort() method into a new class, say column_head, which was instantiated once for each column. That way the flagIsSortOrderCalled attribute would pertain to each column.

Take care,

Antun

PS I tweaked your sort() method a little while I was debugging it - that's why the two comparator functions are variables, and why there are a few more debug.write() statements.