summaryrefslogtreecommitdiff
path: root/misc/openlayers/tests/Events.html
blob: 03c540c26bbd09b65b4e32bdaaea089ca7044cb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
<html>
<head>
  <script src="OLLoader.js"></script>
  <script type="text/javascript">
    var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
    var map; 
    var a;
    
    function test_Events_constructor (t) {
        t.plan(4);

        var mapDiv = OpenLayers.Util.getElement('map');
        var obj = {result: 0};

        events = new OpenLayers.Events(obj, mapDiv);
        t.ok( events instanceof OpenLayers.Events, "new OpenLayers.Control returns object" );
        t.ok(events.object ==obj, " 'object' property correctly set");
        t.ok(events.element == mapDiv, " 'element' property correctly set");
        events.destroy();

        // default/nulls
        events = new OpenLayers.Events(null, null, null);
        t.ok( events.listeners != null,
              "init of Events with null object/element/eventTypes still creates listeners array" );
        events.destroy();
    }

    function test_Events_register(t){
        t.plan(4);

        var ev = {
            'object': {},
            'extensionCount': {
                'listenerA': 0,
                'listenerB': 0
            },
            'listeners': {
                'listenerA': { 
                    'push': function(options){
                                gObjA = options.obj;
                                gFuncA = options.func;
                            }
                },
                'listenerB': { 
                    'push': function(options){
                                gObjB = options.obj;
                                gFuncB = options.func;
                            }
                }
            }
        };

        var type = null;
        var object = null;
        var func = null;

      //func null
        gObjA = null; gFuncA = null; gObjB = null; gFuncB = null;
        OpenLayers.Events.prototype.register.apply(ev, [type, object, func]);
        t.ok((gObjA == null) && (gFuncA == null) && 
             (gObjB == null) && (gFuncB == null), "no push called func null"); 

      //valid func, type not in ev.eventTypes
        func = function() {};
        gObjA = null; gFuncA = null; gObjB = null; gFuncB = null;
        OpenLayers.Events.prototype.register.apply(ev, [type, object, func]);
        t.ok((gObjA == null) && (gFuncA == null) && 
             (gObjB == null) && (gFuncB == null), "no push called func null"); 

      //valid func, type in ev.eventTypes, null obj
        type = 'listenerA';
        gObjA = null; gFuncA = null; gObjB = null; gFuncB = null;
        OpenLayers.Events.prototype.register.apply(ev, [type, object, func]);
        t.ok((gObjA == ev.object) && (gFuncA == func) && 
             (gObjB == null) && (gFuncB == null), "push called on listenerA's mock array when type passed in 'listenerA'. events.object taken since obj is null."); 
        
      //valid func, type in ev.eventTypes, valid obj
        type = 'listenerB';
        object = {};
        gObjA = null; gFuncA = null; gObjB = null; gFuncB = null;
        OpenLayers.Events.prototype.register.apply(ev, [type, object, func]);
        t.ok((gObjA == null) && (gFuncA == null) && 
             (gObjB == object) && (gFuncB == func), "push called on listenerB's mock array when type passed in 'listenerB'."); 
        
    }

    function test_Events_register_unregister(t) {
 
        t.plan(20);
 
        var mapDiv = OpenLayers.Util.getElement('map');
        var obj = {result: 0};
        
        events = new OpenLayers.Events(obj, mapDiv);
        
        var func = function () { this.result++ }
        events.register( "doThingA", obj, func );

        var listenerList = events.listeners["doThingA"];
        t.eq( listenerList.length, 1, "register correctly adds to event.listeners" );
        t.ok( listenerList[0].obj == obj, "obj property correctly registered");
        t.ok( listenerList[0].func == func, "func property correctly registered");

        var func2 = function () { this.result-- }
        events.register( "doThingA", obj, func2 );

        var listenerList = events.listeners["doThingA"];
        t.eq( listenerList.length, 2, "register correctly appends new callback to event.listeners[doThingA]" );
        t.ok( listenerList[1].obj == obj, "obj property correctly registered");
        t.ok( listenerList[1].func == func2, "func property correctly registered");

        var func3 = function () { this.result = this.result + 3; }
        events.register( "doThingA", null, func3 );

        var listenerList = events.listeners["doThingA"];
        t.eq( listenerList.length, 3, "register correctly appends new callback to event.listeners[doThingA] even when obj passed in is null" );
        t.ok( listenerList[2].obj == obj, "obj is correctly set to Events.object default when null is passed in.");
        t.ok( listenerList[2].func == func3, "func property correctly registered");

        events.register( "doThingA", obj, null);

        var listenerList = events.listeners["doThingA"];
        t.eq( listenerList.length, 3, "register correctly does not append null callback to event.listeners[doThingA] even when obj passed in is null" );

        events.register("chicken", obj, func);
        t.eq(events.listeners["chicken"].length, 1, "register() allows listeners for any named event");

        events.unregister("chicken", obj, func);
        t.eq(events.listeners["chicken"].length, 0, "unregistering an event that is not in eventTypes list works")

        events.unregister("doThingA", obj, null);
        var listenerList = events.listeners["doThingA"];
        t.eq( listenerList.length, 3, "trying to unregister a null callback does nothing -- but doesnt crash :-)" );
    
        events.unregister("doThingA", obj, func);
        var found = false;
        for (var i = 0; i < listenerList.length; i++) {
            var listener = listenerList[i];
            if (listener.obj == obj && listener.func == func) {
                found = true;
            }
        }                
        t.ok( (listenerList.length == 2) && !found, "unregister correctly removes callback" );

        events.unregister("doThingA", null, func3);
        var found = false;
        for (var i = 0; i < listenerList.length; i++) {
            var listener = listenerList[i];
            if (listener.obj == obj && listener.func == func) {
                found = true;
            }
        }                
        t.ok( (listenerList.length == 1) && !found, "unregister correctly removes callback when no obj specified" );
        
        var func4 = function () { this.result = "chicken"; }
        events.unregister("doThingA", obj, func4);
        t.ok( (listenerList.length == 1), "unregister does not bomb if you try to remove an unregistered callback" );

        var obj2 = { chicken: 151 };
        events.unregister("doThingA", obj2, func2);
        t.ok( (listenerList.length == 1), "unregister does not bomb or accidntally remove if you try to remove a valid callback on a valid event type, but with the wrong context object" );

        events.unregister("doThingA", obj, null);
        t.ok( (listenerList.length == 1), "unregister does not bomb if you try to remove a null callback" );

        try {
            events.unregister("asdf", obj, func);
            t.ok("unregistering for an event with no registered listeners works");
        } catch (err) {
            t.fail("unregistering for an event with no registered listeners causes trouble: " + err);
        }
        
        events.register("buttonclick", obj, func);
        t.ok(events.extensions.buttonclick, "buttonclick extension registered");

    }

    function test_Events_remove(t) {

        t.plan( 2 );
 
        var mapDiv = OpenLayers.Util.getElement('map');
        var obj = {result: 0};
        
        events = new OpenLayers.Events(obj, mapDiv);
        
        var func = function () { this.result++ }
        var func2 = function () { this.result-- }
        var func3 = function () { this.result = this.result + 3; }

        events.register( "doThingA", obj, func );
        events.register( "doThingA", obj, func2 );
        events.register( "doThingA", null, func3 );

        events.remove("doThingA");

        t.eq( events.listeners["doThingA"].length, 0, "remove() correctly clears the event listeners" );

        events.remove("chicken");
        t.ok( events.listeners["chicken"] == null, "remove on non-enabled event does not break or accidentally enable the event");

    }

    function test_Events_triggerEvent(t) {
    
        t.plan(13);
 
        var mapDiv = OpenLayers.Util.getElement('map');
        var obj = {result: 0};
        
        events = new OpenLayers.Events(obj, mapDiv);
        
        
        var func = function () { this.result++ }
        events.register( "doThingA", obj, func );

        events.triggerEvent("doThingA", {});
        t.eq( obj.result, 1, "result is 1 after we call triggerEvent" );
        events.triggerEvent("doThingA");
        t.eq( obj.result, 2, "result is 2 after we call triggerEvent with no event" );

        var funcB = function() { this.FUNK = "B"; return false; }
        events.register( "doThingA", obj, funcB);

        events.triggerEvent("doThingA");
        t.ok ((obj.result == 3) && (obj.FUNK == "B"), "executing multiple callbacks works")

        var funcZ = function() { this.FUNK = "Z"; }
        events.register( "doThingA", obj, funcZ);

        events.triggerEvent("doThingA");
        t.ok ((obj.result == 4) && (obj.FUNK == "B"), "executing multiple callbacks works, and when one returns false, it stops chain correctly")


        var func2 = function() { this.result = this.result + 10; }
        events.register( "doThingB", null, func2);
        
        events.triggerEvent("doThingB");
        t.eq( obj.result, 14, "passing a null object default gets set correctly");
        
        //no specific t.ok for this one, but if it breaks, you will know it.
        events.triggerEvent("chicken");

        events = new OpenLayers.Events(null, mapDiv);
        
        // a is global variable (context-irrelevant)
        a = 0;
        var func = function () { a = 5; }
        events.register( "doThingC", null, func );
        events.triggerEvent("doThingC");

        t.eq(a, 5, "if Events has no object set and an event is registered also with no object, triggerEvent() calls it without trying to set the context to null");
        
        // trigger events with additional arguments
        events = new OpenLayers.Events();
        var instance = {id: Math.random()};
        var listener = function(obj) {
            t.eq(this.id, instance.id,
                 "listener called with proper scope");
            t.eq(arguments.length, 1,
                 "listener called with a single argument");
            t.eq(typeof arguments, "object",
                 "listener called with an object");
            t.eq(obj.foo, evt.foo,
                 "foo property set on the layer");
        };
        events.register("something", instance, listener);        
        var evt = {
            id: Math.random(),
            "foo": "bar"
        };
        events.triggerEvent("something", evt);
        events.unregister("something", instance, listener);
        
        // test return from triggerEvent
        var listener1 = function() {
            return "foo";
        }
        var listener2 = function() {
            return false;
        }
        var listener3 = function() {
            t.fail("never call me again!");
        }
        events.register("something", instance, listener1);
        var ret = events.triggerEvent("something", evt);
        t.eq(ret, "foo", "correct return from single listener");
        
        events.register("something", instance, listener2);
        ret = events.triggerEvent("something", evt);
        t.eq(ret, false, "correct return for two listeners");
        
        events.register("something", instance, listener3);
        ret = events.triggerEvent("something", evt);
        t.eq(ret, false, "correct return for three listeners where second cancels");
        
        events.unregister("something", instance, listener1);
        events.unregister("something", instance, listener2);
        events.unregister("something", instance, listener3);
    }

    function test_Events_handleBrowserEvent(t) {
        t.plan(8);
        var events = new OpenLayers.Events({}, null);
        events.on({'sometouchevent': function() {}});

        // this test verifies that when handling a touch event we correctly
        // set clientX and clientY in the event object 
        var evt = {type: 'sometouchevent',
                   touches: [{clientX: 1, clientY: 1}, {clientX: 2, clientY: 2}]
                  };
        events.handleBrowserEvent(evt);
        t.eq(evt.clientX, 1.5, "evt.clientX value is correct");
        t.eq(evt.clientY, 1.5, "evt.clientY value is correct");
        
        // test bug where clientX/clientY includes scroll offset
        window.olMockWin = {
            pageXOffset: 10,
            pageYOffset: 20
        };
        evt = {type: 'sometouchevent',
               touches: [{
                   clientX: 11,
                   clientY: 21,
                   pageX: 0,
                   pageY: 0
               }]
              };
        events.handleBrowserEvent(evt);
        t.eq(evt.clientX, 1, "evt.clientX value is correct");
        t.eq(evt.clientY, 1, "evt.clientY value is correct");
        
        
        // test bug where clientX/clientY have negative values
        evt = {
            type: 'sometouchevent',
            touches: [{
                clientX: -412,
                clientY: -1005,
                pageX: 11,
                pageY: 21
            }]
        };
        events.handleBrowserEvent(evt);
        t.eq(evt.clientX, 1, "evt.clientX value is correct");
        t.eq(evt.clientY, 1, "evt.clientY value is correct");
        
        window.olMockWin = {
            pageXOffset: 11,
            pageYOffset: 299
        };
        evt = {
            type: 'sometouchevent',
                touches: [{
                clientX: 223,
                clientY: 119,
                pageX: 242,
                pageY: 623
            }]
        };
        events.handleBrowserEvent(evt);
        t.eq(evt.clientX, 231, "evt.clientX value is correct");
        t.eq(evt.clientY, 324, "evt.clientY value is correct");
        
        window.olMockWin = undefined;
    }
    
    function test_Events_attachToElement(t) {
        t.plan(3);
        var events = new OpenLayers.Events({}, null);
        var element = document.createElement("div");
        events.attachToElement(element);
        t.ok(events.eventHandler, "eventHandler method bound");
        t.ok(events.clearMouseListener, "clearMouseListener method bound");
        t.ok(events.element === element, "element set");
    }

    function test_Events_destroy (t) {
        t.plan(2);

        var div   = OpenLayers.Util.getElement('test');
        var obj   = {};
        var events = new OpenLayers.Events(obj, div);

        // +1 because of blocking dragstart in attachToElement()
        t.eq(OpenLayers.Event.observers[div._eventCacheID].length,
             OpenLayers.Events.prototype.BROWSER_EVENTS.length + 1,
             "construction creates new arrayin hash, registers appropriate events");
             
        events.destroy();
        events = null;
        t.eq(OpenLayers.Event.observers["test"], null,
             "destruction removes the event observer from hash");
    }
    
    function test_Event(t) {
        t.plan(24);
        
        var div   = OpenLayers.Util.getElement('test');
        var name = "mouseover";
        var func = function() {};

      //1st elem 1st listener        
        OpenLayers.Event.observe(div, name, func);

        var cacheID = div._eventCacheID;
        t.ok(cacheID, "element given new cache id");
        
        var elementObservers = OpenLayers.Event.observers[cacheID];
        
        t.ok(elementObservers, "new cache bucket made for event");
        t.eq(elementObservers.length, 1, "one listener registered");        
        
        var listener = elementObservers[0];
        
        t.ok(listener.element == div, "element registered");
        t.eq(listener.name, name, "name registered");
        t.ok(listener.observer == func, "function registered");
        t.eq(listener.useCapture, false, "useCapture defaults to false");

      //1st elem 2nd listener        
        name = "mouseout";
        var newFunc = function() {};
      
        OpenLayers.Event.observe(div, name, newFunc, true);
        var newCacheID = div._eventCacheID;
        t.eq(newCacheID, cacheID, "element's cache id not overridden");
        
        t.eq(elementObservers.length, 2, "listener added to existing bucket");        
        
        var listener = elementObservers[1];
        
        t.ok(listener.element == div, "element registered");
        t.eq(listener.name, name, "name registered");
        t.ok(listener.observer == newFunc, "function registered");
        t.eq(listener.useCapture, true, "useCapture correctly registered");

      //2st elem 1st listener        
        div = OpenLayers.Util.getElement('test2'); 
        OpenLayers.Event.observe(div, name, func);

        var cacheID = div._eventCacheID;
        t.ok(cacheID, "new element given new cache id");
        t.ok(cacheID != newCacheID, "new cache id is unique");
        
        elementObservers = OpenLayers.Event.observers[cacheID];
        
        t.ok(elementObservers, "new cache bucket made for event");
        t.eq(elementObservers.length, 1, "one listener registered");        
        
        var listener = elementObservers[0];
        
        t.ok(listener.element == div, "element registered");
        t.eq(listener.name, name, "name registered");
        t.ok(listener.observer == func, "function registered");
        t.eq(listener.useCapture, false, "useCapture defaults to false");

      //stopObservingElement by element
        OpenLayers.Event.stopObservingElement(div);
        elementObservers = OpenLayers.Event.observers[cacheID];
        t.ok(elementObservers == null, "stopObservingElement by elem works");

      //stopObservingElement by id
        OpenLayers.Event.stopObservingElement("test");
        elementObservers = OpenLayers.Event.observers[newCacheID];
        t.ok(elementObservers == null, "stopObservingElement by id works");


      //unloadCache by element
        OpenLayers.Event.observe(div, name, func);
        
        OpenLayers.Event.unloadCache();

        elementObservers = OpenLayers.Event.observers[cacheID];
        t.ok(elementObservers == null, "stopObservingElement by elem works");

        
    }

  </script>
</head>
<body>
    <div id="map" style="width: 1024px; height: 512px;"/>
    <div id="test"></div>
    <div id="test2"></div>
</body>
</html>