xrsh-com/com/app.js

81 lines
2.9 KiB
JavaScript
Raw Normal View History

2023-12-31 21:25:51 +01:00
// this is a highlevel way of loading buildless 'apps' (a collection of js components)
AFRAME.registerComponent('app', {
schema:{
"uri":{ type:"string"}
},
2024-01-02 19:00:25 +01:00
events:{
"app:ready": function(){
let {id,component,type} = this.parseAppURI(this.data.uri)
2023-12-31 21:25:51 +01:00
let entity = document.createElement("a-entity")
this.el.setAttribute(component,this.data)
2024-01-01 19:53:10 +01:00
}
2023-12-31 21:25:51 +01:00
},
2024-01-02 19:00:25 +01:00
init: function() {
let {id,component,type} = this.parseAppURI(this.data.uri)
if( AFRAME.components[component] || document.head.querySelector(`script#${id}`) ) this.el.emit('app:ready',{})
else this.require([ this.data.uri ], 'app:ready')
},
parseAppURI: AFRAME.AComponent.prototype.parseAppURI = function(uri){
return {
id: String(uri).split("/").pop(), // 'a/b/c/mycom.js' => 'mycom.js'
component: String(uri).split("/").pop().split(".js").shift(), // 'mycom.js' => 'mycom'
type: String(uri).split(".").pop() // 'mycom.js' => 'js'
}
},
2023-12-31 21:25:51 +01:00
// usage: require(["./app/foo.js"])
// require({foo: "https://foo.com/foo.js"})
2024-01-02 19:00:25 +01:00
require: AFRAME.AComponent.prototype.require = function(packages,readyEvent){
2023-12-31 21:25:51 +01:00
let deps = []
if( !packages.map ) packages = Object.values(packages)
packages.map( (package) => {
let id = package.split("/").pop()
if( !document.head.querySelector(`script#${id}`) ){
2024-01-02 19:00:25 +01:00
let {id,component,type} = this.parseAppURI(package)
2023-12-31 21:25:51 +01:00
let p = new Promise( (resolve,reject) => {
2024-01-02 19:00:25 +01:00
switch(type){
case "js": let script = document.createElement("script")
script.id = id
script.src = package
script.onload = () => resolve()
script.onerror = (e) => reject(e)
document.head.appendChild(script)
break;
case "css": let link = document.createElement("link")
link.id = id
link.href = package
link.rel = 'stylesheet'
document.head.appendChild(link)
resolve()
break;
}
2023-12-31 21:25:51 +01:00
})
deps.push(p)
}
})
2024-01-02 19:00:25 +01:00
Promise.all(deps).then( () => this.el.emit( readyEvent||'ready', packages) )
2023-12-31 21:25:51 +01:00
}
})
// monkeypatching initComponent will trigger events when components
// are initialized (that way apps can react to attached components)
// basically, in both situations:
// <a-entity foo="a:1"/>
// <a-entity app="uri: myapp.js"/> <!-- myapp.js calls this.require(['foo.js']) -->
//
// event 'foo' will be triggered as both entities (in)directly require component 'foo'
AFRAME.AComponent.prototype.initComponent = function(initComponent){
return function(){
this.el.emit( this.attrName, this)
return initComponent.apply(this,arguments)
}
}( AFRAME.AComponent.prototype.initComponent)