all files / js/ baseDispatcher.js

82.98% Statements 39/47
58.33% Branches 14/24
83.33% Functions 10/12
82.98% Lines 39/47
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                       141× 141× 141×   297× 297× 141×                           68× 68×       68×                   68× 68×                         1127× 1127× 1127×   1127× 68×   68× 68× 68×   68× 68×   68×     68×       68× 68×   68× 68×   68× 68×                           1059×               141×      
define(['utils', 'IPlugin'], function(Utils, IPlugin) {
    "use strict";
 
    //todo может например перейти на https://github.com/component/emitter
    /**
     * @class
     * Класс диспетчера, инкапсулирует событийную модель, каждый экземпляр представляет собой событие.
     * @param {JQuery} mainDiv - элемент, в котором располагается панель. Должен содержать класс rb-wrapper.
     * @constructor BaseDispatcher
     * @extends IPlugin
     */
    function BaseDispatcher(mainDiv) {
        this._actions = {};
        this._index = 0;
        this._mainDiv = mainDiv;
    }
    Utils.inherite(BaseDispatcher, IPlugin);
    BaseDispatcher.prototype.configure = function(config) {
        Eif (typeof config === 'object') {
            if (config.loadingDiv !== undefined) {
                this._loadingDiv = $(config.loadingDiv);
            }
        }
    };
 
    // todo сделать не once, а дать возможность указать число - количество срабатываний,
    // или функцию которая если вернет true - не отписываться, false - отписываться
    /**
     * Зарегистрировать действие, которое выполнится при запуске действий
     * @param {function} action - регистрируемое действие
     * @param {boolean} [once] - выполнить действие только в первый раз
     * @returns {number|null} индекс зарегистрированного действия (null, если действие не было зарегистрировано)
     * @memberOf BaseDispatcher
     */
    BaseDispatcher.prototype.add = function(action, once) {
        Eif (typeof action === 'function') {
            this._actions[this._index++] = {
                action: action,
                once: once
            };
            return this._index-1;
        }
        return null;
    };
    // todo отписка не по индексу, а по функции
    /**
     * Удалить действие из списка зарегистрированных действий
     * @param {number} index - индекс удаляемого действия
     * @memberOf BaseDispatcher
     */
    BaseDispatcher.prototype.remove = function(index) {
        Eif (this._actions.hasOwnProperty(index)) {
            delete this._actions[index];
        }
    };
    /**
     * Запустить зарегистрированные действия
     * @param {function} [fn] - функция, которая будет выполнена после того, как выполнятся все зарегистрированные действия.
     * Если зарегистрированные функции возвращают Promise, функция выполнится после завершения этих Promise.
     * Если хотя бы одна из зарегистрированных функций (или их Promise) вернет false, фунция fn не будет вызвана.
     * @param {Array} [actionArgs] - аргументы для зарегистрированных функций (для всех функций будут переданы одни и те же аргументы).
     * @returns {*} Результат выполнения функции fn, либо undefined если функция fn не была вызвана
     * @memberOf BaseDispatcher
     */
    BaseDispatcher.prototype.runActions = function(fn, actionArgs) {
        var
            actions = [],
            results = [],
            self = this;
 
        if (Object.keys(this._actions).length) {
            this._mainDiv.append(this._loadingDiv); // todo вынести это в moving, а здесь просто вызывать функцию
 
            Object.keys(this._actions).map(function(index) {
                var value = this._actions[index],
                    result = value.action.apply(undefined, actionArgs);
 
                Eif (value.once) {
                    this.remove(index);
                }
                Iif (result instanceof Promise) {
                    actions.push(result);
                } else {
                    results.push(result);
                }
            }.bind(this));
 
            return Promise.all(actions).then(function(promiseResult) {
                self._loadingDiv.remove();
 
                var isOk = results.concat(promiseResult).every(function(res) {
                    return res !== false;
                });
                Eif (isOk) {
                    return fn && fn();
                }
            }, function(error) {
                self._loadingDiv.remove();
                console.error(error);
 
                var isOk = results.every(function(res) {
                    return res !== false;
                });
                if (isOk) {
                    return fn && fn();
                }
            });
        } else {
            return fn && fn();
        }
    };
 
    /**
     * Уничтожить экземпляр класса
     * @memberOf BaseDispatcher
     */
    BaseDispatcher.prototype.destroy = function() {
        this._actions = null;
    };
 
    return BaseDispatcher;
});