better & tab-able buttons/notifications #accessibility
This commit is contained in:
parent
093de1ec6f
commit
0bc5fa86d1
9 changed files with 112129 additions and 11 deletions
2
dist/xrfragment.aframe.all.js
vendored
2
dist/xrfragment.aframe.all.js
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* v0.5.1 generated at Sat Jun 15 05:46:02 PM CEST 2024
|
* v0.5.1 generated at Mon Jun 17 12:41:29 PM UTC 2024
|
||||||
* https://xrfragment.org
|
* https://xrfragment.org
|
||||||
* SPDX-License-Identifier: MPL-2.0
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
2
dist/xrfragment.aframe.js
vendored
2
dist/xrfragment.aframe.js
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* v0.5.1 generated at Sat Jun 15 05:46:02 PM CEST 2024
|
* v0.5.1 generated at Mon Jun 17 12:41:29 PM UTC 2024
|
||||||
* https://xrfragment.org
|
* https://xrfragment.org
|
||||||
* SPDX-License-Identifier: MPL-2.0
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
111967
dist/xrfragment.module.js
vendored
111967
dist/xrfragment.module.js
vendored
File diff suppressed because it is too large
Load diff
81
dist/xrfragment.plugin.frontend.js
vendored
81
dist/xrfragment.plugin.frontend.js
vendored
|
|
@ -284,6 +284,8 @@ window.accessibility = (opts) => new Proxy({
|
||||||
.replace(/&/,' and ')
|
.replace(/&/,' and ')
|
||||||
.replace(/=/,' is ')
|
.replace(/=/,' is ')
|
||||||
}
|
}
|
||||||
|
if( str == this.speak.lastStr ) return // no duplicates
|
||||||
|
this.speak.lastStr = str
|
||||||
let speech = window.speechSynthesis
|
let speech = window.speechSynthesis
|
||||||
let utterance = new SpeechSynthesisUtterance( str )
|
let utterance = new SpeechSynthesisUtterance( str )
|
||||||
this.speak_voices = speech.getVoices().length
|
this.speak_voices = speech.getVoices().length
|
||||||
|
|
@ -304,6 +306,18 @@ window.accessibility = (opts) => new Proxy({
|
||||||
|
|
||||||
init(){
|
init(){
|
||||||
|
|
||||||
|
this
|
||||||
|
.speakArrowKeys()
|
||||||
|
.setupListeners()
|
||||||
|
.setupPersistance()
|
||||||
|
.setupHrefCycling()
|
||||||
|
.setupSpeechKillOnEscape()
|
||||||
|
|
||||||
|
setTimeout( () => this.initCommands(), 200 )
|
||||||
|
},
|
||||||
|
|
||||||
|
speakArrowKeys(){
|
||||||
|
// speak arrow keys
|
||||||
window.addEventListener('keydown', (e) => {
|
window.addEventListener('keydown', (e) => {
|
||||||
if( !this.speak_keyboard ) return
|
if( !this.speak_keyboard ) return
|
||||||
let k = e.key
|
let k = e.key
|
||||||
|
|
@ -315,6 +329,60 @@ window.accessibility = (opts) => new Proxy({
|
||||||
}
|
}
|
||||||
this.speak(k,{override:true})
|
this.speak(k,{override:true})
|
||||||
})
|
})
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
|
setupSpeechKillOnEscape(){
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if( e.key == "Escape" ){
|
||||||
|
this.speak("stop",{override:true})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
setupHrefCycling(){
|
||||||
|
// speak arrow keys
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if( e.key != 'Tab') return
|
||||||
|
let subScene = xrf.scene.getObjectByName( xrf.frag.pos.last )
|
||||||
|
if( !subScene ) subScene = xrf.scene
|
||||||
|
let cache = this.setupHrefCycling.cache = this.setupHrefCycling.cache || {current: 0}
|
||||||
|
let objects = []
|
||||||
|
subScene.traverse( (n) => (n.userData.href || n.userData['aria-description']) && objects.push(n) )
|
||||||
|
|
||||||
|
const highlight = (n) => {
|
||||||
|
if( this.helper){
|
||||||
|
if( this.helper.selected == n.uuid ) return // already selected
|
||||||
|
xrf.scene.remove(this.helper)
|
||||||
|
}
|
||||||
|
this.selected = n
|
||||||
|
this.helper = new THREE.BoxHelper( n, 0xFF00FF )
|
||||||
|
this.helper.computeLineDistances()
|
||||||
|
this.helper.material.linewidth = 8
|
||||||
|
this.helper.material.color = xrf.focusLine.material.color
|
||||||
|
this.helper.material.dashSize = xrf.focusLine.material.dashSize
|
||||||
|
this.helper.material.gapSize = xrf.focusLine.material.gapSize
|
||||||
|
this.helper.selected = n.uuid
|
||||||
|
xrf.scene.add(this.helper)
|
||||||
|
|
||||||
|
notify(`${n.userData['aria-description']||''}` + (n.userData.href ? `<br><b>name:</b> ${n.name}<br><b>link:</b> ${n.userData['href']}` :'') )
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure valid href
|
||||||
|
cache.current = cache.current % objects.length
|
||||||
|
highlight( objects[cache.current] )
|
||||||
|
console.log(objects[cache.current].userData.href)
|
||||||
|
|
||||||
|
// increment to next
|
||||||
|
cache.current = cache.current + 1
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
|
setupListeners(){
|
||||||
|
|
||||||
document.addEventListener('$menu:buttons:render', (e) => {
|
document.addEventListener('$menu:buttons:render', (e) => {
|
||||||
let $ = e.detail
|
let $ = e.detail
|
||||||
|
|
@ -354,8 +422,10 @@ window.accessibility = (opts) => new Proxy({
|
||||||
network.posName = opts.frag.pos.string
|
network.posName = opts.frag.pos.string
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
setTimeout( () => this.initCommands(), 200 )
|
setupPersistance(){
|
||||||
// auto-enable if previously enabled
|
// auto-enable if previously enabled
|
||||||
if( window.localStorage.getItem("accessibility") === 'true' || xrf.navigator.URI.XRF.accessible ){
|
if( window.localStorage.getItem("accessibility") === 'true' || xrf.navigator.URI.XRF.accessible ){
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
|
|
@ -363,11 +433,14 @@ window.accessibility = (opts) => new Proxy({
|
||||||
this.setFontSize()
|
this.setFontSize()
|
||||||
}, 100 )
|
}, 100 )
|
||||||
}
|
}
|
||||||
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
initCommands(){
|
initCommands(){
|
||||||
|
|
||||||
document.addEventListener('chat.command.help', (e) => {
|
document.addEventListener('chat.command.help', (e) => {
|
||||||
|
e.detail.message += `<br><b class="badge"><Escape></b> silence TTS `
|
||||||
|
e.detail.message += `<br><b class="badge"><Tab></b> cycle [href] buttons / silence TTS `
|
||||||
e.detail.message += `<br><b class="badge">/fontsize <number></b> set fontsize (default=14) `
|
e.detail.message += `<br><b class="badge">/fontsize <number></b> set fontsize (default=14) `
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -572,6 +645,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
el: null,
|
el: null,
|
||||||
|
notify_links: true,
|
||||||
plugin: {},
|
plugin: {},
|
||||||
xrf,
|
xrf,
|
||||||
|
|
||||||
|
|
@ -651,7 +725,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
let instructions = AFRAME.utils.device.isMobile()
|
let instructions = AFRAME.utils.device.isMobile()
|
||||||
? "hold 2-3 fingers to move forward/backward"
|
? "hold 2-3 fingers to move forward/backward"
|
||||||
: "use WASD-keys and mouse-drag to move around"
|
: "use W A S D keys and mouse-drag to move around"
|
||||||
window.notify(instructions,{timeout:false})
|
window.notify(instructions,{timeout:false})
|
||||||
xrf.addEventListener('pos', (opts) => {
|
xrf.addEventListener('pos', (opts) => {
|
||||||
let pos = opts.frag.pos.string
|
let pos = opts.frag.pos.string
|
||||||
|
|
@ -662,7 +736,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
xrf.addEventListener('href', (data) => {
|
xrf.addEventListener('href', (data) => {
|
||||||
if( !data.selected ) return
|
if( !data.selected ) return
|
||||||
|
|
||||||
let html = `<b class="badge">${data.mesh.isSRC && !data.mesh.portal ? 'src' : 'href'}</b>${ data.xrf ? data.xrf.string : data.mesh.userData.src}<br>`
|
let html = this.notify_links ? `<b class="badge">${data.mesh.isSRC && !data.mesh.portal ? 'src' : 'href'}</b>${ data.xrf ? data.xrf.string : data.mesh.userData.src}<br>` : ''
|
||||||
let metadata = data.mesh.userData
|
let metadata = data.mesh.userData
|
||||||
let meta = xrf.Parser.getMetaData()
|
let meta = xrf.Parser.getMetaData()
|
||||||
|
|
||||||
|
|
@ -682,6 +756,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
let transcript = xrf.sceneToTranscript(root,data.mesh)
|
let transcript = xrf.sceneToTranscript(root,data.mesh)
|
||||||
if( transcript.length ) html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
|
if( transcript.length ) html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
|
||||||
if (hasMeta && !data.mesh.portal && metadata.XRF.src ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
|
if (hasMeta && !data.mesh.portal && metadata.XRF.src ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
|
||||||
|
if( !html ) return
|
||||||
window.notify(html,{timeout: 7000 * (hasMeta ? 1.5 : 1) })
|
window.notify(html,{timeout: 7000 * (hasMeta ? 1.5 : 1) })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
2
dist/xrfragment.three.js
vendored
2
dist/xrfragment.three.js
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* v0.5.1 generated at Sat Jun 15 05:46:02 PM CEST 2024
|
* v0.5.1 generated at Mon Jun 17 12:41:29 PM UTC 2024
|
||||||
* https://xrfragment.org
|
* https://xrfragment.org
|
||||||
* SPDX-License-Identifier: MPL-2.0
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
2
dist/xrfragment.three.module.js
vendored
2
dist/xrfragment.three.module.js
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* v0.5.1 generated at Sat Jun 15 05:46:02 PM CEST 2024
|
* v0.5.1 generated at Mon Jun 17 12:41:29 PM UTC 2024
|
||||||
* https://xrfragment.org
|
* https://xrfragment.org
|
||||||
* SPDX-License-Identifier: MPL-2.0
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,9 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
document.addEventListener('$menu:ready', (e) => {
|
document.addEventListener('$menu:ready', (e) => {
|
||||||
let {$menu} = e.detail
|
frontend.notify_links = true // shows href/src's as notifications when hovering buttons
|
||||||
// add your menubuttons:
|
// add your menubuttons:
|
||||||
|
let {$menu} = e.detail
|
||||||
$menu.buttons = $menu.buttons.concat([
|
$menu.buttons = $menu.buttons.concat([
|
||||||
`<a class="btn" aria-label="button" aria-title="menu button" onclick="$menu.showAbout()"><i class="gg-info"></i> about</a><br>`
|
`<a class="btn" aria-label="button" aria-title="menu button" onclick="$menu.showAbout()"><i class="gg-info"></i> about</a><br>`
|
||||||
])
|
])
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ window.accessibility = (opts) => new Proxy({
|
||||||
.replace(/&/,' and ')
|
.replace(/&/,' and ')
|
||||||
.replace(/=/,' is ')
|
.replace(/=/,' is ')
|
||||||
}
|
}
|
||||||
|
if( str == this.speak.lastStr ) return // no duplicates
|
||||||
|
this.speak.lastStr = str
|
||||||
let speech = window.speechSynthesis
|
let speech = window.speechSynthesis
|
||||||
let utterance = new SpeechSynthesisUtterance( str )
|
let utterance = new SpeechSynthesisUtterance( str )
|
||||||
this.speak_voices = speech.getVoices().length
|
this.speak_voices = speech.getVoices().length
|
||||||
|
|
@ -52,6 +54,18 @@ window.accessibility = (opts) => new Proxy({
|
||||||
|
|
||||||
init(){
|
init(){
|
||||||
|
|
||||||
|
this
|
||||||
|
.speakArrowKeys()
|
||||||
|
.setupListeners()
|
||||||
|
.setupPersistance()
|
||||||
|
.setupHrefCycling()
|
||||||
|
.setupSpeechKillOnEscape()
|
||||||
|
|
||||||
|
setTimeout( () => this.initCommands(), 200 )
|
||||||
|
},
|
||||||
|
|
||||||
|
speakArrowKeys(){
|
||||||
|
// speak arrow keys
|
||||||
window.addEventListener('keydown', (e) => {
|
window.addEventListener('keydown', (e) => {
|
||||||
if( !this.speak_keyboard ) return
|
if( !this.speak_keyboard ) return
|
||||||
let k = e.key
|
let k = e.key
|
||||||
|
|
@ -63,6 +77,60 @@ window.accessibility = (opts) => new Proxy({
|
||||||
}
|
}
|
||||||
this.speak(k,{override:true})
|
this.speak(k,{override:true})
|
||||||
})
|
})
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
|
setupSpeechKillOnEscape(){
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if( e.key == "Escape" ){
|
||||||
|
this.speak("stop",{override:true})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
setupHrefCycling(){
|
||||||
|
// speak arrow keys
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if( e.key != 'Tab') return
|
||||||
|
let subScene = xrf.scene.getObjectByName( xrf.frag.pos.last )
|
||||||
|
if( !subScene ) subScene = xrf.scene
|
||||||
|
let cache = this.setupHrefCycling.cache = this.setupHrefCycling.cache || {current: 0}
|
||||||
|
let objects = []
|
||||||
|
subScene.traverse( (n) => (n.userData.href || n.userData['aria-description']) && objects.push(n) )
|
||||||
|
|
||||||
|
const highlight = (n) => {
|
||||||
|
if( this.helper){
|
||||||
|
if( this.helper.selected == n.uuid ) return // already selected
|
||||||
|
xrf.scene.remove(this.helper)
|
||||||
|
}
|
||||||
|
this.selected = n
|
||||||
|
this.helper = new THREE.BoxHelper( n, 0xFF00FF )
|
||||||
|
this.helper.computeLineDistances()
|
||||||
|
this.helper.material.linewidth = 8
|
||||||
|
this.helper.material.color = xrf.focusLine.material.color
|
||||||
|
this.helper.material.dashSize = xrf.focusLine.material.dashSize
|
||||||
|
this.helper.material.gapSize = xrf.focusLine.material.gapSize
|
||||||
|
this.helper.selected = n.uuid
|
||||||
|
xrf.scene.add(this.helper)
|
||||||
|
|
||||||
|
notify(`${n.userData['aria-description']||''}` + (n.userData.href ? `<br><b>name:</b> ${n.name}<br><b>link:</b> ${n.userData['href']}` :'') )
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure valid href
|
||||||
|
cache.current = cache.current % objects.length
|
||||||
|
highlight( objects[cache.current] )
|
||||||
|
console.log(objects[cache.current].userData.href)
|
||||||
|
|
||||||
|
// increment to next
|
||||||
|
cache.current = cache.current + 1
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
|
setupListeners(){
|
||||||
|
|
||||||
document.addEventListener('$menu:buttons:render', (e) => {
|
document.addEventListener('$menu:buttons:render', (e) => {
|
||||||
let $ = e.detail
|
let $ = e.detail
|
||||||
|
|
@ -102,8 +170,10 @@ window.accessibility = (opts) => new Proxy({
|
||||||
network.posName = opts.frag.pos.string
|
network.posName = opts.frag.pos.string
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
setTimeout( () => this.initCommands(), 200 )
|
setupPersistance(){
|
||||||
// auto-enable if previously enabled
|
// auto-enable if previously enabled
|
||||||
if( window.localStorage.getItem("accessibility") === 'true' || xrf.navigator.URI.XRF.accessible ){
|
if( window.localStorage.getItem("accessibility") === 'true' || xrf.navigator.URI.XRF.accessible ){
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
|
|
@ -111,11 +181,14 @@ window.accessibility = (opts) => new Proxy({
|
||||||
this.setFontSize()
|
this.setFontSize()
|
||||||
}, 100 )
|
}, 100 )
|
||||||
}
|
}
|
||||||
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
initCommands(){
|
initCommands(){
|
||||||
|
|
||||||
document.addEventListener('chat.command.help', (e) => {
|
document.addEventListener('chat.command.help', (e) => {
|
||||||
|
e.detail.message += `<br><b class="badge"><Escape></b> silence TTS `
|
||||||
|
e.detail.message += `<br><b class="badge"><Tab></b> cycle [href] buttons / silence TTS `
|
||||||
e.detail.message += `<br><b class="badge">/fontsize <number></b> set fontsize (default=14) `
|
e.detail.message += `<br><b class="badge">/fontsize <number></b> set fontsize (default=14) `
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
el: null,
|
el: null,
|
||||||
|
notify_links: true,
|
||||||
plugin: {},
|
plugin: {},
|
||||||
xrf,
|
xrf,
|
||||||
|
|
||||||
|
|
@ -92,7 +93,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
let instructions = AFRAME.utils.device.isMobile()
|
let instructions = AFRAME.utils.device.isMobile()
|
||||||
? "hold 2-3 fingers to move forward/backward"
|
? "hold 2-3 fingers to move forward/backward"
|
||||||
: "use WASD-keys and mouse-drag to move around"
|
: "use W A S D keys and mouse-drag to move around"
|
||||||
window.notify(instructions,{timeout:false})
|
window.notify(instructions,{timeout:false})
|
||||||
xrf.addEventListener('pos', (opts) => {
|
xrf.addEventListener('pos', (opts) => {
|
||||||
let pos = opts.frag.pos.string
|
let pos = opts.frag.pos.string
|
||||||
|
|
@ -103,7 +104,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
xrf.addEventListener('href', (data) => {
|
xrf.addEventListener('href', (data) => {
|
||||||
if( !data.selected ) return
|
if( !data.selected ) return
|
||||||
|
|
||||||
let html = `<b class="badge">${data.mesh.isSRC && !data.mesh.portal ? 'src' : 'href'}</b>${ data.xrf ? data.xrf.string : data.mesh.userData.src}<br>`
|
let html = this.notify_links ? `<b class="badge">${data.mesh.isSRC && !data.mesh.portal ? 'src' : 'href'}</b>${ data.xrf ? data.xrf.string : data.mesh.userData.src}<br>` : ''
|
||||||
let metadata = data.mesh.userData
|
let metadata = data.mesh.userData
|
||||||
let meta = xrf.Parser.getMetaData()
|
let meta = xrf.Parser.getMetaData()
|
||||||
|
|
||||||
|
|
@ -123,6 +124,7 @@ window.frontend = (opts) => new Proxy({
|
||||||
let transcript = xrf.sceneToTranscript(root,data.mesh)
|
let transcript = xrf.sceneToTranscript(root,data.mesh)
|
||||||
if( transcript.length ) html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
|
if( transcript.length ) html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
|
||||||
if (hasMeta && !data.mesh.portal && metadata.XRF.src ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
|
if (hasMeta && !data.mesh.portal && metadata.XRF.src ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
|
||||||
|
if( !html ) return
|
||||||
window.notify(html,{timeout: 7000 * (hasMeta ? 1.5 : 1) })
|
window.notify(html,{timeout: 7000 * (hasMeta ? 1.5 : 1) })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue