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