Skip to content

Commit 94d3965

Browse files
fix: Properly mount DOMElement
DOMElements are components, therefore it should be able to instantiate them in an isolated fashion and then add them at a later point in time using `Node#addComponent`.
1 parent a5d7fd5 commit 94d3965

File tree

1 file changed

+67
-72
lines changed

1 file changed

+67
-72
lines changed

dom-renderables/DOMElement.js

Lines changed: 67 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var Size = require('../core/Size');
3636
*
3737
* @class DOMElement
3838
*
39-
* @param {Node} node The Node to which the `DOMElement`
39+
* @param {Node} [node] The Node to which the `DOMElement`
4040
* renderable should be attached to.
4141
* @param {Object} options Initial options used for instantiating
4242
* the Node.
@@ -53,54 +53,41 @@ var Size = require('../core/Size');
5353
* for DOM and WebGL layering. On by default.
5454
*/
5555
function DOMElement(node, options) {
56-
if (!node) throw new Error('DOMElement must be instantiated on a node');
56+
if (node && node.constructor === Object) {
57+
options = node;
58+
node = null;
59+
}
60+
61+
options = options || {};
5762

5863
this._changeQueue = [];
5964

6065
this._requestingUpdate = false;
6166
this._renderSized = false;
6267
this._requestRenderSize = false;
6368

64-
this._UIEvents = node.getUIEvents().slice(0);
65-
this._classes = ['famous-dom-element'];
69+
this._UIEvents = [];
70+
this._classes = ['famous-dom-element'].concat(options.classes);
6671
this._requestingEventListeners = [];
67-
this._styles = {};
6872

69-
this._attributes = {};
70-
this._content = '';
73+
this._properties = options.properties || {};
74+
this._attributes = options.attributes || {};
7175

72-
this._tagName = options && options.tagName ? options.tagName : 'div';
76+
if (options.id != null)
77+
this._attributes.id = options.id;
78+
79+
this._content = options.content || '';
80+
this._tagName = options.tagName || 'div';
7381
this._renderSize = [0, 0, 0];
7482

75-
this._node = node;
83+
this._cutout = options.cutout != null ? options.cutout : true;
7684

77-
if (node) node.addComponent(this);
85+
this._node = null;
86+
this._id = null;
7887

7988
this._callbacks = new CallbackStore();
8089

81-
this.setProperty('display', node.isShown() ? 'block' : 'none');
82-
this.onOpacityChange(node.getOpacity());
83-
84-
if (!options) return;
85-
86-
var i;
87-
var key;
88-
89-
if (options.classes)
90-
for (i = 0; i < options.classes.length; i++)
91-
this.addClass(options.classes[i]);
92-
93-
if (options.attributes)
94-
for (key in options.attributes)
95-
this.setAttribute(key, options.attributes[key]);
96-
97-
if (options.properties)
98-
for (key in options.properties)
99-
this.setProperty(key, options.properties[key]);
100-
101-
if (options.id) this.setId(options.id);
102-
if (options.content) this.setContent(options.content);
103-
if (options.cutout === false) this.setCutoutState(options.cutout);
90+
if (node) node.addComponent(this);
10491
}
10592

10693
/**
@@ -113,11 +100,12 @@ function DOMElement(node, options) {
113100
DOMElement.prototype.getValue = function getValue() {
114101
return {
115102
classes: this._classes,
116-
styles: this._styles,
103+
styles: this._properties,
117104
attributes: this._attributes,
118105
content: this._content,
119106
id: this._attributes.id,
120-
tagName: this._tagName
107+
tagName: this._tagName,
108+
cutout: this._cutout
121109
};
122110
};
123111

@@ -169,11 +157,16 @@ DOMElement.prototype.onUpdate = function onUpdate () {
169157
DOMElement.prototype.onMount = function onMount(node, id) {
170158
this._node = node;
171159
this._id = id;
160+
172161
this._UIEvents = node.getUIEvents().slice(0);
162+
173163
TransformSystem.makeBreakPointAt(node.getLocation());
164+
174165
this.onSizeModeChange.apply(this, node.getSizeMode());
175-
this.draw();
176166
this.setAttribute('data-fa-path', node.getLocation());
167+
this.onOpacityChange(node.getOpacity());
168+
169+
this._draw();
177170
};
178171

179172
/**
@@ -219,24 +212,6 @@ DOMElement.prototype.onHide = function onHide() {
219212
this.setProperty('display', 'none');
220213
};
221214

222-
/**
223-
* Enables or disables WebGL 'cutout' for this element, which affects
224-
* how the element is layered with WebGL objects in the scene.
225-
*
226-
* @method
227-
*
228-
* @param {Boolean} usesCutout The presence of a WebGL 'cutout' for this element.
229-
*
230-
* @return {DOMElement} this
231-
*/
232-
DOMElement.prototype.setCutoutState = function setCutoutState (usesCutout) {
233-
if (this._initialized)
234-
this._changeQueue.push(Commands.GL_CUTOUT_STATE, usesCutout);
235-
236-
if (!this._requestingUpdate) this._requestUpdate();
237-
return this;
238-
};
239-
240215
/**
241216
* Method to be invoked by the node as soon as the transform matrix associated
242217
* with the node changes. The DOMElement will react to transform changes by sending
@@ -461,10 +436,11 @@ DOMElement.prototype._requestUpdate = function _requestUpdate() {
461436
* or reallocates a new Element in the actual DOM hierarchy.
462437
*
463438
* @method
439+
* @private
464440
*
465441
* @return {undefined} undefined
466442
*/
467-
DOMElement.prototype.init = function init () {
443+
DOMElement.prototype._init = function _init () {
468444
this._changeQueue.push(Commands.INIT_DOM, this._tagName);
469445
this._initialized = true;
470446
this.onTransformChange(TransformSystem.get(this._node.getLocation()));
@@ -570,7 +546,7 @@ DOMElement.prototype.setAttribute = function setAttribute (name, value) {
570546
};
571547

572548
/**
573-
* Sets a CSS property
549+
* Sets a CSS property.
574550
*
575551
* @chainable
576552
*
@@ -580,8 +556,8 @@ DOMElement.prototype.setAttribute = function setAttribute (name, value) {
580556
* @return {DOMElement} this
581557
*/
582558
DOMElement.prototype.setProperty = function setProperty (name, value) {
583-
if (this._styles[name] !== value || this._inDraw) {
584-
this._styles[name] = value;
559+
if (this._properties[name] !== value || this._inDraw) {
560+
this._properties[name] = value;
585561
if (this._initialized) this._changeQueue.push(Commands.CHANGE_PROPERTY, name, value);
586562
if (!this._requestingUpdate) this._requestUpdate();
587563
if (this._renderSized) this._requestRenderSize = true;
@@ -590,6 +566,26 @@ DOMElement.prototype.setProperty = function setProperty (name, value) {
590566
return this;
591567
};
592568

569+
/**
570+
* Enables or disables WebGL 'cutout' for this element, which affects
571+
* how the element is layered with WebGL objects in the scene.
572+
*
573+
* @method
574+
*
575+
* @param {Boolean} usesCutout The presence of a WebGL 'cutout' for this element.
576+
*
577+
* @return {DOMElement} this
578+
*/
579+
DOMElement.prototype.setCutoutState = function setCutoutState (usesCutout) {
580+
if (this._cutout !== usesCutout || this._inDraw) {
581+
this._cutout = usesCutout;
582+
if (this._initialized) this._changeQueue.push(Commands.GL_CUTOUT_STATE, usesCutout);
583+
if (!this._requestingUpdate) this._requestUpdate();
584+
}
585+
586+
return this;
587+
};
588+
593589
/**
594590
* Sets the content of the DOMElement. This is using `innerHTML`, escaping user
595591
* generated content is therefore essential for security purposes.
@@ -660,27 +656,26 @@ DOMElement.prototype.onReceive = function onReceive (event, payload) {
660656
*
661657
* @return {undefined} undefined
662658
*/
663-
DOMElement.prototype.draw = function draw() {
664-
var key;
665-
var i;
666-
var len;
667-
659+
DOMElement.prototype._draw = function _draw() {
668660
this._inDraw = true;
669661

670-
this.init();
662+
this._init();
663+
664+
var i;
665+
var len;
666+
var key;
671667

672-
for (i = 0, len = this._classes.length ; i < len ; i++)
668+
for (i = 0, len = this._classes.length; i < len; i++)
673669
this.addClass(this._classes[i]);
674670

675-
if (this._content) this.setContent(this._content);
671+
for (key in this._attributes)
672+
this.setAttribute(key, this._attributes[key]);
676673

677-
for (key in this._styles)
678-
if (this._styles[key] != null)
679-
this.setProperty(key, this._styles[key]);
674+
for (key in this._properties)
675+
this.setProperty(key, this._properties[key]);
680676

681-
for (key in this._attributes)
682-
if (this._attributes[key] != null)
683-
this.setAttribute(key, this._attributes[key]);
677+
this.setContent(this._content);
678+
this.setCutoutState(this._cutout);
684679

685680
for (i = 0, len = this._UIEvents.length ; i < len ; i++)
686681
this.onAddUIEvent(this._UIEvents[i]);

0 commit comments

Comments
 (0)