remotemodel.js 6.39 KB
/* global Slick, slickgrid */

(function ($) {
    "use strict";
    function RemoteModel(data_url, search_index_url) {
        // private
        var PAGESIZE = 50;
        var data = {length: 0};
        var searchstr = "";
        var h_request = null;
        var ajax_request = null;
        var sort_rules = null;
        var filter = {group_op: "AND", rules: []};
        var columns = null;
        var force_reload = false;

        // events
        var onDataLoading = new Slick.Event();
        var onDataLoaded = new Slick.Event();
        var onAjaxError = new Slick.Event();

        function getItemMetadata(row) {
            if (data[row]) {
                var hidden = '';
                if (data[row].hidden)
                    hidden = ' hidden';
                return {
                    cssClasses: 'scheme' + data[row].scheme + hidden
                };
            } else
                return undefined;
        }
        data.getItemMetadata = getItemMetadata;

        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) {
                if (data.hasOwnProperty(key))
                    delete data[key];
            }
            data.length = 0;
            data.getItemMetadata = getItemMetadata;
        }

        function ensureData(from, to) {
            if (ajax_request) {
                ajax_request.abort();
                for (var i = ajax_request.fromPage; i <= ajax_request.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)) {
                onDataLoaded.notify({from: from, to: to});
                return;
            }

            if (h_request !== null) {
                clearTimeout(h_request);
            }

            h_request = setTimeout(function () {
                for (var i = fromPage; i <= toPage; i++)
                    data[i * PAGESIZE] = null; // requested but not available yet

                onDataLoading.notify({from: from, to: to});

                var ajax_data = {
                    rows: PAGESIZE,
                    from_page: fromPage || 0, // nie wiem, skąd te nulle
                    to_page: toPage || 0,
                    force_reload: force_reload,
                    query_params: slickgrid.query_params(),
                    columns: getColumns()
                };
                force_reload = false;

                ajax_request = $.ajaxJSON({
                    url: data_url,
                    method: 'get',
                    callback: onSuccess,
                    data: ajax_data,
                    error_callback: function () {
                        onError(fromPage, toPage);
                    }
                });
                ajax_request.fromPage = fromPage;
                ajax_request.toPage = toPage;
            }, 50);
        }

        function onError(fromPage, toPage) {
            onAjaxError.notify();
        }

        function onSuccess(ajax_data) {
            var from = ajax_data.page * PAGESIZE,
                to = from + ajax_data.rows.length;
            data.length = ajax_data.count;

            $.each(ajax_data.rows, function(i, row) {
                data[from + i] = row;
                data[from + i].index = from + i;
            });

            ajax_request = null;

            onDataLoaded.notify({from: from, to: to});
        }

        function reloadData(from, to) {
            clear();
            ensureData(from, to);
        }

        function setSort(rules) {
            sort_rules = rules;
            clear();
        }

        function getSort() {
            return sort_rules;
        }

        function setSearch(str) {
            searchstr = str;
            clear();
        }

        function setFilter(f, reload) {
            if (reload === undefined) reload = true;
            filter = f;
            force_reload = reload;
            clear();
        }

        function getFilter() {
            return filter;
        }

        function setColumns(new_columns) {
            columns = new_columns;
        }

        function getColumns() {
            return columns;
        }

        function searchRow(callback) {
            var search_counter = slickgrid.search_counter;
            var search_text = slickgrid.search_string();
            var data = {
                search: search_text,
                query_params: slickgrid.query_params()
            };
            $.ajaxJSON({
                url: search_index_url,
                method: 'get',
                data: data,
                callback: function(data) {
                    if (slickgrid.search_string() === search_text &&
                            slickgrid.search_counter === search_counter)
                        callback(data.index);
                }
            });
        }

        init();

        return {
            // properties
            "data": data,

            // methods
            "clear": clear,
            "isDataLoaded": isDataLoaded,
            "ensureData": ensureData,
            "reloadData": reloadData,
            "setSort": setSort,
            "getSort": getSort,
            "setSearch": setSearch,
            "setFilter": setFilter,
            "getFilter": getFilter,
            "setColumns": setColumns,
            "getColumns": getColumns,
            "searchRow": searchRow,

            // events
            "onDataLoading": onDataLoading,
            "onDataLoaded": onDataLoaded,
            "onAjaxError": onAjaxError
        };
    }

    // Slick.Data.RemoteModel
    $.extend(true, window, {Slick: {Data: {RemoteModel: RemoteModel}}});
})(jQuery);