source: oceandb/jQuery_Prototype/script/dragzoom.js @ 120

Last change on this file since 120 was 120, checked in by rider, 15 years ago

ZoomIn/Out? libraries

File size: 25.8 KB
Line 
1/*
2* DragZoomControl Class v1.3
3*  Copyright (c) 2005-2007, Andre Lewis, andre@earthcode.com
4*
5* Back Button functionality
6*  Copyright (c)  2007, Richard Garland, papabear.newyork@gmail.com
7*
8* Licensed under the Apache License, Version 2.0 (the "License");
9* you may not use this file except in compliance with the License.
10* You may obtain a copy of the License at
11*
12*       http://www.apache.org/licenses/LICENSE-2.0
13*
14* Unless required by applicable law or agreed to in writing, software
15* distributed under the License is distributed on an "AS IS" BASIS,
16* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17* See the License for the specific language governing permissions and
18* limitations under the License.
19*
20* This class lets you add a control to the map which will let the user
21*  zoom by dragging a rectangle.
22*  More info on original GZoom at http://earthcode.com
23*
24* Back Button functionality provides the user with a one click means to return the map state
25*  to its state prior to the DragZoom.  Sequential DragZooms are backed out in reverse order.
26*/
27
28/**
29 * Constructor for DragZoomControl, which takes 3 option hashes and
30 *  uses them to customize the control.
31 * @param {opts_boxStyle} Named optional arguments:
32 *   opts_boxStyle.opacity {Number} Opacity from 0-1
33 *   opts_boxStyle.fillColor {String} Hex value of fill color
34 *   opts_boxStyle.border {String} CSS-style declaration of border
35 * @param {opts_other} Named optional arguments:
36 *   opts_other.buttonHTML {String} The zoom button HTML in non-activated state
37 *   opts_other.buttonStartingStyle {Object} A hash of css styles for the
38 *     zoom button which are common to both un-activated and activated state
39 *   opts_other.buttonStyle {Object} A hash of css styles for the zoom button
40 *     which will be applied when the button is in un-activated state.
41 *   opts_other.rightMouseZoomOutEnabled {Boolean} Whether to zoom out when a drag
42 *     with the right mouse button occurs.
43 *   opts_other.buttonZoomingHTML {String} HTML which is placed in the
44 *     zoom button when the button is activated.
45 *   opts_other.buttonZoomingStyle {Object} A hash of css styles for the
46 *    zoom button which will be applied when the button is activated.
47 *   opts_other.overlayRemoveTime {Number} The number of milliseconds to wait before
48 *     removing the rectangle indicating the zoomed-in area after the zoom has happened.
49 *   opts_other.stickyZoomEnabled {Boolean} Whether or not the control stays in
50 *     "zoom mode" until turned off. When true, the user can zoom repeatedly,
51 *     until clicking on the zoom button again to turn zoom mode off.
52 *   opts_other.backButtonEnabled {Boolean} enables Back Button functionality
53 *   opts_other.backButtonHTML {String} The back button HTML
54 *   opts_other.backButtonStyle {Object} A hash of css styles for the back button
55 *     which will be applied when the button is created.
56 *   opts_other.minDragSize {Number} The minimum size of the rectangle when it is
57 *     released for a zoom to happen.
58 * @param {opts_callbacks} Named optional arguments:
59 *   opts_callbacks.buttonclick {Function} Called when the DragZoom is activated
60 *     by clicking on the "zoom" button.
61 *   opts_callbacks.dragstart {Function} Called when user starts to drag a rectangle.
62 *     Callback args are x,y -- the PIXEL values, relative to the upper-left-hand
63 *     corner of the map, where the user began dragging.
64 *   opts_callbacks.dragging {Function} Called repeatedly while the user is dragging.
65 *     Callback args are startX,startY, currentX,currentY -- the PIXEL values of the
66 *     start of the drag, and the current drag point, respectively.
67 *   opts_callbacks.dragend {Function} Called when the user releases the mouse button
68 *     after dragging the rectangle. Callback args are: NW {GLatLng}, NE {GLatLng},
69 *     SE {GLatLng}, SW {GLatLng}, NW {GPoint}, NE {GPoint}, SE {GPoint}, SW {GPoint}.
70 *     The first 4 are the latitudes/longitudes; the last 4 are the pixel coords on the map.
71 *   opts_callbacks.backbuttonclick {Function} Called when the back button is activated
72 *     after the map context is restored. Callback args: methodCall (boolean) set true if
73 *     this backbuttonclick was to restore context set by the mathod call, else false.
74 * Method
75 *    this.saveMapContext(text) Call to push map context onto the backStack and set the button text
76 *    this.initiateZoom() Call to simulate clicking the dragZoom button
77 *    this.initiateZoomBack() Call to simulate clicking the dragZoom back button
78 **/
79
80/**
81 *  Versions
82 *  1.0 original version (v 189) 5/24/2007
83 *  1.1 backbutton functionality added  (v 211) 7/30/2007
84 *  1.2 bug fixes and 2 new methods 9/6/2007
85 *    fix text selection conflict in IE
86 *    fix align-text:center inheritance problem in IE
87 *    create methods initiateZoom and initiateZoomBack which call buttonclick_() and backbuttonclick_()
88 **/
89
90function DragZoomControl(opts_boxStyle, opts_other, opts_callbacks) {
91  // Holds all information needed globally
92  // Not all globals are initialized here
93  this.globals = {
94    draggingOn: false,
95    cornerTopDiv: null,
96    cornerRightDiv: null,
97    cornerBottomDiv: null,
98    cornerLeftDiv: null,
99    mapPosition: null,
100    outlineDiv: null,
101    mapWidth: 0,
102    mapHeight: 0,
103    mapRatio: 0,
104    startX: 0,
105    startY: 0,
106    borderCorrection: 0
107  };
108
109  //box style options
110  this.globals.style = {
111    opacity: .2,
112    fillColor: "#000",
113    border: "2px solid blue"
114  };
115
116  var style = this.globals.style;
117  for (var s in opts_boxStyle) {
118    style[s]=opts_boxStyle[s];
119  }
120
121  var borderStyleArray = style.border.split(' ');
122  style.outlineWidth = parseInt(borderStyleArray[0].replace(/\D/g,''));
123  style.outlineColor = borderStyleArray[2];
124  style.alphaIE = 'alpha(opacity=' + (style.opacity * 100) + ')';
125 
126  // map context stack for back button
127  this.globals.backStack = [];
128
129  // Other options
130  this.globals.options={
131    buttonHTML: 'zoom ...',
132    buttonStartingStyle: 
133      {width: '52px', border: '1px solid black', padding: '2px'},
134    buttonStyle: {background: '#FFF'},
135    backButtonHTML: 'zoom back',
136    backButtonStyle: {background: '#FFF', display: 'none'},
137    buttonZoomingHTML: 'Drag a region on the map',
138    buttonZoomingStyle: {background: '#FF0'},
139    overlayRemoveTime: 6000,
140    backButtonEnabled: false,
141    stickyZoomEnabled: false,
142    rightMouseZoomOutEnabled: false,
143    minDragSize: 0
144  };
145 
146  for (var s in opts_other) {
147    this.globals.options[s] = opts_other[s]
148  }
149
150  // callbacks: buttonclick, dragstart, dragging, dragend, backbuttonclick
151  if (opts_callbacks == null) {
152    opts_callbacks = {}
153  }
154  this.globals.callbacks = opts_callbacks;
155};
156
157DragZoomControl.prototype = new GControl();
158
159/**
160 * Methods
161 */
162
163/**
164 * Method called to save the map context before the zoom.
165 * Back Button functionality:
166 * @param {text} text string for the back button
167 */
168DragZoomControl.prototype.saveMapContext = function(text) {
169  if (this.globals.options.backButtonEnabled) {
170    this.saveBackContext_(text,true);
171    this.globals.backButtonDiv.style.display = 'block';
172  } 
173};
174
175/**
176 * Method called to initiate a dragZoom as if the user had clicked the dragZoom button.
177 */
178DragZoomControl.prototype.initiateZoom = function() {this.buttonclick_()};
179
180/**
181 * Method called to initiate a dragZoom back operation as if the user had clicked the dragZoom back button.
182 * Back Button functionality:
183 */
184DragZoomControl.prototype.initiateZoomBack = function() {if (this.globals.options.backButtonEnabled) this.backbuttonclick_()}; 
185
186/**
187 * Creates a new button to control gzoom and appends to the button container div.
188 * @param {DOM Node} buttonContainerDiv created in main .initialize code
189 */
190DragZoomControl.prototype.initButton_ = function(buttonContainerDiv) {
191  var G = this.globals;
192  var buttonDiv = document.createElement('div');
193  buttonDiv.innerHTML = G.options.buttonHTML;
194  DragZoomUtil.style([buttonDiv], {cursor: 'pointer', zIndex:200});
195  DragZoomUtil.style([buttonDiv], G.options.buttonStartingStyle);
196  DragZoomUtil.style([buttonDiv], G.options.buttonStyle);
197  buttonContainerDiv.appendChild(buttonDiv);
198  return buttonDiv;
199};
200
201/**                       
202 * Creates a second new button to control backup zoom and appends to the button container div.
203 * @param {DOM Node} buttonContainerDiv created in main .initialize code
204 */
205DragZoomControl.prototype.initBackButton_ = function(buttonContainerDiv) {
206  var G = this.globals;
207  var backButtonDiv = document.createElement('div');
208  backButtonDiv.innerHTML = G.options.backButtonHTML;
209  DragZoomUtil.style([backButtonDiv], {cursor: 'pointer', zIndex:200});
210  DragZoomUtil.style([backButtonDiv], G.options.buttonStartingStyle);
211  DragZoomUtil.style([backButtonDiv], G.options.backButtonStyle);
212  buttonContainerDiv.appendChild(backButtonDiv);
213  return backButtonDiv;
214};
215
216/**
217 * Sets button mode to zooming or otherwise, changes CSS & HTML.
218 * @param {String} mode Either "zooming" or not.
219 */
220DragZoomControl.prototype.setButtonMode_ = function(mode){
221  var G = this.globals;
222  if (mode == 'zooming') {
223    G.buttonDiv.innerHTML = G.options.buttonZoomingHTML;
224    DragZoomUtil.style([G.buttonDiv], G.options.buttonStartingStyle);
225    DragZoomUtil.style([G.buttonDiv], G.options.buttonZoomingStyle);
226  } else {
227    G.buttonDiv.innerHTML = G.options.buttonHTML;
228    DragZoomUtil.style([G.buttonDiv], G.options.buttonStartingStyle);
229    DragZoomUtil.style([G.buttonDiv], G.options.buttonStyle);
230  }
231};
232
233/**
234 * Is called by GMap2's addOverlay method. Creates the zoom control
235 * divs and appends to the map div.
236 * @param {GMap2} map The map that has had this DragZoomControl added to it.
237 * @return {DOM Object} Div that holds the gzoomcontrol button
238 */ 
239DragZoomControl.prototype.initialize = function(map) {
240  var G = this.globals;
241  var me = this;
242  var mapDiv = map.getContainer();
243 
244  // Create div for both buttons 
245  var buttonContainerDiv = document.createElement("div"); 
246  DragZoomUtil.style([buttonContainerDiv], {cursor: 'pointer', zIndex: 150});
247
248  // create and init the zoom button
249  //DOM:button
250  var buttonDiv = this.initButton_(buttonContainerDiv);
251
252  // create and init the back button       
253  //DOM:button
254  var backButtonDiv = this.initBackButton_(buttonContainerDiv);
255 
256  // Add the two buttons to the map           
257  mapDiv.appendChild(buttonContainerDiv);
258 
259  //DOM:map covers
260  var zoomDiv = document.createElement("div");
261  var DIVS_TO_CREATE = ['outlineDiv', 'cornerTopDiv', 'cornerLeftDiv', 'cornerRightDiv', 'cornerBottomDiv'];
262  for (var i=0; i<DIVS_TO_CREATE.length; i++) {
263    var id = DIVS_TO_CREATE[i];
264    var div = document.createElement("div");
265    DragZoomUtil.style([div], {position: 'absolute', display: 'none'});
266    zoomDiv.appendChild(div);
267    G[id] = div;
268  }
269  DragZoomUtil.style([zoomDiv], {position: 'absolute', display: 'none', overflow: 'hidden', cursor: 'crosshair', zIndex: 101});
270  mapDiv.appendChild(zoomDiv);
271 
272  // add event listeners
273  GEvent.addDomListener(buttonDiv, 'click', function(e) {
274    me.buttonclick_(e);
275  });
276  GEvent.addDomListener(backButtonDiv, 'click', function(e) {
277    me.backbuttonclick_(e);
278  });
279  GEvent.addDomListener(zoomDiv, 'mousedown', function(e) {
280    me.coverMousedown_(e);
281  });
282  GEvent.addDomListener(document, 'mousemove', function(e) {
283    me.drag_(e);
284  });
285  GEvent.addDomListener(document, 'mouseup', function(e) {
286    me.mouseup_(e);
287  });
288 
289  // get globals
290  G.mapPosition = DragZoomUtil.getElementPosition(mapDiv);
291  G.buttonDiv = buttonDiv;
292  G.backButtonDiv = backButtonDiv;
293  G.mapCover = zoomDiv;
294  G.map = map;
295
296  G.borderCorrection = G.style.outlineWidth * 2; 
297  this.setDimensions_();
298 
299  //styles
300  this.initStyles_();
301
302  // disable text selection on map cover
303  G.mapCover.onselectstart = function() {return false}; 
304   
305  return buttonContainerDiv;
306};
307
308/**
309 * Required by GMaps API for controls.
310 * @return {GControlPosition} Default location for control
311 */
312DragZoomControl.prototype.getDefaultPosition = function() {
313  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(3, 120));
314};
315
316/**
317 * Function called when mousedown event is captured.
318 * @param {Object} e
319 */
320DragZoomControl.prototype.coverMousedown_ = function(e){
321  var G = this.globals;
322  var pos = this.getRelPos_(e);
323  G.startX = pos.left;
324  G.startY = pos.top;
325
326  if (e.which) {
327    var rightMouse = (e.which != 1);
328  } else if (e.button) {
329    var rightMouse = (e.button != 1);
330  }
331  G.draggingRightMouse = rightMouse;
332 
333  DragZoomUtil.style([G.mapCover], {background: 'transparent', opacity: 1, filter: 'alpha(opacity=100)'});
334  DragZoomUtil.style([G.outlineDiv], {left: G.startX + 'px', top: G.startY + 'px', display: 'block', width: '1px', height: '1px'});
335  G.draggingOn = true;
336
337  G.cornerTopDiv.style.top = (G.startY - G.mapHeight) + 'px';
338  G.cornerTopDiv.style.display ='block';
339  G.cornerLeftDiv.style.left = (G.startX - G.mapWidth) +'px';
340  G.cornerLeftDiv.style.top = G.startY + 'px';
341  G.cornerLeftDiv.style.display = 'block';
342
343  G.cornerRightDiv.style.left = G.startX + 'px';
344  G.cornerRightDiv.style.top = G.startY + 'px';
345  G.cornerRightDiv.style.display = 'block';
346  G.cornerBottomDiv.style.left = G.startX + 'px';
347  G.cornerBottomDiv.style.top = G.startY + 'px';
348  G.cornerBottomDiv.style.width = '0px';
349  G.cornerBottomDiv.style.display = 'block';
350
351  // invoke the callback if provided
352  if (G.callbacks.dragstart != null) {
353    G.callbacks.dragstart(G.startX, G.startY);
354  }
355
356  return false;
357};
358
359/**
360 * Function called when drag event is captured
361 * @param {Object} e
362 */
363DragZoomControl.prototype.drag_ = function(e){
364  var G = this.globals;
365  if(G.draggingOn) {
366    var pos = this.getRelPos_(e);
367    var rect = this.getRectangle_(G.startX, G.startY, pos, G.mapRatio);
368
369    if (rect.left) {
370      addX = -rect.width;     
371    } else { 
372      addX = 0;
373    }
374
375    if (rect.top) {
376      addY = -rect.height;
377    } else {
378      addY = 0;
379    }
380
381    DragZoomUtil.style([G.outlineDiv], {left: G.startX + addX + 'px', top: G.startY + addY + 'px', display: 'block', width: '1px', height: '1px'}); 
382 
383    G.outlineDiv.style.width = rect.width + "px";
384    G.outlineDiv.style.height = rect.height + "px";
385
386    G.cornerTopDiv.style.height = ((G.startY + addY) - (G.startY - G.mapHeight)) + 'px';
387    G.cornerLeftDiv.style.top = (G.startY + addY) + 'px';
388    G.cornerLeftDiv.style.width = ((G.startX + addX) - (G.startX - G.mapWidth)) + 'px';
389    G.cornerRightDiv.style.top = G.cornerLeftDiv.style.top;
390    G.cornerRightDiv.style.left = (G.startX + addX + rect.width + G.borderCorrection) + 'px';
391    G.cornerBottomDiv.style.top = (G.startY + addY + rect.height + G.borderCorrection) + 'px';
392    G.cornerBottomDiv.style.left = (G.startX - G.mapWidth + ((G.startX + addX) - (G.startX - G.mapWidth))) + 'px';
393    G.cornerBottomDiv.style.width = (rect.width + G.borderCorrection) + 'px';
394   
395    // invoke callback if provided
396    if (G.callbacks.dragging != null) {
397      G.callbacks.dragging(G.startX, G.startY, rect.endX, rect.endY)
398    }
399   
400    return false;
401  } 
402};
403
404/**
405 * Function called when mouseup event is captured
406 * @param {Event} e
407 */
408DragZoomControl.prototype.mouseup_ = function(e){
409  var G = this.globals;
410  if (G.draggingOn) {
411    var pos = this.getRelPos_(e);
412    G.draggingOn = false;
413   
414    var rect = this.getRectangle_(G.startX, G.startY, pos, G.mapRatio);
415
416    if (rect.left) rect.endX = rect.startX - rect.width;
417    if (rect.top) rect.endY = rect.startY - rect.height;
418 
419    this.resetDragZoom_();
420
421    if (rect.width >= G.options.minDragSize && rect.height >= G.options.minDragSize) {
422      var nwpx = new GPoint(rect.startX, rect.startY);
423      var nepx = new GPoint(rect.endX, rect.startY);
424      var sepx = new GPoint(rect.endX, rect.endY);
425      var swpx = new GPoint(rect.startX, rect.endY);
426      var nw = G.map.fromContainerPixelToLatLng(nwpx); 
427      var ne = G.map.fromContainerPixelToLatLng(nepx); 
428      var se = G.map.fromContainerPixelToLatLng(sepx); 
429      var sw = G.map.fromContainerPixelToLatLng(swpx); 
430
431      var zoomAreaPoly = new GPolyline([nw, ne, se, sw, nw], G.style.outlineColor, G.style.outlineWidth + 1,.4);
432
433      try{
434        G.map.addOverlay(zoomAreaPoly);
435        setTimeout (function() {G.map.removeOverlay(zoomAreaPoly)}, G.options.overlayRemoveTime); 
436      }catch(e) {}
437
438      var polyBounds = zoomAreaPoly.getBounds();
439      var ne = polyBounds.getNorthEast();
440      var sw = polyBounds.getSouthWest();
441      var se = new GLatLng(sw.lat(), ne.lng());
442      var nw = new GLatLng(ne.lat(), sw.lng());
443      if (G.options.rightMouseZoomOutEnabled && G.draggingRightMouse) {
444        var mapSpan = G.map.getBounds().toSpan();
445        var polySpan = polyBounds.toSpan();
446        var dSize = Math.max(mapSpan.lat()/polySpan.lat(), mapSpan.lng()/polySpan.lng());
447        var zoomLevel = G.map.getZoom() - Math.ceil(Math.log(dSize, 2));
448      } else {
449        var zoomLevel = G.map.getBoundsZoomLevel(polyBounds);
450      }
451      var center = polyBounds.getCenter();
452      G.map.setCenter(center, zoomLevel);
453
454      // invoke callback if provided
455      if (G.callbacks.dragend != null) {
456        G.callbacks.dragend(nw, ne, se, sw, nwpx, nepx, sepx, swpx);
457      }
458    }
459
460    //re-init if sticky
461    if (G.options.stickyZoomEnabled) {
462      //GLog.write("stickyZoomEnabled, re-initting");
463      this.initCover_();
464      if (G.options.backButtonEnabled) this.saveBackContext_(G.options.backButtonHTML,false); // save the map context for back button
465      G.backButtonDiv.style.display='none';
466    }
467  }
468};
469
470/**
471 * Set the cover sizes according to the size of the map
472 */
473DragZoomControl.prototype.setDimensions_ = function() {
474  var G = this.globals;
475  var mapSize = G.map.getSize();
476  G.mapWidth  = mapSize.width;
477  G.mapHeight = mapSize.height;
478  G.mapRatio  = G.mapHeight / G.mapWidth;
479  // set left:0px in next <div>s in case we inherit text-align:center from map <div> in IE.
480  DragZoomUtil.style([G.mapCover, G.cornerTopDiv, G.cornerRightDiv, G.cornerBottomDiv, G.cornerLeftDiv], 
481      {top: '0px', left: '0px', width: G.mapWidth + 'px', height: G.mapHeight +'px'});
482};
483
484/**
485 * Initializes styles based on global parameters
486 */
487DragZoomControl.prototype.initStyles_ = function(){
488  var G = this.globals;
489  DragZoomUtil.style([G.mapCover, G.cornerTopDiv, G.cornerRightDiv, G.cornerBottomDiv, G.cornerLeftDiv], 
490    {filter: G.style.alphaIE, opacity: G.style.opacity, background:G.style.fillColor});
491  G.outlineDiv.style.border = G.style.border; 
492};
493
494/**
495 * Function called when the zoom button's click event is captured.
496 */
497DragZoomControl.prototype.buttonclick_ = function(){
498  var G = this.globals; 
499  G.backButtonDiv.style.display='none';
500  if (G.mapCover.style.display == 'block') { // reset if clicked before dragging
501    this.resetDragZoom_();
502    if (G.options.backButtonEnabled) { 
503      this.restoreBackContext_();  // pop the backStack on a button reset
504      if (G.backStack.length==0) G.backButtonDiv.style.display='none';
505    }
506  } else {
507    this.initCover_();
508    if ( G.options.backButtonEnabled ) this.saveBackContext_(G.options.backButtonHTML,false); // save the map context for back button
509  }
510};
511
512/**
513 * Back Button functionality:
514 * Function called when the back button's click event is captured.
515 * calls the function to set the map context back to where it was before the zoom.
516 */
517DragZoomControl.prototype.backbuttonclick_ = function(){
518  var G = this.globals; 
519  if (G.options.backButtonEnabled && G.backStack.length > 0) {
520    this.restoreBackContext_();
521    // invoke the callback if provided
522    if (G.callbacks['backbuttonclick'] != null) {
523      G.callbacks.backbuttonclick(G.methodCall);
524    }
525  }
526};
527
528/**
529 * Back Button functionality:
530 * Saves the map context and pushes it on the backStack for later use by the back button
531 */
532DragZoomControl.prototype.saveBackContext_ = function(text,methodCall) {
533  var G = this.globals;
534  var backFrame = {};
535  backFrame["center"] = G.map.getCenter();
536  backFrame["zoom"] = G.map.getZoom();
537  backFrame["maptype"] = G.map.getCurrentMapType();
538  backFrame["text"] = G.backButtonDiv.innerHTML; // this saves the previous button text
539  backFrame["methodCall"] = methodCall; //This determines if it was an internal or method call
540  G.backStack.push(backFrame);
541  G.backButtonDiv.innerHTML = text;
542  // Back Button is turned on in resetDragZoom_()
543};
544
545/**
546 * Back Button functionality:
547 * Pops the previous map context off of the backStack and restores the map to that context
548 */
549DragZoomControl.prototype.restoreBackContext_ = function() {
550  var G = this.globals;
551  var backFrame = G.backStack.pop();
552  G.map.setCenter(backFrame["center"],backFrame["zoom"],backFrame["maptype"]);
553  G.backButtonDiv.innerHTML = backFrame["text"];
554  G.methodCall = backFrame["methodCall"];
555  if (G.backStack.length==0) G.backButtonDiv.style.display = 'none'; // if we're at the top of the stack, hide the back botton
556};
557
558/**
559 * Shows the cover over the map
560 */
561DragZoomControl.prototype.initCover_ = function(){
562  var G = this.globals;
563  G.mapPosition = DragZoomUtil.getElementPosition(G.map.getContainer());
564  this.setDimensions_();
565  this.setButtonMode_('zooming');
566  DragZoomUtil.style([G.mapCover], {display: 'block', background: G.style.fillColor});
567  DragZoomUtil.style([G.outlineDiv], {width: '0px', height: '0px'});
568
569  //invoke callback if provided
570  if(G.callbacks['buttonclick'] != null){
571    G.callbacks.buttonclick();
572  }
573};
574
575/**
576 * Gets position of the mouse relative to the map
577 * @param {Object} e
578 */
579DragZoomControl.prototype.getRelPos_ = function(e) {
580  var pos = DragZoomUtil.getMousePosition(e);
581  var G = this.globals;
582  return {top: (pos.top - G.mapPosition.top), 
583          left: (pos.left - G.mapPosition.left)};
584};
585
586/**
587 * Figures out the rectangle the user's trying to draw
588 * @param {Number} startX
589 * @param {Number} startY
590 * @param {Object} pos
591 * @param {Number} ratio
592 * @return {Object} Describes the rectangle
593 */
594DragZoomControl.prototype.getRectangle_ = function(startX, startY, pos, ratio){
595  var left = false;
596  var top = false;
597  var dX = pos.left - startX;
598  var dY = pos.top - startY; 
599  if (dX < 0) {
600    dX = dX * -1;
601    left = true;
602  }
603  if (dY < 0) {
604    dY = dY * -1;
605    top = true;
606  }
607  delta = dX > dY ? dX : dY;
608
609  return {
610    startX: startX,
611    startY: startY,
612    endX: startX + delta,
613    endY: startY + parseInt(delta * ratio),
614    width: delta,
615    height: parseInt(delta * ratio),
616    left:left,
617    top:top
618  }
619};
620
621/**
622 * Resets CSS and button display when drag zoom done
623 */
624DragZoomControl.prototype.resetDragZoom_ = function() {
625  var G = this.globals;
626  DragZoomUtil.style([G.mapCover, G.cornerTopDiv, G.cornerRightDiv, G.cornerBottomDiv, G.cornerLeftDiv], 
627    {display: 'none', opacity: G.style.opacity, filter: G.style.alphaIE});
628  G.outlineDiv.style.display = 'none'; 
629  this.setButtonMode_('normal');
630  if (G.options.backButtonEnabled  && (G.backStack.length > 0)) G.backButtonDiv.style.display = 'block'; // show the back button
631};
632
633/* utility functions in DragZoomUtil.namespace */
634var DragZoomUtil={};
635
636/**
637 * Alias function for getting element by id
638 * @param {String} sId
639 * @return {Object} DOM object with sId id
640 */
641DragZoomUtil.gE = function(sId) {
642  return document.getElementById(sId);
643};
644
645/**
646 * A general-purpose function to get the absolute position
647 * of the mouse.
648 * @param {Object} e  Mouse event
649 * @return {Object} Describes position
650 */
651DragZoomUtil.getMousePosition = function(e) {
652  var posX = 0;
653  var posY = 0;
654  if (!e) var e = window.event;
655  if (e.pageX || e.pageY) {
656    posX = e.pageX;
657    posY = e.pageY;
658  } else if (e.clientX || e.clientY){
659    posX = e.clientX + 
660      (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
661    posY = e.clientY + 
662      (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
663  }
664  return {left: posX, top: posY}; 
665};
666
667/**
668 * Gets position of element
669 * @param {Object} element
670 * @return {Object} Describes position
671 */
672DragZoomUtil.getElementPosition = function(element) {
673  var leftPos = element.offsetLeft;          // initialize var to store calculations
674  var topPos = element.offsetTop;            // initialize var to store calculations
675  var parElement = element.offsetParent;     // identify first offset parent element 
676  while (parElement != null ) {                // move up through element hierarchy
677    leftPos += parElement.offsetLeft;      // appending left offset of each parent
678    topPos += parElement.offsetTop; 
679    parElement = parElement.offsetParent;  // until no more offset parents exist
680  }
681  return {left: leftPos, top: topPos};
682};
683
684/**
685 * Applies styles to DOM objects
686 * @param {String/Object} elements Either comma-delimited list of ids
687 *   or an array of DOM objects
688 * @param {Object} styles Hash of styles to be applied
689 */
690DragZoomUtil.style = function(elements, styles){
691  if (typeof(elements) == 'string') {
692    elements = DragZoomUtil.getManyElements(elements);
693  }
694  for (var i = 0; i < elements.length; i++){
695    for (var s in styles) { 
696      elements[i].style[s] = styles[s];
697    }
698  }
699};
700
701/**
702 * Gets DOM elements array according to list of IDs
703 * @param {String} elementsString Comma-delimited list of IDs
704 * @return {Array} Array of DOM elements corresponding to s
705 */
706DragZoomUtil.getManyElements = function(idsString){   
707  var idsArray = idsString.split(',');
708  var elements = [];
709  for (var i = 0; i < idsArray.length; i++){
710    elements[elements.length] = DragZoomUtil.gE(idsArray[i])
711  };
712  return elements;
713};
Note: See TracBrowser for help on using the repository browser.