events.js 7.52 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

/* global varienEvents */
/* eslint-disable strict */
define([
    'Magento_Ui/js/modal/alert',
    'prototype'
], function (alert) {
    // from http://www.someelement.com/2007/03/eventpublisher-custom-events-la-pubsub.html
    window.varienEvents = Class.create();

    varienEvents.prototype = {
        /**
         * Initialize.
         */
        initialize: function () {
            this.arrEvents = {};
            this.eventPrefix = '';
        },

        /**
        * Attaches a {handler} function to the publisher's {eventName} event for execution upon the event firing
        * @param {String} eventName
        * @param {Function} handler
        * @param {Boolean} [asynchFlag] - Defaults to false if omitted.
        * Indicates whether to execute {handler} asynchronously (true) or not (false).
        */
        attachEventHandler: function (eventName, handler) {
            var asynchVar, handlerObj;

            if (typeof handler == 'undefined' || handler == null) {
                return;
            }
            eventName += this.eventPrefix;
            // using an event cache array to track all handlers for proper cleanup
            if (this.arrEvents[eventName] == null) {
                this.arrEvents[eventName] = [];
            }
            //create a custom object containing the handler method and the asynch flag
            asynchVar = arguments.length > 2 ? arguments[2] : false;
            handlerObj = {
                method: handler,
                asynch: asynchVar
            };
            this.arrEvents[eventName].push(handlerObj);
        },

        /**
        * Removes a single handler from a specific event
        * @param {String} eventName - The event name to clear the handler from
        * @param {Function} handler - A reference to the handler function to un-register from the event
        */
        removeEventHandler: function (eventName, handler) {
            eventName += this.eventPrefix;

            if (this.arrEvents[eventName] != null) {
                this.arrEvents[eventName] = this.arrEvents[eventName].reject(function (obj) {
                    return obj.method == handler; //eslint-disable-line eqeqeq
                });
            }
        },

        /**
        * Removes all handlers from a single event
        * @param {String} eventName - The event name to clear handlers from
        */
        clearEventHandlers: function (eventName) {
            eventName += this.eventPrefix;
            this.arrEvents[eventName] = null;
        },

        /**
        * Removes all handlers from ALL events
        */
        clearAllEventHandlers: function () {
            this.arrEvents = {};
        },

        /**
         * Collect and modify value of arg synchronously in succession and return its new value.
         * In order to use, call attachEventHandler and add function handlers with eventName.
         * Then call fireEventReducer with eventName and any argument to have its value accumulatively modified.
         * Event handlers will be applied to argument in order of first attached to last attached.
         * @param {String} eventName
         * @param {*} arg
         */
        fireEventReducer: function (eventName, arg) {
            var evtName = eventName + this.eventPrefix,
                result = arg,
                len,
                i;

            if (!this.arrEvents[evtName]) {
                return result;
            }

            len = this.arrEvents[evtName].length; //optimization

            for (i = 0; i < len; i++) {
                /* eslint-disable max-depth */
                try {
                    result = this.arrEvents[evtName][i].method(result);
                } catch (e) {
                    if (this.id) {
                        alert({
                            content: 'error: error in ' + this.id + '.fireEventReducer():\n\nevent name: ' +
                            eventName + '\n\nerror message: ' + e.message
                        });
                    } else {
                        alert({
                            content: 'error: error in [unknown object].fireEventReducer():\n\nevent name: ' +
                            eventName + '\n\nerror message: ' + e.message
                        });
                    }
                }
                /* eslint-disable max-depth */
            }

            return result;
        },

        /**
        * Fires the event {eventName}, resulting in all registered handlers to be executed.
        * It also collects and returns results of all non-asynchronous handlers
        * @param {String} eventName - The name of the event to fire
        * @param {Object} [args] - Any object, will be passed into the handler function as the only argument
        * @return {Array}
        */
        fireEvent: function (eventName) {
            var evtName = eventName + this.eventPrefix,
                results = [],
                result, len, i, eventArgs, method, eventHandler;

            if (this.arrEvents[evtName] != null) {
                len = this.arrEvents[evtName].length; //optimization

                for (i = 0; i < len; i++) {
                    /* eslint-disable max-depth */
                    try {
                        if (arguments.length > 1) {
                            if (this.arrEvents[evtName][i].asynch) {
                                eventArgs = arguments[1];
                                method = this.arrEvents[evtName][i].method.bind(this);
                                setTimeout(function () { //eslint-disable-line no-loop-func
                                    method(eventArgs);
                                }, 10);
                            } else {
                                result = this.arrEvents[evtName][i].method(arguments[1]);
                            }
                        } else {
                            if (this.arrEvents[evtName][i].asynch) { //eslint-disable-line no-lonely-if
                                eventHandler = this.arrEvents[evtName][i].method;
                                setTimeout(eventHandler, 1);
                            } else if (
                                this.arrEvents &&
                                this.arrEvents[evtName] &&
                                this.arrEvents[evtName][i] &&
                                this.arrEvents[evtName][i].method
                            ) {
                                result = this.arrEvents[evtName][i].method();
                            }
                        }
                        results.push(result);
                    }
                    catch (e) {
                        if (this.id) {
                            alert({
                                content: 'error: error in ' + this.id + '.fireEvent():\n\nevent name: ' +
                                eventName + '\n\nerror message: ' + e.message
                            });
                        } else {
                            alert({
                                content: 'error: error in [unknown object].fireEvent():\n\nevent name: ' +
                                eventName + '\n\nerror message: ' + e.message
                            });
                        }
                    }

                    /* eslint-enable max-depth */
                }
            }

            return results;
        }
    };

    window.varienGlobalEvents = new varienEvents(); //jscs:ignore requireCapitalizedConstructors

    return window.varienGlobalEvents;
});