Box.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the Clear BSD license.
  3. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  4. * full text of the license. */
  5. /**
  6. * @requires OpenLayers/Handler.js
  7. * @requires OpenLayers/Handler/Drag.js
  8. */
  9. /**
  10. * Class: OpenLayers.Handler.Box
  11. * Handler for dragging a rectangle across the map. Box is displayed
  12. * on mouse down, moves on mouse move, and is finished on mouse up.
  13. *
  14. * Inherits from:
  15. * - <OpenLayers.Handler>
  16. */
  17. OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, {
  18. /**
  19. * Property: dragHandler
  20. * {<OpenLayers.Handler.Drag>}
  21. */
  22. dragHandler: null,
  23. /**
  24. * APIProperty: boxDivClassName
  25. * {String} The CSS class to use for drawing the box. Default is
  26. * olHandlerBoxZoomBox
  27. */
  28. boxDivClassName: 'olHandlerBoxZoomBox',
  29. /**
  30. * Property: boxOffsets
  31. * {Object} Caches box offsets from css. This is used by the getBoxOffsets
  32. * method.
  33. */
  34. boxOffsets: null,
  35. /**
  36. * Constructor: OpenLayers.Handler.Box
  37. *
  38. * Parameters:
  39. * control - {<OpenLayers.Control>}
  40. * callbacks - {Object} An object with a properties whose values are
  41. * functions. Various callbacks described below.
  42. * options - {Object}
  43. *
  44. * Named callbacks:
  45. * start - Called when the box drag operation starts.
  46. * done - Called when the box drag operation is finished.
  47. * The callback should expect to receive a single argument, the box
  48. * bounds or a pixel. If the box dragging didn't span more than a 5
  49. * pixel distance, a pixel will be returned instead of a bounds object.
  50. */
  51. initialize: function(control, callbacks, options) {
  52. OpenLayers.Handler.prototype.initialize.apply(this, arguments);
  53. this.dragHandler = new OpenLayers.Handler.Drag(
  54. this,
  55. {
  56. down: this.startBox,
  57. move: this.moveBox,
  58. out: this.removeBox,
  59. up: this.endBox
  60. },
  61. {keyMask: this.keyMask}
  62. );
  63. },
  64. /**
  65. * Method: destroy
  66. */
  67. destroy: function() {
  68. OpenLayers.Handler.prototype.destroy.apply(this, arguments);
  69. if (this.dragHandler) {
  70. this.dragHandler.destroy();
  71. this.dragHandler = null;
  72. }
  73. },
  74. /**
  75. * Method: setMap
  76. */
  77. setMap: function (map) {
  78. OpenLayers.Handler.prototype.setMap.apply(this, arguments);
  79. if (this.dragHandler) {
  80. this.dragHandler.setMap(map);
  81. }
  82. },
  83. /**
  84. * Method: startBox
  85. *
  86. * Parameters:
  87. * xy - {<OpenLayers.Pixel>}
  88. */
  89. startBox: function (xy) {
  90. this.callback("start", []);
  91. this.zoomBox = OpenLayers.Util.createDiv('zoomBox',
  92. new OpenLayers.Pixel(-9999, -9999));
  93. this.zoomBox.className = this.boxDivClassName;
  94. this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
  95. this.map.eventsDiv.appendChild(this.zoomBox);
  96. OpenLayers.Element.addClass(
  97. this.map.eventsDiv, "olDrawBox"
  98. );
  99. },
  100. /**
  101. * Method: moveBox
  102. */
  103. moveBox: function (xy) {
  104. var startX = this.dragHandler.start.x;
  105. var startY = this.dragHandler.start.y;
  106. var deltaX = Math.abs(startX - xy.x);
  107. var deltaY = Math.abs(startY - xy.y);
  108. var offset = this.getBoxOffsets();
  109. this.zoomBox.style.width = (deltaX + offset.width + 1) + "px";
  110. this.zoomBox.style.height = (deltaY + offset.height + 1) + "px";
  111. this.zoomBox.style.left = (xy.x < startX ?
  112. startX - deltaX - offset.left : startX - offset.left) + "px";
  113. this.zoomBox.style.top = (xy.y < startY ?
  114. startY - deltaY - offset.top : startY - offset.top) + "px";
  115. },
  116. /**
  117. * Method: endBox
  118. */
  119. endBox: function(end) {
  120. var result;
  121. if (Math.abs(this.dragHandler.start.x - end.x) > 5 ||
  122. Math.abs(this.dragHandler.start.y - end.y) > 5) {
  123. var start = this.dragHandler.start;
  124. var top = Math.min(start.y, end.y);
  125. var bottom = Math.max(start.y, end.y);
  126. var left = Math.min(start.x, end.x);
  127. var right = Math.max(start.x, end.x);
  128. result = new OpenLayers.Bounds(left, bottom, right, top);
  129. } else {
  130. result = this.dragHandler.start.clone(); // i.e. OL.Pixel
  131. }
  132. this.removeBox();
  133. this.callback("done", [result]);
  134. },
  135. /**
  136. * Method: removeBox
  137. * Remove the zoombox from the screen and nullify our reference to it.
  138. */
  139. removeBox: function() {
  140. this.map.eventsDiv.removeChild(this.zoomBox);
  141. this.zoomBox = null;
  142. this.boxOffsets = null;
  143. OpenLayers.Element.removeClass(
  144. this.map.eventsDiv, "olDrawBox"
  145. );
  146. },
  147. /**
  148. * Method: activate
  149. */
  150. activate: function () {
  151. if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
  152. this.dragHandler.activate();
  153. return true;
  154. } else {
  155. return false;
  156. }
  157. },
  158. /**
  159. * Method: deactivate
  160. */
  161. deactivate: function () {
  162. if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
  163. if (this.dragHandler.deactivate()) {
  164. if (this.zoomBox) {
  165. this.removeBox();
  166. }
  167. }
  168. return true;
  169. } else {
  170. return false;
  171. }
  172. },
  173. /**
  174. * Method: getBoxOffsets
  175. * Determines border offsets for a box, according to the box model.
  176. *
  177. * Returns:
  178. * {Object} an object with the following offsets:
  179. * - left
  180. * - right
  181. * - top
  182. * - bottom
  183. * - width
  184. * - height
  185. */
  186. getBoxOffsets: function() {
  187. if (!this.boxOffsets) {
  188. // Determine the box model. If the testDiv's clientWidth is 3, then
  189. // the borders are outside and we are dealing with the w3c box
  190. // model. Otherwise, the browser uses the traditional box model and
  191. // the borders are inside the box bounds, leaving us with a
  192. // clientWidth of 1.
  193. var testDiv = document.createElement("div");
  194. //testDiv.style.visibility = "hidden";
  195. testDiv.style.position = "absolute";
  196. testDiv.style.border = "1px solid black";
  197. testDiv.style.width = "3px";
  198. document.body.appendChild(testDiv);
  199. var w3cBoxModel = testDiv.clientWidth == 3;
  200. document.body.removeChild(testDiv);
  201. var left = parseInt(OpenLayers.Element.getStyle(this.zoomBox,
  202. "border-left-width"));
  203. var right = parseInt(OpenLayers.Element.getStyle(
  204. this.zoomBox, "border-right-width"));
  205. var top = parseInt(OpenLayers.Element.getStyle(this.zoomBox,
  206. "border-top-width"));
  207. var bottom = parseInt(OpenLayers.Element.getStyle(
  208. this.zoomBox, "border-bottom-width"));
  209. this.boxOffsets = {
  210. left: left,
  211. right: right,
  212. top: top,
  213. bottom: bottom,
  214. width: w3cBoxModel === false ? left + right : 0,
  215. height: w3cBoxModel === false ? top + bottom : 0
  216. };
  217. }
  218. return this.boxOffsets;
  219. },
  220. CLASS_NAME: "OpenLayers.Handler.Box"
  221. });