[ 5 posts ]

scott page

  • Username: swpage
  • Joined: Thu Sep 22, 2011 8:14 am
  • Posts: 4
  • Offline
  • Profile
Tags:

Updating 3.5 datatable with 250+ rows hangs the browser

Post Posted: Thu May 03, 2012 1:30 pm
+0-
When I iterate through a DataTable having 250+ rows and attempt to either update a cell or modify a row,
it will either hang (usually displaying 'A script on this page may be busy, or may have stopped responding' message)
or take 15+ seconds to complete.

code below:

Code:
<button id="pushme">BOOM</button>
<div id="tableGoesHere"></div>
<script>
YUI().use('node', 'datatable', 'datatable-mutable', function(Y) {
    var columns = [
        {key: "action"},
        {key: "existsInSource"},
        {key: "existsInTarget"},
        {key: "fileName"},
        {key: "fileID"},
        {key: "sourcePath"},
        {key: "selectedOption"}
    ];

    var data = [];
    for (var i=0; i < 250; i++) {
        data.push({
            fileID: 'fileID' + i,
            fileName: 'fileName' + i,
            sourcePath: 'sourcePath' + i,
            existsInSource: true,
            existsInTarget: true,
            selectedOption: 1,
            action: 'action' + i
       });
    }

    var dataTable = new Y.DataTable({
        columns: columns,
        data: data,
        scrollable: 'y'
    }).render("#tableGoesHere"),
    rowCount = dataTable.data.size();

    Y.one('#pushme').on('click', function() {
        var selectedIndex = Math.floor((Math.random()*10)+1);
        Y.log(selectedIndex);
        dataTable.data.each(function (record, i) {
            // either action below causes the problem
            record.set('selectedOption', selectedIndex);
            dataTable.modifyRow(i, {'selectedOption': selectedIndex});
        });
        // Also tried:
        // for (var i=0; i < rowCount; i++) {
        //     record = dataTable.data.item(i);
        //     record.set('selectedOption', selectedIndex);
        //     //dataTable.modifyRow(i, {'selectedOption': selectedIndex});
        // }
    });
});
</script>


Last edited by swpage on Thu May 03, 2012 2:40 pm, edited 1 time in total.

Luke Smith

YUI Contributor

  • Username: lsmith
  • Joined: Thu Aug 28, 2008 7:50 am
  • Posts: 511
  • Location: Sunnyvale
  • Twitter: ls_n
  • GitHub: lsmith
  • Gists: lsmith
  • IRC: ls_n
  • YUI Developer
  • Offline
  • Profile

Re: Updating 3.5 datatable with 100+ rows hangs the browser

Post Posted: Thu May 03, 2012 2:46 pm
+1-
Each modification is triggering a re-render. In 3.5.0, mutation triggered re-rendering isn't optimized. Here's a gist that is an initial implementation of what will be in core for 3.6.0: https://gist.github.com/2295032

in the mean time, you can use that, or do:

Code:
dataTable.data.each(function (record) {
    record.set('selectedOption', selectedIndex, { silent: true });
});
dataTable.syncUI();


or
Code:
dataTable.data.invoke('set', 'selectedOption', selectedIndex, { silent: true });
dataTable.syncUI();


This will silence the mutation events, then re-render the table once after all the changes have been made to the data.

HTH

scott page

  • Username: swpage
  • Joined: Thu Sep 22, 2011 8:14 am
  • Posts: 4
  • Offline
  • Profile

Re: Updating 3.5 datatable with 250+ rows hangs the browser

Post Posted: Fri May 04, 2012 7:54 am
+0-
Thanks for your quick response. Using the 'silent' attribute along with syncUI works great.

One side-effect for my application is it re-sets an HTML select menu I have within one of the column headers. Doing a set('selectedIndex', selectedIndex) after syncUI does nothing, presumably as the headers are immutable.

I can't seem to find anything on how to dynamically set data within the column headers.

Thanks

Luke Smith

YUI Contributor

  • Username: lsmith
  • Joined: Thu Aug 28, 2008 7:50 am
  • Posts: 511
  • Location: Sunnyvale
  • Twitter: ls_n
  • GitHub: lsmith
  • Gists: lsmith
  • IRC: ls_n
  • YUI Developer
  • Offline
  • Profile

Re: Updating 3.5 datatable with 250+ rows hangs the browser

Post Posted: Fri May 04, 2012 10:24 am
+0-
Hmm, the select complicates any potential solution because it's typical to subscribe to the 'change' event of select elements, but 'change' doesn't bubble, which means you can't use a delegate subscription (until I create the synthetic event patch).

So it's likely that you're storing a reference to the Node for the select element in the header and subscribing to its 'change' event. What's happening is that syncUI() rerenders the table, including the headers, which means the select element that's there after syncUI() is not the same select element that you initially captured. You have a couple options:

Probably best option for you is to replace the new select with the one you initially captured after the syncUI().

Code:
dataTable.render(...);
var headerSelect = dataTable.one('contentBox').one('.foo');

Y.Do.after(function () {
    this.get('container').one('.foo').replace(headerSelect);
}, dataTable.head, 'render');


Another, less comprehensive, solution is to call dataTable.body.render() instead of dataTable.syncUI();

In the future, after I create the bubbling 'change' synthetic event, it would be best to do:

Code:
dataTable.delegate('change', function (e) {
    // code that updates the records
}, '.yui3-datatable-columns .foo', dataTable);

scott page

  • Username: swpage
  • Joined: Thu Sep 22, 2011 8:14 am
  • Posts: 4
  • Offline
  • Profile

Re: Updating 3.5 datatable with 250+ rows hangs the browser

Post Posted: Fri May 04, 2012 11:11 am
+0-
I had success by capturing the header select node prior to the updates and syncUI(), then doing the replace afterwards:

Code:
selectChangeEvent = function(menu) {
    headerSelect = Y.one('#selectAll');
    dataTable.data.some(function (record, recordIndex) {
        record.set(..);
        ...
    });
    dataTable.syncUI();
    Y.one('#selectAll').replace(headerSelect);
}


Thanks again!
  [ 5 posts ]
Display posts from previous:  Sort by  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum