]> git.pond.sub.org Git - eow/blobdiff - static/dojo-release-1.1.1/dojo/_base/event.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojo / _base / event.js
diff --git a/static/dojo-release-1.1.1/dojo/_base/event.js b/static/dojo-release-1.1.1/dojo/_base/event.js
new file mode 100644 (file)
index 0000000..41cfd4d
--- /dev/null
@@ -0,0 +1,529 @@
+if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.event"] = true;
+dojo.provide("dojo._base.event");
+dojo.require("dojo._base.connect");
+
+// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
+
+(function(){
+       // DOM event listener machinery
+       var del = (dojo._event_listener = {
+               add: function(/*DOMNode*/node, /*String*/name, /*Function*/fp){
+                       if(!node){return;} 
+                       name = del._normalizeEventName(name);
+                       fp = del._fixCallback(name, fp);
+                       var oname = name;
+                       if(!dojo.isIE && (name == "mouseenter" || name == "mouseleave")){
+                               var ofp = fp;
+                               //oname = name;
+                               name = (name == "mouseenter") ? "mouseover" : "mouseout";
+                               fp = function(e){
+                                       // thanks ben!
+                                       if(!dojo.isDescendant(e.relatedTarget, node)){
+                                               // e.type = oname; // FIXME: doesn't take? SJM: event.type is generally immutable.
+                                               return ofp.call(this, e); 
+                                       }
+                               }
+                       }
+                       node.addEventListener(name, fp, false);
+                       return fp; /*Handle*/
+               },
+               remove: function(/*DOMNode*/node, /*String*/event, /*Handle*/handle){
+                       // summary:
+                       //              clobbers the listener from the node
+                       // node:
+                       //              DOM node to attach the event to
+                       // event:
+                       //              the name of the handler to remove the function from
+                       // handle:
+                       //              the handle returned from add
+                       if (node){
+                               node.removeEventListener(del._normalizeEventName(event), handle, false);
+                       }
+               },
+               _normalizeEventName: function(/*String*/name){
+                       // Generally, name should be lower case, unless it is special
+                       // somehow (e.g. a Mozilla DOM event).
+                       // Remove 'on'.
+                       return name.slice(0,2) =="on" ? name.slice(2) : name;
+               },
+               _fixCallback: function(/*String*/name, fp){
+                       // By default, we only invoke _fixEvent for 'keypress'
+                       // If code is added to _fixEvent for other events, we have
+                       // to revisit this optimization.
+                       // This also applies to _fixEvent overrides for Safari and Opera
+                       // below.
+                       return name != "keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); };
+               },
+               _fixEvent: function(evt, sender){
+                       // _fixCallback only attaches us to keypress.
+                       // Switch on evt.type anyway because we might 
+                       // be called directly from dojo.fixEvent.
+                       switch(evt.type){
+                               case "keypress":
+                                       del._setKeyChar(evt);
+                                       break;
+                       }
+                       return evt;
+               },
+               _setKeyChar: function(evt){
+                       evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
+               }
+       });
+
+       // DOM events
+       
+       dojo.fixEvent = function(/*Event*/evt, /*DOMNode*/sender){
+               // summary:
+               //              normalizes properties on the event object including event
+               //              bubbling methods, keystroke normalization, and x/y positions
+               // evt: Event
+               //              native event object
+               // sender: DOMNode
+               //              node to treat as "currentTarget"
+               return del._fixEvent(evt, sender);
+       }
+
+       dojo.stopEvent = function(/*Event*/evt){
+               // summary:
+               //              prevents propagation and clobbers the default action of the
+               //              passed event
+               // evt: Event
+               //              The event object. If omitted, window.event is used on IE.
+               evt.preventDefault();
+               evt.stopPropagation();
+               // NOTE: below, this method is overridden for IE
+       }
+
+       // the default listener to use on dontFix nodes, overriden for IE
+       var node_listener = dojo._listener;
+       
+       // Unify connect and event listeners
+       dojo._connect = function(obj, event, context, method, dontFix){
+               // FIXME: need a more strict test
+               var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
+               // choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
+               // we need the third option to provide leak prevention on broken browsers (IE)
+               var lid = !isNode ? 0 : (!dontFix ? 1 : 2), l = [dojo._listener, del, node_listener][lid];
+               // create a listener
+               var h = l.add(obj, event, dojo.hitch(context, method));
+               // formerly, the disconnect package contained "l" directly, but if client code
+               // leaks the disconnect package (by connecting it to a node), referencing "l" 
+               // compounds the problem.
+               // instead we return a listener id, which requires custom _disconnect below.
+               // return disconnect package
+               return [ obj, event, h, lid ];
+       }
+
+       dojo._disconnect = function(obj, event, handle, listener){
+               ([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
+       }
+
+       // Constants
+
+       // Public: client code should test
+       // keyCode against these named constants, as the
+       // actual codes can vary by browser.
+       dojo.keys = {
+               // summary: definitions for common key values
+               BACKSPACE: 8,
+               TAB: 9,
+               CLEAR: 12,
+               ENTER: 13,
+               SHIFT: 16,
+               CTRL: 17,
+               ALT: 18,
+               PAUSE: 19,
+               CAPS_LOCK: 20,
+               ESCAPE: 27,
+               SPACE: 32,
+               PAGE_UP: 33,
+               PAGE_DOWN: 34,
+               END: 35,
+               HOME: 36,
+               LEFT_ARROW: 37,
+               UP_ARROW: 38,
+               RIGHT_ARROW: 39,
+               DOWN_ARROW: 40,
+               INSERT: 45,
+               DELETE: 46,
+               HELP: 47,
+               LEFT_WINDOW: 91,
+               RIGHT_WINDOW: 92,
+               SELECT: 93,
+               NUMPAD_0: 96,
+               NUMPAD_1: 97,
+               NUMPAD_2: 98,
+               NUMPAD_3: 99,
+               NUMPAD_4: 100,
+               NUMPAD_5: 101,
+               NUMPAD_6: 102,
+               NUMPAD_7: 103,
+               NUMPAD_8: 104,
+               NUMPAD_9: 105,
+               NUMPAD_MULTIPLY: 106,
+               NUMPAD_PLUS: 107,
+               NUMPAD_ENTER: 108,
+               NUMPAD_MINUS: 109,
+               NUMPAD_PERIOD: 110,
+               NUMPAD_DIVIDE: 111,
+               F1: 112,
+               F2: 113,
+               F3: 114,
+               F4: 115,
+               F5: 116,
+               F6: 117,
+               F7: 118,
+               F8: 119,
+               F9: 120,
+               F10: 121,
+               F11: 122,
+               F12: 123,
+               F13: 124,
+               F14: 125,
+               F15: 126,
+               NUM_LOCK: 144,
+               SCROLL_LOCK: 145
+       };
+       
+       // IE event normalization
+       if(dojo.isIE){ 
+               var _trySetKeyCode = function(e, code){
+                       try{
+                               // squelch errors when keyCode is read-only
+                               // (e.g. if keyCode is ctrl or shift)
+                               return (e.keyCode = code);
+                       }catch(e){
+                               return 0;
+                       }
+               }
+
+               // by default, use the standard listener
+               var iel = dojo._listener;
+               // dispatcher tracking property
+               if(!dojo.config._allow_leaks){
+                       // custom listener that handles leak protection for DOM events
+                       node_listener = iel = dojo._ie_listener = {
+                               // support handler indirection: event handler functions are 
+                               // referenced here. Event dispatchers hold only indices.
+                               handlers: [],
+                               // add a listener to an object
+                               add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
+                                       source = source || dojo.global;
+                                       var f = source[method];
+                                       if(!f||!f._listeners){
+                                               var d = dojo._getIeDispatcher();
+                                               // original target function is special
+                                               d.target = f && (ieh.push(f) - 1);
+                                               // dispatcher holds a list of indices into handlers table
+                                               d._listeners = [];
+                                               // redirect source to dispatcher
+                                               f = source[method] = d;
+                                       }
+                                       return f._listeners.push(ieh.push(listener) - 1) ; /*Handle*/
+                               },
+                               // remove a listener from an object
+                               remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
+                                       var f = (source||dojo.global)[method], l = f && f._listeners;
+                                       if(f && l && handle--){
+                                               delete ieh[l[handle]];
+                                               delete l[handle];
+                                       }
+                               }
+                       };
+                       // alias used above
+                       var ieh = iel.handlers;
+               }
+
+               dojo.mixin(del, {
+                       add: function(/*DOMNode*/node, /*String*/event, /*Function*/fp){
+                               if(!node){return;} // undefined
+                               event = del._normalizeEventName(event);
+                               if(event=="onkeypress"){
+                                       // we need to listen to onkeydown to synthesize
+                                       // keypress events that otherwise won't fire
+                                       // on IE
+                                       var kd = node.onkeydown;
+                                       if(!kd || !kd._listeners || !kd._stealthKeydownHandle){
+                                               var h = del.add(node, "onkeydown", del._stealthKeyDown);
+                                               kd = node.onkeydown;
+                                               kd._stealthKeydownHandle = h;
+                                               kd._stealthKeydownRefs = 1;
+                                       }else{
+                                               kd._stealthKeydownRefs++;
+                                       }
+                               }
+                               return iel.add(node, event, del._fixCallback(fp));
+                       },
+                       remove: function(/*DOMNode*/node, /*String*/event, /*Handle*/handle){
+                               event = del._normalizeEventName(event);
+                               iel.remove(node, event, handle); 
+                               if(event=="onkeypress"){
+                                       var kd = node.onkeydown;
+                                       if(--kd._stealthKeydownRefs <= 0){
+                                               iel.remove(node, "onkeydown", kd._stealthKeydownHandle);
+                                               delete kd._stealthKeydownHandle;
+                                       }
+                               }
+                       },
+                       _normalizeEventName: function(/*String*/eventName){
+                               // Generally, eventName should be lower case, unless it is
+                               // special somehow (e.g. a Mozilla event)
+                               // ensure 'on'
+                               return eventName.slice(0,2) != "on" ? "on" + eventName : eventName;
+                       },
+                       _nop: function(){},
+                       _fixEvent: function(/*Event*/evt, /*DOMNode*/sender){
+                               // summary:
+                               //              normalizes properties on the event object including event
+                               //              bubbling methods, keystroke normalization, and x/y positions
+                               // evt: native event object
+                               // sender: node to treat as "currentTarget"
+                               if(!evt){
+                                       var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window;
+                                       evt = w.event; 
+                               }
+                               if(!evt){return(evt);}
+                               evt.target = evt.srcElement; 
+                               evt.currentTarget = (sender || evt.srcElement); 
+                               evt.layerX = evt.offsetX;
+                               evt.layerY = evt.offsetY;
+                               // FIXME: scroll position query is duped from dojo.html to
+                               // avoid dependency on that entire module. Now that HTML is in
+                               // Base, we should convert back to something similar there.
+                               var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
+                               // DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
+                               // here rather than document.body
+                               var docBody = ((dojo.isIE < 6) || (doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
+                               var offset = dojo._getIeDocumentElementOffset();
+                               evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
+                               evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
+                               if(evt.type == "mouseover"){ 
+                                       evt.relatedTarget = evt.fromElement;
+                               }
+                               if(evt.type == "mouseout"){ 
+                                       evt.relatedTarget = evt.toElement;
+                               }
+                               evt.stopPropagation = del._stopPropagation;
+                               evt.preventDefault = del._preventDefault;
+                               return del._fixKeys(evt);
+                       },
+                       _fixKeys: function(evt){
+                               switch(evt.type){
+                                       case "keypress":
+                                               var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
+                                               if (c==10){
+                                                       // CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
+                                                       c=0;
+                                                       evt.keyCode = 13;
+                                               }else if(c==13||c==27){
+                                                       c=0; // Mozilla considers ENTER and ESC non-printable
+                                               }else if(c==3){
+                                                       c=99; // Mozilla maps CTRL-BREAK to CTRL-c
+                                               }
+                                               // Mozilla sets keyCode to 0 when there is a charCode
+                                               // but that stops the event on IE.
+                                               evt.charCode = c;
+                                               del._setKeyChar(evt);
+                                               break;
+                               }
+                               return evt;
+                       },
+                       // some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
+                       // we map those virtual key codes to ascii here
+                       // not valid for all (non-US) keyboards, so maybe we shouldn't bother
+                       _punctMap: { 
+                               106:42, 
+                               111:47, 
+                               186:59, 
+                               187:43, 
+                               188:44, 
+                               189:45, 
+                               190:46, 
+                               191:47, 
+                               192:96, 
+                               219:91, 
+                               220:92, 
+                               221:93, 
+                               222:39 
+                       },
+                       _stealthKeyDown: function(evt){
+                               // IE doesn't fire keypress for most non-printable characters.
+                               // other browsers do, we simulate it here.
+                               var kp = evt.currentTarget.onkeypress;
+                               // only works if kp exists and is a dispatcher
+                               if(!kp || !kp._listeners){ return; }
+                               // munge key/charCode
+                               var k=evt.keyCode;
+                               // These are Windows Virtual Key Codes
+                               // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
+                               var unprintable = (k!=13)&&(k!=32)&&(k!=27)&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222);
+                               // synthesize keypress for most unprintables and CTRL-keys
+                               if(unprintable||evt.ctrlKey){
+                                       var c = unprintable ? 0 : k;
+                                       if(evt.ctrlKey){
+                                               if(k==3 || k==13){
+                                                       return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively 
+                                               }else if(c>95 && c<106){ 
+                                                       c -= 48; // map CTRL-[numpad 0-9] to ASCII
+                                               }else if((!evt.shiftKey)&&(c>=65&&c<=90)){ 
+                                                       c += 32; // map CTRL-[A-Z] to lowercase
+                                               }else{ 
+                                                       c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
+                                               }
+                                       }
+                                       // simulate a keypress event
+                                       var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
+                                       kp.call(evt.currentTarget, faux);
+                                       evt.cancelBubble = faux.cancelBubble;
+                                       evt.returnValue = faux.returnValue;
+                                       _trySetKeyCode(evt, faux.keyCode);
+                               }
+                       },
+                       // Called in Event scope
+                       _stopPropagation: function(){
+                               this.cancelBubble = true; 
+                       },
+                       _preventDefault: function(){
+                               // Setting keyCode to 0 is the only way to prevent certain keypresses (namely
+                               // ctrl-combinations that correspond to menu accelerator keys).
+                               // Otoh, it prevents upstream listeners from getting this information
+                               // Try to split the difference here by clobbering keyCode only for ctrl 
+                               // combinations. If you still need to access the key upstream, bubbledKeyCode is
+                               // provided as a workaround.
+                               this.bubbledKeyCode = this.keyCode;
+                               if(this.ctrlKey){_trySetKeyCode(this, 0);}
+                               this.returnValue = false;
+                       }
+               });
+                               
+               // override stopEvent for IE
+               dojo.stopEvent = function(evt){
+                       evt = evt || window.event;
+                       del._stopPropagation.call(evt);
+                       del._preventDefault.call(evt);
+               }
+       }
+
+       del._synthesizeEvent = function(evt, props){
+                       var faux = dojo.mixin({}, evt, props);
+                       del._setKeyChar(faux);
+                       // FIXME: would prefer to use dojo.hitch: dojo.hitch(evt, evt.preventDefault); 
+                       // but it throws an error when preventDefault is invoked on Safari
+                       // does Event.preventDefault not support "apply" on Safari?
+                       faux.preventDefault = function(){ evt.preventDefault(); }; 
+                       faux.stopPropagation = function(){ evt.stopPropagation(); }; 
+                       return faux;
+       }
+       
+       // Opera event normalization
+       if(dojo.isOpera){
+               dojo.mixin(del, {
+                       _fixEvent: function(evt, sender){
+                               switch(evt.type){
+                                       case "keypress":
+                                               var c = evt.which;
+                                               if(c==3){
+                                                       c=99; // Mozilla maps CTRL-BREAK to CTRL-c
+                                               }
+                                               // can't trap some keys at all, like INSERT and DELETE
+                                               // there is no differentiating info between DELETE and ".", or INSERT and "-"
+                                               c = ((c<41)&&(!evt.shiftKey) ? 0 : c);
+                                               if((evt.ctrlKey)&&(!evt.shiftKey)&&(c>=65)&&(c<=90)){
+                                                       // lowercase CTRL-[A-Z] keys
+                                                       c += 32;
+                                               }
+                                               return del._synthesizeEvent(evt, { charCode: c });
+                               }
+                               return evt;
+                       }
+               });
+       }
+
+       // Safari event normalization
+       if(dojo.isSafari){
+               dojo.mixin(del, {
+                       _fixEvent: function(evt, sender){
+                               switch(evt.type){
+                                       case "keypress":
+                                               var c = evt.charCode, s = evt.shiftKey, k = evt.keyCode;
+                                               // FIXME: This is a hack, suggest we rethink keyboard strategy.
+                                               // Arrow and page keys have 0 "keyCode" in keypress events.on Safari for Windows
+                                               k = k || identifierMap[evt.keyIdentifier] || 0;
+                                               if(evt.keyIdentifier=="Enter"){
+                                                       c = 0; // differentiate Enter from CTRL-m (both code 13)
+                                               }else if((evt.ctrlKey)&&(c>0)&&(c<27)){
+                                                       c += 96; // map CTRL-[A-Z] codes to ASCII
+                                               } else if (c==dojo.keys.SHIFT_TAB) {
+                                                       c = dojo.keys.TAB; // morph SHIFT_TAB into TAB + shiftKey: true
+                                                       s = true;
+                                               } else {
+                                                       c = (c>=32 && c<63232 ? c : 0); // avoid generating keyChar for non-printables
+                                               }
+                                               return del._synthesizeEvent(evt, {charCode: c, shiftKey: s, keyCode: k});
+                               }
+                               return evt;
+                       }
+               });
+               
+               dojo.mixin(dojo.keys, {
+                       SHIFT_TAB: 25,
+                       UP_ARROW: 63232,
+                       DOWN_ARROW: 63233,
+                       LEFT_ARROW: 63234,
+                       RIGHT_ARROW: 63235,
+                       F1: 63236,
+                       F2: 63237,
+                       F3: 63238,
+                       F4: 63239,
+                       F5: 63240,
+                       F6: 63241,
+                       F7: 63242,
+                       F8: 63243,
+                       F9: 63244,
+                       F10: 63245,
+                       F11: 63246,
+                       F12: 63247,
+                       PAUSE: 63250,
+                       DELETE: 63272,
+                       HOME: 63273,
+                       END: 63275,
+                       PAGE_UP: 63276,
+                       PAGE_DOWN: 63277,
+                       INSERT: 63302,
+                       PRINT_SCREEN: 63248,
+                       SCROLL_LOCK: 63249,
+                       NUM_LOCK: 63289
+               });
+               var dk = dojo.keys, identifierMap = { "Up": dk.UP_ARROW, "Down": dk.DOWN_ARROW, "Left": dk.LEFT_ARROW, "Right": dk.RIGHT_ARROW, "PageUp": dk.PAGE_UP, "PageDown": dk.PAGE_DOWN }; 
+       }
+})();
+
+if(dojo.isIE){
+       // keep this out of the closure
+       // closing over 'iel' or 'ieh' b0rks leak prevention
+       // ls[i] is an index into the master handler array
+       dojo._ieDispatcher = function(args, sender){
+               var ap=Array.prototype, h=dojo._ie_listener.handlers, c=args.callee, ls=c._listeners, t=h[c.target];
+               // return value comes from original target function
+               var r = t && t.apply(sender, args);
+               // invoke listeners after target function
+               for(var i in ls){
+                       if(!(i in ap)){
+                               h[ls[i]].apply(sender, args);
+                       }
+               }
+               return r;
+       }
+       dojo._getIeDispatcher = function(){
+               // ensure the returned function closes over nothing
+               return new Function(dojo._scopeName + "._ieDispatcher(arguments, this)"); // function
+       }
+       // keep this out of the closure to reduce RAM allocation
+       dojo._event_listener._fixCallback = function(fp){
+               var f = dojo._event_listener._fixEvent;
+               return function(e){ return fp.call(this, f(e, this)); };
+       }
+}
+
+}