~mortenoh/+junk/dhis2-detailed-import-export

« back to all changes in this revision

Viewing changes to gis/dhis-gis-geostat/mfbase/openlayers/lib/OpenLayers/Control/SelectFeature.js

  • Committer: larshelge at gmail
  • Date: 2009-03-03 16:46:36 UTC
  • Revision ID: larshelge@gmail.com-20090303164636-2sjlrquo7ib1gf7r
Initial check-in

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
 
2
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 
3
 * full text of the license. */
 
4
 
 
5
 
 
6
/**
 
7
 * @requires OpenLayers/Control.js
 
8
 * @requires OpenLayers/Feature/Vector.js
 
9
 * @requires OpenLayers/Handler/Feature.js
 
10
 */
 
11
 
 
12
/**
 
13
 * Class: OpenLayers.Control.SelectFeature
 
14
 * Selects vector features from a given layer on click or hover. 
 
15
 *
 
16
 * Inherits from:
 
17
 *  - <OpenLayers.Control>
 
18
 */
 
19
OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
 
20
    
 
21
    /**
 
22
     * Property: multipleKey
 
23
     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
 
24
     *     the <multiple> property to true.  Default is null.
 
25
     */
 
26
    multipleKey: null,
 
27
    
 
28
    /**
 
29
     * Property: toggleKey
 
30
     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
 
31
     *     the <toggle> property to true.  Default is null.
 
32
     */
 
33
    toggleKey: null,
 
34
    
 
35
    /**
 
36
     * APIProperty: multiple
 
37
     * {Boolean} Allow selection of multiple geometries.  Default is false.
 
38
     */
 
39
    multiple: false, 
 
40
 
 
41
    /**
 
42
     * APIProperty: clickout
 
43
     * {Boolean} Unselect features when clicking outside any feature.
 
44
     *     Default is true.
 
45
     */
 
46
    clickout: true,
 
47
 
 
48
    /**
 
49
     * APIProperty: toggle
 
50
     * {Boolean} Unselect a selected feature on click.  Default is false.  Only
 
51
     *     has meaning if hover is false.
 
52
     */
 
53
    toggle: false,
 
54
 
 
55
    /**
 
56
     * APIProperty: hover
 
57
     * {Boolean} Select on mouse over and deselect on mouse out.  If true, this
 
58
     * ignores clicks and only listens to mouse moves.
 
59
     */
 
60
    hover: false,
 
61
    
 
62
    /**
 
63
     * APIProperty: box
 
64
     * {Boolean} Allow feature selection by drawing a box.
 
65
     */
 
66
    box: false,
 
67
    
 
68
    /**
 
69
     * Property: onBeforeSelect 
 
70
     * {Function} Optional function to be called before a feature is selected.
 
71
     *     The function should expect to be called with a feature.
 
72
     */
 
73
    onBeforeSelect: function() {},
 
74
    
 
75
    /**
 
76
     * APIProperty: onSelect 
 
77
     * {Function} Optional function to be called when a feature is selected.
 
78
     *     The function should expect to be called with a feature.
 
79
     */
 
80
    onSelect: function() {},
 
81
 
 
82
    /**
 
83
     * APIProperty: onUnselect
 
84
     * {Function} Optional function to be called when a feature is unselected.
 
85
     *     The function should expect to be called with a feature.
 
86
     */
 
87
    onUnselect: function() {},
 
88
    
 
89
    /**
 
90
     * Property: scope
 
91
     * {Object} The scope to use with the onBeforeSelect, onSelect, onUnselect
 
92
     *     callbacks. If null the scope will be this control.
 
93
     */
 
94
    scope: this,
 
95
 
 
96
    /**
 
97
     * APIProperty: geometryTypes
 
98
     * {Array(String)} To restrict selecting to a limited set of geometry types,
 
99
     *     send a list of strings corresponding to the geometry class names.
 
100
     */
 
101
    geometryTypes: null,
 
102
 
 
103
    /**
 
104
     * Property: layer
 
105
     * {<OpenLayers.Layer.Vector>}
 
106
     */
 
107
    layer: null,
 
108
    
 
109
    /**
 
110
     * APIProperty: callbacks
 
111
     * {Object} The functions that are sent to the handlers.feature for callback
 
112
     */
 
113
    callbacks: null,
 
114
    
 
115
    /**
 
116
     * APIProperty: selectStyle 
 
117
     * {Object} Hash of styles
 
118
     */
 
119
    selectStyle: null,
 
120
    
 
121
    /**
 
122
     * Property: renderIntent
 
123
     * {String} key used to retrieve the select style from the layer's
 
124
     * style map.
 
125
     */
 
126
    renderIntent: "select",
 
127
 
 
128
    /**
 
129
     * Property: handlers
 
130
     * {Object} Object with references to multiple <OpenLayers.Handler>
 
131
     *     instances.
 
132
     */
 
133
    handlers: null,
 
134
 
 
135
    /**
 
136
     * Constructor: <OpenLayers.Control.SelectFeature>
 
137
     *
 
138
     * Parameters:
 
139
     * layer - {<OpenLayers.Layer.Vector>} 
 
140
     * options - {Object} 
 
141
     */
 
142
    initialize: function(layer, options) {
 
143
        OpenLayers.Control.prototype.initialize.apply(this, [options]);
 
144
        this.layer = layer;
 
145
        var callbacks = {
 
146
            click: this.clickFeature,
 
147
            clickout: this.clickoutFeature
 
148
        };
 
149
        if (this.hover) {
 
150
            callbacks.over = this.overFeature;
 
151
            callbacks.out = this.outFeature;
 
152
        }
 
153
             
 
154
        this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
 
155
        this.handlers = {
 
156
            feature: new OpenLayers.Handler.Feature(
 
157
                this, layer, this.callbacks, {geometryTypes: this.geometryTypes}
 
158
            )
 
159
        };
 
160
 
 
161
        if (this.box) {
 
162
            this.handlers.box = new OpenLayers.Handler.Box(
 
163
                this, {done: this.selectBox},
 
164
                {boxDivClassName: "olHandlerBoxSelectFeature"}
 
165
            ); 
 
166
        }
 
167
    },
 
168
 
 
169
    /**
 
170
     * Method: activate
 
171
     * Activates the control.
 
172
     * 
 
173
     * Returns:
 
174
     * {Boolean} The control was effectively activated.
 
175
     */
 
176
    activate: function () {
 
177
        if (!this.active) {
 
178
            this.handlers.feature.activate();
 
179
            if(this.box && this.handlers.box) {
 
180
                this.handlers.box.activate();
 
181
            }
 
182
        }
 
183
        return OpenLayers.Control.prototype.activate.apply(
 
184
            this, arguments
 
185
        );
 
186
    },
 
187
 
 
188
    /**
 
189
     * Method: deactivate
 
190
     * Deactivates the control.
 
191
     * 
 
192
     * Returns:
 
193
     * {Boolean} The control was effectively deactivated.
 
194
     */
 
195
    deactivate: function () {
 
196
        if (this.active) {
 
197
            this.handlers.feature.deactivate();
 
198
            if(this.handlers.box) {
 
199
                this.handlers.box.deactivate();
 
200
            }
 
201
        }
 
202
        return OpenLayers.Control.prototype.deactivate.apply(
 
203
            this, arguments
 
204
        );
 
205
    },
 
206
 
 
207
    /**
 
208
     * Method: unselectAll
 
209
     * Unselect all selected features.  To unselect all except for a single
 
210
     *     feature, set the options.except property to the feature.
 
211
     *
 
212
     * Parameters:
 
213
     * options - {Object} Optional configuration object.
 
214
     */
 
215
    unselectAll: function(options) {
 
216
        // we'll want an option to supress notification here
 
217
        var feature;
 
218
        for(var i=this.layer.selectedFeatures.length-1; i>=0; --i) {
 
219
            feature = this.layer.selectedFeatures[i];
 
220
            if(!options || options.except != feature) {
 
221
                this.unselect(feature);
 
222
            }
 
223
        }
 
224
    },
 
225
 
 
226
    /**
 
227
     * Method: clickFeature
 
228
     * Called on click in a feature
 
229
     * Only responds if this.hover is false.
 
230
     *
 
231
     * Parameters:
 
232
     * feature - {<OpenLayers.Feature.Vector>} 
 
233
     */
 
234
    clickFeature: function(feature) {
 
235
        if(!this.hover) {
 
236
            var selected = (OpenLayers.Util.indexOf(this.layer.selectedFeatures,
 
237
                                                    feature) > -1);
 
238
            if(selected) {
 
239
                if(this.toggleSelect()) {
 
240
                    this.unselect(feature);
 
241
                } else if(!this.multipleSelect()) {
 
242
                    this.unselectAll({except: feature});
 
243
                }
 
244
            } else {
 
245
                if(!this.multipleSelect()) {
 
246
                    this.unselectAll({except: feature});
 
247
                }
 
248
                this.select(feature);
 
249
            }
 
250
        }
 
251
    },
 
252
 
 
253
    /**
 
254
     * Method: multipleSelect
 
255
     * Allow for multiple selected features based on <multiple> property and
 
256
     *     <multipleKey> event modifier.
 
257
     *
 
258
     * Returns:
 
259
     * {Boolean} Allow for multiple selected features.
 
260
     */
 
261
    multipleSelect: function() {
 
262
        return this.multiple || this.handlers.feature.evt[this.multipleKey];
 
263
    },
 
264
    
 
265
    /**
 
266
     * Method: toggleSelect
 
267
     * Event should toggle the selected state of a feature based on <toggle>
 
268
     *     property and <toggleKey> event modifier.
 
269
     *
 
270
     * Returns:
 
271
     * {Boolean} Toggle the selected state of a feature.
 
272
     */
 
273
    toggleSelect: function() {
 
274
        return this.toggle || this.handlers.feature.evt[this.toggleKey];
 
275
    },
 
276
 
 
277
    /**
 
278
     * Method: clickoutFeature
 
279
     * Called on click outside a previously clicked (selected) feature.
 
280
     * Only responds if this.hover is false.
 
281
     *
 
282
     * Parameters:
 
283
     * feature - {<OpenLayers.Vector.Feature>} 
 
284
     */
 
285
    clickoutFeature: function(feature) {
 
286
        if(!this.hover && this.clickout) {
 
287
            this.unselectAll();
 
288
        }
 
289
    },
 
290
 
 
291
    /**
 
292
     * Method: overFeature
 
293
     * Called on over a feature.
 
294
     * Only responds if this.hover is true.
 
295
     *
 
296
     * Parameters:
 
297
     * feature - {<OpenLayers.Feature.Vector>} 
 
298
     */
 
299
    overFeature: function(feature) {
 
300
        if(this.hover &&
 
301
           (OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) == -1)) {
 
302
            this.select(feature);
 
303
        }
 
304
    },
 
305
 
 
306
    /**
 
307
     * Method: outFeature
 
308
     * Called on out of a selected feature.
 
309
     * Only responds if this.hover is true.
 
310
     *
 
311
     * Parameters:
 
312
     * feature - {<OpenLayers.Feature.Vector>} 
 
313
     */
 
314
    outFeature: function(feature) {
 
315
        if(this.hover) {
 
316
            this.unselect(feature);
 
317
        }
 
318
    },
 
319
    
 
320
    /**
 
321
     * Method: select
 
322
     * Add feature to the layer's selectedFeature array, render the feature as
 
323
     * selected, and call the onSelect function.
 
324
     * 
 
325
     * Parameters:
 
326
     * feature - {<OpenLayers.Feature.Vector>} 
 
327
     */
 
328
    select: function(feature) {
 
329
        var cont = this.onBeforeSelect.call(this.scope, feature);
 
330
        if(cont !== false) {
 
331
            cont = this.layer.events.triggerEvent("beforefeatureselected", {
 
332
                feature: feature
 
333
            });
 
334
            if(cont !== false) {
 
335
                this.layer.selectedFeatures.push(feature);
 
336
        
 
337
                var selectStyle = this.selectStyle || this.renderIntent;
 
338
                
 
339
                this.layer.drawFeature(feature, selectStyle);
 
340
                this.layer.events.triggerEvent("featureselected", {feature: feature});
 
341
                this.onSelect.call(this.scope, feature);
 
342
            }
 
343
        }
 
344
    },
 
345
 
 
346
    /**
 
347
     * Method: unselect
 
348
     * Remove feature from the layer's selectedFeature array, render the feature as
 
349
     * normal, and call the onUnselect function.
 
350
     *
 
351
     * Parameters:
 
352
     * feature - {<OpenLayers.Feature.Vector>}
 
353
     */
 
354
    unselect: function(feature) {
 
355
        // Store feature style for restoration later
 
356
        this.layer.drawFeature(feature, "default");
 
357
        OpenLayers.Util.removeItem(this.layer.selectedFeatures, feature);
 
358
        this.layer.events.triggerEvent("featureunselected", {feature: feature});
 
359
        this.onUnselect.call(this.scope, feature);
 
360
    },
 
361
    
 
362
    /**
 
363
     * Method: selectBox
 
364
     * Callback from the handlers.box set up when <box> selection is true
 
365
     *     on.
 
366
     *
 
367
     * Parameters:
 
368
     * position - {<OpenLayers.Bounds> || <OpenLayers.Pixel> }  
 
369
     */
 
370
    selectBox: function(position) {
 
371
        if (position instanceof OpenLayers.Bounds) {
 
372
            var minXY = this.map.getLonLatFromPixel(
 
373
                new OpenLayers.Pixel(position.left, position.bottom)
 
374
            );
 
375
            var maxXY = this.map.getLonLatFromPixel(
 
376
                new OpenLayers.Pixel(position.right, position.top)
 
377
            );
 
378
            var bounds = new OpenLayers.Bounds(
 
379
                minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
 
380
            );
 
381
            
 
382
            // if multiple is false, first deselect currently selected features
 
383
            if (!this.multipleSelect()) {
 
384
                this.unselectAll();
 
385
            }
 
386
            
 
387
            // because we're using a box, we consider we want multiple selection
 
388
            var prevMultiple = this.multiple;
 
389
            this.multiple = true;
 
390
            for(var i=0, len = this.layer.features.length; i<len; ++i) {
 
391
                var feature = this.layer.features[i];
 
392
                if (this.geometryTypes == null || OpenLayers.Util.indexOf(
 
393
                        this.geometryTypes, feature.geometry.CLASS_NAME) > -1) {
 
394
                    if (bounds.toGeometry().intersects(feature.geometry)) {
 
395
                        if (OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) == -1) {
 
396
                            this.select(feature);
 
397
                        }
 
398
                    }
 
399
                }
 
400
            }
 
401
            this.multiple = prevMultiple;
 
402
        }
 
403
    },
 
404
 
 
405
    /** 
 
406
     * Method: setMap
 
407
     * Set the map property for the control. 
 
408
     * 
 
409
     * Parameters:
 
410
     * map - {<OpenLayers.Map>} 
 
411
     */
 
412
    setMap: function(map) {
 
413
        this.handlers.feature.setMap(map);
 
414
        if (this.box) {
 
415
            this.handlers.box.setMap(map);
 
416
        }
 
417
        OpenLayers.Control.prototype.setMap.apply(this, arguments);
 
418
    },
 
419
 
 
420
    CLASS_NAME: "OpenLayers.Control.SelectFeature"
 
421
});