text: /* Copyright (c) 2006-2012 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/Control/PanZoom.js
   */
  
  /**
   * Class: OpenLayers.Control.PanZoomBar
   * The PanZoomBar is a visible control composed of a
   * <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomBar>. 
   * By default it is displayed in the upper left corner of the map as 4
   * directional arrows above a vertical slider.
   *
   * Inherits from:
   *  - <OpenLayers.Control.PanZoom>
   */
  OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
  
      /** 
       * APIProperty: zoomStopWidth
       */
      zoomStopWidth: 18,
  
      /** 
       * APIProperty: zoomStopHeight
       */
      zoomStopHeight: 11,
  
      /** 
       * Property: slider
       */
      slider: null,
  
      /** 
       * Property: sliderEvents
       * {<OpenLayers.Events>}
       */
      sliderEvents: null,
  
      /** 
       * Property: zoombarDiv
       * {DOMElement}
       */
      zoombarDiv: null,
  
      /** 
       * APIProperty: zoomWorldIcon
       * {Boolean}
       */
      zoomWorldIcon: false,
  
      /**
       * APIProperty: panIcons
       * {Boolean} Set this property to false not to display the pan icons. If
       * false the zoom world icon is placed under the zoom bar. Defaults to
       * true.
       */
      panIcons: true,
  
      /**
       * APIProperty: forceFixedZoomLevel
       * {Boolean} Force a fixed zoom level even though the map has 
       *     fractionalZoom
       */
      forceFixedZoomLevel: false,
  
      /**
       * Property: mouseDragStart
       * {<OpenLayers.Pixel>}
       */
      mouseDragStart: null,
  
      /**
       * Property: deltaY
       * {Number} The cumulative vertical pixel offset during a zoom bar drag.
       */
      deltaY: null,
  
      /**
       * Property: zoomStart
       * {<OpenLayers.Pixel>}
       */
      zoomStart: null,
  
      /**
       * Constructor: OpenLayers.Control.PanZoomBar
       */ 
  
      /**
       * APIMethod: destroy
       */
      destroy: function() {
  
          this._removeZoomBar();
  
          this.map.events.un({
              "changebaselayer": this.redraw,
              "updatesize": this.redraw,
              scope: this
          });
  
          OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
  
          delete this.mouseDragStart;
          delete this.zoomStart;
      },
      
      /**
       * Method: setMap
       * 
       * Parameters:
       * map - {<OpenLayers.Map>} 
       */
      setMap: function(map) {
          OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
          this.map.events.on({
              "changebaselayer": this.redraw,
              "updatesize": this.redraw,
              scope: this
          });
      },
  
      /** 
       * Method: redraw
       * clear the div and start over.
       */
      redraw: function() {
          if (this.div != null) {
              this.removeButtons();
              this._removeZoomBar();
          }  
          this.draw();
      },
      
      /**
      * Method: draw 
      *
      * Parameters:
      * px - {<OpenLayers.Pixel>} 
      */
      draw: function(px) {
          // initialize our internal div
          OpenLayers.Control.prototype.draw.apply(this, arguments);
          px = this.position.clone();
  
          // place the controls
          this.buttons = [];
  
          var sz = {w: 18, h: 18};
          if (this.panIcons) {
              var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
              var wposition = sz.w;
  
              if (this.zoomWorldIcon) {
                  centered = new OpenLayers.Pixel(px.x+sz.w, px.y);
              }
  
              this._addButton("panup", "north-mini.png", centered, sz);
              px.y = centered.y+sz.h;
              this._addButton("panleft", "west-mini.png", px, sz);
              if (this.zoomWorldIcon) {
                  this._addButton("zoomworld", "zoom-world-mini.png", px.add(sz.w, 0), sz);
  
                  wposition *= 2;
              }
              this._addButton("panright", "east-mini.png", px.add(wposition, 0), sz);
              this._addButton("pandown", "south-mini.png", centered.add(0, sz.h*2), sz);
              this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, sz.h*3+5), sz);
              centered = this._addZoomBar(centered.add(0, sz.h*4 + 5));
              this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
          }
          else {
              this._addButton("zoomin", "zoom-plus-mini.png", px, sz);
              centered = this._addZoomBar(px.add(0, sz.h));
              this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
              if (this.zoomWorldIcon) {
                  centered = centered.add(0, sz.h+3);
                  this._addButton("zoomworld", "zoom-world-mini.png", centered, sz);
              }
          }
          return this.div;
      },
  
      /** 
      * Method: _addZoomBar
      * 
      * Parameters:
      * centered - {<OpenLayers.Pixel>} where zoombar drawing is to start.
      */
      _addZoomBar:function(centered) {
          var imgLocation = OpenLayers.Util.getImageLocation("slider.png");
          var id = this.id + "_" + this.map.id;
          var minZoom = this.map.getMinZoom();
          var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
          var slider = OpenLayers.Util.createAlphaImageDiv(id,
                         centered.add(-1, zoomsToEnd * this.zoomStopHeight), 
                         {w: 20, h: 9},
                         imgLocation,
                         "absolute");
          slider.style.cursor = "move";
          this.slider = slider;
          
          this.sliderEvents = new OpenLayers.Events(this, slider, null, true,
                                              {includeXY: true});
          this.sliderEvents.on({
              "touchstart": this.zoomBarDown,
              "touchmove": this.zoomBarDrag,
              "touchend": this.zoomBarUp,
              "mousedown": this.zoomBarDown,
              "mousemove": this.zoomBarDrag,
              "mouseup": this.zoomBarUp
          });
          
          var sz = {
              w: this.zoomStopWidth,
              h: this.zoomStopHeight * (this.map.getNumZoomLevels() - minZoom)
          };
          var imgLocation = OpenLayers.Util.getImageLocation("zoombar.png");
          var div = null;
          
          if (OpenLayers.Util.alphaHack()) {
              var id = this.id + "_" + this.map.id;
              div = OpenLayers.Util.createAlphaImageDiv(id, centered,
                                        {w: sz.w, h: this.zoomStopHeight},
                                        imgLocation,
                                        "absolute", null, "crop");
              div.style.height = sz.h + "px";
          } else {
              div = OpenLayers.Util.createDiv(
                          'OpenLayers_Control_PanZoomBar_Zoombar' + this.map.id,
                          centered,
                          sz,
                          imgLocation);
          }
          div.style.cursor = "pointer";
          div.className = "olButton";
          this.zoombarDiv = div;
          
          this.div.appendChild(div);
  
          this.startTop = parseInt(div.style.top);
          this.div.appendChild(slider);
  
          this.map.events.register("zoomend", this, this.moveZoomBar);
  
          centered = centered.add(0, 
              this.zoomStopHeight * (this.map.getNumZoomLevels() - minZoom));
          return centered; 
      },
      
      /**
       * Method: _removeZoomBar
       */
      _removeZoomBar: function() {
          this.sliderEvents.un({
              "touchstart": this.zoomBarDown,
              "touchmove": this.zoomBarDrag,
              "touchend": this.zoomBarUp,
              "mousedown": this.zoomBarDown,
              "mousemove": this.zoomBarDrag,
              "mouseup": this.zoomBarUp
          });
          this.sliderEvents.destroy();
          
          this.div.removeChild(this.zoombarDiv);
          this.zoombarDiv = null;
          this.div.removeChild(this.slider);
          this.slider = null;
          
          this.map.events.unregister("zoomend", this, this.moveZoomBar);
      },
      
      /**
       * Method: onButtonClick
       *
       * Parameters:
       * evt - {Event}
       */
      onButtonClick: function(evt) {
          OpenLayers.Control.PanZoom.prototype.onButtonClick.apply(this, arguments);
          if (evt.buttonElement === this.zoombarDiv) {
              var levels = evt.buttonXY.y / this.zoomStopHeight;
              if(this.forceFixedZoomLevel || !this.map.fractionalZoom) {
                  levels = Math.floor(levels);
              }    
              var zoom = (this.map.getNumZoomLevels() - 1) - levels; 
              zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1);
              this.map.zoomTo(zoom);
          }
      },
      
      /**
       * Method: passEventToSlider
       * This function is used to pass events that happen on the div, or the map,
       * through to the slider, which then does its moving thing.
       *
       * Parameters:
       * evt - {<OpenLayers.Event>} 
       */
      passEventToSlider:function(evt) {
          this.sliderEvents.handleBrowserEvent(evt);
      },
      
      /*
       * Method: zoomBarDown
       * event listener for clicks on the slider
       *
       * Parameters:
       * evt - {<OpenLayers.Event>} 
       */
      zoomBarDown:function(evt) {
          if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) {
              return;
          }
          this.map.events.on({
              "touchmove": this.passEventToSlider,
              "mousemove": this.passEventToSlider,
              "mouseup": this.passEventToSlider,
              scope: this
          });
          this.mouseDragStart = evt.xy.clone();
          this.zoomStart = evt.xy.clone();
          this.div.style.cursor = "move";
          // reset the div offsets just in case the div moved
          this.zoombarDiv.offsets = null; 
          OpenLayers.Event.stop(evt);
      },
      
      /*
       * Method: zoomBarDrag
       * This is what happens when a click has occurred, and the client is
       * dragging.  Here we must ensure that the slider doesn't go beyond the
       * bottom/top of the zoombar div, as well as moving the slider to its new
       * visual location
       *
       * Parameters:
       * evt - {<OpenLayers.Event>} 
       */
      zoomBarDrag:function(evt) {
          if (this.mouseDragStart != null) {
              var deltaY = this.mouseDragStart.y - evt.xy.y;
              var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv);
              if ((evt.clientY - offsets[1]) > 0 && 
                  (evt.clientY - offsets[1]) < parseInt(this.zoombarDiv.style.height) - 2) {
                  var newTop = parseInt(this.slider.style.top) - deltaY;
                  this.slider.style.top = newTop+"px";
                  this.mouseDragStart = evt.xy.clone();
              }
              // set cumulative displacement
              this.deltaY = this.zoomStart.y - evt.xy.y;
              OpenLayers.Event.stop(evt);
          }
      },
      
      /*
       * Method: zoomBarUp
       * Perform cleanup when a mouseup event is received -- discover new zoom
       * level and switch to it.
       *
       * Parameters:
       * evt - {<OpenLayers.Event>} 
       */
      zoomBarUp:function(evt) {
          if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") {
              return;
          }
          if (this.mouseDragStart) {
              this.div.style.cursor="";
              this.map.events.un({
                  "touchmove": this.passEventToSlider,
                  "mouseup": this.passEventToSlider,
                  "mousemove": this.passEventToSlider,
                  scope: this
              });
              var zoomLevel = this.map.zoom;
              if (!this.forceFixedZoomLevel && this.map.fractionalZoom) {
                  zoomLevel += this.deltaY/this.zoomStopHeight;
                  zoomLevel = Math.min(Math.max(zoomLevel, 0), 
                                       this.map.getNumZoomLevels() - 1);
              } else {
                  zoomLevel += this.deltaY/this.zoomStopHeight;
                  zoomLevel = Math.max(Math.round(zoomLevel), 0);      
              }
              this.map.zoomTo(zoomLevel);
              this.mouseDragStart = null;
              this.zoomStart = null;
              this.deltaY = 0;
              OpenLayers.Event.stop(evt);
          }
      },
      
      /*
      * Method: moveZoomBar
      * Change the location of the slider to match the current zoom level.
      */
      moveZoomBar:function() {
          var newTop = 
              ((this.map.getNumZoomLevels()-1) - this.map.getZoom()) * 
              this.zoomStopHeight + this.startTop + 1;
          this.slider.style.top = newTop + "px";
      },    
      
      CLASS_NAME: "OpenLayers.Control.PanZoomBar"
  });