Index: /oceandb/jQuery_Prototype/script/dragzoom.js
===================================================================
--- /oceandb/jQuery_Prototype/script/dragzoom.js	(revision 120)
+++ /oceandb/jQuery_Prototype/script/dragzoom.js	(revision 120)
@@ -0,0 +1,713 @@
+/*
+* DragZoomControl Class v1.3 
+*  Copyright (c) 2005-2007, Andre Lewis, andre@earthcode.com
+*
+* Back Button functionality
+*  Copyright (c)  2007, Richard Garland, papabear.newyork@gmail.com
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* 
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* This class lets you add a control to the map which will let the user
+*  zoom by dragging a rectangle.
+*  More info on original GZoom at http://earthcode.com
+*
+* Back Button functionality provides the user with a one click means to return the map state 
+*  to its state prior to the DragZoom.  Sequential DragZooms are backed out in reverse order.
+*/
+
+/**
+ * Constructor for DragZoomControl, which takes 3 option hashes and
+ *  uses them to customize the control.
+ * @param {opts_boxStyle} Named optional arguments:
+ *   opts_boxStyle.opacity {Number} Opacity from 0-1
+ *   opts_boxStyle.fillColor {String} Hex value of fill color
+ *   opts_boxStyle.border {String} CSS-style declaration of border
+ * @param {opts_other} Named optional arguments:
+ *   opts_other.buttonHTML {String} The zoom button HTML in non-activated state
+ *   opts_other.buttonStartingStyle {Object} A hash of css styles for the 
+ *     zoom button which are common to both un-activated and activated state
+ *   opts_other.buttonStyle {Object} A hash of css styles for the zoom button 
+ *     which will be applied when the button is in un-activated state.
+ *   opts_other.rightMouseZoomOutEnabled {Boolean} Whether to zoom out when a drag
+ *     with the right mouse button occurs.
+ *   opts_other.buttonZoomingHTML {String} HTML which is placed in the 
+ *     zoom button when the button is activated. 
+ *   opts_other.buttonZoomingStyle {Object} A hash of css styles for the 
+ *    zoom button which will be applied when the button is activated.
+ *   opts_other.overlayRemoveTime {Number} The number of milliseconds to wait before
+ *     removing the rectangle indicating the zoomed-in area after the zoom has happened.
+ *   opts_other.stickyZoomEnabled {Boolean} Whether or not the control stays in 
+ *     "zoom mode" until turned off. When true, the user can zoom repeatedly, 
+ *     until clicking on the zoom button again to turn zoom mode off.
+ *   opts_other.backButtonEnabled {Boolean} enables Back Button functionality
+ *   opts_other.backButtonHTML {String} The back button HTML
+ *   opts_other.backButtonStyle {Object} A hash of css styles for the back button
+ *     which will be applied when the button is created.
+ *   opts_other.minDragSize {Number} The minimum size of the rectangle when it is
+ *     released for a zoom to happen.
+ * @param {opts_callbacks} Named optional arguments:
+ *   opts_callbacks.buttonclick {Function} Called when the DragZoom is activated 
+ *     by clicking on the "zoom" button. 
+ *   opts_callbacks.dragstart {Function} Called when user starts to drag a rectangle.
+ *     Callback args are x,y -- the PIXEL values, relative to the upper-left-hand 
+ *     corner of the map, where the user began dragging.
+ *   opts_callbacks.dragging {Function} Called repeatedly while the user is dragging.
+ *     Callback args are startX,startY, currentX,currentY -- the PIXEL values of the 
+ *     start of the drag, and the current drag point, respectively.
+ *   opts_callbacks.dragend {Function} Called when the user releases the mouse button 
+ *     after dragging the rectangle. Callback args are: NW {GLatLng}, NE {GLatLng}, 
+ *     SE {GLatLng}, SW {GLatLng}, NW {GPoint}, NE {GPoint}, SE {GPoint}, SW {GPoint}.
+ *     The first 4 are the latitudes/longitudes; the last 4 are the pixel coords on the map.
+ *   opts_callbacks.backbuttonclick {Function} Called when the back button is activated 
+ *     after the map context is restored. Callback args: methodCall (boolean) set true if
+ *     this backbuttonclick was to restore context set by the mathod call, else false.
+ * Method
+ *    this.saveMapContext(text) Call to push map context onto the backStack and set the button text 
+ *    this.initiateZoom() Call to simulate clicking the dragZoom button
+ *    this.initiateZoomBack() Call to simulate clicking the dragZoom back button
+ **/
+
+/**
+ *  Versions
+ *  1.0 original version (v 189) 5/24/2007
+ *  1.1 backbutton functionality added  (v 211) 7/30/2007
+ *  1.2 bug fixes and 2 new methods 9/6/2007
+ *    fix text selection conflict in IE
+ *    fix align-text:center inheritance problem in IE
+ *    create methods initiateZoom and initiateZoomBack which call buttonclick_() and backbuttonclick_()
+ **/
+
+function DragZoomControl(opts_boxStyle, opts_other, opts_callbacks) {
+  // Holds all information needed globally
+  // Not all globals are initialized here
+  this.globals = {
+    draggingOn: false,
+    cornerTopDiv: null,
+    cornerRightDiv: null,
+    cornerBottomDiv: null,
+    cornerLeftDiv: null,
+    mapPosition: null,
+    outlineDiv: null,
+    mapWidth: 0,
+    mapHeight: 0,
+    mapRatio: 0,
+    startX: 0,
+    startY: 0,
+    borderCorrection: 0
+  };
+
+  //box style options
+  this.globals.style = {
+    opacity: .2,
+    fillColor: "#000",
+    border: "2px solid blue"
+  };
+
+  var style = this.globals.style;
+  for (var s in opts_boxStyle) {
+    style[s]=opts_boxStyle[s];
+  }
+
+  var borderStyleArray = style.border.split(' ');
+  style.outlineWidth = parseInt(borderStyleArray[0].replace(/\D/g,''));
+  style.outlineColor = borderStyleArray[2];
+  style.alphaIE = 'alpha(opacity=' + (style.opacity * 100) + ')';
+ 
+  // map context stack for back button
+  this.globals.backStack = [];
+
+  // Other options
+  this.globals.options={
+    buttonHTML: 'zoom ...',
+    buttonStartingStyle: 
+      {width: '52px', border: '1px solid black', padding: '2px'},
+    buttonStyle: {background: '#FFF'},
+    backButtonHTML: 'zoom back',
+    backButtonStyle: {background: '#FFF', display: 'none'},
+    buttonZoomingHTML: 'Drag a region on the map',
+    buttonZoomingStyle: {background: '#FF0'},
+    overlayRemoveTime: 6000,
+    backButtonEnabled: false,
+    stickyZoomEnabled: false,
+    rightMouseZoomOutEnabled: false,
+    minDragSize: 0
+  };
+	
+  for (var s in opts_other) {
+    this.globals.options[s] = opts_other[s]
+  }
+
+  // callbacks: buttonclick, dragstart, dragging, dragend, backbuttonclick 
+  if (opts_callbacks == null) {
+    opts_callbacks = {}
+  }
+  this.globals.callbacks = opts_callbacks;
+};
+
+DragZoomControl.prototype = new GControl();
+
+/**
+ * Methods
+ */
+
+/**
+ * Method called to save the map context before the zoom.
+ * Back Button functionality:	
+ * @param {text} text string for the back button
+ */
+DragZoomControl.prototype.saveMapContext = function(text) {
+  if (this.globals.options.backButtonEnabled) {
+    this.saveBackContext_(text,true);
+    this.globals.backButtonDiv.style.display = 'block';
+  }	
+};
+
+/**
+ * Method called to initiate a dragZoom as if the user had clicked the dragZoom button.
+ */
+DragZoomControl.prototype.initiateZoom = function() {this.buttonclick_()};
+
+/**
+ * Method called to initiate a dragZoom back operation as if the user had clicked the dragZoom back button.
+ * Back Button functionality:	
+ */
+DragZoomControl.prototype.initiateZoomBack = function() {if (this.globals.options.backButtonEnabled) this.backbuttonclick_()};	
+
+/**
+ * Creates a new button to control gzoom and appends to the button container div.
+ * @param {DOM Node} buttonContainerDiv created in main .initialize code
+ */
+DragZoomControl.prototype.initButton_ = function(buttonContainerDiv) {
+  var G = this.globals;
+  var buttonDiv = document.createElement('div');
+  buttonDiv.innerHTML = G.options.buttonHTML;
+  DragZoomUtil.style([buttonDiv], {cursor: 'pointer', zIndex:200});
+  DragZoomUtil.style([buttonDiv], G.options.buttonStartingStyle);
+  DragZoomUtil.style([buttonDiv], G.options.buttonStyle);
+  buttonContainerDiv.appendChild(buttonDiv);
+  return buttonDiv;
+};
+
+/**												
+ * Creates a second new button to control backup zoom and appends to the button container div.
+ * @param {DOM Node} buttonContainerDiv created in main .initialize code
+ */
+DragZoomControl.prototype.initBackButton_ = function(buttonContainerDiv) {
+  var G = this.globals;
+  var backButtonDiv = document.createElement('div');
+  backButtonDiv.innerHTML = G.options.backButtonHTML;
+  DragZoomUtil.style([backButtonDiv], {cursor: 'pointer', zIndex:200});
+  DragZoomUtil.style([backButtonDiv], G.options.buttonStartingStyle);
+  DragZoomUtil.style([backButtonDiv], G.options.backButtonStyle);
+  buttonContainerDiv.appendChild(backButtonDiv);
+  return backButtonDiv;
+};
+
+/**
+ * Sets button mode to zooming or otherwise, changes CSS & HTML.
+ * @param {String} mode Either "zooming" or not.
+ */
+DragZoomControl.prototype.setButtonMode_ = function(mode){
+  var G = this.globals;
+  if (mode == 'zooming') {
+    G.buttonDiv.innerHTML = G.options.buttonZoomingHTML;
+    DragZoomUtil.style([G.buttonDiv], G.options.buttonStartingStyle);
+    DragZoomUtil.style([G.buttonDiv], G.options.buttonZoomingStyle);
+  } else {
+    G.buttonDiv.innerHTML = G.options.buttonHTML;
+    DragZoomUtil.style([G.buttonDiv], G.options.buttonStartingStyle);
+    DragZoomUtil.style([G.buttonDiv], G.options.buttonStyle);
+  }
+};
+
+/**
+ * Is called by GMap2's addOverlay method. Creates the zoom control
+ * divs and appends to the map div.
+ * @param {GMap2} map The map that has had this DragZoomControl added to it.
+ * @return {DOM Object} Div that holds the gzoomcontrol button
+ */ 
+DragZoomControl.prototype.initialize = function(map) {
+  var G = this.globals;
+  var me = this;
+  var mapDiv = map.getContainer();
+ 
+  // Create div for both buttons	
+  var buttonContainerDiv = document.createElement("div");	
+  DragZoomUtil.style([buttonContainerDiv], {cursor: 'pointer', zIndex: 150});
+
+  // create and init the zoom button
+  //DOM:button
+  var buttonDiv = this.initButton_(buttonContainerDiv);
+
+  // create and init the back button				
+  //DOM:button
+  var backButtonDiv = this.initBackButton_(buttonContainerDiv);
+  
+  // Add the two buttons to the map 					
+  mapDiv.appendChild(buttonContainerDiv);
+ 
+  //DOM:map covers
+  var zoomDiv = document.createElement("div");
+  var DIVS_TO_CREATE = ['outlineDiv', 'cornerTopDiv', 'cornerLeftDiv', 'cornerRightDiv', 'cornerBottomDiv'];
+  for (var i=0; i<DIVS_TO_CREATE.length; i++) {
+    var id = DIVS_TO_CREATE[i];
+    var div = document.createElement("div");
+    DragZoomUtil.style([div], {position: 'absolute', display: 'none'});
+    zoomDiv.appendChild(div);
+    G[id] = div;
+  }
+  DragZoomUtil.style([zoomDiv], {position: 'absolute', display: 'none', overflow: 'hidden', cursor: 'crosshair', zIndex: 101});
+  mapDiv.appendChild(zoomDiv);
+  
+  // add event listeners
+  GEvent.addDomListener(buttonDiv, 'click', function(e) {
+    me.buttonclick_(e);
+  });
+  GEvent.addDomListener(backButtonDiv, 'click', function(e) {
+    me.backbuttonclick_(e);
+  });
+  GEvent.addDomListener(zoomDiv, 'mousedown', function(e) {
+    me.coverMousedown_(e);
+  });
+  GEvent.addDomListener(document, 'mousemove', function(e) {
+    me.drag_(e);
+  });
+  GEvent.addDomListener(document, 'mouseup', function(e) {
+    me.mouseup_(e);
+  });
+  
+  // get globals
+  G.mapPosition = DragZoomUtil.getElementPosition(mapDiv);
+  G.buttonDiv = buttonDiv;
+  G.backButtonDiv = backButtonDiv;
+  G.mapCover = zoomDiv;
+  G.map = map;
+
+  G.borderCorrection = G.style.outlineWidth * 2;	
+  this.setDimensions_();
+  
+  //styles
+  this.initStyles_();
+
+  // disable text selection on map cover
+  G.mapCover.onselectstart = function() {return false}; 
+    
+  return buttonContainerDiv;
+};
+
+/**
+ * Required by GMaps API for controls. 
+ * @return {GControlPosition} Default location for control
+ */
+DragZoomControl.prototype.getDefaultPosition = function() {
+  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(3, 120));
+};
+
+/**
+ * Function called when mousedown event is captured.
+ * @param {Object} e 
+ */
+DragZoomControl.prototype.coverMousedown_ = function(e){
+  var G = this.globals;
+  var pos = this.getRelPos_(e);
+  G.startX = pos.left;
+  G.startY = pos.top;
+
+  if (e.which) {
+    var rightMouse = (e.which != 1);
+  } else if (e.button) {
+    var rightMouse = (e.button != 1);
+  }
+  G.draggingRightMouse = rightMouse;
+  
+  DragZoomUtil.style([G.mapCover], {background: 'transparent', opacity: 1, filter: 'alpha(opacity=100)'});
+  DragZoomUtil.style([G.outlineDiv], {left: G.startX + 'px', top: G.startY + 'px', display: 'block', width: '1px', height: '1px'});
+  G.draggingOn = true;
+
+  G.cornerTopDiv.style.top = (G.startY - G.mapHeight) + 'px';
+  G.cornerTopDiv.style.display ='block';
+  G.cornerLeftDiv.style.left = (G.startX - G.mapWidth) +'px';
+  G.cornerLeftDiv.style.top = G.startY + 'px';
+  G.cornerLeftDiv.style.display = 'block';
+
+  G.cornerRightDiv.style.left = G.startX + 'px';
+  G.cornerRightDiv.style.top = G.startY + 'px';
+  G.cornerRightDiv.style.display = 'block';
+  G.cornerBottomDiv.style.left = G.startX + 'px';
+  G.cornerBottomDiv.style.top = G.startY + 'px';
+  G.cornerBottomDiv.style.width = '0px';
+  G.cornerBottomDiv.style.display = 'block';
+
+  // invoke the callback if provided
+  if (G.callbacks.dragstart != null) {
+    G.callbacks.dragstart(G.startX, G.startY);
+  }
+
+  return false;
+};
+
+/**
+ * Function called when drag event is captured
+ * @param {Object} e 
+ */
+DragZoomControl.prototype.drag_ = function(e){
+  var G = this.globals;
+  if(G.draggingOn) {
+    var pos = this.getRelPos_(e);
+    var rect = this.getRectangle_(G.startX, G.startY, pos, G.mapRatio);
+
+    if (rect.left) {
+      addX = -rect.width;			
+    } else { 
+      addX = 0;
+    }
+
+    if (rect.top) {
+      addY = -rect.height;
+    } else {
+      addY = 0;
+    }
+
+    DragZoomUtil.style([G.outlineDiv], {left: G.startX + addX + 'px', top: G.startY + addY + 'px', display: 'block', width: '1px', height: '1px'});	
+	
+    G.outlineDiv.style.width = rect.width + "px";
+    G.outlineDiv.style.height = rect.height + "px";
+
+    G.cornerTopDiv.style.height = ((G.startY + addY) - (G.startY - G.mapHeight)) + 'px';
+    G.cornerLeftDiv.style.top = (G.startY + addY) + 'px';
+    G.cornerLeftDiv.style.width = ((G.startX + addX) - (G.startX - G.mapWidth)) + 'px';
+    G.cornerRightDiv.style.top = G.cornerLeftDiv.style.top;
+    G.cornerRightDiv.style.left = (G.startX + addX + rect.width + G.borderCorrection) + 'px';
+    G.cornerBottomDiv.style.top = (G.startY + addY + rect.height + G.borderCorrection) + 'px';
+    G.cornerBottomDiv.style.left = (G.startX - G.mapWidth + ((G.startX + addX) - (G.startX - G.mapWidth))) + 'px';
+    G.cornerBottomDiv.style.width = (rect.width + G.borderCorrection) + 'px';
+		
+    // invoke callback if provided
+    if (G.callbacks.dragging != null) {
+      G.callbacks.dragging(G.startX, G.startY, rect.endX, rect.endY)
+    }
+		
+    return false;
+  }  
+};
+
+/** 
+ * Function called when mouseup event is captured
+ * @param {Event} e
+ */
+DragZoomControl.prototype.mouseup_ = function(e){
+  var G = this.globals;
+  if (G.draggingOn) {
+    var pos = this.getRelPos_(e);
+    G.draggingOn = false;
+    
+    var rect = this.getRectangle_(G.startX, G.startY, pos, G.mapRatio);
+
+    if (rect.left) rect.endX = rect.startX - rect.width;
+    if (rect.top) rect.endY = rect.startY - rect.height;
+	
+    this.resetDragZoom_();
+
+    if (rect.width >= G.options.minDragSize && rect.height >= G.options.minDragSize) {
+      var nwpx = new GPoint(rect.startX, rect.startY);
+      var nepx = new GPoint(rect.endX, rect.startY);
+      var sepx = new GPoint(rect.endX, rect.endY);
+      var swpx = new GPoint(rect.startX, rect.endY);
+      var nw = G.map.fromContainerPixelToLatLng(nwpx); 
+      var ne = G.map.fromContainerPixelToLatLng(nepx); 
+      var se = G.map.fromContainerPixelToLatLng(sepx); 
+      var sw = G.map.fromContainerPixelToLatLng(swpx); 
+
+      var zoomAreaPoly = new GPolyline([nw, ne, se, sw, nw], G.style.outlineColor, G.style.outlineWidth + 1,.4);
+
+      try{
+        G.map.addOverlay(zoomAreaPoly);
+        setTimeout (function() {G.map.removeOverlay(zoomAreaPoly)}, G.options.overlayRemoveTime);  
+      }catch(e) {}
+
+      var polyBounds = zoomAreaPoly.getBounds();
+      var ne = polyBounds.getNorthEast();
+      var sw = polyBounds.getSouthWest();
+      var se = new GLatLng(sw.lat(), ne.lng());
+      var nw = new GLatLng(ne.lat(), sw.lng());
+      if (G.options.rightMouseZoomOutEnabled && G.draggingRightMouse) {
+        var mapSpan = G.map.getBounds().toSpan();
+        var polySpan = polyBounds.toSpan();
+        var dSize = Math.max(mapSpan.lat()/polySpan.lat(), mapSpan.lng()/polySpan.lng());
+        var zoomLevel = G.map.getZoom() - Math.ceil(Math.log(dSize, 2));
+      } else {
+        var zoomLevel = G.map.getBoundsZoomLevel(polyBounds);
+      }
+      var center = polyBounds.getCenter();
+      G.map.setCenter(center, zoomLevel);
+
+      // invoke callback if provided
+      if (G.callbacks.dragend != null) {
+        G.callbacks.dragend(nw, ne, se, sw, nwpx, nepx, sepx, swpx);
+      }
+    }
+
+    //re-init if sticky
+    if (G.options.stickyZoomEnabled) {
+      //GLog.write("stickyZoomEnabled, re-initting");
+      this.initCover_();
+      if (G.options.backButtonEnabled) this.saveBackContext_(G.options.backButtonHTML,false); // save the map context for back button
+      G.backButtonDiv.style.display='none';
+    }
+  }
+};
+
+/**
+ * Set the cover sizes according to the size of the map
+ */
+DragZoomControl.prototype.setDimensions_ = function() {
+  var G = this.globals;
+  var mapSize = G.map.getSize();
+  G.mapWidth  = mapSize.width;
+  G.mapHeight = mapSize.height;
+  G.mapRatio  = G.mapHeight / G.mapWidth;
+  // set left:0px in next <div>s in case we inherit text-align:center from map <div> in IE.
+  DragZoomUtil.style([G.mapCover, G.cornerTopDiv, G.cornerRightDiv, G.cornerBottomDiv, G.cornerLeftDiv], 
+      {top: '0px', left: '0px', width: G.mapWidth + 'px', height: G.mapHeight +'px'});
+};
+
+/**
+ * Initializes styles based on global parameters
+ */
+DragZoomControl.prototype.initStyles_ = function(){
+  var G = this.globals;
+  DragZoomUtil.style([G.mapCover, G.cornerTopDiv, G.cornerRightDiv, G.cornerBottomDiv, G.cornerLeftDiv], 
+    {filter: G.style.alphaIE, opacity: G.style.opacity, background:G.style.fillColor});
+  G.outlineDiv.style.border = G.style.border;  
+};
+
+/**
+ * Function called when the zoom button's click event is captured.
+ */
+DragZoomControl.prototype.buttonclick_ = function(){
+  var G = this.globals;	
+  G.backButtonDiv.style.display='none';
+  if (G.mapCover.style.display == 'block') { // reset if clicked before dragging 
+    this.resetDragZoom_();
+    if (G.options.backButtonEnabled) {  
+      this.restoreBackContext_();  // pop the backStack on a button reset
+      if (G.backStack.length==0) G.backButtonDiv.style.display='none';
+    }
+  } else {
+    this.initCover_();
+    if ( G.options.backButtonEnabled ) this.saveBackContext_(G.options.backButtonHTML,false); // save the map context for back button
+  }
+};
+
+/**
+ * Back Button functionality:	
+ * Function called when the back button's click event is captured.
+ * calls the function to set the map context back to where it was before the zoom.
+ */
+DragZoomControl.prototype.backbuttonclick_ = function(){
+  var G = this.globals;	
+  if (G.options.backButtonEnabled && G.backStack.length > 0) {
+    this.restoreBackContext_();
+    // invoke the callback if provided
+    if (G.callbacks['backbuttonclick'] != null) {
+      G.callbacks.backbuttonclick(G.methodCall);
+    }
+  }
+};
+
+/** 
+ * Back Button functionality:	
+ * Saves the map context and pushes it on the backStack for later use by the back button
+ */
+DragZoomControl.prototype.saveBackContext_ = function(text,methodCall) {
+  var G = this.globals;
+  var backFrame = {};
+  backFrame["center"] = G.map.getCenter();
+  backFrame["zoom"] = G.map.getZoom();
+  backFrame["maptype"] = G.map.getCurrentMapType();
+  backFrame["text"] = G.backButtonDiv.innerHTML; // this saves the previous button text
+  backFrame["methodCall"] = methodCall; //This determines if it was an internal or method call
+  G.backStack.push(backFrame);
+  G.backButtonDiv.innerHTML = text;
+  // Back Button is turned on in resetDragZoom_()
+};
+
+/** 
+ * Back Button functionality:	
+ * Pops the previous map context off of the backStack and restores the map to that context
+ */
+DragZoomControl.prototype.restoreBackContext_ = function() {
+  var G = this.globals;
+  var backFrame = G.backStack.pop();
+  G.map.setCenter(backFrame["center"],backFrame["zoom"],backFrame["maptype"]);
+  G.backButtonDiv.innerHTML = backFrame["text"];
+  G.methodCall = backFrame["methodCall"];
+  if (G.backStack.length==0) G.backButtonDiv.style.display = 'none'; // if we're at the top of the stack, hide the back botton
+};
+
+/**
+ * Shows the cover over the map
+ */
+DragZoomControl.prototype.initCover_ = function(){
+  var G = this.globals;
+  G.mapPosition = DragZoomUtil.getElementPosition(G.map.getContainer());
+  this.setDimensions_();
+  this.setButtonMode_('zooming');
+  DragZoomUtil.style([G.mapCover], {display: 'block', background: G.style.fillColor});
+  DragZoomUtil.style([G.outlineDiv], {width: '0px', height: '0px'});
+
+  //invoke callback if provided
+  if(G.callbacks['buttonclick'] != null){
+    G.callbacks.buttonclick();
+  }
+};
+
+/**
+ * Gets position of the mouse relative to the map
+ * @param {Object} e
+ */
+DragZoomControl.prototype.getRelPos_ = function(e) {
+  var pos = DragZoomUtil.getMousePosition(e);
+  var G = this.globals;
+  return {top: (pos.top - G.mapPosition.top), 
+          left: (pos.left - G.mapPosition.left)};
+};
+
+/**
+ * Figures out the rectangle the user's trying to draw
+ * @param {Number} startX 
+ * @param {Number} startY
+ * @param {Object} pos
+ * @param {Number} ratio
+ * @return {Object} Describes the rectangle
+ */
+DragZoomControl.prototype.getRectangle_ = function(startX, startY, pos, ratio){
+  var left = false;
+  var top = false;
+  var dX = pos.left - startX;
+  var dY = pos.top - startY;	
+  if (dX < 0) {
+    dX = dX * -1;
+    left = true;
+  }
+  if (dY < 0) {
+    dY = dY * -1;
+    top = true;
+  }
+  delta = dX > dY ? dX : dY;
+
+  return {
+    startX: startX,
+    startY: startY,
+    endX: startX + delta,
+    endY: startY + parseInt(delta * ratio),
+    width: delta,
+    height: parseInt(delta * ratio),
+    left:left,
+    top:top
+  }
+};
+
+/** 
+ * Resets CSS and button display when drag zoom done
+ */
+DragZoomControl.prototype.resetDragZoom_ = function() {
+  var G = this.globals;
+  DragZoomUtil.style([G.mapCover, G.cornerTopDiv, G.cornerRightDiv, G.cornerBottomDiv, G.cornerLeftDiv], 
+    {display: 'none', opacity: G.style.opacity, filter: G.style.alphaIE});
+  G.outlineDiv.style.display = 'none';	
+  this.setButtonMode_('normal');
+  if (G.options.backButtonEnabled  && (G.backStack.length > 0)) G.backButtonDiv.style.display = 'block'; // show the back button
+};
+
+/* utility functions in DragZoomUtil.namespace */
+var DragZoomUtil={};
+
+/**
+ * Alias function for getting element by id
+ * @param {String} sId
+ * @return {Object} DOM object with sId id
+ */
+DragZoomUtil.gE = function(sId) {
+  return document.getElementById(sId);
+};
+
+/**
+ * A general-purpose function to get the absolute position
+ * of the mouse.
+ * @param {Object} e  Mouse event
+ * @return {Object} Describes position
+ */
+DragZoomUtil.getMousePosition = function(e) {
+  var posX = 0;
+  var posY = 0;
+  if (!e) var e = window.event;
+  if (e.pageX || e.pageY) {
+    posX = e.pageX;
+    posY = e.pageY;
+  } else if (e.clientX || e.clientY){
+    posX = e.clientX + 
+      (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
+    posY = e.clientY + 
+      (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
+  }
+  return {left: posX, top: posY};  
+};
+
+/**
+ * Gets position of element
+ * @param {Object} element
+ * @return {Object} Describes position
+ */
+DragZoomUtil.getElementPosition = function(element) {
+  var leftPos = element.offsetLeft;          // initialize var to store calculations
+  var topPos = element.offsetTop;            // initialize var to store calculations
+  var parElement = element.offsetParent;     // identify first offset parent element  
+  while (parElement != null ) {                // move up through element hierarchy
+    leftPos += parElement.offsetLeft;      // appending left offset of each parent
+    topPos += parElement.offsetTop;  
+    parElement = parElement.offsetParent;  // until no more offset parents exist
+  }
+  return {left: leftPos, top: topPos};
+};
+
+/**
+ * Applies styles to DOM objects 
+ * @param {String/Object} elements Either comma-delimited list of ids 
+ *   or an array of DOM objects
+ * @param {Object} styles Hash of styles to be applied
+ */
+DragZoomUtil.style = function(elements, styles){
+  if (typeof(elements) == 'string') {
+    elements = DragZoomUtil.getManyElements(elements);
+  }
+  for (var i = 0; i < elements.length; i++){
+    for (var s in styles) { 
+      elements[i].style[s] = styles[s];
+    }
+  }
+};
+
+/**
+ * Gets DOM elements array according to list of IDs
+ * @param {String} elementsString Comma-delimited list of IDs
+ * @return {Array} Array of DOM elements corresponding to s
+ */
+DragZoomUtil.getManyElements = function(idsString){		
+  var idsArray = idsString.split(',');
+  var elements = [];
+  for (var i = 0; i < idsArray.length; i++){
+    elements[elements.length] = DragZoomUtil.gE(idsArray[i])
+  };
+  return elements;
+};
Index: /oceandb/jQuery_Prototype/script/textualzoomcontrol.js
===================================================================
--- /oceandb/jQuery_Prototype/script/textualzoomcontrol.js	(revision 120)
+++ /oceandb/jQuery_Prototype/script/textualzoomcontrol.js	(revision 120)
@@ -0,0 +1,58 @@
+	function TextualZoomControl() {
+	}
+	
+	TextualZoomControl.prototype = new GControl();
+
+// 	Creates a one DIV for each of the buttons and places them in a container
+// 	DIV which is returned as our control element.
+	TextualZoomControl.prototype.initialize = function(map) {
+		var container = document.createElement("div");
+
+// "Zoom In" button
+		var zoomInDiv = document.createElement("div");
+		this.setButtonStyle_(zoomInDiv);
+		container.appendChild(zoomInDiv);
+		zoomInDiv.appendChild(document.createTextNode("Zoom In"));
+		// The "true" argument in the zoomIn() method allows continuous zooming
+		GEvent.addDomListener(zoomInDiv, "click", function() {map.zoomIn(null,null,true);} );
+
+// "Zoom Out" button
+		var zoomOutDiv = document.createElement("div");
+		this.setButtonStyle_(zoomOutDiv);
+		zoomOutDiv.style.borderTop = 0+'px';
+		container.appendChild(zoomOutDiv);
+		zoomOutDiv.appendChild(document.createTextNode("Zoom Out"));
+		// The "true" argument in the zoomOut() method allows continuous zooming
+		GEvent.addDomListener(zoomOutDiv, "click", function() {map.zoomOut(null,true);} );
+
+// 		We add the control to to the map container and return the element 
+// 		for the map class to position properly.
+
+		map.getContainer().appendChild(container);
+		return container;
+	}
+
+
+// 	The control will appear in the top left corner of the map with 7 pixels of padding.
+	TextualZoomControl.prototype.getDefaultPosition = function() {
+		return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(15, 7));
+	}
+
+// Sets the proper CSS for the given button element.
+	TextualZoomControl.prototype.setButtonStyle_ = function(button) {
+		button.style.textDecoration = "none";
+		button.style.color = "black";
+		button.style.backgroundColor = "white";
+//		button.style.font = "12px Verdana bold";
+		button.style.fontFamily = "Verdana";
+		button.style.fontSize = "12px";
+		button.style.fontWeight= "bold";
+		button.style.border = "1px solid gray";
+		button.style.padding = "0px";
+		button.style.marginBottom = "0px";
+		button.style.textAlign = "center";
+		button.style.width = "7em";
+		button.style.height = "15px";
+		button.style.cursor = "pointer";
+	}
+
