text: /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
   * full list of contributors). Published under the 2-clause BSD license.
   * See license.txt in the OpenLayers distribution or repository for the
   * full text of the license. */
  
  /**
   * @requires OpenLayers/BaseTypes/Class.js
   */
  
  /**
   * Class: OpenLayers.Control
   * Controls affect the display or behavior of the map. They allow everything
   * from panning and zooming to displaying a scale indicator. Controls by
   * default are added to the map they are contained within however it is
   * possible to add a control to an external div by passing the div in the
   * options parameter.
   *
   * Example:
   * The following example shows how to add many of the common controls
   * to a map.
   *
   * > var map = new OpenLayers.Map('map', { controls: [] });
   * >
   * > map.addControl(new OpenLayers.Control.PanZoomBar());
   * > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
   * > map.addControl(new OpenLayers.Control.Permalink());
   * > map.addControl(new OpenLayers.Control.Permalink('permalink'));
   * > map.addControl(new OpenLayers.Control.MousePosition());
   * > map.addControl(new OpenLayers.Control.OverviewMap());
   * > map.addControl(new OpenLayers.Control.KeyboardDefaults());
   *
   * The next code fragment is a quick example of how to intercept
   * shift-mouse click to display the extent of the bounding box
   * dragged out by the user.  Usually controls are not created
   * in exactly this manner.  See the source for a more complete
   * example:
   *
   * > var control = new OpenLayers.Control();
   * > OpenLayers.Util.extend(control, {
   * >     draw: function () {
   * >         // this Handler.Box will intercept the shift-mousedown
   * >         // before Control.MouseDefault gets to see it
   * >         this.box = new OpenLayers.Handler.Box( control, 
   * >             {"done": this.notice},
   * >             {keyMask: OpenLayers.Handler.MOD_SHIFT});
   * >         this.box.activate();
   * >     },
   * >
   * >     notice: function (bounds) {
   * >         OpenLayers.Console.userError(bounds);
   * >     }
   * > });
   * > map.addControl(control);
   *
   */
  OpenLayers.Control = OpenLayers.Class({
  
      /**
       * Property: id
       * {String}
       */
      id: null,
  
      /**
       * Property: map
       * {<OpenLayers.Map>} this gets set in the addControl() function in
       * OpenLayers.Map
       */
      map: null,
  
      /**
       * APIProperty: div
       * {DOMElement} The element that contains the control, if not present the
       *     control is placed inside the map.
       */
      div: null,
  
      /**
       * APIProperty: type
       * {Number} Controls can have a 'type'. The type determines the type of
       * interactions which are possible with them when they are placed in an
       * <OpenLayers.Control.Panel>.
       */
      type: null,
  
      /**
       * Property: allowSelection
       * {Boolean} By default, controls do not allow selection, because
       * it may interfere with map dragging. If this is true, OpenLayers
       * will not prevent selection of the control.
       * Default is false.
       */
      allowSelection: false,
  
      /**
       * Property: displayClass
       * {string}  This property is used for CSS related to the drawing of the
       * Control.
       */
      displayClass: "",
  
      /**
       * APIProperty: title
       * {string}  This property is used for showing a tooltip over the
       * Control.
       */
      title: "",
  
      /**
       * APIProperty: autoActivate
       * {Boolean} Activate the control when it is added to a map.  Default is
       *     false.
       */
      autoActivate: false,
  
      /**
       * APIProperty: active
       * {Boolean} The control is active (read-only).  Use <activate> and
       *     <deactivate> to change control state.
       */
      active: null,
  
      /**
       * Property: handlerOptions
       * {Object} Used to set non-default properties on the control's handler
       */
      handlerOptions: null,
  
      /**
       * Property: handler
       * {<OpenLayers.Handler>} null
       */
      handler: null,
  
      /**
       * APIProperty: eventListeners
       * {Object} If set as an option at construction, the eventListeners
       *     object will be registered with <OpenLayers.Events.on>.  Object
       *     structure must be a listeners object as shown in the example for
       *     the events.on method.
       */
      eventListeners: null,
  
      /**
       * APIProperty: events
       * {<OpenLayers.Events>} Events instance for listeners and triggering
       *     control specific events.
       *
       * Register a listener for a particular event with the following syntax:
       * (code)
       * control.events.register(type, obj, listener);
       * (end)
       *
       * Listeners will be called with a reference to an event object.  The
       *     properties of this event depends on exactly what happened.
       *
       * All event objects have at least the following properties:
       * object - {Object} A reference to control.events.object (a reference
       *      to the control).
       * element - {DOMElement} A reference to control.events.element (which
       *      will be null unless documented otherwise).
       *
       * Supported map event types:
       * activate - Triggered when activated.
       * deactivate - Triggered when deactivated.
       */
      events: null,
  
      /**
       * Constructor: OpenLayers.Control
       * Create an OpenLayers Control.  The options passed as a parameter
       * directly extend the control.  For example passing the following:
       *
       * > var control = new OpenLayers.Control({div: myDiv});
       *
       * Overrides the default div attribute value of null.
       *
       * Parameters:
       * options - {Object}
       */
      initialize: function (options) {
          // We do this before the extend so that instances can override
          // className in options.
          this.displayClass =
              this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
  
          OpenLayers.Util.extend(this, options);
  
          this.events = new OpenLayers.Events(this);
          if (this.eventListeners instanceof Object) {
              this.events.on(this.eventListeners);
          }
          if (this.id == null) {
              this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
          }
      },
  
      /**
       * Method: destroy
       * The destroy method is used to perform any clean up before the control
       * is dereferenced.  Typically this is where event listeners are removed
       * to prevent memory leaks.
       */
      destroy: function () {
          if (this.events) {
              if (this.eventListeners) {
                  this.events.un(this.eventListeners);
              }
              this.events.destroy();
              this.events = null;
          }
          this.eventListeners = null;
  
          // eliminate circular references
          if (this.handler) {
              this.handler.destroy();
              this.handler = null;
          }
          if (this.handlers) {
              for (var key in this.handlers) {
                  if (this.handlers.hasOwnProperty(key) &&
                      typeof this.handlers[key].destroy == "function") {
                      this.handlers[key].destroy();
                  }
              }
              this.handlers = null;
          }
          if (this.map) {
              this.map.removeControl(this);
              this.map = null;
          }
          this.div = null;
      },
  
      /**
       * Method: setMap
       * Set the map property for the control. This is done through an accessor
       * so that subclasses can override this and take special action once
       * they have their map variable set.
       *
       * Parameters:
       * map - {<OpenLayers.Map>}
       */
      setMap: function (map) {
          this.map = map;
          if (this.handler) {
              this.handler.setMap(map);
          }
      },
  
      /**
       * Method: draw
       * The draw method is called when the control is ready to be displayed
       * on the page.  If a div has not been created one is created.  Controls
       * with a visual component will almost always want to override this method
       * to customize the look of control.
       *
       * Parameters:
       * px - {<OpenLayers.Pixel>} The top-left pixel position of the control
       *      or null.
       *
       * Returns:
       * {DOMElement} A reference to the DIV DOMElement containing the control
       */
      draw: function (px) {
          if (this.div == null) {
              this.div = OpenLayers.Util.createDiv(this.id);
              this.div.className = this.displayClass;
              if (!this.allowSelection) {
                  this.div.className += " olControlNoSelect";
                  this.div.setAttribute("unselectable", "on", 0);
                  this.div.onselectstart = OpenLayers.Function.False;
              }
              if (this.title != "") {
                  this.div.title = this.title;
              }
          }
          if (px != null) {
              this.position = px.clone();
          }
          this.moveTo(this.position);
          return this.div;
      },
  
      /**
       * Method: moveTo
       * Sets the left and top style attributes to the passed in pixel
       * coordinates.
       *
       * Parameters:
       * px - {<OpenLayers.Pixel>}
       */
      moveTo: function (px) {
          if ((px != null) && (this.div != null)) {
              this.div.style.left = px.x + "px";
              this.div.style.top = px.y + "px";
          }
      },
  
      /**
       * APIMethod: activate
       * Explicitly activates a control and it's associated
       * handler if one has been set.  Controls can be
       * deactivated by calling the deactivate() method.
       *
       * Returns:
       * {Boolean}  True if the control was successfully activated or
       *            false if the control was already active.
       */
      activate: function () {
          if (this.active) {
              return false;
          }
          if (this.handler) {
              this.handler.activate();
          }
          this.active = true;
          if (this.map) {
              OpenLayers.Element.addClass(
                  this.map.viewPortDiv,
                  this.displayClass.replace(/ /g, "") + "Active"
              );
          }
          this.events.triggerEvent("activate");
          return true;
      },
  
      /**
       * APIMethod: deactivate
       * Deactivates a control and it's associated handler if any.  The exact
       * effect of this depends on the control itself.
       *
       * Returns:
       * {Boolean} True if the control was effectively deactivated or false
       *           if the control was already inactive.
       */
      deactivate: function () {
          if (this.active) {
              if (this.handler) {
                  this.handler.deactivate();
              }
              this.active = false;
              if (this.map) {
                  OpenLayers.Element.removeClass(
                      this.map.viewPortDiv,
                      this.displayClass.replace(/ /g, "") + "Active"
                  );
              }
              this.events.triggerEvent("deactivate");
              return true;
          }
          return false;
      },
  
      CLASS_NAME: "OpenLayers.Control"
  });
  
  /**
   * Constant: OpenLayers.Control.TYPE_BUTTON
   */
  OpenLayers.Control.TYPE_BUTTON = 1;
  
  /**
   * Constant: OpenLayers.Control.TYPE_TOGGLE
   */
  OpenLayers.Control.TYPE_TOGGLE = 2;
  
  /**
   * Constant: OpenLayers.Control.TYPE_TOOL
   */
  OpenLayers.Control.TYPE_TOOL = 3;
  