xrfragment-haxe/src/3rd/js/three/navigator.js

194 lines
6.4 KiB
JavaScript
Raw Normal View History

2024-04-16 18:40:49 +02:00
xrf.navigator = {
opts: {
openInNewTab: true
},
URI: xrf.URI.parse(document.location.href)
// scheme: document.location.protocol.replace(/:$/,''),
// directory: document.location.pathname,
// host: document.location.hostname,
// port: document.location.port,
// file: 'index.glb'
// }
2024-04-16 18:40:49 +02:00
}
2023-05-17 21:31:28 +02:00
2023-07-04 17:15:23 +02:00
xrf.navigator.to = (url,flags,loader,data) => {
2023-05-18 17:11:11 +02:00
if( !url ) throw 'xrf.navigator.to(..) no url given'
2024-04-10 16:38:50 +00:00
let URI = xrfragment.URI.toAbsolute( xrf.navigator.URI, url )
URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...)
2024-04-17 15:20:21 +00:00
// decorate with extra state
URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file
console.log( URI.URN + URI.file )
console.log( xrf.navigator.URI.URN + xrf.navigator.URI.file )
2024-04-17 15:20:21 +00:00
URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname
URI.hasPos = URI.hash.pos ? true : false
URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos
URI.hashChange = String(xrf.navigator.URI.fragment||"") != String(URI.fragment||"")
2024-04-10 10:54:24 +00:00
let hashbus = xrf.hashbus
2024-07-12 18:08:18 +00:00
//console.dir({URI1:xrf.navigator.URI,URI2:URI})
2024-04-10 16:38:50 +00:00
xrf.navigator.URI = URI
let {directory,file,fragment,fileExt} = URI;
2024-04-10 10:54:24 +00:00
const evalFragment = () => {
2024-04-10 16:38:50 +00:00
if( URI.fragment ){
hashbus.pub( URI.fragment, xrf.model, flags ) // eval local URI XR fragments
2024-04-10 10:54:24 +00:00
xrf.navigator.updateHash(fragment) // which don't require
}
}
2023-05-17 21:31:28 +02:00
return new Promise( (resolve,reject) => {
xrf
.emit('navigate', {url,loader,data})
.then( () => {
2023-05-18 17:11:11 +02:00
2024-04-10 16:38:50 +00:00
const Loader = xrf.loaders[fileExt]
2024-04-10 10:54:24 +00:00
if( fileExt && !loader ){
if( !Loader ) return resolve()
2024-04-10 16:38:50 +00:00
loader = loader || new Loader().setPath( URI.URN )
}
if( URI.duplicatePos || (!Object.values(URI.XRF).length && !URI.file && !URI.fileExt) ){
2024-04-17 15:20:21 +00:00
return resolve(xrf.model) // nothing we can do here
}
if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){
2024-04-10 10:54:24 +00:00
evalFragment()
2024-04-17 15:20:21 +00:00
return resolve(xrf.model) // eval non-positional fragments (no loader needed)
}
xrf
.emit('navigateLoading', {url,loader,data})
.then( () => {
2024-04-17 15:20:21 +00:00
if( (!URI.fileChange || !file) && URI.hashChange && URI.hasPos ){ // we're already loaded
2024-04-10 10:54:24 +00:00
evalFragment()
xrf.emit('navigateLoaded',{url})
return resolve(xrf.model)
}
2024-04-17 15:20:21 +00:00
// clear xrf objects from scene
if( xrf.model && xrf.model.scene ) xrf.model.scene.visible = false
xrf.reset()
// force relative path for files which dont include protocol or relative path
2024-04-10 10:54:24 +00:00
if( directory ) directory = directory[0] == '.' || directory.match("://") ? directory : `.${directory}`
2024-06-25 13:58:12 +00:00
if( loader || Loader ){
const onLoad = (model) => {
xrf.loadModel(model,url)
resolve(model)
}
2024-06-25 13:58:12 +00:00
loader = loader || new Loader().setPath( URI.URN )
if( data ){ // file upload
loader.parse(data, "", onLoad )
}else{
try{
loader.load(file, onLoad )
}catch(e){
console.error(e)
xrf.emit('navigateError',{url})
}
}
}else xrf.emit('navigateError',{url,URI})
})
})
2023-05-17 21:31:28 +02:00
})
}
xrf.navigator.init = () => {
if( xrf.navigator.init.inited ) return
2023-10-12 17:04:46 +02:00
2024-04-10 16:38:50 +00:00
xrf.navigator.URI = xrfragment.URI.parse(document.location.href)
2024-04-10 10:54:24 +00:00
2023-05-17 21:31:28 +02:00
window.addEventListener('popstate', function (event){
2024-06-26 11:17:14 +00:00
if( xrf.navigator.updateHash.active ){ // ignore programmatic hash updates (causes infinite recursion)
2024-04-22 14:01:02 +02:00
xrf.navigator.to( document.location.href.replace(/.*\?/,'') )
}
2023-05-17 21:31:28 +02:00
})
2023-10-12 17:04:46 +02:00
window.addEventListener('hashchange', function (e){
xrf.emit('hash', {hash: document.location.hash })
})
xrf.navigator.setupNavigateFallbacks()
// this allows selectionlines to be updated according to the camera (renderloop)
xrf.focusLine = new xrf.THREE.Group()
xrf.focusLine.material = new xrf.THREE.LineDashedMaterial({color:0xFF00FF,linewidth:3, scale: 1, dashSize: 0.2, gapSize: 0.1,opacity:0.3, transparent:true})
xrf.focusLine.isXRF = true
xrf.focusLine.position.set(0,0,-0.5);
xrf.focusLine.points = []
xrf.focusLine.lines = []
xrf.camera.add(xrf.focusLine)
2023-05-17 21:31:28 +02:00
xrf.navigator.init.inited = true
}
xrf.navigator.setupNavigateFallbacks = () => {
xrf.addEventListener('navigate', (opts) => {
let {url} = opts
2024-04-10 16:38:50 +00:00
let {fileExt} = xrfragment.URI.parse(url)
// handle http links
if( url.match(/^http/) && url != xrf.navigator.URI.URN && !xrf.loaders[fileExt] ){
let inIframe
try { inIframe = window.self !== window.top; } catch (e) { inIframe = true; }
if( inIframe ){
window.parent.postMessage({ url }, '*')
}else{
if( xrf.navigator.opts.openInNewTab ) window.open( url, '_blank')
else{ setTimeout( () => document.location.href = url, 1000) }
}
// in case you're running in an iframe, then use this in the parent page:
//
// window.addEventListener("message", (e) => {
// if (e.data && e.data.url){
// window.open( e.data.url, '_blank')
// }
// },
// false,
// );
}
})
}
xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
2024-04-10 16:38:50 +00:00
console.log(`URI: ${document.location.search.substr(1)}#${hash}`)
xrf.navigator.updateHash.active = false // important to prevent recursion
document.location.hash = hash
xrf.navigator.updateHash.active = true
}
2024-07-25 09:31:51 +00:00
xrf.navigator.updateHash.active = true
2023-05-18 17:11:11 +02:00
xrf.navigator.pushState = (file,hash) => {
if( file == document.location.search.substr(1) ) return // page is in its default state
window.history.pushState({}, '', document.location.pathname + `?${xrf.navigator.URI.source.replace(/#.*/,'')}#${hash}` )
xrf.emit('pushState', {file, hash} )
2023-05-17 21:31:28 +02:00
}
2024-04-10 16:38:50 +00:00
xrf.navigator.reactifyHash = ( obj ) => {
return new Proxy(obj,{
get(me,k) { return me[k] },
set(me,k,v){
me[k] = v
2024-06-26 11:17:14 +00:00
if( xrf.navigator.updateHash.active ){
xrf.navigator.to( "#" + this.toString(me) )
}
2024-06-26 11:17:14 +00:00
xrf.navigator.URI.fragment = this.toString(me)
2024-04-10 16:38:50 +00:00
},
toString(me){
let parts = []
Object.keys(me).map( (k) => {
2024-04-16 18:40:49 +02:00
parts.push( me[k] ? `${k}=${me[k]}` : k )
2024-04-10 16:38:50 +00:00
})
return parts.join('&')
}
})
}