-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdom.js
137 lines (124 loc) · 4.34 KB
/
dom.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* ## [dom](com/dom.js)
*
* instances reactive DOM component from AFRAME component's `dom` metadata
*
* ```html
* <script>
* AFRAME.registerComponent('mycom',{
* init: function(){ this.data.foo = 1 },
* dom: {
* scale: 3,
* events: ['click'],
* html: (me) => `<div id="iconmenu">${me.data.foo}</div>`,
* css: (me) => `#iconmenu { display:block }`
* },
* event: {
* click: (e) => alert(e),
* foo: (e) => alert("I was updated!")
* }
* })
* </script>
*
* <a-entity mycom dom/>
* ```
*
* | property | type | example |
* |--------------|--------------------|----------------------------------------------------------------------------------------|
* | `com` | `array` of strings | <a-entity app="app/launcher.js; registers: https://foo.com/index.json, ./index.json"/> |
*
* | event | target | info |
* |--------------|-------------------------------------------------------------------------------------------------------------|
* | `DOMready` | self | fired when dom component (`this.dom`) is created |
*/
if( !AFRAME.components.dom ){
AFRAME.registerComponent('dom',{
init: function(){
Object.values(this.el.components)
.map( (c) => {
if( c.dom && c.attrName != "dom"){
this.dom = c.dom
this.com = c
}
})
if( !this.dom || !this.com){
return console.warn('dom.js did not find a .dom object inside component')
}
this
.ensureOverlay()
.addCSS()
.createReactiveDOMElement()
.assignUniqueID()
.scaleDOMvsXR()
.triggerKeyboardForInputs()
document.querySelector('#overlay').appendChild(this.el.dom)
this.el.emit('DOMready',{el: this.el.dom})
},
ensureOverlay: function(){
// ensure overlay
let overlay = document.querySelector('#overlay')
if( !overlay ){
overlay = document.createElement('div')
overlay.id = "overlay"
overlay.setAttribute('style','position:fixed;top:0px;left:0px;right:0px;bottom:0px;pointer-events:none')
document.body.appendChild(overlay)
document.head.innerHTML += `
<style type="text/css">#overlay * { pointer-events:all }</style>
`
// sceneEl.setAttribute("webxr","overlayElement:#overlay")
}
return this
},
reactify: function(el,data){
return new Proxy(data, {
get(me,k,v) {
return me[k]
},
set(me,k,v){
me[k] = v
el.emit(k,{el,k,v})
}
})
},
// creates el.dom (the 2D DOM object)
createReactiveDOMElement: function(){
this.el.dom = document.createElement('div')
this.el.dom.innerHTML = this.dom.html(this)
this.el.dom.className = this.dom.attrName
this.com.data = this.reactify( this.el, this.com.data )
this.el.dom = this.el.dom.children[0]
if( this.dom.events ){
this.dom.events.map( (e) => {
this.el.dom.addEventListener(e, (ev) => this.el.emit(e,ev) )
})
}
return this
},
assignUniqueID: function(){
// assign unique app id so it's easy to reference (by html-mesh component e.g.)
if( !this.el.uid ) this.el.uid = this.el.dom.id = '_'+String(Math.random()).substr(10)
return this
},
addCSS: function(){
if( this.dom.css && !document.head.querySelector(`style#${this.com.attrName}`) ){
document.head.innerHTML += `<style id="${this.com.attrName}">${this.dom.css(this)}</style>`
}
return this
},
scaleDOMvsXR: function(){
if( this.dom.scale ) this.el.setAttribute('scale',`${this.dom.scale} ${this.dom.scale} ${this.dom.scale}`)
return this
},
triggerKeyboardForInputs: function(){
// https://developer.oculus.com/documentation/web/webxr-keyboard ;
[...this.el.dom.querySelectorAll('[type=text]')].map( (input) => {
let triggerKeyboard = function(){
this.focus()
console.log("focus")
}
input.addEventListener('click', triggerKeyboard )
})
return this
},
})
}