Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('event-simulate', function (Y, NAME) {
2
 
3
(function() {
4
/**
5
 * Simulate user interaction by generating native DOM events.
6
 *
7
 * @module event-simulate
8
 * @requires event
9
 */
10
 
11
//shortcuts
12
var L   = Y.Lang,
13
    win = Y.config.win,
14
    isFunction  = L.isFunction,
15
    isString    = L.isString,
16
    isBoolean   = L.isBoolean,
17
    isObject    = L.isObject,
18
    isNumber    = L.isNumber,
19
 
20
    //mouse events supported
21
    mouseEvents = {
22
        click:      1,
23
        dblclick:   1,
24
        mouseover:  1,
25
        mouseout:   1,
26
        mousedown:  1,
27
        mouseup:    1,
28
        mousemove:  1,
29
        contextmenu:1
30
    },
31
 
32
    pointerEvents = (win && win.PointerEvent) ? {
33
        pointerover:  1,
34
        pointerout:   1,
35
        pointerdown:  1,
36
        pointerup:    1,
37
        pointermove:  1
38
    } : {
39
        MSPointerOver:  1,
40
        MSPointerOut:   1,
41
        MSPointerDown:  1,
42
        MSPointerUp:    1,
43
        MSPointerMove:  1
44
    },
45
 
46
    //key events supported
47
    keyEvents   = {
48
        keydown:    1,
49
        keyup:      1,
50
        keypress:   1
51
    },
52
 
53
    //HTML events supported
54
    uiEvents  = {
55
        submit:     1,
56
        blur:       1,
57
        change:     1,
58
        focus:      1,
59
        resize:     1,
60
        scroll:     1,
61
        select:     1
62
    },
63
 
64
    //events that bubble by default
65
    bubbleEvents = {
66
        scroll:     1,
67
        resize:     1,
68
        reset:      1,
69
        submit:     1,
70
        change:     1,
71
        select:     1,
72
        error:      1,
73
        abort:      1
74
    },
75
 
76
    //touch events supported
77
    touchEvents = {
78
        touchstart: 1,
79
        touchmove: 1,
80
        touchend: 1,
81
        touchcancel: 1
82
    },
83
 
84
    gestureEvents = {
85
        gesturestart: 1,
86
        gesturechange: 1,
87
        gestureend: 1
88
    };
89
 
90
//all key, mouse and touch events bubble
91
Y.mix(bubbleEvents, mouseEvents);
92
Y.mix(bubbleEvents, keyEvents);
93
Y.mix(bubbleEvents, touchEvents);
94
 
95
/*
96
 * Note: Intentionally not for YUIDoc generation.
97
 * Simulates a key event using the given event information to populate
98
 * the generated event object. This method does browser-equalizing
99
 * calculations to account for differences in the DOM and IE event models
100
 * as well as different browser quirks. Note: keydown causes Safari 2.x to
101
 * crash.
102
 * @method simulateKeyEvent
103
 * @private
104
 * @static
105
 * @param {HTMLElement} target The target of the given event.
106
 * @param {String} type The type of event to fire. This can be any one of
107
 *      the following: keyup, keydown, and keypress.
108
 * @param {Boolean} [bubbles=true] Indicates if the event can be
109
 *      bubbled up. DOM Level 3 specifies that all key events bubble by
110
 *      default.
111
 * @param {Boolean} [cancelable=true] Indicates if the event can be
112
 *      canceled using preventDefault(). DOM Level 3 specifies that all
113
 *      key events can be cancelled.
114
 * @param {Window} [view=window] The view containing the target. This is
115
 *      typically the window object.
116
 * @param {Boolean} [ctrlKey=false] Indicates if one of the CTRL keys
117
 *      is pressed while the event is firing.
118
 * @param {Boolean} [altKey=false] Indicates if one of the ALT keys
119
 *      is pressed while the event is firing.
120
 * @param {Boolean} [shiftKey=false] Indicates if one of the SHIFT keys
121
 *      is pressed while the event is firing.
122
 * @param {Boolean} [metaKey=false] Indicates if one of the META keys
123
 *      is pressed while the event is firing.
124
 * @param {Number} [keyCode=0] The code for the key that is in use.
125
 * @param {Number} [charCode=0] The Unicode code for the character
126
 *      associated with the key being used.
127
 */
128
function simulateKeyEvent(target /*:HTMLElement*/, type /*:String*/,
129
                             bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
130
                             view /*:Window*/,
131
                             ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,
132
                             shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,
133
                             keyCode /*:int*/,        charCode /*:int*/) /*:Void*/
134
{
135
    //check target
136
    if (!target){
137
        Y.error("simulateKeyEvent(): Invalid target.");
138
    }
139
 
140
    //check event type
141
    if (isString(type)){
142
        type = type.toLowerCase();
143
        switch(type){
144
            case "textevent": //DOM Level 3
145
                type = "keypress";
146
                break;
147
            case "keyup":
148
            case "keydown":
149
            case "keypress":
150
                break;
151
            default:
152
                Y.error("simulateKeyEvent(): Event type '" + type + "' not supported.");
153
        }
154
    } else {
155
        Y.error("simulateKeyEvent(): Event type must be a string.");
156
    }
157
 
158
    //setup default values
159
    if (!isBoolean(bubbles)){
160
        bubbles = true; //all key events bubble
161
    }
162
    if (!isBoolean(cancelable)){
163
        cancelable = true; //all key events can be cancelled
164
    }
165
    if (!isObject(view)){
166
        view = Y.config.win; //view is typically window
167
    }
168
    if (!isBoolean(ctrlKey)){
169
        ctrlKey = false;
170
    }
171
    if (!isBoolean(altKey)){
172
        altKey = false;
173
    }
174
    if (!isBoolean(shiftKey)){
175
        shiftKey = false;
176
    }
177
    if (!isBoolean(metaKey)){
178
        metaKey = false;
179
    }
180
    if (!isNumber(keyCode)){
181
        keyCode = 0;
182
    }
183
    if (!isNumber(charCode)){
184
        charCode = 0;
185
    }
186
 
187
    //try to create a mouse event
188
    var customEvent /*:MouseEvent*/ = null;
189
 
190
    //check for DOM-compliant browsers first
191
    if (isFunction(Y.config.doc.createEvent)){
192
 
193
        try {
194
 
195
            //try to create key event
196
            customEvent = Y.config.doc.createEvent("KeyEvents");
197
 
198
            /*
199
             * Interesting problem: Firefox implemented a non-standard
200
             * version of initKeyEvent() based on DOM Level 2 specs.
201
             * Key event was removed from DOM Level 2 and re-introduced
202
             * in DOM Level 3 with a different interface. Firefox is the
203
             * only browser with any implementation of Key Events, so for
204
             * now, assume it's Firefox if the above line doesn't error.
205
             */
206
            // @TODO: Decipher between Firefox's implementation and a correct one.
207
            customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey,
208
                altKey, shiftKey, metaKey, keyCode, charCode);
209
 
210
        } catch (ex /*:Error*/){
211
 
212
            /*
213
             * If it got here, that means key events aren't officially supported.
214
             * Safari/WebKit is a real problem now. WebKit 522 won't let you
215
             * set keyCode, charCode, or other properties if you use a
216
             * UIEvent, so we first must try to create a generic event. The
217
             * fun part is that this will throw an error on Safari 2.x. The
218
             * end result is that we need another try...catch statement just to
219
             * deal with this mess.
220
             */
221
            try {
222
 
223
                //try to create generic event - will fail in Safari 2.x
224
                customEvent = Y.config.doc.createEvent("Events");
225
 
226
            } catch (uierror /*:Error*/){
227
 
228
                //the above failed, so create a UIEvent for Safari 2.x
229
                customEvent = Y.config.doc.createEvent("UIEvents");
230
 
231
            } finally {
232
 
233
                customEvent.initEvent(type, bubbles, cancelable);
234
 
235
                //initialize
236
                customEvent.view = view;
237
                customEvent.altKey = altKey;
238
                customEvent.ctrlKey = ctrlKey;
239
                customEvent.shiftKey = shiftKey;
240
                customEvent.metaKey = metaKey;
241
                customEvent.keyCode = keyCode;
242
                customEvent.charCode = charCode;
243
 
244
            }
245
 
246
        }
247
 
248
        //fire the event
249
        target.dispatchEvent(customEvent);
250
 
251
    } else if (isObject(Y.config.doc.createEventObject)){ //IE
252
 
253
        //create an IE event object
254
        customEvent = Y.config.doc.createEventObject();
255
 
256
        //assign available properties
257
        customEvent.bubbles = bubbles;
258
        customEvent.cancelable = cancelable;
259
        customEvent.view = view;
260
        customEvent.ctrlKey = ctrlKey;
261
        customEvent.altKey = altKey;
262
        customEvent.shiftKey = shiftKey;
263
        customEvent.metaKey = metaKey;
264
 
265
        /*
266
         * IE doesn't support charCode explicitly. CharCode should
267
         * take precedence over any keyCode value for accurate
268
         * representation.
269
         */
270
        customEvent.keyCode = (charCode > 0) ? charCode : keyCode;
271
 
272
        //fire the event
273
        target.fireEvent("on" + type, customEvent);
274
 
275
    } else {
276
        Y.error("simulateKeyEvent(): No event simulation framework present.");
277
    }
278
}
279
 
280
/*
281
 * Note: Intentionally not for YUIDoc generation.
282
 * Simulates a mouse event using the given event information to populate
283
 * the generated event object. This method does browser-equalizing
284
 * calculations to account for differences in the DOM and IE event models
285
 * as well as different browser quirks.
286
 * @method simulateMouseEvent
287
 * @private
288
 * @static
289
 * @param {HTMLElement} target The target of the given event.
290
 * @param {String} type The type of event to fire. This can be any one of
291
 *      the following: click, dblclick, mousedown, mouseup, mouseout,
292
 *      mouseover, and mousemove.
293
 * @param {Boolean} bubbles (Optional) Indicates if the event can be
294
 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
295
 *      default. The default is true.
296
 * @param {Boolean} cancelable (Optional) Indicates if the event can be
297
 *      canceled using preventDefault(). DOM Level 2 specifies that all
298
 *      mouse events except mousemove can be cancelled. The default
299
 *      is true for all events except mousemove, for which the default
300
 *      is false.
301
 * @param {Window} view (Optional) The view containing the target. This is
302
 *      typically the window object. The default is window.
303
 * @param {Number} detail (Optional) The number of times the mouse button has
304
 *      been used. The default value is 1.
305
 * @param {Number} screenX (Optional) The x-coordinate on the screen at which
306
 *      point the event occured. The default is 0.
307
 * @param {Number} screenY (Optional) The y-coordinate on the screen at which
308
 *      point the event occured. The default is 0.
309
 * @param {Number} clientX (Optional) The x-coordinate on the client at which
310
 *      point the event occured. The default is 0.
311
 * @param {Number} clientY (Optional) The y-coordinate on the client at which
312
 *      point the event occured. The default is 0.
313
 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
314
 *      is pressed while the event is firing. The default is false.
315
 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
316
 *      is pressed while the event is firing. The default is false.
317
 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
318
 *      is pressed while the event is firing. The default is false.
319
 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
320
 *      is pressed while the event is firing. The default is false.
321
 * @param {Number} button (Optional) The button being pressed while the event
322
 *      is executing. The value should be 0 for the primary mouse button
323
 *      (typically the left button), 1 for the terciary mouse button
324
 *      (typically the middle button), and 2 for the secondary mouse button
325
 *      (typically the right button). The default is 0.
326
 * @param {HTMLElement} relatedTarget (Optional) For mouseout events,
327
 *      this is the element that the mouse has moved to. For mouseover
328
 *      events, this is the element that the mouse has moved from. This
329
 *      argument is ignored for all other events. The default is null.
330
 */
331
function simulateMouseEvent(target /*:HTMLElement*/, type /*:String*/,
332
                               bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
333
                               view /*:Window*/,        detail /*:int*/,
334
                               screenX /*:int*/,        screenY /*:int*/,
335
                               clientX /*:int*/,        clientY /*:int*/,
336
                               ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,
337
                               shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,
338
                               button /*:int*/,         relatedTarget /*:HTMLElement*/) /*:Void*/
339
{
340
    //check target
341
    if (!target){
342
        Y.error("simulateMouseEvent(): Invalid target.");
343
    }
344
 
345
 
346
    if (isString(type)){
347
 
348
        //make sure it's a supported mouse event or an msPointerEvent.
349
        if (!mouseEvents[type.toLowerCase()] && !pointerEvents[type]){
350
            Y.error("simulateMouseEvent(): Event type '" + type + "' not supported.");
351
        }
352
    }
353
    else {
354
        Y.error("simulateMouseEvent(): Event type must be a string.");
355
    }
356
 
357
    //setup default values
358
    if (!isBoolean(bubbles)){
359
        bubbles = true; //all mouse events bubble
360
    }
361
    if (!isBoolean(cancelable)){
362
        cancelable = (type !== "mousemove"); //mousemove is the only one that can't be cancelled
363
    }
364
    if (!isObject(view)){
365
        view = Y.config.win; //view is typically window
366
    }
367
    if (!isNumber(detail)){
368
        detail = 1;  //number of mouse clicks must be at least one
369
    }
370
    if (!isNumber(screenX)){
371
        screenX = 0;
372
    }
373
    if (!isNumber(screenY)){
374
        screenY = 0;
375
    }
376
    if (!isNumber(clientX)){
377
        clientX = 0;
378
    }
379
    if (!isNumber(clientY)){
380
        clientY = 0;
381
    }
382
    if (!isBoolean(ctrlKey)){
383
        ctrlKey = false;
384
    }
385
    if (!isBoolean(altKey)){
386
        altKey = false;
387
    }
388
    if (!isBoolean(shiftKey)){
389
        shiftKey = false;
390
    }
391
    if (!isBoolean(metaKey)){
392
        metaKey = false;
393
    }
394
    if (!isNumber(button)){
395
        button = 0;
396
    }
397
 
398
    relatedTarget = relatedTarget || null;
399
 
400
    //try to create a mouse event
401
    var customEvent /*:MouseEvent*/ = null;
402
 
403
    //check for DOM-compliant browsers first
404
    if (isFunction(Y.config.doc.createEvent)){
405
 
406
        customEvent = Y.config.doc.createEvent("MouseEvents");
407
 
408
        //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()
409
        if (customEvent.initMouseEvent){
410
            customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,
411
                                 screenX, screenY, clientX, clientY,
412
                                 ctrlKey, altKey, shiftKey, metaKey,
413
                                 button, relatedTarget);
414
        } else { //Safari
415
 
416
            //the closest thing available in Safari 2.x is UIEvents
417
            customEvent = Y.config.doc.createEvent("UIEvents");
418
            customEvent.initEvent(type, bubbles, cancelable);
419
            customEvent.view = view;
420
            customEvent.detail = detail;
421
            customEvent.screenX = screenX;
422
            customEvent.screenY = screenY;
423
            customEvent.clientX = clientX;
424
            customEvent.clientY = clientY;
425
            customEvent.ctrlKey = ctrlKey;
426
            customEvent.altKey = altKey;
427
            customEvent.metaKey = metaKey;
428
            customEvent.shiftKey = shiftKey;
429
            customEvent.button = button;
430
            customEvent.relatedTarget = relatedTarget;
431
        }
432
 
433
        /*
434
         * Check to see if relatedTarget has been assigned. Firefox
435
         * versions less than 2.0 don't allow it to be assigned via
436
         * initMouseEvent() and the property is readonly after event
437
         * creation, so in order to keep YAHOO.util.getRelatedTarget()
438
         * working, assign to the IE proprietary toElement property
439
         * for mouseout event and fromElement property for mouseover
440
         * event.
441
         */
442
        if (relatedTarget && !customEvent.relatedTarget){
443
            if (type === "mouseout"){
444
                customEvent.toElement = relatedTarget;
445
            } else if (type === "mouseover"){
446
                customEvent.fromElement = relatedTarget;
447
            }
448
        }
449
 
450
        //fire the event
451
        target.dispatchEvent(customEvent);
452
 
453
    } else if (isObject(Y.config.doc.createEventObject)){ //IE
454
 
455
        //create an IE event object
456
        customEvent = Y.config.doc.createEventObject();
457
 
458
        //assign available properties
459
        customEvent.bubbles = bubbles;
460
        customEvent.cancelable = cancelable;
461
        customEvent.view = view;
462
        customEvent.detail = detail;
463
        customEvent.screenX = screenX;
464
        customEvent.screenY = screenY;
465
        customEvent.clientX = clientX;
466
        customEvent.clientY = clientY;
467
        customEvent.ctrlKey = ctrlKey;
468
        customEvent.altKey = altKey;
469
        customEvent.metaKey = metaKey;
470
        customEvent.shiftKey = shiftKey;
471
 
472
        //fix button property for IE's wacky implementation
473
        switch(button){
474
            case 0:
475
                customEvent.button = 1;
476
                break;
477
            case 1:
478
                customEvent.button = 4;
479
                break;
480
            case 2:
481
                //leave as is
482
                break;
483
            default:
484
                customEvent.button = 0;
485
        }
486
 
487
        /*
488
         * Have to use relatedTarget because IE won't allow assignment
489
         * to toElement or fromElement on generic events. This keeps
490
         * YAHOO.util.customEvent.getRelatedTarget() functional.
491
         */
492
        customEvent.relatedTarget = relatedTarget;
493
 
494
        //fire the event
495
        target.fireEvent("on" + type, customEvent);
496
 
497
    } else {
498
        Y.error("simulateMouseEvent(): No event simulation framework present.");
499
    }
500
}
501
 
502
/*
503
 * Note: Intentionally not for YUIDoc generation.
504
 * Simulates a UI event using the given event information to populate
505
 * the generated event object. This method does browser-equalizing
506
 * calculations to account for differences in the DOM and IE event models
507
 * as well as different browser quirks.
508
 * @method simulateHTMLEvent
509
 * @private
510
 * @static
511
 * @param {HTMLElement} target The target of the given event.
512
 * @param {String} type The type of event to fire. This can be any one of
513
 *      the following: click, dblclick, mousedown, mouseup, mouseout,
514
 *      mouseover, and mousemove.
515
 * @param {Boolean} bubbles (Optional) Indicates if the event can be
516
 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
517
 *      default. The default is true.
518
 * @param {Boolean} cancelable (Optional) Indicates if the event can be
519
 *      canceled using preventDefault(). DOM Level 2 specifies that all
520
 *      mouse events except mousemove can be cancelled. The default
521
 *      is true for all events except mousemove, for which the default
522
 *      is false.
523
 * @param {Window} view (Optional) The view containing the target. This is
524
 *      typically the window object. The default is window.
525
 * @param {Number} detail (Optional) The number of times the mouse button has
526
 *      been used. The default value is 1.
527
 */
528
function simulateUIEvent(target /*:HTMLElement*/, type /*:String*/,
529
                               bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
530
                               view /*:Window*/,        detail /*:int*/) /*:Void*/
531
{
532
 
533
    //check target
534
    if (!target){
535
        Y.error("simulateUIEvent(): Invalid target.");
536
    }
537
 
538
    //check event type
539
    if (isString(type)){
540
        type = type.toLowerCase();
541
 
542
        //make sure it's a supported mouse event
543
        if (!uiEvents[type]){
544
            Y.error("simulateUIEvent(): Event type '" + type + "' not supported.");
545
        }
546
    } else {
547
        Y.error("simulateUIEvent(): Event type must be a string.");
548
    }
549
 
550
    //try to create a mouse event
551
    var customEvent = null;
552
 
553
 
554
    //setup default values
555
    if (!isBoolean(bubbles)){
556
        bubbles = (type in bubbleEvents);  //not all events bubble
557
    }
558
    if (!isBoolean(cancelable)){
559
        cancelable = (type === "submit"); //submit is the only one that can be cancelled
560
    }
561
    if (!isObject(view)){
562
        view = Y.config.win; //view is typically window
563
    }
564
    if (!isNumber(detail)){
565
        detail = 1;  //usually not used but defaulted to this
566
    }
567
 
568
    //check for DOM-compliant browsers first
569
    if (isFunction(Y.config.doc.createEvent)){
570
 
571
        //just a generic UI Event object is needed
572
        customEvent = Y.config.doc.createEvent("UIEvents");
573
        customEvent.initUIEvent(type, bubbles, cancelable, view, detail);
574
 
575
        //fire the event
576
        target.dispatchEvent(customEvent);
577
 
578
    } else if (isObject(Y.config.doc.createEventObject)){ //IE
579
 
580
        //create an IE event object
581
        customEvent = Y.config.doc.createEventObject();
582
 
583
        //assign available properties
584
        customEvent.bubbles = bubbles;
585
        customEvent.cancelable = cancelable;
586
        customEvent.view = view;
587
        customEvent.detail = detail;
588
 
589
        //fire the event
590
        target.fireEvent("on" + type, customEvent);
591
 
592
    } else {
593
        Y.error("simulateUIEvent(): No event simulation framework present.");
594
    }
595
}
596
 
597
/*
598
 * (iOS only) This is for creating native DOM gesture events which only iOS
599
 * v2.0+ is supporting.
600
 *
601
 * @method simulateGestureEvent
602
 * @private
603
 * @param {HTMLElement} target The target of the given event.
604
 * @param {String} type The type of event to fire. This can be any one of
605
 *      the following: touchstart, touchmove, touchend, touchcancel.
606
 * @param {Boolean} bubbles (Optional) Indicates if the event can be
607
 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
608
 *      default. The default is true.
609
 * @param {Boolean} cancelable (Optional) Indicates if the event can be
610
 *      canceled using preventDefault(). DOM Level 2 specifies that all
611
 *      touch events except touchcancel can be cancelled. The default
612
 *      is true for all events except touchcancel, for which the default
613
 *      is false.
614
 * @param {Window} view (Optional) The view containing the target. This is
615
 *      typically the window object. The default is window.
616
 * @param {Number} detail (Optional) Specifies some detail information about
617
 *      the event depending on the type of event.
618
 * @param {Number} screenX (Optional) The x-coordinate on the screen at which
619
 *      point the event occured. The default is 0.
620
 * @param {Number} screenY (Optional) The y-coordinate on the screen at which
621
 *      point the event occured. The default is 0.
622
 * @param {Number} clientX (Optional) The x-coordinate on the client at which
623
 *      point the event occured. The default is 0.
624
 * @param {Number} clientY (Optional) The y-coordinate on the client at which
625
 *      point the event occured. The default is 0.
626
 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
627
 *      is pressed while the event is firing. The default is false.
628
 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
629
 *      is pressed while the event is firing. The default is false.
630
 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
631
 *      is pressed while the event is firing. The default is false.
632
 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
633
 *      is pressed while the event is firing. The default is false.
634
 * @param {Number} scale (iOS v2+ only) The distance between two fingers
635
 *      since the start of an event as a multiplier of the initial distance.
636
 *      The default value is 1.0.
637
 * @param {Number} rotation (iOS v2+ only) The delta rotation since the start
638
 *      of an event, in degrees, where clockwise is positive and
639
 *      counter-clockwise is negative. The default value is 0.0.
640
 */
641
function simulateGestureEvent(target, type,
642
    bubbles,            // boolean
643
    cancelable,         // boolean
644
    view,               // DOMWindow
645
    detail,             // long
646
    screenX, screenY,   // long
647
    clientX, clientY,   // long
648
    ctrlKey, altKey, shiftKey, metaKey, // boolean
649
    scale,              // float
650
    rotation            // float
651
) {
652
    var customEvent;
653
 
654
    if(!Y.UA.ios || Y.UA.ios<2.0) {
655
        Y.error("simulateGestureEvent(): Native gesture DOM eventframe is not available in this platform.");
656
    }
657
 
658
    // check taget
659
    if (!target){
660
        Y.error("simulateGestureEvent(): Invalid target.");
661
    }
662
 
663
    //check event type
664
    if (Y.Lang.isString(type)) {
665
        type = type.toLowerCase();
666
 
667
        //make sure it's a supported touch event
668
        if (!gestureEvents[type]){
669
            Y.error("simulateTouchEvent(): Event type '" + type + "' not supported.");
670
        }
671
    } else {
672
        Y.error("simulateGestureEvent(): Event type must be a string.");
673
    }
674
 
675
    // setup default values
676
    if (!Y.Lang.isBoolean(bubbles)) { bubbles = true; } // bubble by default
677
    if (!Y.Lang.isBoolean(cancelable)) { cancelable = true; }
678
    if (!Y.Lang.isObject(view))     { view = Y.config.win; }
679
    if (!Y.Lang.isNumber(detail))   { detail = 2; }     // usually not used.
680
    if (!Y.Lang.isNumber(screenX))  { screenX = 0; }
681
    if (!Y.Lang.isNumber(screenY))  { screenY = 0; }
682
    if (!Y.Lang.isNumber(clientX))  { clientX = 0; }
683
    if (!Y.Lang.isNumber(clientY))  { clientY = 0; }
684
    if (!Y.Lang.isBoolean(ctrlKey)) { ctrlKey = false; }
685
    if (!Y.Lang.isBoolean(altKey))  { altKey = false; }
686
    if (!Y.Lang.isBoolean(shiftKey)){ shiftKey = false; }
687
    if (!Y.Lang.isBoolean(metaKey)) { metaKey = false; }
688
 
689
    if (!Y.Lang.isNumber(scale)){ scale = 1.0; }
690
    if (!Y.Lang.isNumber(rotation)){ rotation = 0.0; }
691
 
692
    customEvent = Y.config.doc.createEvent("GestureEvent");
693
 
694
    customEvent.initGestureEvent(type, bubbles, cancelable, view, detail,
695
        screenX, screenY, clientX, clientY,
696
        ctrlKey, altKey, shiftKey, metaKey,
697
        target, scale, rotation);
698
 
699
    target.dispatchEvent(customEvent);
700
}
701
 
702
 
703
/*
704
 * @method simulateTouchEvent
705
 * @private
706
 * @param {HTMLElement} target The target of the given event.
707
 * @param {String} type The type of event to fire. This can be any one of
708
 *      the following: touchstart, touchmove, touchend, touchcancel.
709
 * @param {Boolean} bubbles (Optional) Indicates if the event can be
710
 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
711
 *      default. The default is true.
712
 * @param {Boolean} cancelable (Optional) Indicates if the event can be
713
 *      canceled using preventDefault(). DOM Level 2 specifies that all
714
 *      touch events except touchcancel can be cancelled. The default
715
 *      is true for all events except touchcancel, for which the default
716
 *      is false.
717
 * @param {Window} view (Optional) The view containing the target. This is
718
 *      typically the window object. The default is window.
719
 * @param {Number} detail (Optional) Specifies some detail information about
720
 *      the event depending on the type of event.
721
 * @param {Number} screenX (Optional) The x-coordinate on the screen at which
722
 *      point the event occured. The default is 0.
723
 * @param {Number} screenY (Optional) The y-coordinate on the screen at which
724
 *      point the event occured. The default is 0.
725
 * @param {Number} clientX (Optional) The x-coordinate on the client at which
726
 *      point the event occured. The default is 0.
727
 * @param {Number} clientY (Optional) The y-coordinate on the client at which
728
 *      point the event occured. The default is 0.
729
 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
730
 *      is pressed while the event is firing. The default is false.
731
 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
732
 *      is pressed while the event is firing. The default is false.
733
 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
734
 *      is pressed while the event is firing. The default is false.
735
 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
736
 *      is pressed while the event is firing. The default is false.
737
 * @param {TouchList} touches A collection of Touch objects representing
738
 *      all touches associated with this event.
739
 * @param {TouchList} targetTouches A collection of Touch objects
740
 *      representing all touches associated with this target.
741
 * @param {TouchList} changedTouches A collection of Touch objects
742
 *      representing all touches that changed in this event.
743
 * @param {Number} scale (iOS v2+ only) The distance between two fingers
744
 *      since the start of an event as a multiplier of the initial distance.
745
 *      The default value is 1.0.
746
 * @param {Number} rotation (iOS v2+ only) The delta rotation since the start
747
 *      of an event, in degrees, where clockwise is positive and
748
 *      counter-clockwise is negative. The default value is 0.0.
749
 */
750
function simulateTouchEvent(target, type,
751
    bubbles,            // boolean
752
    cancelable,         // boolean
753
    view,               // DOMWindow
754
    detail,             // long
755
    screenX, screenY,   // long
756
    clientX, clientY,   // long
757
    ctrlKey, altKey, shiftKey, metaKey, // boolean
758
    touches,            // TouchList
759
    targetTouches,      // TouchList
760
    changedTouches,     // TouchList
761
    scale,              // float
762
    rotation            // float
763
) {
764
 
765
    var customEvent;
766
 
767
    // check taget
768
    if (!target){
769
        Y.error("simulateTouchEvent(): Invalid target.");
770
    }
771
 
772
    //check event type
773
    if (Y.Lang.isString(type)) {
774
        type = type.toLowerCase();
775
 
776
        //make sure it's a supported touch event
777
        if (!touchEvents[type]){
778
            Y.error("simulateTouchEvent(): Event type '" + type + "' not supported.");
779
        }
780
    } else {
781
        Y.error("simulateTouchEvent(): Event type must be a string.");
782
    }
783
 
784
    // note that the caller is responsible to pass appropriate touch objects.
785
    // check touch objects
786
    // Android(even 4.0) doesn't define TouchList yet
787
    /*if(type === 'touchstart' || type === 'touchmove') {
788
        if(!touches instanceof TouchList) {
789
            Y.error('simulateTouchEvent(): Invalid touches. It must be a TouchList');
790
        } else {
791
            if(touches.length === 0) {
792
                Y.error('simulateTouchEvent(): No touch object found.');
793
            }
794
        }
795
    } else if(type === 'touchend') {
796
        if(!changedTouches instanceof TouchList) {
797
            Y.error('simulateTouchEvent(): Invalid touches. It must be a TouchList');
798
        } else {
799
            if(changedTouches.length === 0) {
800
                Y.error('simulateTouchEvent(): No touch object found.');
801
            }
802
        }
803
    }*/
804
 
805
    if(type === 'touchstart' || type === 'touchmove') {
806
        if(touches.length === 0) {
807
            Y.error('simulateTouchEvent(): No touch object in touches');
808
        }
809
    } else if(type === 'touchend') {
810
        if(changedTouches.length === 0) {
811
            Y.error('simulateTouchEvent(): No touch object in changedTouches');
812
        }
813
    }
814
 
815
    // setup default values
816
    if (!Y.Lang.isBoolean(bubbles)) { bubbles = true; } // bubble by default.
817
    if (!Y.Lang.isBoolean(cancelable)) {
818
        cancelable = (type !== "touchcancel"); // touchcancel is not cancelled
819
    }
820
    if (!Y.Lang.isObject(view))     { view = Y.config.win; }
821
    if (!Y.Lang.isNumber(detail))   { detail = 1; } // usually not used. defaulted to # of touch objects.
822
    if (!Y.Lang.isNumber(screenX))  { screenX = 0; }
823
    if (!Y.Lang.isNumber(screenY))  { screenY = 0; }
824
    if (!Y.Lang.isNumber(clientX))  { clientX = 0; }
825
    if (!Y.Lang.isNumber(clientY))  { clientY = 0; }
826
    if (!Y.Lang.isBoolean(ctrlKey)) { ctrlKey = false; }
827
    if (!Y.Lang.isBoolean(altKey))  { altKey = false; }
828
    if (!Y.Lang.isBoolean(shiftKey)){ shiftKey = false; }
829
    if (!Y.Lang.isBoolean(metaKey)) { metaKey = false; }
830
    if (!Y.Lang.isNumber(scale))    { scale = 1.0; }
831
    if (!Y.Lang.isNumber(rotation)) { rotation = 0.0; }
832
 
833
 
834
    //check for DOM-compliant browsers first
835
    if (Y.Lang.isFunction(Y.config.doc.createEvent)) {
836
        if (Y.UA.android) {
837
            /*
838
                * Couldn't find android start version that supports touch event.
839
                * Assumed supported(btw APIs broken till icecream sandwitch)
840
                * from the beginning.
841
            */
842
            if(Y.UA.android < 4.0) {
843
                /*
844
                    * Touch APIs are broken in androids older than 4.0. We will use
845
                    * simulated touch apis for these versions.
846
                    * App developer still can listen for touch events. This events
847
                    * will be dispatched with touch event types.
848
                    *
849
                    * (Note) Used target for the relatedTarget. Need to verify if
850
                    * it has a side effect.
851
                */
852
                customEvent = Y.config.doc.createEvent("MouseEvents");
853
                customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,
854
                    screenX, screenY, clientX, clientY,
855
                    ctrlKey, altKey, shiftKey, metaKey,
856
                    0, target);
857
 
858
                customEvent.touches = touches;
859
                customEvent.targetTouches = targetTouches;
860
                customEvent.changedTouches = changedTouches;
861
            } else {
862
                customEvent = Y.config.doc.createEvent("TouchEvent");
863
 
864
                // Andoroid isn't compliant W3C initTouchEvent method signature.
865
                customEvent.initTouchEvent(touches, targetTouches, changedTouches,
866
                    type, view,
867
                    screenX, screenY, clientX, clientY,
868
                    ctrlKey, altKey, shiftKey, metaKey);
869
            }
870
        } else if (Y.UA.ios) {
871
            if(Y.UA.ios >= 2.0) {
872
                customEvent = Y.config.doc.createEvent("TouchEvent");
873
 
874
                // Available iOS 2.0 and later
875
                customEvent.initTouchEvent(type, bubbles, cancelable, view, detail,
876
                    screenX, screenY, clientX, clientY,
877
                    ctrlKey, altKey, shiftKey, metaKey,
878
                    touches, targetTouches, changedTouches,
879
                    scale, rotation);
880
            } else {
881
                Y.error('simulateTouchEvent(): No touch event simulation framework present for iOS, '+Y.UA.ios+'.');
882
            }
883
        } else {
884
            Y.error('simulateTouchEvent(): Not supported agent yet, '+Y.UA.userAgent);
885
        }
886
 
887
        //fire the event
888
        target.dispatchEvent(customEvent);
889
    //} else if (Y.Lang.isObject(doc.createEventObject)){ // Windows Mobile/IE, support later
890
    } else {
891
        Y.error('simulateTouchEvent(): No event simulation framework present.');
892
    }
893
}
894
 
895
/**
896
 * Simulates the event or gesture with the given name on a target.
897
 * @param {HTMLElement} target The DOM element that's the target of the event.
898
 * @param {String} type The type of event or name of the supported gesture to simulate
899
 *      (i.e., "click", "doubletap", "flick").
900
 * @param {Object} options (Optional) Extra options to copy onto the event object.
901
 *      For gestures, options are used to refine the gesture behavior.
902
 * @for Event
903
 * @method simulate
904
 * @static
905
 */
906
Y.Event.simulate = function(target, type, options){
907
 
908
    options = options || {};
909
 
910
    if (mouseEvents[type] || pointerEvents[type]){
911
        simulateMouseEvent(target, type, options.bubbles,
912
            options.cancelable, options.view, options.detail, options.screenX,
913
            options.screenY, options.clientX, options.clientY, options.ctrlKey,
914
            options.altKey, options.shiftKey, options.metaKey, options.button,
915
            options.relatedTarget);
916
    } else if (keyEvents[type]){
917
        simulateKeyEvent(target, type, options.bubbles,
918
            options.cancelable, options.view, options.ctrlKey,
919
            options.altKey, options.shiftKey, options.metaKey,
920
            options.keyCode, options.charCode);
921
    } else if (uiEvents[type]){
922
        simulateUIEvent(target, type, options.bubbles,
923
            options.cancelable, options.view, options.detail);
924
 
925
    // touch low-level event simulation
926
    } else if (touchEvents[type]) {
927
        if((Y.config.win && ("ontouchstart" in Y.config.win)) && !(Y.UA.phantomjs) && !(Y.UA.chrome && Y.UA.chrome < 6)) {
928
            simulateTouchEvent(target, type,
929
                options.bubbles, options.cancelable, options.view, options.detail,
930
                options.screenX, options.screenY, options.clientX, options.clientY,
931
                options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
932
                options.touches, options.targetTouches, options.changedTouches,
933
                options.scale, options.rotation);
934
        } else {
935
            Y.error("simulate(): Event '" + type + "' can't be simulated. Use gesture-simulate module instead.");
936
        }
937
 
938
    // ios gesture low-level event simulation (iOS v2+ only)
939
    } else if(Y.UA.ios && Y.UA.ios >= 2.0 && gestureEvents[type]) {
940
        simulateGestureEvent(target, type,
941
            options.bubbles, options.cancelable, options.view, options.detail,
942
            options.screenX, options.screenY, options.clientX, options.clientY,
943
            options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
944
            options.scale, options.rotation);
945
 
946
    // anything else
947
    } else {
948
        Y.error("simulate(): Event '" + type + "' can't be simulated.");
949
    }
950
};
951
 
952
 
953
})();
954
 
955
 
956
 
957
}, '3.18.1', {"requires": ["event-base"]});