fixed box sizing and positioning. r=sbrunner (closes #2910)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@11749 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
ahocevar
2011-03-29 13:44:04 +00:00
parent 54b58e3faf
commit c5dfe37bd4
4 changed files with 204 additions and 48 deletions

View File

@@ -32,11 +32,11 @@ OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, {
boxDivClassName: 'olHandlerBoxZoomBox', boxDivClassName: 'olHandlerBoxZoomBox',
/** /**
* Property: boxCharacteristics * Property: boxOffsets
* {Object} Caches some box characteristics from css. This is used * {Object} Caches box offsets from css. This is used by the getBoxOffsets
* by the getBoxCharacteristics method. * method.
*/ */
boxCharacteristics: null, boxOffsets: null,
/** /**
* Constructor: OpenLayers.Handler.Box * Constructor: OpenLayers.Handler.Box
@@ -96,8 +96,14 @@ OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, {
new OpenLayers.Pixel(-9999, -9999)); new OpenLayers.Pixel(-9999, -9999));
this.zoomBox.className = this.boxDivClassName; this.zoomBox.className = this.boxDivClassName;
this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
this.map.eventsDiv.appendChild(this.zoomBox); this.map.eventsDiv.appendChild(this.zoomBox);
var offset = this.getBoxOffsets();
var pos = this.dragHandler.start;
this.zoomBox.style.left = (pos.x - offset.left) + "px";
this.zoomBox.style.top = (pos.y - offset.top) + "px";
OpenLayers.Element.addClass( OpenLayers.Element.addClass(
this.map.eventsDiv, "olDrawBox" this.map.eventsDiv, "olDrawBox"
); );
@@ -111,24 +117,14 @@ OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, {
var startY = this.dragHandler.start.y; var startY = this.dragHandler.start.y;
var deltaX = Math.abs(startX - xy.x); var deltaX = Math.abs(startX - xy.x);
var deltaY = Math.abs(startY - xy.y); 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 var offset = this.getBoxOffsets();
// of the box into account this.zoomBox.style.width = (deltaX + offset.width + 1) + "px";
var box = this.getBoxCharacteristics(); this.zoomBox.style.height = (deltaY + offset.height + 1) + "px";
if (box.newBoxModel) { this.zoomBox.style.left = (xy.x < startX ?
if (xy.x > startX) { startX - deltaX - offset.left : startX - offset.left) + "px";
this.zoomBox.style.width = this.zoomBox.style.top = (xy.y < startY ?
Math.max(1, deltaX - box.xOffset) + "px"; startY - deltaY - offset.top : startY - offset.top) + "px";
}
if (xy.y > startY) {
this.zoomBox.style.height =
Math.max(1, deltaY - box.yOffset) + "px";
}
}
}, },
/** /**
@@ -159,7 +155,7 @@ OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, {
removeBox: function() { removeBox: function() {
this.map.eventsDiv.removeChild(this.zoomBox); this.map.eventsDiv.removeChild(this.zoomBox);
this.zoomBox = null; this.zoomBox = null;
this.boxCharacteristics = null; this.boxOffsets = null;
OpenLayers.Element.removeClass( OpenLayers.Element.removeClass(
this.map.eventsDiv, "olDrawBox" this.map.eventsDiv, "olDrawBox"
); );
@@ -195,33 +191,52 @@ OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, {
}, },
/** /**
* Method: getCharacteristics * Method: getBoxOffsets
* Determines offset and box model for a box. * Determines border offsets for a box, according to the box model.
* *
* Returns: * Returns:
* {Object} a hash with the following properties: * {Object} an object with the following offsets:
* - xOffset - Corner offset in x-direction * - left
* - yOffset - Corner offset in y-direction * - right
* - newBoxModel - true for all browsers except IE in quirks mode * - top
* - bottom
* - width
* - height
*/ */
getBoxCharacteristics: function() { getBoxOffsets: function() {
if (!this.boxCharacteristics) { if (!this.boxOffsets) {
var xOffset = parseInt(OpenLayers.Element.getStyle(this.zoomBox, // Determine the box model. If the testDiv's clientWidth is 3, then
"border-left-width")) + parseInt(OpenLayers.Element.getStyle( // the borders are outside and we are dealing with the w3c box
this.zoomBox, "border-right-width")) + 1; // model. Otherwise, the browser uses the traditional box model and
var yOffset = parseInt(OpenLayers.Element.getStyle(this.zoomBox, // the borders are inside the box bounds, leaving us with a
"border-top-width")) + parseInt(OpenLayers.Element.getStyle( // clientWidth of 1.
this.zoomBox, "border-bottom-width")) + 1; var testDiv = document.createElement("div");
// all browsers use the new box model, except IE in quirks mode testDiv.style.visibility = "hidden";
var newBoxModel = OpenLayers.BROWSER_NAME == "msie" ? testDiv.style.position = "absolute";
document.compatMode != "BackCompat" : true; testDiv.style.border = "1px solid black";
this.boxCharacteristics = { testDiv.style.width = "3px";
xOffset: xOffset, document.body.appendChild(testDiv);
yOffset: yOffset, var w3cBoxModel = testDiv.clientWidth == 3;
newBoxModel: newBoxModel document.body.removeChild(testDiv);
};
} var left = parseInt(OpenLayers.Element.getStyle(this.zoomBox,
return this.boxCharacteristics; "border-left-width"));
var right = parseInt(OpenLayers.Element.getStyle(
this.zoomBox, "border-right-width"));
var top = parseInt(OpenLayers.Element.getStyle(this.zoomBox,
"border-top-width"));
var bottom = parseInt(OpenLayers.Element.getStyle(
this.zoomBox, "border-bottom-width"));
this.boxOffsets = {
left: left,
right: right,
top: top,
bottom: bottom,
width: w3cBoxModel === false ? left + right : 0,
height: w3cBoxModel === false ? top + bottom : 0
};
}
return this.boxOffsets;
}, },
CLASS_NAME: "OpenLayers.Handler.Box" CLASS_NAME: "OpenLayers.Handler.Box"

View File

@@ -2,6 +2,49 @@
<head> <head>
<script src="../OLLoader.js"></script> <script src="../OLLoader.js"></script>
<script type="text/javascript"> <script type="text/javascript">
function test_Handler_Box_constructor(t) {
t.plan(4);
var control = new OpenLayers.Control();
control.id = Math.random();
var callbacks = {done: "bar"};
var options = {bar: "foo"};
var handler = new OpenLayers.Handler.Box(control, callbacks, options);
t.eq(handler.control.id, control.id, "handler created with the correct control");
t.eq(handler.callbacks.done, "bar", "handler created with the correct callback");
t.eq(handler.bar, "foo", "handler created with the correct options");
t.ok(handler.dragHandler instanceof OpenLayers.Handler.Drag, "drag handler created");
}
function test_Handler_Box_draw(t) {
t.plan(12);
var map = new OpenLayers.Map('map');
var control = new OpenLayers.Control();
map.addControl(control);
var handler = new OpenLayers.Handler.Box(control, {done: function(e) {
t.ok(e.equals(new OpenLayers.Bounds(5, 11, 11, 5)), "box result correct");
}});
handler.activate();
handler.dragHandler.start = {x: 5, y: 5};
handler.startBox({x: 5, y: 5});
var offset = handler.getBoxOffsets();
t.eq(parseInt(handler.zoomBox.style.left), 5 - offset.left, "x position of box correct");
t.eq(parseInt(handler.zoomBox.style.top), 5 - offset.top, "y position of box correct");
handler.moveBox({x: 10, y: 10});
t.eq(parseInt(handler.zoomBox.style.left), 5 - offset.left, "x position of box still correct");
t.eq(parseInt(handler.zoomBox.style.top), 5 - offset.top, "y position of box still correct");
t.eq(parseInt(handler.zoomBox.style.width), 5 + offset.width + 1, "x dimension of box correct");
t.eq(parseInt(handler.zoomBox.style.height), 5 + offset.height + 1, "y dimension of box correct");
handler.moveBox({x: 0, y: 0});
t.eq(parseInt(handler.zoomBox.style.left), 0 - offset.left, "new x position of box correct");
t.eq(parseInt(handler.zoomBox.style.top), 0 - offset.top, "new y position of box correct");
t.eq(parseInt(handler.zoomBox.style.width), 5 + offset.width + 1, "x dimension of box still correct");
t.eq(parseInt(handler.zoomBox.style.height), 5 + offset.height + 1, "y dimension of box still correct");
handler.endBox({x: 11, y: 11});
t.eq(handler.zoomBox, null, "box removed after endBox");
}
function test_Handler_Box_destroy(t) { function test_Handler_Box_destroy(t) {
t.plan(1); t.plan(1);
var map = new OpenLayers.Map('map'); var map = new OpenLayers.Map('map');
@@ -21,6 +64,6 @@
</script> </script>
</head> </head>
<body> <body>
<div id="map" style="width: 300px; height: 150px;"/> <div id="map" style="width: 300px; height: 150px;"></div>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,52 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Box Handler Quirks Mode Test</title>
<link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
<link rel="stylesheet" href="../../examples/style.css" type="text/css" />
<style type="text/css">
/* simulate quirks mode (traditional box model) in browsers other than IE */
div {
box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.olHandlerBoxZoomBox {
border: 20px solid red;
border-left-width: 10px;
border-bottom-width: 30px;
}
</style>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var map, layer;
function init(){
map = new OpenLayers.Map( 'map' );
layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{layers: 'basic'} );
map.addLayer(layer);
map.zoomToMaxExtent();
}
</script>
</head>
<body onload="init()">
<h1 id="title">Box handler Quirks Mode Test</h1>
<div id="shortdesc">Test the correct appearance of the ZoomBox in quirks mode</div>
<div id="map" class="smallmap"></div>
<div id="docs">
<p>For the box to be positioned correctly, we need to know the
width of the borders.</p>
<p>Shift-click on the map. A red box should be visible around the mouse
cursor position, with 20 pixels to the top and right, 10 pixels to
the left and 30 pixels to the bottom edge of the box.</p>
<p>Drag the box both to the top-left and the bottom-right. The cursor
should always be at the top-left or bottom-right inner corner of
the box.</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Box Handler Strict Mode Test</title>
<link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
<link rel="stylesheet" href="../../examples/style.css" type="text/css" />
<style type="text/css">
.olHandlerBoxZoomBox {
border: 20px solid red;
border-left-width: 10px;
border-bottom-width: 30px;
}
</style>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var map, layer;
function init(){
map = new OpenLayers.Map( 'map' );
layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{layers: 'basic'} );
map.addLayer(layer);
map.zoomToMaxExtent();
}
</script>
</head>
<body onload="init()">
<h1 id="title">Box Handler Strict Mode Test</h1>
<div id="shortdesc">Test the correct appearance of the ZoomBox in strict mode</div>
<div id="map" class="smallmap"></div>
<div id="docs">
<p>For the box to be positioned correctly, we need to know the
width of the borders.</p>
<p>Shift-click on the map. A red box should be visible around the mouse
cursor position, with 20 pixels to the top and right, 10 pixels to
the left and 30 pixels to the bottom edge of the box.</p>
<p>Drag the box both to the top-left and the bottom-right. The cursor
should always be at the top-left or bottom-right inner corner of
the box.</p>
</div>
</body>
</html>