Enables unselecting selected features by clicking outside any feature. This is the default mode of the modify feature control. If you want to use the old mode where a click on a selected feature unselects that feature, set the toggle option to true. If you really want the old mode and not have selected features be unselected when clicking outside any feature, set the clickout option to false. The patch also adds the properties toggleKey and multipleKey to the modify feature control. With these one can temporarily enable the toggle and multiple mode, respectively. See the select-feature.html example to see all this in action. Thanks to pvalsecc and tschaub for the great colloration on this. (closes #1137)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@5506 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -13,7 +13,7 @@
|
|||||||
</style>
|
</style>
|
||||||
<script src="../lib/OpenLayers.js"></script>
|
<script src="../lib/OpenLayers.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var map, drawControls, select;
|
var map, drawControls;
|
||||||
OpenLayers.Feature.Vector.style['default']['strokeWidth'] = '2';
|
OpenLayers.Feature.Vector.style['default']['strokeWidth'] = '2';
|
||||||
function init(){
|
function init(){
|
||||||
map = new OpenLayers.Map('map');
|
map = new OpenLayers.Map('map');
|
||||||
@@ -38,9 +38,14 @@
|
|||||||
polygon: new OpenLayers.Control.DrawFeature(
|
polygon: new OpenLayers.Control.DrawFeature(
|
||||||
vectors, OpenLayers.Handler.Polygon
|
vectors, OpenLayers.Handler.Polygon
|
||||||
),
|
),
|
||||||
select: new OpenLayers.Control.SelectFeature(vectors),
|
select: new OpenLayers.Control.SelectFeature(
|
||||||
hover: new OpenLayers.Control.SelectFeature(
|
vectors,
|
||||||
vectors, {hover: true}
|
{
|
||||||
|
clickout: false, toggle: false,
|
||||||
|
multiple: false, hover: false,
|
||||||
|
toggleKey: "ctrlKey", // ctrl key removes from selection
|
||||||
|
multipleKey: "shiftKey" // shift key adds to selection
|
||||||
|
}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,6 +66,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var clickout = document.getElementById("clickout").checked;
|
||||||
|
drawControls.select.clickout = clickout;
|
||||||
|
var hover = document.getElementById("hover").checked;
|
||||||
|
drawControls.select.hover = hover;
|
||||||
|
if(hover && drawControls.select.active) {
|
||||||
|
// turn on/off to clear feature property of handler
|
||||||
|
drawControls.select.deactivate();
|
||||||
|
drawControls.select.activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="init()">
|
<body onload="init()">
|
||||||
@@ -94,13 +111,23 @@
|
|||||||
<li>
|
<li>
|
||||||
<input type="radio" name="type" value="select" id="selectToggle"
|
<input type="radio" name="type" value="select" id="selectToggle"
|
||||||
onclick="toggleControl(this);" />
|
onclick="toggleControl(this);" />
|
||||||
<label for="selectToggle">select feature on click</label>
|
<label for="selectToggle">select feature</label>
|
||||||
</li>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<input type="radio" name="type" value="hover" id="hoverToggle"
|
<input id="clickout" type="checkbox"
|
||||||
onclick="toggleControl(this);" />
|
name="clickout" onchange="update()" />
|
||||||
<label for="hoverToggle">select feature on hover</label>
|
<label for="clickout">click out to unselect features</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input id="hover" type="checkbox"
|
||||||
|
name="hover" onchange="update()" />
|
||||||
|
<label for="hover">hover to select features</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>Use the shift key to select multiple features. Use the ctrl key to
|
||||||
|
toggle selection on features one at a time. Note: the "clickout" option has no
|
||||||
|
effect when "hover" is selected.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -28,6 +28,20 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
*/
|
*/
|
||||||
geometryTypes: null,
|
geometryTypes: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: clickout
|
||||||
|
* {Boolean} Unselect features when clicking outside any feature.
|
||||||
|
* Default is true.
|
||||||
|
*/
|
||||||
|
clickout: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: toggle
|
||||||
|
* {Boolean} Unselect a selected feature on click.
|
||||||
|
* Default is true.
|
||||||
|
*/
|
||||||
|
toggle: true,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property: layer
|
* Property: layer
|
||||||
* {<OpenLayers.Layer.Vector>}
|
* {<OpenLayers.Layer.Vector>}
|
||||||
@@ -165,6 +179,8 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
// configure the select control
|
// configure the select control
|
||||||
var selectOptions = {
|
var selectOptions = {
|
||||||
geometryTypes: this.geometryTypes,
|
geometryTypes: this.geometryTypes,
|
||||||
|
clickout: this.clickout,
|
||||||
|
toggle: this.toggle,
|
||||||
onSelect: function(feature) {
|
onSelect: function(feature) {
|
||||||
control.selectFeature.apply(control, [feature]);
|
control.selectFeature.apply(control, [feature]);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,12 +15,40 @@
|
|||||||
*/
|
*/
|
||||||
OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
|
OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: multipleKey
|
||||||
|
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
|
||||||
|
* the <multiple> property to true. Default is null.
|
||||||
|
*/
|
||||||
|
multipleKey: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: toggleKey
|
||||||
|
* {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
|
||||||
|
* the <toggle> property to true. Default is null.
|
||||||
|
*/
|
||||||
|
toggleKey: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* APIProperty: multiple
|
* APIProperty: multiple
|
||||||
* {Boolean} Allow selection of multiple geometries
|
* {Boolean} Allow selection of multiple geometries. Default is false.
|
||||||
*/
|
*/
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: clickout
|
||||||
|
* {Boolean} Unselect features when clicking outside any feature.
|
||||||
|
* Default is true.
|
||||||
|
*/
|
||||||
|
clickout: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: toggle
|
||||||
|
* {Boolean} Unselect a selected feature on click. Default is false. Only
|
||||||
|
* has meaning if hover is false.
|
||||||
|
*/
|
||||||
|
toggle: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* APIProperty: hover
|
* APIProperty: hover
|
||||||
* {Boolean} Select on mouse over and deselect on mouse out. If true, this
|
* {Boolean} Select on mouse over and deselect on mouse out. If true, this
|
||||||
@@ -85,18 +113,31 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
this.callbacks = OpenLayers.Util.extend({
|
this.callbacks = OpenLayers.Util.extend({
|
||||||
click: this.clickFeature,
|
click: this.clickFeature,
|
||||||
|
clickout: this.clickoutFeature,
|
||||||
over: this.overFeature,
|
over: this.overFeature,
|
||||||
out: this.outFeature
|
out: this.outFeature
|
||||||
}, this.callbacks);
|
}, this.callbacks);
|
||||||
var handlerOptions = {geometryTypes: this.geometryTypes};
|
var handlerOptions = { geometryTypes: this.geometryTypes};
|
||||||
this.handler = new OpenLayers.Handler.Feature(this, layer,
|
this.handler = new OpenLayers.Handler.Feature(this, layer,
|
||||||
this.callbacks,
|
this.callbacks,
|
||||||
handlerOptions);
|
handlerOptions);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: unselectAll
|
||||||
|
* Unselect all selected features.
|
||||||
|
*/
|
||||||
|
unselectAll: function() {
|
||||||
|
// we'll want an option to supress notification here
|
||||||
|
while (this.layer.selectedFeatures.length > 0) {
|
||||||
|
this.unselect(this.layer.selectedFeatures[0]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method: clickFeature
|
* Method: clickFeature
|
||||||
* Called when the feature handler detects a click on a feature
|
* Called on click in a feature
|
||||||
|
* Only responds if this.hover is false.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* feature - {<OpenLayers.Vector.Feature>}
|
* feature - {<OpenLayers.Vector.Feature>}
|
||||||
@@ -105,56 +146,66 @@ OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
if(this.hover) {
|
if(this.hover) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.multiple) {
|
var selected = (OpenLayers.Util.indexOf(this.layer.selectedFeatures,
|
||||||
if(OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) > -1) {
|
feature) > -1);
|
||||||
|
if(!this.multiple && !this.handler.evt[this.multipleKey]) {
|
||||||
|
// perhaps an "except" argument
|
||||||
|
this.unselectAll();
|
||||||
|
}
|
||||||
|
if(selected) {
|
||||||
|
if(this.toggle || this.handler.evt[this.toggleKey]) {
|
||||||
|
// notify here
|
||||||
this.unselect(feature);
|
this.unselect(feature);
|
||||||
} else {
|
} else {
|
||||||
|
// don't notify here - could be removed if unselectAll is modified
|
||||||
this.select(feature);
|
this.select(feature);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) > -1) {
|
this.select(feature);
|
||||||
this.unselect(feature);
|
}
|
||||||
} else {
|
},
|
||||||
if (this.layer.selectedFeatures) {
|
|
||||||
for (var i = 0; i < this.layer.selectedFeatures.length; i++) {
|
/**
|
||||||
this.unselect(this.layer.selectedFeatures[i]);
|
* Method: clickoutFeature
|
||||||
}
|
* Called on click outside a previously clicked (selected) feature.
|
||||||
}
|
* Only responds if this.hover is false.
|
||||||
this.select(feature);
|
*
|
||||||
}
|
* Parameters:
|
||||||
|
* feature - {<OpenLayers.Vector.Feature>}
|
||||||
|
*/
|
||||||
|
clickoutFeature: function(feature) {
|
||||||
|
if(!this.hover && this.clickout) {
|
||||||
|
this.unselectAll();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method: overFeature
|
* Method: overFeature
|
||||||
* Called when the feature handler detects a mouse-over on a feature.
|
* Called on over a feature.
|
||||||
* Only responds if this.hover is true.
|
* Only responds if this.hover is true.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* feature - {<OpenLayers.Feature.Vector>}
|
* feature - {<OpenLayers.Feature.Vector>}
|
||||||
*/
|
*/
|
||||||
overFeature: function(feature) {
|
overFeature: function(feature) {
|
||||||
if(!this.hover) {
|
if(this.hover &&
|
||||||
return;
|
(OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) == -1)) {
|
||||||
}
|
|
||||||
if(!(OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) > -1)) {
|
|
||||||
this.select(feature);
|
this.select(feature);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method: outFeature
|
* Method: outFeature
|
||||||
* Called when the feature handler detects a mouse-out on a feature.
|
* Called on out of a selected feature.
|
||||||
* Only responds if this.hover is true.
|
* Only responds if this.hover is true.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* feature - {<OpenLayers.Feature.Vector>}
|
* feature - {<OpenLayers.Feature.Vector>}
|
||||||
*/
|
*/
|
||||||
outFeature: function(feature) {
|
outFeature: function(feature) {
|
||||||
if(!this.hover) {
|
if(this.hover) {
|
||||||
return;
|
this.unselect(feature);
|
||||||
}
|
}
|
||||||
this.unselect(feature);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ OpenLayers.Handler = OpenLayers.Class({
|
|||||||
* the callback (defined by the control).
|
* the callback (defined by the control).
|
||||||
*/
|
*/
|
||||||
callback: function (name, args) {
|
callback: function (name, args) {
|
||||||
if (this.callbacks[name]) {
|
if (name && this.callbacks[name]) {
|
||||||
this.callbacks[name].apply(this.control, args);
|
this.callbacks[name].apply(this.control, args);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,13 +7,57 @@
|
|||||||
* @requires OpenLayers/Handler.js
|
* @requires OpenLayers/Handler.js
|
||||||
*
|
*
|
||||||
* Class: OpenLayers.Handler.Feature
|
* Class: OpenLayers.Handler.Feature
|
||||||
* Handler to respond to mouse events related to a drawn feature.
|
* Handler to respond to mouse events related to a drawn feature. Callbacks
|
||||||
* Callbacks will be called for over, move, out, up, down, and click
|
* with the following keys will be notified of the following events
|
||||||
* (corresponding to the equivalent mouse events).
|
* associated with features: click, clickout, over, out, and dblclick.
|
||||||
|
*
|
||||||
|
* This handler stops event propagation for mousedown and mouseup if those
|
||||||
|
* browser events target features that can be selected.
|
||||||
*/
|
*/
|
||||||
OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Property: EVENTMAP
|
||||||
|
* {Object} A object mapping the browser events to objects with callback
|
||||||
|
* keys for in and out.
|
||||||
|
*/
|
||||||
|
EVENTMAP: {
|
||||||
|
'click': {'in': 'click', 'out': 'clickout'},
|
||||||
|
'mousemove': {'in': 'over', 'out': 'out'},
|
||||||
|
'dblclick': {'in': 'dblclick', 'out': null},
|
||||||
|
'mousedown': {'in': null, 'out': null},
|
||||||
|
'mouseup': {'in': null, 'out': null}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: feature
|
||||||
|
* {<OpenLayers.Feature.Vector>} The last feature that was handled.
|
||||||
|
*/
|
||||||
|
feature: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: down
|
||||||
|
* {<OpenLayers.Pixel>} The location of the last mousedown.
|
||||||
|
*/
|
||||||
|
down: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: up
|
||||||
|
* {<OpenLayers.Pixel>} The location of the last mouseup.
|
||||||
|
*/
|
||||||
|
up: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: clickoutTolerance
|
||||||
|
* {Number} The number of pixels the mouse can move during a click that
|
||||||
|
* still constitutes a click out. When dragging the map, clicks should
|
||||||
|
* not trigger the clickout property unless this tolerance is reached.
|
||||||
|
* Default is 4.
|
||||||
|
*/
|
||||||
|
clickoutTolerance: 4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: geometryTypes
|
||||||
* To restrict dragging to a limited set of geometry types, send a list
|
* To restrict dragging to a limited set of geometry types, send a list
|
||||||
* of strings corresponding to the geometry class names.
|
* of strings corresponding to the geometry class names.
|
||||||
*
|
*
|
||||||
@@ -27,12 +71,6 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
|||||||
*/
|
*/
|
||||||
layerIndex: null,
|
layerIndex: null,
|
||||||
|
|
||||||
/**
|
|
||||||
* Property: feature
|
|
||||||
* {<OpenLayers.Feature.Vector>}
|
|
||||||
*/
|
|
||||||
feature: null,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor: OpenLayers.Handler.Feature
|
* Constructor: OpenLayers.Handler.Feature
|
||||||
*
|
*
|
||||||
@@ -49,117 +87,161 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
|||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Method: click
|
|
||||||
* Handle click. Call the "click" callback if down on a feature.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* evt - {Event}
|
|
||||||
*/
|
|
||||||
click: function(evt) {
|
|
||||||
var selected = this.select('click', evt);
|
|
||||||
return !selected; // stop event propagation if selected
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method: mousedown
|
* Method: mousedown
|
||||||
* Handle mouse down. Call the "down" callback if down on a feature.
|
* Handle mouse down. Stop propagation if a feature is targeted by this
|
||||||
|
* event (stops map dragging during feature selection).
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* evt - {Event}
|
* evt - {Event}
|
||||||
*/
|
*/
|
||||||
mousedown: function(evt) {
|
mousedown: function(evt) {
|
||||||
var selected = this.select('down', evt);
|
this.down = evt.xy;
|
||||||
return !selected; // stop event propagation if selected
|
return !this.handle(evt);
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method: mousemove
|
|
||||||
* Handle mouse moves. Call the "move" callback if moving over a feature.
|
|
||||||
* Call the "over" callback if moving over a feature for the first time.
|
|
||||||
* Call the "out" callback if moving off of a feature.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* evt - {Event}
|
|
||||||
*/
|
|
||||||
mousemove: function(evt) {
|
|
||||||
this.select('move', evt);
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method: mouseup
|
* Method: mouseup
|
||||||
* Handle mouse up. Call the "up" callback if up on a feature.
|
* Handle mouse up. Stop propagation if a feature is targeted by this
|
||||||
|
* event.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* evt - {Event}
|
* evt - {Event}
|
||||||
*/
|
*/
|
||||||
mouseup: function(evt) {
|
mouseup: function(evt) {
|
||||||
var selected = this.select('up', evt);
|
this.up = evt.xy;
|
||||||
return !selected; // stop event propagation if selected
|
return !this.handle(evt);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: click
|
||||||
|
* Handle click. Call the "click" callback if click on a feature,
|
||||||
|
* or the "clickout" callback if click outside any feature.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* evt - {Event}
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Boolean}
|
||||||
|
*/
|
||||||
|
click: function(evt) {
|
||||||
|
return !this.handle(evt);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: mousemove
|
||||||
|
* Handle mouse moves. Call the "over" callback if move over a feature,
|
||||||
|
* or the "out" callback if move outside any feature.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* evt - {Event}
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Boolean}
|
||||||
|
*/
|
||||||
|
mousemove: function(evt) {
|
||||||
|
this.handle(evt);
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method: dblclick
|
* Method: dblclick
|
||||||
* Capture double-clicks. Let the event continue propagating if the
|
* Handle dblclick. Call the "dblclick" callback if dblclick on a feature.
|
||||||
* double-click doesn't hit a feature. Otherwise call the dblclick
|
|
||||||
* callback.
|
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* evt - {Event}
|
* evt - {Event}
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Boolean}
|
||||||
*/
|
*/
|
||||||
dblclick: function(evt) {
|
dblclick: function(evt) {
|
||||||
var selected = this.select('dblclick', evt);
|
return !this.handle(evt);
|
||||||
return !selected; // stop event propagation if selected
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method: select
|
* Method: geometryTypeMatches
|
||||||
* Trigger the appropriate callback if a feature is under the mouse.
|
* Return true if the geometry type of the passed feature matches
|
||||||
|
* one of the geometry types in the geometryTypes array.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* type - {String} Callback key
|
* feature - {<OpenLayers.Vector.Feature>}
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* {Boolean} A feature was selected
|
* {Boolean}
|
||||||
*/
|
*/
|
||||||
select: function(type, evt) {
|
geometryTypeMatches: function(feature) {
|
||||||
|
return this.geometryTypes == null ||
|
||||||
|
OpenLayers.Util.indexOf(this.geometryTypes,
|
||||||
|
feature.geometry.CLASS_NAME) > -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: handle
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* evt - {Event}
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Boolean} Stop event propagation.
|
||||||
|
*/
|
||||||
|
handle: function(evt) {
|
||||||
|
var type = evt.type;
|
||||||
|
var stopEvtPropag = false;
|
||||||
|
var lastFeature = this.feature;
|
||||||
var feature = this.layer.getFeatureFromEvent(evt);
|
var feature = this.layer.getFeatureFromEvent(evt);
|
||||||
var selected = false;
|
|
||||||
if(feature) {
|
if(feature) {
|
||||||
if(this.geometryTypes == null ||
|
if(this.geometryTypeMatches(feature)) {
|
||||||
(OpenLayers.Util.indexOf(this.geometryTypes,
|
if(lastFeature && (lastFeature != feature)) {
|
||||||
feature.geometry.CLASS_NAME) > -1)) {
|
// out of last feature
|
||||||
// three cases:
|
this.triggerCallback(type, 'out', [lastFeature]);
|
||||||
// over a new, out of the last and over a new, or still on the last
|
|
||||||
if(!this.feature) {
|
|
||||||
// over a new feature
|
|
||||||
this.callback('over', [feature]);
|
|
||||||
} else if(this.feature != feature) {
|
|
||||||
// out of the last and over a new
|
|
||||||
this.callback('out', [this.feature]);
|
|
||||||
this.callback('over', [feature]);
|
|
||||||
}
|
}
|
||||||
this.feature = feature;
|
this.triggerCallback(type, 'in', [feature]);
|
||||||
this.callback(type, [feature]);
|
lastFeature = feature;
|
||||||
selected = true;
|
stopEvtPropag = true;
|
||||||
} else {
|
} else {
|
||||||
if(this.feature && (this.feature != feature)) {
|
if(lastFeature && (lastFeature != feature)) {
|
||||||
// out of the last and over a new
|
// out of last feature
|
||||||
this.callback('out', [this.feature]);
|
this.triggerCallback(type, 'out', [lastFeature]);
|
||||||
this.feature = null;
|
lastFeature = feature;
|
||||||
}
|
}
|
||||||
selected = false;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(this.feature) {
|
if(lastFeature) {
|
||||||
// out of the last
|
this.triggerCallback(type, 'out', [lastFeature]);
|
||||||
this.callback('out', [this.feature]);
|
lastFeature = null;
|
||||||
this.feature = null;
|
}
|
||||||
|
}
|
||||||
|
if(lastFeature) {
|
||||||
|
this.feature = lastFeature;
|
||||||
|
}
|
||||||
|
return stopEvtPropag;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: triggerCallback
|
||||||
|
* Call the callback keyed in the event map with the supplied arguments.
|
||||||
|
* For click out, the <clickoutTolerance> is checked first.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* type - {String}
|
||||||
|
*/
|
||||||
|
triggerCallback: function(type, mode, args) {
|
||||||
|
var key = this.EVENTMAP[type][mode];
|
||||||
|
if(key) {
|
||||||
|
if(type == 'click' && mode == 'out' && this.up && this.down) {
|
||||||
|
// for clickout, only trigger callback if tolerance is met
|
||||||
|
var dpx = Math.sqrt(
|
||||||
|
Math.pow(this.up.x - this.down.x, 2) +
|
||||||
|
Math.pow(this.up.y - this.down.y, 2)
|
||||||
|
);
|
||||||
|
if(dpx <= this.clickoutTolerance) {
|
||||||
|
this.callback(key, args);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.callback(key, args);
|
||||||
}
|
}
|
||||||
selected = false;
|
|
||||||
}
|
}
|
||||||
return selected;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,13 +252,13 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
|||||||
* {Boolean}
|
* {Boolean}
|
||||||
*/
|
*/
|
||||||
activate: function() {
|
activate: function() {
|
||||||
|
var activated = false;
|
||||||
if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
|
if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
|
||||||
this.layerIndex = this.layer.div.style.zIndex;
|
this.layerIndex = this.layer.div.style.zIndex;
|
||||||
this.layer.div.style.zIndex = this.map.Z_INDEX_BASE['Popup'] - 1;
|
this.layer.div.style.zIndex = this.map.Z_INDEX_BASE['Popup'] - 1;
|
||||||
return true;
|
activated = true;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return activated;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -187,14 +269,17 @@ OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
|
|||||||
* {Boolean}
|
* {Boolean}
|
||||||
*/
|
*/
|
||||||
deactivate: function() {
|
deactivate: function() {
|
||||||
|
var deactivated = false;
|
||||||
if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
|
if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
|
||||||
if (this.layer && this.layer.div) {
|
if (this.layer && this.layer.div) {
|
||||||
this.layer.div.style.zIndex = this.layerIndex;
|
this.layer.div.style.zIndex = this.layerIndex;
|
||||||
}
|
}
|
||||||
return true;
|
this.feature = null;
|
||||||
} else {
|
this.down = null;
|
||||||
return false;
|
this.up = null;
|
||||||
|
deactivated = true;
|
||||||
}
|
}
|
||||||
|
return deactivated;
|
||||||
},
|
},
|
||||||
|
|
||||||
CLASS_NAME: "OpenLayers.Handler.Feature"
|
CLASS_NAME: "OpenLayers.Handler.Feature"
|
||||||
|
|||||||
@@ -85,7 +85,7 @@
|
|||||||
layer.getFeatureFromEvent = function(evt) {
|
layer.getFeatureFromEvent = function(evt) {
|
||||||
return "foo";
|
return "foo";
|
||||||
}
|
}
|
||||||
map.events.triggerEvent("mousemove");
|
map.events.triggerEvent("mousemove", {type: "mousemove"});
|
||||||
|
|
||||||
t.eq(control.feature, "foo",
|
t.eq(control.feature, "foo",
|
||||||
"control gets the proper feature from the feature handler");
|
"control gets the proper feature from the feature handler");
|
||||||
@@ -107,14 +107,14 @@
|
|||||||
layer.getFeatureFromEvent = function(evt) {
|
layer.getFeatureFromEvent = function(evt) {
|
||||||
return "foo";
|
return "foo";
|
||||||
}
|
}
|
||||||
map.events.triggerEvent("mousemove");
|
map.events.triggerEvent("mousemove", {type: "mousemove"});
|
||||||
|
|
||||||
// simulate a mousedown on a feature
|
// simulate a mousedown on a feature
|
||||||
control.onStart = function(feature, pixel) {
|
control.onStart = function(feature, pixel) {
|
||||||
t.eq(feature, "foo", "onStart called with the correct feature");
|
t.eq(feature, "foo", "onStart called with the correct feature");
|
||||||
t.eq(pixel, "bar", "onStart called with the correct pixel");
|
t.eq(pixel, "bar", "onStart called with the correct pixel");
|
||||||
}
|
}
|
||||||
map.events.triggerEvent("mousedown", {xy: "bar", which: 1});
|
map.events.triggerEvent("mousedown", {xy: "bar", which: 1, type: "mousemove"});
|
||||||
|
|
||||||
t.eq(control.lastPixel, "bar",
|
t.eq(control.lastPixel, "bar",
|
||||||
"mousedown sets the lastPixel correctly");
|
"mousedown sets the lastPixel correctly");
|
||||||
@@ -152,15 +152,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// simulate a mouseover on a feature
|
// simulate a mouseover on a feature
|
||||||
map.events.triggerEvent("mousemove");
|
map.events.triggerEvent("mousemove", {type: "mousemove"});
|
||||||
|
|
||||||
// simulate a mousedown on a feature
|
// simulate a mousedown on a feature
|
||||||
var down = new OpenLayers.Pixel(0, 0);
|
var down = new OpenLayers.Pixel(0, 0);
|
||||||
map.events.triggerEvent("mousedown", {xy: down, which: 1});
|
map.events.triggerEvent("mousedown", {xy: down, which: 1, type: "mousemove"});
|
||||||
|
|
||||||
// simulate a mousemove on a feature
|
// simulate a mousemove on a feature
|
||||||
var move = new OpenLayers.Pixel(1, 2);
|
var move = new OpenLayers.Pixel(1, 2);
|
||||||
map.events.triggerEvent("mousemove", {xy: move, which: 1});
|
map.events.triggerEvent("mousemove", {xy: move, which: 1, type: "mousemove"});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
layer.getFeatureFromEvent = function() {
|
layer.getFeatureFromEvent = function() {
|
||||||
return "foo";
|
return "foo";
|
||||||
};
|
};
|
||||||
map.events.triggerEvent("mousemove");
|
map.events.triggerEvent("mousemove", {type: "mousemove"});
|
||||||
t.eq(control.feature, "foo",
|
t.eq(control.feature, "foo",
|
||||||
"feature is set on mouse over");
|
"feature is set on mouse over");
|
||||||
control.doneDragging();
|
control.doneDragging();
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
layer.getFeatureFromEvent = function() {
|
layer.getFeatureFromEvent = function() {
|
||||||
return "foo";
|
return "foo";
|
||||||
};
|
};
|
||||||
map.events.triggerEvent("mousemove");
|
map.events.triggerEvent("mousemove", {type: "mousemove"});
|
||||||
t.eq(control.feature, "foo",
|
t.eq(control.feature, "foo",
|
||||||
"feature is set on mouse over");
|
"feature is set on mouse over");
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
layer.getFeatureFromEvent = function() {
|
layer.getFeatureFromEvent = function() {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
map.events.triggerEvent("mousemove");
|
map.events.triggerEvent("mousemove", {type: "mousemove"});
|
||||||
t.ok(control.feature == null,
|
t.ok(control.feature == null,
|
||||||
"feature is set to null on mouse out");
|
"feature is set to null on mouse out");
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function test_Handler_feature_geometrytype_limit(t) {
|
function test_Handler_feature_geometrytype_limit(t) {
|
||||||
t.plan(2);
|
t.plan(1);
|
||||||
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0));
|
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0));
|
||||||
var map = new OpenLayers.Map('map');
|
var map = new OpenLayers.Map('map');
|
||||||
var control = new OpenLayers.Control();
|
var control = new OpenLayers.Control();
|
||||||
@@ -112,16 +112,17 @@
|
|||||||
handler.callback = function(type,featurelist) {
|
handler.callback = function(type,featurelist) {
|
||||||
t.eq(featurelist[0].id, feature.id, "Correct feature called back on");
|
t.eq(featurelist[0].id, feature.id, "Correct feature called back on");
|
||||||
}
|
}
|
||||||
handler.select("foo", {});
|
handler.handle({type: "click"});
|
||||||
handler.feature = null;
|
handler.feature = null;
|
||||||
|
handler.lastFeature = null;
|
||||||
handler.callback = function(type,featurelist) {
|
handler.callback = function(type,featurelist) {
|
||||||
t.fail("Shouldn't have called back on " + featurelist[0].geometry);
|
t.fail("Shouldn't have called back on " + featurelist[0].geometry);
|
||||||
}
|
}
|
||||||
feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(0,0));
|
feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(0,0));
|
||||||
handler.select("foo", {});
|
handler.handle("click", {});
|
||||||
}
|
}
|
||||||
function test_Handler_Feature_callbacks(t) {
|
function test_Handler_Feature_callbacks(t) {
|
||||||
t.plan(75);
|
t.plan(9);
|
||||||
|
|
||||||
var map = new OpenLayers.Map('map', {controls: []});
|
var map = new OpenLayers.Map('map', {controls: []});
|
||||||
var control = new OpenLayers.Control();
|
var control = new OpenLayers.Control();
|
||||||
@@ -129,95 +130,88 @@
|
|||||||
var layer = new OpenLayers.Layer();
|
var layer = new OpenLayers.Layer();
|
||||||
map.addLayer(layer);
|
map.addLayer(layer);
|
||||||
|
|
||||||
var evtsToTest = [
|
|
||||||
{
|
|
||||||
shortName: "down",
|
|
||||||
longName: "mousedown"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
shortName: "move",
|
|
||||||
longName: "mousemove"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
shortName: "up",
|
|
||||||
longName: "mouseup"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
shortName: "click",
|
|
||||||
longName: "click"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
shortName: "dblclick",
|
|
||||||
longName: "dblclick"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
var numEvents = {};
|
|
||||||
var callbacks = {};
|
var callbacks = {};
|
||||||
|
var newFeature, lastFeature;
|
||||||
|
var evtPx = {xy: new OpenLayers.Pixel(Math.random(), Math.random())};
|
||||||
|
|
||||||
var newFeature;
|
// define a callback factory function
|
||||||
var oldFeature;
|
|
||||||
|
|
||||||
function getCallback(evt, feature) {
|
function getCallback(evt, feature) {
|
||||||
return function(f) {
|
return function(f) {
|
||||||
t.ok(f == feature, "callback called with proper feature");
|
t.ok(f == feature, evt + " callback called with proper feature");
|
||||||
numEvents[evt]++;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// override the layer's getFeatureFromEvent func so that it always
|
||||||
|
// returns newFeature
|
||||||
layer.getFeatureFromEvent = function(evt) { return newFeature; };
|
layer.getFeatureFromEvent = function(evt) { return newFeature; };
|
||||||
|
|
||||||
var handler = new OpenLayers.Handler.Feature(control, layer, callbacks);
|
var handler = new OpenLayers.Handler.Feature(control, layer, callbacks);
|
||||||
handler.activate();
|
handler.activate();
|
||||||
|
|
||||||
for (var i = 0; i < evtsToTest.length; i++) {
|
// test click in new feature
|
||||||
evt = evtsToTest[i];
|
// only 'click' callback should be called
|
||||||
|
handler.feature = null;
|
||||||
|
lastFeature = null;
|
||||||
|
newFeature = new OpenLayers.Feature.Vector();
|
||||||
|
callbacks['click'] = getCallback('click', newFeature);
|
||||||
|
callbacks['clickout'] = getCallback('clickout', lastFeature);
|
||||||
|
evtPx.type = "click";
|
||||||
|
map.events.triggerEvent('click', evtPx);
|
||||||
|
|
||||||
var evtShortName = evt.shortName;
|
// test click in new feature and out of last feature
|
||||||
var evtLongName = evt.longName;
|
// both 'click' and 'clickout' callbacks should be called
|
||||||
|
lastFeature = newFeature;
|
||||||
|
newFeature = new OpenLayers.Feature.Vector();
|
||||||
|
callbacks['click'] = getCallback('click', newFeature);
|
||||||
|
callbacks['clickout'] = getCallback('clickout', lastFeature);
|
||||||
|
evtPx.type = "click";
|
||||||
|
map.events.triggerEvent('click', evtPx);
|
||||||
|
|
||||||
var evtPx = {xy: new OpenLayers.Pixel(Math.random(), Math.random())};
|
// test click out of last feature
|
||||||
|
// only 'clickout' callback should be called
|
||||||
|
lastFeature = newFeature;
|
||||||
|
newFeature = null;
|
||||||
|
callbacks['click'] = getCallback('click', newFeature);
|
||||||
|
callbacks['clickout'] = getCallback('clickout', lastFeature);
|
||||||
|
evtPx.type = "click";
|
||||||
|
map.events.triggerEvent('click', evtPx);
|
||||||
|
|
||||||
handler.feature = null;
|
// test over a new feature
|
||||||
|
// only 'over' callback should be called
|
||||||
|
handler.feature = null;
|
||||||
|
lastFeature = null;
|
||||||
|
newFeature = new OpenLayers.Feature.Vector();
|
||||||
|
callbacks['over'] = getCallback('over', newFeature);
|
||||||
|
callbacks['out'] = getCallback('out', lastFeature);
|
||||||
|
evtPx.type = "mousemove";
|
||||||
|
map.events.triggerEvent('mousemove', evtPx);
|
||||||
|
|
||||||
numEvents[evtShortName] = 0;
|
// test over a new feature and out of last feature
|
||||||
numEvents["over"] = 0;
|
// both 'over' and 'out' callbacks should be called
|
||||||
numEvents["out"] = 0;
|
lastFeature = newFeature;
|
||||||
oldFeature = null;
|
newFeature = new OpenLayers.Feature.Vector();
|
||||||
newFeature = new OpenLayers.Feature.Vector();
|
callbacks['over'] = getCallback('over', newFeature);
|
||||||
callbacks[evtShortName] = getCallback(evtShortName, newFeature);
|
callbacks['out'] = getCallback('out', lastFeature);
|
||||||
callbacks["over"] = getCallback("over", newFeature);
|
evtPx.type = "mousemove";
|
||||||
callbacks["out"] = getCallback("out", oldFeature);
|
map.events.triggerEvent('mousemove', evtPx);
|
||||||
map.events.triggerEvent(evtLongName, evtPx);
|
|
||||||
t.ok(numEvents[evtShortName] == 1, evtShortName + " triggered click callback");
|
|
||||||
t.ok(numEvents["over"] == 1, evtShortName + " triggered over callbacks");
|
|
||||||
t.ok(numEvents["out"] == 0, evtShortName + " did not trigger out callback");
|
|
||||||
|
|
||||||
numEvents[evtShortName] = 0;
|
// test out of last feature
|
||||||
numEvents["over"] = 0;
|
// only 'out' callback should be called
|
||||||
numEvents["out"] = 0;
|
lastFeature = newFeature;
|
||||||
oldFeature = newFeature;
|
newFeature = null;
|
||||||
newFeature = new OpenLayers.Feature.Vector();
|
callbacks['over'] = getCallback('over', newFeature);
|
||||||
callbacks[evtShortName] = getCallback(evtShortName, newFeature);
|
callbacks['out'] = getCallback('out', lastFeature);
|
||||||
callbacks["over"] = getCallback("over", newFeature);
|
evtPx.type = "mousemove";
|
||||||
callbacks["out"] = getCallback("out", oldFeature);
|
map.events.triggerEvent('mousemove', evtPx);
|
||||||
map.events.triggerEvent(evtLongName, evtPx);
|
|
||||||
t.ok(numEvents[evtShortName] == 1, evtShortName + " triggered click callback");
|
|
||||||
t.ok(numEvents["over"] == 1, evtShortName + " triggered over callbacks");
|
|
||||||
t.ok(numEvents["out"] == 1, evtShortName + " triggered out callback");
|
|
||||||
|
|
||||||
numEvents[evtShortName] = 0;
|
// test dblclick on a feature
|
||||||
numEvents["over"] = 0;
|
// 'dblclick' callback should be called
|
||||||
numEvents["out"] = 0;
|
handler.feature = null;
|
||||||
oldFeature = newFeature;
|
lastFeature = null;
|
||||||
callbacks[evtShortName] = getCallback(evtShortName, newFeature);
|
newFeature = new OpenLayers.Feature.Vector();
|
||||||
callbacks["over"] = getCallback("over", newFeature);
|
callbacks['dblclick'] = getCallback('dblclick', newFeature);
|
||||||
callbacks["out"] = getCallback("out", oldFeature);
|
evtPx.type = "dblclick";
|
||||||
map.events.triggerEvent(evtLongName, evtPx);
|
map.events.triggerEvent('dblclick', evtPx);
|
||||||
t.ok(numEvents[evtShortName] == 1, evtShortName + " triggered click callback");
|
|
||||||
t.ok(numEvents["over"] == 0, evtShortName + " did not trigger over callbacks");
|
|
||||||
t.ok(numEvents["out"] == 0, evtShortName + " did not trigger out callback");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_Handler_Feature_deactivate(t) {
|
function test_Handler_Feature_deactivate(t) {
|
||||||
|
|||||||
Reference in New Issue
Block a user