1/** 2 * Copyright (c) 2010,2011,2012,2013,2014 Morgan Roderick http://roderick.dk 3 * License: MIT - http://mrgnrdrck.mit-license.org 4 * 5 * https://github.com/mroderick/PubSubJS 6 */ 7 8(function (root, factory){ 9 'use strict'; 10 11 var PubSub = {}; 12 root.PubSub = PubSub; 13 factory(PubSub); 14 // CommonJS and Node.js module support 15 if (typeof exports === 'object'){ 16 if (module !== undefined && module.exports) { 17 exports = module.exports = PubSub; // Node.js specific `module.exports` 18 } 19 exports.PubSub = PubSub; // CommonJS module 1.1.1 spec 20 module.exports = exports = PubSub; // CommonJS 21 } 22 // AMD support 23 /* eslint-disable no-undef */ 24 else if (typeof define === 'function' && define.amd){ 25 define(function() { return PubSub; }); 26 /* eslint-enable no-undef */ 27 } 28 29}(( typeof window === 'object' && window ) || this, function (PubSub){ 30 'use strict'; 31 32 var messages = {}, 33 lastUid = -1, 34 ALL_SUBSCRIBING_MSG = '*'; 35 36 function hasKeys(obj){ 37 var key; 38 39 for (key in obj){ 40 if ( obj.hasOwnProperty(key) ){ 41 return true; 42 } 43 } 44 return false; 45 } 46 47 /** 48 * Returns a function that throws the passed exception, for use as argument for setTimeout 49 * @alias throwException 50 * @function 51 * @param { Object } ex An Error object 52 */ 53 function throwException( ex ){ 54 return function reThrowException(){ 55 throw ex; 56 }; 57 } 58 59 function callSubscriberWithDelayedExceptions( subscriber, message, data ){ 60 try { 61 subscriber( message, data ); 62 } catch( ex ){ 63 setTimeout( throwException( ex ), 0); 64 } 65 } 66 67 function callSubscriberWithImmediateExceptions( subscriber, message, data ){ 68 subscriber( message, data ); 69 } 70 71 function deliverMessage( originalMessage, matchedMessage, data, immediateExceptions ){ 72 var subscribers = messages[matchedMessage], 73 callSubscriber = immediateExceptions ? callSubscriberWithImmediateExceptions : callSubscriberWithDelayedExceptions, 74 s; 75 76 if ( !messages.hasOwnProperty( matchedMessage ) ) { 77 return; 78 } 79 80 for (s in subscribers){ 81 if ( subscribers.hasOwnProperty(s)){ 82 callSubscriber( subscribers[s], originalMessage, data ); 83 } 84 } 85 } 86 87 function createDeliveryFunction( message, data, immediateExceptions ){ 88 return function deliverNamespaced(){ 89 var topic = String( message ), 90 position = topic.lastIndexOf( '.' ); 91 92 // deliver the message as it is now 93 deliverMessage(message, message, data, immediateExceptions); 94 95 // trim the hierarchy and deliver message to each level 96 while( position !== -1 ){ 97 topic = topic.substr( 0, position ); 98 position = topic.lastIndexOf('.'); 99 deliverMessage( message, topic, data, immediateExceptions ); 100 } 101 102 deliverMessage(message, ALL_SUBSCRIBING_MSG, data, immediateExceptions); 103 }; 104 } 105 106 function hasDirectSubscribersFor( message ) { 107 var topic = String( message ), 108 found = Boolean(messages.hasOwnProperty( topic ) && hasKeys(messages[topic])); 109 110 return found; 111 } 112 113 function messageHasSubscribers( message ){ 114 var topic = String( message ), 115 found = hasDirectSubscribersFor(topic) || hasDirectSubscribersFor(ALL_SUBSCRIBING_MSG), 116 position = topic.lastIndexOf( '.' ); 117 118 while ( !found && position !== -1 ){ 119 topic = topic.substr( 0, position ); 120 position = topic.lastIndexOf( '.' ); 121 found = hasDirectSubscribersFor(topic); 122 } 123 124 return found; 125 } 126 127 function publish( message, data, sync, immediateExceptions ){ 128 message = (typeof message === 'symbol') ? message.toString() : message; 129 130 var deliver = createDeliveryFunction( message, data, immediateExceptions ), 131 hasSubscribers = messageHasSubscribers( message ); 132 133 if ( !hasSubscribers ){ 134 return false; 135 } 136 137 if ( sync === true ){ 138 deliver(); 139 } else { 140 setTimeout( deliver, 0 ); 141 } 142 return true; 143 } 144 145 /** 146 * Publishes the message, passing the data to it's subscribers 147 * @function 148 * @alias publish 149 * @param { String } message The message to publish 150 * @param {} data The data to pass to subscribers 151 * @return { Boolean } 152 */ 153 PubSub.publish = function( message, data ){
154 return publish( message, data, false, PubSub.immediateExceptions ); 155 }; 156 157 /** 158 * Publishes the message synchronously, passing the data to it's subscribers 159 * @function 160 * @alias publishSync 161 * @param { String } message The message to publish 162 * @param {} data The data to pass to subscribers 163 * @return { Boolean } 164 */ 165 PubSub.publishSync = function( message, data ){ 166 return publish( message, data, true, PubSub.immediateExceptions ); 167 }; 168 169 /** 170 * Subscribes the passed function to the passed message. Every returned token is unique and should be stored if you need to unsubscribe 171 * @function 172 * @alias subscribe 173 * @param { String } message The message to subscribe to 174 * @param { Function } func The function to call when a new message is published 175 * @return { String } 176 */ 177 PubSub.subscribe = function( message, func ){ 178 if ( typeof func !== 'function'){ 179 return false; 180 } 181 182 message = (typeof message === 'symbol') ? message.toString() : message; 183 184 // message is not registered yet 185 if ( !messages.hasOwnProperty( message ) ){ 186 messages[message] = {}; 187 } 188 189 // forcing token as String, to allow for future expansions without breaking usage 190 // and allow for easy use as key names for the 'messages' object 191 var token = 'uid_' + String(++lastUid); 192 messages[message][token] = func; 193 194 // return token for unsubscribing 195 return token; 196 }; 197 198 PubSub.subscribeAll = function( func ){ 199 return PubSub.subscribe(ALL_SUBSCRIBING_MSG, func); 200 }; 201 202 /** 203 * Subscribes the passed function to the passed message once 204 * @function 205 * @alias subscribeOnce 206 * @param { String } message The message to subscribe to 207 * @param { Function } func The function to call when a new message is published 208 * @return { PubSub } 209 */ 210 PubSub.subscribeOnce = function( message, func ){ 211 var token = PubSub.subscribe( message, function(){ 212 // before func apply, unsubscribe message 213 PubSub.unsubscribe( token ); 214 func.apply( this, arguments ); 215 }); 216 return PubSub; 217 }; 218 219 /** 220 * Clears all subscriptions 221 * @function 222 * @public 223 * @alias clearAllSubscriptions 224 */ 225 PubSub.clearAllSubscriptions = function clearAllSubscriptions(){ 226 messages = {}; 227 }; 228 229 /** 230 * Clear subscriptions by the topic 231 * @function 232 * @public 233 * @alias clearAllSubscriptions 234 * @return { int } 235 */ 236 PubSub.clearSubscriptions = function clearSubscriptions(topic){ 237 var m; 238 for (m in messages){ 239 if (messages.hasOwnProperty(m) && m.indexOf(topic) === 0){ 240 delete messages[m]; 241 } 242 } 243 }; 244 245 /** 246 Count subscriptions by the topic 247 * @function 248 * @public 249 * @alias countSubscriptions 250 * @return { Array } 251 */ 252 PubSub.countSubscriptions = function countSubscriptions(topic){ 253 var m; 254 var count = 0; 255 for (m in messages){ 256 if (messages.hasOwnProperty(m) && m.indexOf(topic) === 0){ 257 count++; 258 } 259 } 260 return count; 261 }; 262 263 264 /** 265 Gets subscriptions by the topic 266 * @function 267 * @public 268 * @alias getSubscriptions 269 */ 270 PubSub.getSubscriptions = function getSubscriptions(topic){ 271 var m; 272 var list = []; 273 for (m in messages){ 274 if (messages.hasOwnProperty(m) && m.indexOf(topic) === 0){ 275 list.push(m); 276 } 277 } 278 return list; 279 }; 280 281 /** 282 * Removes subscriptions 283 * 284 * - When passed a token, removes a specific subscription. 285 * 286 * - When passed a function, removes all subscriptions for that function 287 * 288 * - When passed a topic, removes all subscriptions for that topic (hierarchy) 289 * @function 290 * @public 291 * @alias subscribeOnce 292 * @param { String | Function } value A token, function or topic to unsubscribe from 293 * @example // Unsubscribing with a token 294 * var token = PubSub.subscribe('mytopic', myFunc); 295 * PubSub.unsubscribe(token); 296 * @example // Unsubscribing with a function 297 * PubSub.unsubscribe(myFunc);
298 * @example // Unsubscribing from a topic 299 * PubSub.unsubscribe('mytopic'); 300 */ 301 PubSub.unsubscribe = function(value){ 302 var descendantTopicExists = function(topic) { 303 var m; 304 for ( m in messages ){ 305 if ( messages.hasOwnProperty(m) && m.indexOf(topic) === 0 ){ 306 // a descendant of the topic exists: 307 return true; 308 } 309 } 310 311 return false; 312 }, 313 isTopic = typeof value === 'string' && ( messages.hasOwnProperty(value) || descendantTopicExists(value) ), 314 isToken = !isTopic && typeof value === 'string', 315 isFunction = typeof value === 'function', 316 result = false, 317 m, message, t; 318 319 if (isTopic){ 320 PubSub.clearSubscriptions(value); 321 return; 322 } 323 324 for ( m in messages ){ 325 if ( messages.hasOwnProperty( m ) ){ 326 message = messages[m]; 327 328 if ( isToken && message[value] ){ 329 delete message[value]; 330 result = value; 331 // tokens are unique, so we can just stop here 332 break; 333 } 334 335 if (isFunction) { 336 for ( t in message ){ 337 if (message.hasOwnProperty(t) && message[t] === value){ 338 delete message[t]; 339 result = true; 340 } 341 } 342 } 343 } 344 } 345 346 return result; 347 }; 348}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.