PageRenderTime 49ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs/eventproxy/0.1.4/eventproxy.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 359 lines | 211 code | 26 blank | 122 comment | 37 complexity | 929592a4924e94d445462abb681db66f MD5 | raw file
  1. /*global exports */
  2. /**
  3. * @fileoverview This file is used for define the EventProxy library.
  4. * @author <a href="mailto:shyvo1987@gmail.com">Jackson Tian</a>
  5. * @version 0.1.0
  6. */
  7. ;(function (name, definition) {
  8. // this is considered "safe":
  9. var hasDefine = typeof define === 'function',
  10. // hasDefine = typeof define === 'function',
  11. hasExports = typeof module !== 'undefined' && module.exports;
  12. if (hasDefine) { // AMD Module or CMD Module
  13. define(definition);
  14. } else if (hasExports) { // Node.js Module
  15. module.exports = definition();
  16. } else { // Assign to common namespaces or simply the global object (window)
  17. this[name] = definition();
  18. }
  19. })('EventProxy', function () {
  20. /**
  21. * @description EventProxy. A module that can be mixed in to *any object* in order to provide it with
  22. * custom events. You may `bind` or `unbind` a callback function to an event;
  23. * `trigger`-ing an event fires all callbacks in succession.
  24. * @constructor
  25. * @name EventProxy
  26. * @class EventProxy. An implementation of task/event based asynchronous pattern.
  27. * @example
  28. * var render = function (template, resources) {};
  29. * var proxy = new EventProxy();
  30. * proxy.assign("template", "l10n", render);
  31. * proxy.trigger("template", template);
  32. * proxy.trigger("l10n", resources);
  33. */
  34. var EventProxy = function () {
  35. if (!(this instanceof EventProxy)) {
  36. return new EventProxy();
  37. }
  38. this._callbacks = {};
  39. this._fired = {};
  40. };
  41. /**
  42. * @description Bind an event, specified by a string name, `ev`, to a `callback` function.
  43. * Passing `"all"` will bind the callback to all events fired.
  44. * @memberOf EventProxy#
  45. * @param {string} eventName Event name.
  46. * @param {function} callback Callback.
  47. */
  48. EventProxy.prototype.addListener = function (ev, callback) {
  49. this._callbacks = this._callbacks || {};
  50. this._callbacks[ev] = this._callbacks[ev] || [];
  51. this._callbacks[ev].push(callback);
  52. return this;
  53. };
  54. EventProxy.prototype.bind = EventProxy.prototype.addListener;
  55. EventProxy.prototype.on = EventProxy.prototype.addListener;
  56. EventProxy.prototype.await = EventProxy.prototype.addListener;
  57. /**
  58. * @description Remove one or many callbacks. If `callback` is null, removes all
  59. * callbacks for the event. If `ev` is null, removes all bound callbacks
  60. * for all events.
  61. * @memberOf EventProxy#
  62. * @param {string} eventName Event name.
  63. * @param {function} callback Callback.
  64. */
  65. EventProxy.prototype.removeListener = function (ev, callback) {
  66. var calls = this._callbacks, i, l;
  67. if (!ev) {
  68. this._callbacks = {};
  69. } else if (calls) {
  70. if (!callback) {
  71. calls[ev] = [];
  72. } else {
  73. var list = calls[ev];
  74. if (!list) {
  75. return this;
  76. }
  77. l = list.length;
  78. for (i = 0; i < l; i++) {
  79. if (callback === list[i]) {
  80. list[i] = null;
  81. break;
  82. }
  83. }
  84. }
  85. }
  86. return this;
  87. };
  88. EventProxy.prototype.unbind = EventProxy.prototype.removeListener;
  89. /**
  90. * @description Remove all listeners.
  91. * It equals unbind(); Just add this API for as same as Event.Emitter.
  92. * @memberOf EventProxy#
  93. * @param {string} event Event name.
  94. */
  95. EventProxy.prototype.removeAllListeners = function (event) {
  96. return this.unbind(event);
  97. };
  98. /**
  99. * @description Trigger an event, firing all bound callbacks. Callbacks are passed the
  100. * same arguments as `trigger` is, apart from the event name.
  101. * Listening for `"all"` passes the true event name as the first argument.
  102. * @param {string} eventName Event name
  103. * @param {mix} data Pass in data
  104. */
  105. EventProxy.prototype.trigger = function (eventName, data) {
  106. var list, calls, ev, callback, args, i, l;
  107. var both = 2;
  108. if (!(calls = this._callbacks)) {
  109. return this;
  110. }
  111. while (both--) {
  112. ev = both ? eventName : 'all';
  113. list = calls[ev];
  114. if (list) {
  115. for (i = 0, l = list.length; i < l; i++) {
  116. if (!(callback = list[i])) {
  117. list.splice(i, 1); i--; l--;
  118. } else {
  119. args = both ? Array.prototype.slice.call(arguments, 1) : arguments;
  120. callback.apply(this, args);
  121. }
  122. }
  123. }
  124. }
  125. return this;
  126. };
  127. EventProxy.prototype.emit = EventProxy.prototype.trigger;
  128. EventProxy.prototype.fire = EventProxy.prototype.trigger;
  129. /**
  130. * @description Bind an event like the bind method, but will remove the listener after it was fired.
  131. * @param {string} ev Event name
  132. * @param {function} callback Callback
  133. */
  134. EventProxy.prototype.once = function (ev, callback) {
  135. var self = this,
  136. wrapper = function () {
  137. callback.apply(self, arguments);
  138. self.unbind(ev, wrapper);
  139. };
  140. this.bind(ev, wrapper);
  141. return this;
  142. };
  143. /**
  144. * @description Bind an event, and trigger it immediately.
  145. * @param {string} ev Event name.
  146. * @param {function} callback Callback.
  147. * @param {mix} data The data that will be passed to calback as arguments.
  148. */
  149. EventProxy.prototype.immediate = function (ev, callback, data) {
  150. this.bind(ev, callback);
  151. this.trigger(ev, data);
  152. return this;
  153. };
  154. var _assign = function (eventname1, eventname2, cb, once) {
  155. var proxy = this, length, index = 0, argsLength = arguments.length,
  156. bind, _all,
  157. callback, events, isOnce, times = 0, flag = {};
  158. // Check the arguments length.
  159. if (argsLength < 3) {
  160. return this;
  161. }
  162. events = Array.prototype.slice.apply(arguments, [0, argsLength - 2]);
  163. callback = arguments[argsLength - 2];
  164. isOnce = arguments[argsLength - 1];
  165. // Check the callback type.
  166. if (typeof callback !== "function") {
  167. return this;
  168. }
  169. length = events.length;
  170. bind = function (key) {
  171. var method = isOnce ? "once" : "bind";
  172. proxy[method](key, function (data) {
  173. proxy._fired[key] = proxy._fired[key] || {};
  174. proxy._fired[key].data = data;
  175. if (!flag[key]) {
  176. flag[key] = true;
  177. times++;
  178. }
  179. });
  180. };
  181. for (index = 0; index < length; index++) {
  182. bind(events[index]);
  183. }
  184. _all = function (event) {
  185. if (times < length) {
  186. return;
  187. }
  188. if (!flag[event]) {
  189. return;
  190. }
  191. var data = [];
  192. for (index = 0; index < length; index++) {
  193. data.push(proxy._fired[events[index]].data);
  194. }
  195. if (isOnce) {
  196. proxy.unbind("all", _all);
  197. }
  198. callback.apply(null, data);
  199. };
  200. proxy.bind("all", _all);
  201. };
  202. /**
  203. * @description Assign some events, after all events were fired, the callback will be executed once.
  204. * @example
  205. * proxy.all(ev1, ev2, callback);
  206. * proxy.all([ev1, ev2], callback);
  207. * proxy.all(ev1, [ev2, ev3], callback);
  208. * @param {string} eventName1 First event name.
  209. * @param {string} eventName2 Second event name.
  210. * @param {function} callback Callback, that will be called after predefined events were fired.
  211. */
  212. EventProxy.prototype.all = function (eventname1, eventname2, cb) {
  213. var args = Array.prototype.concat.apply([], arguments);
  214. args.push(true);
  215. _assign.apply(this, args);
  216. return this;
  217. };
  218. EventProxy.prototype.assign = EventProxy.prototype.all;
  219. /**
  220. * @description Assign some events, after all events were fired, the callback will be executed first time.
  221. * then any event that predefined be fired again, the callback will executed with the newest data.
  222. * @example
  223. * proxy.tail(ev1, ev2, callback);
  224. * proxy.tail([ev1, ev2], callback);
  225. * proxy.tail(ev1, [ev2, ev3], callback);
  226. * @memberOf EventProxy#
  227. * @param {string} eventName1 First event name.
  228. * @param {string} eventName2 Second event name.
  229. * @param {function} callback Callback, that will be called after predefined events were fired.
  230. */
  231. EventProxy.prototype.tail = function () {
  232. var args = Array.prototype.concat.apply([], arguments);
  233. args.push(false);
  234. _assign.apply(this, args);
  235. return this;
  236. };
  237. EventProxy.prototype.assignAll = EventProxy.prototype.tail;
  238. EventProxy.prototype.assignAlways = EventProxy.prototype.tail;
  239. /**
  240. * @description The callback will be executed after the event be fired N times.
  241. * @memberOf EventProxy#
  242. * @param {string} eventName Event name.
  243. * @param {number} times N times.
  244. * @param {function} callback Callback, that will be called after event was fired N times.
  245. */
  246. EventProxy.prototype.after = function (eventName, times, callback) {
  247. if (times === 0) {
  248. callback.call(null, []);
  249. return this;
  250. }
  251. var proxy = this,
  252. firedData = [],
  253. all;
  254. all = function (name, data) {
  255. if (name === eventName) {
  256. times--;
  257. firedData.push(data);
  258. if (times < 1) {
  259. proxy.unbind("all", all);
  260. callback.apply(null, [firedData]);
  261. }
  262. }
  263. };
  264. proxy.bind("all", all);
  265. return this;
  266. };
  267. /**
  268. * @description The callback will be executed after any registered event was fired. It only executed once.
  269. * @memberOf EventProxy#
  270. * @param {string} eventName1 Event name.
  271. * @param {string} eventName2 Event name.
  272. * @param {function} callback The callback will get a map that has data and eventName attributes.
  273. */
  274. EventProxy.prototype.any = function () {
  275. var proxy = this,
  276. index,
  277. _bind,
  278. len = arguments.length,
  279. callback = arguments[len - 1],
  280. events = Array.prototype.slice.apply(arguments, [0, len - 1]),
  281. count = events.length,
  282. _eventName = events.join("_");
  283. proxy.once(_eventName, callback);
  284. _bind = function (key) {
  285. proxy.bind(key, function (data) {
  286. proxy.trigger(_eventName, {"data": data, eventName: key});
  287. });
  288. };
  289. for (index = 0; index < count; index++) {
  290. _bind(events[index]);
  291. }
  292. };
  293. /**
  294. * @description The callback will be executed when the evnet name not equals with assigned evnet.
  295. * @memberOf EventProxy#
  296. * @param {string} eventName Event name.
  297. * @param {function} callback Callback.
  298. */
  299. EventProxy.prototype.not = function (eventName, callback) {
  300. var proxy = this;
  301. proxy.bind("all", function (name, data) {
  302. if (name !== eventName) {
  303. callback(data);
  304. }
  305. });
  306. };
  307. /**
  308. * Create a new EventProxy
  309. * @example
  310. * var ep = EventProxy.create();
  311. * ep.assign('user', 'articles', function(user, articles) {
  312. * // do something...
  313. * });
  314. *
  315. * // or one line ways: Create EventProxy and Assign
  316. *
  317. * var ep = EventProxy.create('user', 'articles', function(user, articles) {
  318. * // do something...
  319. * });
  320. *
  321. * @returns {EventProxy}
  322. */
  323. EventProxy.create = function () {
  324. var ep = new EventProxy();
  325. if (arguments.length) {
  326. ep.assign.apply(ep, Array.prototype.slice.call(arguments));
  327. }
  328. return ep;
  329. };
  330. // Backwards compatibility
  331. EventProxy.EventProxy = EventProxy;
  332. return EventProxy;
  333. });