More trip planner testing with colors
[busui.git] / labs / openlayers / lib / OpenLayers / Control / ScaleLine.js
blob:a/labs/openlayers/lib/OpenLayers/Control/ScaleLine.js -> blob:b/labs/openlayers/lib/OpenLayers/Control/ScaleLine.js
  /* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
  * full list of contributors). Published under the Clear BSD license.
  * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  * full text of the license. */
   
  /**
  * @requires OpenLayers/Control.js
  */
   
  /**
  * Class: OpenLayers.Control.ScaleLine
  * The ScaleLine displays a small line indicator representing the current
  * map scale on the map. By default it is drawn in the lower left corner of
  * the map.
  *
  * Inherits from:
  * - <OpenLayers.Control>
  *
  * Is a very close copy of:
  * - <OpenLayers.Control.Scale>
  */
  OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
   
  /**
  * Property: maxWidth
  * {Integer} Maximum width of the scale line in pixels. Default is 100.
  */
  maxWidth: 100,
   
  /**
  * Property: topOutUnits
  * {String} Units for zoomed out on top bar. Default is km.
  */
  topOutUnits: "km",
   
  /**
  * Property: topInUnits
  * {String} Units for zoomed in on top bar. Default is m.
  */
  topInUnits: "m",
   
  /**
  * Property: bottomOutUnits
  * {String} Units for zoomed out on bottom bar. Default is mi.
  */
  bottomOutUnits: "mi",
   
  /**
  * Property: bottomInUnits
  * {String} Units for zoomed in on bottom bar. Default is ft.
  */
  bottomInUnits: "ft",
   
  /**
  * Property: eTop
  * {DOMElement}
  */
  eTop: null,
   
  /**
  * Property: eBottom
  * {DOMElement}
  */
  eBottom:null,
   
  /**
  * APIProperty: geodesic
  * {Boolean} Use geodesic measurement. Default is false. The recommended
  * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to
  * true, the scale will be calculated based on the horizontal size of the
  * pixel in the center of the map viewport.
  */
  geodesic: false,
   
  /**
  * Constructor: OpenLayers.Control.ScaleLine
  * Create a new scale line control.
  *
  * Parameters:
  * options - {Object} An optional object whose properties will be used
  * to extend the control.
  */
  initialize: function(options) {
  OpenLayers.Control.prototype.initialize.apply(this, [options]);
  },
   
  /**
  * Method: draw
  *
  * Returns:
  * {DOMElement}
  */
  draw: function() {
  OpenLayers.Control.prototype.draw.apply(this, arguments);
  if (!this.eTop) {
  // stick in the top bar
  this.eTop = document.createElement("div");
  this.eTop.className = this.displayClass + "Top";
  var theLen = this.topInUnits.length;
  this.div.appendChild(this.eTop);
  if((this.topOutUnits == "") || (this.topInUnits == "")) {
  this.eTop.style.visibility = "hidden";
  } else {
  this.eTop.style.visibility = "visible";
  }
   
  // and the bottom bar
  this.eBottom = document.createElement("div");
  this.eBottom.className = this.displayClass + "Bottom";
  this.div.appendChild(this.eBottom);
  if((this.bottomOutUnits == "") || (this.bottomInUnits == "")) {
  this.eBottom.style.visibility = "hidden";
  } else {
  this.eBottom.style.visibility = "visible";
  }
  }
  this.map.events.register('moveend', this, this.update);
  this.update();
  return this.div;
  },
   
  /**
  * Method: getBarLen
  * Given a number, round it down to the nearest 1,2,5 times a power of 10.
  * That seems a fairly useful set of number groups to use.
  *
  * Parameters:
  * maxLen - {float} the number we're rounding down from
  *
  * Returns:
  * {Float} the rounded number (less than or equal to maxLen)
  */
  getBarLen: function(maxLen) {
  // nearest power of 10 lower than maxLen
  var digits = parseInt(Math.log(maxLen) / Math.log(10));
  var pow10 = Math.pow(10, digits);
   
  // ok, find first character
  var firstChar = parseInt(maxLen / pow10);
   
  // right, put it into the correct bracket
  var barLen;
  if(firstChar > 5) {
  barLen = 5;
  } else if(firstChar > 2) {
  barLen = 2;
  } else {
  barLen = 1;
  }
   
  // scale it up the correct power of 10
  return barLen * pow10;
  },
   
  /**
  * Method: update
  * Update the size of the bars, and the labels they contain.
  */
  update: function() {
  var res = this.map.getResolution();
  if (!res) {
  return;
  }
   
  var curMapUnits = this.map.getUnits();
  var inches = OpenLayers.INCHES_PER_UNIT;
   
  // convert maxWidth to map units
  var maxSizeData = this.maxWidth * res * inches[curMapUnits];
  var geodesicRatio = 1;
  if(this.geodesic === true) {
  var maxSizeGeodesic = (this.map.getGeodesicPixelSize().w ||
  0.000001) * this.maxWidth;
  var maxSizeKilometers = maxSizeData / inches["km"];
  geodesicRatio = maxSizeGeodesic / maxSizeKilometers;
  maxSizeData *= geodesicRatio;
  }
   
  // decide whether to use large or small scale units
  var topUnits;
  var bottomUnits;
  if(maxSizeData > 100000) {
  topUnits = this.topOutUnits;
  bottomUnits = this.bottomOutUnits;
  } else {
  topUnits = this.topInUnits;
  bottomUnits = this.bottomInUnits;
  }
   
  // and to map units units
  var topMax = maxSizeData / inches[topUnits];
  var bottomMax = maxSizeData / inches[bottomUnits];
   
  // now trim this down to useful block length
  var topRounded = this.getBarLen(topMax);
  var bottomRounded = this.getBarLen(bottomMax);
   
  // and back to display units
  topMax = topRounded / inches[curMapUnits] * inches[topUnits];
  bottomMax = bottomRounded / inches[curMapUnits] * inches[bottomUnits];
   
  // and to pixel units
  var topPx = topMax / res / geodesicRatio;
  var bottomPx = bottomMax / res / geodesicRatio;
   
  // now set the pixel widths
  // and the values inside them
   
  if (this.eBottom.style.visibility == "visible"){
  this.eBottom.style.width = Math.round(bottomPx) + "px";
  this.eBottom.innerHTML = bottomRounded + " " + bottomUnits ;
  }
   
  if (this.eTop.style.visibility == "visible"){
  this.eTop.style.width = Math.round(topPx) + "px";
  this.eTop.innerHTML = topRounded + " " + topUnits;
  }
   
  },
   
  CLASS_NAME: "OpenLayers.Control.ScaleLine"
  });