174 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| (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);
 |