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