From a089699c8915636ba4f158d77dba9b012bc93208 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 4 Mar 2011 19:02:28 +0300 Subject: build custom layer of Dojo to speed up loading of tt-rss (refs #293) --- lib/dojo/_base/event.js | 978 +++++++++++++++++++++++++++++++----------------- 1 file changed, 632 insertions(+), 346 deletions(-) (limited to 'lib/dojo/_base/event.js') diff --git a/lib/dojo/_base/event.js b/lib/dojo/_base/event.js index 1e6ef788a..5268c6cff 100644 --- a/lib/dojo/_base/event.js +++ b/lib/dojo/_base/event.js @@ -5,355 +5,641 @@ */ -if(!dojo._hasResource["dojo._base.event"]){ -dojo._hasResource["dojo._base.event"]=true; +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(){ -var _1=(dojo._event_listener={add:function(_2,_3,fp){ -if(!_2){ -return; -} -_3=_1._normalizeEventName(_3); -fp=_1._fixCallback(_3,fp); -var _4=_3; -if(!dojo.isIE&&(_3=="mouseenter"||_3=="mouseleave")){ -var _5=fp; -_3=(_3=="mouseenter")?"mouseover":"mouseout"; -fp=function(e){ -if(!dojo.isDescendant(e.relatedTarget,_2)){ -return _5.call(this,e); -} -}; -} -_2.addEventListener(_3,fp,false); -return fp; -},remove:function(_6,_7,_8){ -if(_6){ -_7=_1._normalizeEventName(_7); -if(!dojo.isIE&&(_7=="mouseenter"||_7=="mouseleave")){ -_7=(_7=="mouseenter")?"mouseover":"mouseout"; -} -_6.removeEventListener(_7,_8,false); -} -},_normalizeEventName:function(_9){ -return _9.slice(0,2)=="on"?_9.slice(2):_9; -},_fixCallback:function(_a,fp){ -return _a!="keypress"?fp:function(e){ -return fp.call(this,_1._fixEvent(e,this)); -}; -},_fixEvent:function(_b,_c){ -switch(_b.type){ -case "keypress": -_1._setKeyChar(_b); -break; -} -return _b; -},_setKeyChar:function(_d){ -_d.keyChar=_d.charCode?String.fromCharCode(_d.charCode):""; -_d.charOrCode=_d.keyChar||_d.keyCode; -},_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}}); -dojo.fixEvent=function(_e,_f){ -return _1._fixEvent(_e,_f); -}; -dojo.stopEvent=function(evt){ -evt.preventDefault(); -evt.stopPropagation(); -}; -var _10=dojo._listener; -dojo._connect=function(obj,_11,_12,_13,_14){ -var _15=obj&&(obj.nodeType||obj.attachEvent||obj.addEventListener); -var lid=_15?(_14?2:1):0,l=[dojo._listener,_1,_10][lid]; -var h=l.add(obj,_11,dojo.hitch(_12,_13)); -return [obj,_11,h,lid]; -}; -dojo._disconnect=function(obj,_16,_17,_18){ -([dojo._listener,_1,_10][_18]).remove(obj,_16,_17); -}; -dojo.keys={BACKSPACE:8,TAB:9,CLEAR:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,META:dojo.isSafari?91:224,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,copyKey:dojo.isMac&&!dojo.isAIR?(dojo.isSafari?91:224):17}; -var _19=dojo.isMac?"metaKey":"ctrlKey"; -dojo.isCopyKey=function(e){ -return e[_19]; -}; -if(dojo.isIE){ -dojo.mouseButtons={LEFT:1,MIDDLE:4,RIGHT:2,isButton:function(e,_1a){ -return e.button&_1a; -},isLeft:function(e){ -return e.button&1; -},isMiddle:function(e){ -return e.button&4; -},isRight:function(e){ -return e.button&2; -}}; -}else{ -dojo.mouseButtons={LEFT:0,MIDDLE:1,RIGHT:2,isButton:function(e,_1b){ -return e.button==_1b; -},isLeft:function(e){ -return e.button==0; -},isMiddle:function(e){ -return e.button==1; -},isRight:function(e){ -return e.button==2; -}}; -} -if(dojo.isIE){ -var _1c=function(e,_1d){ -try{ -return (e.keyCode=_1d); -} -catch(e){ -return 0; -} -}; -var iel=dojo._listener; -var _1e=(dojo._ieListenersName="_"+dojo._scopeName+"_listeners"); -if(!dojo.config._allow_leaks){ -_10=iel=dojo._ie_listener={handlers:[],add:function(_1f,_20,_21){ -_1f=_1f||dojo.global; -var f=_1f[_20]; -if(!f||!f[_1e]){ -var d=dojo._getIeDispatcher(); -d.target=f&&(ieh.push(f)-1); -d[_1e]=[]; -f=_1f[_20]=d; -} -return f[_1e].push(ieh.push(_21)-1); -},remove:function(_22,_23,_24){ -var f=(_22||dojo.global)[_23],l=f&&f[_1e]; -if(f&&l&&_24--){ -delete ieh[l[_24]]; -delete l[_24]; -} -}}; -var ieh=iel.handlers; -} -dojo.mixin(_1,{add:function(_25,_26,fp){ -if(!_25){ -return; -} -_26=_1._normalizeEventName(_26); -if(_26=="onkeypress"){ -var kd=_25.onkeydown; -if(!kd||!kd[_1e]||!kd._stealthKeydownHandle){ -var h=_1.add(_25,"onkeydown",_1._stealthKeyDown); -kd=_25.onkeydown; -kd._stealthKeydownHandle=h; -kd._stealthKeydownRefs=1; -}else{ -kd._stealthKeydownRefs++; -} -} -return iel.add(_25,_26,_1._fixCallback(fp)); -},remove:function(_27,_28,_29){ -_28=_1._normalizeEventName(_28); -iel.remove(_27,_28,_29); -if(_28=="onkeypress"){ -var kd=_27.onkeydown; -if(--kd._stealthKeydownRefs<=0){ -iel.remove(_27,"onkeydown",kd._stealthKeydownHandle); -delete kd._stealthKeydownHandle; -} -} -},_normalizeEventName:function(_2a){ -return _2a.slice(0,2)!="on"?"on"+_2a:_2a; -},_nop:function(){ -},_fixEvent:function(evt,_2b){ -if(!evt){ -var w=_2b&&(_2b.ownerDocument||_2b.document||_2b).parentWindow||window; -evt=w.event; -} -if(!evt){ -return (evt); -} -evt.target=evt.srcElement; -evt.currentTarget=(_2b||evt.srcElement); -evt.layerX=evt.offsetX; -evt.layerY=evt.offsetY; -var se=evt.srcElement,doc=(se&&se.ownerDocument)||document; -var _2c=((dojo.isIE<6)||(doc["compatMode"]=="BackCompat"))?doc.body:doc.documentElement; -var _2d=dojo._getIeDocumentElementOffset(); -evt.pageX=evt.clientX+dojo._fixIeBiDiScrollLeft(_2c.scrollLeft||0)-_2d.x; -evt.pageY=evt.clientY+(_2c.scrollTop||0)-_2d.y; -if(evt.type=="mouseover"){ -evt.relatedTarget=evt.fromElement; -} -if(evt.type=="mouseout"){ -evt.relatedTarget=evt.toElement; -} -evt.stopPropagation=_1._stopPropagation; -evt.preventDefault=_1._preventDefault; -return _1._fixKeys(evt); -},_fixKeys:function(evt){ -switch(evt.type){ -case "keypress": -var c=("charCode" in evt?evt.charCode:evt.keyCode); -if(c==10){ -c=0; -evt.keyCode=13; -}else{ -if(c==13||c==27){ -c=0; -}else{ -if(c==3){ -c=99; -} -} -} -evt.charCode=c; -_1._setKeyChar(evt); -break; -} -return evt; -},_stealthKeyDown:function(evt){ -var kp=evt.currentTarget.onkeypress; -if(!kp||!kp[_1e]){ -return; -} -var k=evt.keyCode; -var _2e=k!=13&&k!=32&&k!=27&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222); -if(_2e||evt.ctrlKey){ -var c=_2e?0:k; -if(evt.ctrlKey){ -if(k==3||k==13){ -return; -}else{ -if(c>95&&c<106){ -c-=48; -}else{ -if((!evt.shiftKey)&&(c>=65&&c<=90)){ -c+=32; -}else{ -c=_1._punctMap[c]||c; -} -} -} -} -var _2f=_1._synthesizeEvent(evt,{type:"keypress",faux:true,charCode:c}); -kp.call(evt.currentTarget,_2f); -evt.cancelBubble=_2f.cancelBubble; -evt.returnValue=_2f.returnValue; -_1c(evt,_2f.keyCode); -} -},_stopPropagation:function(){ -this.cancelBubble=true; -},_preventDefault:function(){ -this.bubbledKeyCode=this.keyCode; -if(this.ctrlKey){ -_1c(this,0); -} -this.returnValue=false; -}}); -dojo.stopEvent=function(evt){ -evt=evt||window.event; -_1._stopPropagation.call(evt); -_1._preventDefault.call(evt); -}; -} -_1._synthesizeEvent=function(evt,_30){ -var _31=dojo.mixin({},evt,_30); -_1._setKeyChar(_31); -_31.preventDefault=function(){ -evt.preventDefault(); -}; -_31.stopPropagation=function(){ -evt.stopPropagation(); -}; -return _31; -}; -if(dojo.isOpera){ -dojo.mixin(_1,{_fixEvent:function(evt,_32){ -switch(evt.type){ -case "keypress": -var c=evt.which; -if(c==3){ -c=99; -} -c=c<41&&!evt.shiftKey?0:c; -if(evt.ctrlKey&&!evt.shiftKey&&c>=65&&c<=90){ -c+=32; -} -return _1._synthesizeEvent(evt,{charCode:c}); -} -return evt; -}}); -} -if(dojo.isWebKit){ -_1._add=_1.add; -_1._remove=_1.remove; -dojo.mixin(_1,{add:function(_33,_34,fp){ -if(!_33){ -return; -} -var _35=_1._add(_33,_34,fp); -if(_1._normalizeEventName(_34)=="keypress"){ -_35._stealthKeyDownHandle=_1._add(_33,"keydown",function(evt){ -var k=evt.keyCode; -var _36=k!=13&&k!=32&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222); -if(_36||evt.ctrlKey){ -var c=_36?0:k; -if(evt.ctrlKey){ -if(k==3||k==13){ -return; -}else{ -if(c>95&&c<106){ -c-=48; -}else{ -if(!evt.shiftKey&&c>=65&&c<=90){ -c+=32; -}else{ -c=_1._punctMap[c]||c; -} -} -} -} -var _37=_1._synthesizeEvent(evt,{type:"keypress",faux:true,charCode:c}); -fp.call(evt.currentTarget,_37); -} -}); -} -return _35; -},remove:function(_38,_39,_3a){ -if(_38){ -if(_3a._stealthKeyDownHandle){ -_1._remove(_38,"keydown",_3a._stealthKeyDownHandle); -} -_1._remove(_38,_39,_3a); -} -},_fixEvent:function(evt,_3b){ -switch(evt.type){ -case "keypress": -if(evt.faux){ -return evt; -} -var c=evt.charCode; -c=c>=32?c:0; -return _1._synthesizeEvent(evt,{charCode:c,faux:true}); -} -return evt; -}}); -} -})(); + // 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){ + 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){ + event = del._normalizeEventName(event); + if(!dojo.isIE && (event == "mouseenter" || event == "mouseleave")){ + event = (event == "mouseenter") ? "mouseover" : "mouseout"; + } + + node.removeEventListener(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) : ''; + evt.charOrCode = evt.keyChar || evt.keyCode; + }, + // For IE and Safari: 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 + } + }); + + // 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 ? (dontFix ? 2 : 1) : 0, 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, + META: dojo.isSafari ? 91 : 224, // the apple key on macs + 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, + // virtual key mapping + copyKey: dojo.isMac && !dojo.isAIR ? (dojo.isSafari ? 91 : 224 ) : 17 + }; + + var evtCopyKey = dojo.isMac ? "metaKey" : "ctrlKey"; + + dojo.isCopyKey = function(e){ + // summary: + // Checks an event for the copy key (meta on Mac, and ctrl anywhere else) + // e: Event + // Event object to examine + return e[evtCopyKey]; // Boolean + }; + + // Public: decoding mouse buttons from events + +/*===== + dojo.mouseButtons = { + // LEFT: Number + // Numeric value of the left mouse button for the platform. + LEFT: 0, + // MIDDLE: Number + // Numeric value of the middle mouse button for the platform. + MIDDLE: 1, + // RIGHT: Number + // Numeric value of the right mouse button for the platform. + RIGHT: 2, + + isButton: function(e, button){ + // summary: + // Checks an event object for a pressed button + // e: Event + // Event object to examine + // button: Number + // The button value (example: dojo.mouseButton.LEFT) + return e.button == button; // Boolean + }, + isLeft: function(e){ + // summary: + // Checks an event object for the pressed left button + // e: Event + // Event object to examine + return e.button == 0; // Boolean + }, + isMiddle: function(e){ + // summary: + // Checks an event object for the pressed middle button + // e: Event + // Event object to examine + return e.button == 1; // Boolean + }, + isRight: function(e){ + // summary: + // Checks an event object for the pressed right button + // e: Event + // Event object to examine + return e.button == 2; // Boolean + } + }; +=====*/ + + if(dojo.isIE){ + dojo.mouseButtons = { + LEFT: 1, + MIDDLE: 4, + RIGHT: 2, + // helper functions + isButton: function(e, button){ return e.button & button; }, + isLeft: function(e){ return e.button & 1; }, + isMiddle: function(e){ return e.button & 4; }, + isRight: function(e){ return e.button & 2; } + }; + }else{ + dojo.mouseButtons = { + LEFT: 0, + MIDDLE: 1, + RIGHT: 2, + // helper functions + isButton: function(e, button){ return e.button == button; }, + isLeft: function(e){ return e.button == 0; }, + isMiddle: function(e){ return e.button == 1; }, + isRight: function(e){ return e.button == 2; } + }; + } + + // 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; + var listenersName = (dojo._ieListenersName = "_" + dojo._scopeName + "_listeners"); + // 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[listenersName]){ + 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[listenersName] = []; + // redirect source to dispatcher + f = source[method] = d; + } + return f[listenersName].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[listenersName]; + 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[listenersName] || !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; + }, + _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[listenersName]){ 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; + } + }); + } + + // Webkit event normalization + if(dojo.isWebKit){ + del._add = del.add; + del._remove = del.remove; + + dojo.mixin(del, { + add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){ + if(!node){return;} // undefined + var handle = del._add(node, event, fp); + if(del._normalizeEventName(event) == "keypress"){ + // we need to listen to onkeydown to synthesize + // keypress events that otherwise won't fire + // in Safari 3.1+: https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html + handle._stealthKeyDownHandle = del._add(node, "keydown", function(evt){ + //A variation on the IE _stealthKeydown function + //Synthesize an onkeypress event, but only for unprintable characters. + 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<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}); + fp.call(evt.currentTarget, faux); + } + }); + } + return handle; /*Handle*/ + }, + + remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){ + if(node){ + if(handle._stealthKeyDownHandle){ + del._remove(node, "keydown", handle._stealthKeyDownHandle); + } + del._remove(node, event, handle); + } + }, + _fixEvent: function(evt, sender){ + switch(evt.type){ + case "keypress": + if(evt.faux){ return evt; } + var c = evt.charCode; + c = c>=32 ? c : 0; + return del._synthesizeEvent(evt, {charCode: c, faux: true}); + } + return evt; + } + }); + } + })(); + if(dojo.isIE){ -dojo._ieDispatcher=function(_3c,_3d){ -var ap=Array.prototype,h=dojo._ie_listener.handlers,c=_3c.callee,ls=c[dojo._ieListenersName],t=h[c.target]; -var r=t&&t.apply(_3d,_3c); -var lls=[].concat(ls); -for(var i in lls){ -var f=h[lls[i]]; -if(!(i in ap)&&f){ -f.apply(_3d,_3c); -} -} -return r; -}; -dojo._getIeDispatcher=function(){ -return new Function(dojo._scopeName+"._ieDispatcher(arguments, this)"); -}; -dojo._event_listener._fixCallback=function(fp){ -var f=dojo._event_listener._fixEvent; -return function(e){ -return fp.call(this,f(e,this)); -}; -}; + // 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[dojo._ieListenersName], + t = h[c.target]; + // return value comes from original target function + var r = t && t.apply(sender, args); + // make local copy of listener array so it's immutable during processing + var lls = [].concat(ls); + // invoke listeners after target function + for(var i in lls){ + var f = h[lls[i]]; + if(!(i in ap) && f){ + f.apply(sender, args); + } + } + return r; + } + dojo._getIeDispatcher = function(){ + // ensure the returned function closes over nothing ("new Function" apparently doesn't close) + 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)); }; + } } + } -- cgit v1.2.3