Mercurial > pub > ImplabJs
view src/djol/VectorStore.js @ 19:8332e287d552
fix (click on cospas)
author | nickolay |
---|---|
date | Wed, 04 Oct 2017 21:05:21 +0300 |
parents | f0035923ff3e |
children | 60f6493e2892 |
line wrap: on
line source
define( [ "dojo/_base/declare", "dojo/_base/array", "implab/safe", "implab/Uuid", "ol", "ol3/listen", "./VectorStoreQuery", "dojo/store/util/QueryResults" ], function (declare, array, safe, UUID, ol, listen, VectorStoreQuery, QueryResults) { function createPaginator(opts) { return (opts.count || opts.start) && function (results) { var total = results.length; results = results.slice(opts.start || 0, (opts.start || 0) + (opts.count || Infinity)); results.total = total; return results; }; } /** * Обертка вокруг векторного источника данных ol.source.Vector, * реализует dojo/store а также notify, что делает возможным наблюдение * за хранилищем при помощи dojo/store/Observable. * * @disposable */ return declare( null, { _source: null, // ol3.source.Vector _subscriptions: null, constructor: function (opts) { safe.argumentNotNull(opts, "opts"); safe.argumentOfType( opts.source, ol.source.Vector, "opts.source"); var me = this; me._source = opts.source; }, getSource: function () { return this._source; }, get: function (id) { return this._source.getFeatureById(id); }, /** * @param{Object|Function} q предикат для выбора объекта * @param{Object} opts параметры выполнения (start,count,sort) * @return{Function} filter(data) filter.matches * filter.matches.predicate * filter.matches.extent filter.sort * filter.sort.compare */ queryEngine: function (q, opts) { opts = opts || {}; // строим функцию для фильтрации var filter; if (q instanceof Function) { // если передали уже готовую функцию, испольуем ее filter = new VectorStoreQuery(q, q.extent); } else { // если передали объект var extent; // вытаскиваем из него extent if (q && 'extent' in q) { extent = q.extent; delete q.extent; } // строим новую функцию фильтрации filter = new VectorStoreQuery(q, extent); } // строим функцию сортировки var sort = opts.sort && this.sortEngine(opts.sort); var paginate = createPaginator(opts); // строим функцию выполнения запроса var execute = function (data) { var results = array.filter(data, filter); if (sort) sort(results); if (paginate) results = paginate(results); return results; }; execute.matches = filter; execute.sort = sort; execute.paginate = paginate; return execute; }, sortEngine: function (options) { var cmp = function (a, b) { for (var sort, i = 0; (sort = options[i]); i++) { var aValue = a.get(sort.attribute); var bValue = b.get(sort.attribute); if (aValue != bValue) { return Boolean(sort.descending) == aValue > bValue ? -1 : 1; } } return 0; }; var execute = function (data) { return data.sort(cmp); }; execute.compare = cmp; return execute; }, /** * Запрашивает объекты со слоя * * @param{object|VectorStoreQuery|Function} query * * <pre> * { * extent : ol3.Extent, * } * </pre> */ query: function (q, options) { var me = this; var filter = this.queryEngine(q, options); if (this.notify && !this.hasOwnProperty("_subscriptions")) { me._subscriptions = []; var sc = function (evt, handler) { me._subscriptions.push(listen(me._source, evt, safe.delegate(me, handler))); } sc("addfeature", "_onAdd"); sc("changefeature", "_onUpdate"); sc("removefeature", "_onRemove"); } var predicate, data, extent = filter.matches && filter.matches.extent; // если это запрос с указанием области if (extent) { predicate = filter.matches.predicate; data = this._source.getFeaturesInExtent(extent); if (predicate) data = array.filter(data, predicate); if (filter.sort) filter.sort(data); if (filter.paginate) data = filter.paginate(data); } else { // любой другой запрос data = filter(this._source.getFeatures()); } return new QueryResults(data); }, put: function (obj, options) { safe.argumentOfType(obj, ol.Feature, "obj"); if (!options) options = {}; if (options.id) obj.setId(options.id); var id = obj.getId() || new UUID(); var prev = this.get(id); if ('overwrite' in options) { // overwrite=true указан, но перезаписывать нечего if (!prev && options.overwrite) throw new Error("The specified feature with id '" + id + "' doesn't exist in the store"); // overwrite=false указан, но объект уже существует if (prev && !options.overwrite) throw new Error("The specified feature with id '" + id + "' already exists in the store"); } // ok if (prev) { var data = obj.getProperties(); prev.setProperties(data); } else { this._source.addFeature(obj); } return id; }, add: function (obj, options) { safe.argumentOfType(obj, ol.Feature, "obj"); if (!options) options = {}; if (options.id) obj.setId(options.id); var id = obj.getId() || new UUID(); var prev = this.get(id); if (prev) throw new Error("The specified feature with id '" + id + "' already exists in the store"); this._source.addFeature(obj); }, remove: function (id) { var me = this; var ft = me.get(id); if (ft) me._source.removeFeature(ft); }, getIdentity: function (obj) { if (safe.isNull(obj)) return undefined; if (!(obj instanceof ol.Feature)) throw new Error("A feature is expected"); return obj.getId(); }, _onAdd: function (ev) { this.notify(ev.feature); }, _onRemove: function (ev) { var id = ev.feature.getId(); if (!safe.isNull(id)) this.notify(undefined, id); }, _onUpdate: function (ev) { var id = ev.feature.getId(); if (!safe.isNull(id)) this.notify(ev.feature, id); }, dispose: function () { var me = this; if (me._subscriptions) me._subscriptions.forEach(function (sc) { sc.remove(); }); me._source = null; me._subscriptions = null; } }); });