Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-routing-foss4g/web/OpenLayers/lib/OpenLayers/Events.js @ 76

Revision 76, 25.9 KB checked in by djay, 12 years ago (diff)

Ajout du répertoire web

  • Property svn:executable set to *
Line 
1/* Copyright (c) 2006-2010 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
7/**
8 * @requires OpenLayers/Util.js
9 */
10
11/**
12 * Namespace: OpenLayers.Event
13 * Utility functions for event handling.
14 */
15OpenLayers.Event = {
16
17    /**
18     * Property: observers
19     * {Object} A hashtable cache of the event observers. Keyed by
20     * element._eventCacheID
21     */
22    observers: false,
23   
24    /**
25     * Constant: KEY_BACKSPACE
26     * {int}
27     */
28    KEY_BACKSPACE: 8,
29
30    /**
31     * Constant: KEY_TAB
32     * {int}
33     */
34    KEY_TAB: 9,
35
36    /**
37     * Constant: KEY_RETURN
38     * {int}
39     */
40    KEY_RETURN: 13,
41
42    /**
43     * Constant: KEY_ESC
44     * {int}
45     */
46    KEY_ESC: 27,
47
48    /**
49     * Constant: KEY_LEFT
50     * {int}
51     */
52    KEY_LEFT: 37,
53
54    /**
55     * Constant: KEY_UP
56     * {int}
57     */
58    KEY_UP: 38,
59
60    /**
61     * Constant: KEY_RIGHT
62     * {int}
63     */
64    KEY_RIGHT: 39,
65
66    /**
67     * Constant: KEY_DOWN
68     * {int}
69     */
70    KEY_DOWN: 40,
71
72    /**
73     * Constant: KEY_DELETE
74     * {int}
75     */
76    KEY_DELETE: 46,
77
78
79    /**
80     * Method: element
81     * Cross browser event element detection.
82     *
83     * Parameters:
84     * event - {Event}
85     *
86     * Returns:
87     * {DOMElement} The element that caused the event
88     */
89    element: function(event) {
90        return event.target || event.srcElement;
91    },
92
93    /**
94     * Method: isLeftClick
95     * Determine whether event was caused by a left click.
96     *
97     * Parameters:
98     * event - {Event}
99     *
100     * Returns:
101     * {Boolean}
102     */
103    isLeftClick: function(event) {
104        return (((event.which) && (event.which == 1)) ||
105                ((event.button) && (event.button == 1)));
106    },
107
108    /**
109     * Method: isRightClick
110     * Determine whether event was caused by a right mouse click.
111     *
112     * Parameters:
113     * event - {Event}
114     *
115     * Returns:
116     * {Boolean}
117     */
118     isRightClick: function(event) {
119        return (((event.which) && (event.which == 3)) ||
120                ((event.button) && (event.button == 2)));
121    },
122     
123    /**
124     * Method: stop
125     * Stops an event from propagating.
126     *
127     * Parameters:
128     * event - {Event}
129     * allowDefault - {Boolean} If true, we stop the event chain but
130     *                               still allow the default browser
131     *                               behaviour (text selection, radio-button
132     *                               clicking, etc)
133     *                               Default false
134     */
135    stop: function(event, allowDefault) {
136       
137        if (!allowDefault) { 
138            if (event.preventDefault) {
139                event.preventDefault();
140            } else {
141                event.returnValue = false;
142            }
143        }
144               
145        if (event.stopPropagation) {
146            event.stopPropagation();
147        } else {
148            event.cancelBubble = true;
149        }
150    },
151
152    /**
153     * Method: findElement
154     *
155     * Parameters:
156     * event - {Event}
157     * tagName - {String}
158     *
159     * Returns:
160     * {DOMElement} The first node with the given tagName, starting from the
161     * node the event was triggered on and traversing the DOM upwards
162     */
163    findElement: function(event, tagName) {
164        var element = OpenLayers.Event.element(event);
165        while (element.parentNode && (!element.tagName ||
166              (element.tagName.toUpperCase() != tagName.toUpperCase()))){
167            element = element.parentNode;
168        }
169        return element;
170    },
171
172    /**
173     * Method: observe
174     *
175     * Parameters:
176     * elementParam - {DOMElement || String}
177     * name - {String}
178     * observer - {function}
179     * useCapture - {Boolean}
180     */
181    observe: function(elementParam, name, observer, useCapture) {
182        var element = OpenLayers.Util.getElement(elementParam);
183        useCapture = useCapture || false;
184
185        if (name == 'keypress' &&
186           (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
187           || element.attachEvent)) {
188            name = 'keydown';
189        }
190
191        //if observers cache has not yet been created, create it
192        if (!this.observers) {
193            this.observers = {};
194        }
195
196        //if not already assigned, make a new unique cache ID
197        if (!element._eventCacheID) {
198            var idPrefix = "eventCacheID_";
199            if (element.id) {
200                idPrefix = element.id + "_" + idPrefix;
201            }
202            element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);
203        }
204
205        var cacheID = element._eventCacheID;
206
207        //if there is not yet a hash entry for this element, add one
208        if (!this.observers[cacheID]) {
209            this.observers[cacheID] = [];
210        }
211
212        //add a new observer to this element's list
213        this.observers[cacheID].push({
214            'element': element,
215            'name': name,
216            'observer': observer,
217            'useCapture': useCapture
218        });
219
220        //add the actual browser event listener
221        if (element.addEventListener) {
222            element.addEventListener(name, observer, useCapture);
223        } else if (element.attachEvent) {
224            element.attachEvent('on' + name, observer);
225        }
226    },
227
228    /**
229     * Method: stopObservingElement
230     * Given the id of an element to stop observing, cycle through the
231     *   element's cached observers, calling stopObserving on each one,
232     *   skipping those entries which can no longer be removed.
233     *
234     * parameters:
235     * elementParam - {DOMElement || String}
236     */
237    stopObservingElement: function(elementParam) {
238        var element = OpenLayers.Util.getElement(elementParam);
239        var cacheID = element._eventCacheID;
240
241        this._removeElementObservers(OpenLayers.Event.observers[cacheID]);
242    },
243
244    /**
245     * Method: _removeElementObservers
246     *
247     * Parameters:
248     * elementObservers - {Array(Object)} Array of (element, name,
249     *                                         observer, usecapture) objects,
250     *                                         taken directly from hashtable
251     */
252    _removeElementObservers: function(elementObservers) {
253        if (elementObservers) {
254            for(var i = elementObservers.length-1; i >= 0; i--) {
255                var entry = elementObservers[i];
256                var args = new Array(entry.element,
257                                     entry.name,
258                                     entry.observer,
259                                     entry.useCapture);
260                var removed = OpenLayers.Event.stopObserving.apply(this, args);
261            }
262        }
263    },
264
265    /**
266     * Method: stopObserving
267     *
268     * Parameters:
269     * elementParam - {DOMElement || String}
270     * name - {String}
271     * observer - {function}
272     * useCapture - {Boolean}
273     * 
274     * Returns:
275     * {Boolean} Whether or not the event observer was removed
276     */
277    stopObserving: function(elementParam, name, observer, useCapture) {
278        useCapture = useCapture || false;
279   
280        var element = OpenLayers.Util.getElement(elementParam);
281        var cacheID = element._eventCacheID;
282
283        if (name == 'keypress') {
284            if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) || 
285                 element.detachEvent) {
286              name = 'keydown';
287            }
288        }
289
290        // find element's entry in this.observers cache and remove it
291        var foundEntry = false;
292        var elementObservers = OpenLayers.Event.observers[cacheID];
293        if (elementObservers) {
294   
295            // find the specific event type in the element's list
296            var i=0;
297            while(!foundEntry && i < elementObservers.length) {
298                var cacheEntry = elementObservers[i];
299   
300                if ((cacheEntry.name == name) &&
301                    (cacheEntry.observer == observer) &&
302                    (cacheEntry.useCapture == useCapture)) {
303   
304                    elementObservers.splice(i, 1);
305                    if (elementObservers.length == 0) {
306                        delete OpenLayers.Event.observers[cacheID];
307                    }
308                    foundEntry = true;
309                    break; 
310                }
311                i++;           
312            }
313        }
314   
315        //actually remove the event listener from browser
316        if (foundEntry) {
317            if (element.removeEventListener) {
318                element.removeEventListener(name, observer, useCapture);
319            } else if (element && element.detachEvent) {
320                element.detachEvent('on' + name, observer);
321            }
322        }
323        return foundEntry;
324    },
325   
326    /**
327     * Method: unloadCache
328     * Cycle through all the element entries in the events cache and call
329     *   stopObservingElement on each.
330     */
331    unloadCache: function() {
332        // check for OpenLayers.Event before checking for observers, because
333        // OpenLayers.Event may be undefined in IE if no map instance was
334        // created
335        if (OpenLayers.Event && OpenLayers.Event.observers) {
336            for (var cacheID in OpenLayers.Event.observers) {
337                var elementObservers = OpenLayers.Event.observers[cacheID];
338                OpenLayers.Event._removeElementObservers.apply(this, 
339                                                           [elementObservers]);
340            }
341            OpenLayers.Event.observers = false;
342        }
343    },
344
345    CLASS_NAME: "OpenLayers.Event"
346};
347
348/* prevent memory leaks in IE */
349OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);
350
351// FIXME: Remove this in 3.0. In 3.0, Event.stop will no longer be provided
352// by OpenLayers.
353if (window.Event) {
354    OpenLayers.Util.applyDefaults(window.Event, OpenLayers.Event);
355} else {
356    var Event = OpenLayers.Event;
357}
358
359/**
360 * Class: OpenLayers.Events
361 */
362OpenLayers.Events = OpenLayers.Class({
363
364    /**
365     * Constant: BROWSER_EVENTS
366     * {Array(String)} supported events
367     */
368    BROWSER_EVENTS: [
369        "mouseover", "mouseout",
370        "mousedown", "mouseup", "mousemove", 
371        "click", "dblclick", "rightclick", "dblrightclick",
372        "resize", "focus", "blur"
373    ],
374
375    /**
376     * Property: listeners
377     * {Object} Hashtable of Array(Function): events listener functions 
378     */
379    listeners: null,
380
381    /**
382     * Property: object
383     * {Object}  the code object issuing application events
384     */
385    object: null,
386
387    /**
388     * Property: element
389     * {DOMElement}  the DOM element receiving browser events
390     */
391    element: null,
392
393    /**
394     * Property: eventTypes
395     * {Array(String)}  list of support application events
396     */
397    eventTypes: null,
398
399    /**
400     * Property: eventHandler
401     * {Function}  bound event handler attached to elements
402     */
403    eventHandler: null,
404
405    /**
406     * APIProperty: fallThrough
407     * {Boolean}
408     */
409    fallThrough: null,
410
411    /**
412     * APIProperty: includeXY
413     * {Boolean} Should the .xy property automatically be created for browser
414     *    mouse events? In general, this should be false. If it is true, then
415     *    mouse events will automatically generate a '.xy' property on the
416     *    event object that is passed. (Prior to OpenLayers 2.7, this was true
417     *    by default.) Otherwise, you can call the getMousePosition on the
418     *    relevant events handler on the object available via the 'evt.object'
419     *    property of the evt object. So, for most events, you can call:
420     *    function named(evt) {
421     *        this.xy = this.object.events.getMousePosition(evt)
422     *    }
423     *
424     *    This option typically defaults to false for performance reasons:
425     *    when creating an events object whose primary purpose is to manage
426     *    relatively positioned mouse events within a div, it may make
427     *    sense to set it to true.
428     *
429     *    This option is also used to control whether the events object caches
430     *    offsets. If this is false, it will not: the reason for this is that
431     *    it is only expected to be called many times if the includeXY property
432     *    is set to true. If you set this to true, you are expected to clear
433     *    the offset cache manually (using this.clearMouseCache()) if:
434     *        the border of the element changes
435     *        the location of the element in the page changes
436    */
437    includeXY: false,     
438
439    /**
440     * Method: clearMouseListener
441     * A version of <clearMouseCache> that is bound to this instance so that
442     *     it can be used with <OpenLayers.Event.observe> and
443     *     <OpenLayers.Event.stopObserving>.
444     */
445    clearMouseListener: null,
446
447    /**
448     * Constructor: OpenLayers.Events
449     * Construct an OpenLayers.Events object.
450     *
451     * Parameters:
452     * object - {Object} The js object to which this Events object  is being
453     * added element - {DOMElement} A dom element to respond to browser events
454     * eventTypes - {Array(String)} Array of custom application events
455     * fallThrough - {Boolean} Allow events to fall through after these have
456     *                         been handled?
457     * options - {Object} Options for the events object.
458     */
459    initialize: function (object, element, eventTypes, fallThrough, options) {
460        OpenLayers.Util.extend(this, options);
461        this.object     = object;
462        this.fallThrough = fallThrough;
463        this.listeners  = {};
464
465        // keep a bound copy of handleBrowserEvent() so that we can
466        // pass the same function to both Event.observe() and .stopObserving()
467        this.eventHandler = OpenLayers.Function.bindAsEventListener(
468            this.handleBrowserEvent, this
469        );
470       
471        // to be used with observe and stopObserving
472        this.clearMouseListener = OpenLayers.Function.bind(
473            this.clearMouseCache, this
474        );
475
476        // if eventTypes is specified, create a listeners list for each
477        // custom application event.
478        this.eventTypes = [];
479        if (eventTypes != null) {
480            for (var i=0, len=eventTypes.length; i<len; i++) {
481                this.addEventType(eventTypes[i]);
482            }
483        }
484       
485        // if a dom element is specified, add a listeners list
486        // for browser events on the element and register them
487        if (element != null) {
488            this.attachToElement(element);
489        }
490    },
491
492    /**
493     * APIMethod: destroy
494     */
495    destroy: function () {
496        if (this.element) {
497            OpenLayers.Event.stopObservingElement(this.element);
498            if(this.element.hasScrollEvent) {
499                OpenLayers.Event.stopObserving(
500                    window, "scroll", this.clearMouseListener
501                );
502            }
503        }
504        this.element = null;
505
506        this.listeners = null;
507        this.object = null;
508        this.eventTypes = null;
509        this.fallThrough = null;
510        this.eventHandler = null;
511    },
512
513    /**
514     * APIMethod: addEventType
515     * Add a new event type to this events object.
516     * If the event type has already been added, do nothing.
517     *
518     * Parameters:
519     * eventName - {String}
520     */
521    addEventType: function(eventName) {
522        if (!this.listeners[eventName]) {
523            this.eventTypes.push(eventName);
524            this.listeners[eventName] = [];
525        }
526    },
527
528    /**
529     * Method: attachToElement
530     *
531     * Parameters:
532     * element - {HTMLDOMElement} a DOM element to attach browser events to
533     */
534    attachToElement: function (element) {
535        if(this.element) {
536            OpenLayers.Event.stopObservingElement(this.element);
537        }
538        this.element = element;
539        for (var i=0, len=this.BROWSER_EVENTS.length; i<len; i++) {
540            var eventType = this.BROWSER_EVENTS[i];
541
542            // every browser event has a corresponding application event
543            // (whether it's listened for or not).
544            this.addEventType(eventType);
545           
546            // use Prototype to register the event cross-browser
547            OpenLayers.Event.observe(element, eventType, this.eventHandler);
548        }
549        // disable dragstart in IE so that mousedown/move/up works normally
550        OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop);
551    },
552   
553    /**
554     * APIMethod: on
555     * Convenience method for registering listeners with a common scope.
556     *     Internally, this method calls <register> as shown in the examples
557     *     below.
558     *
559     * Example use:
560     * (code)
561     * // register a single listener for the "loadstart" event
562     * events.on({"loadstart", loadStartListener});
563     *
564     * // this is equivalent to the following
565     * events.register("loadstart", undefined, loadStartListener);
566     *
567     * // register multiple listeners to be called with the same `this` object
568     * events.on({
569     *     "loadstart": loadStartListener,
570     *     "loadend": loadEndListener,
571     *     scope: object
572     * });
573     *
574     * // this is equivalent to the following
575     * events.register("loadstart", object, loadStartListener);
576     * events.register("loadstart", object, loadEndListener);
577     * (end)
578     */
579    on: function(object) {
580        for(var type in object) {
581            if(type != "scope") {
582                this.register(type, object.scope, object[type]);
583            }
584        }
585    },
586
587    /**
588     * APIMethod: register
589     * Register an event on the events object.
590     *
591     * When the event is triggered, the 'func' function will be called, in the
592     * context of 'obj'. Imagine we were to register an event, specifying an
593     * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the
594     * context in the callback function will be our Bounds object. This means
595     * that within our callback function, we can access the properties and
596     * methods of the Bounds object through the "this" variable. So our
597     * callback could execute something like:
598     * :    leftStr = "Left: " + this.left;
599     *   
600     *                   or
601     * 
602     * :    centerStr = "Center: " + this.getCenterLonLat();
603     *
604     * Parameters:
605     * type - {String} Name of the event to register
606     * obj - {Object} The object to bind the context to for the callback#.
607     *                     If no object is specified, default is the Events's
608     *                     'object' property.
609     * func - {Function} The callback function. If no callback is
610     *                        specified, this function does nothing.
611     *
612     *
613     */
614    register: function (type, obj, func) {
615
616        if ( (func != null) && 
617             (OpenLayers.Util.indexOf(this.eventTypes, type) != -1) ) {
618
619            if (obj == null)  {
620                obj = this.object;
621            }
622            var listeners = this.listeners[type];
623            listeners.push( {obj: obj, func: func} );
624        }
625    },
626
627    /**
628     * APIMethod: registerPriority
629     * Same as register() but adds the new listener to the *front* of the
630     *     events queue instead of to the end.
631     *   
632     *     TODO: get rid of this in 3.0 - Decide whether listeners should be
633     *     called in the order they were registered or in reverse order.
634     *
635     *
636     * Parameters:
637     * type - {String} Name of the event to register
638     * obj - {Object} The object to bind the context to for the callback#.
639     *                If no object is specified, default is the Events's
640     *                'object' property.
641     * func - {Function} The callback function. If no callback is
642     *                   specified, this function does nothing.
643     */
644    registerPriority: function (type, obj, func) {
645
646        if (func != null) {
647            if (obj == null)  {
648                obj = this.object;
649            }
650            var listeners = this.listeners[type];
651            if (listeners != null) {
652                listeners.unshift( {obj: obj, func: func} );
653            }
654        }
655    },
656   
657    /**
658     * APIMethod: un
659     * Convenience method for unregistering listeners with a common scope.
660     *     Internally, this method calls <unregister> as shown in the examples
661     *     below.
662     *
663     * Example use:
664     * (code)
665     * // unregister a single listener for the "loadstart" event
666     * events.un({"loadstart", loadStartListener});
667     *
668     * // this is equivalent to the following
669     * events.unregister("loadstart", undefined, loadStartListener);
670     *
671     * // unregister multiple listeners with the same `this` object
672     * events.un({
673     *     "loadstart": loadStartListener,
674     *     "loadend": loadEndListener,
675     *     scope: object
676     * });
677     *
678     * // this is equivalent to the following
679     * events.unregister("loadstart", object, loadStartListener);
680     * events.unregister("loadstart", object, loadEndListener);
681     * (end)
682     */
683    un: function(object) {
684        for(var type in object) {
685            if(type != "scope") {
686                this.unregister(type, object.scope, object[type]);
687            }
688        }
689    },
690
691    /**
692     * APIMethod: unregister
693     *
694     * Parameters:
695     * type - {String}
696     * obj - {Object} If none specified, defaults to this.object
697     * func - {Function}
698     */
699    unregister: function (type, obj, func) {
700        if (obj == null)  {
701            obj = this.object;
702        }
703        var listeners = this.listeners[type];
704        if (listeners != null) {
705            for (var i=0, len=listeners.length; i<len; i++) {
706                if (listeners[i].obj == obj && listeners[i].func == func) {
707                    listeners.splice(i, 1);
708                    break;
709                }
710            }
711        }
712    },
713
714    /**
715     * Method: remove
716     * Remove all listeners for a given event type. If type is not registered,
717     *     does nothing.
718     *
719     * Parameters:
720     * type - {String}
721     */
722    remove: function(type) {
723        if (this.listeners[type] != null) {
724            this.listeners[type] = [];
725        }
726    },
727
728    /**
729     * APIMethod: triggerEvent
730     * Trigger a specified registered event. 
731     *
732     * Parameters:
733     * type - {String}
734     * evt - {Event}
735     *
736     * Returns:
737     * {Boolean} The last listener return.  If a listener returns false, the
738     *     chain of listeners will stop getting called.
739     */
740    triggerEvent: function (type, evt) {
741        var listeners = this.listeners[type];
742
743        // fast path
744        if(!listeners || listeners.length == 0) {
745            return;
746        }
747
748        // prep evt object with object & div references
749        if (evt == null) {
750            evt = {};
751        }
752        evt.object = this.object;
753        evt.element = this.element;
754        if(!evt.type) {
755            evt.type = type;
756        }
757   
758        // execute all callbacks registered for specified type
759        // get a clone of the listeners array to
760        // allow for splicing during callbacks
761        var listeners = listeners.slice(), continueChain;
762        for (var i=0, len=listeners.length; i<len; i++) {
763            var callback = listeners[i];
764            // bind the context to callback.obj
765            continueChain = callback.func.apply(callback.obj, [evt]);
766
767            if ((continueChain != undefined) && (continueChain == false)) {
768                // if callback returns false, execute no more callbacks.
769                break;
770            }
771        }
772        // don't fall through to other DOM elements
773        if (!this.fallThrough) {           
774            OpenLayers.Event.stop(evt, true);
775        }
776        return continueChain;
777    },
778
779    /**
780     * Method: handleBrowserEvent
781     * Basically just a wrapper to the triggerEvent() function, but takes
782     *     care to set a property 'xy' on the event with the current mouse
783     *     position.
784     *
785     * Parameters:
786     * evt - {Event}
787     */
788    handleBrowserEvent: function (evt) {
789        if (this.includeXY) {
790            evt.xy = this.getMousePosition(evt);
791        } 
792        this.triggerEvent(evt.type, evt);
793    },
794
795    /**
796     * APIMethod: clearMouseCache
797     * Clear cached data about the mouse position. This should be called any
798     *     time the element that events are registered on changes position
799     *     within the page.
800     */
801    clearMouseCache: function() { 
802        this.element.scrolls = null;
803        this.element.lefttop = null;
804        this.element.offsets = null;
805    },     
806
807    /**
808     * Method: getMousePosition
809     *
810     * Parameters:
811     * evt - {Event}
812     *
813     * Returns:
814     * {<OpenLayers.Pixel>} The current xy coordinate of the mouse, adjusted
815     *                      for offsets
816     */
817    getMousePosition: function (evt) {
818        if (!this.includeXY) {
819            this.clearMouseCache();
820        } else if (!this.element.hasScrollEvent) {
821            OpenLayers.Event.observe(window, "scroll", this.clearMouseListener);
822            this.element.hasScrollEvent = true;
823        }
824       
825        if (!this.element.scrolls) {
826            this.element.scrolls = [
827                (document.documentElement.scrollLeft
828                         || document.body.scrollLeft),
829                (document.documentElement.scrollTop
830                         || document.body.scrollTop)
831            ];
832        }
833
834        if (!this.element.lefttop) {
835            this.element.lefttop = [
836                (document.documentElement.clientLeft || 0),
837                (document.documentElement.clientTop  || 0)
838            ];
839        }
840       
841        if (!this.element.offsets) {
842            this.element.offsets = OpenLayers.Util.pagePosition(this.element);
843            this.element.offsets[0] += this.element.scrolls[0];
844            this.element.offsets[1] += this.element.scrolls[1];
845        }
846        return new OpenLayers.Pixel(
847            (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]
848                         - this.element.lefttop[0], 
849            (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1]
850                         - this.element.lefttop[1]
851        ); 
852    },
853
854    CLASS_NAME: "OpenLayers.Events"
855});
Note: See TracBrowser for help on using the repository browser.