Compare commits
19 Commits
release-2.
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cf69634cf | ||
|
|
c2b7e8b327 | ||
|
|
fe0620dc7f | ||
|
|
8778b746b3 | ||
|
|
a5ea8d7fcf | ||
|
|
b103d3b428 | ||
|
|
8562582dd2 | ||
|
|
cd5ae45273 | ||
|
|
d1b00824fc | ||
|
|
4399ebcb04 | ||
|
|
0bb804c9e7 | ||
|
|
572d78fb4d | ||
|
|
1d948fc914 | ||
|
|
449b85966e | ||
|
|
1223ea339d | ||
|
|
d0f8fa3ecf | ||
|
|
e9a349e4f1 | ||
|
|
8b4592e71a | ||
|
|
7c5afe1acf |
46
examples/feature-events.html
Normal file
46
examples/feature-events.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>OpenLayers Feature Events Example</title>
|
||||
<link rel="stylesheet" href="../theme/default/style.css" type="text/css">
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<style type="text/css">
|
||||
#result {
|
||||
height: 60px;
|
||||
width: 514px;
|
||||
font-size: smaller;
|
||||
overflow: auto;
|
||||
margin-top: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="title">Feature Events Example</h1>
|
||||
|
||||
<div id="tags">
|
||||
feature, select, hover
|
||||
</div>
|
||||
|
||||
<div id="shortdesc">Feature hover and click events</div>
|
||||
|
||||
<div id="map" class="smallmap"></div>
|
||||
<div id="docs">
|
||||
<p id="result">Hover over or click features on the map.</p>
|
||||
|
||||
<p>This example shows how to use the 'featureclick', 'nofeatureclick',
|
||||
'featureover' and 'featureout' events to make features interactive.
|
||||
Look at the <a href="feature-events.js">feature-events.js</a> source
|
||||
code to see how this is done.</p>
|
||||
|
||||
<p>Note that these events can be registered both on the map and on
|
||||
individual layers. If many layers need to be observed, it is
|
||||
recommended to register listeners once on the map for performance
|
||||
reasons.</p>
|
||||
</div>
|
||||
<script src="../lib/OpenLayers.js"></script>
|
||||
<script src="feature-events.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
67
examples/feature-events.js
Normal file
67
examples/feature-events.js
Normal file
@@ -0,0 +1,67 @@
|
||||
var layerListeners = {
|
||||
featureclick: function(e) {
|
||||
log(e.object.name + " says: " + e.feature.id + " clicked.");
|
||||
return false;
|
||||
},
|
||||
nofeatureclick: function(e) {
|
||||
log(e.object.name + " says: No feature clicked.");
|
||||
}
|
||||
};
|
||||
|
||||
var style = new OpenLayers.StyleMap({
|
||||
'default': OpenLayers.Util.applyDefaults(
|
||||
{label: "${l}", pointRadius: 10},
|
||||
OpenLayers.Feature.Vector.style["default"]
|
||||
),
|
||||
'select': OpenLayers.Util.applyDefaults(
|
||||
{pointRadius: 10},
|
||||
OpenLayers.Feature.Vector.style.select
|
||||
)
|
||||
});
|
||||
var layer1 = new OpenLayers.Layer.Vector("Layer 1", {
|
||||
styleMap: style,
|
||||
eventListeners: layerListeners
|
||||
});
|
||||
layer1.addFeatures([
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(-1 -1)"), {l:1}),
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(1 1)"), {l:1})
|
||||
]);
|
||||
var layer2 = new OpenLayers.Layer.Vector("Layer 2", {
|
||||
styleMap: style,
|
||||
eventListeners: layerListeners
|
||||
});
|
||||
layer2.addFeatures([
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(-1 1)"), {l:2}),
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(1 -1)"), {l:2})
|
||||
]);
|
||||
|
||||
var map = new OpenLayers.Map({
|
||||
div: "map",
|
||||
allOverlays: true,
|
||||
layers: [layer1, layer2],
|
||||
zoom: 6,
|
||||
center: [0, 0],
|
||||
eventListeners: {
|
||||
featureover: function(e) {
|
||||
e.feature.renderIntent = "select";
|
||||
e.feature.layer.drawFeature(e.feature);
|
||||
log("Map says: Pointer entered " + e.feature.id + " on " + e.feature.layer.name);
|
||||
},
|
||||
featureout: function(e) {
|
||||
e.feature.renderIntent = "default";
|
||||
e.feature.layer.drawFeature(e.feature);
|
||||
log("Map says: Pointer left " + e.feature.id + " on " + e.feature.layer.name);
|
||||
},
|
||||
featureclick: function(e) {
|
||||
log("Map says: " + e.feature.id + " clicked on " + e.feature.layer.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function log(msg) {
|
||||
if (!log.timer) {
|
||||
result.innerHTML = "";
|
||||
log.timer = window.setTimeout(function() {delete log.timer;}, 100);
|
||||
}
|
||||
result.innerHTML += msg + "<br>";
|
||||
}
|
||||
@@ -146,6 +146,7 @@
|
||||
"OpenLayers/Kinetic.js",
|
||||
"OpenLayers/Events.js",
|
||||
"OpenLayers/Events/buttonclick.js",
|
||||
"OpenLayers/Events/featureclick.js",
|
||||
"OpenLayers/Request.js",
|
||||
"OpenLayers/Request/XMLHttpRequest.js",
|
||||
"OpenLayers/Projection.js",
|
||||
@@ -425,4 +426,4 @@
|
||||
* When asking questions or reporting issues, make sure to include the output of
|
||||
* OpenLayers.VERSION_NUMBER in the question or issue-description.
|
||||
*/
|
||||
OpenLayers.VERSION_NUMBER="Release 2.13-rc1";
|
||||
OpenLayers.VERSION_NUMBER="Release 2.13-rc5";
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* full text of the license. */
|
||||
|
||||
/**
|
||||
* @requires OpenLayers/Control.js
|
||||
* @requires OpenLayers/Handler/Drag.js
|
||||
* @requires OpenLayers/Handler/Keyboard.js
|
||||
*/
|
||||
@@ -234,8 +235,8 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
|
||||
this.handlers.drag.evt);
|
||||
if (feature) {
|
||||
this.dragStart(feature);
|
||||
} else if (this.feature && this.clickout) {
|
||||
this.unselectFeature(this.feature);
|
||||
} else if (this.clickout) {
|
||||
this._unselect = this.feature;
|
||||
}
|
||||
},
|
||||
move: function(pixel) {
|
||||
@@ -362,8 +363,9 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
|
||||
* feature - {<OpenLayers.Feature.Vector>} the selected feature.
|
||||
*/
|
||||
selectFeature: function(feature) {
|
||||
if (this.geometryTypes && OpenLayers.Util.indexOf(this.geometryTypes,
|
||||
feature.geometry.CLASS_NAME) == -1) {
|
||||
if (this.feature === feature ||
|
||||
(this.geometryTypes && OpenLayers.Util.indexOf(this.geometryTypes,
|
||||
feature.geometry.CLASS_NAME) == -1)) {
|
||||
return;
|
||||
}
|
||||
if (this.beforeSelectFeature(feature) !== false) {
|
||||
|
||||
321
lib/OpenLayers/Events/featureclick.js
Normal file
321
lib/OpenLayers/Events/featureclick.js
Normal file
@@ -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;
|
||||
@@ -102,8 +102,9 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, {
|
||||
* {Array(Array(int))} An array containing n-dimensional arrays of
|
||||
* coordinates.
|
||||
*/
|
||||
decode: function(encoded, dims) {
|
||||
var flatPoints = this.decodeDeltas(encoded, dims, 1);
|
||||
decode: function(encoded, dims, opt_factor) {
|
||||
var factor = opt_factor || 1e5;
|
||||
var flatPoints = this.decodeDeltas(encoded, dims, factor);
|
||||
var flatPointsLength = flatPoints.length;
|
||||
|
||||
var points = [];
|
||||
@@ -177,7 +178,8 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, {
|
||||
* Returns:
|
||||
* {String} An encoded string
|
||||
*/
|
||||
encode: function (points, dims) {
|
||||
encode: function (points, dims, opt_factor) {
|
||||
var factor = opt_factor || 1e5;
|
||||
var flatPoints = [];
|
||||
|
||||
var pointsLength = points.length;
|
||||
@@ -189,7 +191,7 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, {
|
||||
}
|
||||
}
|
||||
|
||||
return this.encodeDeltas(flatPoints, dims, 1);
|
||||
return this.encodeDeltas(flatPoints, dims, factor);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -147,7 +147,7 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
||||
* evt - {Event}
|
||||
*/
|
||||
touchmove: function(evt) {
|
||||
OpenLayers.Event.stop(evt);
|
||||
OpenLayers.Event.preventDefault(evt);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -278,7 +278,7 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
||||
if(type === "touchstart") {
|
||||
// stop the event to prevent Android Webkit from
|
||||
// "flashing" the map div
|
||||
OpenLayers.Event.stop(evt);
|
||||
OpenLayers.Event.preventDefault(evt);
|
||||
}
|
||||
var inNew = (this.feature != this.lastFeature);
|
||||
if(this.geometryTypeMatches(this.feature)) {
|
||||
|
||||
@@ -274,6 +274,10 @@ OpenLayers.Layer.Google = OpenLayers.Class(
|
||||
if (poweredBy && poweredBy.parentNode) {
|
||||
poweredBy.parentNode.removeChild(poweredBy);
|
||||
}
|
||||
if (this.mapObject && window.google && google.maps &&
|
||||
google.maps.event && google.maps.event.clearListeners) {
|
||||
google.maps.event.clearListeners(this.mapObject, 'tilesloaded');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -53,10 +53,9 @@ OpenLayers.Layer.Google.v3 = {
|
||||
|
||||
/**
|
||||
* Method: loadMapObject
|
||||
* Load the GMap and register appropriate event listeners. If we can't
|
||||
* load GMap2, then display a warning message.
|
||||
* Load the GMap and register appropriate event listeners.
|
||||
*/
|
||||
loadMapObject:function() {
|
||||
loadMapObject: function() {
|
||||
if (!this.type) {
|
||||
this.type = google.maps.MapTypeId.ROADMAP;
|
||||
}
|
||||
@@ -92,7 +91,6 @@ OpenLayers.Layer.Google.v3 = {
|
||||
googleControl.style.width = '100%';
|
||||
googleControl.style.height = '100%';
|
||||
mapObject.controls[google.maps.ControlPosition.TOP_LEFT].push(googleControl);
|
||||
this.map.div.appendChild(container);
|
||||
|
||||
// cache elements for use by any other google layers added to
|
||||
// this same map
|
||||
@@ -141,13 +139,24 @@ OpenLayers.Layer.Google.v3 = {
|
||||
}
|
||||
var container = this.mapObject.getDiv();
|
||||
if (visible === true) {
|
||||
container.style.display = '';
|
||||
cache.googleControl.appendChild(map.viewPortDiv);
|
||||
google.maps.event.trigger(this.mapObject, 'resize');
|
||||
if (container.parentNode !== map.div) {
|
||||
if (!cache.rendered) {
|
||||
var me = this;
|
||||
google.maps.event.addListenerOnce(this.mapObject, 'tilesloaded', function() {
|
||||
cache.rendered = true;
|
||||
me.setGMapVisibility(me.getVisibility());
|
||||
me.moveTo(me.map.getCenter());
|
||||
});
|
||||
} else {
|
||||
map.div.appendChild(container);
|
||||
cache.googleControl.appendChild(map.viewPortDiv);
|
||||
google.maps.event.trigger(this.mapObject, 'resize');
|
||||
}
|
||||
}
|
||||
this.mapObject.setMapTypeId(type);
|
||||
} else {
|
||||
} else if (cache.googleControl.hasChildNodes()) {
|
||||
map.div.appendChild(map.viewPortDiv);
|
||||
container.style.display = 'none';
|
||||
map.div.removeChild(container);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1100,7 +1100,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
this.events.triggerEvent("tileloadstart", {tile: tile});
|
||||
this.numLoadingTiles++;
|
||||
if (!this.singleTile && this.backBuffer && this.gridResolution === this.backBufferResolution) {
|
||||
OpenLayers.Element.addClass(tile.imgDiv, replacingCls);
|
||||
OpenLayers.Element.addClass(tile.getTile(), replacingCls);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1112,13 +1112,14 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
aborted: aborted
|
||||
});
|
||||
if (!this.singleTile && !aborted && this.backBuffer && this.gridResolution === this.backBufferResolution) {
|
||||
if (OpenLayers.Element.getStyle(tile.imgDiv, 'display') === 'none') {
|
||||
var tileDiv = tile.getTile();
|
||||
if (OpenLayers.Element.getStyle(tileDiv, 'display') === 'none') {
|
||||
var bufferTile = document.getElementById(tile.id + '_bb');
|
||||
if (bufferTile) {
|
||||
bufferTile.parentNode.removeChild(bufferTile);
|
||||
}
|
||||
}
|
||||
OpenLayers.Element.removeClass(tile.imgDiv, replacingCls);
|
||||
OpenLayers.Element.removeClass(tileDiv, replacingCls);
|
||||
}
|
||||
//if that was the last tile, then trigger a 'loadend' on the layer
|
||||
if (this.numLoadingTiles === 0) {
|
||||
|
||||
@@ -7,7 +7,7 @@ var OpenLayers = {
|
||||
/**
|
||||
* Constant: VERSION_NUMBER
|
||||
*/
|
||||
VERSION_NUMBER: "Release 2.13-rc1",
|
||||
VERSION_NUMBER: "Release 2.13-rc5",
|
||||
|
||||
/**
|
||||
* Constant: singleFile
|
||||
|
||||
@@ -175,7 +175,7 @@ OpenLayers.TileManager = OpenLayers.Class({
|
||||
* evt - {Object} Listener argument
|
||||
*/
|
||||
move: function(evt) {
|
||||
this.updateTimeout(evt.object, this.moveDelay);
|
||||
this.updateTimeout(evt.object, this.moveDelay, true);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -272,11 +272,16 @@ OpenLayers.TileManager = OpenLayers.Class({
|
||||
* Parameters:
|
||||
* map - {<OpenLayers.Map>} The map to update the timeout for
|
||||
* delay - {Number} The delay to apply
|
||||
* nice - {Boolean} If true, the timeout function will only be created if
|
||||
* the tilequeue is not empty. This is used by the move handler to
|
||||
* avoid impacts on dragging performance. For other events, the tile
|
||||
* queue may not be populated yet, so we need to set the timer
|
||||
* regardless of the queue size.
|
||||
*/
|
||||
updateTimeout: function(map, delay) {
|
||||
updateTimeout: function(map, delay, nice) {
|
||||
window.clearTimeout(this.tileQueueId[map.id]);
|
||||
var tileQueue = this.tileQueue[map.id];
|
||||
if (tileQueue.length) {
|
||||
if (!nice || tileQueue.length) {
|
||||
this.tileQueueId[map.id] = window.setTimeout(
|
||||
OpenLayers.Function.bind(function() {
|
||||
this.drawTilesFromQueue(map);
|
||||
@@ -383,6 +388,11 @@ OpenLayers.TileManager = OpenLayers.Class({
|
||||
if (img && (!img.parentNode ||
|
||||
OpenLayers.Element.hasClass(img.parentNode, 'olBackBuffer'))) {
|
||||
if (tile.layer.backBuffer) {
|
||||
if (tile.layer.backBuffer === img.parentNode) {
|
||||
// cached image is on the target layer's backbuffer already,
|
||||
// so nothing to do here
|
||||
return;
|
||||
}
|
||||
img.style.opacity = 0;
|
||||
img.style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
@@ -866,11 +866,17 @@ OpenLayers.Util.destinationVincenty = function(lonlat, brng, dist) {
|
||||
* url - {String} Optional url used to extract the query string.
|
||||
* If url is null or is not supplied, query string is taken
|
||||
* from the page location.
|
||||
* options - {Object} Additional options. Optional.
|
||||
*
|
||||
* Valid options:
|
||||
* splitArgs - {Boolean} Split comma delimited params into arrays? Default is
|
||||
* true.
|
||||
*
|
||||
* Returns:
|
||||
* {Object} An object of key/value pairs from the query string.
|
||||
*/
|
||||
OpenLayers.Util.getParameters = function(url) {
|
||||
OpenLayers.Util.getParameters = function(url, options) {
|
||||
options = options || {};
|
||||
// if no url specified, take it from the location bar
|
||||
url = (url === null || url === undefined) ? window.location.href : url;
|
||||
|
||||
@@ -906,7 +912,9 @@ OpenLayers.Util.getParameters = function(url) {
|
||||
}
|
||||
|
||||
// follow OGC convention of comma delimited values
|
||||
value = value.split(",");
|
||||
if (options.splitArgs !== false) {
|
||||
value = value.split(",");
|
||||
}
|
||||
|
||||
//if there's only one value, do not return as array
|
||||
if (value.length == 1) {
|
||||
@@ -1299,7 +1307,8 @@ OpenLayers.Util.isEquivalentUrl = function(url1, url2, options) {
|
||||
OpenLayers.Util.applyDefaults(options, {
|
||||
ignoreCase: true,
|
||||
ignorePort80: true,
|
||||
ignoreHash: true
|
||||
ignoreHash: true,
|
||||
splitArgs: false
|
||||
});
|
||||
|
||||
var urlObj1 = OpenLayers.Util.createUrlObject(url1, options);
|
||||
@@ -1340,6 +1349,8 @@ OpenLayers.Util.isEquivalentUrl = function(url1, url2, options) {
|
||||
* ignoreCase - {Boolean} lowercase url,
|
||||
* ignorePort80 - {Boolean} don't include explicit port if port is 80,
|
||||
* ignoreHash - {Boolean} Don't include part of url after the hash (#).
|
||||
* splitArgs - {Boolean} Split comma delimited params into arrays? Default is
|
||||
* true.
|
||||
*
|
||||
* Returns:
|
||||
* {Object} An object with separate url, a, port, host, and args parsed out
|
||||
@@ -1395,7 +1406,8 @@ OpenLayers.Util.createUrlObject = function(url, options) {
|
||||
var qMark = url.indexOf("?");
|
||||
queryString = (qMark != -1) ? url.substr(qMark) : "";
|
||||
}
|
||||
urlObject.args = OpenLayers.Util.getParameters(queryString);
|
||||
urlObject.args = OpenLayers.Util.getParameters(queryString,
|
||||
{splitArgs: options.splitArgs});
|
||||
|
||||
// pathname
|
||||
//
|
||||
|
||||
@@ -35,6 +35,11 @@ Corresponding issues/pull requests:
|
||||
|
||||
* http://github.com/openlayers/openlayers/pull/700
|
||||
|
||||
## New Map and Vector Layer Events for Feature Interaction
|
||||
|
||||
The featureclick events extension (`lib/Events/featureclick.js`) provides four new events ("featureclick", "nofeatureclick", "featureover", "featureout") that can be used as an alternative to the Feature handler or the
|
||||
SelectFeature control. It works with multiple layers out of the box and can detect hits on multiple features (except when using the Canvas renderer). See `examples/feature-events.html` for an implementation example.
|
||||
|
||||
# Behavior Changes from Past Releases
|
||||
|
||||
## Control.DragPan: Kinetic by default
|
||||
@@ -44,7 +49,7 @@ The `enableKinetic` property for the DragPan control has been changed to true by
|
||||
## Control.ModifyFeature: no more built-in SelectFeature control
|
||||
|
||||
The ModifyFeature control is now much leaner, making it more reliable when combined with other controls. The most noticable change is that it has no
|
||||
`selectControl` member any more. Users who previously relied on this built-in SelectFeature control will now have to create both a SelectFeature and a ModifyFeature control and configure the ModifyFeature control with `standalone: true`. To get features selected, call the `selectFeature` method e.g. from a `featureselected` listener on the vector layer.
|
||||
`selectControl` member any more. Users who previously relied on this built-in SelectFeature control will now have to create both a SelectFeature and a ModifyFeature control and configure the ModifyFeature control with `standalone: true`. To get features selected, call the `selectFeature` method e.g. from a `featureselected` listener on the vector layer. Note that other than in the old implementation, calling `selectFeature` on an already selected feature will not do anything.
|
||||
|
||||
## Format.GPX: No more prefixes
|
||||
|
||||
|
||||
@@ -225,6 +225,7 @@
|
||||
|
||||
// Points don't call collectVertices
|
||||
control.selectFeature(fakeFeature);
|
||||
control.unselectFeature(fakeFeature);
|
||||
|
||||
control.collectVertices = function() {
|
||||
t.ok(true, "collectVertices called");
|
||||
@@ -237,7 +238,8 @@
|
||||
layer.addFeatures = function(features) {
|
||||
t.ok(features == 'a' || features == 'd', "features passed correctly");
|
||||
}
|
||||
|
||||
layer.destroyFeatures = function() {};
|
||||
|
||||
fakeFeature.geometry = new OpenLayers.Geometry.Polygon([
|
||||
new OpenLayers.Geometry.LinearRing([
|
||||
new OpenLayers.Geometry.Point(0, 0),
|
||||
@@ -246,7 +248,9 @@
|
||||
]);
|
||||
|
||||
// OnSelect calls collectVertices and passes features to layer
|
||||
control.selectFeature(fakeFeature);
|
||||
control.selectFeature(fakeFeature);
|
||||
control.unselectFeature(fakeFeature);
|
||||
layer.destroyFeatures = OpenLayers.Layer.Vector.prototype.destroyFeatures;
|
||||
|
||||
control.vertices = ['a'];
|
||||
control.virtualVertices = [{destroy: function() {}}];
|
||||
|
||||
91
tests/Events/featureclick.html
Normal file
91
tests/Events/featureclick.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="../OLLoader.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var layer1, style, logevt, lognoevt, map, lonlat, pixel, element;
|
||||
|
||||
function init() {
|
||||
|
||||
element = document.getElementById("map");
|
||||
|
||||
style = new OpenLayers.StyleMap({
|
||||
'default': OpenLayers.Util.applyDefaults(
|
||||
{label: "${l}", pointRadius: 30},
|
||||
OpenLayers.Feature.Vector.style["default"]
|
||||
),
|
||||
'select': OpenLayers.Util.applyDefaults(
|
||||
{pointRadius: 30},
|
||||
OpenLayers.Feature.Vector.style.select
|
||||
)
|
||||
});
|
||||
|
||||
layer1 = new OpenLayers.Layer.Vector("Layer 1", {
|
||||
styleMap: style
|
||||
});
|
||||
|
||||
layer1.addFeatures([
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(0 0)"), {l:1}),
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(0 0)"), {l:1}),
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(0 0)"), {l:1}),
|
||||
new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT("POINT(0 0)"), {l:1})
|
||||
]);
|
||||
|
||||
map = new OpenLayers.Map({
|
||||
div: "map",
|
||||
allOverlays: true,
|
||||
layers: [layer1],
|
||||
zoom: 6,
|
||||
center: [0, 0],
|
||||
eventListeners: {
|
||||
featureclick: logEvent,
|
||||
nofeatureclick: logNoEvent
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function logNoEvent(e) {
|
||||
lognoevt.push(e);
|
||||
}
|
||||
|
||||
function logEvent(e) {
|
||||
logevt.push(e);
|
||||
}
|
||||
|
||||
function trigger(type, pxl) {
|
||||
var map_position = OpenLayers.Util.pagePosition(element);
|
||||
map.events.triggerEvent(type, {
|
||||
xy: pxl,
|
||||
clientX: pxl.x + map_position[0],
|
||||
clientY: pxl.y + map_position[1],
|
||||
which: 1 // which == 1 means left-click
|
||||
});
|
||||
}
|
||||
|
||||
// TESTS
|
||||
|
||||
function test_onClick(t) {
|
||||
t.plan(2);
|
||||
logevt = [];
|
||||
lognoevt = [];
|
||||
lonlat = new OpenLayers.LonLat(0,0);
|
||||
pixel = map.getPixelFromLonLat(lonlat);
|
||||
|
||||
trigger('mousedown', pixel);
|
||||
trigger('mouseup', pixel);
|
||||
|
||||
t.eq(logevt.length, 4, "4 features hit");
|
||||
|
||||
trigger('mousedown', {x: 40, y: 40});
|
||||
trigger('mouseup', {x: 40, y: 40});
|
||||
t.eq(lognoevt.length, 1, "nofeatureclick fired for click outside features.");
|
||||
}
|
||||
|
||||
// END TESTS
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
<div id="map" style="width: 300px; height: 150px; border: 1px solid black"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,12 +3,12 @@
|
||||
<script src="../OLLoader.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var flatPoints;
|
||||
var floats, smallFloats, encodedFloats;
|
||||
var signedIntegers, encodedSignedIntegers;
|
||||
var unsignedIntegers, encodedUnsignedIntegers;
|
||||
var flatPoints;
|
||||
var floats, smallFloats, encodedFloats;
|
||||
var signedIntegers, encodedSignedIntegers;
|
||||
var unsignedIntegers, encodedUnsignedIntegers;
|
||||
|
||||
function resetTestingData() {
|
||||
function resetTestingData() {
|
||||
flatPoints = [38.50000, -120.20000,
|
||||
40.70000, -120.95000,
|
||||
43.25200, -126.45300];
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
unsignedIntegers = [0, 30, 1, 31, 32, 2, 174];
|
||||
encodedUnsignedIntegers = '?]@^_@AmD';
|
||||
}
|
||||
}
|
||||
|
||||
var basePoints = new Array(
|
||||
new Array(3850000, -12020000),
|
||||
@@ -106,8 +106,8 @@
|
||||
for (i in decodedPoints) {
|
||||
var point = basePoints[i];
|
||||
var decodedPoint = decodedPoints[i];
|
||||
t.eq(point[0], decodedPoint[0]);
|
||||
t.eq(point[1], decodedPoint[1]);
|
||||
t.eq(parseInt(decodedPoint[0] * 1e5), point[0]);
|
||||
t.eq(parseInt(decodedPoint[1] * 1e5), point[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
|
||||
var format = new OpenLayers.Format.EncodedPolyline();
|
||||
|
||||
t.eq(format.encode(basePoints, 2), encoded);
|
||||
t.eq(format.encode(basePoints, 2, 1), encoded);
|
||||
}
|
||||
|
||||
function test_encodeDeltas_returns_expected_value(t) {
|
||||
|
||||
@@ -783,7 +783,7 @@
|
||||
}
|
||||
|
||||
function test_Util_isEquivalentUrl(t) {
|
||||
t.plan(9);
|
||||
t.plan(10);
|
||||
|
||||
var url1, url2, options;
|
||||
|
||||
@@ -846,6 +846,11 @@
|
||||
url2 = new Array(window.location.pathname.split("/").length-1).join("../")+"foo/bar";
|
||||
|
||||
t.ok(OpenLayers.Util.isEquivalentUrl(url1, url2), "absolute and relative path without host works for "+url2)
|
||||
|
||||
//ARGS
|
||||
url1 = "foo.html?bbox=1,2,3,4",
|
||||
url2 = url1;
|
||||
t.ok(OpenLayers.Util.isEquivalentUrl(url1, url2), "equal urls with comma delimited params are equal");
|
||||
}
|
||||
|
||||
function test_createUrlObject(t) {
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<li>Control/ZoomBox.html</li>
|
||||
<li>Events.html</li>
|
||||
<li>Events/buttonclick.html</li>
|
||||
<li>Events/featureclick.html?visible</li>
|
||||
<li>Extras.html</li>
|
||||
<li>Feature.html</li>
|
||||
<li>Feature/Vector.html</li>
|
||||
|
||||
@@ -506,7 +506,7 @@ a.olControlZoomOut {
|
||||
}
|
||||
|
||||
/* when replacing tiles, do not show tile and backbuffer at the same time */
|
||||
.olTileImage.olTileReplacing {
|
||||
.olTileReplacing {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user