Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-routing-foss4g/web/OpenLayers/lib/OpenLayers/Control/GetFeature.js @ 81

Revision 76, 19.4 KB checked in by djay, 12 years ago (diff)

Ajout du répertoire web

  • Property svn:executable set to *
Line 
1/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
2 * full list of contributors). Published under the Clear BSD license. 
3 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
4 * full text of the license. */
5
6/**
7 * @requires OpenLayers/Control.js
8 * @requires OpenLayers/Handler/Click.js
9 * @requires OpenLayers/Handler/Box.js
10 * @requires OpenLayers/Handler/Hover.js
11 * @requires OpenLayers/Filter/Spatial.js
12 */
13
14/**
15 * Class: OpenLayers.Control.GetFeature
16 * Gets vector features for locations underneath the mouse cursor. Can be
17 *     configured to act on click, hover or dragged boxes. Uses an
18 *     <OpenLayers.Protocol> that supports spatial filters to retrieve
19 *     features from a server and fires events that notify applications of the
20 *     selected features.
21 *
22 * Inherits from:
23 *  - <OpenLayers.Control>
24 */
25OpenLayers.Control.GetFeature = OpenLayers.Class(OpenLayers.Control, {
26   
27    /**
28     * APIProperty: protocol
29     * {<OpenLayers.Protocol>} Required. The protocol used for fetching
30     *     features.
31     */
32    protocol: null,
33   
34    /**
35     * APIProperty: multipleKey
36     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
37     *     the <multiple> property to true.  Default is null.
38     */
39    multipleKey: null,
40   
41    /**
42     * APIProperty: toggleKey
43     * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
44     *     the <toggle> property to true.  Default is null.
45     */
46    toggleKey: null,
47   
48    /**
49     * Property: modifiers
50     * {Object} The event modifiers to use, according to the current event
51     *     being handled by this control's handlers
52     */
53    modifiers: null,
54   
55    /**
56     * APIProperty: multiple
57     * {Boolean} Allow selection of multiple geometries.  Default is false.
58     */
59    multiple: false, 
60
61    /**
62     * APIProperty: click
63     * {Boolean} Use a click handler for selecting/unselecting features. If
64     *     both <click> and <box> are set to true, the click handler takes
65     *     precedence over the box handler if a box with zero extent was
66     *     selected.  Default is true.
67     */
68    click: true,
69
70    /**
71     * APIProperty: single
72     * {Boolean} Tells whether select by click should select a single
73     *     feature. If set to false, all matching features are selected.
74     *     If set to true, only the best matching feature is selected.
75     *     This option has an effect only of the <click> option is set
76     *     to true. Default is true.
77     */
78    single: true,
79   
80    /**
81     * APIProperty: clickout
82     * {Boolean} Unselect features when clicking outside any feature.
83     *     Applies only if <click> is true.  Default is true.
84     */
85    clickout: true,
86   
87    /**
88     * APIProperty: toggle
89     * {Boolean} Unselect a selected feature on click.  Applies only if
90     *     <click> is true.  Default is false.
91     */
92    toggle: false,
93
94    /**
95     * APIProperty: clickTolerance
96     * {Integer} Tolerance for the filter query in pixels. This has the
97     *     same effect as the tolerance parameter on WMS GetFeatureInfo
98     *     requests.  Will be ignored for box selections.  Applies only if
99     *     <click> or <hover> is true.  Default is 5.  Note that this not
100     *     only affects requests on click, but also on hover.
101     */
102    clickTolerance: 5,
103   
104    /**
105     * APIProperty: hover
106     * {Boolean} Send feature requests on mouse moves.  Default is false.
107     */
108    hover: false,
109
110    /**
111     * APIProperty: box
112     * {Boolean} Allow feature selection by drawing a box. If set to
113     *     true set <click> to false to disable the click handler and
114     *     rely on the box handler only, even for "zero extent" boxes.
115     *     See the description of the <click> option for additional
116     *     information.  Default is false.
117     */
118    box: false,
119   
120    /**
121     * APIProperty: maxFeatures
122     * {Integer} Maximum number of features to return from a query in single mode
123     *     if supported by the <protocol>. This set of features is then used to
124     *     determine the best match client-side. Default is 10.
125     */
126    maxFeatures: 10,
127   
128    /**
129     * Property: features
130     * {Object} Hash of {<OpenLayers.Feature.Vector>}, keyed by fid, holding
131     *     the currently selected features
132     */
133    features: null,
134   
135    /**
136     * Proeprty: hoverFeature
137     * {<OpenLayers.Feature.Vector>} The feature currently selected by the
138     *     hover handler
139     */
140    hoverFeature: null,
141   
142    /**
143     * APIProperty: handlerOptions
144     * {Object} Additional options for the handlers used by this control. This
145     *     is a hash with the keys "click", "box" and "hover".
146     */
147    handlerOptions: null,
148   
149    /**
150     * Property: handlers
151     * {Object} Object with references to multiple <OpenLayers.Handler>
152     *     instances.
153     */
154    handlers: null,
155
156    /**
157     * Property: hoverResponse
158     * {<OpenLayers.Protocol.Response>} The response object associated with
159     *     the currently running hover request (if any).
160     */
161    hoverResponse: null,
162   
163    /**
164     * Property: filterType
165     * {<String>} The type of filter to use when sending off a request.
166     *     Possible values:
167     *     OpenLayers.Filter.Spatial.<BBOX|INTERSECTS|WITHIN|CONTAINS>
168     *     Defaults to: OpenLayers.Filter.Spatial.BBOX
169     */
170    filterType: OpenLayers.Filter.Spatial.BBOX,
171
172    /**
173     * Constant: EVENT_TYPES
174     *
175     * Supported event types:
176     * beforefeatureselected - Triggered when <click> is true before a
177     *      feature is selected. The event object has a feature property with
178     *      the feature about to select
179     * featureselected - Triggered when <click> is true and a feature is
180     *      selected. The event object has a feature property with the
181     *      selected feature
182     * beforefeaturesselected - Triggered when <click> is true before a
183     *      set of features is selected. The event object is an array of
184     *      feature properties with the features about to be selected. 
185     *      Return false after receiving this event to discontinue processing
186     *      of all featureselected events and the featuresselected event.
187     * featuresselected - Triggered when <click> is true and a set of
188     *      features is selected.  The event object is an array of feature
189     *      properties of the selected features
190     * featureunselected - Triggered when <click> is true and a feature is
191     *      unselected. The event object has a feature property with the
192     *      unselected feature
193     * clickout - Triggered when when <click> is true and no feature was
194     *      selected.
195     * hoverfeature - Triggered when <hover> is true and the mouse has
196     *      stopped over a feature
197     * outfeature - Triggered when <hover> is true and the mouse moves
198     *      moved away from a hover-selected feature
199     */
200    EVENT_TYPES: ["featureselected", "featuresselected", "featureunselected", 
201        "clickout", "beforefeatureselected", "beforefeaturesselected", 
202        "hoverfeature", "outfeature"],
203
204    /**
205     * Constructor: OpenLayers.Control.GetFeature
206     * Create a new control for fetching remote features.
207     *
208     * Parameters:
209     * options - {Object} A configuration object which at least has to contain
210     *     a <protocol> property
211     */
212    initialize: function(options) {
213        // concatenate events specific to vector with those from the base
214        this.EVENT_TYPES =
215            OpenLayers.Control.GetFeature.prototype.EVENT_TYPES.concat(
216            OpenLayers.Control.prototype.EVENT_TYPES
217        );
218
219        options.handlerOptions = options.handlerOptions || {};
220
221        OpenLayers.Control.prototype.initialize.apply(this, [options]);
222       
223        this.features = {};
224
225        this.handlers = {};
226       
227        if(this.click) {
228            this.handlers.click = new OpenLayers.Handler.Click(this,
229                {click: this.selectClick}, this.handlerOptions.click || {});
230        }
231
232        if(this.box) {
233            this.handlers.box = new OpenLayers.Handler.Box(
234                this, {done: this.selectBox},
235                OpenLayers.Util.extend(this.handlerOptions.box, {
236                    boxDivClassName: "olHandlerBoxSelectFeature"
237                })
238            ); 
239        }
240       
241        if(this.hover) {
242            this.handlers.hover = new OpenLayers.Handler.Hover(
243                this, {'move': this.cancelHover, 'pause': this.selectHover},
244                OpenLayers.Util.extend(this.handlerOptions.hover, {
245                    'delay': 250
246                })
247            );
248        }
249    },
250   
251    /**
252     * Method: activate
253     * Activates the control.
254     *
255     * Returns:
256     * {Boolean} The control was effectively activated.
257     */
258    activate: function () {
259        if (!this.active) {
260            for(var i in this.handlers) {
261                this.handlers[i].activate();
262            }
263        }
264        return OpenLayers.Control.prototype.activate.apply(
265            this, arguments
266        );
267    },
268
269    /**
270     * Method: deactivate
271     * Deactivates the control.
272     *
273     * Returns:
274     * {Boolean} The control was effectively deactivated.
275     */
276    deactivate: function () {
277        if (this.active) {
278            for(var i in this.handlers) {
279                this.handlers[i].deactivate();
280            }
281        }
282        return OpenLayers.Control.prototype.deactivate.apply(
283            this, arguments
284        );
285    },
286   
287    /**
288     * Method: selectClick
289     * Called on click
290     *
291     * Parameters:
292     * evt - {<OpenLayers.Event>}
293     */
294    selectClick: function(evt) {
295        var bounds = this.pixelToBounds(evt.xy);
296       
297        this.setModifiers(evt);
298        this.request(bounds, {single: this.single});
299    },
300
301    /**
302     * Method: selectBox
303     * Callback from the handlers.box set up when <box> selection is on
304     *
305     * Parameters:
306     * position - {<OpenLayers.Bounds>} 
307     */
308    selectBox: function(position) {
309        var bounds;
310        if (position instanceof OpenLayers.Bounds) {
311            var minXY = this.map.getLonLatFromPixel(
312                new OpenLayers.Pixel(position.left, position.bottom)
313            );
314            var maxXY = this.map.getLonLatFromPixel(
315                new OpenLayers.Pixel(position.right, position.top)
316            );
317            bounds = new OpenLayers.Bounds(
318                minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
319            );
320           
321        } else {
322            if(this.click) {
323                // box without extent - let the click handler take care of it
324                return;
325            }
326            bounds = this.pixelToBounds(position);
327        }
328        this.setModifiers(this.handlers.box.dragHandler.evt);
329        this.request(bounds);
330    },
331   
332    /**
333     * Method selectHover
334     * Callback from the handlers.hover set up when <hover> selection is on
335     *
336     * Parameters:
337     * evt {Object} - event object with an xy property
338     */
339    selectHover: function(evt) {
340        var bounds = this.pixelToBounds(evt.xy);
341        this.request(bounds, {single: true, hover: true});
342    },
343
344    /**
345     * Method: cancelHover
346     * Callback from the handlers.hover set up when <hover> selection is on
347     */
348    cancelHover: function() {
349        if (this.hoverResponse) {
350            this.protocol.abort(this.hoverResponse);
351            this.hoverResponse = null;
352
353            OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
354        }
355    },
356
357    /**
358     * Method: request
359     * Sends a GetFeature request to the WFS
360     *
361     * Parameters:
362     * bounds - {<OpenLayers.Bounds>} bounds for the request's BBOX filter
363     * options - {Object} additional options for this method.
364     *
365     * Supported options include:
366     * single - {Boolean} A single feature should be returned.
367     *     Note that this will be ignored if the protocol does not
368     *     return the geometries of the features.
369     * hover - {Boolean} Do the request for the hover handler.
370     */
371    request: function(bounds, options) {
372        options = options || {};
373        var filter = new OpenLayers.Filter.Spatial({
374            type: this.filterType, 
375            value: bounds
376        });
377       
378        // Set the cursor to "wait" to tell the user we're working.
379        OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
380
381        var response = this.protocol.read({
382            maxFeatures: options.single == true ? this.maxFeatures : undefined,
383            filter: filter,
384            callback: function(result) {
385                if(result.success()) {
386                    if(result.features.length) {
387                        if(options.single == true) {
388                            this.selectBestFeature(result.features,
389                                bounds.getCenterLonLat(), options);
390                        } else {
391                            this.select(result.features);
392                        }
393                    } else if(options.hover) {
394                        this.hoverSelect();
395                    } else {
396                        this.events.triggerEvent("clickout");
397                        if(this.clickout) {
398                            this.unselectAll();
399                        }
400                    }
401                }
402                // Reset the cursor.
403                OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
404            },
405            scope: this
406        });
407        if(options.hover == true) {
408            this.hoverResponse = response;
409        }
410    },
411
412    /**
413     * Method: selectBestFeature
414     * Selects the feature from an array of features that is the best match
415     *     for the click position.
416     *
417     * Parameters:
418     * features - {Array(<OpenLayers.Feature.Vector>)}
419     * clickPosition - {<OpenLayers.LonLat>}
420     * options - {Object} additional options for this method
421     *
422     * Supported options include:
423     * hover - {Boolean} Do the selection for the hover handler.
424     */
425    selectBestFeature: function(features, clickPosition, options) {
426        options = options || {};
427        if(features.length) {
428            var point = new OpenLayers.Geometry.Point(clickPosition.lon,
429                clickPosition.lat);
430            var feature, resultFeature, dist;
431            var minDist = Number.MAX_VALUE;
432            for(var i=0; i<features.length; ++i) {
433                feature = features[i];
434                if(feature.geometry) {
435                    dist = point.distanceTo(feature.geometry, {edge: false});
436                    if(dist < minDist) {
437                        minDist = dist;
438                        resultFeature = feature;
439                        if(minDist == 0) {
440                            break;
441                        }
442                    }
443                }
444            }
445           
446            if(options.hover == true) {
447                this.hoverSelect(resultFeature);
448            } else {
449                this.select(resultFeature || features);
450            } 
451        }
452    },
453   
454    /**
455     * Method: setModifiers
456     * Sets the multiple and toggle modifiers according to the current event
457     *
458     * Parameters:
459     * evt {<OpenLayers.Event>}
460     */
461    setModifiers: function(evt) {
462        this.modifiers = {
463            multiple: this.multiple || (this.multipleKey && evt[this.multipleKey]),
464            toggle: this.toggle || (this.toggleKey && evt[this.toggleKey])
465        };       
466    },
467
468    /**
469     * Method: select
470     * Add feature to the hash of selected features and trigger the
471     * featureselected and featuresselected events.
472     *
473     * Parameters:
474     * features - {<OpenLayers.Feature.Vector>} or an array of features
475     */
476    select: function(features) {
477        if(!this.modifiers.multiple && !this.modifiers.toggle) {
478            this.unselectAll();
479        }
480        if(!(features instanceof Array)) {
481            features = [features];
482        }
483       
484        var cont = this.events.triggerEvent("beforefeaturesselected", {
485            features: features
486        });
487        if(cont !== false) {
488            var selectedFeatures = [];
489            var feature;
490            for(var i=0, len=features.length; i<len; ++i) {
491                feature = features[i];
492                if(this.features[feature.fid || feature.id]) {
493                    if(this.modifiers.toggle) {
494                        this.unselect(this.features[feature.fid || feature.id]);
495                    }
496                } else {
497                    cont = this.events.triggerEvent("beforefeatureselected", {
498                        feature: feature
499                    });
500                    if(cont !== false) {
501                        this.features[feature.fid || feature.id] = feature;
502                        selectedFeatures.push(feature);
503               
504                        this.events.triggerEvent("featureselected",
505                            {feature: feature});
506                    }
507                }
508            }
509            this.events.triggerEvent("featuresselected", {
510                features: selectedFeatures
511            });
512        }
513    },
514   
515    /**
516     * Method: hoverSelect
517     * Sets/unsets the <hoverFeature>
518     *
519     * Parameters:
520     * feature - {<OpenLayers.Feature.Vector>} the feature to hover-select.
521     *     If none is provided, the current <hoverFeature> will be nulled and
522     *     the outfeature event will be triggered.
523     */
524    hoverSelect: function(feature) {
525        var fid = feature ? feature.fid || feature.id : null;
526        var hfid = this.hoverFeature ?
527            this.hoverFeature.fid || this.hoverFeature.id : null;
528           
529        if(hfid && hfid != fid) {
530            this.events.triggerEvent("outfeature",
531                {feature: this.hoverFeature});
532            this.hoverFeature = null;
533        }
534        if(fid && fid != hfid) {
535            this.events.triggerEvent("hoverfeature", {feature: feature});
536            this.hoverFeature = feature;
537        }
538    },
539
540    /**
541     * Method: unselect
542     * Remove feature from the hash of selected features and trigger the
543     * featureunselected event.
544     *
545     * Parameters:
546     * feature - {<OpenLayers.Feature.Vector>}
547     */
548    unselect: function(feature) {
549        delete this.features[feature.fid || feature.id];
550        this.events.triggerEvent("featureunselected", {feature: feature});
551    },
552   
553    /**
554     * Method: unselectAll
555     * Unselect all selected features.
556     */
557    unselectAll: function() {
558        // we'll want an option to supress notification here
559        for(var fid in this.features) {
560            this.unselect(this.features[fid]);
561        }
562    },
563   
564    /**
565     * Method: setMap
566     * Set the map property for the control.
567     *
568     * Parameters:
569     * map - {<OpenLayers.Map>}
570     */
571    setMap: function(map) {
572        for(var i in this.handlers) {
573            this.handlers[i].setMap(map);
574        }
575        OpenLayers.Control.prototype.setMap.apply(this, arguments);
576    },
577   
578    /**
579     * Method: pixelToBounds
580     * Takes a pixel as argument and creates bounds after adding the
581     * <clickTolerance>.
582     *
583     * Parameters:
584     * pixel - {<OpenLayers.Pixel>}
585     */
586    pixelToBounds: function(pixel) {
587        var llPx = pixel.add(-this.clickTolerance/2, this.clickTolerance/2);
588        var urPx = pixel.add(this.clickTolerance/2, -this.clickTolerance/2);
589        var ll = this.map.getLonLatFromPixel(llPx);
590        var ur = this.map.getLonLatFromPixel(urPx);
591        return new OpenLayers.Bounds(ll.lon, ll.lat, ur.lon, ur.lat);
592    },
593
594    CLASS_NAME: "OpenLayers.Control.GetFeature"
595});
Note: See TracBrowser for help on using the repository browser.