Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Nov 26th, 2012  |  syntax: JavaScript  |  size: 4.65 KB  |  views: 69  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /**
  2.  * Facility for coordinating communication between components in an event-based
  3.  * manner.
  4.  *
  5.  * <p>
  6.  * Communication is modeled by using signals.
  7.  *
  8.  * A Signal consist of a category and a payload (data). Components can publish
  9.  * signals or subscribe to signals of a certain category. When a signal is
  10.  * published, all components subscribed for the signal's category are notified.
  11.  * </p>
  12.  */
  13. function EventBus(config) {
  14.  
  15.         var log = getLogger("EventBus");
  16.  
  17.         /*
  18.          * A No-Operation function that is used to replace
  19.          * handlers when a subscription is cancelled.
  20.          */
  21.         var noop = function() {};
  22.        
  23.         /**
  24.          * key: signal category value: list of handlers subscribed for this category.
  25.          */
  26.         var subscribers = {};
  27.  
  28.         /**
  29.          * Registers a listener for a certain signal.
  30.          *
  31.          * @param category
  32.          *            The signal type
  33.          * @param handler
  34.          *            The function to be called when a signal is received.
  35.          *            
  36.          * @return A Subscription object that can be used
  37.          *                  to unsubscribe from an event.  
  38.          */
  39.         this.subscribe = function(category, handler) {
  40.  
  41.                 //log.info("subscribing", handler, "for", category);
  42.  
  43.                 var handlerList = null;
  44.                
  45.                 if (category in subscribers) {
  46.                         handlerList = subscribers[category];
  47.  
  48.                 } else {
  49.                         handlerList = [];
  50.                         subscribers[category] = handlerList;
  51.                 }
  52.  
  53.                 handlerList.push(handler);
  54.                
  55.                 return new Subscription(category, handler);
  56.  
  57.         };
  58.        
  59.         /**
  60.          * Publishes a signal by notifying the handlers
  61.          * registered for the category.
  62.          *
  63.          * @return the number of subscribers the signal was sent to.
  64.          */
  65.         this.publish = function(category, data) {
  66.                
  67.                 if (config.debug) {
  68.                         log.info("publishing", category, data);
  69.                 }
  70.                
  71.                 if (category in subscribers) {
  72.                        
  73.                         var subscribersForCategory = subscribers[category];
  74.                        
  75.                         for (var i = 0; i < subscribersForCategory.length; i++) {
  76.                                 subscribersForCategory[i](data);
  77.                         }
  78.                
  79.                         return subscribersForCategory.length;
  80.                 }
  81.                
  82.                 return 0;
  83.  
  84.         };
  85.        
  86.         /**
  87.          * <p>
  88.          * The subscription can be stored und used later by a client to
  89.          * unsubscribe a handler from an event.
  90.          * </p>
  91.          *
  92.          * For convenience, subscriptions can be "chained" by calling the
  93.          * add-method.
  94.          *  
  95.          * @returns {Subscription}
  96.          */
  97.         function Subscription(category, handler) {
  98.                
  99.                 var cancelled = false;
  100.                 var that = this;
  101.                
  102.                 this.cancel = function() {
  103.                        
  104.                         if (cancelled) {
  105.                                 return;
  106.                         }
  107.                        
  108.                         log.info("unsubscribing from " + category);
  109.                        
  110.                         var handlerList = subscribers[category];
  111.                        
  112.                         if (handlerList) {
  113.                                
  114.                                 for (var i = 0; i < handlerList.length; i++) {
  115.  
  116.                                         if (handlerList[i] === handler) {
  117.                                                 handlerList[i] = noop;
  118.                                                 cancelled = true;
  119.                                                 handler = null;
  120.                                                 return;
  121.                                         }
  122.                                        
  123.                                 }
  124.                         }
  125.                        
  126.                         // for safety. Make sure the subscription was found and removed.
  127.                         throw "handler " + handler + " not subscribed to " + category;
  128.                        
  129.                 };
  130.                
  131.                 /**
  132.                  * Adds another subscription to this subscription.
  133.                  * This is handy, when a client subscribes to multiple categories,
  134.                  * and does not want to declare a separate variable for
  135.                  * each subscription.
  136.                  *
  137.                  * <p>
  138.                  * If the cancel() is invoked, all "nested" subscriptions are
  139.                  * cancelled as well.
  140.                  * </p>
  141.                  */
  142.                 this.add = function(otherSubscription) {
  143.  
  144.                         var original = that.cancel;
  145.                        
  146.                         that.cancel = function() {
  147.                                 otherSubscription.cancel();
  148.                                 original.cancel();
  149.                         };
  150.                        
  151.                 };
  152.                
  153.         }
  154.        
  155.         /**
  156.          * A facility, that can collect other subscriptions which can than
  157.          * be canceled all-at-once with one call.
  158.          * <p>
  159.          * This is handy, if client code subscribes to multiple categories,
  160.          * or if client code eventually subscribes to a category and does not
  161.          * want to check if the subscription actually did happen upon unsubscribe.
  162.          * </p>
  163.          * Example:
  164.          *
  165.          * <pre>
  166.          * var subscriptions = eventBus.newSubscriptionList();
  167.          *
  168.          * subscriptions.add(eventBus.subscribe('category1', ...);
  169.          * subscriptions.add(eventBus.subscribe('category2', ...);
  170.          *
  171.          * [...]
  172.          *
  173.          * subscriptions.cancel();
  174.          *
  175.          * </pre>
  176.          *  
  177.          */
  178.         this.nullSubscription = function() {
  179.  
  180.                 var nullSubscription = {
  181.                        
  182.                         // do nothing
  183.                         cancel: function() {},
  184.                        
  185.                         add: function(otherSubscription) {
  186.                                 /*
  187.                                  * As soon as the first "real" subscription is
  188.                                  * added, replace our own cancel and add-implementation
  189.                                  * with the real one.
  190.                                  * All subsequent calls to add() will then be delegated to the
  191.                                  * real implementation.
  192.                                  */
  193.                                 nullSubscription.cancel = otherSubscription.cancel;
  194.                                 nullSubscription.add = otherSubscription.add;
  195.                         }
  196.                        
  197.                 };
  198.                
  199.                 return nullSubscription;
  200.                
  201.         };
  202.  
  203. }
clone this paste RAW Paste Data