[OpenLayers-Commits] r10871 - in trunk/openlayers: build
lib/OpenLayers lib/OpenLayers/Handler tests/manual
commits-20090109 at openlayers.org
commits-20090109 at openlayers.org
Fri Nov 5 08:44:38 EDT 2010
Author: ahocevar
Date: 2010-11-05 05:44:38 -0700 (Fri, 05 Nov 2010)
New Revision: 10871
Added:
trunk/openlayers/tests/manual/page-position.html
Modified:
trunk/openlayers/build/license.txt
trunk/openlayers/lib/OpenLayers/Events.js
trunk/openlayers/lib/OpenLayers/Handler/Drag.js
trunk/openlayers/lib/OpenLayers/Map.js
trunk/openlayers/lib/OpenLayers/Util.js
Log:
Make it so getMousePosition does not report incorrect position when borders are used in containing elements, by replacing the pagePosition method with a new one and attaching map events to the internal viewport div instead of the user provided map div. r=erilem,tschaub (closes #2247)
Modified: trunk/openlayers/build/license.txt
===================================================================
--- trunk/openlayers/build/license.txt 2010-11-05 07:49:12 UTC (rev 10870)
+++ trunk/openlayers/build/license.txt 2010-11-05 12:44:38 UTC (rev 10871)
@@ -90,3 +90,36 @@
* issues. Applications that use the code below will continue to work seamlessly
* when that happens.
*/
+
+/**
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission of Yahoo! Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
\ No newline at end of file
Modified: trunk/openlayers/lib/OpenLayers/Events.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Events.js 2010-11-05 07:49:12 UTC (rev 10870)
+++ trunk/openlayers/lib/OpenLayers/Events.js 2010-11-05 12:44:38 UTC (rev 10871)
@@ -823,11 +823,10 @@
}
if (!this.element.scrolls) {
+ var viewportElement = OpenLayers.Util.getViewportElement();
this.element.scrolls = [
- (document.documentElement.scrollLeft
- || document.body.scrollLeft),
- (document.documentElement.scrollTop
- || document.body.scrollTop)
+ viewportElement.scrollLeft,
+ viewportElement.scrollTop
];
}
@@ -840,8 +839,6 @@
if (!this.element.offsets) {
this.element.offsets = OpenLayers.Util.pagePosition(this.element);
- this.element.offsets[0] += this.element.scrolls[0];
- this.element.offsets[1] += this.element.scrolls[1];
}
return new OpenLayers.Pixel(
(evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]
Modified: trunk/openlayers/lib/OpenLayers/Handler/Drag.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Handler/Drag.js 2010-11-05 07:49:12 UTC (rev 10870)
+++ trunk/openlayers/lib/OpenLayers/Handler/Drag.js 2010-11-05 12:44:38 UTC (rev 10871)
@@ -397,7 +397,7 @@
* evt - {Object}
*/
adjustXY: function(evt) {
- var pos = OpenLayers.Util.pagePosition(this.map.div);
+ var pos = OpenLayers.Util.pagePosition(this.map.viewPortDiv);
evt.xy.x -= pos[0];
evt.xy.y -= pos[1];
},
Modified: trunk/openlayers/lib/OpenLayers/Map.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Map.js 2010-11-05 07:49:12 UTC (rev 10870)
+++ trunk/openlayers/lib/OpenLayers/Map.js 2010-11-05 12:44:38 UTC (rev 10871)
@@ -513,7 +513,7 @@
this.viewPortDiv.appendChild(this.layerContainerDiv);
this.events = new OpenLayers.Events(this,
- this.div,
+ this.viewPortDiv,
this.EVENT_TYPES,
this.fallThrough,
{includeXY: true});
@@ -610,7 +610,6 @@
render: function(div) {
this.div = OpenLayers.Util.getElement(div);
OpenLayers.Element.addClass(this.div, 'olMap');
- this.events.attachToElement(this.div);
this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);
this.div.appendChild(this.viewPortDiv);
this.updateSize();
Modified: trunk/openlayers/lib/OpenLayers/Util.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Util.js 2010-11-05 07:49:12 UTC (rev 10870)
+++ trunk/openlayers/lib/OpenLayers/Util.js 2010-11-05 12:44:38 UTC (rev 10871)
@@ -1336,51 +1336,142 @@
/**
* Function: pagePositon
- * Calculates the position of an element on the page.
+ * Calculates the position of an element on the page (see
+ * http://code.google.com/p/doctype/wiki/ArticlePageOffset)
*
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission of Yahoo! Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
* Parameters:
* forElement - {DOMElement}
*
* Returns:
- * {Array} two item array, L value then T value.
+ * {Array} two item array, Left value then Top value.
*/
-OpenLayers.Util.pagePosition = function(forElement) {
- var valueT = 0, valueL = 0;
+OpenLayers.Util.pagePosition = function(forElement) {
+ // NOTE: If element is hidden (display none or disconnected or any the
+ // ancestors are hidden) we get (0,0) by default but we still do the
+ // accumulation of scroll position.
- var element = forElement;
- var child = forElement;
- while(element) {
+ var pos = [0, 0];
+ var viewportElement = OpenLayers.Util.getViewportElement();
+ if (!forElement || forElement == window || forElement == viewportElement) {
+ // viewport is always at 0,0 as that defined the coordinate system for
+ // this function - this avoids special case checks in the code below
+ return pos;
+ }
- if(element == document.body) {
- if(OpenLayers.Element.getStyle(child, 'position') == 'absolute') {
- break;
+ // Gecko browsers normally use getBoxObjectFor to calculate the position.
+ // When invoked for an element with an implicit absolute position though it
+ // can be off by one. Therefore the recursive implementation is used in
+ // those (relatively rare) cases.
+ var BUGGY_GECKO_BOX_OBJECT =
+ OpenLayers.IS_GECKO && document.getBoxObjectFor &&
+ OpenLayers.Element.getStyle(forElement, 'position') == 'absolute' &&
+ (forElement.style.top == '' || forElement.style.left == '');
+
+ var parent = null;
+ var box;
+
+ if (forElement.getBoundingClientRect) { // IE
+ box = forElement.getBoundingClientRect();
+ var scrollTop = viewportElement.scrollTop;
+ var scrollLeft = viewportElement.scrollLeft;
+
+ pos[0] = box.left + scrollLeft;
+ pos[1] = box.top + scrollTop;
+
+ } else if (document.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT) { // gecko
+ // Gecko ignores the scroll values for ancestors, up to 1.9. See:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=330619
+
+ box = document.getBoxObjectFor(forElement);
+ var vpBox = document.getBoxObjectFor(viewportElement);
+ pos[0] = box.screenX - vpBox.screenX;
+ pos[1] = box.screenY - vpBox.screenY;
+
+ } else { // safari/opera
+ pos[0] = forElement.offsetLeft;
+ pos[1] = forElement.offsetTop;
+ parent = forElement.offsetParent;
+ if (parent != forElement) {
+ while (parent) {
+ pos[0] += parent.offsetLeft;
+ pos[1] += parent.offsetTop;
+ parent = parent.offsetParent;
}
}
-
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- child = element;
- try {
- // wrapping this in a try/catch because IE chokes on the offsetParent
- element = element.offsetParent;
- } catch(e) {
- OpenLayers.Console.error(OpenLayers.i18n(
- "pagePositionFailed",{'elemId':element.id}));
- break;
+ var browser = OpenLayers.BROWSER_NAME;
+
+ // opera & (safari absolute) incorrectly account for body offsetTop
+ if (browser == "opera" || (browser == "safari" &&
+ OpenLayers.Element.getStyle(forElement, 'position') == 'absolute')) {
+ pos[1] -= document.body.offsetTop;
}
- }
- element = forElement;
- while(element) {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- element = element.parentNode;
+ // accumulate the scroll positions for everything but the body element
+ parent = forElement.offsetParent;
+ while (parent && parent != document.body) {
+ pos[0] -= parent.scrollLeft;
+ // see https://bugs.opera.com/show_bug.cgi?id=249965
+ if (browser != "opera" || parent.tagName != 'TR') {
+ pos[1] -= parent.scrollTop;
+ }
+ parent = parent.offsetParent;
+ }
}
- return [valueL, valueT];
+ return pos;
};
+/**
+ * Function: getViewportElement
+ * Returns die viewport element of the document. The viewport element is
+ * usually document.documentElement, except in IE,where it is either
+ * document.body or document.documentElement, depending on the document's
+ * compatibility mode (see
+ * http://code.google.com/p/doctype/wiki/ArticleClientViewportElement)
+ */
+OpenLayers.Util.getViewportElement = function() {
+ var viewportElement = arguments.callee.viewportElement;
+ if (viewportElement == undefined) {
+ viewportElement = (OpenLayers.BROWSER_NAME == "msie" &&
+ document.compatMode != 'CSS1Compat') ? document.body :
+ document.documentElement;
+ arguments.callee.viewportElement = viewportElement;
+ }
+ return viewportElement;
+};
/**
* Function: isEquivalentUrl
Added: trunk/openlayers/tests/manual/page-position.html
===================================================================
--- trunk/openlayers/tests/manual/page-position.html (rev 0)
+++ trunk/openlayers/tests/manual/page-position.html 2010-11-05 12:44:38 UTC (rev 10871)
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Page Position 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">
+ #mapwrap {
+ border: 10px solid red;
+ width: 532px;
+ height: 276px;
+ }
+ #map {
+ position: absolute;
+ border: 10px solid #ccc;
+ width: 512px;
+ height: 256px;
+ }
+ #controlToggle li {
+ list-style: none;
+ }
+ p {
+ width: 512px;
+ }
+ #scrollspace {
+ height: 500px;
+ }
+ </style>
+ <script src="../../lib/OpenLayers.js"></script>
+ <script type="text/javascript">
+ var map, drawControls;
+ function init(){
+ map = new OpenLayers.Map('map');
+
+ var wmsLayer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
+ "http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic'});
+
+ var lineLayer = new OpenLayers.Layer.Vector("Line Layer");
+
+ map.addLayers([wmsLayer, lineLayer]);
+ map.addControl(new OpenLayers.Control.LayerSwitcher());
+ map.addControl(new OpenLayers.Control.MousePosition());
+
+ drawControl = new OpenLayers.Control.DrawFeature(lineLayer,
+ OpenLayers.Handler.Path);
+
+ map.addControl(drawControl);
+
+ map.setCenter(new OpenLayers.LonLat(0, 0), 3);
+
+ document.getElementById('noneToggle').checked = true;
+ }
+
+ function toggleControl(element) {
+ var control = drawControl;
+ if(element.value == "draw" && element.checked) {
+ control.activate();
+ } else {
+ control.deactivate();
+ }
+ }
+ </script>
+ </head>
+ <body onload="init()">
+ <h1 id="title">OpenLayers Page Position Test</h1>
+
+ <p id="shortdesc">
+ Test if borders and scroll position cause unwanted offsets on the
+ mouse positions reported by map events.
+ </p>
+ <div id="mapwrap">
+ <div id="map"></div>
+ </div>
+
+ <ul id="controlToggle">
+ <li>
+ <input type="radio" name="type" value="none" id="noneToggle"
+ onclick="toggleControl(this);" checked="checked" />
+ <label for="noneToggle">navigate</label>
+ </li>
+ <li>
+ <input type="radio" name="type" value="draw" id="lineToggle" onclick="toggleControl(this);" />
+ <label for="lineToggle">draw line</label>
+ </li>
+ </ul>
+
+ <div id="docs">
+ <p>This map's div has a border and absolute positioning, wrapped
+ by a container which also has a border. The page is also
+ scrollable. Neither the borders nor scrolling the page should
+ result in unwanted offsets on pixel positions reported by map
+ events.</p>
+ <p>With the line drawing control active, click on the map to add a
+ point. The point should be drawn at the exact mouse location.</p>
+ <p>With the navigation control active, shift-drag a zoom rectangle.
+ The rectangle's corner should align exactly with the mouse
+ cursor.</p>
+ <p>Scroll the page and repeat the above tests.</p>
+ <div id="scrollspace"><div>
+ </div>
+ </body>
+</html>
More information about the Commits
mailing list