Explorar el Código

fix emitter to leverage jQuery. fixes bug with not supporting namespaces.

Adam Shaw hace 9 años
padre
commit
96a4131b28
Se han modificado 1 ficheros con 37 adiciones y 42 borrados
  1. 37 42
      src/common/EmitterMixin.js

+ 37 - 42
src/common/EmitterMixin.js

@@ -1,66 +1,61 @@
 
 var EmitterMixin = FC.EmitterMixin = {
 
-	callbackHash: null,
-
+	// jQuery-ification via $(this) allows a non-DOM object to have
+	// the same event handling capabilities (including namespaces).
+
+
+	on: function(types, handler) {
+
+		// handlers are always called with an "event" object as their first param.
+		// sneak the `this` context and arguments into the extra parameter object
+		// and forward them on to the original handler.
+		var intercept = function(ev, extra) {
+			return handler.apply(
+				extra.context || this,
+				extra.args || []
+			);
+		};
+
+		// mimick jQuery's internal "proxy" system (risky, I know)
+		// causing all functions with the same .guid to appear to be the same.
+		// https://github.com/jquery/jquery/blob/2.2.4/src/core.js#L448
+		// this is needed for calling .off with the original non-intercept handler.
+		if (!handler.guid) {
+			handler.guid = $.guid++;
+		}
+		intercept.guid = handler.guid;
 
-	on: function(name, callback) {
-		this.loopCallbacks(name, 'add', [ callback ]);
+		$(this).on(types, intercept);
 
 		return this; // for chaining
 	},
 
 
-	off: function(name, callback) {
-		this.loopCallbacks(name, 'remove', [ callback ]);
+	off: function(types, handler) {
+		$(this).off(types, handler);
 
 		return this; // for chaining
 	},
 
 
-	trigger: function(name) { // args...
-		var args = Array.prototype.slice.call(arguments, 1);
-
-		this.triggerWith(name, this, args);
-
-		return this; // for chaining
-	},
-
+	trigger: function(types) {
+		var args = Array.prototype.slice.call(arguments, 1); // arguments after the first
 
-	triggerWith: function(name, context, args) {
-		this.loopCallbacks(name, 'fireWith', [ context, args ]);
+		// pass in "extra" info to the intercept
+		$(this).triggerHandler(types, { args: args });
 
 		return this; // for chaining
 	},
 
 
-	/*
-	Given an event name string with possible namespaces,
-	call the given methodName on all the internal Callback object with the given arguments.
-	*/
-	loopCallbacks: function(name, methodName, args) {
-		var parts = name.split('.'); // "click.namespace" -> [ "click", "namespace" ]
-		var i, part;
-		var callbackObj;
-
-		for (i = 0; i < parts.length; i++) {
-			part = parts[i];
-			if (part) { // in case no event name like "click"
-				callbackObj = this.ensureCallbackObj((i ? '.' : '') + part); // put periods in front of namespaces
-				callbackObj[methodName].apply(callbackObj, args);
-			}
-		}
-	},
+	triggerWith: function(types, context, args) {
 
+		// `triggerHandler` is less reliant on the DOM compared to `trigger`.
+		// pass in "extra" info to the intercept.
+		$(this).triggerHandler(types, { context: context, args: args });
 
-	ensureCallbackObj: function(name) {
-		if (!this.callbackHash) {
-			this.callbackHash = {};
-		}
-		if (!this.callbackHash[name]) {
-			this.callbackHash[name] = $.Callbacks();
-		}
-		return this.callbackHash[name];
+		return this; // for chaining
 	}
 
-};
+};