events.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /**
  2. * Copyright © Magento, Inc. All rights reserved.
  3. * See COPYING.txt for license details.
  4. */
  5. /* global varienEvents */
  6. /* eslint-disable strict */
  7. define([
  8. 'Magento_Ui/js/modal/alert',
  9. 'prototype'
  10. ], function (alert) {
  11. // from http://www.someelement.com/2007/03/eventpublisher-custom-events-la-pubsub.html
  12. window.varienEvents = Class.create();
  13. varienEvents.prototype = {
  14. /**
  15. * Initialize.
  16. */
  17. initialize: function () {
  18. this.arrEvents = {};
  19. this.eventPrefix = '';
  20. },
  21. /**
  22. * Attaches a {handler} function to the publisher's {eventName} event for execution upon the event firing
  23. * @param {String} eventName
  24. * @param {Function} handler
  25. * @param {Boolean} [asynchFlag] - Defaults to false if omitted.
  26. * Indicates whether to execute {handler} asynchronously (true) or not (false).
  27. */
  28. attachEventHandler: function (eventName, handler) {
  29. var asynchVar, handlerObj;
  30. if (typeof handler == 'undefined' || handler == null) {
  31. return;
  32. }
  33. eventName += this.eventPrefix;
  34. // using an event cache array to track all handlers for proper cleanup
  35. if (this.arrEvents[eventName] == null) {
  36. this.arrEvents[eventName] = [];
  37. }
  38. //create a custom object containing the handler method and the asynch flag
  39. asynchVar = arguments.length > 2 ? arguments[2] : false;
  40. handlerObj = {
  41. method: handler,
  42. asynch: asynchVar
  43. };
  44. this.arrEvents[eventName].push(handlerObj);
  45. },
  46. /**
  47. * Removes a single handler from a specific event
  48. * @param {String} eventName - The event name to clear the handler from
  49. * @param {Function} handler - A reference to the handler function to un-register from the event
  50. */
  51. removeEventHandler: function (eventName, handler) {
  52. eventName += this.eventPrefix;
  53. if (this.arrEvents[eventName] != null) {
  54. this.arrEvents[eventName] = this.arrEvents[eventName].reject(function (obj) {
  55. return obj.method == handler; //eslint-disable-line eqeqeq
  56. });
  57. }
  58. },
  59. /**
  60. * Removes all handlers from a single event
  61. * @param {String} eventName - The event name to clear handlers from
  62. */
  63. clearEventHandlers: function (eventName) {
  64. eventName += this.eventPrefix;
  65. this.arrEvents[eventName] = null;
  66. },
  67. /**
  68. * Removes all handlers from ALL events
  69. */
  70. clearAllEventHandlers: function () {
  71. this.arrEvents = {};
  72. },
  73. /**
  74. * Collect and modify value of arg synchronously in succession and return its new value.
  75. * In order to use, call attachEventHandler and add function handlers with eventName.
  76. * Then call fireEventReducer with eventName and any argument to have its value accumulatively modified.
  77. * Event handlers will be applied to argument in order of first attached to last attached.
  78. * @param {String} eventName
  79. * @param {*} arg
  80. */
  81. fireEventReducer: function (eventName, arg) {
  82. var evtName = eventName + this.eventPrefix,
  83. result = arg,
  84. len,
  85. i;
  86. if (!this.arrEvents[evtName]) {
  87. return result;
  88. }
  89. len = this.arrEvents[evtName].length; //optimization
  90. for (i = 0; i < len; i++) {
  91. /* eslint-disable max-depth */
  92. try {
  93. result = this.arrEvents[evtName][i].method(result);
  94. } catch (e) {
  95. if (this.id) {
  96. alert({
  97. content: 'error: error in ' + this.id + '.fireEventReducer():\n\nevent name: ' +
  98. eventName + '\n\nerror message: ' + e.message
  99. });
  100. } else {
  101. alert({
  102. content: 'error: error in [unknown object].fireEventReducer():\n\nevent name: ' +
  103. eventName + '\n\nerror message: ' + e.message
  104. });
  105. }
  106. }
  107. /* eslint-disable max-depth */
  108. }
  109. return result;
  110. },
  111. /**
  112. * Fires the event {eventName}, resulting in all registered handlers to be executed.
  113. * It also collects and returns results of all non-asynchronous handlers
  114. * @param {String} eventName - The name of the event to fire
  115. * @param {Object} [args] - Any object, will be passed into the handler function as the only argument
  116. * @return {Array}
  117. */
  118. fireEvent: function (eventName) {
  119. var evtName = eventName + this.eventPrefix,
  120. results = [],
  121. result, len, i, eventArgs, method, eventHandler;
  122. if (this.arrEvents[evtName] != null) {
  123. len = this.arrEvents[evtName].length; //optimization
  124. for (i = 0; i < len; i++) {
  125. /* eslint-disable max-depth */
  126. try {
  127. if (arguments.length > 1) {
  128. if (this.arrEvents[evtName][i].asynch) {
  129. eventArgs = arguments[1];
  130. method = this.arrEvents[evtName][i].method.bind(this);
  131. setTimeout(function () { //eslint-disable-line no-loop-func
  132. method(eventArgs);
  133. }, 10);
  134. } else {
  135. result = this.arrEvents[evtName][i].method(arguments[1]);
  136. }
  137. } else {
  138. if (this.arrEvents[evtName][i].asynch) { //eslint-disable-line no-lonely-if
  139. eventHandler = this.arrEvents[evtName][i].method;
  140. setTimeout(eventHandler, 1);
  141. } else if (
  142. this.arrEvents &&
  143. this.arrEvents[evtName] &&
  144. this.arrEvents[evtName][i] &&
  145. this.arrEvents[evtName][i].method
  146. ) {
  147. result = this.arrEvents[evtName][i].method();
  148. }
  149. }
  150. results.push(result);
  151. }
  152. catch (e) {
  153. if (this.id) {
  154. alert({
  155. content: 'error: error in ' + this.id + '.fireEvent():\n\nevent name: ' +
  156. eventName + '\n\nerror message: ' + e.message
  157. });
  158. } else {
  159. alert({
  160. content: 'error: error in [unknown object].fireEvent():\n\nevent name: ' +
  161. eventName + '\n\nerror message: ' + e.message
  162. });
  163. }
  164. }
  165. /* eslint-enable max-depth */
  166. }
  167. }
  168. return results;
  169. }
  170. };
  171. window.varienGlobalEvents = new varienEvents(); //jscs:ignore requireCapitalizedConstructors
  172. return window.varienGlobalEvents;
  173. });