Skip to content

Commit a27ee05

Browse files
authored
fix: Remove img el when there's no poster source (#8130)
* fix: No invalid img el with no poster source * move dom changes into setSrc
1 parent 2c7eea8 commit a27ee05

File tree

2 files changed

+39
-24
lines changed

2 files changed

+39
-24
lines changed

src/js/poster-image.js

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,9 @@ class PosterImage extends ClickableComponent {
4646
* The element that gets created.
4747
*/
4848
createEl() {
49-
const el = Dom.createEl(
50-
'picture', {
51-
className: 'vjs-poster',
52-
53-
// Don't want poster to be tabbable.
54-
tabIndex: -1
55-
},
56-
{},
57-
Dom.createEl('img', {
58-
loading: 'lazy',
59-
crossOrigin: this.crossOrigin()
60-
}, {
61-
alt: ''
62-
})
63-
);
64-
65-
return el;
49+
// The el is an empty div to keep position in the DOM
50+
// A picture and img el will be inserted when a source is set
51+
return Dom.createEl('div', { className: 'vjs-poster'});
6652
}
6753

6854
/**
@@ -79,9 +65,9 @@ class PosterImage extends ClickableComponent {
7965
crossOrigin(value) {
8066
// `null` can be set to unset a value
8167
if (typeof value === 'undefined') {
82-
if (this.el_) {
68+
if (this.$('img')) {
8369
// If the poster's element exists, give its value
84-
return this.el_.querySelector('img').crossOrigin;
70+
return this.$('img').crossOrigin;
8571
} else if (this.player_.tech_ && this.player_.tech_.isReady_) {
8672
// If not but the tech is ready, query the tech
8773
return this.player_.crossOrigin();
@@ -97,7 +83,9 @@ class PosterImage extends ClickableComponent {
9783
return;
9884
}
9985

100-
this.el_.querySelector('img').crossOrigin = value;
86+
if (this.$('img')) {
87+
this.$('img').crossOrigin = value;
88+
}
10189

10290
return;
10391
}
@@ -125,13 +113,38 @@ class PosterImage extends ClickableComponent {
125113
}
126114

127115
/**
128-
* Set the source of the `PosterImage` depending on the display method.
116+
* Set the source of the `PosterImage` depending on the display method. (Re)creates
117+
* the inner picture and img elementss when needed.
129118
*
130-
* @param {string} url
131-
* The URL to the source for the `PosterImage`.
119+
* @param {string} [url]
120+
* The URL to the source for the `PosterImage`. If not specified or falsy,
121+
* any source and ant inner picture/img are removed.
132122
*/
133123
setSrc(url) {
134-
this.el_.querySelector('img').src = url;
124+
if (!url) {
125+
this.el_.textContent = '';
126+
return;
127+
}
128+
129+
if (!this.$('img')) {
130+
this.el_.appendChild(Dom.createEl(
131+
'picture', {
132+
className: 'vjs-poster',
133+
134+
// Don't want poster to be tabbable.
135+
tabIndex: -1
136+
},
137+
{},
138+
Dom.createEl('img', {
139+
loading: 'lazy',
140+
crossOrigin: this.crossOrigin()
141+
}, {
142+
alt: ''
143+
})
144+
));
145+
}
146+
147+
this.$('img').src = url;
135148
}
136149

137150
/**

test/unit/poster.test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ QUnit.test('should remove itself from the document flow when there is no poster'
6161
true,
6262
'Poster image hides with an empty source'
6363
);
64+
assert.equal(posterImage.$('img'), null, 'Poster image with no source has no img el');
6465

6566
// Updated with a valid source
6667
this.mockPlayer.poster_ = this.poster2;
@@ -70,6 +71,7 @@ QUnit.test('should remove itself from the document flow when there is no poster'
7071
false,
7172
'Poster image shows again when there is a source'
7273
);
74+
assert.ok(posterImage.$('img'), 'Poster image with source restores img el');
7375

7476
posterImage.dispose();
7577
});

0 commit comments

Comments
 (0)