This [EventDispatcher] singleton enables and will encourage usage of a pretty lightweighted but still type-safety enforcing implementation of Signals and Slots, an observer concept different from publish-subscribe, and all of it based on this languages core-API.
Registering a native JavaScript object via EventDispatcher.register applies kind of an [EventTarget] interface onto this object thus featuring immediately its 3 standard methods [addEventListener], [removeEventListener] and [dispatchEvent]. In addition to this there is a newly introduced [hasEventListener] helper method available too.
Attempting to register DOM-[Node] or DOM-[Element] objects as well as reregistering of objects that already do implement the [EventTarget] interface is futile.
Furthermore, this observer does not support any DOM-level-2 event flow behavior like capture, bubbling, propagation for there are no dependencies like ancestry or tree-like object hierarchies.
Once such an object features [EventTarget] behavior every other object can subscribe itself or listen via [addEventListener] to a certain event by passing a valid type and a handler to that firstly mentioned object.
/* link-list: English: [http://en.wikipedia.org/wiki/Observer_pattern] - Observer Pattern [http://en.wikipedia.org/wiki/Publish/subscribe] - publish-subscribe [http://en.wikipedia.org/wiki/Signals_and_slots] - Signals and Slots [http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/] [http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html] [http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/ecma-script-binding.html] Deutsch/German: [http://de.wikipedia.org/wiki/Observer_(Entwurfsmuster)] - Observer (Entwurfsmuster) / publish-subscribe [http://de.wikipedia.org/wiki/Signal-Slot-Konzept] - Signal-Slot-Konzept */ var EventDispatcher = (function () { // [EventDispatcher] Singleton. // DOM Level 2 - Appendix C: ECMAScript Language Binding. var exposeImplementation = Object.prototype.toString, stringify = (function (obj) { /*:[string]*/ // kind of [toString] helper method. return ((obj && obj.toString && obj.toString()) || ""); }), isBoolean = (function () { // typedetection. var regXBaseClass = (/^\[object\s+Boolean\]$/); return (function (obj/*:[object|value]*/) { /*:[true|false]*/ return regXBaseClass.test(exposeImplementation.call(obj)); }); })(), isString = (function () { // typedetection. var regXBaseClass = (/^\[object\s+String\]$/); return (function (obj/*:[object|value]*/) { /*:[true|false]*/ return regXBaseClass.test(exposeImplementation.call(obj)); }); })(), isFunction = (function (obj/*:[object|value]*/) { /*:[true|false]*/ // typedetection. return ((typeof obj == "function") && (typeof obj.call == "function") && (typeof obj.apply == "function")); // x-frame-safe and also filters e.g. mozillas [[RegExp]] implementation. }), Handler = { // specialized [indexOf] helper method. indexOf : (function (arr, fct) { /*:[number(>=0|-1)]*/ //var elm, idx = (arr.length - 1); var idx = (arr.length - 1); while (idx > -1) { //elm = arr[idx]; //if (((typeof elm != "undefined") || (idx in arr)) && (elm === fct)) { if (arr[idx] === fct) { break; } --idx; } return idx; }) }, Event = (function (target/*:[EventTarget]*/, type/*:[string|String]*/) { // providing the [[Event]] constructor. this.constructor = Event; // arguments.callee this.target = target; this.type = type; this.timeStamp = new Date(); }), EventListener = (function (target/*:[EventTarget]*/, type/*:[string|String]*/, handler/*:[Function]*/) { // providing the [[EventListener]] constructor. this.constructor = EventListener; // arguments.callee var defaultEvent = new Event(target, type); // default [Event] object this.handleEvent = (function (evt/*:[string|String|Event-like-Object]*/) { /*:void*/ if ((typeof evt == "object") && evt) { //stay strictly typesafe - [dispatchEvent] never will take control of [defaultEvent] e.g trying to delegate another [target] by manipulating its event-object-like argument. evt.target = defaultEvent.target; evt.type = defaultEvent.type; evt.timeStamp = defaultEvent.timeStamp; } else { //create a [defaultEvent] copy. evt = { target: defaultEvent.target, type: defaultEvent.type, timeStamp: defaultEvent.timeStamp }; } handler(evt); }); this.getType = (function () { /*:[string]*/ return type; }); this.getHandler = (function () { /*:[Function]*/ return handler; }); }),/* »The concept of "Mixin"s from the perspective of JavaScript adds behavior to objects by delegation over implemented interfaces. "Trait"s might be the wording that comes closest to this languages design. Furthermore, "augment" describes far better the mechanism behind this special kind of interface inheritance than "mix in" does.« */ EventTarget = (function () { // MIXIN: providing the [[EventTarget]] interface. //this.constructor = EventTarget; // arguments.callee // this is not a constructor . var eventMap = {}, removeEventListener = (function (type/*:[string|String]*/, handler/*:[Function]*/) { /*:[true|false]*/ var event = eventMap[type], successfully = false; if (event) { var handlers = event.handlers, listeners = event.listeners, idx = Handler.indexOf(handlers, handler); if (idx >= 0) { handlers.splice(idx, 1); listeners.splice(idx, 1); successfully = true; } } return successfully; }), hasEventListener = (function (type/*:[string|String]*/, handler/*:[Function]*/) { /*:[true|false]*/ return ((eventMap[type] || false) && (Handler.indexOf(eventMap[type].handlers, handler) >= 0)); }); this.addEventListener = (function (type/*:[string|String]*/, handler/*:[Function]*/) { /*:[EventListener|undefined]*/ var reference; if (type && isString(type) && isFunction(handler)) { var event = eventMap[type], listener = new EventListener(this, type, handler); if (event) { var handlers = event.handlers, listeners = event.listeners, idx = Handler.indexOf(handlers, handler); if (idx == -1) { handlers.push(listener.getHandler()); // in order to store a proper handler reference that later on could be compared to. listeners.push(listener); reference = listener; } else { reference = listeners[idx]; } } else { event = eventMap[type] = {}; event.handlers = [listener.getHandler()]; // in order to store a proper handler reference that later on could be compared to. event.listeners = [listener]; reference = listener; } } return reference; }); this.removeEventListener = (function (typeOrListener/*:[string|String|EventListener]*/, handler/*:[Function]*/) { /*:[true|false]*/ return ((isString(typeOrListener) && isFunction(handler) && removeEventListener(typeOrListener, handler)) || ((typeOrListener instanceof EventListener) && removeEventListener(typeOrListener.getType(), typeOrListener.getHandler())) || false); }); this.hasEventListener = (function (typeOrListener/*:[string|String|EventListener]*/, handler/*:[Function]*/) { /*:[true|false]*/ return ((isString(typeOrListener) && isFunction(handler) && hasEventListener(typeOrListener, handler)) || ((typeOrListener instanceof EventListener) && hasEventListener(typeOrListener.getType(), typeOrListener.getHandler())) || false/* or might >>return undefined<< be even better? */); }); this.dispatchEvent = (function (evt/*:[string|String|Event-like-Object]*/) { /*:[true|false]*/ var successfully = false, type = (((typeof evt == "object") && (typeof evt.type == "string") && evt.type) || ((typeof evt == "string") && evt)), event = (type && eventMap[type]); if (event) { var listeners = (event && event.listeners), len = ((listeners && listeners.length) || 0), idx = 0; if (len >= 1) { while (idx < len) { listeners[idx++].handleEvent(evt); // handle event dispatching serially - recommended if handler-processing is not that time consuming. //handling event dispatching kind of *green threaded* prevents freezing the user interface if dispatch cycle starts. //setTimeout((function () {listeners[idx++].handleEvent(evt);}), 0); // play around adjusting timeout values. //setTimeout((function () {listeners[idx++].handleEvent(evt);}), 1); // ... "" ... //setTimeout((function () {listeners[idx++].handleEvent(evt);}), idx); // ... "" ... //setTimeout((function () {listeners[idx++].handleEvent(evt);}), (idx * 5));// ... "" ... //alternatively each object that implements the [[EventTarget]] interface might enclose calling its own [dispatchEvent] method into a timeout if necessary: // obj = {}; // EventDispatcher.register(obj); // var customEventListener = obj.addEventListener("onCustomEvent", (function (evt) {print("onCustomEvent :\nevt : " + ((evt && ((evt.toSource && evt.toSource()) || evt.toString())) || evt) + "\n");})); // setTimeout((function () {obj.dispatchEvent("onCustomEvent");}), 1); // obj.dispatchEvent("onSomeOtherEvent"); } successfully = true; } } return successfully; }); }), pseudoTarget = new EventTarget, // there will be never ever any [[EventTarget]] instances except this one for copying purpose at initialize-time. CROSSCHECK_TARGET = { addListenerString : pseudoTarget.addEventListener.toString(), removeListenerString : pseudoTarget.removeEventListener.toString(), hasListenerString : pseudoTarget.hasEventListener.toString(), dispatchEventString : pseudoTarget.dispatchEvent.toString() }; delete pseudoTarget; // done ... get rid of this undesirable changeling. /* objects need to be registered and/or unsubscribed explicitly in order to apply/augment and/or withdraw/remove [EventTarget]-properties to/from them. */ return { register: (function (obj/*:[Object]*/) { /*:void*/ // register | sign on //do not apply this customized [[EventTarget]] interface to DOM-[Node] or DOM-[Element] objects or to objects that already got augmented by this customized [EventTarget] features. if ((typeof obj.addEventListener == "function") || obj.attachEvent || (typeof obj.removeEventListener == "function") || obj.detachEvent || (typeof obj.dispatchEvent == "function") || obj.fireEvent) { return; } EventTarget.call(obj); // applying the MIXIN concept - [obj] implements the [[EventTarget]] interface. }), unsubscribe: (function (obj/*:[Object]*/) { /*:void*/ // unsubscribe | sign off if (stringify(obj.addEventListener) === CROSSCHECK_TARGET.addListenerString) { delete obj.addEventListener; } if (stringify(obj.removeEventListener) === CROSSCHECK_TARGET.removeListenerString) { delete obj.removeEventListener; } if (stringify(obj.hasEventListener) === CROSSCHECK_TARGET.hasListenerString) { delete obj.hasEventListener; } if (stringify(obj.dispatchEvent) === CROSSCHECK_TARGET.dispatchEventString) { delete obj.dispatchEvent; } }) }; })(); // [EventDispatcher] Singleton. /* //[http://dean.edwards.name/packer/] - packed - 3666 bytes : (does not include [hasEventListener] functionality) var EventDispatcher=(function(){var exposeImplementation=Object.prototype.toString,stringify=(function(obj){return((obj&&obj.toString&&obj.toString())||"")}),isBoolean=(function(){var regXBaseClass=(/^\[object\s+Boolean\]$/);return(function(obj){return regXBaseClass.test(exposeImplementation.call(obj))})})(),isString=(function(){var regXBaseClass=(/^\[object\s+String\]$/);return(function(obj){return regXBaseClass.test(exposeImplementation.call(obj))})})(),isFunction=(function(obj){return((typeof obj=="function")&&(typeof obj.call=="function")&&(typeof obj.apply=="function"))}),Handler={indexOf:(function(arr,fct){var idx=(arr.length-1);while(idx>-1){if(arr[idx]===fct){break}--idx}return idx})},Event=(function(target,type){this.constructor=Event;this.target=target;this.type=type;this.timeStamp=new Date()}),EventListener=(function(target,type,handler){this.constructor=EventListener;var defaultEvent=new Event(target,type);this.handleEvent=(function(evt){if((typeof evt=="object")&&evt){evt.target=defaultEvent.target;evt.type=defaultEvent.type;evt.timeStamp=defaultEvent.timeStamp}else{evt={target:defaultEvent.target,type:defaultEvent.type,timeStamp:defaultEvent.timeStamp}}handler(evt)});this.getType=(function(){return type});this.getHandler=(function(){return handler})}),EventTarget=(function(){var eventMap={},removeEventListener=(function(type,handler){var event=eventMap[type],successfully=false;if(event){var handlers=event.handlers,listeners=event.listeners,idx=Handler.indexOf(handlers,handler);if(idx>=0){handlers.splice(idx,1);listeners.splice(idx,1);successfully=true}}return successfully});this.addEventListener=(function(type,handler){var reference;if(type&&isString(type)&&isFunction(handler)){var event=eventMap[type],listener=new EventListener(this,type,handler);if(event){var handlers=event.handlers,listeners=event.listeners,idx=Handler.indexOf(handlers,handler);if(idx==-1){handlers.push(listener.getHandler());listeners.push(listener);reference=listener}else{reference=listeners[idx]}}else{event=eventMap[type]={};event.handlers=[listener.getHandler()];event.listeners=[listener];reference=listener}}return reference});this.removeEventListener=(function(typeOrListener,handler){return((isString(typeOrListener)&&isFunction(handler)&&removeEventListener(typeOrListener,handler))||((typeOrListener instanceof EventListener)&&removeEventListener(typeOrListener.getType(),typeOrListener.getHandler()))||false)});this.dispatchEvent=(function(evt){var successfully=false,type=(((typeof evt=="object")&&(typeof evt.type=="string")&&evt.type)||((typeof evt=="string")&&evt)),event=(type&&eventMap[type]);if(event){var listeners=(event&&event.listeners),len=((listeners&&listeners.length)||0),idx=0;if(len>=1){while(idx<len){listeners[idx++].handleEvent(evt)}successfully=true}}return successfully})}),pseudoTarget=new EventTarget,CROSSCHECK_TARGET={addListenerString:pseudoTarget.addEventListener.toString(),removeListenerString:pseudoTarget.removeEventListener.toString(),dispatchEventString:pseudoTarget.dispatchEvent.toString()};delete pseudoTarget;return{register:(function(obj){if((typeof obj.addEventListener=="function")||obj.attachEvent||(typeof obj.removeEventListener=="function")||obj.detachEvent||(typeof obj.dispatchEvent=="function")||obj.fireEvent){return}EventTarget.call(obj)}),unsubscribe:(function(obj){if(stringify(obj.addEventListener)===CROSSCHECK_TARGET.addListenerString){delete obj.addEventListener}if(stringify(obj.removeEventListener)===CROSSCHECK_TARGET.removeListenerString){delete obj.removeEventListener}if(stringify(obj.dispatchEvent)===CROSSCHECK_TARGET.dispatchEventString){delete obj.dispatchEvent}})}})(); //[http://dean.edwards.name/packer/] - packed - 4237 bytes : (additionally featuring [hasEventListener]) var EventDispatcher=(function(){var exposeImplementation=Object.prototype.toString,stringify=(function(obj){return((obj&&obj.toString&&obj.toString())||"")}),isBoolean=(function(){var regXBaseClass=(/^\[object\s+Boolean\]$/);return(function(obj){return regXBaseClass.test(exposeImplementation.call(obj))})})(),isString=(function(){var regXBaseClass=(/^\[object\s+String\]$/);return(function(obj){return regXBaseClass.test(exposeImplementation.call(obj))})})(),isFunction=(function(obj){return((typeof obj=="function")&&(typeof obj.call=="function")&&(typeof obj.apply=="function"))}),Handler={indexOf:(function(arr,fct){var idx=(arr.length-1);while(idx>-1){if(arr[idx]===fct){break}--idx}return idx})},Event=(function(target,type){this.constructor=Event;this.target=target;this.type=type;this.timeStamp=new Date()}),EventListener=(function(target,type,handler){this.constructor=EventListener;var defaultEvent=new Event(target,type);this.handleEvent=(function(evt){if((typeof evt=="object")&&evt){evt.target=defaultEvent.target;evt.type=defaultEvent.type;evt.timeStamp=defaultEvent.timeStamp}else{evt={target:defaultEvent.target,type:defaultEvent.type,timeStamp:defaultEvent.timeStamp}}handler(evt)});this.getType=(function(){return type});this.getHandler=(function(){return handler})}),EventTarget=(function(){var eventMap={},removeEventListener=(function(type,handler){var event=eventMap[type],successfully=false;if(event){var handlers=event.handlers,listeners=event.listeners,idx=Handler.indexOf(handlers,handler);if(idx>=0){handlers.splice(idx,1);listeners.splice(idx,1);successfully=true}}return successfully}),hasEventListener=(function(type,handler){return((eventMap[type]||false)&&(Handler.indexOf(eventMap[type].handlers,handler)>=0))});this.addEventListener=(function(type,handler){var reference;if(type&&isString(type)&&isFunction(handler)){var event=eventMap[type],listener=new EventListener(this,type,handler);if(event){var handlers=event.handlers,listeners=event.listeners,idx=Handler.indexOf(handlers,handler);if(idx==-1){handlers.push(listener.getHandler());listeners.push(listener);reference=listener}else{reference=listeners[idx]}}else{event=eventMap[type]={};event.handlers=[listener.getHandler()];event.listeners=[listener];reference=listener}}return reference});this.removeEventListener=(function(typeOrListener,handler){return((isString(typeOrListener)&&isFunction(handler)&&removeEventListener(typeOrListener,handler))||((typeOrListener instanceof EventListener)&&removeEventListener(typeOrListener.getType(),typeOrListener.getHandler()))||false)});this.hasEventListener=(function(typeOrListener,handler){return((isString(typeOrListener)&&isFunction(handler)&&hasEventListener(typeOrListener,handler))||((typeOrListener instanceof EventListener)&&hasEventListener(typeOrListener.getType(),typeOrListener.getHandler()))||false)});this.dispatchEvent=(function(evt){var successfully=false,type=(((typeof evt=="object")&&(typeof evt.type=="string")&&evt.type)||((typeof evt=="string")&&evt)),event=(type&&eventMap[type]);if(event){var listeners=(event&&event.listeners),len=((listeners&&listeners.length)||0),idx=0;if(len>=1){while(idx<len){listeners[idx++].handleEvent(evt)}successfully=true}}return successfully})}),pseudoTarget=new EventTarget,CROSSCHECK_TARGET={addListenerString:pseudoTarget.addEventListener.toString(),removeListenerString:pseudoTarget.removeEventListener.toString(),hasListenerString:pseudoTarget.hasEventListener.toString(),dispatchEventString:pseudoTarget.dispatchEvent.toString()};delete pseudoTarget;return{register:(function(obj){if((typeof obj.addEventListener=="function")||obj.attachEvent||(typeof obj.removeEventListener=="function")||obj.detachEvent||(typeof obj.dispatchEvent=="function")||obj.fireEvent){return}EventTarget.call(obj)}),unsubscribe:(function(obj){if(stringify(obj.addEventListener)===CROSSCHECK_TARGET.addListenerString){delete obj.addEventListener}if(stringify(obj.removeEventListener)===CROSSCHECK_TARGET.removeListenerString){delete obj.removeEventListener}if(stringify(obj.hasEventListener)===CROSSCHECK_TARGET.hasListenerString){delete obj.hasEventListener}if(stringify(obj.dispatchEvent)===CROSSCHECK_TARGET.dispatchEventString){delete obj.dispatchEvent}})}})(); //[http://dean.edwards.name/packer/] - shrinked + encoded - 2144 bytes : (does not include [hasEventListener] functionality) eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('4 1c=(2(){4 g=16.12.k,u=(2(a){3((a&&a.k&&a.k())||"")}),11=(2(){4 b=(/^\\[t\\s+Z\\]$/);3(2(a){3 b.O(g.w(a))})})(),B=(2(){4 b=(/^\\[t\\s+13\\]$/);3(2(a){3 b.O(g.w(a))})})(),C=(2(a){3((8 a=="2")&&(8 a.w=="2")&&(8 a.10=="2"))}),I={A:(2(a,b){4 c=(a.M-1);W(c>-1){5(a[c]===b){17}--c}3 c})},G=(2(a,b){6.L=G;6.o=a;6.9=b;6.m=x Y()}),v=(2(b,c,d){6.L=v;4 e=x G(b,c);6.X=(2(a){5((8 a=="t")&&a){a.o=e.o;a.9=e.9;a.m=e.m}H{a={o:e.o,9:e.9,m:e.m}}d(a)});6.Q=(2(){3 c});6.q=(2(){3 d})}),K=(2(){4 f={},i=(2(a,b){4 c=f[a],D=J;5(c){4 d=c.F,h=c.h,7=I.A(d,b);5(7>=0){d.V(7,1);h.V(7,1);D=N}}3 D});6.p=(2(a,b){4 c;5(a&&B(a)&&C(b)){4 d=f[a],j=x v(6,a,b);5(d){4 e=d.F,h=d.h,7=I.A(e,b);5(7==-1){e.U(j.q());h.U(j);c=j}H{c=h[7]}}H{d=f[a]={};d.F=[j.q()];d.h=[j];c=j}}3 c});6.i=(2(a,b){3((B(a)&&C(b)&&i(a,b))||((a 15 v)&&i(a.Q(),a.q()))||J)});6.l=(2(a){4 b=J,9=(((8 a=="t")&&(8 a.9=="T")&&a.9)||((8 a=="T")&&a)),y=(9&&f[9]);5(y){4 c=(y&&y.h),E=((c&&c.M)||0),7=0;5(E>=1){W(7<E){c[7++].X(a)}b=N}}3 b})}),n=x K,r={S:n.p.k(),P:n.i.k(),R:n.l.k()};z n;3{14:(2(a){5((8 a.p=="2")||a.18||(8 a.i=="2")||a.19||(8 a.l=="2")||a.1a){3}K.w(a)}),1b:(2(a){5(u(a.p)===r.S){z a.p}5(u(a.i)===r.P){z a.i}5(u(a.l)===r.R){z a.l}})}})();',62,75,'||function|return|var|if|this|idx|typeof|type||||||||listeners|removeEventListener|listener|toString|dispatchEvent|timeStamp|pseudoTarget|target|addEventListener|getHandler|CROSSCHECK_TARGET||object|stringify|EventListener|call|new|event|delete|indexOf|isString|isFunction|successfully|len|handlers|Event|else|Handler|false|EventTarget|constructor|length|true|test|removeListenerString|getType|dispatchEventString|addListenerString|string|push|splice|while|handleEvent|Date|Boolean|apply|isBoolean|prototype|String|register|instanceof|Object|break|attachEvent|detachEvent|fireEvent|unsubscribe|EventDispatcher'.split('|'),0,{})); //[http://dean.edwards.name/packer/] - shrinked + encoded - 2327 bytes : (additionally featuring [hasEventListener]) eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('4 1d=(2(){4 g=14.17.j,q=(2(a){3((a&&a.j&&a.j())||"")}),1e=(2(){4 b=(/^\\[G\\s+11\\]$/);3(2(a){3 b.R(g.D(a))})})(),F=(2(){4 b=(/^\\[G\\s+15\\]$/);3(2(a){3 b.R(g.D(a))})})(),A=(2(a){3((8 a=="2")&&(8 a.D=="2")&&(8 a.16=="2"))}),B={E:(2(a,b){4 c=(a.Y-1);O(c>-1){5(a[c]===b){12}--c}3 c})},I=(2(a,b){6.10=I;6.w=a;6.9=b;6.v=y 13()}),t=(2(b,c,d){6.10=t;4 e=y I(b,c);6.Q=(2(a){5((8 a=="G")&&a){a.w=e.w;a.9=e.9;a.v=e.v}H{a={w:e.w,9:e.9,v:e.v}}d(a)});6.J=(2(){3 c});6.p=(2(){3 d})}),K=(2(){4 f={},i=(2(a,b){4 c=f[a],M=n;5(c){4 d=c.z,h=c.h,7=B.E(d,b);5(7>=0){d.N(7,1);h.N(7,1);M=Z}}3 M}),l=(2(a,b){3((f[a]||n)&&(B.E(f[a].z,b)>=0))});6.x=(2(a,b){4 c;5(a&&F(a)&&A(b)){4 d=f[a],k=y t(6,a,b);5(d){4 e=d.z,h=d.h,7=B.E(e,b);5(7==-1){e.P(k.p());h.P(k);c=k}H{c=h[7]}}H{d=f[a]={};d.z=[k.p()];d.h=[k];c=k}}3 c});6.i=(2(a,b){3((F(a)&&A(b)&&i(a,b))||((a X t)&&i(a.J(),a.p()))||n)});6.l=(2(a,b){3((F(a)&&A(b)&&l(a,b))||((a X t)&&l(a.J(),a.p()))||n)});6.r=(2(a){4 b=n,9=(((8 a=="G")&&(8 a.9=="W")&&a.9)||((8 a=="W")&&a)),C=(9&&f[9]);5(C){4 c=(C&&C.h),L=((c&&c.Y)||0),7=0;5(L>=1){O(7<L){c[7++].Q(a)}b=Z}}3 b})}),m=y K,o={S:m.x.j(),V:m.i.j(),T:m.l.j(),U:m.r.j()};u m;3{18:(2(a){5((8 a.x=="2")||a.19||(8 a.i=="2")||a.1a||(8 a.r=="2")||a.1b){3}K.D(a)}),1c:(2(a){5(q(a.x)===o.S){u a.x}5(q(a.i)===o.V){u a.i}5(q(a.l)===o.T){u a.l}5(q(a.r)===o.U){u a.r}})}})();',62,77,'||function|return|var|if|this|idx|typeof|type||||||||listeners|removeEventListener|toString|listener|hasEventListener|pseudoTarget|false|CROSSCHECK_TARGET|getHandler|stringify|dispatchEvent||EventListener|delete|timeStamp|target|addEventListener|new|handlers|isFunction|Handler|event|call|indexOf|isString|object|else|Event|getType|EventTarget|len|successfully|splice|while|push|handleEvent|test|addListenerString|hasListenerString|dispatchEventString|removeListenerString|string|instanceof|length|true|constructor|Boolean|break|Date|Object|String|apply|prototype|register|attachEvent|detachEvent|fireEvent|unsubscribe|EventDispatcher|isBoolean'.split('|'),0,{})); */