/**
 * ##dispatcher##
 * Behavior modifier for event dispatching.
 * @param {Object} target - the object to apply the methods to.
 * @param {Object} scope - the object that the methods will be applied from
 * @param {object} map - custom names of what methods to map from scope. such as _$emit_ and _$broadcast_.
 */

define('dispatcher', ['apply'], function (apply) {

    function Event(type) {
        this.type = type;
        this.defaultPrevented = false;
        this.propagationStopped = false;
        this.immediatePropagationStopped = false;
    }
    Event.prototype.preventDefault = function() {
        this.defaultPrevented = true;
    };
    Event.prototype.stopPropagation = function() {
        this.propagationStopped = true;
    };
    Event.prototype.stopImmediatePropagation = function() {
        this.immediatePropagationStopped = true;
    };
    Event.prototype.toString = function() {
        return this.type;
    };

    var dispatcher = function (target, scope, map) {
        // if you try to make the same item a dispatcher, it will just do nothing.
        if (target && target.on && target.on.dispatcher) {
            return target;// it is already a dispatcher.
        }
        target = target || {};
        var listeners = {};

        /**
         * ###off###
         * removeEventListener from this object instance. given the event listened for and the callback reference.
         * @param event
         * @param callback
         */
        function off(event, callback) {
            var index, list;
            list = listeners[event];
            if (list) {
                if (callback) {
                    index = list.indexOf(callback);
                    if (index !== -1) {
                        list.splice(index, 1);
                    }
                } else {
                    list.length = 0;
                }
            }
        }

        /**
         * ###on###
         * addEventListener to this object instance.
         * @param {String} event
         * @param {Function} callback
         * @returns {Function} - removeListener or unwatch function.
         */
        function on(event, callback) {
            listeners[event] = listeners[event] || [];
            listeners[event].push(callback);
            return function () {
                off(event, callback);
            };
        }

        /**
         * ###once###
         * addEventListener that gets remove with the first call.
         * @param event
         * @param callback
         * @returns {Function} - removeListener or unwatch function.
         */
        function once(event, callback) {
            function fn() {
                off(event, fn);
                apply(callback, scope || target, arguments);
            }

            return on(event, fn);
        }

        /**
         * ###getListeners###
         * get the listeners from the dispatcher.
         * @param {String} event
         * @param {Boolean} strict
         * @returns {*}
         */
        function getListeners(event, strict) {
            var list, a = '*';
            if (event || strict) {
                list = [];
                if (listeners[a]) {
                    list = listeners[a].concat(list);
                }
                if (listeners[event]) {
                    list = listeners[event].concat(list);
                }
                return list;
            }
            return listeners;
        }

        function removeAllListeners() {
            listeners = {};
        }

        /**
         * ###fire###
         * fire the callback with arguments.
         * @param {Function} callback
         * @param {Array} args
         * @returns {*}
         */
        function fire(callback, args) {
            return callback && apply(callback, target, args);
        }

        /**
         * ###dispatch###
         * fire the event and any arguments that are passed.
         * @param {String} event
         */
        function dispatch(event) {
            var list = getListeners(event, true), len = list.length, i, event = new Event(arguments[0]);
            if (len) {
                arguments[0] = event;
                for (i = 0; i < len; i += 1) {
                    if (!event.immediatePropagationStopped) {
                        fire(list[i], arguments);
                    }
                }
            }
            return event;
        }

        if (scope && map) {
            target.on = scope[map.on] && scope[map.on].bind(scope);
            target.off = scope[map.off] && scope[map.off].bind(scope);
            target.once = scope[map.once] && scope[map.once].bind(scope);
            target.dispatch = target.fire = scope[map.dispatch].bind(scope);
        } else {
            target.on = on;
            target.off = off;
            target.once = once;
            target.dispatch = target.fire = dispatch;
        }
        target.getListeners = getListeners;
        target.removeAllListeners = removeAllListeners;

        return target;
    };

    return dispatcher;

});

@@ -340,16 +340,30 @@
 %5B'apply'
+, 'isFunction'
 %5D, funct
@@ -372,16 +372,28 @@
 n (apply
+, isFunction
 ) %7B%0A%0A   
@@ -961,24 +961,145 @@
 pe;%0A    %7D;%0A%0A
+    function validateEvent(e) %7B%0A        if (!e) %7B%0A            throw Error('event cannot be undefined');%0A        %7D%0A    %7D%0A%0A
     var disp
@@ -1651,32 +1651,66 @@
 nt, callback) %7B%0A
+            validateEvent(event);%0A
             var 
@@ -2349,32 +2349,113 @@
 nt, callback) %7B%0A
+            if(isFunction(callback)) %7B%0A                validateEvent(event);%0A    
             list
@@ -2497,32 +2497,36 @@
 %5B%5D;%0A            
+   
+ 
 listeners%5Bevent%5D
@@ -2550,24 +2550,28 @@
             
+    
 return funct
@@ -2587,32 +2587,36 @@
                 
+  
+  
 off(event, callb
@@ -2629,26 +2629,44 @@
             
+    %7D;%0A            
 %7D
-;
 %0A        %7D%0A%0A
@@ -2930,32 +2930,113 @@
 nt, callback) %7B%0A
+            if(isFunction(callback)) %7B%0A                validateEvent(event);%0A    
             func
@@ -3055,32 +3055,36 @@
                 
+   
+ 
 off(event, fn);%0A
@@ -3075,32 +3075,36 @@
 off(event, fn);%0A
+    
                 
@@ -3152,35 +3152,43 @@
 s);%0A            
-%7D%0A%0A
+    %7D%0A%0A    
             retu
@@ -3197,32 +3197,46 @@
  on(event, fn);%0A
+            %7D%0A
         %7D%0A%0A     
@@ -3465,32 +3465,66 @@
 vent, strict) %7B%0A
+            validateEvent(event);%0A
             var 
@@ -4459,24 +4459,58 @@
 ch(event) %7B%0A
+            validateEvent(event);%0A
             
@@ -4581,30 +4581,59 @@
 t = 
-new Event(arguments%5B0%5D
+typeof event === 'object' ? event : new Event(event
 );%0A 

fix - check if valid function in handler before adding to listeners