]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/event-simulate/event-simulate.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / event-simulate / event-simulate.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('event-simulate', function(Y) {
9
10 (function() {
11 /**
12  * Synthetic DOM events
13  * @module event-simulate
14  * @requires event
15  */
16
17 //shortcuts
18 var L   = Y.Lang,
19     array       = Y.Array,
20     isFunction  = L.isFunction,
21     isString    = L.isString,
22     isBoolean   = L.isBoolean,
23     isObject    = L.isObject,
24     isNumber    = L.isNumber,
25     doc         = Y.config.doc,
26
27     //mouse events supported
28     mouseEvents = {
29         click:      1,
30         dblclick:   1,
31         mouseover:  1,
32         mouseout:   1,
33         mousedown:  1,
34         mouseup:    1,
35         mousemove:  1
36     },
37
38     //key events supported
39     keyEvents   = {
40         keydown:    1,
41         keyup:      1,
42         keypress:   1
43     },
44
45     //HTML events supported
46     uiEvents  = {
47         blur:       1,
48         change:     1,
49         focus:      1,
50         resize:     1,
51         scroll:     1,
52         select:     1
53     },
54
55     //events that bubble by default
56     bubbleEvents = {
57         scroll:     1,
58         resize:     1,
59         reset:      1,
60         submit:     1,
61         change:     1,
62         select:     1,
63         error:      1,
64         abort:      1
65     };
66
67 //all key and mouse events bubble
68 Y.mix(bubbleEvents, mouseEvents);
69 Y.mix(bubbleEvents, keyEvents);
70
71 /*
72  * Note: Intentionally not for YUIDoc generation.
73  * Simulates a key event using the given event information to populate
74  * the generated event object. This method does browser-equalizing
75  * calculations to account for differences in the DOM and IE event models
76  * as well as different browser quirks. Note: keydown causes Safari 2.x to
77  * crash.
78  * @method simulateKeyEvent
79  * @private
80  * @static
81  * @param {HTMLElement} target The target of the given event.
82  * @param {String} type The type of event to fire. This can be any one of
83  *      the following: keyup, keydown, and keypress.
84  * @param {Boolean} bubbles (Optional) Indicates if the event can be
85  *      bubbled up. DOM Level 3 specifies that all key events bubble by
86  *      default. The default is true.
87  * @param {Boolean} cancelable (Optional) Indicates if the event can be
88  *      canceled using preventDefault(). DOM Level 3 specifies that all
89  *      key events can be cancelled. The default
90  *      is true.
91  * @param {Window} view (Optional) The view containing the target. This is
92  *      typically the window object. The default is window.
93  * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
94  *      is pressed while the event is firing. The default is false.
95  * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
96  *      is pressed while the event is firing. The default is false.
97  * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
98  *      is pressed while the event is firing. The default is false.
99  * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
100  *      is pressed while the event is firing. The default is false.
101  * @param {int} keyCode (Optional) The code for the key that is in use.
102  *      The default is 0.
103  * @param {int} charCode (Optional) The Unicode code for the character
104  *      associated with the key being used. The default is 0.
105  */
106 function simulateKeyEvent(target /*:HTMLElement*/, type /*:String*/,
107                              bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
108                              view /*:Window*/,
109                              ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,
110                              shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,
111                              keyCode /*:int*/,        charCode /*:int*/) /*:Void*/
112 {
113     //check target
114     if (!target){
115         Y.error("simulateKeyEvent(): Invalid target.");
116     }
117
118     //check event type
119     if (isString(type)){
120         type = type.toLowerCase();
121         switch(type){
122             case "textevent": //DOM Level 3
123                 type = "keypress";
124                 break;
125             case "keyup":
126             case "keydown":
127             case "keypress":
128                 break;
129             default:
130                 Y.error("simulateKeyEvent(): Event type '" + type + "' not supported.");
131         }
132     } else {
133         Y.error("simulateKeyEvent(): Event type must be a string.");
134     }
135
136     //setup default values
137     if (!isBoolean(bubbles)){
138         bubbles = true; //all key events bubble
139     }
140     if (!isBoolean(cancelable)){
141         cancelable = true; //all key events can be cancelled
142     }
143     if (!isObject(view)){
144         view = window; //view is typically window
145     }
146     if (!isBoolean(ctrlKey)){
147         ctrlKey = false;
148     }
149     if (!isBoolean(altKey)){
150         altKey = false;
151     }
152     if (!isBoolean(shiftKey)){
153         shiftKey = false;
154     }
155     if (!isBoolean(metaKey)){
156         metaKey = false;
157     }
158     if (!isNumber(keyCode)){
159         keyCode = 0;
160     }
161     if (!isNumber(charCode)){
162         charCode = 0;
163     }
164
165     //try to create a mouse event
166     var customEvent /*:MouseEvent*/ = null;
167
168     //check for DOM-compliant browsers first
169     if (isFunction(doc.createEvent)){
170
171         try {
172
173             //try to create key event
174             customEvent = doc.createEvent("KeyEvents");
175
176             /*
177              * Interesting problem: Firefox implemented a non-standard
178              * version of initKeyEvent() based on DOM Level 2 specs.
179              * Key event was removed from DOM Level 2 and re-introduced
180              * in DOM Level 3 with a different interface. Firefox is the
181              * only browser with any implementation of Key Events, so for
182              * now, assume it's Firefox if the above line doesn't error.
183              */
184             // @TODO: Decipher between Firefox's implementation and a correct one.
185             customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey,
186                 altKey, shiftKey, metaKey, keyCode, charCode);
187
188         } catch (ex /*:Error*/){
189
190             /*
191              * If it got here, that means key events aren't officially supported.
192              * Safari/WebKit is a real problem now. WebKit 522 won't let you
193              * set keyCode, charCode, or other properties if you use a
194              * UIEvent, so we first must try to create a generic event. The
195              * fun part is that this will throw an error on Safari 2.x. The
196              * end result is that we need another try...catch statement just to
197              * deal with this mess.
198              */
199             try {
200
201                 //try to create generic event - will fail in Safari 2.x
202                 customEvent = doc.createEvent("Events");
203
204             } catch (uierror /*:Error*/){
205
206                 //the above failed, so create a UIEvent for Safari 2.x
207                 customEvent = doc.createEvent("UIEvents");
208
209             } finally {
210
211                 customEvent.initEvent(type, bubbles, cancelable);
212
213                 //initialize
214                 customEvent.view = view;
215                 customEvent.altKey = altKey;
216                 customEvent.ctrlKey = ctrlKey;
217                 customEvent.shiftKey = shiftKey;
218                 customEvent.metaKey = metaKey;
219                 customEvent.keyCode = keyCode;
220                 customEvent.charCode = charCode;
221
222             }
223
224         }
225
226         //fire the event
227         target.dispatchEvent(customEvent);
228
229     } else if (isObject(doc.createEventObject)){ //IE
230
231         //create an IE event object
232         customEvent = doc.createEventObject();
233
234         //assign available properties
235         customEvent.bubbles = bubbles;
236         customEvent.cancelable = cancelable;
237         customEvent.view = view;
238         customEvent.ctrlKey = ctrlKey;
239         customEvent.altKey = altKey;
240         customEvent.shiftKey = shiftKey;
241         customEvent.metaKey = metaKey;
242
243         /*
244          * IE doesn't support charCode explicitly. CharCode should
245          * take precedence over any keyCode value for accurate
246          * representation.
247          */
248         customEvent.keyCode = (charCode > 0) ? charCode : keyCode;
249
250         //fire the event
251         target.fireEvent("on" + type, customEvent);
252
253     } else {
254         Y.error("simulateKeyEvent(): No event simulation framework present.");
255     }
256 }
257
258 /*
259  * Note: Intentionally not for YUIDoc generation.
260  * Simulates a mouse event using the given event information to populate
261  * the generated event object. This method does browser-equalizing
262  * calculations to account for differences in the DOM and IE event models
263  * as well as different browser quirks.
264  * @method simulateMouseEvent
265  * @private
266  * @static
267  * @param {HTMLElement} target The target of the given event.
268  * @param {String} type The type of event to fire. This can be any one of
269  *      the following: click, dblclick, mousedown, mouseup, mouseout,
270  *      mouseover, and mousemove.
271  * @param {Boolean} bubbles (Optional) Indicates if the event can be
272  *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
273  *      default. The default is true.
274  * @param {Boolean} cancelable (Optional) Indicates if the event can be
275  *      canceled using preventDefault(). DOM Level 2 specifies that all
276  *      mouse events except mousemove can be cancelled. The default
277  *      is true for all events except mousemove, for which the default
278  *      is false.
279  * @param {Window} view (Optional) The view containing the target. This is
280  *      typically the window object. The default is window.
281  * @param {int} detail (Optional) The number of times the mouse button has
282  *      been used. The default value is 1.
283  * @param {int} screenX (Optional) The x-coordinate on the screen at which
284  *      point the event occured. The default is 0.
285  * @param {int} screenY (Optional) The y-coordinate on the screen at which
286  *      point the event occured. The default is 0.
287  * @param {int} clientX (Optional) The x-coordinate on the client at which
288  *      point the event occured. The default is 0.
289  * @param {int} clientY (Optional) The y-coordinate on the client at which
290  *      point the event occured. The default is 0.
291  * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
292  *      is pressed while the event is firing. The default is false.
293  * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
294  *      is pressed while the event is firing. The default is false.
295  * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
296  *      is pressed while the event is firing. The default is false.
297  * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
298  *      is pressed while the event is firing. The default is false.
299  * @param {int} button (Optional) The button being pressed while the event
300  *      is executing. The value should be 0 for the primary mouse button
301  *      (typically the left button), 1 for the terciary mouse button
302  *      (typically the middle button), and 2 for the secondary mouse button
303  *      (typically the right button). The default is 0.
304  * @param {HTMLElement} relatedTarget (Optional) For mouseout events,
305  *      this is the element that the mouse has moved to. For mouseover
306  *      events, this is the element that the mouse has moved from. This
307  *      argument is ignored for all other events. The default is null.
308  */
309 function simulateMouseEvent(target /*:HTMLElement*/, type /*:String*/,
310                                bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
311                                view /*:Window*/,        detail /*:int*/,
312                                screenX /*:int*/,        screenY /*:int*/,
313                                clientX /*:int*/,        clientY /*:int*/,
314                                ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,
315                                shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,
316                                button /*:int*/,         relatedTarget /*:HTMLElement*/) /*:Void*/
317 {
318
319     //check target
320     if (!target){
321         Y.error("simulateMouseEvent(): Invalid target.");
322     }
323
324     //check event type
325     if (isString(type)){
326         type = type.toLowerCase();
327
328         //make sure it's a supported mouse event
329         if (!mouseEvents[type]){
330             Y.error("simulateMouseEvent(): Event type '" + type + "' not supported.");
331         }
332     } else {
333         Y.error("simulateMouseEvent(): Event type must be a string.");
334     }
335
336     //setup default values
337     if (!isBoolean(bubbles)){
338         bubbles = true; //all mouse events bubble
339     }
340     if (!isBoolean(cancelable)){
341         cancelable = (type != "mousemove"); //mousemove is the only one that can't be cancelled
342     }
343     if (!isObject(view)){
344         view = window; //view is typically window
345     }
346     if (!isNumber(detail)){
347         detail = 1;  //number of mouse clicks must be at least one
348     }
349     if (!isNumber(screenX)){
350         screenX = 0;
351     }
352     if (!isNumber(screenY)){
353         screenY = 0;
354     }
355     if (!isNumber(clientX)){
356         clientX = 0;
357     }
358     if (!isNumber(clientY)){
359         clientY = 0;
360     }
361     if (!isBoolean(ctrlKey)){
362         ctrlKey = false;
363     }
364     if (!isBoolean(altKey)){
365         altKey = false;
366     }
367     if (!isBoolean(shiftKey)){
368         shiftKey = false;
369     }
370     if (!isBoolean(metaKey)){
371         metaKey = false;
372     }
373     if (!isNumber(button)){
374         button = 0;
375     }
376
377     relatedTarget = relatedTarget || null;
378
379     //try to create a mouse event
380     var customEvent /*:MouseEvent*/ = null;
381
382     //check for DOM-compliant browsers first
383     if (isFunction(doc.createEvent)){
384
385         customEvent = doc.createEvent("MouseEvents");
386
387         //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()
388         if (customEvent.initMouseEvent){
389             customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,
390                                  screenX, screenY, clientX, clientY,
391                                  ctrlKey, altKey, shiftKey, metaKey,
392                                  button, relatedTarget);
393         } else { //Safari
394
395             //the closest thing available in Safari 2.x is UIEvents
396             customEvent = doc.createEvent("UIEvents");
397             customEvent.initEvent(type, bubbles, cancelable);
398             customEvent.view = view;
399             customEvent.detail = detail;
400             customEvent.screenX = screenX;
401             customEvent.screenY = screenY;
402             customEvent.clientX = clientX;
403             customEvent.clientY = clientY;
404             customEvent.ctrlKey = ctrlKey;
405             customEvent.altKey = altKey;
406             customEvent.metaKey = metaKey;
407             customEvent.shiftKey = shiftKey;
408             customEvent.button = button;
409             customEvent.relatedTarget = relatedTarget;
410         }
411
412         /*
413          * Check to see if relatedTarget has been assigned. Firefox
414          * versions less than 2.0 don't allow it to be assigned via
415          * initMouseEvent() and the property is readonly after event
416          * creation, so in order to keep YAHOO.util.getRelatedTarget()
417          * working, assign to the IE proprietary toElement property
418          * for mouseout event and fromElement property for mouseover
419          * event.
420          */
421         if (relatedTarget && !customEvent.relatedTarget){
422             if (type == "mouseout"){
423                 customEvent.toElement = relatedTarget;
424             } else if (type == "mouseover"){
425                 customEvent.fromElement = relatedTarget;
426             }
427         }
428
429         //fire the event
430         target.dispatchEvent(customEvent);
431
432     } else if (isObject(doc.createEventObject)){ //IE
433
434         //create an IE event object
435         customEvent = doc.createEventObject();
436
437         //assign available properties
438         customEvent.bubbles = bubbles;
439         customEvent.cancelable = cancelable;
440         customEvent.view = view;
441         customEvent.detail = detail;
442         customEvent.screenX = screenX;
443         customEvent.screenY = screenY;
444         customEvent.clientX = clientX;
445         customEvent.clientY = clientY;
446         customEvent.ctrlKey = ctrlKey;
447         customEvent.altKey = altKey;
448         customEvent.metaKey = metaKey;
449         customEvent.shiftKey = shiftKey;
450
451         //fix button property for IE's wacky implementation
452         switch(button){
453             case 0:
454                 customEvent.button = 1;
455                 break;
456             case 1:
457                 customEvent.button = 4;
458                 break;
459             case 2:
460                 //leave as is
461                 break;
462             default:
463                 customEvent.button = 0;
464         }
465
466         /*
467          * Have to use relatedTarget because IE won't allow assignment
468          * to toElement or fromElement on generic events. This keeps
469          * YAHOO.util.customEvent.getRelatedTarget() functional.
470          */
471         customEvent.relatedTarget = relatedTarget;
472
473         //fire the event
474         target.fireEvent("on" + type, customEvent);
475
476     } else {
477         Y.error("simulateMouseEvent(): No event simulation framework present.");
478     }
479 }
480
481 /*
482  * Note: Intentionally not for YUIDoc generation.
483  * Simulates a UI event using the given event information to populate
484  * the generated event object. This method does browser-equalizing
485  * calculations to account for differences in the DOM and IE event models
486  * as well as different browser quirks.
487  * @method simulateHTMLEvent
488  * @private
489  * @static
490  * @param {HTMLElement} target The target of the given event.
491  * @param {String} type The type of event to fire. This can be any one of
492  *      the following: click, dblclick, mousedown, mouseup, mouseout,
493  *      mouseover, and mousemove.
494  * @param {Boolean} bubbles (Optional) Indicates if the event can be
495  *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
496  *      default. The default is true.
497  * @param {Boolean} cancelable (Optional) Indicates if the event can be
498  *      canceled using preventDefault(). DOM Level 2 specifies that all
499  *      mouse events except mousemove can be cancelled. The default
500  *      is true for all events except mousemove, for which the default
501  *      is false.
502  * @param {Window} view (Optional) The view containing the target. This is
503  *      typically the window object. The default is window.
504  * @param {int} detail (Optional) The number of times the mouse button has
505  *      been used. The default value is 1.
506  */
507 function simulateUIEvent(target /*:HTMLElement*/, type /*:String*/,
508                                bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
509                                view /*:Window*/,        detail /*:int*/) /*:Void*/
510 {
511
512     //check target
513     if (!target){
514         Y.error("simulateUIEvent(): Invalid target.");
515     }
516
517     //check event type
518     if (isString(type)){
519         type = type.toLowerCase();
520
521         //make sure it's a supported mouse event
522         if (!uiEvents[type]){
523             Y.error("simulateUIEvent(): Event type '" + type + "' not supported.");
524         }
525     } else {
526         Y.error("simulateUIEvent(): Event type must be a string.");
527     }
528
529     //try to create a mouse event
530     var customEvent = null;
531
532
533     //setup default values
534     if (!isBoolean(bubbles)){
535         bubbles = (type in bubbleEvents);  //not all events bubble
536     }
537     if (!isBoolean(cancelable)){
538         cancelable = (type == "submit"); //submit is the only one that can be cancelled
539     }
540     if (!isObject(view)){
541         view = window; //view is typically window
542     }
543     if (!isNumber(detail)){
544         detail = 1;  //usually not used but defaulted to this
545     }
546
547     //check for DOM-compliant browsers first
548     if (isFunction(doc.createEvent)){
549
550         //just a generic UI Event object is needed
551         customEvent = doc.createEvent("UIEvents");
552         customEvent.initUIEvent(type, bubbles, cancelable, view, detail);
553
554         //fire the event
555         target.dispatchEvent(customEvent);
556
557     } else if (isObject(doc.createEventObject)){ //IE
558
559         //create an IE event object
560         customEvent = doc.createEventObject();
561
562         //assign available properties
563         customEvent.bubbles = bubbles;
564         customEvent.cancelable = cancelable;
565         customEvent.view = view;
566         customEvent.detail = detail;
567
568         //fire the event
569         target.fireEvent("on" + type, customEvent);
570
571     } else {
572         Y.error("simulateUIEvent(): No event simulation framework present.");
573     }
574 }
575
576 /**
577  * Simulates the event with the given name on a target.
578  * @param {HTMLElement} target The DOM element that's the target of the event.
579  * @param {String} type The type of event to simulate (i.e., "click").
580  * @param {Object} options (Optional) Extra options to copy onto the event object.
581  * @return {void}
582  * @for Event
583  * @method simulate
584  * @static
585  */
586 Y.Event.simulate = function(target, type, options){
587
588     options = options || {};
589
590     if (mouseEvents[type]){
591         simulateMouseEvent(target, type, options.bubbles,
592             options.cancelable, options.view, options.detail, options.screenX,
593             options.screenY, options.clientX, options.clientY, options.ctrlKey,
594             options.altKey, options.shiftKey, options.metaKey, options.button,
595             options.relatedTarget);
596     } else if (keyEvents[type]){
597         simulateKeyEvent(target, type, options.bubbles,
598             options.cancelable, options.view, options.ctrlKey,
599             options.altKey, options.shiftKey, options.metaKey,
600             options.keyCode, options.charCode);
601     } else if (uiEvents[type]){
602         simulateUIEvent(target, type, options.bubbles,
603             options.cancelable, options.view, options.detail);
604      } else {
605         Y.error("simulate(): Event '" + type + "' can't be simulated.");
606     }
607 };
608
609
610 })();
611
612
613
614 }, '3.3.0' ,{requires:['event-base']});