mirror of
https://bitbucket.org/bellord13/kit.git
synced 2026-11-13 19:06:11 +03:00
951 lines
30 KiB
JavaScript
951 lines
30 KiB
JavaScript
window.kit = window.kit || {};
|
|
kit.service = kit.service || {};
|
|
kit.config = kit.config || {};
|
|
|
|
|
|
(function(global){
|
|
/**
|
|
* @class kitConfig
|
|
*/
|
|
var defaultConfig = {
|
|
version: '2.0',
|
|
assetsPath: '',
|
|
requiredDependencies: [],
|
|
autoloadPluginList: [],
|
|
debug: true,
|
|
};
|
|
|
|
var stateList = {
|
|
undefined: 0,
|
|
registered: 1,
|
|
loading: 3,
|
|
loaded: 4,
|
|
installing: 5,
|
|
installed: 6,
|
|
};
|
|
|
|
/**
|
|
* @see https://requirejs.org/
|
|
* @see https://sazzer.github.io/blog/2015/05/12/Javascript-modules-ES5-vs-ES6/
|
|
* @see https://habr.com/ru/articles/501198/
|
|
*/
|
|
var MD_TYPE = { // module definition
|
|
ES: 'ES', // CMAScript2020 or ES11
|
|
UMD: 'UMD', // https://github.com/umdjs/umd
|
|
HMD: 'HMD', // HandlerMD - function(require, exports, module, global){module.exports = {}; return {};}
|
|
default: 'default',
|
|
};
|
|
/**
|
|
* @memberOf kit
|
|
* @param pluginId
|
|
* @param config
|
|
* @constructor
|
|
*/
|
|
function Plugin(pluginId, config = {}){
|
|
this.id = pluginId;
|
|
this.state = stateList.undefined;
|
|
this.state2 = stateList.undefined;
|
|
this.module = {
|
|
code: '',
|
|
exports: {},
|
|
};
|
|
this.config = {
|
|
autoRequire: false,
|
|
loadJsAfterModule: false,
|
|
isSetTimestamp: true,
|
|
path: '',
|
|
module: '', // file.js
|
|
type: 'default',
|
|
handler: undefined,
|
|
onRegister: function(plugin){},
|
|
onLoad: function(plugin){},
|
|
onInstall: function(plugin){},
|
|
js: [],
|
|
css: [],
|
|
alias: [],
|
|
deps: [],
|
|
debug: false,
|
|
};
|
|
this.pluginManager = undefined,
|
|
this.promise = new Promise(function(resolve, reject){resolve()});
|
|
this.errors = [];
|
|
|
|
this.register(config);
|
|
}
|
|
|
|
Plugin.prototype.setPluginManager = function (pluginManager){
|
|
this.pluginManager = pluginManager;
|
|
};
|
|
|
|
function isAssetLoaded(src) {
|
|
src = src.match(/^[^#?]*/)[0];
|
|
return document.querySelector('script[src^="'+src+'"]') ||
|
|
document.querySelector('link[href^="'+src+'"]') ||
|
|
document.querySelector('meta[property="kit:file-load"][content="'+src+'"]');
|
|
}
|
|
function getUrlWithTimestamp(url){
|
|
var t = ((new Date()).getTime() / 1000 / 3600 >> 0) * 3600;
|
|
try {
|
|
var uri = new URL(url);
|
|
uri.searchParams.append('__pm', String(t));
|
|
url = uri.toString();
|
|
} catch (e) {
|
|
url = String(url).split('?')[0];
|
|
url = '' + url + '?__pm' + t;
|
|
}
|
|
return url;
|
|
}
|
|
|
|
Plugin.prototype.queuePush = function (callbackPromise, argArr = []){
|
|
var self = this;
|
|
if(typeof callbackPromise !== 'function'){
|
|
return;
|
|
}
|
|
this.promise = this.promise.then(function(m){
|
|
var p = callbackPromise.apply(this, argArr);
|
|
if(p){
|
|
return p;
|
|
}
|
|
});
|
|
};
|
|
|
|
Plugin.prototype.__queue = function (admission, callback, argArr = [], context = undefined){
|
|
var self = this;
|
|
if(context === undefined) {
|
|
context = self;
|
|
}
|
|
if(self.__checkState(admission)){
|
|
callback.apply(context, argArr);
|
|
} else {
|
|
self.promise = self.promise.then(function(){
|
|
return new Promise(function (resolve, reject){
|
|
callback.apply(context, argArr);
|
|
resolve();
|
|
})
|
|
}.bind(self));
|
|
}
|
|
};
|
|
|
|
Plugin.prototype.__exec = function (admission, callback, argArr = [], context = undefined) {
|
|
var self = this;
|
|
if(context === undefined) {
|
|
context = self;
|
|
}
|
|
if(self.__checkState(admission)){
|
|
callback.apply(context, argArr);
|
|
} else {
|
|
self.promise = self.promise.then(function(){
|
|
callback.apply(context, argArr);
|
|
}.bind(self));
|
|
}
|
|
};
|
|
|
|
Plugin.prototype.__checkState = function(state, stateTo = undefined){
|
|
if(stateTo === undefined){
|
|
return this.state >= state;
|
|
}
|
|
|
|
return this.state >= state && this.state <= stateTo;
|
|
};
|
|
|
|
Plugin.prototype.__check2State = function(state, stateTo = undefined){
|
|
if(stateTo === undefined){
|
|
return this.state2 >= state;
|
|
}
|
|
|
|
return this.state2 >= state && this.state2 <= stateTo;
|
|
};
|
|
|
|
Plugin.prototype.__getValidConfig = function (c = {}){
|
|
|
|
var config = Object.assign({}, c);
|
|
|
|
if(typeof config.onLoad !== 'function') {
|
|
config.onLoad = function(plugin){};
|
|
}
|
|
if(typeof config.onInstall !== 'function') {
|
|
config.onInstall = function(plugin){};
|
|
}
|
|
if(typeof config.onRegister !== 'function') {
|
|
config.onRegister = function(plugin){};
|
|
}
|
|
if(typeof config.path !== 'string') {
|
|
config.path = '';
|
|
}
|
|
if(typeof config.js === 'string') {
|
|
config.js = [config.js];
|
|
} else if(!Array.isArray(config.js)) {
|
|
config.js = [];
|
|
}
|
|
if(typeof config.css === 'string') {
|
|
config.css = [config.css];
|
|
} else if(!Array.isArray(config.css)) {
|
|
config.css = [];
|
|
}
|
|
|
|
if(typeof config.alias === 'string') {
|
|
config.alias = [config.alias];
|
|
} else if(!Array.isArray(config.alias)) {
|
|
config.alias = [];
|
|
}
|
|
|
|
config.autoRequire = config.hasOwnProperty('autoRequire')?!!config.autoRequire:false;
|
|
config.loadJsAfterModule = config.hasOwnProperty('loadJsAfterModule')?!!config.loadJsAfterModule:false;
|
|
config.isSetTimestamp = config.hasOwnProperty('isSetTimestamp')?!!config.isSetTimestamp:true;
|
|
config.type = config.type || 'default';
|
|
|
|
if(typeof config.deps === 'string') {
|
|
config.deps = [config.deps];
|
|
} else if(!Array.isArray(config.deps)) {
|
|
config.deps = [];
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
Plugin.prototype.__setState = function (state, force = false) {
|
|
var self = this;
|
|
if(force){
|
|
self.state = state;
|
|
return;
|
|
}
|
|
if(self.__checkState(state)){
|
|
self.state = state;
|
|
}
|
|
}
|
|
|
|
Plugin.prototype.register = function (config = {}) {
|
|
var self = this;
|
|
var pluginId = self.id;
|
|
//console.warn('Plugin.register: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')');
|
|
|
|
if(
|
|
this.__checkState(stateList.installed)
|
|
) {
|
|
throw new Error('Plugin ' + pluginId + ' уже невозможно конфигурировать ('+self.state+'/'+self.state2+')');
|
|
}
|
|
|
|
var handler;
|
|
if(typeof config === 'function') {
|
|
handler = config;
|
|
config = this.config;
|
|
config.handler = handler;
|
|
config.type = MD_TYPE.HMD;
|
|
}
|
|
else {
|
|
if(
|
|
this.__checkState(stateList.loaded) || this.__check2State(stateList.loading)
|
|
) {
|
|
throw new Error('Plugin ' + pluginId + ' уже невозможно конфигурировать ('+self.state+')');
|
|
}
|
|
|
|
if(typeof config === 'object') {
|
|
config = this.__getValidConfig(config);
|
|
} else {
|
|
throw new Error('Plugin.register: plugin ' + pluginId + ' is not a valid format')
|
|
}
|
|
|
|
Object.assign(this.config, config);
|
|
}
|
|
|
|
if(!this.__checkState(stateList.registered)) {
|
|
|
|
self.config.debug && console.log(`Plugin ${self.id}: onRegister + event.`);
|
|
|
|
this.state = stateList.registered;
|
|
this.config.onRegister(this);
|
|
var event = new CustomEvent("onRegister" + this.id + "Plugin", {
|
|
"detail": {plugin: this}
|
|
});
|
|
document.dispatchEvent(event);
|
|
}
|
|
|
|
|
|
if(config.autoRequire) {
|
|
//this.require();
|
|
}
|
|
|
|
};
|
|
|
|
Plugin.prototype.load = function (callback){
|
|
|
|
var self = this;
|
|
// console.log('Plugin.load: plugin ' + self.id + ' ('+self.state+')');
|
|
if(typeof callback !== 'function') {
|
|
callback = function(){};
|
|
}
|
|
|
|
var pluginId = self.id;
|
|
|
|
if(!self.__checkState(stateList.registered)) {
|
|
console.warn(`Plugin.load(${pluginId}): is not register!.`);
|
|
return self;
|
|
}
|
|
|
|
if(self.__checkState(stateList.loaded)) {
|
|
// console.warn(`Plugin.load(${pluginId}): уже загружен!`);
|
|
callback();
|
|
return self;
|
|
}
|
|
|
|
if(self.__check2State(stateList.loading)) {
|
|
// console.log('Plugin.load: plugin ' + pluginId + ' уже грузится');
|
|
self.__exec(stateList.loaded, callback);
|
|
return self;
|
|
}
|
|
self.state2 = stateList.loading;
|
|
|
|
var config = self.config;
|
|
|
|
var getModulePromiseCallback = function (){
|
|
var src = config.path + config.module;
|
|
if(typeof config.module === 'string' && config.module !== '' && config.type === 'ES') {
|
|
return function(){
|
|
return self.getESModulePromise(src).then(function(m) {
|
|
m.__esModule = true;
|
|
self.module.exports = m;
|
|
}.bind(self));
|
|
}
|
|
} else if(typeof config.module === 'string' && config.module !== '' && config.type === 'UMD') {
|
|
if (isAssetLoaded(src)) {
|
|
self.config.debug && console.warn(`Plugin ${self.id}: Скрипт ${src} уже загружен!`);
|
|
return;
|
|
}
|
|
else {
|
|
return function (){
|
|
return self.httpGet(src)
|
|
.then(function (m) {
|
|
self.module.code = m;
|
|
}.bind(self));
|
|
};
|
|
}
|
|
} else if(config.type === 'HMD' && !(config.hasOwnProperty('handler') && typeof config.handler === 'function')) {
|
|
return function (){
|
|
return self.getScriptPromise(src);
|
|
};
|
|
} else if(typeof config.module === 'string' && config.module !== '' && config.type === 'default') {
|
|
if (isAssetLoaded(src)) {
|
|
self.config.debug && console.warn(`Plugin ${self.id}: Скрипт ${src} уже загружен!`);
|
|
return;
|
|
}
|
|
else {
|
|
return function (){
|
|
return self.getScriptPromise(src);
|
|
};
|
|
}
|
|
}
|
|
return;
|
|
};
|
|
|
|
|
|
config.css.forEach(function(item, i, array){
|
|
self.getStylePromise(config.path + item);
|
|
});
|
|
|
|
var f0;
|
|
if(self.pluginManager){
|
|
f0 = self.pluginManager.__getDepsPromiseCallback(self.config.deps);
|
|
self.queuePush(f0);
|
|
}
|
|
|
|
var f1 = getModulePromiseCallback();
|
|
var f2 = self.getJsAssetsPromiseCallback(config.js);
|
|
if(config.loadJsAfterModule) {
|
|
self.queuePush(f1);
|
|
self.queuePush(f2);
|
|
} else {
|
|
self.queuePush(f2);
|
|
self.queuePush(f1);
|
|
}
|
|
|
|
if(!f0 && !f1 && !f2){
|
|
self.state = stateList.loaded;
|
|
}
|
|
|
|
self.__queue(stateList.loaded, function(){
|
|
self.config.debug && console.log(`Plugin ${self.id}: onLoad + event.`);
|
|
if(!self.isLoaded()){
|
|
self.state = stateList.loaded;
|
|
}
|
|
config.onLoad.call(self, self);
|
|
var event = new CustomEvent('onLoad' + self.id + 'Plugin', {
|
|
"detail": {plugin: self}
|
|
});
|
|
document.dispatchEvent(event);
|
|
});
|
|
|
|
self.__exec(stateList.loaded, function(){
|
|
callback();
|
|
}.bind(self));
|
|
|
|
|
|
return self;
|
|
};
|
|
|
|
Plugin.prototype.install = function (callback){
|
|
var self = this,
|
|
global = self.pluginManager.global,
|
|
require = self.pluginManager.require.bind(self.pluginManager);
|
|
// console.warn('Plugin.install: plugin ' + self.id + ' ('+self.state+')');
|
|
if(typeof callback !== 'function') {
|
|
callback = function(){};
|
|
}
|
|
var pluginId = self.id;
|
|
|
|
if(!self.__checkState(stateList.registered)) {
|
|
console.warn(`Plugin ${pluginId}: is not register!`);
|
|
return self;
|
|
}
|
|
if(self.__checkState(stateList.installed)) {
|
|
callback();
|
|
return self;
|
|
}
|
|
|
|
if(self.__check2State(stateList.installing)) {
|
|
//console.warn(`Plugin.install(${pluginId}): уже устанавливается (${plugin.state})!`);
|
|
self.__exec(stateList.installed, callback);
|
|
return self;
|
|
}
|
|
|
|
if(!self.__checkState(stateList.loaded)) {
|
|
this.load();
|
|
}
|
|
|
|
self.state2 = stateList.installing;
|
|
|
|
var setGlobals = function (global, data) {
|
|
if(data === undefined) {
|
|
return;
|
|
}
|
|
var pluginId = self.id;
|
|
var aliasList = self.config.alias;
|
|
if(!global.hasOwnProperty(pluginId)) {
|
|
global[pluginId] = data;
|
|
}
|
|
if(Array.isArray(aliasList) && aliasList.length) {
|
|
aliasList.forEach(function (alias) {
|
|
if(!global.hasOwnProperty(alias)) {
|
|
global[alias] = data;
|
|
}
|
|
})
|
|
}
|
|
};
|
|
|
|
var module = self.module;
|
|
|
|
var installer = function(){
|
|
|
|
var __exports = undefined;
|
|
if(self.config.type === 'ES' && typeof self.config.module === 'string' && self.config.module !== '') {
|
|
__exports = (typeof self.module.exports === 'object' && self.module.exports.default !== undefined)
|
|
?self.module.exports.default
|
|
:self.module.exports;
|
|
} else if(self.config.type === 'UMD' && typeof self.config.module === 'string' && self.config.module !== '') {
|
|
(function(require, exports, module, global){
|
|
var self = global;
|
|
eval(module.code);
|
|
}.bind(global))
|
|
.call(global, require, self.module.exports, module, global);
|
|
__exports = (typeof self.module.exports === 'object' && self.module.exports.default !== undefined)
|
|
?self.module.exports.default
|
|
:self.module.exports;
|
|
} else if(self.config.type === 'HMD' && typeof self.config.handler === 'function') {
|
|
__exports = self.config.handler.bind(global)
|
|
.call(global, require, self.module.exports, module, global);
|
|
if(__exports === undefined && self.module.exports){
|
|
__exports = self.module.exports;
|
|
}
|
|
}
|
|
|
|
if(typeof global === 'object'){
|
|
setGlobals(global, __exports);
|
|
}
|
|
|
|
self.state = stateList.installed;
|
|
console.log(`%cPlugin ${pluginId}: installed.`, "color: green;");
|
|
self.config.onInstall.call(self, self);
|
|
|
|
var event = new CustomEvent('onInstall' + self.id + 'Plugin', {
|
|
"detail": {plugin: self}
|
|
});
|
|
document.dispatchEvent(event);
|
|
return true;
|
|
}.bind(this);
|
|
|
|
this.__queue(stateList.loaded, installer);
|
|
|
|
this.__exec(stateList.loaded, function(){
|
|
callback();
|
|
});
|
|
|
|
return self;
|
|
};
|
|
|
|
Plugin.prototype.exec = function(callback, argArr = [], context = undefined){
|
|
var self = this;
|
|
if(context === undefined) {
|
|
context = self;
|
|
}
|
|
if(!self.__checkState(stateList.installed)){
|
|
self.load();
|
|
self.install();
|
|
}
|
|
|
|
self.__exec(stateList.installed, callback, argArr, context);
|
|
};
|
|
|
|
Plugin.prototype.getESModulePromise = function (src) {
|
|
var self = this;
|
|
return new Promise(function(resolve, reject) {
|
|
import(src).then(function (m){
|
|
resolve(m);
|
|
}, function (error){
|
|
self.errors.push(error);
|
|
console.log(`%cPlugin ${self.id}: error import module!`, "color: red;");
|
|
reject(error);
|
|
})
|
|
});
|
|
};
|
|
|
|
Plugin.prototype.httpGet = function (url) {
|
|
var self = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
self.config.debug && console.log(`Plugin ${self.id}: httpGet ${url}`);
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.open('GET', url, true);
|
|
|
|
xhr.onload = function() {
|
|
if (this.status == 200) {
|
|
resolve(this.response);
|
|
} else {
|
|
console.log(`%cPlugin.load(${self.id}): error load file!`, "color: red;");
|
|
var error = new Error(this.statusText);
|
|
error.code = this.status;
|
|
reject(error);
|
|
}
|
|
};
|
|
|
|
xhr.onerror = function() {
|
|
console.log(`%cPlugin.load(${self.id}): error load file!`, "color: red;");
|
|
reject(new Error("Network Error"));
|
|
};
|
|
|
|
xhr.send();
|
|
});
|
|
|
|
}
|
|
|
|
Plugin.prototype.getScriptPromise = function (src) {
|
|
var self = this;
|
|
if (isAssetLoaded(src)) {
|
|
self.config.debug && console.warn(`Plugin ${self.id}: Скрипт ${src} уже загружен!`);
|
|
return undefined;
|
|
}
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
self.config.debug && console.log(`Plugin ${self.id}: load script ${src}`);
|
|
|
|
var script = document.createElement('script');
|
|
script.src = src;
|
|
if(self.config.isSetTimestamp){
|
|
script.src = getUrlWithTimestamp(src);
|
|
}
|
|
script.onload = function() {resolve(script);};
|
|
script.onerror = function() {
|
|
var error = new Error(`Ошибка загрузки скрипта ${src}`);
|
|
self.errors.push(error);
|
|
console.log(`%cPlugin.load(${self.id}): error load script!`, "color: red;");
|
|
reject(error);
|
|
};
|
|
document.head.append(script);
|
|
});
|
|
};
|
|
Plugin.prototype.getStylePromise = function (src) {
|
|
var self = this;
|
|
return new Promise(function(resolve, reject) {
|
|
if(isAssetLoaded(src)) {
|
|
self.config.debug && console.warn(`Plugin ${self.id}: Стиль ${src} уже загружен`);
|
|
resolve();
|
|
}
|
|
else {
|
|
var link = document.createElement('link');
|
|
link.rel = 'stylesheet';
|
|
link.type = 'text/css';
|
|
link.media = 'all';
|
|
link.href = src;
|
|
if(self.config.isSetTimestamp){
|
|
link.href = getUrlWithTimestamp(src);
|
|
}
|
|
document.head.append(link);
|
|
resolve(link);
|
|
}
|
|
});
|
|
}
|
|
Plugin.prototype.getAsyncScriptListPromise = function (list) {
|
|
var self = this;
|
|
var pList = list.map(self.getScriptPromise.bind(self)).filter((p) => p !== undefined);
|
|
if(pList.length){
|
|
return Promise.all( pList );
|
|
}
|
|
return undefined;
|
|
}
|
|
Plugin.prototype.getJsAssetsPromiseCallback = function(list = []){
|
|
var self = this;
|
|
if(!list.length){
|
|
return;
|
|
}
|
|
return function(){
|
|
var p = new Promise(function(resolve, reject){resolve();});
|
|
list.forEach(function(item, i, array){
|
|
if(Array.isArray(item)) {
|
|
p = p.then(function () {
|
|
return self.getAsyncScriptListPromise(item);
|
|
});
|
|
} else {
|
|
p = p.then(function () {
|
|
return self.getScriptPromise(self.config.path + item);
|
|
});
|
|
}
|
|
});
|
|
return p;
|
|
};
|
|
};
|
|
|
|
Plugin.prototype.__getRealId = function (pluginId) {
|
|
var self = this;
|
|
var pluginIdLowerCase = pluginId.toLowerCase();
|
|
|
|
if(self.id.toLowerCase() === pluginIdLowerCase) {
|
|
return self.id;
|
|
}
|
|
|
|
var alias;
|
|
for(alias of self.config.alias) {
|
|
if(pluginIdLowerCase === alias.toLowerCase()) {
|
|
return self.id;
|
|
}
|
|
}
|
|
return undefined;
|
|
};
|
|
Plugin.prototype.__is = function(pluginId){
|
|
var self = this;
|
|
return self.id === self.__getRealId(pluginId);
|
|
};
|
|
Plugin.prototype.isLoaded = function(){
|
|
var self = this;
|
|
return self.__checkState(stateList.loaded);
|
|
};
|
|
Plugin.prototype.isInstalled = function(){
|
|
var self = this;
|
|
return self.__checkState(stateList.installed);
|
|
};
|
|
Plugin.prototype.require = function(){
|
|
var self = this;
|
|
if(!self.isInstalled()){
|
|
self.config.debug && console.warn(`Plugin ${self.id}: not instaled!`);
|
|
}
|
|
return self.module.exports;
|
|
};
|
|
|
|
|
|
/**
|
|
* @class PluginManager
|
|
* @param global
|
|
* @param plugins
|
|
* @memberOf kit
|
|
*/
|
|
var PluginManager = function(global){
|
|
this.plugins = {};
|
|
this.global = global;
|
|
};
|
|
|
|
/**
|
|
* @param plugins
|
|
* @return {PluginManager}
|
|
*/
|
|
PluginManager.prototype.registerPlugins = function (plugins) {
|
|
for (var pluginId in plugins) {
|
|
if(plugins.hasOwnProperty(pluginId)) {
|
|
this.register(pluginId, plugins[pluginId]);
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
PluginManager.prototype.register = function (pluginId, config = {}) {
|
|
if(typeof pluginId !== 'string' || pluginId === ''){
|
|
console.warn(`Invalid pluginId!`, pluginId);
|
|
return;
|
|
}
|
|
var plugin = this.__getPlugin(pluginId);
|
|
if(plugin) {
|
|
plugin.register(config);
|
|
} else {
|
|
plugin = new Plugin(pluginId, config);
|
|
plugin.setPluginManager(this);
|
|
this.plugins[pluginId] = plugin;
|
|
}
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param pluginId
|
|
* @returns {undefined|Plugin}
|
|
* @private
|
|
*/
|
|
PluginManager.prototype.__getPlugin = function (pluginId) {
|
|
var self = this;
|
|
var pid, plugin;
|
|
for(pid in self.plugins) {
|
|
if(self.plugins.hasOwnProperty(pid)){
|
|
plugin = self.plugins[pid];
|
|
if(plugin.__is(pluginId)) {
|
|
return plugin;
|
|
}
|
|
}
|
|
}
|
|
return undefined;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param pluginIdList
|
|
* @returns {undefined|(function(): Promise<Awaited<unknown>[]>)}
|
|
* @private
|
|
*/
|
|
PluginManager.prototype.__getDepsPromiseCallback = function (pluginIdList = []) {
|
|
var self = this;
|
|
var pList = pluginIdList.map(function(pluginId){
|
|
var plugin = self.__getPlugin(pluginId);
|
|
if(plugin){
|
|
plugin.install();
|
|
if(plugin.isInstalled()){
|
|
return undefined;
|
|
}
|
|
return plugin.promise;
|
|
}
|
|
console.log(`%cPluginManager: plugin ${pluginId} not found!`, "color: red;");
|
|
return undefined;
|
|
}).filter((p) => p !== undefined);
|
|
|
|
if(!pList.length){
|
|
return undefined;
|
|
}
|
|
|
|
return function(){
|
|
return Promise.all(pList);
|
|
};
|
|
};
|
|
|
|
PluginManager.prototype.__getRealIdList = function (pluginIdList = []) {
|
|
var self = this;
|
|
var pList = pluginIdList.map(function(pluginId){
|
|
var plugin = self.__getPlugin(pluginId);
|
|
if(plugin){
|
|
return plugin.id;
|
|
}
|
|
return undefined;
|
|
});
|
|
|
|
return pList;
|
|
};
|
|
|
|
/**
|
|
* @memberOf kit
|
|
*/
|
|
PluginManager.prototype.exec = function (deps, callback, argArr = [], context = undefined) {
|
|
var self = this;
|
|
if(typeof deps === 'function') {
|
|
context = argArr;
|
|
argArr = callback;
|
|
callback = deps;
|
|
deps = [];
|
|
}
|
|
if(typeof deps === 'string'){
|
|
deps = [deps];
|
|
}
|
|
if(context === undefined) {
|
|
context = self;
|
|
}
|
|
if(typeof argArr === 'undefined') {
|
|
argArr = [];
|
|
}
|
|
if(typeof callback !== 'function') {
|
|
return undefined;
|
|
}
|
|
|
|
if(global.config && global.config.requiredDependencies) {
|
|
deps = Array.from(new Set(deps.concat(global.config.requiredDependencies)));
|
|
}
|
|
|
|
var depsPromiseCallback = self.__getDepsPromiseCallback(deps);
|
|
|
|
if(depsPromiseCallback) {
|
|
depsPromiseCallback().then(function(){
|
|
callback.apply(context, argArr);
|
|
});
|
|
} else {
|
|
callback.apply(context, argArr)
|
|
}
|
|
};
|
|
|
|
PluginManager.prototype.exec2 = function (deps, callback) {
|
|
var self = this;
|
|
var context = this;
|
|
|
|
var depsPromiseCallback = self.__getDepsPromiseCallback(deps);
|
|
|
|
var getArgArr = function () {
|
|
var argArr = [];
|
|
deps.forEach(function (pluginId) {
|
|
var plugin = self.__getPlugin(pluginId);
|
|
if(plugin){
|
|
argArr.push(self.require(pluginId));
|
|
return;
|
|
}
|
|
argArr.push(undefined);
|
|
}.bind(self));
|
|
return argArr;
|
|
}.bind(self);
|
|
|
|
if(depsPromiseCallback) {
|
|
depsPromiseCallback().then(function(){
|
|
callback.apply(context, getArgArr());
|
|
});
|
|
} else {
|
|
callback.apply(context, getArgArr())
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {(string|string[])} deps
|
|
* @param {function} callback
|
|
* @memberOf kit
|
|
*/
|
|
|
|
PluginManager.prototype.ready = function(deps, callback = undefined) {
|
|
var self = this;
|
|
if(typeof deps === 'function') {
|
|
callback = deps;
|
|
deps = [];
|
|
}
|
|
if(typeof callback !== 'function') {
|
|
callback = function (){};
|
|
}
|
|
self.__ready(self.exec, [deps, callback], self);
|
|
};
|
|
PluginManager.prototype.__ready = function(fn, args = [], context = window) {
|
|
var self = this;
|
|
context = context || this;
|
|
if (/complete|interactive|loaded/.test(document.readyState)) {
|
|
fn.apply(context, args);
|
|
} else {
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
fn.apply(context, args);
|
|
}.bind(this));
|
|
}
|
|
};
|
|
|
|
PluginManager.prototype.require = function (pluginId, callback) {
|
|
|
|
var plugin = this.__getPlugin(pluginId);
|
|
if(!plugin) {
|
|
console.warn('PluginManager.require: plugin ' + pluginId + ' not found!');
|
|
return undefined;
|
|
}
|
|
pluginId = plugin.id;
|
|
var module = plugin.module;
|
|
|
|
if(typeof callback !== 'function') {
|
|
callback = function(){};
|
|
}
|
|
|
|
plugin.install(callback);
|
|
|
|
return module.exports;
|
|
};
|
|
|
|
PluginManager.prototype.install = function (pluginId, callback) {
|
|
|
|
var plugin = this.__getPlugin(pluginId);
|
|
if(!plugin) {
|
|
console.warn('PluginManager.install: plugin ' + pluginId + ' not found!');
|
|
return undefined;
|
|
}
|
|
pluginId = plugin.id;
|
|
var module = plugin.module;
|
|
plugin.install(callback);
|
|
};
|
|
|
|
|
|
function init(global){
|
|
|
|
var manager = new PluginManager(global);
|
|
global.ready = manager.ready.bind(manager);
|
|
global.exec = manager.exec.bind(manager);
|
|
global.require = manager.require.bind(manager);
|
|
manager.register('pluginManager', {
|
|
alias: 'pm',
|
|
type: MD_TYPE.HMD,
|
|
handler: function(require, exports, module, global) {
|
|
global.PluginManagerClass = PluginManager;
|
|
if(typeof window === 'object'){
|
|
window.__PluginManager__ = manager;
|
|
/**
|
|
* @var __pmGlobal__
|
|
*/
|
|
window.__pmGlobal__ = global;
|
|
}
|
|
return module.exports = manager;
|
|
},
|
|
onInstall: function(plugin){
|
|
},
|
|
});
|
|
manager.install('pluginManager');
|
|
|
|
|
|
manager.register('config', {
|
|
type: MD_TYPE.HMD,
|
|
handler: function(require, exports, module, global) {
|
|
|
|
var script = document.currentScript;
|
|
if(script){
|
|
try {
|
|
var uri = new URL(script.src);
|
|
defaultConfig.assetsPath = uri.pathname.split('/').slice(0, -2).join('/');
|
|
} catch (e) {
|
|
var path = script.src.split('?')[0];
|
|
defaultConfig.assetsPath = path.split('/').slice(0, -2).join('/');
|
|
}
|
|
}
|
|
|
|
var config = global.config || {};
|
|
config = Object.assign({}, defaultConfig, config);
|
|
if(typeof window === 'object'){
|
|
window.__pmConfig__ = global.config = config;
|
|
}
|
|
|
|
(function(){
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
console.log('%cDOMContentLoaded', 'color:#2053ff');
|
|
});
|
|
}());
|
|
},
|
|
onInstall: function(plugin){
|
|
if(typeof window === 'object'){
|
|
if(window.hasOwnProperty('__PluginManagerConfigHandler__') && typeof __PluginManagerConfigHandler__ === 'function'){
|
|
manager.registerPlugins(__PluginManagerConfigHandler__());
|
|
}
|
|
}
|
|
},
|
|
});
|
|
manager.install('config');
|
|
}
|
|
init(global);
|
|
|
|
})(kit);
|
|
|