PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/eventproxy/0.1.3/eventproxy.js

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