summaryrefslogtreecommitdiff
path: root/misc/openlayers/lib/OpenLayers/Events/featureclick.js
diff options
context:
space:
mode:
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Events/featureclick.js')
-rw-r--r--misc/openlayers/lib/OpenLayers/Events/featureclick.js321
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;