Peer-reviewed code snippets that anyone can edit
A wiki for useful code snippets
[EventDispatcher] singleton - a core-API based Signals and Slots implementation

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,{}));
*/