diff --git a/resources/media-controls.css b/resources/media-controls.css index cbea462157c..5ff7c9728e7 100644 --- a/resources/media-controls.css +++ b/resources/media-controls.css @@ -52,3 +52,6 @@ button { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAAy0lEQVR4AayRtUICUBRA7a7Jye5RF7u+wM4vsF2s0e7O37BzkZqZ+AF2WGk4XLqZeO/dPq/TUtuoZSki7mIgFloFlv3+icgOoKE8GlsH1sVOgOgy9jGjpzIuRjqv/rgNI3/hQCuD0t+8WK7Eywx6NfSGIAX+5t90CwOF5ODgNj4EO2TzxbDkdXwlgmCdLOolr+UlEbTn37QAK0fRBz8BAImvEYwMnmiJfdRzHxTAYoAQJjqPWWxJMf+3vHEAzCf+8A4avXYR9xSpm5QAaOvUDhZuhCsAAAAASUVORK5CYII=") no-repeat; } +.fullscreen { + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAa1JREFUSA3Vlj1Ow0AQhW1OAFUaKmoqOEAklCIlJQ3nyBFyBahc0IAEEnUUunQWVLiloqEKNzDfmJ2V7Z1JlpKRRrt+82bezq7/yrZtH4qiOMUt2wJelWX5aQXJnYDf4UdWHOyjgFTjlm0Bz53ECAsHF65lzUFkDiffXM5Y+esQTq8CZ0ZEchLzBF5gviVsBwgiz2aYvrwtuiFWmkkjEN7S2h+wpn8Gso/ViLhXBP64+COYnkkUiAdqJLgiHhdcD74TWAnQ79pL/AsniGxki+ReTswQmSuJ2BTvm9klhGPNMUcIur+LMYHYIiiYxcd895oiUy9IbI5n3WlejX+OS/uyDV4bxNzt83IiHorfMortOuRlTLImJCe3EpisXIsz7Syulis53L6ZIhAm8hxs8PigMbeKDwpkcuRpXolAg3evipxE3YVdXGL6qqhVAKwTeZJJzwYr1+I6wrO6rcD1ZTcQ6NXtpjuL7xHRWq5ApQVyRqpJJ+PuRaT2vmiXBOPBZ4icwbmweJ7AIeR1jkjgrOFLTmLSmvy2nCSRX0B+W6755n5ZcXLlGbrHvd+W9x/rQiZUwmH0RgAAAABJRU5ErkJggg==') no-repeat; +} diff --git a/resources/media-controls.js b/resources/media-controls.js index 383b025ee0e..f646ad833a5 100644 --- a/resources/media-controls.js +++ b/resources/media-controls.js @@ -5,19 +5,6 @@ (() => { "use strict"; - const MARKUP = ` -
- - - - - -
- `; - // States. const BUFFERING = "buffering"; const ENDED = "ended"; @@ -50,6 +37,22 @@ } }; + function generateMarkup(isAudioOnly) { + return ` +
+ + + + + + ${isAudioOnly ? "" : ''} +
+ `; + } + function camelCase(str) { const rdashes = /-(.)/g; return str.replace(rdashes, (str, p1) => { @@ -89,15 +92,16 @@ attributeFilter: ["controls"] }); + this.isAudioOnly = this.media.localName == "audio"; + // Create root element and load markup. this.root = document.createElement("div"); this.root.classList.add("root"); - this.root.innerHTML = MARKUP; + this.root.innerHTML = generateMarkup(this.isAudioOnly); this.controls.appendChild(this.root); - // Import elements. - this.elements = {}; - [ + + const elementNames = [ "duration", "play-pause-button", "position-duration-box", @@ -105,7 +109,15 @@ "progress", "volume-switch", "volume-level" - ].forEach(id => { + ]; + + if (!this.isAudioOnly) { + elementNames.push("fullscreen-switch"); + } + + // Import elements. + this.elements = {}; + elementNames.forEach(id => { this.elements[camelCase(id)] = this.controls.getElementById(id); }); @@ -182,6 +194,11 @@ { el: this.elements.volumeSwitch, type: "click" }, { el: this.elements.volumeLevel, type: "input" } ]; + + if (!this.isAudioOnly) { + this.controlEvents.push({ el: this.elements.fullscreenSwitch, type: "click" }); + } + this.controlEvents.forEach(({ el, type }) => { el.addEventListener(type, this); }); @@ -238,8 +255,7 @@ } render(from = this.state) { - const isAudioOnly = this.media.localName == "audio"; - if (!isAudioOnly) { + if (!this.isAudioOnly) { // XXX This should ideally use clientHeight/clientWidth, // but for some reason I couldn't figure out yet, // using it breaks layout. @@ -312,6 +328,9 @@ case this.elements.volumeSwitch: this.toggleMuted(); break; + case this.elements.fullscreenSwitch: + this.toggleFullscreen(); + break; } break; case "input": @@ -368,6 +387,10 @@ this.media.muted = !this.media.muted; } + toggleFullscreen() { + this.media.requestFullscreen(); + } + changeVolume() { const volume = parseInt(this.elements.volumeLevel.value); if (!isNaN(volume)) {