| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916 |
- /* Copyright (c) 2006-2011 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/Util.js
- */
- /**
- * Namespace: OpenLayers.Event
- * Utility functions for event handling.
- */
- OpenLayers.Event = {
- /**
- * Property: observers
- * {Object} A hashtable cache of the event observers. Keyed by
- * element._eventCacheID
- */
- observers: false,
-
- /**
- * Constant: KEY_BACKSPACE
- * {int}
- */
- KEY_BACKSPACE: 8,
- /**
- * Constant: KEY_TAB
- * {int}
- */
- KEY_TAB: 9,
- /**
- * Constant: KEY_RETURN
- * {int}
- */
- KEY_RETURN: 13,
- /**
- * Constant: KEY_ESC
- * {int}
- */
- KEY_ESC: 27,
- /**
- * Constant: KEY_LEFT
- * {int}
- */
- KEY_LEFT: 37,
- /**
- * Constant: KEY_UP
- * {int}
- */
- KEY_UP: 38,
- /**
- * Constant: KEY_RIGHT
- * {int}
- */
- KEY_RIGHT: 39,
- /**
- * Constant: KEY_DOWN
- * {int}
- */
- KEY_DOWN: 40,
- /**
- * Constant: KEY_DELETE
- * {int}
- */
- KEY_DELETE: 46,
- /**
- * Method: element
- * Cross browser event element detection.
- *
- * Parameters:
- * event - {Event}
- *
- * Returns:
- * {DOMElement} The element that caused the event
- */
- element: function(event) {
- return event.target || event.srcElement;
- },
- /**
- * Method: isSingleTouch
- * Determine whether event was caused by a single touch
- *
- * Parameters:
- * event - {Event}
- *
- * Returns:
- * {Boolean}
- */
- isSingleTouch: function(event) {
- return event.touches && event.touches.length == 1;
- },
- /**
- * Method: isMultiTouch
- * Determine whether event was caused by a multi touch
- *
- * Parameters:
- * event - {Event}
- *
- * Returns:
- * {Boolean}
- */
- isMultiTouch: function(event) {
- return event.touches && event.touches.length > 1;
- },
- /**
- * Method: isLeftClick
- * Determine whether event was caused by a left click.
- *
- * Parameters:
- * event - {Event}
- *
- * Returns:
- * {Boolean}
- */
- isLeftClick: function(event) {
- return (((event.which) && (event.which == 1)) ||
- ((event.button) && (event.button == 1)));
- },
- /**
- * Method: isRightClick
- * Determine whether event was caused by a right mouse click.
- *
- * Parameters:
- * event - {Event}
- *
- * Returns:
- * {Boolean}
- */
- isRightClick: function(event) {
- return (((event.which) && (event.which == 3)) ||
- ((event.button) && (event.button == 2)));
- },
-
- /**
- * Method: stop
- * Stops an event from propagating.
- *
- * Parameters:
- * event - {Event}
- * allowDefault - {Boolean} If true, we stop the event chain but
- * still allow the default browser
- * behaviour (text selection, radio-button
- * clicking, etc)
- * Default false
- */
- stop: function(event, allowDefault) {
-
- if (!allowDefault) {
- if (event.preventDefault) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
- }
-
- if (event.stopPropagation) {
- event.stopPropagation();
- } else {
- event.cancelBubble = true;
- }
- },
- /**
- * Method: findElement
- *
- * Parameters:
- * event - {Event}
- * tagName - {String}
- *
- * Returns:
- * {DOMElement} The first node with the given tagName, starting from the
- * node the event was triggered on and traversing the DOM upwards
- */
- findElement: function(event, tagName) {
- var element = OpenLayers.Event.element(event);
- while (element.parentNode && (!element.tagName ||
- (element.tagName.toUpperCase() != tagName.toUpperCase()))){
- element = element.parentNode;
- }
- return element;
- },
- /**
- * Method: observe
- *
- * Parameters:
- * elementParam - {DOMElement || String}
- * name - {String}
- * observer - {function}
- * useCapture - {Boolean}
- */
- observe: function(elementParam, name, observer, useCapture) {
- var element = OpenLayers.Util.getElement(elementParam);
- useCapture = useCapture || false;
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.attachEvent)) {
- name = 'keydown';
- }
- //if observers cache has not yet been created, create it
- if (!this.observers) {
- this.observers = {};
- }
- //if not already assigned, make a new unique cache ID
- if (!element._eventCacheID) {
- var idPrefix = "eventCacheID_";
- if (element.id) {
- idPrefix = element.id + "_" + idPrefix;
- }
- element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);
- }
- var cacheID = element._eventCacheID;
- //if there is not yet a hash entry for this element, add one
- if (!this.observers[cacheID]) {
- this.observers[cacheID] = [];
- }
- //add a new observer to this element's list
- this.observers[cacheID].push({
- 'element': element,
- 'name': name,
- 'observer': observer,
- 'useCapture': useCapture
- });
- //add the actual browser event listener
- if (element.addEventListener) {
- element.addEventListener(name, observer, useCapture);
- } else if (element.attachEvent) {
- element.attachEvent('on' + name, observer);
- }
- },
- /**
- * Method: stopObservingElement
- * Given the id of an element to stop observing, cycle through the
- * element's cached observers, calling stopObserving on each one,
- * skipping those entries which can no longer be removed.
- *
- * parameters:
- * elementParam - {DOMElement || String}
- */
- stopObservingElement: function(elementParam) {
- var element = OpenLayers.Util.getElement(elementParam);
- var cacheID = element._eventCacheID;
- this._removeElementObservers(OpenLayers.Event.observers[cacheID]);
- },
- /**
- * Method: _removeElementObservers
- *
- * Parameters:
- * elementObservers - {Array(Object)} Array of (element, name,
- * observer, usecapture) objects,
- * taken directly from hashtable
- */
- _removeElementObservers: function(elementObservers) {
- if (elementObservers) {
- for(var i = elementObservers.length-1; i >= 0; i--) {
- var entry = elementObservers[i];
- var args = new Array(entry.element,
- entry.name,
- entry.observer,
- entry.useCapture);
- var removed = OpenLayers.Event.stopObserving.apply(this, args);
- }
- }
- },
- /**
- * Method: stopObserving
- *
- * Parameters:
- * elementParam - {DOMElement || String}
- * name - {String}
- * observer - {function}
- * useCapture - {Boolean}
- *
- * Returns:
- * {Boolean} Whether or not the event observer was removed
- */
- stopObserving: function(elementParam, name, observer, useCapture) {
- useCapture = useCapture || false;
-
- var element = OpenLayers.Util.getElement(elementParam);
- var cacheID = element._eventCacheID;
- if (name == 'keypress') {
- if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) ||
- element.detachEvent) {
- name = 'keydown';
- }
- }
- // find element's entry in this.observers cache and remove it
- var foundEntry = false;
- var elementObservers = OpenLayers.Event.observers[cacheID];
- if (elementObservers) {
-
- // find the specific event type in the element's list
- var i=0;
- while(!foundEntry && i < elementObservers.length) {
- var cacheEntry = elementObservers[i];
-
- if ((cacheEntry.name == name) &&
- (cacheEntry.observer == observer) &&
- (cacheEntry.useCapture == useCapture)) {
-
- elementObservers.splice(i, 1);
- if (elementObservers.length == 0) {
- delete OpenLayers.Event.observers[cacheID];
- }
- foundEntry = true;
- break;
- }
- i++;
- }
- }
-
- //actually remove the event listener from browser
- if (foundEntry) {
- if (element.removeEventListener) {
- element.removeEventListener(name, observer, useCapture);
- } else if (element && element.detachEvent) {
- element.detachEvent('on' + name, observer);
- }
- }
- return foundEntry;
- },
-
- /**
- * Method: unloadCache
- * Cycle through all the element entries in the events cache and call
- * stopObservingElement on each.
- */
- unloadCache: function() {
- // check for OpenLayers.Event before checking for observers, because
- // OpenLayers.Event may be undefined in IE if no map instance was
- // created
- if (OpenLayers.Event && OpenLayers.Event.observers) {
- for (var cacheID in OpenLayers.Event.observers) {
- var elementObservers = OpenLayers.Event.observers[cacheID];
- OpenLayers.Event._removeElementObservers.apply(this,
- [elementObservers]);
- }
- OpenLayers.Event.observers = false;
- }
- },
- CLASS_NAME: "OpenLayers.Event"
- };
- /* prevent memory leaks in IE */
- OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);
- // FIXME: Remove this in 3.0. In 3.0, Event.stop will no longer be provided
- // by OpenLayers.
- if (window.Event) {
- OpenLayers.Util.applyDefaults(window.Event, OpenLayers.Event);
- } else {
- var Event = OpenLayers.Event;
- }
- /**
- * Class: OpenLayers.Events
- */
- OpenLayers.Events = OpenLayers.Class({
- /**
- * Constant: BROWSER_EVENTS
- * {Array(String)} supported events
- */
- BROWSER_EVENTS: [
- "mouseover", "mouseout",
- "mousedown", "mouseup", "mousemove",
- "click", "dblclick", "rightclick", "dblrightclick",
- "resize", "focus", "blur",
- "touchstart", "touchmove", "touchend"
- ],
- /**
- * Property: listeners
- * {Object} Hashtable of Array(Function): events listener functions
- */
- listeners: null,
- /**
- * Property: object
- * {Object} the code object issuing application events
- */
- object: null,
- /**
- * Property: element
- * {DOMElement} the DOM element receiving browser events
- */
- element: null,
- /**
- * Property: eventTypes
- * {Array(String)} list of support application events
- */
- eventTypes: null,
- /**
- * Property: eventHandler
- * {Function} bound event handler attached to elements
- */
- eventHandler: null,
- /**
- * APIProperty: fallThrough
- * {Boolean}
- */
- fallThrough: null,
- /**
- * APIProperty: includeXY
- * {Boolean} Should the .xy property automatically be created for browser
- * mouse events? In general, this should be false. If it is true, then
- * mouse events will automatically generate a '.xy' property on the
- * event object that is passed. (Prior to OpenLayers 2.7, this was true
- * by default.) Otherwise, you can call the getMousePosition on the
- * relevant events handler on the object available via the 'evt.object'
- * property of the evt object. So, for most events, you can call:
- * function named(evt) {
- * this.xy = this.object.events.getMousePosition(evt)
- * }
- *
- * This option typically defaults to false for performance reasons:
- * when creating an events object whose primary purpose is to manage
- * relatively positioned mouse events within a div, it may make
- * sense to set it to true.
- *
- * This option is also used to control whether the events object caches
- * offsets. If this is false, it will not: the reason for this is that
- * it is only expected to be called many times if the includeXY property
- * is set to true. If you set this to true, you are expected to clear
- * the offset cache manually (using this.clearMouseCache()) if:
- * the border of the element changes
- * the location of the element in the page changes
- */
- includeXY: false,
- /**
- * Method: clearMouseListener
- * A version of <clearMouseCache> that is bound to this instance so that
- * it can be used with <OpenLayers.Event.observe> and
- * <OpenLayers.Event.stopObserving>.
- */
- clearMouseListener: null,
- /**
- * Constructor: OpenLayers.Events
- * Construct an OpenLayers.Events object.
- *
- * Parameters:
- * object - {Object} The js object to which this Events object is being added
- * element - {DOMElement} A dom element to respond to browser events
- * eventTypes - {Array(String)} Array of custom application events
- * fallThrough - {Boolean} Allow events to fall through after these have
- * been handled?
- * options - {Object} Options for the events object.
- */
- initialize: function (object, element, eventTypes, fallThrough, options) {
- OpenLayers.Util.extend(this, options);
- this.object = object;
- this.fallThrough = fallThrough;
- this.listeners = {};
- // keep a bound copy of handleBrowserEvent() so that we can
- // pass the same function to both Event.observe() and .stopObserving()
- this.eventHandler = OpenLayers.Function.bindAsEventListener(
- this.handleBrowserEvent, this
- );
-
- // to be used with observe and stopObserving
- this.clearMouseListener = OpenLayers.Function.bind(
- this.clearMouseCache, this
- );
- // if eventTypes is specified, create a listeners list for each
- // custom application event.
- this.eventTypes = [];
- if (eventTypes != null) {
- for (var i=0, len=eventTypes.length; i<len; i++) {
- this.addEventType(eventTypes[i]);
- }
- }
-
- // if a dom element is specified, add a listeners list
- // for browser events on the element and register them
- if (element != null) {
- this.attachToElement(element);
- }
- },
- /**
- * APIMethod: destroy
- */
- destroy: function () {
- if (this.element) {
- OpenLayers.Event.stopObservingElement(this.element);
- if(this.element.hasScrollEvent) {
- OpenLayers.Event.stopObserving(
- window, "scroll", this.clearMouseListener
- );
- }
- }
- this.element = null;
- this.listeners = null;
- this.object = null;
- this.eventTypes = null;
- this.fallThrough = null;
- this.eventHandler = null;
- },
- /**
- * APIMethod: addEventType
- * Add a new event type to this events object.
- * If the event type has already been added, do nothing.
- *
- * Parameters:
- * eventName - {String}
- */
- addEventType: function(eventName) {
- if (!this.listeners[eventName]) {
- this.eventTypes.push(eventName);
- this.listeners[eventName] = [];
- }
- },
- /**
- * Method: attachToElement
- *
- * Parameters:
- * element - {HTMLDOMElement} a DOM element to attach browser events to
- */
- attachToElement: function (element) {
- if(this.element) {
- OpenLayers.Event.stopObservingElement(this.element);
- }
- this.element = element;
- for (var i=0, len=this.BROWSER_EVENTS.length; i<len; i++) {
- var eventType = this.BROWSER_EVENTS[i];
- // every browser event has a corresponding application event
- // (whether it's listened for or not).
- this.addEventType(eventType);
-
- // use Prototype to register the event cross-browser
- OpenLayers.Event.observe(element, eventType, this.eventHandler);
- }
- // disable dragstart in IE so that mousedown/move/up works normally
- OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop);
- },
-
- /**
- * APIMethod: on
- * Convenience method for registering listeners with a common scope.
- * Internally, this method calls <register> as shown in the examples
- * below.
- *
- * Example use:
- * (code)
- * // register a single listener for the "loadstart" event
- * events.on({"loadstart": loadStartListener});
- *
- * // this is equivalent to the following
- * events.register("loadstart", undefined, loadStartListener);
- *
- * // register multiple listeners to be called with the same `this` object
- * events.on({
- * "loadstart": loadStartListener,
- * "loadend": loadEndListener,
- * scope: object
- * });
- *
- * // this is equivalent to the following
- * events.register("loadstart", object, loadStartListener);
- * events.register("loadend", object, loadEndListener);
- * (end)
- *
- * Parameters:
- * object - {Object}
- */
- on: function(object) {
- for(var type in object) {
- if(type != "scope") {
- this.register(type, object.scope, object[type]);
- }
- }
- },
- /**
- * APIMethod: register
- * Register an event on the events object.
- *
- * When the event is triggered, the 'func' function will be called, in the
- * context of 'obj'. Imagine we were to register an event, specifying an
- * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the
- * context in the callback function will be our Bounds object. This means
- * that within our callback function, we can access the properties and
- * methods of the Bounds object through the "this" variable. So our
- * callback could execute something like:
- * : leftStr = "Left: " + this.left;
- *
- * or
- *
- * : centerStr = "Center: " + this.getCenterLonLat();
- *
- * Parameters:
- * type - {String} Name of the event to register
- * obj - {Object} The object to bind the context to for the callback#.
- * If no object is specified, default is the Events's
- * 'object' property.
- * func - {Function} The callback function. If no callback is
- * specified, this function does nothing.
- *
- *
- */
- register: function (type, obj, func) {
- if ( (func != null) &&
- (OpenLayers.Util.indexOf(this.eventTypes, type) != -1) ) {
- if (obj == null) {
- obj = this.object;
- }
- var listeners = this.listeners[type];
- listeners.push( {obj: obj, func: func} );
- }
- },
- /**
- * APIMethod: registerPriority
- * Same as register() but adds the new listener to the *front* of the
- * events queue instead of to the end.
- *
- * TODO: get rid of this in 3.0 - Decide whether listeners should be
- * called in the order they were registered or in reverse order.
- *
- *
- * Parameters:
- * type - {String} Name of the event to register
- * obj - {Object} The object to bind the context to for the callback#.
- * If no object is specified, default is the Events's
- * 'object' property.
- * func - {Function} The callback function. If no callback is
- * specified, this function does nothing.
- */
- registerPriority: function (type, obj, func) {
- if (func != null) {
- if (obj == null) {
- obj = this.object;
- }
- var listeners = this.listeners[type];
- if (listeners != null) {
- listeners.unshift( {obj: obj, func: func} );
- }
- }
- },
-
- /**
- * APIMethod: un
- * Convenience method for unregistering listeners with a common scope.
- * Internally, this method calls <unregister> as shown in the examples
- * below.
- *
- * Example use:
- * (code)
- * // unregister a single listener for the "loadstart" event
- * events.un({"loadstart": loadStartListener});
- *
- * // this is equivalent to the following
- * events.unregister("loadstart", undefined, loadStartListener);
- *
- * // unregister multiple listeners with the same `this` object
- * events.un({
- * "loadstart": loadStartListener,
- * "loadend": loadEndListener,
- * scope: object
- * });
- *
- * // this is equivalent to the following
- * events.unregister("loadstart", object, loadStartListener);
- * events.unregister("loadend", object, loadEndListener);
- * (end)
- */
- un: function(object) {
- for(var type in object) {
- if(type != "scope") {
- this.unregister(type, object.scope, object[type]);
- }
- }
- },
- /**
- * APIMethod: unregister
- *
- * Parameters:
- * type - {String}
- * obj - {Object} If none specified, defaults to this.object
- * func - {Function}
- */
- unregister: function (type, obj, func) {
- if (obj == null) {
- obj = this.object;
- }
- var listeners = this.listeners[type];
- if (listeners != null) {
- for (var i=0, len=listeners.length; i<len; i++) {
- if (listeners[i].obj == obj && listeners[i].func == func) {
- listeners.splice(i, 1);
- break;
- }
- }
- }
- },
- /**
- * Method: remove
- * Remove all listeners for a given event type. If type is not registered,
- * does nothing.
- *
- * Parameters:
- * type - {String}
- */
- remove: function(type) {
- if (this.listeners[type] != null) {
- this.listeners[type] = [];
- }
- },
- /**
- * APIMethod: triggerEvent
- * Trigger a specified registered event.
- *
- * Parameters:
- * type - {String}
- * evt - {Event}
- *
- * Returns:
- * {Boolean} The last listener return. If a listener returns false, the
- * chain of listeners will stop getting called.
- */
- triggerEvent: function (type, evt) {
- var listeners = this.listeners[type];
- // fast path
- if(!listeners || listeners.length == 0) {
- return undefined;
- }
- // prep evt object with object & div references
- if (evt == null) {
- evt = {};
- }
- evt.object = this.object;
- evt.element = this.element;
- if(!evt.type) {
- evt.type = type;
- }
-
- // execute all callbacks registered for specified type
- // get a clone of the listeners array to
- // allow for splicing during callbacks
- listeners = listeners.slice();
- var continueChain;
- for (var i=0, len=listeners.length; i<len; i++) {
- var callback = listeners[i];
- // bind the context to callback.obj
- continueChain = callback.func.apply(callback.obj, [evt]);
- if ((continueChain != undefined) && (continueChain == false)) {
- // if callback returns false, execute no more callbacks.
- break;
- }
- }
- // don't fall through to other DOM elements
- if (!this.fallThrough) {
- OpenLayers.Event.stop(evt, true);
- }
- return continueChain;
- },
- /**
- * Method: handleBrowserEvent
- * Basically just a wrapper to the triggerEvent() function, but takes
- * care to set a property 'xy' on the event with the current mouse
- * position.
- *
- * Parameters:
- * evt - {Event}
- */
- handleBrowserEvent: function (evt) {
- var type = evt.type, listeners = this.listeners[type];
- if(!listeners || listeners.length == 0) {
- // noone's listening, bail out
- return;
- }
- // add clientX & clientY to all events - corresponds to average x, y
- var touches = evt.touches;
- if (touches && touches[0]) {
- var x = 0;
- var y = 0;
- var num = touches.length;
- var touch;
- for (var i=0; i<num; ++i) {
- touch = touches[i];
- x += touch.clientX;
- y += touch.clientY;
- }
- evt.clientX = x / num;
- evt.clientY = y / num;
- }
- if (this.includeXY) {
- evt.xy = this.getMousePosition(evt);
- }
- this.triggerEvent(type, evt);
- },
- /**
- * APIMethod: clearMouseCache
- * Clear cached data about the mouse position. This should be called any
- * time the element that events are registered on changes position
- * within the page.
- */
- clearMouseCache: function() {
- this.element.scrolls = null;
- this.element.lefttop = null;
- // OpenLayers.Util.pagePosition needs to use
- // element.getBoundingClientRect to correctly calculate the offsets
- // for the iPhone, but once the page is scrolled, getBoundingClientRect
- // returns incorrect offsets. So our best bet is to not invalidate the
- // offsets once we have them, and hope that the page was not scrolled
- // when we did the initial calculation.
- var body = document.body;
- if (body && !((body.scrollTop != 0 || body.scrollLeft != 0) &&
- navigator.userAgent.match(/iPhone/i))) {
- this.element.offsets = null;
- }
- },
- /**
- * Method: getMousePosition
- *
- * Parameters:
- * evt - {Event}
- *
- * Returns:
- * {<OpenLayers.Pixel>} The current xy coordinate of the mouse, adjusted
- * for offsets
- */
- getMousePosition: function (evt) {
- if (!this.includeXY) {
- this.clearMouseCache();
- } else if (!this.element.hasScrollEvent) {
- OpenLayers.Event.observe(window, "scroll", this.clearMouseListener);
- this.element.hasScrollEvent = true;
- }
-
- if (!this.element.scrolls) {
- var viewportElement = OpenLayers.Util.getViewportElement();
- this.element.scrolls = [
- viewportElement.scrollLeft,
- viewportElement.scrollTop
- ];
- }
- if (!this.element.lefttop) {
- this.element.lefttop = [
- (document.documentElement.clientLeft || 0),
- (document.documentElement.clientTop || 0)
- ];
- }
-
- if (!this.element.offsets) {
- this.element.offsets = OpenLayers.Util.pagePosition(this.element);
- }
- return new OpenLayers.Pixel(
- (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]
- - this.element.lefttop[0],
- (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1]
- - this.element.lefttop[1]
- );
- },
- CLASS_NAME: "OpenLayers.Events"
- });
|