More trip planner testing with colors
[busui.git] / labs / openlayers / lib / OpenLayers / Layer / Google / v3.js
blob:a/labs/openlayers/lib/OpenLayers/Layer/Google/v3.js -> blob:b/labs/openlayers/lib/OpenLayers/Layer/Google/v3.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/Layer/Google.js
  */
   
  /**
  * Constant: OpenLayers.Layer.Google.v3
  *
  * Mixin providing functionality specific to the Google Maps API v3. Note that
  * this layer configures the google.maps.map object with the "disableDefaultUI"
  * option set to true. Using UI controls that the Google Maps API provides is
  * not supported by the OpenLayers API.
  */
  OpenLayers.Layer.Google.v3 = {
   
  /**
  * Constant: DEFAULTS
  * {Object} It is not recommended to change the properties set here. Note
  * that Google.v3 layers only work when sphericalMercator is set to true.
  *
  * (code)
  * {
  * maxExtent: new OpenLayers.Bounds(
  * -128 * 156543.0339,
  * -128 * 156543.0339,
  * 128 * 156543.0339,
  * 128 * 156543.0339
  * ),
  * sphericalMercator: true,
  * maxResolution: 156543.0339,
  * units: "m",
  * projection: "EPSG:900913"
  * }
  * (end)
  */
  DEFAULTS: {
  maxExtent: new OpenLayers.Bounds(
  -128 * 156543.0339,
  -128 * 156543.0339,
  128 * 156543.0339,
  128 * 156543.0339
  ),
  sphericalMercator: true,
  maxResolution: 156543.0339,
  units: "m",
  projection: "EPSG:900913"
  },
   
  /**
  * Method: loadMapObject
  * Load the GMap and register appropriate event listeners. If we can't
  * load GMap2, then display a warning message.
  */
  loadMapObject:function() {
  if (!this.type) {
  this.type = google.maps.MapTypeId.ROADMAP;
  }
  var mapObject;
  var cache = OpenLayers.Layer.Google.cache[this.map.id];
  if (cache) {
  // there are already Google layers added to this map
  mapObject = cache.mapObject;
  // increment the layer count
  ++cache.count;
  } else {
  // this is the first Google layer for this map
   
  var container = this.map.viewPortDiv;
  var div = document.createElement("div");
  div.id = this.map.id + "_GMapContainer";
  div.style.position = "absolute";
  div.style.width = "100%";
  div.style.height = "100%";
  container.appendChild(div);
   
  // create GMap and shuffle elements
  var center = this.map.getCenter();
  mapObject = new google.maps.Map(div, {
  center: center ?
  new google.maps.LatLng(center.lat, center.lon) :
  new google.maps.LatLng(0, 0),
  zoom: this.map.getZoom() || 0,
  mapTypeId: this.type,
  disableDefaultUI: true,
  keyboardShortcuts: false,
  draggable: false,
  disableDoubleClickZoom: true,
  scrollwheel: false
  });
   
  // cache elements for use by any other google layers added to
  // this same map
  cache = {
  mapObject: mapObject,
  count: 1
  };
  OpenLayers.Layer.Google.cache[this.map.id] = cache;
  this.repositionListener = google.maps.event.addListenerOnce(
  mapObject,
  "center_changed",
  OpenLayers.Function.bind(this.repositionMapElements, this)
  );
  }
  this.mapObject = mapObject;
  this.setGMapVisibility(this.visibility);
  },
   
  /**
  * Method: repositionMapElements
  *
  * Waits until powered by and terms of use elements are available and then
  * moves them so they are clickable.
  */
  repositionMapElements: function() {
   
  // This is the first time any Google layer in this mapObject has been
  // made visible. The mapObject needs to know the container size.
  google.maps.event.trigger(this.mapObject, "resize");
   
  var div = this.mapObject.getDiv().firstChild;
  if (!div || div.childNodes.length < 3) {
  this.repositionTimer = window.setTimeout(
  OpenLayers.Function.bind(this.repositionMapElements, this),
  250
  );
  return false;
  }
   
  var cache = OpenLayers.Layer.Google.cache[this.map.id];
  var container = this.map.viewPortDiv;
   
  // move the ToS and branding stuff up to the container div
  var termsOfUse = div.lastChild;
  container.appendChild(termsOfUse);
  termsOfUse.style.zIndex = "1100";
  termsOfUse.style.bottom = "";
  termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3";
  termsOfUse.style.display = "";
  cache.termsOfUse = termsOfUse;
   
  var poweredBy = div.lastChild;
  container.appendChild(poweredBy);
  poweredBy.style.zIndex = "1100";
  poweredBy.style.bottom = "";
  poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";
  poweredBy.style.display = "";
  cache.poweredBy = poweredBy;
   
  this.setGMapVisibility(this.visibility);
   
  },
   
  /**
  * APIMethod: onMapResize
  */
  onMapResize: function() {
  if (this.visibility) {
  google.maps.event.trigger(this.mapObject, "resize");
  } else {
  if (!this._resized) {
  var layer = this;
  google.maps.event.addListenerOnce(this.mapObject, "tilesloaded", function() {
  delete layer._resized;
  google.maps.event.trigger(layer.mapObject, "resize");
  layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
  });
  }
  this._resized = true;
  }
  },
   
  /**
  * Method: setGMapVisibility
  * Display the GMap container and associated elements.
  *
  * Parameters:
  * visible - {Boolean} Display the GMap elements.
  */
  setGMapVisibility: function(visible) {
  var cache = OpenLayers.Layer.Google.cache[this.map.id];
  if (cache) {
  var type = this.type;
  var layers = this.map.layers;
  var layer;
  for (var i=layers.length-1; i>=0; --i) {
  layer = layers[i];
  if (layer instanceof OpenLayers.Layer.Google &&
  layer.visibility === true && layer.inRange === true) {
  type = layer.type;
  visible = true;
  break;
  }
  }
  var container = this.mapObject.getDiv();
  if (visible === true) {
  this.mapObject.setMapTypeId(type);
  container.style.left = "";
  if (cache.termsOfUse && cache.termsOfUse.style) {
  cache.termsOfUse.style.left = "";
  cache.termsOfUse.style.display = "";
  cache.poweredBy.style.display = "";
  }
  cache.displayed = this.id;
  } else {
  delete cache.displayed;
  container.style.left = "-9999px";
  if (cache.termsOfUse && cache.termsOfUse.style) {
  cache.termsOfUse.style.display = "none";
  // move ToU far to the left in addition to setting
  // display to "none", because at the end of the GMap
  // load sequence, display: none will be unset and ToU
  // would be visible after loading a map with a google
  // layer that is initially hidden.
  cache.termsOfUse.style.left = "-9999px";
  cache.poweredBy.style.display = "none";
  }
  }
  }
  },
   
  /**
  * Method: getMapContainer
  *
  * Returns:
  * {DOMElement} the GMap container's div
  */
  getMapContainer: function() {
  return this.mapObject.getDiv();
  },
   
  //
  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
  //
   
  /**
  * APIMethod: getMapObjectBoundsFromOLBounds
  *
  * Parameters:
  * olBounds - {<OpenLayers.Bounds>}
  *
  * Returns:
  * {Object} A MapObject Bounds, translated from olBounds
  * Returns null if null value is passed in
  */
  getMapObjectBoundsFromOLBounds: function(olBounds) {
  var moBounds = null;
  if (olBounds != null) {
  var sw = this.sphericalMercator ?
  this.inverseMercator(olBounds.bottom, olBounds.left) :
  new OpenLayers.LonLat(olBounds.bottom, olBounds.left);
  var ne = this.sphericalMercator ?
  this.inverseMercator(olBounds.top, olBounds.right) :
  new OpenLayers.LonLat(olBounds.top, olBounds.right);
  moBounds = new google.maps.LatLngBounds(
  new google.maps.LatLng(sw.lat, sw.lon),
  new google.maps.LatLng(ne.lat, ne.lon)
  );
  }
  return moBounds;
  },
   
   
  /************************************
  * *
  * MapObject Interface Controls *
  * *
  ************************************/
   
   
  // LonLat - Pixel Translation
   
  /**
  * APIMethod: getMapObjectLonLatFromMapObjectPixel
  *
  * Parameters:
  * moPixel - {Object} MapObject Pixel format
  *
  * Returns:
  * {Object} MapObject LonLat translated from MapObject Pixel
  */
  getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
  var size = this.map.getSize();
  var lon = this.getLongitudeFromMapObjectLonLat(this.mapObject.center);
  var lat = this.getLatitudeFromMapObjectLonLat(this.mapObject.center);
  var res = this.map.getResolution();
   
  var delta_x = moPixel.x - (size.w / 2);
  var delta_y = moPixel.y - (size.h / 2);
   
  var lonlat = new OpenLayers.LonLat(
  lon + delta_x * res,
  lat - delta_y * res
  );
   
  if (this.wrapDateLine) {
  lonlat = lonlat.wrapDateLine(this.maxExtent);
  }
  return this.getMapObjectLonLatFromLonLat(lonlat.lon, lonlat.lat);
  },
   
  /**
  * APIMethod: getMapObjectPixelFromMapObjectLonLat
  *
  * Parameters:
  * moLonLat - {Object} MapObject LonLat format
  *
  * Returns:
  * {Object} MapObject Pixel transtlated from MapObject LonLat
  */
  getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
  var lon = this.getLongitudeFromMapObjectLonLat(moLonLat);
  var lat = this.getLatitudeFromMapObjectLonLat(moLonLat);
  var res = this.map.getResolution();
  var extent = this.map.getExtent();
  var px = new OpenLayers.Pixel(
  (1/res * (lon - extent.left)),
  (1/res * (extent.top - lat))
  );
  return this.getMapObjectPixelFromXY(px.x, px.y);
  },
   
   
  /**
  * APIMethod: setMapObjectCenter
  * Set the mapObject to the specified center and zoom
  *
  * Parameters:
  * center - {Object} MapObject LonLat format
  * zoom - {int} MapObject zoom format
  */
  setMapObjectCenter: function(center, zoom) {
  this.mapObject.setOptions({
  center: center,
  zoom: zoom
  });
  },
   
   
  // Bounds
   
  /**
  * APIMethod: getMapObjectZoomFromMapObjectBounds
  *
  * Parameters:
  * moBounds - {Object} MapObject Bounds format
  *
  * Returns:
  * {Object} MapObject Zoom for specified MapObject Bounds
  */
  getMapObjectZoomFromMapObjectBounds: function(moBounds) {
  return this.mapObject.getBoundsZoomLevel(moBounds);
  },
   
  /************************************
  * *
  * MapObject Primitives *
  * *
  ************************************/
   
   
  // LonLat
   
  /**
  * APIMethod: getMapObjectLonLatFromLonLat
  *
  * Parameters:
  * lon - {Float}
  * lat - {Float}