goog.provide('ol.control.Select'); goog.require('goog.array'); goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.dom.classes'); goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('ol.MapBrowserEvent.EventType'); goog.require('ol.control.Control'); goog.require('ol.css'); goog.require('ol.interaction.condition'); goog.require('ol.layer.Vector'); goog.require('ol.source.Vector'); /** * @typedef {{layer: ol.layer.Layer, * selected: (Array.|undefined), * type: goog.events.EventType, * unselected: (Array.|undefined)}} */ ol.control.SelectEventObject; /** * @constructor * @extends {ol.control.Control} * @param {ol.control.SelectOptions=} opt_options Options. */ ol.control.Select = function(opt_options) { var options = goog.isDef(opt_options) ? opt_options : {}; /** * @type {boolean} * @private */ this.active_ = false; /** * @type {Object.} * @private */ this.featureMap_ = {}; /** * @type {ol.layer.Vector} * @protected */ this.layer = new ol.layer.Vector({ source: new ol.source.Vector({parser: null}), temp: true }); /** * @type {Array.} * @private */ this.layers_ = options.layers; // TODO: css/button refactoring var className = goog.isDef(options.className) ? options.className : 'ol-select'; var element = goog.dom.createDom(goog.dom.TagName.DIV, { 'class': className + ' ' + ol.css.CLASS_UNSELECTABLE }); var button = goog.dom.createDom(goog.dom.TagName.A, { 'href': '#Select' }); goog.dom.appendChild(element, button); goog.events.listen(element, [ goog.events.EventType.TOUCHEND, goog.events.EventType.CLICK ], this.toggleActive_, false, this); goog.base(this, { element: element, map: options.map, target: options.target }); }; goog.inherits(ol.control.Select, ol.control.Control); /** * @param {goog.events.BrowserEvent} browserEvent Browser event. * @private */ ol.control.Select.prototype.toggleActive_ = function(browserEvent) { // prevent #Select anchor from getting appended to the url browserEvent.preventDefault(); if (this.active_) { this.deactivate(); } else { this.activate(); } }; /** * Activate the control. */ ol.control.Select.prototype.activate = function() { if (!this.active_) { this.active_ = true; goog.dom.classes.add(this.element, 'active'); this.getMap().addLayer(this.layer); // TODO: Implement box selection this.listenerKeys.push( goog.events.listen(this.getMap(), ol.MapBrowserEvent.EventType.CLICK, this.handleClick, true, this)); } }; /** * Dectivate the control. */ ol.control.Select.prototype.deactivate = function() { if (this.active_) { if (!goog.array.isEmpty(this.listenerKeys)) { goog.array.forEach(this.listenerKeys, goog.events.unlistenByKey); this.listenerKeys.length = 0; } this.getMap().removeLayer(this.layer); goog.dom.classes.remove(this.element, 'active'); this.active_ = false; } }; /** * @param {ol.MapBrowserEvent} evt Event. */ ol.control.Select.prototype.handleClick = function(evt) { var clear = !ol.interaction.condition.shiftKeyOnly(evt.browserEvent); function select(featuresByLayer) { this.select(featuresByLayer, clear); } this.getMap().getFeatures({ layers: this.layers_, pixel: evt.getPixel(), success: goog.bind(select, this) }); }; /** * @param {Array.>} featuresByLayer Features by layer. * @param {boolean} clear Whether the current layer content should be cleared. */ ol.control.Select.prototype.select = function(featuresByLayer, clear) { for (var i = 0, ii = featuresByLayer.length; i < ii; ++i) { var layer = this.layers_[i]; var features = featuresByLayer[i]; var numFeatures = features.length; var selectedFeatures = []; var featuresToAdd = []; var unselectedFeatures = []; var featuresToRemove = []; for (var j = 0; j < numFeatures; ++j) { var feature = features[j]; var uid = goog.getUid(feature); var clone = this.featureMap_[uid]; if (clone) { // TODO: make toggle configurable selectedFeatures.push(feature); featuresToRemove.push(clone); delete this.featureMap_[uid]; } if (clear) { for (var f in this.featureMap_) { unselectedFeatures.push(layer.getFeatureWithUid(f)); featuresToRemove.push(this.featureMap_[f]); } this.featureMap_ = {}; } if (!clone) { clone = feature.clone(); this.featureMap_[uid] = clone; selectedFeatures.push(feature); featuresToAdd.push(clone); } } if (goog.isFunction(layer.setRenderIntent)) { // TODO: Implement setRenderIntent for ol.layer.Vector layer.setRenderIntent('hidden', selectedFeatures); layer.setRenderIntent('default', unselectedFeatures); } this.layer.removeFeatures(featuresToRemove); this.layer.addFeatures(featuresToAdd); this.dispatchEvent(/** @type {ol.control.SelectEventObject} */ ({ layer: layer, selected: selectedFeatures, type: goog.events.EventType.CHANGE, unselected: unselectedFeatures })); } };