-
Notifications
You must be signed in to change notification settings - Fork 0
/
golgi.min.js
1 lines (1 loc) · 18.3 KB
/
golgi.min.js
1
let count=0,golgi={dataStore:{},components:[],componentsByName:{},assemblies:new Map,stateMap:new Map,resourceLoaded:new Map,listeners:new Map,logging:!1,version:"1.5.1",setLog:function(e){this.logging=e},loadJSAsync:async function(e,t){return await golgi.loadJSFilePromise(e,t)},loadJSFilePromise:async function(e,t){let o=this;return new Promise(n=>{o.loadJS(e,t,function(e){n(e)})})},loadJS:function(e,t,o){let n;t&&(o||"function"!=typeof t?"object"==typeof t&&(n=t.crossorigin):o=t);let a=document.createElement("script");a.type="text/javascript",a.src=e;let i=this;a.onload=function(){i.logMessage("script "+e+" loaded"),o&&o(e)},n&&a.setAttribute("crossorigin",n),document.body.appendChild(a)},loadCSSAsync:async function(e,t){return await golgi.loadCSSPromise(e,t)},loadCSSPromise:async function(e,t){let o=this;return new Promise(n=>{o.loadCSS(e,t,function(e){n(e)})})},loadCSS:function(e,t,o){let n;t&&(o||"function"!=typeof t?"object"==typeof t&&(n=t.crossorigin,(t=t.target)||(t=document.getElementsByTagName("head")[0])):(o=t,t=document.getElementsByTagName("head")[0])),t||(t=document.getElementsByTagName("head")[0]);let a=t,i=document.createElement("link");i.rel="stylesheet",i.setAttribute("type","text/css"),i.href=e,n&&i.setAttribute("crossorigin",n);let s=this;i.onload=function(){s.logMessage("CSS file "+e+" loaded"),o&&o(e)},a.appendChild(i)},addMetaTag:function(e){let t,o=document.createElement("meta");for(t in e)o.setAttribute(t,e[t]);document.getElementsByTagName("head")[0].appendChild(o)},fetch_optimised_components:async function(e,t){let o=t||"golgi-components.js";this.logMessage("fetching optimised file of all components: "+o);const{golgi_components:n}=await import(o);let a=this;n.forEach(function(e){if(!customElements.get(e.n))try{e.f(),a.logMessage(e.n+" loaded")}catch(e){a.logMessage("Unable to fetch optimised component module"),console.log(e)}})},fetch_optimised_assemblies:async function(e,t){let o=t||"golgi-assemblies.js",n=e.assemblyPath+o;this.logMessage("fetching optimised file of all assemblies: "+n);let a=this;try{const{golgi_assemblies:e}=await import(n);e.forEach(function(e){a.assemblies.set(e.n,e.c)})}catch(e){this.logMessage("Unable to fetch optimised assembly module")}this.emit("assembliesLoaded")},load:async function(e,t,o){let n=e.split("-")[0];this.logMessage("*** load "+e);let a=o.componentPath||"./";o.componentPaths&&o.componentPaths[n]&&(a=o.componentPaths[n]);let i=a;function s(e){let n=new e;return t?t.appendChild(n):golgi.components.push(n),n.context=o,n.path=a,n.rootPath=i,n.isComponent=!0,n}"/"!==i.slice(-1)&&(i=a+"/");let l=customElements.get(e);if(l){return this.logMessage("** component "+e+" already imported"),s(l)}{let t=await import(a+e+".js");o.golgiLoadSequence||(o.golgiLoadSequence=[]),o.golgiLoadSequence.push(e),this.logging&&(this.logMessage("Component Load Sequence so far:"),console.log(o.golgiLoadSequence));let n=customElements.get(e);return n||(t.load.call(this),n=customElements.get(e),this.logMessage("** component "+e+" had to be imported")),s(n)}},loadGroup:async function(e,t,o,n){"body"===t&&(t=document.getElementsByTagName("body")[0]),o=o||{},Array.isArray(e)||(e=[e]);let a=e[0].assemblyName;for(const i of e)await this.processComponent(i,a,t,o,n)},processComponent:async function(e,t,o,n,a){let i=o;if(e.targetElement){let t=this.getParentComponent.call(i,e.targetElement.componentName);t&&t[e.targetElement.target]&&(i=t[e.targetElement.target])}if("assembly"===e.componentName.split(":")[0]){let t=e.componentName.split("assembly:")[1];if(await this.renderAssembly(t,i,n),e.hook)try{e.hook.call(this,n)}catch(e){this.logging&&(this.logMessage("Unable to execute hook "+name+" for "+config.componentName),console.log(e))}return}let s=await this.loadComponent(e,t,i,n,a);e.children&&e.children[0]&&s.childrenTarget&&(e.children.forEach(function(o,n){e.children[n].assemblyName=t}),await this.loadGroup(e.children,s.childrenTarget,n,a))},loadComponent:async function(e,t,o,n,a){let i=Object.assign({},e);if(!i.componentName.includes("-")&&!i.componentName.includes(":")){let e=document.createElement(i.componentName);e.textContent=i.textContent;for(let t in i.attributes)"golgi:ref"===t?a[i.attributes[t]]=e:e.setAttribute(t,i.attributes[t]);if(e.childrenTarget=e,o&&o.appendChild(e),i.hook)try{let t={...this};t.element=e,"AsyncFunction"===i.hook.constructor.name?await i.hook.call(t,n):i.hook.call(t,n)}catch(e){this.logging&&(this.logMessage("Unable to execute hook "+name+" for "+i.componentName),console.log(e))}return e}i.meta&&i.meta.forEach(function(e){golgi.addMetaTag(e)});await Promise.all(["script","css"].map(async e=>{"script"===e&&i.script&&await Promise.all(i.script.map(async e=>{if(!golgi.resourceLoaded.has(e.src)){let t;e.crossorigin&&(t={crossorigin:e.crossorigin}),e.await?await golgi.loadJSAsync(e.src,t):golgi.loadJS(e.src,t),golgi.resourceLoaded.set(e.src,!0)}})),"css"===e&&i.css&&await Promise.all(i.css.map(async e=>{if(!golgi.resourceLoaded.has(e.src)){let t;e.crossorigin&&(t={crossorigin:e.crossorigin}),e.await?await golgi.loadCSSAsync(e.src,t):golgi.loadCSS(e.src,t),golgi.resourceLoaded.set(e.src,!0)}}))}));let s=await this.renderWebComponent(i,o,n,a);return s.parentComponent&&s.parentComponent.onChildComponentReady&&s.parentComponent.onChildComponentReady.call(s.parentComponent,s),s},renderWebComponent:async function(e,t,o,n){let a,i=e.assemblyName,s=await this.load(e.componentName,t,o);if(n&&e.state&&e.state["golgi:ref"]){n[e.state["golgi:ref"]]=s,delete e.state["golgi:ref"]}if(this.logging,s.shadowRoot){if(s.rootElement=s.shadowRoot.firstElementChild,"STYLE"===s.rootElement.tagName){let e=!1,t=s.rootElement;do{t.nextSibling&&1===(t=t.nextSibling).nodeType&&(e=!0)}while(!e);s.rootElement=e?t:s.shadowRoot.firstElementChild}a=s.shadowRoot.querySelectorAll("*")}else void 0!==s.html&&(s.innerHTML=s.html,s.rootElement=s.firstElementChild,a=s.querySelectorAll("*"));if(void 0!==s.rootElement){s.databinding=[],a.forEach(function(e){if(e.hasAttribute("golgi:prop")){let t=e.getAttribute("golgi:prop");s[t]=e,e.removeAttribute("golgi:prop")}e.ownerComponent=s,e.childNodes.forEach(function(t){if(3===t.nodeType){let o=t.nodeValue.toString();if(t.nodeValue.includes("golgi:bind")){let o=t.nodeValue.split("golgi:bind=")[1]||"dummy";o=o.split(";")[0];let n=document.createElement("span");e.insertBefore(n,t);let a=function(e){let t=e;"object"==typeof e&&(t=e[o]),void 0!==t&&(n.innerHTML=t)};s.databinding.push(a),t.nodeValue=""}if(o.includes("golgi:observer")){let t=e;e.firstChild&&"SPAN"===e.firstChild.tagName&&(t=e.firstChild);let n=o.split("golgi:observer=")[1];n=n.split(";")[0],golgi.observeText(t,s,n,e).observe(t,{childList:!0,subtree:!0})}}}),[...e.attributes].forEach(function(t){if(t.name.startsWith("golgi:on_")){let o=t.name.split("golgi:on_")[1],n=t.value;if(s[n]&&"function"==typeof s[n]){let t;t="AsyncFunction"===s[n].constructor.name?async function(e){await s[n](e)}:function(e){s[n](e)},golgi.addHandler.call(s,t,e,o)}e.removeAttribute(t.name)}if(t.value.includes("golgi:bind")){let o,n=t.value.split("golgi:bind=")[1];n=n.split(";")[0],o="INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName||"value"!==t.name?function(o){let a=o;"object"==typeof o&&(a=o[n]),void 0!==a&&e.setAttribute(t.name,a)}:function(t){let o=t;"object"==typeof t&&(o=t[n]),void 0!==o&&(e.value=o)},s.databinding.push(o),e.removeAttribute(t.name)}if(t.value.includes("golgi:observer")){let o=t.value.split("golgi:observer=")[1];o=o.split(";")[0],golgi.observeAttr(t.name,o).observe(e,{attributeFilter:[t.name],attributeOldValue:!0})}})}),s.childrenTarget||(s.childrenTarget=s.rootElement),s.childrenTarget.ownerComponent=s;let e="golgi:component-class",t=s.rootElement.getAttribute(e);if(t){t.split(" ").forEach(function(e){s.classList.add(e)}),s.rootElement.removeAttribute(e)}}if(s.componentName=e.componentName,s.getParentComponent=this.getParentComponent.bind(s),s.onUnload=this.onUnload.bind(s),s.registerUnloadMethod=this.registerUnloadMethod.bind(s),s.remove=this.remove.bind(s),s.removeAllByName=this.removeAllByName,s.getComponentByName=this.getComponentByName.bind(this),s.getComponentsByName=this.getComponentsByName,s.addHandler=this.addHandler.bind(s),s.addMetaTag=this.addMetaTag,s.loadResources=this.loadResources,s.loadJSAsync=this.loadJSAsync,s.loadJS=this.loadJS.bind(this),s.loadCSSAsync=this.loadCSSAsync,s.loadCSS=this.loadCSS.bind(this),s.logging=this.logging,s.logMessage=this.logMessage.bind(this),s.loadGroup=this.loadGroup.bind(this),s.renderAssembly=this.renderAssembly.bind(this),s.renderComponent=this.renderComponent.bind(this),s.renderComponentMap=this.renderComponentMap.bind(this),s.observerStart=this.observerStart,s.methodsToRemove=[],s.golgi_state=this.golgi_state,s.addStateMap=this.addStateMap.bind(s),s.applyDataBinding=this.applyDataBinding.bind(s),s.registeredListenerTypes=new Map,s.on=this.el_on.bind(s),s.off=this.el_off.bind(s),s.emit=this.el_emit.bind(s),s.onAssemblyRendered=function(e,t){golgi.on(e+"_rendered",t,s)},s.ownerAssembly=i,s.onOwnerAssemblyRendered=function(e){golgi.on(i+"_rendered",e,s)},o.rootComponent||(o.rootComponent=s),s.rootComponent=o.rootComponent,t&&(s.parentComponent=t.ownerComponent),golgi.componentsByName[s.tagName]||(golgi.componentsByName[s.tagName]=[]),golgi.componentsByName[s.tagName].push(s),this.logging&&(this.logMessage("Golgi Component instantiated and ready for use:"),console.log(s)),s.onBeforeState&&("AsyncFunction"===s.onBeforeState.constructor.name?await s.onBeforeState():s.onBeforeState()),e.state){for(let t in e.state)s[t]&&"function"==typeof s[t]&&(s[t].call(s,e.state[t]),delete e.state[t]);e.state&&s.setState&&"function"==typeof s.setState&&s.setState(e.state)}if(e.stateMap){e.state_map=new Map;for(let t in e.stateMap)e.state_map.set(t,e.stateMap[t])}if(e.state_map&&e.state_map.forEach(function(e,t){golgi.stateMap.has(t)||golgi.stateMap.set(t,[]),golgi.stateMap.get(t).push({component:s,method:e})}),s.onBeforeHooks&&s.onBeforeHooks(),e.hook)try{"AsyncFunction"===e.hook.constructor.name?await e.hook.call(s,o):e.hook.call(s,o)}catch(t){this.logging&&(this.logMessage("Unable to execute hook "+name+" for "+e.componentName),console.log(t))}return s.onAfterHooks&&s.onAfterHooks(),s.emit("componentReady"),s},renderComponentMap:async function(e,t,o,n,a,i){let s=-1,l=a.split(":"),r=l[0],g=l[1];void 0!==g&&""!==g||(g="applyDataBinding");for(let a of n){let n=await this.renderComponent(e,t,o);i&&i.call(n,n,a);let l=r+"."+ ++s;n.addStateMap(l,g)}this.golgi_state[r]=n},renderAssembly:async function(e,t,o){let n,a={};if(t||o||"object"!=typeof e?n=e:(t=e.targetElement,o=e.context,n=e.name),!o)return;if(!n)return;if(""===n)return;let i,s=o.assemblyPath;""===s&&(s="./"),"/"!==s.slice(-1)&&(s+="/");let l=(i=this.assemblies.has(n)?{load:this.assemblies.get(n)}:await import(s+n+".js")).load.call(this,o),r=l.gjson||{};if(l.gx&&(r=this.parse(l.gx,l.hooks,o)),r){Array.isArray(r)||(r=[r]);let e=!1;r.forEach(function(t,o){r[o].assemblyName=n,t.state&&"root"===t.state["golgi:ref"]&&(e=!0)}),e||(r[0].state||(r[0].state={}),r[0].state["golgi:ref"]="root")}await this.loadGroup(r,t,o,a),this.emit(n+"_rendered");let g=a.root;for(let e in a)"root"!==e&&(g[e]=a[e]);return g.refs=a,g},async renderComponent(e,t,o){"body"===t&&(t=document.getElementsByTagName("body")[0]);let n=0;t&&(n=t.getElementsByTagName(e).length);let a=[{componentName:e}];return await this.loadGroup(a,t,o),t?t.getElementsByTagName(e)[n]:golgi.components},getParentComponent(e){"string"==typeof(e=e||{})&&(e={match:e}),this.element&&(this.tagName=this.element.tagName,this.parentNode=this.element.parentNode);let t=e.prefix||this.tagName.split("-")[0];return function o(n){if(!(n=11===n.nodeType?n.host:n.parentNode))return null;if(e.match){if(n.tagName===e.match.toUpperCase())return n}else if(n.tagName.startsWith(t))return n;return o(n)}(this)},getComponentsByName:e=>golgi.componentsByName[e.toUpperCase()]||[],getComponentByName(e,t,o){let n,a=[...(o=o||document).getElementsByTagName(e.toUpperCase())];if(!t)return a;for(n=0;n<a.length;n++)if(a[n].name===t)return a[n]},addHandler:function(e,t,o){o||"string"!=typeof t||(o=t,t=null),o=o||"click",(t=t||this.rootElement).addEventListener(o,e),this.listeners||(this.listeners=[]),this.listeners.push({type:o,fn:e,target:t})},registerUnloadMethod(e){this.methodsToRemove.push(e)},onUnload:function(){this.logging&&(this.logMessage("removing Golgi COmponent:"),console.log(this));for(const e of this.registeredListenerTypes.keys())this.logMessage("removing customHandler for type "+e),this.off(e);let e=this;this.listeners&&this.listeners.forEach(function(t){e.logging&&(e.logMessage("removing listener"),console.log(t)),t.target.removeEventListener(t.type,t.fn)}),this.methodsToRemove.forEach(function(t){e.logging&&(e.logMessage("invoking custom unload method"),console.log(t)),t()})},remove:function(){!function e(t){[...t.childNodes].forEach(function(t){1===t.nodeType&&(t.shadowRoot&&(t=t.shadowRoot),e(t),t.isComponent&&(t.onUnload(),t.parentNode.removeChild(t)))})}(this),this.onUnload();for(let e in golgi.componentsByName[this.tagName]){if(golgi.componentsByName[this.tagName][e].name===this.name){golgi.componentsByName[this.tagName].splice(e,1);break}}this.parentNode.removeChild(this)},removeAllByName:function(e,t){let o;(o=t?[...t.getElementsByTagName(e)]:[...document.getElementsByTagName(e)])&&o.forEach(e=>{e.remove()})},el_on:function(e,t){if(!this.registeredListenerTypes.has(e)){let o=function(e){t(e.detail)};this.addEventListener(e,o),this.registeredListenerTypes.set(e,o)}},el_emit:function(e,t){if(this.registeredListenerTypes.has(e)){let o=new CustomEvent(e,{detail:t});this.dispatchEvent(o)}},el_off:function(e){if(this.registeredListenerTypes.has(e)){let t=this.registeredListenerTypes.get(e);this.removeEventListener(e,t),this.registeredListenerTypes.delete(e)}},on:function(e,t,o){if(!this.listeners.has(e)){let n={handler:t,context:o};this.listeners.set(e,n)}},off:function(e){this.listeners.has(e)&&this.listeners.delete(e)},emit:function(e,t){if(this.listeners.has(e)){let o=this.listeners.get(e),n=o.context||this;o.handler.call(n,t)}},logMessage:function(e){this.logging&&console.log(Date.now()+": "+e)},parse:function(e,t,o){let n='<xml xmlns="http://mgateway.com" xmlns:assembly="http://mgateway.com" xmlns:golgi="http://mgateway.com">'+e+"</xml>",a=[];return function e(n,a){[...n.childNodes].forEach(function(i){if(1===i.nodeType){if(["script","css","meta"].includes(i.tagName))return;let s={componentName:i.tagName,state:{}};if(i.tagName.includes("-")&&""!==i.textContent.trim()){let e=[...i.childNodes];for(let t=0;t<e.length;t++){let o=e[t];if(3===o.nodeType){let e=o.textContent.trim();if(""!==e){s.state.textContent=e;break}}}}if(i.hasAttributes())if(i.tagName.includes("-")||i.tagName.includes(":")){let e=[...i.attributes],a={};e.forEach(function(e){let l=e.value;if("true"===l)l=!0;else if("false"===l)l=!1;else if(l.startsWith&&l.startsWith("golgi:context=")){let e=l.split("golgi:context=")[1].split("."),t=o,n=!1;e.forEach(function(e,o){n||(void 0!==t[e]?t=t[e]:n=!0)}),l=n?"*Invalid context reference*":t}else try{l=JSON.parse(l)}catch(e){}if("golgi:hook"===e.name&&t&&t[i.tagName]&&t[i.tagName][l]&&(s.hook=t[i.tagName][l]),"golgi:stateMap"===e.name){let e=l.split(":")[0];s.state_map||(s.state_map=new Map);let t=l.split(":")[1];void 0!==t&&""!==t||(t="applyDataBinding"),s.state_map.set(e,t)}else if("golgi:appendTo"===e.name)s.targetElement={componentName:n.tagName,target:l};else if(e.name.includes(".")){let t=e.name.split("."),o=t.length,n=a;t.forEach(function(e,t){n[e]||(n[e]={}),t===o-1?n[e]=l:n=n[e]})}else s.state[e.name]=l});for(let e in a)s.state[e]=a[e]}else s.attributes={},[...i.attributes].forEach(function(e){"golgi:appendTo"===e.name?s.targetElement={componentName:n.tagName,target:e.value}:"golgi:hook"===e.name&&t&&t[i.tagName]&&t[i.tagName][e.value]?s.hook=t[i.tagName][e.value]:s.attributes[e.name]=e.value});i.tagName.includes("-")||0!==i.childElementCount||(s.textContent=i.textContent,s.childElementCount=i.childElementCount),i.hasChildNodes()&&(s.children=[],[...i.childNodes].forEach(function(e){if(1===e.nodeType&&["script","css","meta"].includes(e.tagName)){s[e.tagName]||(s[e.tagName]=[]);let t={};[...e.attributes].forEach(function(e){t[e.name]=e.value}),s[e.tagName].push(t)}}),e(i,s.children)),a.push(s)}})}((new DOMParser).parseFromString(n,"text/xml").documentElement,a),a},observerStart(){if(this.logging&&(this.logMessage("running observerStart on this:"),console.log(this)),this.observerCallback){let e=this.shadowRoot||this;golgi.observer.observe(e,{attributes:!0,attributeOldValue:!0,characterData:!0,characterDataOldValue:!0,childList:!0,subtree:!0})}},observer:new MutationObserver(function(e){e.forEach(function(e){let t=function(e){let t=!1,o=e;do{11===(o=o.parentNode).nodeType&&(o=o.host),o&&!o.tagName.includes("-")||(t=!0)}while(!t);return o}(e.target);t.observerCallback&&t.observerCallback(e)})}),observeAttr:(e,t)=>new MutationObserver(function(o){o.forEach(function(o){if("attributes"===o.type){let n=o.target.getAttribute(e),a=o.target.ownerComponent[t];a&&o.target.ownerComponent&&n&&n!==o.oldValue&&a.call(o.target.ownerComponent,n,o.oldValue)}})}),observeText:(e,t,o,n)=>new MutationObserver(function(a){a.forEach(function(a){if("childList"===a.type){let a=e.textContent,i=t[o];i&&a&&i.call(t,a,e,n)}})}),addStateMap(e,t){t=t||"applyDataBinding",golgi.stateMap.has(e)||golgi.stateMap.set(e,[]),golgi.stateMap.get(e).push({component:this,method:t})},applyDataBinding(e){this.databinding.forEach(function(t){t(e)}),this.onDataUpdated&&this.onDataUpdated(e)}};golgi.golgi_state=new Proxy(golgi.dataStore,{get:function(e,t,o){return setTimeout(function(){!function(e,t){if(golgi.logging&&(golgi.logMessage("1 trying to apply state for mapKey "+e+":"),console.log(t)),golgi.stateMap.has(e)){let o=golgi.stateMap.get(e);o.forEach((e,n)=>{if(e.component)if(e.component[e.method])e.component[e.method](t);else{let o={};o[e.method]=t,e.component.setState(o)}else o.splice(n,1)})}}(t,e[t])},100),e[t]},set:function(e,t,o){let n=[];function a(e,t){if(golgi.logging&&(golgi.logMessage("2 trying to apply state for mapKey "+e+":"),console.log(t)),golgi.stateMap.has(e)){let o=golgi.stateMap.get(e);o.forEach((e,n)=>{if(e.component)if(e.component[e.method])e.component[e.method](t);else{let o={};o[e.method]=t,e.component.setState(o)}else o.splice(n,1)})}}return golgi.dataStore[t]=o,"object"==typeof o&&function e(t,o){golgi.logging&&(golgi.logMessage("getProps called for "+t),console.log(o)),n.push(t),a(n.join("."),o),Object.entries(o).forEach((t,o)=>{const[i,s]=t;"object"!=typeof s?a(n.join(".")+"."+i,s):(e(i,s),n.pop())})}(t,o),"string"!=typeof o&&"number"!=typeof o||a(t,o),!0}});export{golgi};