]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Control.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Control.js
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  * @requires OpenLayers/Console.js
7  */
8
9 /**
10  * Class: OpenLayers.Control
11  * Controls affect the display or behavior of the map. They allow everything
12  * from panning and zooming to displaying a scale indicator. Controls by 
13  * default are added to the map they are contained within however it is
14  * possible to add a control to an external div by passing the div in the
15  * options parameter.
16  * 
17  * Example:
18  * The following example shows how to add many of the common controls
19  * to a map.
20  * 
21  * > var map = new OpenLayers.Map('map', { controls: [] });
22  * >
23  * > map.addControl(new OpenLayers.Control.PanZoomBar());
24  * > map.addControl(new OpenLayers.Control.MouseToolbar());
25  * > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
26  * > map.addControl(new OpenLayers.Control.Permalink());
27  * > map.addControl(new OpenLayers.Control.Permalink('permalink'));
28  * > map.addControl(new OpenLayers.Control.MousePosition());
29  * > map.addControl(new OpenLayers.Control.OverviewMap());
30  * > map.addControl(new OpenLayers.Control.KeyboardDefaults());
31  *
32  * The next code fragment is a quick example of how to intercept 
33  * shift-mouse click to display the extent of the bounding box
34  * dragged out by the user.  Usually controls are not created
35  * in exactly this manner.  See the source for a more complete 
36  * example:
37  *
38  * > var control = new OpenLayers.Control();
39  * > OpenLayers.Util.extend(control, {
40  * >     draw: function () {
41  * >         // this Handler.Box will intercept the shift-mousedown
42  * >         // before Control.MouseDefault gets to see it
43  * >         this.box = new OpenLayers.Handler.Box( control, 
44  * >             {"done": this.notice},
45  * >             {keyMask: OpenLayers.Handler.MOD_SHIFT});
46  * >         this.box.activate();
47  * >     },
48  * >
49  * >     notice: function (bounds) {
50  * >         OpenLayers.Console.userError(bounds);
51  * >     }
52  * > }); 
53  * > map.addControl(control);
54  * 
55  */
56 OpenLayers.Control = OpenLayers.Class({
57
58     /** 
59      * Property: id 
60      * {String} 
61      */
62     id: null,
63     
64     /** 
65      * Property: map 
66      * {<OpenLayers.Map>} this gets set in the addControl() function in
67      * OpenLayers.Map 
68      */
69     map: null,
70
71     /** 
72      * Property: div 
73      * {DOMElement} 
74      */
75     div: null,
76
77     /** 
78      * Property: type 
79      * {OpenLayers.Control.TYPES} Controls can have a 'type'. The type
80      * determines the type of interactions which are possible with them when
81      * they are placed into a toolbar. 
82      */
83     type: null, 
84
85     /** 
86      * Property: allowSelection
87      * {Boolean} By deafault, controls do not allow selection, because
88      * it may interfere with map dragging. If this is true, OpenLayers
89      * will not prevent selection of the control.
90      * Default is false.
91      */
92     allowSelection: false,  
93
94     /** 
95      * Property: displayClass 
96      * {string}  This property is used for CSS related to the drawing of the
97      * Control. 
98      */
99     displayClass: "",
100     
101     /**
102     * Property: title  
103     * {string}  This property is used for showing a tooltip over the  
104     * Control.  
105     */ 
106     title: "",
107
108     /** 
109      * Property: active 
110      * {Boolean} The control is active.
111      */
112     active: null,
113
114     /** 
115      * Property: handler 
116      * {<OpenLayers.Handler>} null
117      */
118     handler: null,
119
120     /**
121      * APIProperty: eventListeners
122      * {Object} If set as an option at construction, the eventListeners
123      *     object will be registered with <OpenLayers.Events.on>.  Object
124      *     structure must be a listeners object as shown in the example for
125      *     the events.on method.
126      */
127     eventListeners: null,
128
129     /** 
130      * Property: events
131      * {<OpenLayers.Events>} Events instance for triggering control specific
132      *     events.
133      */
134     events: null,
135
136     /**
137      * Constant: EVENT_TYPES
138      * {Array(String)} Supported application event types.  Register a listener
139      *     for a particular event with the following syntax:
140      * (code)
141      * control.events.register(type, obj, listener);
142      * (end)
143      *
144      * Listeners will be called with a reference to an event object.  The
145      *     properties of this event depends on exactly what happened.
146      *
147      * All event objects have at least the following properties:
148      * object - {Object} A reference to control.events.object (a reference
149      *      to the control).
150      * element - {DOMElement} A reference to control.events.element (which
151      *      will be null unless documented otherwise).
152      *
153      * Supported map event types:
154      * activate - Triggered when activated.
155      * deactivate - Triggered when deactivated.
156      */
157     EVENT_TYPES: ["activate", "deactivate"],
158
159     /**
160      * Constructor: OpenLayers.Control
161      * Create an OpenLayers Control.  The options passed as a parameter
162      * directly extend the control.  For example passing the following:
163      * 
164      * > var control = new OpenLayers.Control({div: myDiv});
165      *
166      * Overrides the default div attribute value of null.
167      * 
168      * Parameters:
169      * options - {Object} 
170      */
171     initialize: function (options) {
172         // We do this before the extend so that instances can override
173         // className in options.
174         this.displayClass = 
175             this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
176         
177         OpenLayers.Util.extend(this, options);
178         
179         this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
180         if(this.eventListeners instanceof Object) {
181             this.events.on(this.eventListeners);
182         }
183         if (this.id == null) {
184             this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
185         }
186     },
187
188     /**
189      * Method: destroy
190      * The destroy method is used to perform any clean up before the control
191      * is dereferenced.  Typically this is where event listeners are removed
192      * to prevent memory leaks.
193      */
194     destroy: function () {
195         if(this.events) {
196             if(this.eventListeners) {
197                 this.events.un(this.eventListeners);
198             }
199             this.events.destroy();
200             this.events = null;
201         }
202         this.eventListeners = null;
203
204         // eliminate circular references
205         if (this.handler) {
206             this.handler.destroy();
207             this.handler = null;
208         }
209         if(this.handlers) {
210             for(var key in this.handlers) {
211                 if(this.handlers.hasOwnProperty(key) &&
212                    typeof this.handlers[key].destroy == "function") {
213                     this.handlers[key].destroy();
214                 }
215             }
216             this.handlers = null;
217         }
218         if (this.map) {
219             this.map.removeControl(this);
220             this.map = null;
221         }
222     },
223
224     /** 
225      * Method: setMap
226      * Set the map property for the control. This is done through an accessor
227      * so that subclasses can override this and take special action once 
228      * they have their map variable set. 
229      *
230      * Parameters:
231      * map - {<OpenLayers.Map>} 
232      */
233     setMap: function(map) {
234         this.map = map;
235         if (this.handler) {
236             this.handler.setMap(map);
237         }
238     },
239   
240     /**
241      * Method: draw
242      * The draw method is called when the control is ready to be displayed
243      * on the page.  If a div has not been created one is created.  Controls
244      * with a visual component will almost always want to override this method 
245      * to customize the look of control. 
246      *
247      * Parameters:
248      * px - {<OpenLayers.Pixel>} The top-left pixel position of the control
249      *      or null.
250      *
251      * Returns:
252      * {DOMElement} A reference to the DIV DOMElement containing the control
253      */
254     draw: function (px) {
255         if (this.div == null) {
256             this.div = OpenLayers.Util.createDiv(this.id);
257             this.div.className = this.displayClass;
258             if (!this.allowSelection) {
259                 this.div.className += " olControlNoSelect";
260                 this.div.setAttribute("unselectable", "on", 0);
261                 this.div.onselectstart = function() { return(false); }; 
262             }    
263             if (this.title != "") {
264                 this.div.title = this.title;
265             }
266         }
267         if (px != null) {
268             this.position = px.clone();
269         }
270         this.moveTo(this.position);
271         return this.div;
272     },
273
274     /**
275      * Method: moveTo
276      * Sets the left and top style attributes to the passed in pixel 
277      * coordinates.
278      *
279      * Parameters:
280      * px - {<OpenLayers.Pixel>}
281      */
282     moveTo: function (px) {
283         if ((px != null) && (this.div != null)) {
284             this.div.style.left = px.x + "px";
285             this.div.style.top = px.y + "px";
286         }
287     },
288
289     /**
290      * Method: activate
291      * Explicitly activates a control and it's associated
292      * handler if one has been set.  Controls can be
293      * deactivated by calling the deactivate() method.
294      * 
295      * Returns:
296      * {Boolean}  True if the control was successfully activated or
297      *            false if the control was already active.
298      */
299     activate: function () {
300         if (this.active) {
301             return false;
302         }
303         if (this.handler) {
304             this.handler.activate();
305         }
306         this.active = true;
307         if(this.map) {
308             OpenLayers.Element.addClass(
309                 this.map.viewPortDiv,
310                 this.displayClass.replace(/ /g, "") + "Active"
311             );
312         }
313         this.events.triggerEvent("activate");
314         return true;
315     },
316     
317     /**
318      * Method: deactivate
319      * Deactivates a control and it's associated handler if any.  The exact
320      * effect of this depends on the control itself.
321      * 
322      * Returns:
323      * {Boolean} True if the control was effectively deactivated or false
324      *           if the control was already inactive.
325      */
326     deactivate: function () {
327         if (this.active) {
328             if (this.handler) {
329                 this.handler.deactivate();
330             }
331             this.active = false;
332             if(this.map) {
333                 OpenLayers.Element.removeClass(
334                     this.map.viewPortDiv,
335                     this.displayClass.replace(/ /g, "") + "Active"
336                 );
337             }
338             this.events.triggerEvent("deactivate");
339             return true;
340         }
341         return false;
342     },
343
344     CLASS_NAME: "OpenLayers.Control"
345 });
346
347 OpenLayers.Control.TYPE_BUTTON = 1;
348 OpenLayers.Control.TYPE_TOGGLE = 2;
349 OpenLayers.Control.TYPE_TOOL   = 3;