Skip to content

Instantly share code, notes, and snippets.

@Tocacar
Created May 8, 2012 13:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Tocacar/2635086 to your computer and use it in GitHub Desktop.
Save Tocacar/2635086 to your computer and use it in GitHub Desktop.
Infinite scrolling datatable plugin YUI 3.5.1
YUI.add('dt-scroll', function(Y){
Y.DtScroll = Y.Base.create('dt-scroll', Y.Plugin.Base, [], {
_scroll : true,
_scrollbarNode: null,
_loaderNode : null,
_noticeNode : null,
_datasource: null,
_page : 2,
initializer : function(config) {
this._scrollbarNode = config.scrollbarNode;
this._loaderNode = config.loaderNode;
this._noticeNode = config.noticeNode;
this._datasource = config.datasource;
this.bindUI();
},
bindUI : function() {
this._scrollbarNode.on('scroll', Y.bind(function(e) {
var scrollTop = this._scrollbarNode.get('scrollTop');
var scrollHeight = this._scrollbarNode.get('scrollHeight');
var tbodyHeight = parseInt(this._scrollbarNode.getComputedStyle('height'));
if ((scrollHeight - scrollTop - tbodyHeight) <= 1) {
if(!this._scroll) {
this._setNotice("I've hit rock bottom :(");
} else {
this._setNotice();
this._loaderNode.addClass('loading'); //this relies on css rule that displays spinner gif (needs improving?)
this._datasource.sendRequest({
request: '?page='+ this._page,
callback: {
success: Y.bind(function(e) {
if( e.data.statusText == "Unauthorized") {
window.location = "path/to/login/screen"; //have this url passed in with config??
}
var data = e.response.results;
if(data.length > 0) {
try {
this._updateTable(data, 'add')
this._page = this._page + 1;
}
catch(e) {
this._page = this._page - 1;
this._loaderNode.removeClass('loading');
}
} else {
this._setNotice(e.response.meta.msg); //expects a message from server, probably needs improving?
this._loaderNode.removeClass('loading');
}
}, this),
failure : Y.bind(function (e) {
if( e.data && e.data.statusText == "Unauthorized") {
window.location = "path/to/login/screen"; //as above, pass in with config??
}
this._loaderNode.removeClass('loading');
this._setNotice(e.response.meta.msg); //expects a message from server
}, this)
}
});
}
} else {
this._setNotice(); //this clears any message that might be showing from previous scrolls
}
}, this));
},
_setNotice : function(msg) {
if(msg) {
this._noticeNode.setHTML(msg);
this._noticeNode.addClass('display_notice'); //this relies on a css rule that displays the node (needs improving)
this._scroll = false;
} else {
this._noticeNode.empty();
this._noticeNode.removeClass('display_notice');
}
},
_updateTable : function(data, id) {
var i, len, row, rows = [];
for (i = 0, len = data.length; i < len; i++) {
var new_data = {};
if (!Y.Lang.isArray(row))
row = Object.keys(data[i]);
Y.Array.each(row, function (item) {
new_data[item] = data[i][item];
});
rows.push(new_data);
}
this.get('host').get('data').add(rows);
this._loaderNode.removeClass('loading');
}
},
{
NS : 'dtscroll',
ATTRS : {}
});
}, '1.0.0', {
requires : [ 'plugin', 'base-build']
});
@lsmith
Copy link

lsmith commented May 8, 2012

Encouraging that a basic infinite scroll can be implemented in 88 lines of code!

The big issue that jumps out at me, which is nothing particular about this implementation, is that the memory consumption will increase and the UI update will slow steadily as more pages of data are loaded in. You could try https://gist.github.com/2295032 until I get that rolled into core. That would replace the {silent: true} + syncUI() and would result in individual <tr>s being added. Ideal would be to have those rows created and appended in a document fragment, but that's not in the gist/core (yet).

@Tocacar
Copy link
Author

Tocacar commented May 9, 2012

Thanks for your comments lsmith! I have added your code, as suggested (lines 35-83). Before doing that, I made an attempt at adding a batch of new records to the datatable all in one go (see revision 01e6cd). This worked fine, but I recognise it isn't the right way to go about it.

Is there any chance my infinite scrolling table can be included in YUI in some way? I'm not sure of next steps (if there are any to be taken). Thanks.

@Tocacar
Copy link
Author

Tocacar commented Jun 27, 2012

I've made this into a plugin now, but need some feedback as there are definitely improvements required.

@godgav
Copy link

godgav commented Sep 8, 2012

Tocacar, thank you for dt-scroll plugin! That was an excellent point to start with! Based on your code I implemented extension for DataTable widget that adds Infinite Scroll functionality to it.

@Tocacar
Copy link
Author

Tocacar commented Oct 4, 2012

@godgav Glad you found it useful. Any chance you can share your extension code? Would be interesting to see it, if possible

@Tocacar
Copy link
Author

Tocacar commented Oct 4, 2012

@godgav Ignore me - I just noticed your fork!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment