(function ($) { /*** * A sample AJAX data store implementation. * Right now, it's hooked up to load Hackernews stories, but can * easily be extended to support any JSONP-compatible backend that accepts paging parameters. */ function RemoteModel() { // private var PAGESIZE = 50; var data = {length: 0}; var searchstr = ""; var sortcol = null; var sortdir = 1; var h_request = null; var req = null; // ajax request // events var onDataLoading = new Slick.Event(); var onDataLoaded = new Slick.Event(); function init() { } function isDataLoaded(from, to) { for (var i = from; i <= to; i++) { if (data[i] == undefined || data[i] == null) { return false; } } return true; } function clear() { for (var key in data) { delete data[key]; } data.length = 0; } function ensureData(from, to) { if (req) { req.abort(); for (var i = req.fromPage; i <= req.toPage; i++) data[i * PAGESIZE] = undefined; } if (from < 0) { from = 0; } if (data.length > 0) { to = Math.min(to, data.length - 1); } var fromPage = Math.floor(from / PAGESIZE); var toPage = Math.floor(to / PAGESIZE); while (data[fromPage * PAGESIZE] !== undefined && fromPage < toPage) fromPage++; while (data[toPage * PAGESIZE] !== undefined && fromPage < toPage) toPage--; if (fromPage > toPage || ((fromPage == toPage) && data[fromPage * PAGESIZE] !== undefined)) { // TODO: look-ahead onDataLoaded.notify({from: from, to: to}); return; } var url = "http://api.thriftdb.com/api.hnsearch.com/items/_search?filter[fields][type][]=submission&q=" + searchstr + "&start=" + (fromPage * PAGESIZE) + "&limit=" + (((toPage - fromPage) * PAGESIZE) + PAGESIZE); if (sortcol != null) { url += ("&sortby=" + sortcol + ((sortdir > 0) ? "+asc" : "+desc")); } if (h_request != null) { clearTimeout(h_request); } h_request = setTimeout(function () { for (var i = fromPage; i <= toPage; i++) data[i * PAGESIZE] = null; // null indicates a 'requested but not available yet' onDataLoading.notify({from: from, to: to}); req = $.jsonp({ url: url, callbackParameter: "callback", cache: true, success: onSuccess, error: function () { onError(fromPage, toPage) } }); req.fromPage = fromPage; req.toPage = toPage; }, 50); } function onError(fromPage, toPage) { alert("error loading pages " + fromPage + " to " + toPage); } function onSuccess(resp) { var from = resp.request.start, to = from + resp.results.length; data.length = Math.min(parseInt(resp.hits),1000); // limitation of the API for (var i = 0; i < resp.results.length; i++) { var item = resp.results[i].item; // Old IE versions can't parse ISO dates, so change to universally-supported format. item.create_ts = item.create_ts.replace(/^(\d+)-(\d+)-(\d+)T(\d+:\d+:\d+)Z$/, "$2/$3/$1 $4 UTC"); item.create_ts = new Date(item.create_ts); data[from + i] = item; data[from + i].index = from + i; } req = null; onDataLoaded.notify({from: from, to: to}); } function reloadData(from, to) { for (var i = from; i <= to; i++) delete data[i]; ensureData(from, to); } function setSort(column, dir) { sortcol = column; sortdir = dir; clear(); } function setSearch(str) { searchstr = str; clear(); } init(); return { // properties "data": data, // methods "clear": clear, "isDataLoaded": isDataLoaded, "ensureData": ensureData, "reloadData": reloadData, "setSort": setSort, "setSearch": setSearch, // events "onDataLoading": onDataLoading, "onDataLoaded": onDataLoaded }; } // Slick.Data.RemoteModel $.extend(true, window, { Slick: { Data: { RemoteModel: RemoteModel }}}); })(jQuery);