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) {
if (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) {
if (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) {
if (this._actions.hasOwnProperty(index)) {
delete this._actions[index];
}
};
/**
* Запустить зарегистрированные действия
* @param {function|undefined} [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);
if (value.once) {
this.remove(index);
}
if (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;
});
if (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;
});