      1 var func = require("../base/functions"),
      2 		define = require("../define").define;
      3
      4
      5 var Broadcaster = define(null, {
      6 			instance : {
      7 				/** @lends comb.plugins.Broadcaster.prototype */
      8 				/**
      9 				 * Plugin to allow a class to easily broadcast events
     10 				 *
     11 				 * @example
     12 				 *
     13 				 * var Mammal = define(comb.plugins.Broadcaster, {
     14 				 *   instance : {
     15 				 *
     16 				 *      constructor: function(options) {
     17 				 *          options = options || {};
     18 				 *          this.super(arguments);
     19 				 *          this._type = options.type || "mammal";
     20 				 *      },
     21 				 *
     22 				 *      speak : function() {
     23 				 *          var str = "A mammal of type " + this._type + " sounds like";
     24 				 *          this.broadcast("speak", str);
     25 				 *          this.onSpeak(str);
     26 				 *          return str;
     27 				 *      },
     28 				 *
     29 				 *      onSpeak : function(){}
     30 				 *    }
     31 				 * });
     32 				 *
     33 				 *
     34 				 * var m = new Mammal({color : "gold"});
     35 				 * m.listen("speak", function(str){
     36 				 *      //called back from the broadcast event
     37 				 *       console.log(str);
     38 				 * });
     39 				 * m.speak();
     40 				 *
     41 				 * @constructs
     42 				 */
     43 				constructor : function() {
     44 					this.__listeners = {};
     45 				},
     46
     47 				/**
     48 				 * Broadcasts an event from an object
     49 				 *
     50 				 * @param name the name of the event to broadcast
     51 				 * @param {Object|String|Function|Date|Number} [args]  variable number of arguments to pass to listeners, can be anything
     52 				 */
     53 				broadcast : function(topic, args) {
     54 					var args = Array.prototype.slice.call(arguments, 0), topic = args.shift();
     55 					if (topic && topic in this.__listeners) {
     56 						var list = this.__listeners[topic], i = list.length - 1;
     57 						while (i >= 0) {
     58 							list[i--].cb.apply(this, args);
     59 						}
     60 					}
     61 				},
     62
     63 				/**
     64 				 * Listens to a broadcasted event
     65 				 * Simimlar to {@link comb.listen}
     66 				 *
     67 				 * @param {String} topic the topic to listen to
     68 				 * @param {Function} callback the function to callback on event publish
     69 				 *
     70 				 * @returns {Array} handle to disconnect a topic
     71 				 */
     72 				listen : function(topic, callback) {
     73 					if (!func.isFunction(callback)) throw new Error("callback must be a function");
     74 					var handle = {
     75 						topic : topic,
     76 						cb : callback
     77 					};
     78 					var list = this.__listeners[topic];
     79 					if (!list) {
     80 						list = (this.__listeners[topic] = [handle]);
     81 						handle.pos = 0;
     82 					} else {
     83 						handle.pos = list.push(handle);
     84 					}
     85 					return handle;
     86 				},
     87
     88 				/**
     89 				 * Disconnects a listener
     90 				 * Similar to {@link comb.unListen}
     91 				 *
     92 				 * @param  handle disconnect a handle returned from Broadcaster.listen
     93 				 */
     94 				unListen : function(handle) {
     95 					if (handle) {
     96 						var topic = handle.topic;
     97 						if (topic in this.__listeners) {
     98 							var listeners = this.__listeners, list = listeners[topic];
     99 							if (list) {
    100 								for (var i = list.length - 1; i >= 0; i--) {
    101 									if (list[i] == handle) {
    102 										list.splice(i, 1);
    103 										break;
    104 									}
    105 								}
    106 							}
    107 						}
    108 					}
    109 				}
    110 			}
    111 		});
    112
    113 exports = module.exports = Broadcaster;