--- a/labs/openlayers/lib/OpenLayers/Handler/Box.js +++ b/labs/openlayers/lib/OpenLayers/Handler/Box.js @@ -1,1 +1,222 @@ - +/* 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/Handler.js + * @requires OpenLayers/Handler/Drag.js + */ + +/** + * Class: OpenLayers.Handler.Box + * Handler for dragging a rectangle across the map. Box is displayed + * on mouse down, moves on mouse move, and is finished on mouse up. + * + * Inherits from: + * - + */ +OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, { + + /** + * Property: dragHandler + * {} + */ + dragHandler: null, + + /** + * APIProperty: boxDivClassName + * {String} The CSS class to use for drawing the box. Default is + * olHandlerBoxZoomBox + */ + boxDivClassName: 'olHandlerBoxZoomBox', + + /** + * Property: boxCharacteristics + * {Object} Caches some box characteristics from css. This is used + * by the getBoxCharacteristics method. + */ + boxCharacteristics: null, + + /** + * Constructor: OpenLayers.Handler.Box + * + * Parameters: + * control - {} + * callbacks - {Object} An object containing a single function to be + * called when the drag operation is finished. + * The callback should expect to recieve a single + * argument, the point geometry. + * options - {Object} + */ + initialize: function(control, callbacks, options) { + OpenLayers.Handler.prototype.initialize.apply(this, arguments); + var callbacks = { + "down": this.startBox, + "move": this.moveBox, + "out": this.removeBox, + "up": this.endBox + }; + this.dragHandler = new OpenLayers.Handler.Drag( + this, callbacks, {keyMask: this.keyMask}); + }, + + /** + * Method: destroy + */ + destroy: function() { + if (this.dragHandler) { + this.dragHandler.destroy(); + this.dragHandler = null; + } + OpenLayers.Handler.prototype.destroy.apply(this, arguments); + }, + + /** + * Method: setMap + */ + setMap: function (map) { + OpenLayers.Handler.prototype.setMap.apply(this, arguments); + if (this.dragHandler) { + this.dragHandler.setMap(map); + } + }, + + /** + * Method: startBox + * + * Parameters: + * evt - {Event} + */ + startBox: function (xy) { + this.zoomBox = OpenLayers.Util.createDiv('zoomBox', + this.dragHandler.start); + this.zoomBox.className = this.boxDivClassName; + this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; + this.map.viewPortDiv.appendChild(this.zoomBox); + + OpenLayers.Element.addClass( + this.map.viewPortDiv, "olDrawBox" + ); + }, + + /** + * Method: moveBox + */ + moveBox: function (xy) { + var startX = this.dragHandler.start.x; + var startY = this.dragHandler.start.y; + var deltaX = Math.abs(startX - xy.x); + var deltaY = Math.abs(startY - xy.y); + this.zoomBox.style.width = Math.max(1, deltaX) + "px"; + this.zoomBox.style.height = Math.max(1, deltaY) + "px"; + this.zoomBox.style.left = xy.x < startX ? xy.x+"px" : startX+"px"; + this.zoomBox.style.top = xy.y < startY ? xy.y+"px" : startY+"px"; + + // depending on the box model, modify width and height to take borders + // of the box into account + var box = this.getBoxCharacteristics(); + if (box.newBoxModel) { + if (xy.x > startX) { + this.zoomBox.style.width = + Math.max(1, deltaX - box.xOffset) + "px"; + } + if (xy.y > startY) { + this.zoomBox.style.height = + Math.max(1, deltaY - box.yOffset) + "px"; + } + } + }, + + /** + * Method: endBox + */ + endBox: function(end) { + var result; + if (Math.abs(this.dragHandler.start.x - end.x) > 5 || + Math.abs(this.dragHandler.start.y - end.y) > 5) { + var start = this.dragHandler.start; + var top = Math.min(start.y, end.y); + var bottom = Math.max(start.y, end.y); + var left = Math.min(start.x, end.x); + var right = Math.max(start.x, end.x); + result = new OpenLayers.Bounds(left, bottom, right, top); + } else { + result = this.dragHandler.start.clone(); // i.e. OL.Pixel + } + this.removeBox(); + + this.callback("done", [result]); + }, + + /** + * Method: removeBox + * Remove the zoombox from the screen and nullify our reference to it. + */ + removeBox: function() { + this.map.viewPortDiv.removeChild(this.zoomBox); + this.zoomBox = null; + this.boxCharacteristics = null; + OpenLayers.Element.removeClass( + this.map.viewPortDiv, "olDrawBox" + ); + + }, + + /** + * Method: activate + */ + activate: function () { + if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { + this.dragHandler.activate(); + return true; + } else { + return false; + } + }, + + /** + * Method: deactivate + */ + deactivate: function () { + if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { + this.dragHandler.deactivate(); + return true; + } else { + return false; + } + }, + + /** + * Method: getCharacteristics + * Determines offset and box model for a box. + * + * Returns: + * {Object} a hash with the following properties: + * - xOffset - Corner offset in x-direction + * - yOffset - Corner offset in y-direction + * - newBoxModel - true for all browsers except IE in quirks mode + */ + getBoxCharacteristics: function() { + if (!this.boxCharacteristics) { + var xOffset = parseInt(OpenLayers.Element.getStyle(this.zoomBox, + "border-left-width")) + parseInt(OpenLayers.Element.getStyle( + this.zoomBox, "border-right-width")) + 1; + var yOffset = parseInt(OpenLayers.Element.getStyle(this.zoomBox, + "border-top-width")) + parseInt(OpenLayers.Element.getStyle( + this.zoomBox, "border-bottom-width")) + 1; + // all browsers use the new box model, except IE in quirks mode + var newBoxModel = OpenLayers.Util.getBrowserName() == "msie" ? + document.compatMode != "BackCompat" : true; + this.boxCharacteristics = { + xOffset: xOffset, + yOffset: yOffset, + newBoxModel: newBoxModel + }; + } + return this.boxCharacteristics; + }, + + CLASS_NAME: "OpenLayers.Handler.Box" +}); +