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. */
6 * @requires OpenLayers/Console.js
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
18 * The following example shows how to add many of the common controls
21 * > var map = new OpenLayers.Map('map', { controls: [] });
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());
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
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();
49 * > notice: function (bounds) {
50 * > OpenLayers.Console.userError(bounds);
53 * > map.addControl(control);
56 OpenLayers.Control = OpenLayers.Class({
66 * {<OpenLayers.Map>} this gets set in the addControl() function in
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.
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.
92 allowSelection: false,
95 * Property: displayClass
96 * {string} This property is used for CSS related to the drawing of the
103 * {string} This property is used for showing a tooltip over the
110 * {Boolean} The control is active.
116 * {<OpenLayers.Handler>} null
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.
127 eventListeners: null,
131 * {<OpenLayers.Events>} Events instance for triggering control specific
137 * Constant: EVENT_TYPES
138 * {Array(String)} Supported application event types. Register a listener
139 * for a particular event with the following syntax:
141 * control.events.register(type, obj, listener);
144 * Listeners will be called with a reference to an event object. The
145 * properties of this event depends on exactly what happened.
147 * All event objects have at least the following properties:
148 * object - {Object} A reference to control.events.object (a reference
150 * element - {DOMElement} A reference to control.events.element (which
151 * will be null unless documented otherwise).
153 * Supported map event types:
154 * activate - Triggered when activated.
155 * deactivate - Triggered when deactivated.
157 EVENT_TYPES: ["activate", "deactivate"],
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:
164 * > var control = new OpenLayers.Control({div: myDiv});
166 * Overrides the default div attribute value of null.
171 initialize: function (options) {
172 // We do this before the extend so that instances can override
173 // className in options.
175 this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
177 OpenLayers.Util.extend(this, options);
179 this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
180 if(this.eventListeners instanceof Object) {
181 this.events.on(this.eventListeners);
183 if (this.id == null) {
184 this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
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.
194 destroy: function () {
196 if(this.eventListeners) {
197 this.events.un(this.eventListeners);
199 this.events.destroy();
202 this.eventListeners = null;
204 // eliminate circular references
206 this.handler.destroy();
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();
216 this.handlers = null;
219 this.map.removeControl(this);
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.
231 * map - {<OpenLayers.Map>}
233 setMap: function(map) {
236 this.handler.setMap(map);
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.
248 * px - {<OpenLayers.Pixel>} The top-left pixel position of the control
252 * {DOMElement} A reference to the DIV DOMElement containing the control
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); };
263 if (this.title != "") {
264 this.div.title = this.title;
268 this.position = px.clone();
270 this.moveTo(this.position);
276 * Sets the left and top style attributes to the passed in pixel
280 * px - {<OpenLayers.Pixel>}
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";
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.
296 * {Boolean} True if the control was successfully activated or
297 * false if the control was already active.
299 activate: function () {
304 this.handler.activate();
308 OpenLayers.Element.addClass(
309 this.map.viewPortDiv,
310 this.displayClass.replace(/ /g, "") + "Active"
313 this.events.triggerEvent("activate");
319 * Deactivates a control and it's associated handler if any. The exact
320 * effect of this depends on the control itself.
323 * {Boolean} True if the control was effectively deactivated or false
324 * if the control was already inactive.
326 deactivate: function () {
329 this.handler.deactivate();
333 OpenLayers.Element.removeClass(
334 this.map.viewPortDiv,
335 this.displayClass.replace(/ /g, "") + "Active"
338 this.events.triggerEvent("deactivate");
344 CLASS_NAME: "OpenLayers.Control"
347 OpenLayers.Control.TYPE_BUTTON = 1;
348 OpenLayers.Control.TYPE_TOGGLE = 2;
349 OpenLayers.Control.TYPE_TOOL = 3;