diff options
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Events/featureclick.js')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Events/featureclick.js | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Events/featureclick.js b/misc/openlayers/lib/OpenLayers/Events/featureclick.js new file mode 100644 index 0000000..9ae6ec5 --- /dev/null +++ b/misc/openlayers/lib/OpenLayers/Events/featureclick.js @@ -0,0 +1,321 @@ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for + * full list of contributors). Published under the 2-clause BSD license. + * See license.txt in the OpenLayers distribution or repository for the + * full text of the license. */ + +/** + * @requires OpenLayers/Events.js + */ + +/** + * Class: OpenLayers.Events.featureclick + * + * Extension event type for handling feature click events, including overlapping + * features. + * + * Event types provided by this extension: + * - featureclick + */ +OpenLayers.Events.featureclick = OpenLayers.Class({ + + /** + * Property: cache + * {Object} A cache of features under the mouse. + */ + cache: null, + + /** + * Property: map + * {<OpenLayers.Map>} The map to register browser events on. + */ + map: null, + + /** + * Property: provides + * {Array(String)} The event types provided by this extension. + */ + provides: ["featureclick", "nofeatureclick", "featureover", "featureout"], + + /** + * Constructor: OpenLayers.Events.featureclick + * Create a new featureclick event type. + * + * Parameters: + * target - {<OpenLayers.Events>} The events instance to create the events + * for. + */ + initialize: function(target) { + this.target = target; + if (target.object instanceof OpenLayers.Map) { + this.setMap(target.object); + } else if (target.object instanceof OpenLayers.Layer.Vector) { + if (target.object.map) { + this.setMap(target.object.map); + } else { + target.object.events.register("added", this, function(evt) { + this.setMap(target.object.map); + }); + } + } else { + throw("Listeners for '" + this.provides.join("', '") + + "' events can only be registered for OpenLayers.Layer.Vector " + + "or OpenLayers.Map instances"); + } + for (var i=this.provides.length-1; i>=0; --i) { + target.extensions[this.provides[i]] = true; + } + }, + + /** + * Method: setMap + * + * Parameters: + * map - {<OpenLayers.Map>} The map to register browser events on. + */ + setMap: function(map) { + this.map = map; + this.cache = {}; + map.events.register("mousedown", this, this.start, {extension: true}); + map.events.register("mouseup", this, this.onClick, {extension: true}); + map.events.register("touchstart", this, this.start, {extension: true}); + map.events.register("touchmove", this, this.cancel, {extension: true}); + map.events.register("touchend", this, this.onClick, {extension: true}); + map.events.register("mousemove", this, this.onMousemove, {extension: true}); + }, + + /** + * Method: start + * Sets startEvt = evt. + * + * Parameters: + * evt - {<OpenLayers.Event>} + */ + start: function(evt) { + this.startEvt = evt; + }, + + /** + * Method: cancel + * Deletes the start event. + * + * Parameters: + * evt - {<OpenLayers.Event>} + */ + cancel: function(evt) { + delete this.startEvt; + }, + + /** + * Method: onClick + * Listener for the click event. + * + * Parameters: + * evt - {<OpenLayers.Event>} + */ + onClick: function(evt) { + if (!this.startEvt || evt.type !== "touchend" && + !OpenLayers.Event.isLeftClick(evt)) { + return; + } + var features = this.getFeatures(this.startEvt); + delete this.startEvt; + // fire featureclick events + var feature, layer, more, clicked = {}; + for (var i=0, len=features.length; i<len; ++i) { + feature = features[i]; + layer = feature.layer; + clicked[layer.id] = true; + more = this.triggerEvent("featureclick", {feature: feature}); + if (more === false) { + break; + } + } + // fire nofeatureclick events on all vector layers with no targets + for (i=0, len=this.map.layers.length; i<len; ++i) { + layer = this.map.layers[i]; + if (layer instanceof OpenLayers.Layer.Vector && !clicked[layer.id]) { + this.triggerEvent("nofeatureclick", {layer: layer}); + } + } + }, + + /** + * Method: onMousemove + * Listener for the mousemove event. + * + * Parameters: + * evt - {<OpenLayers.Event>} + */ + onMousemove: function(evt) { + delete this.startEvt; + var features = this.getFeatures(evt); + var over = {}, newly = [], feature; + for (var i=0, len=features.length; i<len; ++i) { + feature = features[i]; + over[feature.id] = feature; + if (!this.cache[feature.id]) { + newly.push(feature); + } + } + // check if already over features + var out = []; + for (var id in this.cache) { + feature = this.cache[id]; + if (feature.layer && feature.layer.map) { + if (!over[feature.id]) { + out.push(feature); + } + } else { + // removed + delete this.cache[id]; + } + } + // fire featureover events + var more; + for (i=0, len=newly.length; i<len; ++i) { + feature = newly[i]; + this.cache[feature.id] = feature; + more = this.triggerEvent("featureover", {feature: feature}); + if (more === false) { + break; + } + } + // fire featureout events + for (i=0, len=out.length; i<len; ++i) { + feature = out[i]; + delete this.cache[feature.id]; + more = this.triggerEvent("featureout", {feature: feature}); + if (more === false) { + break; + } + } + }, + + /** + * Method: triggerEvent + * Determines where to trigger the event and triggers it. + * + * Parameters: + * type - {String} The event type to trigger + * evt - {Object} The listener argument + * + * Returns: + * {Boolean} The last listener return. + */ + triggerEvent: function(type, evt) { + var layer = evt.feature ? evt.feature.layer : evt.layer, + object = this.target.object; + if (object instanceof OpenLayers.Map || object === layer) { + return this.target.triggerEvent(type, evt); + } + }, + + /** + * Method: getFeatures + * Get all features at the given screen location. + * + * Parameters: + * evt - {Object} Event object. + * + * Returns: + * {Array(<OpenLayers.Feature.Vector>)} List of features at the given point. + */ + getFeatures: function(evt) { + var x = evt.clientX, y = evt.clientY, + features = [], targets = [], layers = [], + layer, target, feature, i, len; + // go through all layers looking for targets + for (i=this.map.layers.length-1; i>=0; --i) { + layer = this.map.layers[i]; + if (layer.div.style.display !== "none") { + if (layer.renderer instanceof OpenLayers.Renderer.Elements) { + if (layer instanceof OpenLayers.Layer.Vector) { + target = document.elementFromPoint(x, y); + while (target && target._featureId) { + feature = layer.getFeatureById(target._featureId); + if (feature) { + features.push(feature); + target.style.display = "none"; + targets.push(target); + target = document.elementFromPoint(x, y); + } else { + // sketch, all bets off + target = false; + } + } + } + layers.push(layer); + layer.div.style.display = "none"; + } else if (layer.renderer instanceof OpenLayers.Renderer.Canvas) { + feature = layer.renderer.getFeatureIdFromEvent(evt); + if (feature) { + features.push(feature); + layers.push(layer); + } + } + } + } + // restore feature visibility + for (i=0, len=targets.length; i<len; ++i) { + targets[i].style.display = ""; + } + // restore layer visibility + for (i=layers.length-1; i>=0; --i) { + layers[i].div.style.display = "block"; + } + return features; + }, + + /** + * APIMethod: destroy + * Clean up. + */ + destroy: function() { + for (var i=this.provides.length-1; i>=0; --i) { + delete this.target.extensions[this.provides[i]]; + } + this.map.events.un({ + mousemove: this.onMousemove, + mousedown: this.start, + mouseup: this.onClick, + touchstart: this.start, + touchmove: this.cancel, + touchend: this.onClick, + scope: this + }); + delete this.cache; + delete this.map; + delete this.target; + } + +}); + +/** + * Class: OpenLayers.Events.nofeatureclick + * + * Extension event type for handling click events that do not hit a feature. + * + * Event types provided by this extension: + * - nofeatureclick + */ +OpenLayers.Events.nofeatureclick = OpenLayers.Events.featureclick; + +/** + * Class: OpenLayers.Events.featureover + * + * Extension event type for handling hovering over a feature. + * + * Event types provided by this extension: + * - featureover + */ +OpenLayers.Events.featureover = OpenLayers.Events.featureclick; + +/** + * Class: OpenLayers.Events.featureout + * + * Extension event type for handling leaving a feature. + * + * Event types provided by this extension: + * - featureout + */ +OpenLayers.Events.featureout = OpenLayers.Events.featureclick; |