-
-
Save Tocacar/2635086 to your computer and use it in GitHub Desktop.
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'] | |
}); |
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.
I've made this into a plugin now, but need some feedback as there are definitely improvements required.
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.
@godgav Glad you found it useful. Any chance you can share your extension code? Would be interesting to see it, if possible
@godgav Ignore me - I just noticed your fork!
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).