diff --git a/assets/Action/Action.js b/assets/Action/Action.js index ab2e1e6..cbd1198 100644 --- a/assets/Action/Action.js +++ b/assets/Action/Action.js @@ -1,5 +1,5 @@ /** @module Action */ -kit.PluginManager.register('Action', function(module, exports, require, global) { +__PluginManager__.register('Action', function(require, exports, module, global) { var support = require('support'); diff --git a/assets/ActionCollection/ActionCollection.js b/assets/ActionCollection/ActionCollection.js index bd79b56..b0bce25 100644 --- a/assets/ActionCollection/ActionCollection.js +++ b/assets/ActionCollection/ActionCollection.js @@ -1,5 +1,5 @@ /** @module ActionCollection */ -kit.PluginManager.register('ActionCollection', function(module, exports, require, global) { +__PluginManager__.register('ActionCollection', function(require, exports, module, global) { var Collection = require('Collection'); var support = require('support'); diff --git a/assets/Viewer/Viewer.js b/assets/Viewer/Viewer.js index 7b5a209..e27081f 100644 --- a/assets/Viewer/Viewer.js +++ b/assets/Viewer/Viewer.js @@ -1,5 +1,5 @@ /** @module Viewer */ -kit.PluginManager.register('Viewer', function(module, exports, require, global) { +__PluginManager__.register('Viewer', function(require, exports, module, global) { var Collection = require('Collection'); var support = require('support'); diff --git a/assets/align/align.js b/assets/align/align.js index 6da0465..9ec8c25 100644 --- a/assets/align/align.js +++ b/assets/align/align.js @@ -1,5 +1,5 @@ /** @module align */ -kit.PluginManager.register('align',function(module, exports, require) { +__PluginManager__.register('align',function(require, exports, module) { var support = require('support'); diff --git a/assets/animations/animations.js b/assets/animations/animations.js index 1173cec..73827a1 100644 --- a/assets/animations/animations.js +++ b/assets/animations/animations.js @@ -2,7 +2,7 @@ * @link https://animista.net/ * @module animations **/ -kit.PluginManager.register('animations',function(module, exports, require, global) { +__PluginManager__.register('animations',function(require, exports, module, global) { /** * @memberOf kit diff --git a/assets/autoComplete/autoComplete.js b/assets/autoComplete/autoComplete.js index 24a6843..fba944f 100644 --- a/assets/autoComplete/autoComplete.js +++ b/assets/autoComplete/autoComplete.js @@ -1,5 +1,5 @@ -(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document); +//(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document); (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : diff --git a/assets/autoComplete/autoComplete.min.js b/assets/autoComplete/autoComplete.min.js index 01fc1b6..ea78fd9 100644 --- a/assets/autoComplete/autoComplete.min.js +++ b/assets/autoComplete/autoComplete.min.js @@ -1,5 +1,5 @@ /** @module autoComplete */ -kit.PluginManager.register('autoComplete', function(module, exports, require, global){ +__PluginManager__.register('autoComplete', function(require, exports, module, global){ var t,e;t=this,e=function(){"use strict";function t(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function e(e){for(var n=1;nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,u=!0,a=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return u=t.done,t},e:function(t){a=!0,s=t},f:function(){try{u||null==n.return||n.return()}finally{if(a)throw s}}}}(n.keys);try{for(l.s();!(c=l.n()).done;)a(c.value)}catch(t){l.e(t)}finally{l.f()}}else a()})),n.filter&&(i=n.filter(i));var s=i.slice(0,e.resultsList.maxResults);e.feedback={query:t,matches:i,results:s},f("results",e)},m="aria-expanded",b="aria-activedescendant",y="aria-selected",v=function(t,n){t.feedback.selection=e({index:n},t.feedback.results[n])},g=function(t){t.isOpen||((t.wrapper||t.input).setAttribute(m,!0),t.list.removeAttribute("hidden"),t.isOpen=!0,f("open",t))},w=function(t){t.isOpen&&((t.wrapper||t.input).setAttribute(m,!1),t.input.setAttribute(b,""),t.list.setAttribute("hidden",""),t.isOpen=!1,f("close",t))},O=function(t,e){var n=e.resultItem,r=e.list.getElementsByTagName(n.tag),o=!!n.selected&&n.selected.split(" ");if(e.isOpen&&r.length){var s,u,a=e.cursor;t>=r.length&&(t=0),t<0&&(t=r.length-1),e.cursor=t,a>-1&&(r[a].removeAttribute(y),o&&(u=r[a].classList).remove.apply(u,i(o))),r[t].setAttribute(y,!0),o&&(s=r[t].classList).add.apply(s,i(o)),e.input.setAttribute(b,r[e.cursor].id),e.list.scrollTop=r[t].offsetTop-e.list.clientHeight+r[t].clientHeight+5,e.feedback.cursor=e.cursor,v(e,t),f("navigate",e)}},A=function(t){O(t.cursor+1,t)},k=function(t){O(t.cursor-1,t)},L=function(t,e,n){(n=n>=0?n:t.cursor)<0||(t.feedback.event=e,v(t,n),f("selection",t),w(t))};function j(t,n){var r=this;return new Promise((function(i,o){var s,u;return s=n||((u=t.input)instanceof HTMLInputElement||u instanceof HTMLTextAreaElement?u.value:u.innerHTML),function(t,e,n){return e?e(t):t.length>=n}(s=t.query?t.query(s):s,t.trigger,t.threshold)?d(t,s).then((function(n){try{return t.feedback instanceof Error?i():(h(s,t),t.resultsList&&function(t){var n=t.resultsList,r=t.list,i=t.resultItem,o=t.feedback,s=o.matches,u=o.results;if(t.cursor=-1,r.innerHTML="",s.length||n.noResults){var c=new DocumentFragment;u.forEach((function(t,n){var r=a(i.tag,e({id:"".concat(i.id,"_").concat(n),role:"option",innerHTML:t.match,inside:c},i.class&&{class:i.class}));i.element&&i.element(r,t)})),r.append(c),n.element&&n.element(r,o),g(t)}else w(t)}(t),c.call(r))}catch(t){return o(t)}}),o):(w(t),c.call(r));function c(){return i()}}))}var S=function(t,e){for(var n in t)for(var r in t[n])e(n,r)},T=function(t){var n,r,i,o=t.events,s=(n=function(){return j(t)},r=t.debounce,function(){clearTimeout(i),i=setTimeout((function(){return n()}),r)}),u=t.events=e({input:e({},o&&o.input)},t.resultsList&&{list:o?e({},o.list):{}}),a={input:{input:function(){s()},keydown:function(e){!function(t,e){switch(t.keyCode){case 40:case 38:t.preventDefault(),40===t.keyCode?A(e):k(e);break;case 13:e.submit||t.preventDefault(),e.cursor>=0&&L(e,t);break;case 9:e.resultsList.tabSelect&&e.cursor>=0&&L(e,t);break;case 27:e.input.value="",w(e)}}(e,t)},blur:function(){w(t)}},list:{mousedown:function(t){t.preventDefault()},click:function(e){!function(t,e){var n=e.resultItem.tag.toUpperCase(),r=Array.from(e.list.querySelectorAll(n)),i=t.target.closest(n);i&&i.nodeName===n&&L(e,t,r.indexOf(i))}(e,t)}}};S(a,(function(e,n){(t.resultsList||"input"===n)&&(u[e][n]||(u[e][n]=a[e][n]))})),S(u,(function(e,n){t[e].addEventListener(n,u[e][n])}))};function E(t){var n=this;return new Promise((function(r,i){var o,s,u;if(o=t.placeHolder,u={role:"combobox","aria-owns":(s=t.resultsList).id,"aria-haspopup":!0,"aria-expanded":!1},a(t.input,e(e({"aria-controls":s.id,"aria-autocomplete":"both"},o&&{placeholder:o}),!t.wrapper&&e({},u))),t.wrapper&&(t.wrapper=a("div",e({around:t.input,class:t.name+"_wrapper"},u))),s&&(t.list=a(s.tag,e({dest:[s.destination,s.position],id:s.id,role:"listbox",hidden:"hidden"},s.class&&{class:s.class}))),T(t),t.data.cache)return d(t).then((function(t){try{return c.call(n)}catch(t){return i(t)}}),i);function c(){return f("init",t),r()}return c.call(n)}))}function x(t){var e=t.prototype;e.init=function(){E(this)},e.start=function(t){j(this,t)},e.unInit=function(){if(this.wrapper){var t=this.wrapper.parentNode;t.insertBefore(this.input,this.wrapper),t.removeChild(this.wrapper)}var e;S((e=this).events,(function(t,n){e[t].removeEventListener(n,e.events[t][n])}))},e.open=function(){g(this)},e.close=function(){w(this)},e.goTo=function(t){O(t,this)},e.next=function(){A(this)},e.previous=function(){k(this)},e.select=function(t){L(this,null,t)},e.search=function(t,e,n){return p(t,e,n)}}return function t(e){this.options=e,this.id=t.instances=(t.instances||0)+1,this.name="autoComplete",this.wrapper=1,this.threshold=1,this.debounce=0,this.resultsList={position:"afterend",tag:"ul",maxResults:5},this.resultItem={tag:"li"},function(t){var e=t.name,r=t.options,i=t.resultsList,o=t.resultItem;for(var s in r)if("object"===n(r[s]))for(var a in t[s]||(t[s]={}),r[s])t[s][a]=r[s][a];else t[s]=r[s];t.selector=t.selector||"#"+e,i.destination=i.destination||t.selector,i.id=i.id||e+"_list_"+t.id,o.id=o.id||e+"_result",t.input=u(t.selector)}(this),x.call(this,t),E(this)}},"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).autoComplete=e(); diff --git a/assets/bsCore/bsCore.js b/assets/bsCore/bsCore.js index f6af871..3996fa5 100644 --- a/assets/bsCore/bsCore.js +++ b/assets/bsCore/bsCore.js @@ -1,5 +1,5 @@ /** @module bsCore */ -kit.PluginManager.register('bsCore', function(module, exports, require, global){ +__PluginManager__.register('bsCore', function(require, exports, module, global){ /** * @memberOf kit diff --git a/assets/bsToast/bsToast.js b/assets/bsToast/bsToast.js index acb4229..049232f 100644 --- a/assets/bsToast/bsToast.js +++ b/assets/bsToast/bsToast.js @@ -1,5 +1,5 @@ /** @module bsToast */ -kit.PluginManager.register('bsToast', function(module, exports, require){ +__PluginManager__.register('bsToast', function(require, exports, module){ var bsCore = require('bsCore'); var diff --git a/assets/bsToastService/bsToastService.js b/assets/bsToastService/bsToastService.js index 5fde465..5419da5 100644 --- a/assets/bsToastService/bsToastService.js +++ b/assets/bsToastService/bsToastService.js @@ -1,5 +1,5 @@ /** @module bsToastService */ -kit.PluginManager.register('bsToastService', function(module, exports, require, global){ +__PluginManager__.register('bsToastService', function(require, exports, module, global){ var support = require('support'); var bsToast = require('bsToast'); var Collection = require('Collection'); diff --git a/assets/chosen/chosen.jquery.js b/assets/chosen/chosen.jquery.js index 6433139..91bef57 100644 --- a/assets/chosen/chosen.jquery.js +++ b/assets/chosen/chosen.jquery.js @@ -1,5 +1,5 @@ /** @module chosen */ -kit.PluginManager.register('Chosen', function(module, exports, require, global) { +__PluginManager__.register('Chosen', function(require, exports, module, global) { var jQuery = require('jQuery'); /*! diff --git a/assets/collapse/collapse.js b/assets/collapse/collapse.js index ff7b05b..b325fb2 100644 --- a/assets/collapse/collapse.js +++ b/assets/collapse/collapse.js @@ -1,4 +1,4 @@ -kit.PluginManager.register('collapse', function(module, exports, require) { +__PluginManager__.register('collapse', function(require, exports, module) { var bsCore = require('bsCore'); /** diff --git a/assets/collection/collection.js b/assets/collection/collection.js index 5cdd3f3..dd3f5c8 100644 --- a/assets/collection/collection.js +++ b/assets/collection/collection.js @@ -1,5 +1,5 @@ /** @module Collection */ -kit.PluginManager.register('Collection', function(module, exports, require, global) { +__PluginManager__.register('Collection', function(require, exports, module, global) { var support = require('support'); var valueEx = support.valueEx; diff --git a/assets/config/config.js b/assets/config/config.js index b4dab7a..09e5c33 100644 --- a/assets/config/config.js +++ b/assets/config/config.js @@ -2,8 +2,7 @@ * @namespace kit * @module kit */ -var kit; -kit = window.kit = window.kit || {}; +window.kit = window.kit || {}; /** * @typedef kit.service */ @@ -17,7 +16,7 @@ kit.config = kit.config || {}; Object.assign(kit.config, { debug: true, assetsPath: '/local/templater.dev/kit/assets', - requiredDependencies: ['bsCore', 'toolkit', 'support'], - autoloadPluginList: ['tooltip', 'support'], + requiredDependencies: [], + autoloadPluginList: ['tooltip'], defaultPhoneMask: '+7 (999) 999-99-99', }); \ No newline at end of file diff --git a/assets/cookie/cookie.js b/assets/cookie/cookie.js index da22823..9019767 100644 --- a/assets/cookie/cookie.js +++ b/assets/cookie/cookie.js @@ -1,7 +1,7 @@ /** * @module cookie **/ -kit.PluginManager.register('cookie', function(module, exports, require){ +__PluginManager__.register('cookie', function(require, exports, module){ var defaultConverter = { read: function (value) { diff --git a/assets/core/core.js b/assets/core/core.js index f3f4546..850fad0 100644 --- a/assets/core/core.js +++ b/assets/core/core.js @@ -1,19 +1,644 @@ - -var kit; -kit = window.kit = window.kit || {}; +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, - loaded: 3, - installed: 4, + loading: 3, + loaded: 4, + installing: 5, + installed: 6, }; - var moduleTypeList = { - loader: 'loader', - import: 'import', + + /** + * @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 {};} }; + /** + * @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: 'ES', + 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){ + try { + var uri = new URL(url); + uri.searchParams.append('__pm', (new Date()).getTime()); + url = uri.toString(); + } catch (e) { + url = String(url).split('?')[0]; + url = '' + url + '?__pm' + (new Date()).getTime(); + } + 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 || 'ES'; + + 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); + }; + } + 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 exports = self.module.exports; + + var installer = function(){ + + var __exports = undefined; + if(self.config.type === 'ES' && typeof self.config.module === 'string' && self.config.module !== '') { + __exports = (typeof exports === 'object' && exports.default !== undefined) + ?exports.default + :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, exports, module, global); + __exports = (typeof exports === 'object' && exports.default !== undefined) + ?exports.default + :exports; + } else if(self.config.type === 'HMD' && typeof self.config.handler === 'function') { + __exports = self.config.handler.bind(global) + .call(global, require, exports, module, global); + if(__exports === undefined && exports){ + __exports = 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 @@ -21,31 +646,16 @@ kit.config = kit.config || {}; * @param plugins * @memberOf kit */ - var PluginManager = function(global, plugins = {}){ + var PluginManager = function(global){ this.plugins = {}; this.global = global; - this.registerPlugins(plugins); - }; - - /** - * - * @type {kit.PluginManager|PluginManager} - * @private - */ - var __proto = PluginManager.prototype; - - __proto.__checkState = function(pluginId, state){ - return this.plugins.hasOwnProperty(pluginId) && this.plugins[pluginId].state >= state; }; /** * @param plugins * @return {PluginManager} */ - __proto.registerPlugins = function (plugins) { - if(Array.isArray(plugins)) { - plugins = Object.assign({}, plugins); - } + PluginManager.prototype.registerPlugins = function (plugins) { for (var pluginId in plugins) { if(plugins.hasOwnProperty(pluginId)) { this.register(pluginId, plugins[pluginId]); @@ -54,536 +664,144 @@ kit.config = kit.config || {}; return this; }; - /** - * @return {boolean} - */ - __proto.register = function (pluginId, config = {}) { - //console.warn('PluginManager.register: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); - var defaultPlugin = { - module: { - exports: {}, - }, - config: { - }, - promise: new Promise(function(resolve, reject){resolve()}), - id: pluginId, - state: stateList.undefined, - stateInit: { - loading: false, - installing: false, - }, - }; + PluginManager.prototype.register = function (pluginId, config = {}) { + if(typeof pluginId !== 'string' || pluginId === ''){ + console.warn(`Invalid pluginId!`, pluginId); + return; + } var plugin = this.__getPlugin(pluginId); if(plugin) { - pluginId = plugin.id; + plugin.register(config); } else { - plugin = this.plugins[pluginId] = defaultPlugin; + plugin = new Plugin(pluginId, config); + plugin.setPluginManager(this); + this.plugins[pluginId] = plugin; } - - /** - * @todo !!! - */ - if( - (this.__checkState(pluginId, stateList.installed) && typeof config.loader === 'function') || - ( - (plugin.stateInit.loading || this.__checkState(pluginId, stateList.loaded)) && typeof config === 'object' - ) - ) { - console.warn('PluginManager.register: plugin ' + pluginId + ' уже невозможно конфигурировать ('+plugin.state+')'); - return false; - } - - var loader; - if(typeof config === 'function') { - loader = config; - config = plugin.config; - config.loader = loader; - config.type = 'loader'; - if(this.__checkState(pluginId, stateList.registered)) { - if(this.__checkState(pluginId, stateList.loaded)){ - plugin.stateInit.installing = false; - } - //console.log(`PluginManager.register(${pluginId}): (${plugin.state} > ${stateList.registered})`); - plugin.state = stateList.registered; - if(plugin.config.autoRequire) { - this.require(pluginId); - } - } - } - - if(typeof config === 'object') { - if(typeof config.onLoad !== 'function') { - config.onLoad = function(){}; - } - if(typeof config.onInstall !== 'function') { - config.onInstall = function(){}; - } - if(typeof config.onRegister !== 'function') { - config.onRegister = function(){}; - } - if(typeof config.path !== 'string') { - config.path = ''; - } - if(!config.hasOwnProperty('modulePath')) { - config.modulePath = config.path; - } else if(typeof config.modulePath !== 'string') { - config.modulePath = 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.loadJsAfterModule = !!config.loadJsAfterModule; - config.isSetTimestamp = config.hasOwnProperty('isSetTimestamp')?!!config.isSetTimestamp:true; - config.type = config.type || 'import'; //loader - - if(typeof config.deps === 'string') { - config.deps = [config.deps]; - } else if(!Array.isArray(config.deps)) { - config.deps = []; - } - - } else { - console.warn('PluginManager.register: plugin ' + pluginId + ' is not a valid format'); - return false; - } - - Object.assign(plugin.config, config); - - if(!this.__checkState(pluginId, stateList.registered)) { - plugin.state = stateList.registered; - plugin.config.onRegister(plugin); - var event = new CustomEvent("onRegister" + plugin.id + "Plugin", { - "detail": {plugin: plugin} - }); - document.dispatchEvent(event); - } - - return true; }; /** + * * @param pluginId - * @param callback - * @return {PluginManager} + * @returns {undefined|Plugin} + * @private */ - __proto.load = function (pluginId, callback) { + PluginManager.prototype.__getPlugin = function (pluginId) { var self = this; - //console.log('PluginManager.load: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); - if(typeof callback !== 'function') { - callback = function(){}; - } - - var plugin = this.__getPlugin(pluginId); - if(plugin) { - pluginId = plugin.id; - } - - if(!this.__checkState(pluginId, stateList.registered)) { - console.warn('kit.load: plugin ' + pluginId + ' is not register'); - return this; - } - if(this.__checkState(pluginId, stateList.loaded)) { - //console.warn('PluginManager.load: plugin ' + pluginId + ' уже загружен'); - callback(); - return this; - } - - - if(plugin.stateInit.loading) { - //console.log('PluginManager.install: plugin ' + pluginId + ' уже грузится'); - this.__exec(pluginId, callback); - return this; - } - plugin.stateInit.loading = true; - - var configModule = plugin.config; - - var stackPush = function (callbackPromise, argArr = []){ - if(typeof plugin.promise === 'undefined') { - plugin.promise = callbackPromise.apply(this, argArr); - } else { - plugin.promise = plugin.promise.then(function(m){ - return callbackPromise.apply(this, argArr); - }); - } - }.bind(this); - - var getModulePromise = (function () { - - function getFileLoadNode(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 loadScript(src, resolveCallback, rejectCallback) { - var originSrc = src; - src = String(src).split('?')[0]; - if(typeof resolveCallback !== 'function'){ - resolveCallback = function(){}; + var pid, plugin; + for(pid in self.plugins) { + if(self.plugins.hasOwnProperty(pid)){ + plugin = self.plugins[pid]; + if(plugin.__is(pluginId)) { + return plugin; } - if(typeof rejectCallback !== 'function'){ - rejectCallback = function(res){ - console.warn(res.message, originSrc); - }; - } - return new Promise(function(resolve, reject) { - var loadNode = getFileLoadNode(src); - if (loadNode) { - global.config.debug && console.warn(`Скрипт ${src} уже загружен`); - // self.__ready(resolve, [loadNode]); - resolve(); - } else { - var script = document.createElement('script'); - - try { - var url = new URL(originSrc); - if(plugin.config.isSetTimestamp){ - url.searchParams.append('__pm', (new Date()).getTime()); - } - script.src = url.toString(); - } catch (e) { - script.src = '' + src + '?__pm' + ((new Date()).getTime()); - } - - script.onload = function() {resolve(script);}; - script.onerror = function() {reject(new Error(`Ошибка загрузки скрипта ${src}`));}; - document.head.append(script); - } - }).then(resolveCallback, rejectCallback); } - function syncLoadScriptList(list) { - - return new Promise(function(resolve, reject) { - var i = 0; - var status = true; - var count = list.length; - var checkResolve = function(src, cond){ - if(!cond) { - console.error(`Ошибка загрузки скрипта ${src}`) - } - status = status && cond; - i++; - if(i === count) { - resolve(); - } - }; - var syncPromise = new Promise(function(_resolve, _reject){_resolve();}); - list.forEach(function(item, i, arr){ - syncPromise.then(function(){ - var src = configModule.path + item; - var loadNode = getFileLoadNode(src); - if(loadNode){ - self.__ready(resolve, [src, true]); - // resolve(src, true); - } else { - var script = document.createElement('script'); - script.src = '' + src + '?__pm' + (new Date()).getTime(); - script.onload = () => checkResolve(src, true); - script.onerror = () => checkResolve(src, false); - document.head.append(script); - } - }); - }); - }) - } - function loadStyle(src) { - return new Promise(function(resolve, reject) { - var loadNode = getFileLoadNode(src); - if(loadNode) { - global.config.debug && console.warn(`Стиль ${src} уже загружен`); - // self.__ready(resolve, [src]); - resolve(); - } else { - var link = document.createElement('link'); - link.rel = 'stylesheet'; - link.type = 'text/css'; - link.href = src + '?__pm' + (new Date()).getTime(); - link.media = 'all'; - document.head.append(link); - resolve(link); - } - }); - } - - var getImportPromise = function (){ - if(configModule.module && configModule.type === 'import') { - return import(configModule.modulePath + configModule.module).then(function(m) { - m.__esModule = true; - plugin.module.exports = m; - }.bind(this), function(r){ - console.error(r); - }); - } else if(configModule.module && configModule.type === 'loader' && !(configModule.hasOwnProperty('loader') && typeof configModule.loader === 'function')) { - return loadScript(configModule.modulePath + configModule.module).then(function() { - - }.bind(this)); - } - return new Promise(function(resolve, reject){resolve();}); - }.bind(this); - var getResPromise = function(){ - var p = new Promise(function(resolve, reject){resolve();}); - configModule.js.forEach(function(item, i, array){ - if(Array.isArray(item)) { - p = p.then(function () { - return syncLoadScriptList(item); - }); - } else { - p = p.then(function () { - return loadScript(configModule.path + item); - }); - } - //loadScript(configModule.path + item); - }); - return p; - }.bind(this); - var setSkipLoadPromise = function (depsPromise) { - - var jsPromiseExists = true, importPromiseExists = true; - if(configModule.js.length === 0) { - jsPromiseExists = false; - } - if((!configModule.module && configModule.type === 'import') || (configModule.type === 'loader' && typeof configModule.loader === 'function')) { - importPromiseExists = false; - } - plugin.skipLoadPromise = !importPromiseExists && !jsPromiseExists && !depsPromise; - - return plugin.skipLoadPromise; - }.bind(this); - - configModule.css.forEach(function(item, i, array){ - loadStyle(configModule.path + item); - }); - - var depsPromise = this.__getDepsPromise(this.depsCorrection(configModule.deps)); - setSkipLoadPromise(depsPromise); - - if(depsPromise) { - stackPush(function () { - return depsPromise; - }); - } - - if(configModule.loadJsAfterModule) { - stackPush(getImportPromise); - stackPush(getResPromise); - } else { - stackPush(getResPromise); - stackPush(getImportPromise); - } - - this.__exec(pluginId, function(){ - plugin.state = stateList.loaded; - plugin.skipLoadPromise = true; - configModule.onLoad.call(plugin.module.exports); - var event = new CustomEvent("onLoad" + plugin.id + "Plugin", { - "detail": {plugin: plugin} - }); - document.dispatchEvent(event); - callback(); - }.bind(this)); - - return plugin.promise; - - }).bind(this); - - getModulePromise(); - - return this; + } + return undefined; }; /** - * @param pluginId - * @param callback - * @return {PluginManager} + * + * @param pluginIdList + * @returns {undefined|(function(): Promise[]>)} + * @private */ - __proto.install = function(pluginId, callback){ - //console.warn('PluginManager.install: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); - if(typeof callback !== 'function') { - callback = function(){}; - } - - var plugin = this.__getPlugin(pluginId); - if(plugin) { - pluginId = plugin.id; - } - var module = plugin.module; - - if(!this.__checkState(pluginId, stateList.registered)) { - console.warn('PluginManager.install: plugin ' + pluginId + ' is not register'); - return this; - } - if(this.__checkState(pluginId, stateList.installed)) { - callback(); - return this; - } - - if(plugin.stateInit.installing) { - //console.warn(`PluginManager.install(${pluginId}): уже устанавливается (${plugin.state}).`); - this.__exec(pluginId, callback); - return this; - } - plugin.stateInit.installing = true; - - this.load(pluginId); - - var installer = function(){ - var setGlobalExtension = function (key, aliasList, data) { - if(data === undefined) { - return; + 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; } - if(!this.global.hasOwnProperty(key)) { - this.global[key] = data; - } - if(Array.isArray(aliasList) && aliasList.length) { - aliasList.forEach(function (alias) { - setGlobalExtension(alias, [], data) - }.bind(this)) - } - }.bind(this); - - /** - * @todo !!! - */ - var returnData; - if(plugin.config.type === moduleTypeList.loader && typeof plugin.config.loader === 'function') { - // var returnData = plugin.config.loader.bind(module.exports).call(module.exports, module, module.exports, this.require.bind(this), global); - returnData = plugin.config.loader.bind(this.global).call(this.global, module, module.exports, this.require.bind(this), this.global); - if(returnData === undefined && module.exports){ - returnData = module.exports; - } - setGlobalExtension(pluginId, plugin.config.alias, returnData); - } else if(plugin.config.type === moduleTypeList.import && typeof plugin.config.module === 'string') { - returnData = (typeof module.exports === 'object' && module.exports.default !== undefined)?module.exports.default:module.exports; - setGlobalExtension(pluginId, plugin.config.alias, returnData); + return plugin.promise; } + console.log(`%cPluginManager: plugin ${pluginId} not found!`, "color: red;"); + return undefined; + }).filter((p) => p !== undefined); - console.log(`%cPluginManager.install(${pluginId}): installed (${plugin.state} > ${stateList.installed}).`, "color: green;"); - plugin.state = stateList.installed; - - - return true; - }.bind(this); - - this.__exec(pluginId, function(){ - if(!this.__checkState(pluginId, stateList.installed)) { - if(installer()){ - plugin.config.onInstall.call(module.exports, plugin); - var event = new CustomEvent("onInstall" + plugin.id + "Plugin", { - "detail": {plugin: plugin} - }); - document.dispatchEvent(event); - } - } - callback(); - }.bind(this)); - - return this; - }; - - /** - * @name kitPluginManagerRequire - * @param {string} pluginId - * @param {callback} callback - * @return {boolean} - * @memberOf {kit} - */ - __proto.require = function (pluginId, callback) { - - var plugin = this.__getPlugin(pluginId); - if(!plugin) { - console.warn('PluginManager.require: plugin ' + pluginId + ' not found ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); + if(!pList.length){ return undefined; } - pluginId = plugin.id; - var module = plugin.module; - if(!this.__checkState(pluginId, stateList.registered)) { - console.warn('PluginManager.require: plugin ' + pluginId + ' is not register'); - return undefined; - } - if(typeof callback !== 'function') { - callback = function(){}; - } - - this.install(pluginId, callback); - - return module.exports; + return function(){ + return Promise.all(pList); + }; }; - - - __proto.depsCorrection = function(deps){ - if(!Array.isArray(deps) ) { - deps = [deps]; - } - var correct = []; - deps.forEach(function(pluginId, i, arr) { - var realPlugin = this.__getPlugin(pluginId); - if(realPlugin === undefined) { - console.warn(`Plugin "${pluginId}" not registered!`); - return false; + PluginManager.prototype.__getRealIdList = function (pluginIdList = []) { + var self = this; + var pList = pluginIdList.map(function(pluginId){ + var plugin = self.__getPlugin(pluginId); + if(plugin){ + return plugin.id; } - correct.push(realPlugin.id); - }.bind(this)); - return correct; + return undefined; + }); + + return pList; }; /** * @memberOf kit */ - __proto.exec = function (deps, callback, argArr = [], context = undefined) { - + 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 = this; + context = self; } - - deps = this.depsCorrection(deps); - if(typeof argArr === 'undefined') { argArr = []; } - - deps = Array.from(new Set(deps.concat(global.config.requiredDependencies))); - if(typeof callback !== 'function') { return undefined; } - var depsPromise = this.__getDepsPromise(deps); + + 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 () { - if(argArr.length === 0) { - deps.forEach(function (pluginId) { - argArr.push(this.require(pluginId)); - }.bind(this)); - return argArr; - } + 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(this); + }.bind(self); - if(depsPromise) { - depsPromise.then(function(){ + if(depsPromiseCallback) { + depsPromiseCallback().then(function(){ callback.apply(context, getArgArr()); }); } else { @@ -591,59 +809,21 @@ kit.config = kit.config || {}; } }; - __proto.__exec = function (pluginId, callback, argArr = []) { - - var plugin = this.plugins[pluginId]; - - var exec = function(_callback, argArr){ - if(plugin.skipLoadPromise) { - _callback.apply(this, argArr); - } else { - plugin.promise = plugin.promise.then(function(){ - _callback.apply(this, argArr); - }.bind(this)); - } - }.bind(this); - - exec(callback, argArr); - }; - - __proto.__getDepsPromise = function (pluginList) { - var skipPromise = true; - var promise = new Promise((resolve, reject)=>{ - var i = 0; - var checkModule = function(){ - if(++i === pluginList.length + 1) { - resolve(); - } - }; - checkModule(); - pluginList.forEach(function(pluginId, i, array){ - if(!this.__checkState(pluginId, stateList.registered)) { - checkModule(); - return false; - } - this.install(pluginId, checkModule); - skipPromise = skipPromise && this.plugins[pluginId].skipLoadPromise; - }.bind(this)); - }); - - return !skipPromise?promise:undefined; - }; - /** * @param {(string|string[])} deps * @param {function} callback * @memberOf kit */ - __proto.ready = function(deps, callback = undefined) { + PluginManager.prototype.ready = function(deps, callback = undefined) { + var self = this; if(typeof deps === 'function') { callback = deps; deps = []; } - this.__ready(this.exec, [deps, callback], this); + self.__ready(self.exec, [deps, callback], self); }; - __proto.__ready = function(fn, args = [], context = window) { + 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); @@ -654,77 +834,102 @@ kit.config = kit.config || {}; } }; - __proto.__getPlugin = function (pluginId) { - if(this.plugins.hasOwnProperty(pluginId)) { - return this.plugins[pluginId]; + PluginManager.prototype.require = function (pluginId, callback) { + + var plugin = this.__getPlugin(pluginId); + if(!plugin) { + console.warn('PluginManager.require: plugin ' + pluginId + ' not found!'); + return undefined; } - var _pluginId, alias; - for (_pluginId in this.plugins) { - if(this.plugins.hasOwnProperty(_pluginId) && this.plugins[_pluginId].config.alias.indexOf(pluginId) !== -1) { - return this.plugins[_pluginId]; - } + pluginId = plugin.id; + var module = plugin.module; + + if(typeof callback !== 'function') { + callback = function(){}; } - var pluginIdLowerCase = pluginId.toLowerCase(); - for (_pluginId in this.plugins) { - if(!this.plugins.hasOwnProperty(_pluginId)) { - continue; - } - if(pluginIdLowerCase === _pluginId.toLowerCase()) { - return this.plugins[_pluginId]; - } - for(alias of this.plugins[_pluginId].config.alias) { - if(pluginIdLowerCase === alias.toLowerCase()) { - return this.plugins[_pluginId]; + + 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 undefined; - }; + return module.exports = manager; + }, + onInstall: function(plugin){ + }, + }); + manager.install('pluginManager'); - /** - * @class kitConfig - */ - var defaultConfig = { - version: '1.10', - assetsPath: '', - requiredDependencies: [], - autoloadPluginList: [], - debug: false, - defaultPhoneMask: '+7 (999) 999-99-99', - }; - var script = document.currentScript; - if(script){ - var path = script.src.split('?')[0]; - defaultConfig.assetsPath = path.split('/').slice(0, -2).join('/'); + 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); - var manager = new PluginManager(global); - manager.register('PluginManager', { - alias: 'pm', - type: moduleTypeList.loader, - loader: function(module, exports, require) { - return module.exports = manager; - } - }); - manager.install('PluginManager'); - manager.register('config', { - type: moduleTypeList.loader, - loader: function(module, exports, require, global) { - var config = global.config || {}; - config = Object.assign({}, defaultConfig, config); - window.__pmConfig__ = global.config = config; - } - }); - manager.install('config'); - - window.__PluginManager__ = manager; - global.ready = manager.ready.bind(manager); - global.exec = manager.exec.bind(manager); - global.require = manager.require.bind(manager); - /** - * @var __pmGlobal__ - */ - window.__pmGlobal__ = global; })(kit); diff --git a/assets/core/core.min.js b/assets/core/core.min.js new file mode 100644 index 0000000..8d17ccd --- /dev/null +++ b/assets/core/core.min.js @@ -0,0 +1 @@ +window.kit=window.kit||{},kit.service=kit.service||{},kit.config=kit.config||{},function(global){var defaultConfig={version:"2.0",assetsPath:"",requiredDependencies:[],autoloadPluginList:[],debug:!0},stateList={undefined:0,registered:1,loading:3,loaded:4,installing:5,installed:6},MD_TYPE={ES:"ES",UMD:"UMD",HMD:"HMD"};function Plugin(e,t={}){this.id=e,this.state=stateList.undefined,this.state2=stateList.undefined,this.module={code:"",exports:{}},this.config={autoRequire:!1,loadJsAfterModule:!1,isSetTimestamp:!0,path:"",module:"",type:"ES",handler:void 0,onRegister:function(e){},onLoad:function(e){},onInstall:function(e){},js:[],css:[],alias:[],deps:[],debug:!1},this.pluginManager=void 0,this.promise=new Promise((function(e,t){e()})),this.errors=[],this.register(t)}function isAssetLoaded(e){return e=e.match(/^[^#?]*/)[0],document.querySelector('script[src^="'+e+'"]')||document.querySelector('link[href^="'+e+'"]')||document.querySelector('meta[property="kit:file-load"][content="'+e+'"]')}function getUrlWithTimestamp(e){try{var t=new URL(e);t.searchParams.append("__pm",(new Date).getTime()),e=t.toString()}catch(t){e=(e=String(e).split("?")[0])+"?__pm"+(new Date).getTime()}return e}Plugin.prototype.setPluginManager=function(e){this.pluginManager=e},Plugin.prototype.queuePush=function(e,t=[]){"function"==typeof e&&(this.promise=this.promise.then((function(n){var i=e.apply(this,t);if(i)return i})))},Plugin.prototype.__queue=function(e,t,n=[],i=void 0){var o=this;void 0===i&&(i=o),o.__checkState(e)?t.apply(i,n):o.promise=o.promise.then(function(){return new Promise((function(e,o){t.apply(i,n),e()}))}.bind(o))},Plugin.prototype.__exec=function(e,t,n=[],i=void 0){var o=this;void 0===i&&(i=o),o.__checkState(e)?t.apply(i,n):o.promise=o.promise.then(function(){t.apply(i,n)}.bind(o))},Plugin.prototype.__checkState=function(e,t=void 0){return void 0===t?this.state>=e:this.state>=e&&this.state<=t},Plugin.prototype.__check2State=function(e,t=void 0){return void 0===t?this.state2>=e:this.state2>=e&&this.state2<=t},Plugin.prototype.__getValidConfig=function(e={}){var t=Object.assign({},e);return"function"!=typeof t.onLoad&&(t.onLoad=function(e){}),"function"!=typeof t.onInstall&&(t.onInstall=function(e){}),"function"!=typeof t.onRegister&&(t.onRegister=function(e){}),"string"!=typeof t.path&&(t.path=""),"string"==typeof t.js?t.js=[t.js]:Array.isArray(t.js)||(t.js=[]),"string"==typeof t.css?t.css=[t.css]:Array.isArray(t.css)||(t.css=[]),"string"==typeof t.alias?t.alias=[t.alias]:Array.isArray(t.alias)||(t.alias=[]),t.autoRequire=!!t.hasOwnProperty("autoRequire")&&!!t.autoRequire,t.loadJsAfterModule=!!t.hasOwnProperty("loadJsAfterModule")&&!!t.loadJsAfterModule,t.isSetTimestamp=!t.hasOwnProperty("isSetTimestamp")||!!t.isSetTimestamp,t.type=t.type||"ES","string"==typeof t.deps?t.deps=[t.deps]:Array.isArray(t.deps)||(t.deps=[]),t},Plugin.prototype.__setState=function(e,t=!1){var n=this;(t||n.__checkState(e))&&(n.state=e)},Plugin.prototype.register=function(e={}){var t,n=this,i=n.id;if(this.__checkState(stateList.installed))throw new Error("Plugin "+i+" уже невозможно конфигурировать ("+n.state+"/"+n.state2+")");if("function"==typeof e)t=e,(e=this.config).handler=t,e.type=MD_TYPE.HMD;else{if(this.__checkState(stateList.loaded)||this.__check2State(stateList.loading))throw new Error("Plugin "+i+" уже невозможно конфигурировать ("+n.state+")");if("object"!=typeof e)throw new Error("Plugin.register: plugin "+i+" is not a valid format");e=this.__getValidConfig(e),Object.assign(this.config,e)}if(!this.__checkState(stateList.registered)){n.config.debug&&console.log(`Plugin ${n.id}: onRegister + event.`),this.state=stateList.registered,this.config.onRegister(this);var o=new CustomEvent("onRegister"+this.id+"Plugin",{detail:{plugin:this}});document.dispatchEvent(o)}e.autoRequire},Plugin.prototype.load=function(e){var t=this;"function"!=typeof e&&(e=function(){});var n=t.id;if(!t.__checkState(stateList.registered))return console.warn(`Plugin.load(${n}): is not register!.`),t;if(t.__checkState(stateList.loaded))return e(),t;if(t.__check2State(stateList.loading))return t.__exec(stateList.loaded,e),t;t.state2=stateList.loading;var i,o=t.config;o.css.forEach((function(e,n,i){t.getStylePromise(o.path+e)})),t.pluginManager&&(i=t.pluginManager.__getDepsPromiseCallback(t.config.deps),t.queuePush(i));var r,s=(r=o.path+o.module,"string"==typeof o.module&&""!==o.module&&"ES"===o.type?function(){return t.getESModulePromise(r).then(function(e){e.__esModule=!0,t.module.exports=e}.bind(t))}:"string"==typeof o.module&&""!==o.module&&"UMD"===o.type?isAssetLoaded(r)?void(t.config.debug&&console.warn(`Plugin ${t.id}: Скрипт ${r} уже загружен!`)):function(){return t.httpGet(r).then(function(e){t.module.code=e}.bind(t))}:"HMD"!==o.type||o.hasOwnProperty("handler")&&"function"==typeof o.handler?void 0:function(){return t.getScriptPromise(r)}),a=t.getJsAssetsPromiseCallback(o.js);return o.loadJsAfterModule?(t.queuePush(s),t.queuePush(a)):(t.queuePush(a),t.queuePush(s)),i||s||a||(t.state=stateList.loaded),t.__queue(stateList.loaded,(function(){t.config.debug&&console.log(`Plugin ${t.id}: onLoad + event.`),t.isLoaded()||(t.state=stateList.loaded),o.onLoad.call(t,t);var e=new CustomEvent("onLoad"+t.id+"Plugin",{detail:{plugin:t}});document.dispatchEvent(e)})),t.__exec(stateList.loaded,function(){e()}.bind(t)),t},Plugin.prototype.install=function(callback){var self=this,global=self.pluginManager.global,require=self.pluginManager.require.bind(self.pluginManager);"function"!=typeof callback&&(callback=function(){});var pluginId=self.id;if(!self.__checkState(stateList.registered))return console.warn(`Plugin ${pluginId}: is not register!`),self;if(self.__checkState(stateList.installed))return callback(),self;if(self.__check2State(stateList.installing))return self.__exec(stateList.installed,callback),self;self.__checkState(stateList.loaded)||this.load(),self.state2=stateList.installing;var setGlobals=function(e,t){if(void 0!==t){var n=self.id,i=self.config.alias;e.hasOwnProperty(n)||(e[n]=t),Array.isArray(i)&&i.length&&i.forEach((function(n){e.hasOwnProperty(n)||(e[n]=t)}))}},module=self.module,exports=self.module.exports,installer=function(){var __exports=void 0;"ES"===self.config.type&&"string"==typeof self.config.module&&""!==self.config.module?__exports="object"==typeof exports&&void 0!==exports.default?exports.default:exports:"UMD"===self.config.type&&"string"==typeof self.config.module&&""!==self.config.module?(function(require,exports,module,global){var self=global;eval(module.code)}.bind(global).call(global,require,exports,module,global),__exports="object"==typeof exports&&void 0!==exports.default?exports.default:exports):"HMD"===self.config.type&&"function"==typeof self.config.handler&&(__exports=self.config.handler.bind(global).call(global,require,exports,module,global),void 0===__exports&&exports&&(__exports=exports)),"object"==typeof global&&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}});return document.dispatchEvent(event),!0}.bind(this);return this.__queue(stateList.loaded,installer),this.__exec(stateList.loaded,(function(){callback()})),self},Plugin.prototype.exec=function(e,t=[],n=void 0){var i=this;void 0===n&&(n=i),i.__checkState(stateList.installed)||(i.load(),i.install()),i.__exec(stateList.installed,e,t,n)},Plugin.prototype.getESModulePromise=function(e){var t=this;return new Promise((function(n,i){import(e).then((function(e){n(e)}),(function(e){t.errors.push(e),console.log(`%cPlugin ${t.id}: error import module!`,"color: red;"),i(e)}))}))},Plugin.prototype.httpGet=function(e){var t=this;return new Promise((function(n,i){t.config.debug&&console.log(`Plugin ${t.id}: httpGet ${e}`);var o=new XMLHttpRequest;o.open("GET",e,!0),o.onload=function(){if(200==this.status)n(this.response);else{console.log(`%cPlugin.load(${t.id}): error load file!`,"color: red;");var e=new Error(this.statusText);e.code=this.status,i(e)}},o.onerror=function(){console.log(`%cPlugin.load(${t.id}): error load file!`,"color: red;"),i(new Error("Network Error"))},o.send()}))},Plugin.prototype.getScriptPromise=function(e){var t=this;if(!isAssetLoaded(e))return new Promise((function(n,i){t.config.debug&&console.log(`Plugin ${t.id}: load script ${e}`);var o=document.createElement("script");o.src=e,t.config.isSetTimestamp&&(o.src=getUrlWithTimestamp(e)),o.onload=function(){n(o)},o.onerror=function(){var n=new Error(`Ошибка загрузки скрипта ${e}`);t.errors.push(n),console.log(`%cPlugin.load(${t.id}): error load script!`,"color: red;"),i(n)},document.head.append(o)}));t.config.debug&&console.warn(`Plugin ${t.id}: Скрипт ${e} уже загружен!`)},Plugin.prototype.getStylePromise=function(e){var t=this;return new Promise((function(n,i){if(isAssetLoaded(e))t.config.debug&&console.warn(`Plugin ${t.id}: Стиль ${e} уже загружен`),n();else{var o=document.createElement("link");o.rel="stylesheet",o.type="text/css",o.media="all",o.href=e,t.config.isSetTimestamp&&(o.href=getUrlWithTimestamp(e)),document.head.append(o),n(o)}}))},Plugin.prototype.getAsyncScriptListPromise=function(e){var t=e.map(this.getScriptPromise.bind(this)).filter((e=>void 0!==e));if(t.length)return Promise.all(t)},Plugin.prototype.getJsAssetsPromiseCallback=function(e=[]){var t=this;if(e.length)return function(){var n=new Promise((function(e,t){e()}));return e.forEach((function(e,i,o){n=Array.isArray(e)?n.then((function(){return t.getAsyncScriptListPromise(e)})):n.then((function(){return t.getScriptPromise(t.config.path+e)}))})),n}},Plugin.prototype.__getRealId=function(e){var t,n=this,i=e.toLowerCase();if(n.id.toLowerCase()===i)return n.id;for(t of n.config.alias)if(i===t.toLowerCase())return n.id},Plugin.prototype.__is=function(e){return this.id===this.__getRealId(e)},Plugin.prototype.isLoaded=function(){return this.__checkState(stateList.loaded)},Plugin.prototype.isInstalled=function(){return this.__checkState(stateList.installed)},Plugin.prototype.require=function(){var e=this;return e.isInstalled()||e.config.debug&&console.warn(`Plugin ${e.id}: not instaled!`),e.module.exports};var PluginManager=function(e){this.plugins={},this.global=e};function init(e){var t=new PluginManager(e);e.ready=t.ready.bind(t),e.exec=t.exec.bind(t),e.require=t.require.bind(t),t.register("pluginManager",{alias:"pm",type:MD_TYPE.HMD,handler:function(e,n,i,o){return o.PluginManagerClass=PluginManager,"object"==typeof window&&(window.__PluginManager__=t,window.__pmGlobal__=o),i.exports=t},onInstall:function(e){}}),t.install("pluginManager"),t.register("config",{type:MD_TYPE.HMD,handler:function(e,t,n,i){var o=document.currentScript;if(o)try{var r=new URL(o.src);defaultConfig.assetsPath=r.pathname.split("/").slice(0,-2).join("/")}catch(e){var s=o.src.split("?")[0];defaultConfig.assetsPath=s.split("/").slice(0,-2).join("/")}var a=i.config||{};a=Object.assign({},defaultConfig,a),"object"==typeof window&&(window.__pmConfig__=i.config=a),document.addEventListener("DOMContentLoaded",(function(){console.log("%cDOMContentLoaded","color:#2053ff")}))},onInstall:function(e){"object"==typeof window&&window.hasOwnProperty("__PluginManagerConfigHandler__")&&"function"==typeof __PluginManagerConfigHandler__&&t.registerPlugins(__PluginManagerConfigHandler__())}}),t.install("config")}PluginManager.prototype.registerPlugins=function(e){for(var t in e)e.hasOwnProperty(t)&&this.register(t,e[t]);return this},PluginManager.prototype.register=function(e,t={}){if("string"==typeof e&&""!==e){var n=this.__getPlugin(e);n?n.register(t):((n=new Plugin(e,t)).setPluginManager(this),this.plugins[e]=n)}else console.warn("Invalid pluginId!",e)},PluginManager.prototype.__getPlugin=function(e){var t,n,i=this;for(t in i.plugins)if(i.plugins.hasOwnProperty(t)&&(n=i.plugins[t]).__is(e))return n},PluginManager.prototype.__getDepsPromiseCallback=function(e=[]){var t=this,n=e.map((function(e){var n=t.__getPlugin(e);if(n){if(n.install(),n.isInstalled())return;return n.promise}console.log(`%cPluginManager: plugin ${e} not found!`,"color: red;")})).filter((e=>void 0!==e));if(n.length)return function(){return Promise.all(n)}},PluginManager.prototype.__getRealIdList=function(e=[]){var t=this;return e.map((function(e){var n=t.__getPlugin(e);if(n)return n.id}))},PluginManager.prototype.exec=function(e,t,n=[],i=void 0){if("function"==typeof e&&(i=n,n=t,t=e,e=[]),"string"==typeof e&&(e=[e]),void 0===i&&(i=this),void 0===n&&(n=[]),"function"==typeof t){global.config&&global.config.requiredDependencies&&(e=Array.from(new Set(e.concat(global.config.requiredDependencies))));var o=this.__getDepsPromiseCallback(e);o?o().then((function(){t.apply(i,n)})):t.apply(i,n)}},PluginManager.prototype.exec2=function(e,t){var n=this,i=this,o=n.__getDepsPromiseCallback(e),r=function(){var t=[];return e.forEach(function(e){n.__getPlugin(e)?t.push(n.require(e)):t.push(void 0)}.bind(n)),t}.bind(n);o?o().then((function(){t.apply(i,r())})):t.apply(i,r())},PluginManager.prototype.ready=function(e,t=void 0){var n=this;"function"==typeof e&&(t=e,e=[]),n.__ready(n.exec,[e,t],n)},PluginManager.prototype.__ready=function(e,t=[],n=window){n=n||this,/complete|interactive|loaded/.test(document.readyState)?e.apply(n,t):document.addEventListener("DOMContentLoaded",function(){e.apply(n,t)}.bind(this))},PluginManager.prototype.require=function(e,t){var n=this.__getPlugin(e);if(n){e=n.id;var i=n.module;return"function"!=typeof t&&(t=function(){}),n.install(t),i.exports}console.warn("PluginManager.require: plugin "+e+" not found!")},PluginManager.prototype.install=function(e,t){var n=this.__getPlugin(e);if(n){e=n.id;n.module;n.install(t)}else console.warn("PluginManager.install: plugin "+e+" not found!")},init(global)}(kit); \ No newline at end of file diff --git a/assets/core/core.plugins.config.js b/assets/core/core.plugins.config.js new file mode 100644 index 0000000..ef36f34 --- /dev/null +++ b/assets/core/core.plugins.config.js @@ -0,0 +1,425 @@ +var __PluginManagerConfigHandler__ = function() { + var root = __pmConfig__.assetsPath; + return { + menu: { + path: root + '/menu', + module: '/menu.js', + css: [ + '/menu.css' + ], + type: 'HMD', + deps: ['lib', 'align', 'dataStructures', 'animations', 'userAction', 'Collection', 'support', 'ActionCollection', 'Action', 'Viewer'] + }, + lib: { + path: root + '/lib', + module: '/lib.js', + type: 'HMD', + }, + align: { + path: root + '/align', + module: '/align.js', + type: 'HMD', + deps: ['support'] + }, + flexKit: { + path: root + '/flex-kit', + css: '/flex-kit.css' + }, + support: { + path: root + '/support', + module: '/support.js', + type: 'HMD', + }, + jqueryIniter: { + type: 'HMD', + handler: function(require, exports, module, global){ + var J = function (){ + var c = []; + J.queue.push(c); + c.push(['$', arguments]); + var J2 = function(){} + J2.ready = function (){ + c.push(['ready', arguments]); + } + return J2 + } + J.queue = []; + + function JQueryIniter(){} + JQueryIniter.prototype.J = J; + JQueryIniter.prototype.hasJQuery = function(){ + return window.hasOwnProperty('jQuery') && window.jQuery.hasOwnProperty('fn'); + }; + JQueryIniter.prototype.hasJQueryIniter = function(){ + return window.hasOwnProperty('jQuery') && Object.is(window.jQuery, J); + }; + JQueryIniter.prototype.onRegister = function(plugin){ + if(!this.hasJQuery()){ + (function(w){ + w.$ = w.jQuery = J; + plugin.module.initer = J; + })(window); + } + }; + JQueryIniter.prototype.onInstall = function(plugin){ + var self = this; + (function(w){ + var q = plugin.module.initer.queue; + if(self.hasJQueryIniter()){ + w.$ = w.jQuery = plugin.module.exports; + for (var ch of q){ + var root = w; + for (var c of ch){ + root = root[c[0]].apply(c[0], c[1]); + } + } + } + })(window); + }; + + module.exports = new JQueryIniter(); + + }, + }, + jquery: { + path: root + '/jquery', + module: '/jquery.min.js', + type: 'UMD', + alias: ['$', 'jQuery'], + onRegister: function (plugin) { + console.log('reg jq'); + var initer = kit.require('jqueryIniter'); + initer.onRegister(plugin); + }, + onInstall: function(plugin){ + var initer = kit.require('jqueryIniter'); + initer.onInstall(plugin); + }, + }, + popper: { + path: root + '/popper', + alias: 'popper.js', + module: '/popper.js', + type: 'HMD', + css: '/popper.css', + }, + bsCore: { + path: root + '/bsCore', + module: '/bsCore.js', + type: 'HMD', + css: [ + '/bsCore.css' + ] + }, + bsToast: { + path: root + '/bsToast', + module: '/bsToast.js', + type: 'HMD', + deps: ['bsCore'], + }, + bsToastService: { + path: root + '/bsToastService', + module: '/bsToastService.js', + type: 'HMD', + css: [ + '/bsToastService.css' + ], + deps: ['bsToast', 'support', 'Collection'], + }, + Tooltip: { + path: root + '/tooltip', + module: '/tooltip.js', + type: 'HMD', + css: '/tooltip.css', + onInstall: function (plugin) { + var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); + var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { + return __pmGlobal__.Tooltip.getOrCreateInstance(tooltipTriggerEl, {sanitize: false}); + }); + }, + deps: ['popper', 'bsCore'], + }, + Tooltip2: { + path: root + '/tooltip2', + module: '/tooltip2.js', + type: 'HMD', + css: '/tooltip2.css', + onInstall: function (plugin) { + console.log('tt2 install'); + document.addEventListener('mouseover', function (event) { + // console.log(event); + // console.log(event.target); + if (!(event.target && event.target.dataset.kitTooltip2 === 'autoload')) { + return; + } + // console.log(1); + if (kit.support.getNodeData(event.target, 'tooltip2')) { + return; + } + // console.log(2); + var tooltip = new __pmGlobal__.Tooltip2(event.target); + tooltip.run(); + tooltip.show(); + }); + // var elements = [].slice.call(document.querySelectorAll('[data-kit-tooltip2="autoload"]')); + // elements.map(function (element) { + // var tooltip = new __pmGlobal__.Tooltip2(element); + // tooltip.run(); + // console.log(tooltip); + // }); + }, + deps: ['Viewer', 'support', 'ActionCollection', 'Action', 'userAction', 'align', 'Collection', 'animations'], + }, + Popover: { + path: root + '/popover', + module: '/popover.js', + type: 'HMD', + css: '/popover.css', + onInstall: function () { + var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); + var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { + return new __pmGlobal__.Popover(popoverTriggerEl); + }); + }, + deps: ['popper', 'bsCore', 'Tooltip'], + }, + mask: { + path: root + '/mask', + module: '/mask.js', + type: 'HMD', + deps: ['jQuery'], + }, + toolkit: { + path: root + '/toolkit', + module: '/toolkit.js', + type: 'HMD', + css: ['/toolkit.css'], + deps: ['jQuery', 'mask', 'support'], + }, + Modal: { + path: root + '/modal', + module: '/modal.js', + type: 'HMD', + css: [ + '/modal.css', + ], + deps: ['bsCore'], + onRegister: function (plugin) { + plugin.onLoadConditionHandler = function (event) { + if (event.target && event.target.dataset && event.target.dataset.bsTarget && event.target.dataset.bsToggle === 'modal') { + kit.exec(plugin.id, function () { + var newEvent = new Event("click"); + event.target.dispatchEvent(newEvent); + }); + } + }; + window.addEventListener('click', plugin.onLoadConditionHandler, false); + }, + onInstall: function (plugin) { + if (plugin.onLoadConditionHandler) { + window.removeEventListener('click', plugin.onLoadConditionHandler, false); + } + }, + }, + collapse: { + path: root + '/collapse', + module: '/collapse.js', + type: 'HMD', + css: [ + '/collapse.css', + ], + deps: ['bsCore'], + }, + datepicker: { + path: root + '/datepicker', + module: '/js/datepicker.js', + type: 'HMD', + css: [ + '/css/datepicker.css', + ], + deps: ['jQuery'], + }, + cookie: { + path: root + '/cookie', + module: '/cookie.js', + type: 'HMD', + }, + animations: { + path: root + '/animations', + css: '/animations.css', + module: '/animations.js', + type: 'HMD', + }, + Collection: { + path: root + '/collection', + module: '/collection.js', + type: 'HMD', + deps: ['support'], + }, + dataStructures: { + path: root + '/dataStructures', + module: '/dataStructures.js', + type: 'HMD', + }, + userAction: { + path: root + '/userAction', + module: '/userAction.js', + type: 'HMD', + deps: ['support', 'ActionCollection', 'Action', 'Viewer'], + }, + Viewer: { + path: root + '/Viewer', + module: '/Viewer.js', + type: 'HMD', + deps: ['Collection', 'support', 'ActionCollection', 'Action'], + }, + ActionCollection: { + path: root + '/ActionCollection', + module: '/ActionCollection.js', + type: 'HMD', + deps: ['Collection', 'support', 'Action'], + }, + Action: { + path: root + '/Action', + module: '/Action.js', + type: 'HMD', + deps: ['support'], + }, + date: { + path: root + '/date', + module: '/date.js', + type: 'HMD', + deps: [], + }, + testing: { + path: root + '/testing', + module: '/testing.js', + type: 'module', + deps: ['log'], + }, + log: { + path: root + '/log', + module: '/log.js', + css: '/log.css', + type: 'HMD', + deps: ['support', 'Collection', 'lib'] + }, + fancybox: { + path: root + '/fancybox', + css: '/fancybox.css', + js: '/fancybox.umd.js', + }, + lightGallery: { + path: root + '/lightGallery', + css: '/lightGallery.css', + js: '/lightGallery.js', + deps: ['jQuery'], + }, + owlCarousel: { + path: root + '/owlCarousel', + css: '/owlCarousel.css', + js: '/owlCarousel.js', + deps: ['jQuery'], + }, + Chosen: { + path: root + '/chosen', + css: '/chosen.css', + js: '/chosen.jquery.js', + deps: ['jQuery'], + }, + makeCSSAnimations: { + path: root + '/makeCSSAnimations', + js: '/makeCSSAnimations.js', + deps: ['jQuery', 'support'], + }, + mCustomScrollbar: { + path: root + '/mCustomScrollbar', + alias: 'malihu-custom-scrollbar-plugin', + js: '/mCustomScrollbar.js', + css: '/jquery.mCustomScrollbar.css', + deps: ['jQuery', 'jqueryMousewheel'], + onInstall: function (plugin) { + plugin.module.exports(kit.require('jQuery')); + } + }, + jqueryMousewheel: { + path: root + '/jqueryMousewheel', + alias: 'jquery-mousewheel', + js: '/jquery.mousewheel.js', + deps: ['jQuery'], + onInstall: function (plugin) { + plugin.module.exports(kit.require('jQuery')); + } + }, + jqueryLazy: { + path: root + '/jquery-lazy', + alias: 'jquery-lazy', + js: [ + '/jquery.lazy.min.js', + '/jquery.lazy.plugins.min.js', + ], + deps: ['jQuery'], + }, + slickCarousel: { + path: root + '/slickCarousel', + alias: ['slick', 'slick-carousel'], + js: '/slick.min.js', + css: [ + '/slick.css', + '/slick-theme.css', + ], + deps: ['jQuery'], + }, + mustache: { + path: root + '/mustache', + alias: ['mustache.js'], + js: '/mustache.js', + deps: [], + }, + bxSlider: { + path: root + '/bxSlider', + module: '/jquery.bxslider.min.js', + css: [ + '/jquery.bxslider.min.css', + ], + type: 'import', + deps: ['jQuery'], + }, + selectric: { + path: root + '/selectric', + module: '/jquery.selectric.min.js', + css: [ + '/selectric.css', + ], + type: 'import', + alias: ['jquerySelectric'], + deps: ['jQuery'], + }, + jBox: { + path: root + '/jBox', + module: '/jBox.min.js', + css: [ + '/jBox.min.css', + ], + type: 'import', + deps: ['jQuery'], + }, + intlTelInput: { + path: root + '/intl-tel-input', + module: '/js/intlTelInput.min.js', + css: [ + '/css/intlTelInput.min.css', + ], + type: 'import', + alias: ['intl-tel-input'], + }, + autoComplete: { + path: root + '/autoComplete', + module: '/autoComplete.min.js', + css: [ + '/css/autoComplete.css', + ], + type: 'HMD', + }, + }; +}; \ No newline at end of file diff --git a/assets/core/core.plugins.config.min.js b/assets/core/core.plugins.config.min.js new file mode 100644 index 0000000..2b98c84 --- /dev/null +++ b/assets/core/core.plugins.config.min.js @@ -0,0 +1 @@ +var __PluginManagerConfigHandler__=function(){var e=__pmConfig__.assetsPath;return{menu:{path:e+"/menu",module:"/menu.js",css:["/menu.css"],type:"HMD",deps:["lib","align","dataStructures","animations","userAction","Collection","support","ActionCollection","Action","Viewer"]},lib:{path:e+"/lib",module:"/lib.js",type:"HMD"},align:{path:e+"/align",module:"/align.js",type:"HMD",deps:["support"]},flexKit:{path:e+"/flex-kit",css:"/flex-kit.css"},support:{path:e+"/support",module:"/support.js",type:"HMD"},jqueryIniter:{type:"HMD",handler:function(e,t,s,o){var l=function(){var e=[];l.queue.push(e),e.push(["$",arguments]);var t=function(){};return t.ready=function(){e.push(["ready",arguments])},t};function i(){}l.queue=[],i.prototype.J=l,i.prototype.hasJQuery=function(){return window.hasOwnProperty("jQuery")&&window.jQuery.hasOwnProperty("fn")},i.prototype.hasJQueryIniter=function(){return window.hasOwnProperty("jQuery")&&Object.is(window.jQuery,l)},i.prototype.onRegister=function(e){var t;this.hasJQuery()||((t=window).$=t.jQuery=l,e.module.initer=l)},i.prototype.onInstall=function(e){var t=this;!function(s){var o=e.module.initer.queue;if(t.hasJQueryIniter())for(var l of(s.$=s.jQuery=e.module.exports,o)){var i=s;for(var a of l)i=i[a[0]].apply(a[0],a[1])}}(window)},s.exports=new i}},jquery:{path:e+"/jquery",module:"/jquery.min.js",type:"UMD",alias:["$","jQuery"],onRegister:function(e){console.log("reg jq"),kit.require("jqueryIniter").onRegister(e)},onInstall:function(e){kit.require("jqueryIniter").onInstall(e)}},popper:{path:e+"/popper",alias:"popper.js",module:"/popper.js",type:"HMD",css:"/popper.css"},bsCore:{path:e+"/bsCore",module:"/bsCore.js",type:"HMD",css:["/bsCore.css"]},bsToast:{path:e+"/bsToast",module:"/bsToast.js",type:"HMD",deps:["bsCore"]},bsToastService:{path:e+"/bsToastService",module:"/bsToastService.js",type:"HMD",css:["/bsToastService.css"],deps:["bsToast","support","Collection"]},Tooltip:{path:e+"/tooltip",module:"/tooltip.js",type:"HMD",css:"/tooltip.css",onInstall:function(e){[].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')).map((function(e){return __pmGlobal__.Tooltip.getOrCreateInstance(e,{sanitize:!1})}))},deps:["popper","bsCore"]},Tooltip2:{path:e+"/tooltip2",module:"/tooltip2.js",type:"HMD",css:"/tooltip2.css",onInstall:function(e){console.log("tt2 install"),document.addEventListener("mouseover",(function(e){if(e.target&&"autoload"===e.target.dataset.kitTooltip2&&!kit.support.getNodeData(e.target,"tooltip2")){var t=new __pmGlobal__.Tooltip2(e.target);t.run(),t.show()}}))},deps:["Viewer","support","ActionCollection","Action","userAction","align","Collection","animations"]},Popover:{path:e+"/popover",module:"/popover.js",type:"HMD",css:"/popover.css",onInstall:function(){[].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')).map((function(e){return new __pmGlobal__.Popover(e)}))},deps:["popper","bsCore","Tooltip"]},mask:{path:e+"/mask",module:"/mask.js",type:"HMD",deps:["jQuery"]},toolkit:{path:e+"/toolkit",module:"/toolkit.js",type:"HMD",css:["/toolkit.css"],deps:["jQuery","mask","support"]},Modal:{path:e+"/modal",module:"/modal.js",type:"HMD",css:["/modal.css"],deps:["bsCore"],onRegister:function(e){e.onLoadConditionHandler=function(t){t.target&&t.target.dataset&&t.target.dataset.bsTarget&&"modal"===t.target.dataset.bsToggle&&kit.exec(e.id,(function(){var e=new Event("click");t.target.dispatchEvent(e)}))},window.addEventListener("click",e.onLoadConditionHandler,!1)},onInstall:function(e){e.onLoadConditionHandler&&window.removeEventListener("click",e.onLoadConditionHandler,!1)}},collapse:{path:e+"/collapse",module:"/collapse.js",type:"HMD",css:["/collapse.css"],deps:["bsCore"]},datepicker:{path:e+"/datepicker",module:"/js/datepicker.js",type:"HMD",css:["/css/datepicker.css"],deps:["jQuery"]},cookie:{path:e+"/cookie",module:"/cookie.js",type:"HMD"},animations:{path:e+"/animations",css:"/animations.css",module:"/animations.js",type:"HMD"},Collection:{path:e+"/collection",module:"/collection.js",type:"HMD",deps:["support"]},dataStructures:{path:e+"/dataStructures",module:"/dataStructures.js",type:"HMD"},userAction:{path:e+"/userAction",module:"/userAction.js",type:"HMD",deps:["support","ActionCollection","Action","Viewer"]},Viewer:{path:e+"/Viewer",module:"/Viewer.js",type:"HMD",deps:["Collection","support","ActionCollection","Action"]},ActionCollection:{path:e+"/ActionCollection",module:"/ActionCollection.js",type:"HMD",deps:["Collection","support","Action"]},Action:{path:e+"/Action",module:"/Action.js",type:"HMD",deps:["support"]},date:{path:e+"/date",module:"/date.js",type:"HMD",deps:[]},testing:{path:e+"/testing",module:"/testing.js",type:"module",deps:["log"]},log:{path:e+"/log",module:"/log.js",css:"/log.css",type:"HMD",deps:["support","Collection","lib"]},fancybox:{path:e+"/fancybox",css:"/fancybox.css",js:"/fancybox.umd.js"},lightGallery:{path:e+"/lightGallery",css:"/lightGallery.css",js:"/lightGallery.js",deps:["jQuery"]},owlCarousel:{path:e+"/owlCarousel",css:"/owlCarousel.css",js:"/owlCarousel.js",deps:["jQuery"]},Chosen:{path:e+"/chosen",css:"/chosen.css",js:"/chosen.jquery.js",deps:["jQuery"]},makeCSSAnimations:{path:e+"/makeCSSAnimations",js:"/makeCSSAnimations.js",deps:["jQuery","support"]},mCustomScrollbar:{path:e+"/mCustomScrollbar",alias:"malihu-custom-scrollbar-plugin",js:"/mCustomScrollbar.js",css:"/jquery.mCustomScrollbar.css",deps:["jQuery","jqueryMousewheel"],onInstall:function(e){e.module.exports(kit.require("jQuery"))}},jqueryMousewheel:{path:e+"/jqueryMousewheel",alias:"jquery-mousewheel",js:"/jquery.mousewheel.js",deps:["jQuery"],onInstall:function(e){e.module.exports(kit.require("jQuery"))}},jqueryLazy:{path:e+"/jquery-lazy",alias:"jquery-lazy",js:["/jquery.lazy.min.js","/jquery.lazy.plugins.min.js"],deps:["jQuery"]},slickCarousel:{path:e+"/slickCarousel",alias:["slick","slick-carousel"],js:"/slick.min.js",css:["/slick.css","/slick-theme.css"],deps:["jQuery"]},mustache:{path:e+"/mustache",alias:["mustache.js"],js:"/mustache.js",deps:[]},bxSlider:{path:e+"/bxSlider",module:"/jquery.bxslider.min.js",css:["/jquery.bxslider.min.css"],type:"import",deps:["jQuery"]},selectric:{path:e+"/selectric",module:"/jquery.selectric.min.js",css:["/selectric.css"],type:"import",alias:["jquerySelectric"],deps:["jQuery"]},jBox:{path:e+"/jBox",module:"/jBox.min.js",css:["/jBox.min.css"],type:"import",deps:["jQuery"]},intlTelInput:{path:e+"/intl-tel-input",module:"/js/intlTelInput.min.js",css:["/css/intlTelInput.min.css"],type:"import",alias:["intl-tel-input"]},autoComplete:{path:e+"/autoComplete",module:"/autoComplete.min.js",css:["/css/autoComplete.css"],type:"HMD"}}}; \ No newline at end of file diff --git a/assets/core/v1/core.js b/assets/core/v1/core.js new file mode 100644 index 0000000..f3f4546 --- /dev/null +++ b/assets/core/v1/core.js @@ -0,0 +1,730 @@ + +var kit; +kit = window.kit = window.kit || {}; +kit.service = kit.service || {}; +kit.config = kit.config || {}; +(function(global){ + var stateList = { + undefined: 0, + registered: 1, + loaded: 3, + installed: 4, + }; + var moduleTypeList = { + loader: 'loader', + import: 'import', + }; + + /** + * @class PluginManager + * @param global + * @param plugins + * @memberOf kit + */ + var PluginManager = function(global, plugins = {}){ + this.plugins = {}; + this.global = global; + this.registerPlugins(plugins); + }; + + /** + * + * @type {kit.PluginManager|PluginManager} + * @private + */ + var __proto = PluginManager.prototype; + + __proto.__checkState = function(pluginId, state){ + return this.plugins.hasOwnProperty(pluginId) && this.plugins[pluginId].state >= state; + }; + + /** + * @param plugins + * @return {PluginManager} + */ + __proto.registerPlugins = function (plugins) { + if(Array.isArray(plugins)) { + plugins = Object.assign({}, plugins); + } + for (var pluginId in plugins) { + if(plugins.hasOwnProperty(pluginId)) { + this.register(pluginId, plugins[pluginId]); + } + } + return this; + }; + + /** + * @return {boolean} + */ + __proto.register = function (pluginId, config = {}) { + //console.warn('PluginManager.register: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); + var defaultPlugin = { + module: { + exports: {}, + }, + config: { + }, + promise: new Promise(function(resolve, reject){resolve()}), + id: pluginId, + state: stateList.undefined, + stateInit: { + loading: false, + installing: false, + }, + }; + var plugin = this.__getPlugin(pluginId); + if(plugin) { + pluginId = plugin.id; + } else { + plugin = this.plugins[pluginId] = defaultPlugin; + } + + /** + * @todo !!! + */ + if( + (this.__checkState(pluginId, stateList.installed) && typeof config.loader === 'function') || + ( + (plugin.stateInit.loading || this.__checkState(pluginId, stateList.loaded)) && typeof config === 'object' + ) + ) { + console.warn('PluginManager.register: plugin ' + pluginId + ' уже невозможно конфигурировать ('+plugin.state+')'); + return false; + } + + var loader; + if(typeof config === 'function') { + loader = config; + config = plugin.config; + config.loader = loader; + config.type = 'loader'; + if(this.__checkState(pluginId, stateList.registered)) { + if(this.__checkState(pluginId, stateList.loaded)){ + plugin.stateInit.installing = false; + } + //console.log(`PluginManager.register(${pluginId}): (${plugin.state} > ${stateList.registered})`); + plugin.state = stateList.registered; + if(plugin.config.autoRequire) { + this.require(pluginId); + } + } + } + + if(typeof config === 'object') { + if(typeof config.onLoad !== 'function') { + config.onLoad = function(){}; + } + if(typeof config.onInstall !== 'function') { + config.onInstall = function(){}; + } + if(typeof config.onRegister !== 'function') { + config.onRegister = function(){}; + } + if(typeof config.path !== 'string') { + config.path = ''; + } + if(!config.hasOwnProperty('modulePath')) { + config.modulePath = config.path; + } else if(typeof config.modulePath !== 'string') { + config.modulePath = 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.loadJsAfterModule = !!config.loadJsAfterModule; + config.isSetTimestamp = config.hasOwnProperty('isSetTimestamp')?!!config.isSetTimestamp:true; + config.type = config.type || 'import'; //loader + + if(typeof config.deps === 'string') { + config.deps = [config.deps]; + } else if(!Array.isArray(config.deps)) { + config.deps = []; + } + + } else { + console.warn('PluginManager.register: plugin ' + pluginId + ' is not a valid format'); + return false; + } + + Object.assign(plugin.config, config); + + if(!this.__checkState(pluginId, stateList.registered)) { + plugin.state = stateList.registered; + plugin.config.onRegister(plugin); + var event = new CustomEvent("onRegister" + plugin.id + "Plugin", { + "detail": {plugin: plugin} + }); + document.dispatchEvent(event); + } + + return true; + }; + + /** + * @param pluginId + * @param callback + * @return {PluginManager} + */ + __proto.load = function (pluginId, callback) { + var self = this; + //console.log('PluginManager.load: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); + if(typeof callback !== 'function') { + callback = function(){}; + } + + var plugin = this.__getPlugin(pluginId); + if(plugin) { + pluginId = plugin.id; + } + + if(!this.__checkState(pluginId, stateList.registered)) { + console.warn('kit.load: plugin ' + pluginId + ' is not register'); + return this; + } + if(this.__checkState(pluginId, stateList.loaded)) { + //console.warn('PluginManager.load: plugin ' + pluginId + ' уже загружен'); + callback(); + return this; + } + + + if(plugin.stateInit.loading) { + //console.log('PluginManager.install: plugin ' + pluginId + ' уже грузится'); + this.__exec(pluginId, callback); + return this; + } + plugin.stateInit.loading = true; + + var configModule = plugin.config; + + var stackPush = function (callbackPromise, argArr = []){ + if(typeof plugin.promise === 'undefined') { + plugin.promise = callbackPromise.apply(this, argArr); + } else { + plugin.promise = plugin.promise.then(function(m){ + return callbackPromise.apply(this, argArr); + }); + } + }.bind(this); + + var getModulePromise = (function () { + + function getFileLoadNode(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 loadScript(src, resolveCallback, rejectCallback) { + var originSrc = src; + src = String(src).split('?')[0]; + if(typeof resolveCallback !== 'function'){ + resolveCallback = function(){}; + } + if(typeof rejectCallback !== 'function'){ + rejectCallback = function(res){ + console.warn(res.message, originSrc); + }; + } + return new Promise(function(resolve, reject) { + var loadNode = getFileLoadNode(src); + if (loadNode) { + global.config.debug && console.warn(`Скрипт ${src} уже загружен`); + // self.__ready(resolve, [loadNode]); + resolve(); + } else { + var script = document.createElement('script'); + + try { + var url = new URL(originSrc); + if(plugin.config.isSetTimestamp){ + url.searchParams.append('__pm', (new Date()).getTime()); + } + script.src = url.toString(); + } catch (e) { + script.src = '' + src + '?__pm' + ((new Date()).getTime()); + } + + script.onload = function() {resolve(script);}; + script.onerror = function() {reject(new Error(`Ошибка загрузки скрипта ${src}`));}; + document.head.append(script); + } + }).then(resolveCallback, rejectCallback); + } + function syncLoadScriptList(list) { + + return new Promise(function(resolve, reject) { + var i = 0; + var status = true; + var count = list.length; + var checkResolve = function(src, cond){ + if(!cond) { + console.error(`Ошибка загрузки скрипта ${src}`) + } + status = status && cond; + i++; + if(i === count) { + resolve(); + } + }; + var syncPromise = new Promise(function(_resolve, _reject){_resolve();}); + list.forEach(function(item, i, arr){ + syncPromise.then(function(){ + var src = configModule.path + item; + var loadNode = getFileLoadNode(src); + if(loadNode){ + self.__ready(resolve, [src, true]); + // resolve(src, true); + } else { + var script = document.createElement('script'); + script.src = '' + src + '?__pm' + (new Date()).getTime(); + script.onload = () => checkResolve(src, true); + script.onerror = () => checkResolve(src, false); + document.head.append(script); + } + }); + }); + }) + } + function loadStyle(src) { + return new Promise(function(resolve, reject) { + var loadNode = getFileLoadNode(src); + if(loadNode) { + global.config.debug && console.warn(`Стиль ${src} уже загружен`); + // self.__ready(resolve, [src]); + resolve(); + } else { + var link = document.createElement('link'); + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = src + '?__pm' + (new Date()).getTime(); + link.media = 'all'; + document.head.append(link); + resolve(link); + } + }); + } + + var getImportPromise = function (){ + if(configModule.module && configModule.type === 'import') { + return import(configModule.modulePath + configModule.module).then(function(m) { + m.__esModule = true; + plugin.module.exports = m; + }.bind(this), function(r){ + console.error(r); + }); + } else if(configModule.module && configModule.type === 'loader' && !(configModule.hasOwnProperty('loader') && typeof configModule.loader === 'function')) { + return loadScript(configModule.modulePath + configModule.module).then(function() { + + }.bind(this)); + } + return new Promise(function(resolve, reject){resolve();}); + }.bind(this); + var getResPromise = function(){ + var p = new Promise(function(resolve, reject){resolve();}); + configModule.js.forEach(function(item, i, array){ + if(Array.isArray(item)) { + p = p.then(function () { + return syncLoadScriptList(item); + }); + } else { + p = p.then(function () { + return loadScript(configModule.path + item); + }); + } + //loadScript(configModule.path + item); + }); + return p; + }.bind(this); + var setSkipLoadPromise = function (depsPromise) { + + var jsPromiseExists = true, importPromiseExists = true; + if(configModule.js.length === 0) { + jsPromiseExists = false; + } + if((!configModule.module && configModule.type === 'import') || (configModule.type === 'loader' && typeof configModule.loader === 'function')) { + importPromiseExists = false; + } + plugin.skipLoadPromise = !importPromiseExists && !jsPromiseExists && !depsPromise; + + return plugin.skipLoadPromise; + }.bind(this); + + configModule.css.forEach(function(item, i, array){ + loadStyle(configModule.path + item); + }); + + var depsPromise = this.__getDepsPromise(this.depsCorrection(configModule.deps)); + setSkipLoadPromise(depsPromise); + + if(depsPromise) { + stackPush(function () { + return depsPromise; + }); + } + + if(configModule.loadJsAfterModule) { + stackPush(getImportPromise); + stackPush(getResPromise); + } else { + stackPush(getResPromise); + stackPush(getImportPromise); + } + + this.__exec(pluginId, function(){ + plugin.state = stateList.loaded; + plugin.skipLoadPromise = true; + configModule.onLoad.call(plugin.module.exports); + var event = new CustomEvent("onLoad" + plugin.id + "Plugin", { + "detail": {plugin: plugin} + }); + document.dispatchEvent(event); + callback(); + }.bind(this)); + + return plugin.promise; + + }).bind(this); + + getModulePromise(); + + return this; + }; + + /** + * @param pluginId + * @param callback + * @return {PluginManager} + */ + __proto.install = function(pluginId, callback){ + //console.warn('PluginManager.install: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); + if(typeof callback !== 'function') { + callback = function(){}; + } + + var plugin = this.__getPlugin(pluginId); + if(plugin) { + pluginId = plugin.id; + } + var module = plugin.module; + + if(!this.__checkState(pluginId, stateList.registered)) { + console.warn('PluginManager.install: plugin ' + pluginId + ' is not register'); + return this; + } + if(this.__checkState(pluginId, stateList.installed)) { + callback(); + return this; + } + + if(plugin.stateInit.installing) { + //console.warn(`PluginManager.install(${pluginId}): уже устанавливается (${plugin.state}).`); + this.__exec(pluginId, callback); + return this; + } + plugin.stateInit.installing = true; + + this.load(pluginId); + + var installer = function(){ + var setGlobalExtension = function (key, aliasList, data) { + if(data === undefined) { + return; + } + if(!this.global.hasOwnProperty(key)) { + this.global[key] = data; + } + if(Array.isArray(aliasList) && aliasList.length) { + aliasList.forEach(function (alias) { + setGlobalExtension(alias, [], data) + }.bind(this)) + } + }.bind(this); + + /** + * @todo !!! + */ + var returnData; + if(plugin.config.type === moduleTypeList.loader && typeof plugin.config.loader === 'function') { + // var returnData = plugin.config.loader.bind(module.exports).call(module.exports, module, module.exports, this.require.bind(this), global); + returnData = plugin.config.loader.bind(this.global).call(this.global, module, module.exports, this.require.bind(this), this.global); + if(returnData === undefined && module.exports){ + returnData = module.exports; + } + setGlobalExtension(pluginId, plugin.config.alias, returnData); + } else if(plugin.config.type === moduleTypeList.import && typeof plugin.config.module === 'string') { + returnData = (typeof module.exports === 'object' && module.exports.default !== undefined)?module.exports.default:module.exports; + setGlobalExtension(pluginId, plugin.config.alias, returnData); + } + + console.log(`%cPluginManager.install(${pluginId}): installed (${plugin.state} > ${stateList.installed}).`, "color: green;"); + plugin.state = stateList.installed; + + + return true; + }.bind(this); + + this.__exec(pluginId, function(){ + if(!this.__checkState(pluginId, stateList.installed)) { + if(installer()){ + plugin.config.onInstall.call(module.exports, plugin); + var event = new CustomEvent("onInstall" + plugin.id + "Plugin", { + "detail": {plugin: plugin} + }); + document.dispatchEvent(event); + } + } + callback(); + }.bind(this)); + + return this; + }; + + /** + * @name kitPluginManagerRequire + * @param {string} pluginId + * @param {callback} callback + * @return {boolean} + * @memberOf {kit} + */ + __proto.require = function (pluginId, callback) { + + var plugin = this.__getPlugin(pluginId); + if(!plugin) { + console.warn('PluginManager.require: plugin ' + pluginId + ' not found ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')'); + return undefined; + } + pluginId = plugin.id; + var module = plugin.module; + + if(!this.__checkState(pluginId, stateList.registered)) { + console.warn('PluginManager.require: plugin ' + pluginId + ' is not register'); + return undefined; + } + if(typeof callback !== 'function') { + callback = function(){}; + } + + this.install(pluginId, callback); + + return module.exports; + }; + + + + __proto.depsCorrection = function(deps){ + if(!Array.isArray(deps) ) { + deps = [deps]; + } + var correct = []; + deps.forEach(function(pluginId, i, arr) { + var realPlugin = this.__getPlugin(pluginId); + if(realPlugin === undefined) { + console.warn(`Plugin "${pluginId}" not registered!`); + return false; + } + correct.push(realPlugin.id); + }.bind(this)); + return correct; + }; + + /** + * @memberOf kit + */ + __proto.exec = function (deps, callback, argArr = [], context = undefined) { + + if(typeof deps === 'function') { + context = argArr; + argArr = callback; + callback = deps; + deps = []; + } + if(context === undefined) { + context = this; + } + + deps = this.depsCorrection(deps); + + if(typeof argArr === 'undefined') { + argArr = []; + } + + deps = Array.from(new Set(deps.concat(global.config.requiredDependencies))); + + if(typeof callback !== 'function') { + return undefined; + } + var depsPromise = this.__getDepsPromise(deps); + + var getArgArr = function () { + if(argArr.length === 0) { + deps.forEach(function (pluginId) { + argArr.push(this.require(pluginId)); + }.bind(this)); + return argArr; + } + return argArr; + }.bind(this); + + if(depsPromise) { + depsPromise.then(function(){ + callback.apply(context, getArgArr()); + }); + } else { + callback.apply(context, getArgArr()) + } + }; + + __proto.__exec = function (pluginId, callback, argArr = []) { + + var plugin = this.plugins[pluginId]; + + var exec = function(_callback, argArr){ + if(plugin.skipLoadPromise) { + _callback.apply(this, argArr); + } else { + plugin.promise = plugin.promise.then(function(){ + _callback.apply(this, argArr); + }.bind(this)); + } + }.bind(this); + + exec(callback, argArr); + }; + + __proto.__getDepsPromise = function (pluginList) { + var skipPromise = true; + var promise = new Promise((resolve, reject)=>{ + var i = 0; + var checkModule = function(){ + if(++i === pluginList.length + 1) { + resolve(); + } + }; + checkModule(); + pluginList.forEach(function(pluginId, i, array){ + if(!this.__checkState(pluginId, stateList.registered)) { + checkModule(); + return false; + } + this.install(pluginId, checkModule); + skipPromise = skipPromise && this.plugins[pluginId].skipLoadPromise; + }.bind(this)); + }); + + return !skipPromise?promise:undefined; + }; + + /** + * @param {(string|string[])} deps + * @param {function} callback + * @memberOf kit + */ + __proto.ready = function(deps, callback = undefined) { + if(typeof deps === 'function') { + callback = deps; + deps = []; + } + this.__ready(this.exec, [deps, callback], this); + }; + __proto.__ready = function(fn, args = [], context = window) { + 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)); + } + }; + + __proto.__getPlugin = function (pluginId) { + if(this.plugins.hasOwnProperty(pluginId)) { + return this.plugins[pluginId]; + } + var _pluginId, alias; + for (_pluginId in this.plugins) { + if(this.plugins.hasOwnProperty(_pluginId) && this.plugins[_pluginId].config.alias.indexOf(pluginId) !== -1) { + return this.plugins[_pluginId]; + } + } + var pluginIdLowerCase = pluginId.toLowerCase(); + for (_pluginId in this.plugins) { + if(!this.plugins.hasOwnProperty(_pluginId)) { + continue; + } + if(pluginIdLowerCase === _pluginId.toLowerCase()) { + return this.plugins[_pluginId]; + } + for(alias of this.plugins[_pluginId].config.alias) { + if(pluginIdLowerCase === alias.toLowerCase()) { + return this.plugins[_pluginId]; + } + } + } + return undefined; + }; + + /** + * @class kitConfig + */ + var defaultConfig = { + version: '1.10', + assetsPath: '', + requiredDependencies: [], + autoloadPluginList: [], + debug: false, + defaultPhoneMask: '+7 (999) 999-99-99', + }; + + var script = document.currentScript; + if(script){ + var path = script.src.split('?')[0]; + defaultConfig.assetsPath = path.split('/').slice(0, -2).join('/'); + } + + var manager = new PluginManager(global); + manager.register('PluginManager', { + alias: 'pm', + type: moduleTypeList.loader, + loader: function(module, exports, require) { + return module.exports = manager; + } + }); + manager.install('PluginManager'); + manager.register('config', { + type: moduleTypeList.loader, + loader: function(module, exports, require, global) { + var config = global.config || {}; + config = Object.assign({}, defaultConfig, config); + window.__pmConfig__ = global.config = config; + } + }); + manager.install('config'); + + window.__PluginManager__ = manager; + global.ready = manager.ready.bind(manager); + global.exec = manager.exec.bind(manager); + global.require = manager.require.bind(manager); + /** + * @var __pmGlobal__ + */ + window.__pmGlobal__ = global; +})(kit); + diff --git a/assets/core/core.register.js b/assets/core/v1/core.register.js similarity index 100% rename from assets/core/core.register.js rename to assets/core/v1/core.register.js diff --git a/assets/dataStructures/dataStructures.js b/assets/dataStructures/dataStructures.js index 1c0325e..fc65435 100644 --- a/assets/dataStructures/dataStructures.js +++ b/assets/dataStructures/dataStructures.js @@ -1,5 +1,5 @@ /** @module dataStructures */ -__PluginManager__.register('dataStructures', function(module, exports, require, global){ +__PluginManager__.register('dataStructures', function(require, exports, module, global){ /** diff --git a/assets/date/date.js b/assets/date/date.js index 1390d53..6c22ef1 100644 --- a/assets/date/date.js +++ b/assets/date/date.js @@ -10,7 +10,7 @@ * * @module date **/ -kit.PluginManager.register('date',function(module, exports, require, global) { +__PluginManager__.register('date',function(require, exports, module, global) { (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : diff --git a/assets/datepicker/js/datepicker.js b/assets/datepicker/js/datepicker.js index 85ddc35..756f42c 100644 --- a/assets/datepicker/js/datepicker.js +++ b/assets/datepicker/js/datepicker.js @@ -1,4 +1,4 @@ -kit.PluginManager.register('datepicker', function(module, exports, require, global){ +__PluginManager__.register('datepicker', function(require, exports, module, global){ var $, jQuery; jQuery = $ = require('jQuery'); diff --git a/assets/intl-tel-input/js/intlTelInput.min.js b/assets/intl-tel-input/js/intlTelInput.min.js index 956b84c..aaa7777 100644 --- a/assets/intl-tel-input/js/intlTelInput.min.js +++ b/assets/intl-tel-input/js/intlTelInput.min.js @@ -1,5 +1,5 @@ /** @module intlTelInput */ -kit.PluginManager.register('intlTelInput', function(module, exports, require, global){ +__PluginManager__.register('intlTelInput', function(require, exports, module, global){ /* * International Telephone Input v19.5.7 * https://github.com/jackocnr/intl-tel-input.git diff --git a/assets/jBox/jBox.js b/assets/jBox/jBox.js index 82f42c0..c422cbc 100644 --- a/assets/jBox/jBox.js +++ b/assets/jBox/jBox.js @@ -1,5 +1,5 @@ /** @module jBox */ -kit.PluginManager.register('jBox', function(module, exports, require, global){ +__PluginManager__.register('jBox', function(require, exports, module, global){ /** diff --git a/assets/jBox/jBox.min.js b/assets/jBox/jBox.min.js index d9c9b94..95ba41f 100644 --- a/assets/jBox/jBox.min.js +++ b/assets/jBox/jBox.min.js @@ -1,5 +1,5 @@ /** @module jBox */ -kit.PluginManager.register('jBox', function(module, exports, require, global){ +__PluginManager__.register('jBox', function(require, exports, module, global){ function jBoxWrapper(v){function h(t,i){return this.options={id:null,width:"auto",height:"auto",minWidth:null,minHeight:null,maxWidth:null,maxHeight:null,responsiveWidth:!0,responsiveHeight:!0,responsiveMinWidth:100,responsiveMinHeight:100,attach:null,trigger:"click",preventDefault:!1,content:null,getContent:null,title:null,getTitle:null,footer:null,isolateScroll:!0,ajax:{url:null,data:"",reload:!1,getURL:"data-url",getData:"data-ajax",setContent:!0,loadingClass:!0,spinner:!0,spinnerDelay:300,spinnerReposition:!0},cancelAjaxOnClose:!0,target:null,position:{x:"center",y:"center"},outside:null,offset:0,attributes:{x:"left",y:"top"},fixed:!1,adjustPosition:!0,adjustTracker:!1,adjustDistance:5,reposition:!0,repositionOnOpen:!0,repositionOnContent:!0,holdPosition:!0,pointer:!1,pointTo:"target",fade:180,animation:null,theme:"Default",addClass:null,overlay:!1,overlayClass:null,zIndex:1e4,delayOpen:0,delayClose:0,closeOnEsc:!1,closeOnClick:!1,closeOnMouseleave:!1,closeButton:!1,appendTo:v("body"),createOnInit:!1,blockScroll:!1,blockScrollAdjust:!0,draggable:!1,dragOver:!0,autoClose:!1,delayOnHover:!1,showCountdown:!1,preloadAudio:!0,audio:null,volume:100,onInit:null,onAttach:null,onPosition:null,onCreated:null,onOpen:null,onOpenComplete:null,onClose:null,onCloseComplete:null,onDragStart:null,onDragEnd:null},this._pluginOptions={Tooltip:{getContent:"title",trigger:"mouseenter",position:{x:"center",y:"top"},outside:"y",pointer:!0},Mouse:{responsiveWidth:!1,responsiveHeight:!1,adjustPosition:"flip",target:"mouse",trigger:"mouseenter",position:{x:"right",y:"bottom"},outside:"xy",offset:5},Modal:{target:v(window),fixed:!0,blockScroll:!0,closeOnEsc:!0,closeOnClick:"overlay",closeButton:!0,overlay:!0,animation:"zoomIn"}},this.options=v.extend(!0,this.options,this._pluginOptions[t]||h._pluginOptions[t],i),"string"==v.type(t)&&(this.type=t),this.isTouchDevice=function(){var t=" -webkit- -moz- -o- -ms- ".split(" ");if("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)return!0;var i,t=["(",t.join("touch-enabled),("),"heartz",")"].join("");return i=t,window.matchMedia(i).matches}(),this.isTouchDevice&&"mouseenter"===this.options.trigger&&!1===this.options.closeOnClick&&(this.options.closeOnClick="body"),this._fireEvent=function(t,i){this.options["_"+t]&&this.options["_"+t].bind(this)(i),this.options[t]&&this.options[t].bind(this)(i)},null===this.options.id&&(this.options.id="jBox"+h._getUniqueID()),this.id=this.options.id,("center"==this.options.position.x&&"x"==this.options.outside||"center"==this.options.position.y&&"y"==this.options.outside)&&(this.options.outside=null),"target"!=this.options.pointTo||this.options.outside&&"xy"!=this.options.outside||(this.options.pointer=!1),"object"!=v.type(this.options.offset)?this.options.offset={x:this.options.offset,y:this.options.offset}:this.options.offset=v.extend({x:0,y:0},this.options.offset),"object"!=v.type(this.options.adjustDistance)?this.options.adjustDistance={top:this.options.adjustDistance,right:this.options.adjustDistance,bottom:this.options.adjustDistance,left:this.options.adjustDistance}:this.options.adjustDistance=v.extend({top:5,left:5,right:5,bottom:5},this.options.adjustDistance),this.outside=!(!this.options.outside||"xy"==this.options.outside)&&this.options.position[this.options.outside],this.align=this.outside||("center"!=this.options.position.y&&"number"!=v.type(this.options.position.y)?this.options.position.x:"center"!=this.options.position.x&&"number"!=v.type(this.options.position.x)?this.options.position.y:this.options.attributes.x),h.zIndexMax=Math.max(h.zIndexMax||0,"auto"===this.options.zIndex?1e4:this.options.zIndex),"auto"===this.options.zIndex&&(this.adjustZIndexOnOpen=!0,this.options.zIndex=h.zIndexMax+=2,this.trueModal=this.options.overlay),this._getOpp=function(t){return{left:"right",right:"left",top:"bottom",bottom:"top",x:"y",y:"x"}[t]},this._getXY=function(t){return{left:"x",right:"x",top:"y",bottom:"y",center:"x"}[t]},this._getTL=function(t){return{left:"left",right:"left",top:"top",bottom:"top",center:"left",x:"left",y:"top"}[t]},this._getInt=function(t,i){return"auto"==t?"auto":t&&"string"==v.type(t)&&"%"==t.slice(-1)?v(window)["height"==i?"innerHeight":"innerWidth"]()*parseInt(t.replace("%",""))/100:t},this._createSVG=function(t,i){var o=document.createElementNS("http://www.w3.org/2000/svg",t);return v.each(i,function(t,i){o.setAttribute(i[0],i[1]||"")}),o},this._isolateScroll=function(e){e&&e.length&&e.on("DOMMouseScroll.jBoxIsolateScroll mousewheel.jBoxIsolateScroll",function(t){var i=t.wheelDelta||t.originalEvent&&t.originalEvent.wheelDelta||-t.detail,o=0<=this.scrollTop+e.outerHeight()-this.scrollHeight,s=this.scrollTop<=0;(i<0&&o||0",{id:this.id,class:"jBox-wrapper"+(this.type?" jBox-"+this.type:"")+(this.options.theme?" jBox-"+this.options.theme:"")+(this.options.addClass?" "+this.options.addClass:"")}).css({position:this.options.fixed?"fixed":"absolute",display:"none",opacity:0,zIndex:this.options.zIndex}).data("jBox",this),this.options.closeOnMouseleave&&this.wrapper.on("mouseleave",function(t){!this.source||t.relatedTarget!=this.source[0]&&-1===v.inArray(this.source[0],v(t.relatedTarget).parents("*"))&&this.close()}.bind(this)),"box"==this.options.closeOnClick&&this.wrapper.on("click tap",function(){this.close({ignoreDelay:!0})}.bind(this)),this.container=v('
').appendTo(this.wrapper),this.content=v('
').appendTo(this.container),this.options.footer&&(this.footer=v('