goog.provide('M.handler.Features'); goog.require('M.utils'); goog.require('M.exception'); goog.require('M.facade.Base'); (function() { /** * @classdesc * Main constructor of the class. Creates a layer * with parameters specified by the user * * @constructor * @extends {M.facade.Base} * @api stable */ M.handler.Features = (function(options = {}, impl = new M.impl.handler.Features(options)) { /** * @private * @type {M.Map} * @expose */ this.map_ = null; /** * @private * @type {Array<M.layer.Vector>} * @expose */ this.layers_ = []; /** * @private * @type {boolean} * @expose */ this.activated_ = false; /** * @private * @type {Object} * @expose */ this.prevSelectedFeatures_ = {}; /** * @private * @type {Object} * @expose */ this.prevHoverFeatures_ = {}; // checks if the implementation has all methods if (!M.utils.isFunction(impl.addTo)) { M.exception('La implementación usada no posee el método addTo'); } if (!M.utils.isFunction(impl.getFeaturesByLayer)) { M.exception('La implementación usada no posee el método getFeaturesByLayer'); } // calls the super constructor goog.base(this, impl); }); goog.inherits(M.handler.Features, M.facade.Base); /** * This function adds the control to the specified map * * @public * @function * @param {M.Map} map to add the plugin * @api stable * @export */ M.handler.Features.prototype.addTo = function(map) { this.map_ = map; this.map_.on(M.evt.CLICK, this.clickOnMap_, this); this.map_.on(M.evt.MOVE, this.moveOverMap_, this); this.getImpl().addTo(this.map_); this.fire(M.evt.ADDED_TO_MAP); }; /** * TODO * * @private * @function */ M.handler.Features.prototype.clickOnMap_ = function(evt) { if (this.activated_ === true) { let impl = this.getImpl(); this.layers_.forEach(function(layer) { let clickedFeatures = impl.getFeaturesByLayer(evt, layer); let prevFeatures = [...this.prevSelectedFeatures_[layer.name]]; // no features selected then unselect prev selected features if (clickedFeatures.length === 0 && prevFeatures.length > 0) { this.unselectFeatures(prevFeatures, layer, evt); } else if (clickedFeatures.length > 0) { let newFeatures = clickedFeatures.filter(f => !prevFeatures.some(pf => pf.equals(f))); let diffFeatures = prevFeatures.filter(f => !clickedFeatures.some(pf => pf.equals(f))); // unselect prev selected features which have not been selected this time if (diffFeatures.length > 0) { this.unselectFeatures(diffFeatures, layer, evt); } // select new selected features if (newFeatures.length > 0) { this.selectFeatures(newFeatures, layer, evt); } } }, this); } }; /** * TODO * * @private * @function */ M.handler.Features.prototype.moveOverMap_ = function(evt) { if (this.activated_ === true) { let impl = this.getImpl(); this.layers_.forEach(function(layer) { let hoveredFeatures = impl.getFeaturesByLayer(evt, layer); let prevFeatures = [...this.prevHoverFeatures_[layer.name]]; // no features selected then unselect prev selected features if (hoveredFeatures.length === 0 && prevFeatures.length > 0) { this.leaveFeatures_(prevFeatures, layer, evt); } else if (hoveredFeatures.length > 0) { let newFeatures = hoveredFeatures.filter(f => (f instanceof M.Feature) && !prevFeatures.some(pf => pf.equals(f))); let diffFeatures = prevFeatures.filter(f => !hoveredFeatures.some(pf => pf.equals(f))); // unselect prev selected features which have not been selected this time if (diffFeatures.length > 0) { this.leaveFeatures_(diffFeatures, layer, evt); } // select new selected features if (newFeatures.length > 0) { this.hoverFeatures_(newFeatures, layer, evt); } } }, this); } }; /** * TODO * * @public * @function * @api stable */ M.handler.Features.prototype.selectFeatures = function(features, layer, evt) { this.prevSelectedFeatures_[layer.name] = this.prevSelectedFeatures_[layer.name].concat(features); let layerImpl = layer.getImpl(); if (M.utils.isFunction(layerImpl.selectFeatures)) { layerImpl.selectFeatures(features, evt.coord, evt); } layer.fire(M.evt.SELECT_FEATURES, [features, evt]); }; /** * TODO * * @public * @function * @api stable */ M.handler.Features.prototype.unselectFeatures = function(features, layer, evt) { // removes unselected features this.prevSelectedFeatures_[layer.name] = this.prevSelectedFeatures_[layer.name].filter(pf => !features.some(f => f.equals(pf))); let layerImpl = layer.getImpl(); if (M.utils.isFunction(layerImpl.unselectFeatures)) { layerImpl.unselectFeatures(features, evt.coord); } layer.fire(M.evt.UNSELECT_FEATURES, [features, evt.coord]); }; /** * TODO * * @private * @function * @api stable */ M.handler.Features.prototype.hoverFeatures_ = function(features, layer, evt) { this.prevHoverFeatures_[layer.name] = this.prevHoverFeatures_[layer.name].concat(features); layer.fire(M.evt.HOVER_FEATURES, [features, evt]); this.getImpl().addCursorPointer(); }; /** * TODO * * @private * @function * @api stable */ M.handler.Features.prototype.leaveFeatures_ = function(features, layer, evt) { this.prevHoverFeatures_[layer.name] = this.prevHoverFeatures_[layer.name].filter(pf => !features.some(f => f.equals(pf))); layer.fire(M.evt.LEAVE_FEATURES, [features, evt.coord]); this.getImpl().removeCursorPointer(); }; /** * function adds the event 'click' * * @public * @function * @api stable * @export */ M.handler.Features.prototype.activate = function() { if (this.activated_ === false) { this.activated_ = true; this.fire(M.evt.ACTIVATED); } }; /** * function remove the event 'click' * * @public * @function * @api stable * @export */ M.handler.Features.prototype.deactivate = function() { if (this.activated_ === true) { this.activated_ = false; this.fire(M.evt.DEACTIVATED); } }; /** * Sets the panel of the control * * @public * @function * @param {M.ui.Panel} panel * @api stable * @export */ M.handler.Features.prototype.addLayer = function(layer) { if (!M.utils.includes(this.layers_, layer)) { this.layers_.push(layer); this.prevSelectedFeatures_[layer.name] = []; this.prevHoverFeatures_[layer.name] = []; } }; /** * Gets the panel of the control * * @public * @function * @returns {M.ui.Panel} * @api stable * @export */ M.handler.Features.prototype.removeLayer = function(layer) { this.layers_.remove(layer); this.prevSelectedFeatures_[layer.name] = null; this.prevHoverFeatures_[layer.name] = null; delete this.prevSelectedFeatures_[layer.name]; delete this.prevHoverFeatures_[layer.name]; }; /** * Destroys the handler * * @public * @function * @api stable * @export */ M.handler.Features.prototype.destroy = function() { // TODO // this.getImpl().destroy(); // this.fire(M.evt.DESTROY); }; })();