forked from phaserjs/phaser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDOMElement.js
More file actions
941 lines (847 loc) · 31.8 KB
/
Copy pathDOMElement.js
File metadata and controls
941 lines (847 loc) · 31.8 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../../utils/Class');
var Components = require('../components');
var DOMElementRender = require('./DOMElementRender');
var GameObject = require('../GameObject');
var IsPlainObject = require('../../utils/object/IsPlainObject');
var RemoveFromDOM = require('../../dom/RemoveFromDOM');
var Vector4 = require('../../math/Vector4');
/**
* @classdesc
* DOM Element Game Objects are a way to control and manipulate HTML Elements over the top of your game.
*
* In order for DOM Elements to display you have to enable them by adding the following to your game
* configuration object:
*
* ```javascript
* dom {
* createContainer: true
* }
* ```
*
* When this is added, Phaser will automatically create a DOM Container div that is positioned over the top
* of the game canvas. This div is sized to match the canvas, and if the canvas size changes, as a result of
* settings within the Scale Manager, the dom container is resized accordingly.
*
* You can create a DOM Element by either passing in DOMStrings, or by passing in a reference to an existing
* Element that you wish to be placed under the control of Phaser. For example:
*
* ```javascript
* this.add.dom(x, y, 'div', 'background-color: lime; width: 220px; height: 100px; font: 48px Arial', 'Phaser');
* ```
*
* The above code will insert a div element into the DOM Container at the given x/y coordinate. The DOMString in
* the 4th argument sets the initial CSS style of the div and the final argument is the inner text. In this case,
* it will create a lime colored div that is 220px by 100px in size with the text Phaser in it, in an Arial font.
*
* You should nearly always, without exception, use explicitly sized HTML Elements, in order to fully control
* alignment and positioning of the elements next to regular game content.
*
* Rather than specify the CSS and HTML directly you can use the `load.html` File Loader to load it into the
* cache and then use the `createFromCache` method instead. You can also use `createFromHTML` and various other
* methods available in this class to help construct your elements.
*
* Once the element has been created you can then control it like you would any other Game Object. You can set its
* position, scale, rotation, alpha and other properties. It will move as the main Scene Camera moves and be clipped
* at the edge of the canvas. It's important to remember some limitations of DOM Elements: The obvious one is that
* they appear above or below your game canvas. You cannot blend them into the display list, meaning you cannot have
* a DOM Element, then a Sprite, then another DOM Element behind it.
*
* They also cannot be enabled for input. To do that, you have to use the `addListener` method to add native event
* listeners directly. The final limitation is to do with cameras. The DOM Container is sized to match the game canvas
* entirely and clipped accordingly. DOM Elements respect camera scrolling and scrollFactor settings, but if you
* change the size of the camera so it no longer matches the size of the canvas, they won't be clipped accordingly.
*
* Also, all DOM Elements are inserted into the same DOM Container, regardless of which Scene they are created in.
*
* DOM Elements are a powerful way to align native HTML with your Phaser Game Objects. For example, you can insert
* a login form for a multiplayer game directly into your title screen. Or a text input box for a highscore table.
* Or a banner ad from a 3rd party service. Or perhaps you'd like to use them for high resolution text display and
* UI. The choice is up to you, just remember that you're dealing with standard HTML and CSS floating over the top
* of your game, and should treat it accordingly.
*
* @class DOMElement
* @extends Phaser.GameObjects.GameObject
* @memberof Phaser.GameObjects
* @constructor
* @since 3.17.0
*
* @extends Phaser.GameObjects.Components.Alpha
* @extends Phaser.GameObjects.Components.BlendMode
* @extends Phaser.GameObjects.Components.Depth
* @extends Phaser.GameObjects.Components.Origin
* @extends Phaser.GameObjects.Components.ScrollFactor
* @extends Phaser.GameObjects.Components.Transform
* @extends Phaser.GameObjects.Components.Visible
*
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
* @param {number} [x=0] - The horizontal position of this DOM Element in the world.
* @param {number} [y=0] - The vertical position of this DOM Element in the world.
* @param {(Element|string)} [element] - An existing DOM element, or a string. If a string starting with a # it will do a `getElementById` look-up on the string (minus the hash). Without a hash, it represents the type of element to create, i.e. 'div'.
* @param {(string|any)} [style] - If a string, will be set directly as the elements `style` property value. If a plain object, will be iterated and the values transferred. In both cases the values replacing whatever CSS styles may have been previously set.
* @param {string} [innerText] - If given, will be set directly as the elements `innerText` property value, replacing whatever was there before.
*/
var DOMElement = new Class({
Extends: GameObject,
Mixins: [
Components.Alpha,
Components.BlendMode,
Components.Depth,
Components.Origin,
Components.ScrollFactor,
Components.Transform,
Components.Visible,
DOMElementRender
],
initialize:
function DOMElement (scene, x, y, element, style, innerText)
{
GameObject.call(this, scene, 'DOMElement');
/**
* A reference to the parent DOM Container that the Game instance created when it started.
*
* @name Phaser.GameObjects.DOMElement#parent
* @type {Element}
* @since 3.17.0
*/
this.parent = scene.sys.game.domContainer;
/**
* A reference to the HTML Cache.
*
* @name Phaser.GameObjects.DOMElement#cache
* @type {Phaser.Cache.BaseCache}
* @since 3.17.0
*/
this.cache = scene.sys.cache.html;
/**
* The actual DOM Element that this Game Object is bound to. For example, if you've created a `<div>`
* then this property is a direct reference to that element within the dom.
*
* @name Phaser.GameObjects.DOMElement#node
* @type {Element}
* @since 3.17.0
*/
this.node;
/**
* By default a DOM Element will have its transform, display, opacity, zIndex and blend mode properties
* updated when its rendered. If, for some reason, you don't want any of these changed other than the
* CSS transform, then set this flag to `true`. When `true` only the CSS Transform is applied and it's
* up to you to keep track of and set the other properties as required.
*
* This can be handy if, for example, you've a nested DOM Element and you don't want the opacity to be
* picked-up by any of its children.
*
* @name Phaser.GameObjects.DOMElement#transformOnly
* @type {boolean}
* @since 3.17.0
*/
this.transformOnly = false;
/**
* The angle, in radians, by which to skew the DOM Element on the horizontal axis.
*
* https://developer.mozilla.org/en-US/docs/Web/CSS/transform
*
* @name Phaser.GameObjects.DOMElement#skewX
* @type {number}
* @since 3.17.0
*/
this.skewX = 0;
/**
* The angle, in radians, by which to skew the DOM Element on the vertical axis.
*
* https://developer.mozilla.org/en-US/docs/Web/CSS/transform
*
* @name Phaser.GameObjects.DOMElement#skewY
* @type {number}
* @since 3.17.0
*/
this.skewY = 0;
/**
* A Vector4 that contains the 3D rotation of this DOM Element around a fixed axis in 3D space.
*
* All values in the Vector4 are treated as degrees, unless the `rotate3dAngle` property is changed.
*
* For more details see the following MDN page:
*
* https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d
*
* @name Phaser.GameObjects.DOMElement#rotate3d
* @type {Phaser.Math.Vector4}
* @since 3.17.0
*/
this.rotate3d = new Vector4();
/**
* The unit that represents the 3D rotation values. By default this is `deg` for degrees, but can
* be changed to any supported unit. See this page for further details:
*
* https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d
*
* @name Phaser.GameObjects.DOMElement#rotate3dAngle
* @type {string}
* @since 3.17.0
*/
this.rotate3dAngle = 'deg';
/**
* The native (un-scaled) width of this Game Object.
*
* For a DOM Element this property is read-only.
*
* The property `displayWidth` holds the computed bounds of this DOM Element, factoring in scaling.
*
* @name Phaser.GameObjects.DOMElement#width
* @type {number}
* @readonly
* @since 3.17.0
*/
this.width = 0;
/**
* The native (un-scaled) height of this Game Object.
*
* For a DOM Element this property is read-only.
*
* The property `displayHeight` holds the computed bounds of this DOM Element, factoring in scaling.
*
* @name Phaser.GameObjects.DOMElement#height
* @type {number}
* @readonly
* @since 3.17.0
*/
this.height = 0;
/**
* The computed display width of this Game Object, based on the `getBoundingClientRect` DOM call.
*
* The property `width` holds the un-scaled width of this DOM Element.
*
* @name Phaser.GameObjects.DOMElement#displayWidth
* @type {number}
* @readonly
* @since 3.17.0
*/
this.displayWidth = 0;
/**
* The computed display height of this Game Object, based on the `getBoundingClientRect` DOM call.
*
* The property `height` holds the un-scaled height of this DOM Element.
*
* @name Phaser.GameObjects.DOMElement#displayHeight
* @type {number}
* @readonly
* @since 3.17.0
*/
this.displayHeight = 0;
/**
* Internal native event handler.
*
* @name Phaser.GameObjects.DOMElement#handler
* @type {number}
* @private
* @since 3.17.0
*/
this.handler = this.dispatchNativeEvent.bind(this);
this.setPosition(x, y);
if (typeof element === 'string')
{
// hash?
if (element[0] === '#')
{
this.setElement(element.substr(1), style, innerText);
}
else
{
this.createElement(element, style, innerText);
}
}
else if (element)
{
this.setElement(element, style, innerText);
}
},
/**
* Sets the horizontal and vertical skew values of this DOM Element.
*
* For more information see: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
*
* @method Phaser.GameObjects.DOMElement#setSkew
* @since 3.17.0
*
* @param {number} [x=0] - The angle, in radians, by which to skew the DOM Element on the horizontal axis.
* @param {number} [y=x] - The angle, in radians, by which to skew the DOM Element on the vertical axis.
*
* @return {this} This DOM Element instance.
*/
setSkew: function (x, y)
{
if (x === undefined) { x = 0; }
if (y === undefined) { y = x; }
this.skewX = x;
this.skewY = y;
return this;
},
/**
* Sets the perspective CSS property of the _parent DOM Container_. This determines the distance between the z=0
* plane and the user in order to give a 3D-positioned element some perspective. Each 3D element with
* z > 0 becomes larger; each 3D-element with z < 0 becomes smaller. The strength of the effect is determined
* by the value of this property.
*
* For more information see: https://developer.mozilla.org/en-US/docs/Web/CSS/perspective
*
* **Changing this value changes it globally for all DOM Elements, as they all share the same parent container.**
*
* @method Phaser.GameObjects.DOMElement#setPerspective
* @since 3.17.0
*
* @param {number} value - The perspective value, in pixels, that determines the distance between the z plane and the user.
*
* @return {this} This DOM Element instance.
*/
setPerspective: function (value)
{
this.parent.style.perspective = value + 'px';
return this;
},
/**
* The perspective CSS property value of the _parent DOM Container_. This determines the distance between the z=0
* plane and the user in order to give a 3D-positioned element some perspective. Each 3D element with
* z > 0 becomes larger; each 3D-element with z < 0 becomes smaller. The strength of the effect is determined
* by the value of this property.
*
* For more information see: https://developer.mozilla.org/en-US/docs/Web/CSS/perspective
*
* **Changing this value changes it globally for all DOM Elements, as they all share the same parent container.**
*
* @name Phaser.GameObjects.DOMElement#perspective
* @type {number}
* @since 3.17.0
*/
perspective: {
get: function ()
{
return parseFloat(this.parent.style.perspective);
},
set: function (value)
{
this.parent.style.perspective = value + 'px';
}
},
/**
* Adds one or more native DOM event listeners onto the underlying Element of this Game Object.
* The event is then dispatched via this Game Objects standard event emitter.
*
* For example:
*
* ```javascript
* var div = this.add.dom(x, y, element);
*
* div.addListener('click');
*
* div.on('click', handler);
* ```
*
* @method Phaser.GameObjects.DOMElement#addListener
* @since 3.17.0
*
* @param {string} events - The DOM event/s to listen for. You can specify multiple events by separating them with spaces.
*
* @return {this} This DOM Element instance.
*/
addListener: function (events)
{
if (this.node)
{
events = events.split(' ');
for (var i = 0; i < events.length; i++)
{
this.node.addEventListener(events[i], this.handler, false);
}
}
return this;
},
/**
* Removes one or more native DOM event listeners from the underlying Element of this Game Object.
*
* @method Phaser.GameObjects.DOMElement#removeListener
* @since 3.17.0
*
* @param {string} events - The DOM event/s to stop listening for. You can specify multiple events by separating them with spaces.
*
* @return {this} This DOM Element instance.
*/
removeListener: function (events)
{
if (this.node)
{
events = events.split(' ');
for (var i = 0; i < events.length; i++)
{
this.node.removeEventListener(events[i], this.handler);
}
}
return this;
},
/**
* Internal event proxy to dispatch native DOM Events via this Game Object.
*
* @method Phaser.GameObjects.DOMElement#dispatchNativeEvent
* @private
* @since 3.17.0
*
* @param {any} event - The native DOM event.
*/
dispatchNativeEvent: function (event)
{
this.emit(event.type, event);
},
/**
* Creates a native DOM Element, adds it to the parent DOM Container and then binds it to this Game Object,
* so you can control it. The `tagName` should be a string and is passed to `document.createElement`:
*
* ```javascript
* this.add.dom().createElement('div');
* ```
*
* For more details on acceptable tag names see: https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
*
* You can also pass in a DOMString or style object to set the CSS on the created element, and an optional `innerText`
* value as well. Here is an example of a DOMString:
*
* ```javascript
* this.add.dom().createElement('div', 'background-color: lime; width: 220px; height: 100px; font: 48px Arial', 'Phaser');
* ```
*
* And using a style object:
*
* ```javascript
* var style = {
* 'background-color': 'lime';
* 'width': '200px';
* 'height': '100px';
* 'font': '48px Arial';
* };
*
* this.add.dom().createElement('div', style, 'Phaser');
* ```
*
* If this Game Object already has an Element, it is removed from the DOM entirely first.
* Any event listeners you may have previously created will need to be re-created after this call.
*
* @method Phaser.GameObjects.DOMElement#createElement
* @since 3.17.0
*
* @param {string} tagName - A string that specifies the type of element to be created. The nodeName of the created element is initialized with the value of tagName. Don't use qualified names (like "html:a") with this method.
* @param {(string|any)} [style] - Either a DOMString that holds the CSS styles to be applied to the created element, or an object the styles will be ready from.
* @param {string} [innerText] - A DOMString that holds the text that will be set as the innerText of the created element.
*
* @return {this} This DOM Element instance.
*/
createElement: function (tagName, style, innerText)
{
return this.setElement(document.createElement(tagName), style, innerText);
},
/**
* Binds a new DOM Element to this Game Object. If this Game Object already has an Element it is removed from the DOM
* entirely first. Any event listeners you may have previously created will need to be re-created on the new element.
*
* The `element` argument you pass to this method can be either a string tagName:
*
* ```javascript
* <h1 id="heading">Phaser</h1>
*
* this.add.dom().setElement('heading');
* ```
*
* Or a reference to an Element instance:
*
* ```javascript
* <h1 id="heading">Phaser</h1>
*
* var h1 = document.getElementById('heading');
*
* this.add.dom().setElement(h1);
* ```
*
* You can also pass in a DOMString or style object to set the CSS on the created element, and an optional `innerText`
* value as well. Here is an example of a DOMString:
*
* ```javascript
* this.add.dom().setElement(h1, 'background-color: lime; width: 220px; height: 100px; font: 48px Arial', 'Phaser');
* ```
*
* And using a style object:
*
* ```javascript
* var style = {
* 'background-color': 'lime';
* 'width': '200px';
* 'height': '100px';
* 'font': '48px Arial';
* };
*
* this.add.dom().setElement(h1, style, 'Phaser');
* ```
*
* @method Phaser.GameObjects.DOMElement#setElement
* @since 3.17.0
*
* @param {(string|Element)} element - If a string it is passed to `getElementById()`, or it should be a reference to an existing Element.
* @param {(string|any)} [style] - Either a DOMString that holds the CSS styles to be applied to the created element, or an object the styles will be ready from.
* @param {string} [innerText] - A DOMString that holds the text that will be set as the innerText of the created element.
*
* @return {this} This DOM Element instance.
*/
setElement: function (element, style, innerText)
{
// Already got an element? Remove it first
this.removeElement();
var target;
if (typeof element === 'string')
{
// hash?
if (element[0] === '#')
{
element = element.substr(1);
}
target = document.getElementById(element);
}
else if (typeof element === 'object' && element.nodeType === 1)
{
target = element;
}
if (!target)
{
return this;
}
this.node = target;
// style can be empty, a string or a plain object
if (style && IsPlainObject(style))
{
for (var key in style)
{
target.style[key] = style[key];
}
}
else if (typeof style === 'string')
{
target.style = style;
}
// Add / Override the values we need
target.style.zIndex = '0';
target.style.display = 'inline';
target.style.position = 'absolute';
// Node handler
target.phaser = this;
if (this.parent)
{
this.parent.appendChild(target);
}
// InnerText
if (innerText)
{
target.innerText = innerText;
}
return this.updateSize();
},
/**
* Takes a block of html from the HTML Cache, that has previously been preloaded into the game, and then
* creates a DOM Element from it. The loaded HTML is set as the `innerHTML` property of the created
* element.
*
* Assume the following html is stored in a file called `loginform.html`:
*
* ```html
* <input type="text" name="nameField" placeholder="Enter your name" style="font-size: 32px">
* <input type="button" name="playButton" value="Let's Play" style="font-size: 32px">
* ```
*
* Which is loaded into your game using the cache key 'login':
*
* ```javascript
* this.load.html('login', 'assets/loginform.html');
* ```
*
* You can create a DOM Element from it using the cache key:
*
* ```javascript
* this.add.dom().createFromCache('login');
* ```
*
* The optional `elementType` argument controls the container that is created, into which the loaded html is inserted.
* The default is a plain `div` object, but any valid tagName can be given.
*
* If this Game Object already has an Element, it is removed from the DOM entirely first.
* Any event listeners you may have previously created will need to be re-created after this call.
*
* @method Phaser.GameObjects.DOMElement#createFromCache
* @since 3.17.0
*
* @param {string} The key of the html cache entry to use for this DOM Element.
* @param {string} [tagName='div'] - The tag name of the element into which all of the loaded html will be inserted. Defaults to a plain div tag.
*
* @return {this} This DOM Element instance.
*/
createFromCache: function (key, tagName)
{
var html = this.cache.get(key);
if (html)
{
this.createFromHTML(html, tagName);
}
return this;
},
/**
* Takes a string of html and then creates a DOM Element from it. The HTML is set as the `innerHTML`
* property of the created element.
*
* ```javascript
* let form = `
* <input type="text" name="nameField" placeholder="Enter your name" style="font-size: 32px">
* <input type="button" name="playButton" value="Let's Play" style="font-size: 32px">
* `;
* ```
*
* You can create a DOM Element from it using the string:
*
* ```javascript
* this.add.dom().createFromHTML(form);
* ```
*
* The optional `elementType` argument controls the type of container that is created, into which the html is inserted.
* The default is a plain `div` object, but any valid tagName can be given.
*
* If this Game Object already has an Element, it is removed from the DOM entirely first.
* Any event listeners you may have previously created will need to be re-created after this call.
*
* @method Phaser.GameObjects.DOMElement#createFromHTML
* @since 3.17.0
*
* @param {string} A string of html to be set as the `innerHTML` property of the created element.
* @param {string} [tagName='div'] - The tag name of the element into which all of the html will be inserted. Defaults to a plain div tag.
*
* @return {this} This DOM Element instance.
*/
createFromHTML: function (html, tagName)
{
if (tagName === undefined) { tagName = 'div'; }
// Already got an element? Remove it first
this.removeElement();
var element = document.createElement(tagName);
this.node = element;
element.style.zIndex = '0';
element.style.display = 'inline';
element.style.position = 'absolute';
// Node handler
element.phaser = this;
if (this.parent)
{
this.parent.appendChild(element);
}
element.innerHTML = html;
return this.updateSize();
},
/**
* Removes the current DOM Element bound to this Game Object from the DOM entirely and resets the
* `node` property of this Game Object to be `null`.
*
* @method Phaser.GameObjects.DOMElement#removeElement
* @since 3.17.0
*
* @return {this} This DOM Element instance.
*/
removeElement: function ()
{
if (this.node)
{
RemoveFromDOM(this.node);
this.node = null;
}
return this;
},
/**
* Internal method that calls `getBoundingClientRect` on the `node` and then sets the bounds width
* and height into the `displayWidth` and `displayHeight` properties, and the `clientWidth` and `clientHeight`
* values into the `width` and `height` properties respectively.
*
* This is called automatically whenever a new element is created or set.
*
* @method Phaser.GameObjects.DOMElement#updateSize
* @since 3.17.0
*
* @return {this} This DOM Element instance.
*/
updateSize: function ()
{
var node = this.node;
var nodeBounds = node.getBoundingClientRect();
this.width = node.clientWidth;
this.height = node.clientHeight;
this.displayWidth = nodeBounds.width || 0;
this.displayHeight = nodeBounds.height || 0;
return this;
},
/**
* Gets all children from this DOM Elements node, using `querySelectorAll('*')` and then iterates through
* them, looking for the first one that has a property matching the given key and value. It then returns this child
* if found, or `null` if not.
*
* @method Phaser.GameObjects.DOMElement#getChildByProperty
* @since 3.17.0
*
* @param {string} property - The property to search the children for.
* @param {string} value - The value the property must strictly equal.
*
* @return {?Element} The first matching child DOM Element, or `null` if not found.
*/
getChildByProperty: function (property, value)
{
if (this.node)
{
var children = this.node.querySelectorAll('*');
for (var i = 0; i < children.length; i++)
{
if (children[i][property] === value)
{
return children[i];
}
}
}
return null;
},
/**
* Gets all children from this DOM Elements node, using `querySelectorAll('*')` and then iterates through
* them, looking for the first one that has a matching id. It then returns this child if found, or `null` if not.
*
* Be aware that class and id names are case-sensitive.
*
* @method Phaser.GameObjects.DOMElement#getChildByID
* @since 3.17.0
*
* @param {string} id - The id to search the children for.
*
* @return {?Element} The first matching child DOM Element, or `null` if not found.
*/
getChildByID: function (id)
{
return this.getChildByProperty('id', id);
},
/**
* Gets all children from this DOM Elements node, using `querySelectorAll('*')` and then iterates through
* them, looking for the first one that has a matching name. It then returns this child if found, or `null` if not.
*
* Be aware that class and id names are case-sensitive.
*
* @method Phaser.GameObjects.DOMElement#getChildByName
* @since 3.17.0
*
* @param {string} name - The name to search the children for.
*
* @return {?Element} The first matching child DOM Element, or `null` if not found.
*/
getChildByName: function (name)
{
return this.getChildByProperty('name', name);
},
/**
* Sets the `className` property of the DOM Element node and updates the internal sizes.
*
* @method Phaser.GameObjects.DOMElement#setClassName
* @since 3.17.0
*
* @param {string} className - A string representing the class or space-separated classes of the element.
*
* @return {this} This DOM Element instance.
*/
setClassName: function (className)
{
if (this.node)
{
this.node.className = className;
this.updateSize();
}
return this;
},
/**
* Sets the `innerText` property of the DOM Element node and updates the internal sizes.
*
* Note that only certain types of Elements can have `innerText` set on them.
*
* @method Phaser.GameObjects.DOMElement#setText
* @since 3.17.0
*
* @param {string} text - A DOMString representing the rendered text content of the element.
*
* @return {this} This DOM Element instance.
*/
setText: function (text)
{
if (this.node)
{
this.node.innerText = text;
this.updateSize();
}
return this;
},
/**
* Sets the `innerHTML` property of the DOM Element node and updates the internal sizes.
*
* @method Phaser.GameObjects.DOMElement#setHTML
* @since 3.17.0
*
* @param {string} html - A DOMString of html to be set as the `innerHTML` property of the element.
*
* @return {this} This DOM Element instance.
*/
setHTML: function (html)
{
if (this.node)
{
this.node.innerHTML = html;
this.updateSize();
}
return this;
},
/**
* Runs internal update tasks.
*
* @method Phaser.GameObjects.DOMElement#preUpdate
* @private
* @since 3.17.0
*/
preUpdate: function ()
{
var parent = this.parentContainer;
var node = this.node;
if (node && parent && !parent.willRender())
{
node.style.display = 'none';
}
},
/**
* Compares the renderMask with the renderFlags to see if this Game Object will render or not.
*
* DOMElements always return `true` as they need to still set values during the render pass, even if not visible.
*
* @method Phaser.GameObjects.DOMElement#willRender
* @since 3.17.0
*
* @return {boolean} `true` if the Game Object should be rendered, otherwise `false`.
*/
willRender: function ()
{
return true;
},
/**
* Handles the pre-destroy step for the DOM Element, which removes the underlying node from the DOM.
*
* @method Phaser.GameObjects.DOMElement#preDestroy
* @private
* @since 3.17.0
*/
preDestroy: function ()
{
this.removeElement();
}
});
module.exports = DOMElement;