balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

backbone.radio.js (10363B)


      1 /*! elementor - v0.7.1 - 18-08-2016 */
      2 // Backbone.Radio v1.0.4
      3 
      4 (function (global, factory) {
      5   typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('underscore'), require('backbone')) :
      6   typeof define === 'function' && define.amd ? define(['underscore', 'backbone'], factory) :
      7   (global.Backbone = global.Backbone || {}, global.Backbone.Radio = factory(global._,global.Backbone));
      8 }(this, function (_,Backbone) { 'use strict';
      9 
     10   _ = 'default' in _ ? _['default'] : _;
     11   Backbone = 'default' in Backbone ? Backbone['default'] : Backbone;
     12 
     13   var babelHelpers = {};
     14   babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
     15     return typeof obj;
     16   } : function (obj) {
     17     return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
     18   };
     19   babelHelpers;
     20 
     21   var previousRadio = Backbone.Radio;
     22 
     23   var Radio = Backbone.Radio = {};
     24 
     25   Radio.VERSION = '1.0.4';
     26 
     27   // This allows you to run multiple instances of Radio on the same
     28   // webapp. After loading the new version, call `noConflict()` to
     29   // get a reference to it. At the same time the old version will be
     30   // returned to Backbone.Radio.
     31   Radio.noConflict = function () {
     32     Backbone.Radio = previousRadio;
     33     return this;
     34   };
     35 
     36   // Whether or not we're in DEBUG mode or not. DEBUG mode helps you
     37   // get around the issues of lack of warnings when events are mis-typed.
     38   Radio.DEBUG = false;
     39 
     40   // Format debug text.
     41   Radio._debugText = function (warning, eventName, channelName) {
     42     return warning + (channelName ? ' on the ' + channelName + ' channel' : '') + ': "' + eventName + '"';
     43   };
     44 
     45   // This is the method that's called when an unregistered event was called.
     46   // By default, it logs warning to the console. By overriding this you could
     47   // make it throw an Error, for instance. This would make firing a nonexistent event
     48   // have the same consequence as firing a nonexistent method on an Object.
     49   Radio.debugLog = function (warning, eventName, channelName) {
     50     if (Radio.DEBUG && console && console.warn) {
     51       console.warn(Radio._debugText(warning, eventName, channelName));
     52     }
     53   };
     54 
     55   var eventSplitter = /\s+/;
     56 
     57   // An internal method used to handle Radio's method overloading for Requests.
     58   // It's borrowed from Backbone.Events. It differs from Backbone's overload
     59   // API (which is used in Backbone.Events) in that it doesn't support space-separated
     60   // event names.
     61   Radio._eventsApi = function (obj, action, name, rest) {
     62     if (!name) {
     63       return false;
     64     }
     65 
     66     var results = {};
     67 
     68     // Handle event maps.
     69     if ((typeof name === 'undefined' ? 'undefined' : babelHelpers.typeof(name)) === 'object') {
     70       for (var key in name) {
     71         var result = obj[action].apply(obj, [key, name[key]].concat(rest));
     72         eventSplitter.test(key) ? _.extend(results, result) : results[key] = result;
     73       }
     74       return results;
     75     }
     76 
     77     // Handle space separated event names.
     78     if (eventSplitter.test(name)) {
     79       var names = name.split(eventSplitter);
     80       for (var i = 0, l = names.length; i < l; i++) {
     81         results[names[i]] = obj[action].apply(obj, [names[i]].concat(rest));
     82       }
     83       return results;
     84     }
     85 
     86     return false;
     87   };
     88 
     89   // An optimized way to execute callbacks.
     90   Radio._callHandler = function (callback, context, args) {
     91     var a1 = args[0],
     92         a2 = args[1],
     93         a3 = args[2];
     94     switch (args.length) {
     95       case 0:
     96         return callback.call(context);
     97       case 1:
     98         return callback.call(context, a1);
     99       case 2:
    100         return callback.call(context, a1, a2);
    101       case 3:
    102         return callback.call(context, a1, a2, a3);
    103       default:
    104         return callback.apply(context, args);
    105     }
    106   };
    107 
    108   // A helper used by `off` methods to the handler from the store
    109   function removeHandler(store, name, callback, context) {
    110     var event = store[name];
    111     if ((!callback || callback === event.callback || callback === event.callback._callback) && (!context || context === event.context)) {
    112       delete store[name];
    113       return true;
    114     }
    115   }
    116 
    117   function removeHandlers(store, name, callback, context) {
    118     store || (store = {});
    119     var names = name ? [name] : _.keys(store);
    120     var matched = false;
    121 
    122     for (var i = 0, length = names.length; i < length; i++) {
    123       name = names[i];
    124 
    125       // If there's no event by this name, log it and continue
    126       // with the loop
    127       if (!store[name]) {
    128         continue;
    129       }
    130 
    131       if (removeHandler(store, name, callback, context)) {
    132         matched = true;
    133       }
    134     }
    135 
    136     return matched;
    137   }
    138 
    139   /*
    140    * tune-in
    141    * -------
    142    * Get console logs of a channel's activity
    143    *
    144    */
    145 
    146   var _logs = {};
    147 
    148   // This is to produce an identical function in both tuneIn and tuneOut,
    149   // so that Backbone.Events unregisters it.
    150   function _partial(channelName) {
    151     return _logs[channelName] || (_logs[channelName] = _.partial(Radio.log, channelName));
    152   }
    153 
    154   _.extend(Radio, {
    155 
    156     // Log information about the channel and event
    157     log: function log(channelName, eventName) {
    158       if (typeof console === 'undefined') {
    159         return;
    160       }
    161       var args = _.drop(arguments, 2);
    162       console.log('[' + channelName + '] "' + eventName + '"', args);
    163     },
    164 
    165     // Logs all events on this channel to the console. It sets an
    166     // internal value on the channel telling it we're listening,
    167     // then sets a listener on the Backbone.Events
    168     tuneIn: function tuneIn(channelName) {
    169       var channel = Radio.channel(channelName);
    170       channel._tunedIn = true;
    171       channel.on('all', _partial(channelName));
    172       return this;
    173     },
    174 
    175     // Stop logging all of the activities on this channel to the console
    176     tuneOut: function tuneOut(channelName) {
    177       var channel = Radio.channel(channelName);
    178       channel._tunedIn = false;
    179       channel.off('all', _partial(channelName));
    180       delete _logs[channelName];
    181       return this;
    182     }
    183   });
    184 
    185   /*
    186    * Backbone.Radio.Requests
    187    * -----------------------
    188    * A messaging system for requesting data.
    189    *
    190    */
    191 
    192   function makeCallback(callback) {
    193     return _.isFunction(callback) ? callback : function () {
    194       return callback;
    195     };
    196   }
    197 
    198   Radio.Requests = {
    199 
    200     // Make a request
    201     request: function request(name) {
    202       var args = _.rest(arguments);
    203       var results = Radio._eventsApi(this, 'request', name, args);
    204       if (results) {
    205         return results;
    206       }
    207       var channelName = this.channelName;
    208       var requests = this._requests;
    209 
    210       // Check if we should log the request, and if so, do it
    211       if (channelName && this._tunedIn) {
    212         Radio.log.apply(this, [channelName, name].concat(args));
    213       }
    214 
    215       // If the request isn't handled, log it in DEBUG mode and exit
    216       if (requests && (requests[name] || requests['default'])) {
    217         var handler = requests[name] || requests['default'];
    218         args = requests[name] ? args : arguments;
    219         return Radio._callHandler(handler.callback, handler.context, args);
    220       } else {
    221         Radio.debugLog('An unhandled request was fired', name, channelName);
    222       }
    223     },
    224 
    225     // Set up a handler for a request
    226     reply: function reply(name, callback, context) {
    227       if (Radio._eventsApi(this, 'reply', name, [callback, context])) {
    228         return this;
    229       }
    230 
    231       this._requests || (this._requests = {});
    232 
    233       if (this._requests[name]) {
    234         Radio.debugLog('A request was overwritten', name, this.channelName);
    235       }
    236 
    237       this._requests[name] = {
    238         callback: makeCallback(callback),
    239         context: context || this
    240       };
    241 
    242       return this;
    243     },
    244 
    245     // Set up a handler that can only be requested once
    246     replyOnce: function replyOnce(name, callback, context) {
    247       if (Radio._eventsApi(this, 'replyOnce', name, [callback, context])) {
    248         return this;
    249       }
    250 
    251       var self = this;
    252 
    253       var once = _.once(function () {
    254         self.stopReplying(name);
    255         return makeCallback(callback).apply(this, arguments);
    256       });
    257 
    258       return this.reply(name, once, context);
    259     },
    260 
    261     // Remove handler(s)
    262     stopReplying: function stopReplying(name, callback, context) {
    263       if (Radio._eventsApi(this, 'stopReplying', name)) {
    264         return this;
    265       }
    266 
    267       // Remove everything if there are no arguments passed
    268       if (!name && !callback && !context) {
    269         delete this._requests;
    270       } else if (!removeHandlers(this._requests, name, callback, context)) {
    271         Radio.debugLog('Attempted to remove the unregistered request', name, this.channelName);
    272       }
    273 
    274       return this;
    275     }
    276   };
    277 
    278   /*
    279    * Backbone.Radio.channel
    280    * ----------------------
    281    * Get a reference to a channel by name.
    282    *
    283    */
    284 
    285   Radio._channels = {};
    286 
    287   Radio.channel = function (channelName) {
    288     if (!channelName) {
    289       throw new Error('You must provide a name for the channel.');
    290     }
    291 
    292     if (Radio._channels[channelName]) {
    293       return Radio._channels[channelName];
    294     } else {
    295       return Radio._channels[channelName] = new Radio.Channel(channelName);
    296     }
    297   };
    298 
    299   /*
    300    * Backbone.Radio.Channel
    301    * ----------------------
    302    * A Channel is an object that extends from Backbone.Events,
    303    * and Radio.Requests.
    304    *
    305    */
    306 
    307   Radio.Channel = function (channelName) {
    308     this.channelName = channelName;
    309   };
    310 
    311   _.extend(Radio.Channel.prototype, Backbone.Events, Radio.Requests, {
    312 
    313     // Remove all handlers from the messaging systems of this channel
    314     reset: function reset() {
    315       this.off();
    316       this.stopListening();
    317       this.stopReplying();
    318       return this;
    319     }
    320   });
    321 
    322   /*
    323    * Top-level API
    324    * -------------
    325    * Supplies the 'top-level API' for working with Channels directly
    326    * from Backbone.Radio.
    327    *
    328    */
    329 
    330   var channel;
    331   var args;
    332   var systems = [Backbone.Events, Radio.Requests];
    333   _.each(systems, function (system) {
    334     _.each(system, function (method, methodName) {
    335       Radio[methodName] = function (channelName) {
    336         args = _.rest(arguments);
    337         channel = this.channel(channelName);
    338         return channel[methodName].apply(channel, args);
    339       };
    340     });
    341   });
    342 
    343   Radio.reset = function (channelName) {
    344     var channels = !channelName ? this._channels : [this._channels[channelName]];
    345     _.invoke(channels, 'reset');
    346   };
    347 
    348   return Radio;
    349 
    350 }));