summaryrefslogtreecommitdiff
path: root/includes/js/dojo/_base/event.js
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojo/_base/event.js')
-rw-r--r--includes/js/dojo/_base/event.js529
1 files changed, 529 insertions, 0 deletions
diff --git a/includes/js/dojo/_base/event.js b/includes/js/dojo/_base/event.js
new file mode 100644
index 0000000..41cfd4d
--- /dev/null
+++ b/includes/js/dojo/_base/event.js
@@ -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)); };
+ }
+}
+
+}