Skip to content

Commit 021f972

Browse files
committed
Move A-Frame to customElementsV1 API (fix #4262)
1 parent 6858ed6 commit 021f972

File tree

14 files changed

+1890
-2253
lines changed

14 files changed

+1890
-2253
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"custom-event-polyfill": "^1.0.6",
4040
"debug": "ngokevin/debug#noTimestamp",
4141
"deep-assign": "^2.0.0",
42-
"document-register-element": "dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90",
42+
"@ungap/custom-elements": "^1.1.0",
4343
"load-bmfont": "^1.2.3",
4444
"object-assign": "^4.0.1",
4545
"present": "0.0.6",

src/core/a-assets.js

Lines changed: 114 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
var ANode = require('./a-node');
1+
/* global customElements */
2+
var ANode = require('./a-node').ANode;
23
var bind = require('../utils/bind');
34
var debug = require('../utils/debug');
4-
var registerElement = require('./a-register-element').registerElement;
55
var THREE = require('../lib/three');
66

77
var fileLoader = new THREE.FileLoader();
@@ -10,126 +10,129 @@ var warn = debug('core:a-assets:warn');
1010
/**
1111
* Asset management system. Handles blocking on asset loading.
1212
*/
13-
module.exports = registerElement('a-assets', {
14-
prototype: Object.create(ANode.prototype, {
15-
createdCallback: {
16-
value: function () {
17-
this.isAssets = true;
18-
this.fileLoader = fileLoader;
19-
this.timeout = null;
20-
}
21-
},
22-
23-
attachedCallback: {
24-
value: function () {
25-
var self = this;
26-
var i;
27-
var loaded = [];
28-
var mediaEl;
29-
var mediaEls;
30-
var imgEl;
31-
var imgEls;
32-
var timeout;
33-
34-
if (!this.parentNode.isScene) {
35-
throw new Error('<a-assets> must be a child of a <a-scene>.');
36-
}
13+
class AAssets extends ANode {
14+
constructor () {
15+
super();
16+
this.isAssets = true;
17+
this.fileLoader = fileLoader;
18+
this.timeout = null;
19+
}
3720

38-
// Wait for <img>s.
39-
imgEls = this.querySelectorAll('img');
40-
for (i = 0; i < imgEls.length; i++) {
41-
imgEl = fixUpMediaElement(imgEls[i]);
42-
loaded.push(new Promise(function (resolve, reject) {
43-
// Set in cache because we won't be needing to call three.js loader if we have.
44-
// a loaded media element.
45-
THREE.Cache.add(imgEls[i].getAttribute('src'), imgEl);
46-
imgEl.onload = resolve;
47-
imgEl.onerror = reject;
48-
}));
49-
}
21+
connectedCallback () {
22+
// Defer if DOM is not ready.
23+
if (document.readyState === 'loading') {
24+
document.addEventListener('DOMContentLoaded', this.connectedCallback.bind(this));
25+
return;
26+
}
5027

51-
// Wait for <audio>s and <video>s.
52-
mediaEls = this.querySelectorAll('audio, video');
53-
for (i = 0; i < mediaEls.length; i++) {
54-
mediaEl = fixUpMediaElement(mediaEls[i]);
55-
if (!mediaEl.src && !mediaEl.srcObject) {
56-
warn('Audio/video asset has neither `src` nor `srcObject` attributes.');
57-
}
58-
loaded.push(mediaElementLoaded(mediaEl));
59-
}
28+
this.doConnectedCallback();
29+
}
6030

61-
// Trigger loaded for scene to start rendering.
62-
Promise.allSettled(loaded).then(bind(this.load, this));
63-
64-
// Timeout to start loading anyways.
65-
timeout = parseInt(this.getAttribute('timeout'), 10) || 3000;
66-
this.timeout = setTimeout(function () {
67-
if (self.hasLoaded) { return; }
68-
warn('Asset loading timed out in ', timeout, 'ms');
69-
self.emit('timeout');
70-
self.load();
71-
}, timeout);
72-
}
73-
},
31+
doConnectedCallback () {
32+
var self = this;
33+
var i;
34+
var loaded = [];
35+
var mediaEl;
36+
var mediaEls;
37+
var imgEl;
38+
var imgEls;
39+
var timeout;
7440

75-
detachedCallback: {
76-
value: function () {
77-
if (this.timeout) { clearTimeout(this.timeout); }
78-
}
79-
},
41+
super.connectedCallback();
42+
43+
if (!this.parentNode.isScene) {
44+
throw new Error('<a-assets> must be a child of a <a-scene>.');
45+
}
46+
47+
// Wait for <img>s.
48+
imgEls = this.querySelectorAll('img');
49+
for (i = 0; i < imgEls.length; i++) {
50+
imgEl = fixUpMediaElement(imgEls[i]);
51+
loaded.push(new Promise(function (resolve, reject) {
52+
// Set in cache because we won't be needing to call three.js loader if we have.
53+
// a loaded media element.
54+
THREE.Cache.add(imgEls[i].getAttribute('src'), imgEl);
55+
imgEl.onload = resolve;
56+
imgEl.onerror = reject;
57+
}));
58+
}
8059

81-
load: {
82-
value: function () {
83-
ANode.prototype.load.call(this, null, function waitOnFilter (el) {
84-
return el.isAssetItem && el.hasAttribute('src');
85-
});
60+
// Wait for <audio>s and <video>s.
61+
mediaEls = this.querySelectorAll('audio, video');
62+
for (i = 0; i < mediaEls.length; i++) {
63+
mediaEl = fixUpMediaElement(mediaEls[i]);
64+
if (!mediaEl.src && !mediaEl.srcObject) {
65+
warn('Audio/video asset has neither `src` nor `srcObject` attributes.');
8666
}
67+
loaded.push(mediaElementLoaded(mediaEl));
8768
}
88-
})
89-
});
69+
70+
// Trigger loaded for scene to start rendering.
71+
Promise.allSettled(loaded).then(bind(this.load, this));
72+
73+
// Timeout to start loading anyways.
74+
timeout = parseInt(this.getAttribute('timeout'), 10) || 3000;
75+
this.timeout = setTimeout(function () {
76+
if (self.hasLoaded) { return; }
77+
warn('Asset loading timed out in ', timeout, 'ms');
78+
self.emit('timeout');
79+
self.load();
80+
}, timeout);
81+
}
82+
83+
disconnectedCallback () {
84+
super.disconnectedCallback();
85+
if (this.timeout) { clearTimeout(this.timeout); }
86+
}
87+
88+
load () {
89+
super.load.call(this, null, function waitOnFilter (el) {
90+
return el.isAssetItem && el.hasAttribute('src');
91+
});
92+
}
93+
}
94+
95+
customElements.define('a-assets', AAssets);
9096

9197
/**
9298
* Preload using XHRLoader for any type of asset.
9399
*/
94-
registerElement('a-asset-item', {
95-
prototype: Object.create(ANode.prototype, {
96-
createdCallback: {
97-
value: function () {
98-
this.data = null;
99-
this.isAssetItem = true;
100-
}
101-
},
102-
103-
attachedCallback: {
104-
value: function () {
105-
var self = this;
106-
var src = this.getAttribute('src');
107-
fileLoader.setResponseType(
108-
this.getAttribute('response-type') || inferResponseType(src));
109-
fileLoader.load(src, function handleOnLoad (response) {
110-
self.data = response;
111-
/*
112-
Workaround for a Chrome bug. If another XHR is sent to the same url before the
113-
previous one closes, the second request never finishes.
114-
setTimeout finishes the first request and lets the logic triggered by load open
115-
subsequent requests.
116-
setTimeout can be removed once the fix for the bug below ships:
117-
https://bugs.chromium.org/p/chromium/issues/detail?id=633696&q=component%3ABlink%3ENetwork%3EXHR%20&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified
118-
*/
119-
setTimeout(function load () { ANode.prototype.load.call(self); });
120-
}, function handleOnProgress (xhr) {
121-
self.emit('progress', {
122-
loadedBytes: xhr.loaded,
123-
totalBytes: xhr.total,
124-
xhr: xhr
125-
});
126-
}, function handleOnError (xhr) {
127-
self.emit('error', {xhr: xhr});
128-
});
129-
}
130-
}
131-
})
132-
});
100+
class AAssetItem extends ANode {
101+
constructor () {
102+
super();
103+
this.data = null;
104+
this.isAssetItem = true;
105+
}
106+
107+
connectedCallback () {
108+
var self = this;
109+
var src = this.getAttribute('src');
110+
fileLoader.setResponseType(
111+
this.getAttribute('response-type') || inferResponseType(src));
112+
fileLoader.load(src, function handleOnLoad (response) {
113+
self.data = response;
114+
/*
115+
Workaround for a Chrome bug. If another XHR is sent to the same url before the
116+
previous one closes, the second request never finishes.
117+
setTimeout finishes the first request and lets the logic triggered by load open
118+
subsequent requests.
119+
setTimeout can be removed once the fix for the bug below ships:
120+
https://bugs.chromium.org/p/chromium/issues/detail?id=633696&q=component%3ABlink%3ENetwork%3EXHR%20&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified
121+
*/
122+
setTimeout(function load () { ANode.prototype.load.call(self); });
123+
}, function handleOnProgress (xhr) {
124+
self.emit('progress', {
125+
loadedBytes: xhr.loaded,
126+
totalBytes: xhr.total,
127+
xhr: xhr
128+
});
129+
}, function handleOnError (xhr) {
130+
self.emit('error', {xhr: xhr});
131+
});
132+
}
133+
}
134+
135+
customElements.define('a-asset-item', AAssetItem);
133136

134137
/**
135138
* Create a Promise that resolves once the media element has finished buffering.

src/core/a-cubemap.js

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,45 @@
1+
/* global customElements, HTMLElement */
12
var debug = require('../utils/debug');
2-
var registerElement = require('./a-register-element').registerElement;
33

44
var warn = debug('core:cubemap:warn');
55

66
/**
77
* Cubemap element that handles validation and exposes list of URLs.
88
* Does not listen to updates.
99
*/
10-
module.exports = registerElement('a-cubemap', {
11-
prototype: Object.create(window.HTMLElement.prototype, {
12-
/**
13-
* Calculates this.srcs.
14-
*/
15-
attachedCallback: {
16-
value: function () {
17-
this.srcs = this.validate();
18-
},
19-
writable: window.debug
20-
},
10+
class ACubeMap extends HTMLElement {
11+
/**
12+
* Calculates this.srcs.
13+
*/
14+
constructor (self) {
15+
self = super(self);
16+
self.srcs = self.validate();
17+
return self;
18+
}
2119

22-
/**
23-
* Checks for exactly six elements with [src].
24-
* Does not check explicitly for <img>s in case user does not want
25-
* prefetching.
26-
*
27-
* @returns {Array|null} - six URLs if valid, else null.
28-
*/
29-
validate: {
30-
value: function () {
31-
var elements = this.querySelectorAll('[src]');
32-
var i;
33-
var srcs = [];
34-
if (elements.length === 6) {
35-
for (i = 0; i < elements.length; i++) {
36-
srcs.push(elements[i].getAttribute('src'));
37-
}
38-
return srcs;
39-
}
40-
// Else if there are not six elements, throw a warning.
41-
warn(
42-
'<a-cubemap> did not contain exactly six elements each with a ' +
43-
'`src` attribute.');
44-
},
45-
writable: window.debug
20+
/**
21+
* Checks for exactly six elements with [src].
22+
* Does not check explicitly for <img>s in case user does not want
23+
* prefetching.
24+
*
25+
* @returns {Array|null} - six URLs if valid, else null.
26+
*/
27+
validate () {
28+
var elements = this.querySelectorAll('[src]');
29+
var i;
30+
var srcs = [];
31+
if (elements.length === 6) {
32+
for (i = 0; i < elements.length; i++) {
33+
srcs.push(elements[i].getAttribute('src'));
34+
}
35+
return srcs;
4636
}
47-
})
48-
});
37+
// Else if there are not six elements, throw a warning.
38+
warn(
39+
'<a-cubemap> did not contain exactly six elements each with a ' +
40+
'`src` attribute.');
41+
}
42+
}
43+
44+
customElements.define('a-cubemap', ACubeMap);
45+

0 commit comments

Comments
 (0)