Project

General

Profile

1
/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
2
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the full
3
 * text of the license. */
4
 
5
/**
6
 * @class
7
 */
8
OpenLayers.Events = Class.create();
9
OpenLayers.Events.prototype = {
10

    
11
    /** @final @type Array: supported events */
12
    BROWSER_EVENTS: [
13
        "mouseover", "mouseout",
14
        "mousedown", "mouseup", "mousemove", 
15
        "click", "dblclick",
16
        "resize", "focus", "blur"
17
    ],
18

    
19
    /** Hashtable of Array(Function): events listener functions 
20
     * @type Object */
21
    listeners: null,
22

    
23
    /** @type Object: the code object issuing application events */
24
    object: null,
25

    
26
    /** @type DOMElement: the DOM element receiving browser events */
27
    element: null,
28

    
29
    /** @type Array: list of support application events */
30
    eventTypes: null,
31

    
32

    
33
    /**
34
     * @constructor 
35
     * 
36
     * @param {OpenLayers.Map} object The js object to which this Events object
37
     *                                is being added
38
     * @param {DOMElement} element A dom element to respond to browser events
39
     * @param {Array} eventTypes Array of custom application events
40
     */
41
    initialize: function (object, element, eventTypes) {
42
        this.object     = object;
43
        this.element    = element;
44
        this.eventTypes = eventTypes;
45
        this.listeners  = new Object();
46

    
47
        // if eventTypes is specified, create a listeners list for each 
48
        // custom application event.
49
        if (this.eventTypes != null) 
50
            for (var i = 0; i < this.eventTypes.length; i++)
51
                this.listeners[ this.eventTypes[i] ] = new Array();
52

    
53
        // if a dom element is specified, add a listeners list 
54
        // for browser events on the element and register them
55
        if (this.element != null)
56
            this.attachToElement(element);
57
    },
58

    
59
    /**
60
    * @param {HTMLDOMElement} element a DOM element to attach browser events to
61
    */
62
    attachToElement: function (element) {
63
        for (var i = 0; i < this.BROWSER_EVENTS.length; i++) {
64
            var eventType = this.BROWSER_EVENTS[i];
65

    
66
            // every browser event has a corresponding application event 
67
            // (whether it's listened for or not).
68
            if (this.listeners[eventType] == null)
69
                this.listeners[eventType] = new Array();
70

    
71
            // use Prototype to register the event cross-browser
72
            Event.observe(element, eventType, 
73
                this.handleBrowserEvent.bindAsEventListener(this));
74
        }
75
        // disable dragstart in IE so that mousedown/move/up works normally
76
        Event.observe(element, "dragstart", Event.stop);
77
    },
78

    
79
    /**
80
     * @param {String} type Name of the event to register
81
     * @param {Object} obj The object to bind the context to for the callback#.
82
     *                     If no object is specified, default is the Events's 
83
     *                     'object' property.
84
     * @param {Function} func The callback function. If no callback is 
85
     *                        specified, this function does nothing.
86
     * 
87
     * #When the event is triggered, the 'func' function will be called, in the
88
     *   context of 'obj'. Imagine we were to register an event, specifying an 
89
     *   OpenLayers.Bounds Object as 'obj'. When the event is triggered, the 
90
     *   context in the callback function will be our Bounds object. This means
91
     *   that within our callback function, we can access the properties and 
92
     *   methods of the Bounds object through the "this" variable. So our 
93
     *   callback could execute something like: 
94
     *   
95
     *     leftStr = "Left: " + this.left;
96
     *   
97
     *                   or
98
     *  
99
     *     centerStr = "Center: " + this.getCenterLonLat();
100
     * 
101
     */
102
    register: function (type, obj, func) {
103

    
104
        if (func != null) {
105
            if (obj == null)  {
106
                obj = this.object;
107
            }
108
            var listeners = this.listeners[type];
109
            if (listeners != null) {
110
                listeners.push( {obj: obj, func: func} );
111
            }
112
        }
113
    },
114
    
115
    /**
116
     * @param {String} type
117
     * @param {Object} obj If none specified, defaults to this.object
118
     * @param {Function} func
119
     */
120
    unregister: function (type, obj, func) {
121
        if (obj == null)  {
122
            obj = this.object;
123
        }
124
        var listeners = this.listeners[type];
125
        if (listeners != null) {
126
            for (var i = 0; i < listeners.length; i++) {
127
                if (listeners[i].obj == obj && listeners[i].func == func) {
128
                    listeners.splice(i, 1);
129
                    break;
130
                }
131
            }
132
        }
133
    },
134

    
135
    /** Remove all listeners for a given event type. If type is not registered,
136
     *   does nothing.
137
     * 
138
     * @param {String} type
139
     */
140
    remove: function(type) {
141
        if (this.listeners[type] != null) {
142
            this.listeners[type] = new Array();
143
        }
144
    },
145

    
146
    /** Trigger a specified registered event
147
     * 
148
     * @param {String} type
149
     * @param {Event} evt
150
     */
151
    triggerEvent: function (type, evt) {
152

    
153
        // prep evt object with object & div references
154
        if (evt == null) {
155
            evt = new Object();
156
        }
157
        evt.object = this.object;
158
        evt.element = this.element;
159

    
160
        // execute all callbacks registered for specified type
161
        var listeners = this.listeners[type];
162
        if (listeners != null) {
163
    
164
            for (var i = 0; i < listeners.length; i++) {
165
                var callback = listeners[i];
166
                var continueChain;
167
                if (callback.obj != null) {
168
                    // use the 'call' method to bind the context to callback.obj
169
                    continueChain = callback.func.call(callback.obj, evt);
170
                } else {
171
                    continueChain = callback.func(evt);
172
                }
173
    
174
                if ((continueChain != null) && (continueChain == false)) {
175
                    // if callback returns false, execute no more callbacks.
176
                    break;
177
                }
178
            }
179
        }
180
    },
181

    
182
    /** Basically just a wrapper to the triggerEvent() function, but takes 
183
     *   care to set a property 'xy' on the event with the current mouse 
184
     *   position.
185
     * 
186
     * @private
187
     * 
188
     * @param {Event} evt
189
     */
190
    handleBrowserEvent: function (evt) {
191
        evt.xy = this.getMousePosition(evt); 
192
        this.triggerEvent(evt.type, evt)
193
    },
194

    
195
    /**
196
     * @private 
197
     * 
198
     * @param {Event} evt
199
     * 
200
     * @returns The current xy coordinate of the mouse, adjusted for offsets
201
     * @type OpenLayers.Pixel
202
     */
203
    getMousePosition: function (evt) {
204
        if (!this.element.offsets) {
205
            this.element.offsets = Position.page(this.element);
206
        }
207
        return new OpenLayers.Pixel(
208
                        evt.clientX - this.element.offsets[0], 
209
                        evt.clientY - this.element.offsets[1]); 
210
    },
211

    
212
    /** @final @type String */
213
    CLASS_NAME: "OpenLayers.Events"
214
};
(4-4/13)