Transform more towards HTML5+CSS+JS
This commit is contained in:
@@ -1,18 +1,5 @@
|
||||
{% assign file_info = site.static_files | where: "path", include.url %}
|
||||
<figure class="block {% if include.float == "clear" %}float-clear{% elsif include.float %}float float-{{ include.float }}{% endif %} {% if include.align %}align-{{ include.align }}{% endif %} {% if include.class %}{{ include.class }}{% endif %} {% if include.player %}player{% endif %}" style="{% if include.width %}width: {{ include.width }};{% endif %}">
|
||||
{% if include.player %}
|
||||
<div class="top">
|
||||
<select class="variant"></select>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<span class="play symbol" tabindex=0 aria-label="Play / Pause" data-symbol=""></span>
|
||||
<span class="time">0:00 / 0:00</span>
|
||||
<input type="range" class="progress" tabindex=0>
|
||||
<span class="mute symbol" tabindex=0 aria-label="Mute" data-symbol=""></span>
|
||||
<input type="range" class="volume" tabindex=0>
|
||||
<span class="fullscreen symbol" tabindex=0 aria-label="Fullscreen" data-symbol=""></span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if include.link %}<a href="{% if include.link == true %}{{ include.url }}{% else %}{{ include.link }}{% endif %}" {% if include.caption %}alt="{{ include.caption }}"{% endif %} target="_blank">{% endif %}
|
||||
{% if include.type == "image" %}
|
||||
<picture
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
// Block: Media Player
|
||||
// --------------------------------------------------------------------------------
|
||||
$media-player-button-size: 1.5rem;
|
||||
|
||||
figure.block-media.hide {
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
figure.block-media > .top,
|
||||
figure.block-media > .bottom {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0.2rem 0.5rem;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
figure.block-media > .top {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
display: flex;
|
||||
padding-bottom: 1rem;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
align-content: stretch;
|
||||
gap: 0.5rem;
|
||||
|
||||
background: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%);
|
||||
transition: top ease-in-out 100ms, opacity ease-in-out 100s;
|
||||
opacity: 1.0;
|
||||
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
figure.block-media.hide > .top {
|
||||
top: -100%;
|
||||
opacity: 0.0;
|
||||
transition: top ease-in-out 500ms, opacity ease-in-out 500s;
|
||||
}
|
||||
|
||||
figure.block-media > .top > .variant {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
figure.block-media > .bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
display: flex;
|
||||
padding-top: 1rem;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
align-content: stretch;
|
||||
gap: 0.5rem;
|
||||
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%);
|
||||
transition: top ease-in-out 100ms, opacity ease-in-out 100s;
|
||||
opacity: 1.0;
|
||||
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
figure.block-media.hide > .bottom {
|
||||
bottom: -100%;
|
||||
opacity: 0.0;
|
||||
transition: top ease-in-out 500ms, opacity ease-in-out 500s;
|
||||
}
|
||||
|
||||
figure.block-media > .bottom > .play {
|
||||
display: block;
|
||||
flex-grow: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: $media-player-button-size;
|
||||
height: $media-player-button-size;
|
||||
|
||||
font-size: $media-player-button-size;
|
||||
line-height: $media-player-button-size;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
figure.block-media > .bottom > .play.playing {
|
||||
}
|
||||
|
||||
figure.block-media > .bottom > .time {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
height: $media-player-button-size;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
|
||||
text-align: right;
|
||||
line-height: $media-player-button-size;
|
||||
user-select: auto;
|
||||
}
|
||||
|
||||
figure.block-media > .bottom > .progress {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
min-width: 5rem;
|
||||
height: 100%;
|
||||
flex-grow: 5;
|
||||
flex-shrink: 1;
|
||||
|
||||
display: block;
|
||||
user-select: none;
|
||||
}
|
||||
figure.block-media > .bottom > .mute {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: $media-player-button-size;
|
||||
height: $media-player-button-size;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
|
||||
font-size: $media-player-button-size;
|
||||
line-height: $media-player-button-size;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
figure.block-media > .bottom > .mute.muted {
|
||||
}
|
||||
|
||||
figure.block-media > .bottom > .volume {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
min-width: 3rem;
|
||||
max-width: 6rem;
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 5;
|
||||
flex-basis: auto;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
figure.block-media > .bottom > .fullscreen {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: $media-player-button-size;
|
||||
height: $media-player-button-size;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
|
||||
font-size: $media-player-button-size;
|
||||
line-height: $media-player-button-size;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
figure.block-media > .bottom > .time {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (max-width: 350px) {
|
||||
figure.block-media > .bottom > .volume {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (max-width: 250px) {
|
||||
figure.block-media > .bottom > .play,
|
||||
figure.block-media > .bottom > .mute,
|
||||
figure.block-media > .bottom > .fullscreen {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
+15
-17
@@ -7,7 +7,7 @@ figure.block {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
figure.block>figcaption {
|
||||
figure.block figcaption {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: .25em .5em;
|
||||
@@ -19,10 +19,10 @@ figure.block>figcaption {
|
||||
// --------------------------------------------------------------------------------
|
||||
// Block: Figure > Media
|
||||
// --------------------------------------------------------------------------------
|
||||
figure.block>picture,
|
||||
figure.block>img,
|
||||
figure.block>video,
|
||||
figure.block>audio {
|
||||
figure.block picture,
|
||||
figure.block img,
|
||||
figure.block video,
|
||||
figure.block audio {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
@@ -33,12 +33,10 @@ figure.block>audio {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
@import "_block-figure-player.scss";
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Block: Figure > Table
|
||||
// --------------------------------------------------------------------------------
|
||||
figure.block>table {
|
||||
figure.block table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: table;
|
||||
@@ -47,27 +45,27 @@ figure.block>table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
figure.block>table>thead>tr,
|
||||
figure.block>table>tbody>tr {
|
||||
figure.block table>thead>tr,
|
||||
figure.block table>tbody>tr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
figure.block>table>thead>tr {
|
||||
figure.block table>thead>tr {
|
||||
background: $theme-article-table-head-background;
|
||||
}
|
||||
|
||||
figure.block>table>tbody>tr {
|
||||
figure.block table>tbody>tr {
|
||||
background: $theme-article-table-body-background;
|
||||
}
|
||||
|
||||
figure.block>table>tbody>tr:nth-child(2n) {
|
||||
figure.block table>tbody>tr:nth-child(2n) {
|
||||
background: $theme-article-table-body-background-alt;
|
||||
}
|
||||
|
||||
figure.block>table>thead>tr>th,
|
||||
figure.block>table>tbody>tr>th {
|
||||
figure.block table>thead>tr>th,
|
||||
figure.block table>tbody>tr>th {
|
||||
margin: 0;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-weight: bold;
|
||||
@@ -79,8 +77,8 @@ figure.block>table>tbody>tr>th {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
figure.block>table>thead>tr>td,
|
||||
figure.block>table>tbody>tr>td {
|
||||
figure.block table>thead>tr>td,
|
||||
figure.block table>tbody>tr>td {
|
||||
margin: 0;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
// Block: Table
|
||||
// --------------------------------------------------------------------------------
|
||||
table.block {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: table;
|
||||
width: 100%;
|
||||
table-layout: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.block>thead>tr,
|
||||
table.block>tbody>tr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.block>thead>tr {
|
||||
background: $theme-article-table-head-background;
|
||||
}
|
||||
|
||||
table.block>tbody>tr {
|
||||
background: $theme-article-table-body-background;
|
||||
}
|
||||
|
||||
table.block>tbody>tr:nth-child(2n) {
|
||||
background: $theme-article-table-body-background-alt;
|
||||
}
|
||||
|
||||
table.block>thead>tr>th,
|
||||
table.block>tbody>tr>th {
|
||||
margin: 0;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-weight: bold;
|
||||
font-variant: small-caps;
|
||||
text-align: start;
|
||||
vertical-align: top;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
table.block>thead>tr>td,
|
||||
table.block>tbody>tr>td {
|
||||
margin: 0;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
+2
-6
@@ -3,7 +3,7 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
.block {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin: 0 auto;
|
||||
overflow: auto;
|
||||
text-align: start;
|
||||
}
|
||||
@@ -12,11 +12,6 @@
|
||||
margin-top: 1.25em;
|
||||
}
|
||||
|
||||
.block > .content {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Float
|
||||
// --------------------------------------------------------------------------------
|
||||
@@ -84,3 +79,4 @@
|
||||
@import "_block-figure.scss";
|
||||
@import "_block-heading.scss";
|
||||
@import "_block-list.scss";
|
||||
@import "_block-table.scss";
|
||||
|
||||
@@ -8,6 +8,7 @@ body > .content {
|
||||
|
||||
@import "_breadcrumbs.scss";
|
||||
@import "_article.scss";
|
||||
@import "_player.scss";
|
||||
@import "_comments.scss";
|
||||
@import "_index.scss";
|
||||
@import "_pagination.scss";
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
// Media Player
|
||||
// --------------------------------------------------------------------------------
|
||||
$media-player-button-size: 1.5rem;
|
||||
|
||||
player {
|
||||
overlay {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
|
||||
background: transparent;
|
||||
|
||||
controls {
|
||||
transition: bottom ease-in-out 100ms, opacity ease-in-out 100ms;
|
||||
display: flex;
|
||||
margin: 0;
|
||||
padding: 0.5rem 0.5rem;
|
||||
padding-top: 1rem;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
align-content: stretch;
|
||||
gap: 0.5rem;
|
||||
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%);
|
||||
opacity: 1.0;
|
||||
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
|
||||
.play {
|
||||
display: block;
|
||||
flex-grow: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: $media-player-button-size;
|
||||
height: $media-player-button-size;
|
||||
|
||||
font-size: $media-player-button-size;
|
||||
line-height: $media-player-button-size;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.time {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
height: $media-player-button-size;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
|
||||
text-align: right;
|
||||
line-height: $media-player-button-size;
|
||||
user-select: auto;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
min-width: 5rem;
|
||||
height: 100%;
|
||||
flex-grow: 5;
|
||||
flex-shrink: 1;
|
||||
|
||||
display: block;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mute {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: $media-player-button-size;
|
||||
height: $media-player-button-size;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
|
||||
font-size: $media-player-button-size;
|
||||
line-height: $media-player-button-size;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.volume {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
min-width: 3rem;
|
||||
max-width: 6rem;
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 5;
|
||||
flex-basis: auto;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.fullscreen {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: $media-player-button-size;
|
||||
height: $media-player-button-size;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
|
||||
font-size: $media-player-button-size;
|
||||
line-height: $media-player-button-size;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.hide {
|
||||
cursor: none;
|
||||
|
||||
overlay {
|
||||
controls {
|
||||
bottom: -100%;
|
||||
opacity: 0.0;
|
||||
transition: bottom ease-in-out 500ms, opacity ease-in-out 500ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player>.top {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
display: flex;
|
||||
padding-bottom: 1rem;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
align-content: stretch;
|
||||
gap: 0.5rem;
|
||||
|
||||
background: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 80%);
|
||||
transition: top ease-in-out 100ms, opacity ease-in-out 100s;
|
||||
opacity: 1.0;
|
||||
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
player overlay.hide>.top {
|
||||
top: -100%;
|
||||
opacity: 0.0;
|
||||
transition: top ease-in-out 500ms, opacity ease-in-out 500s;
|
||||
}
|
||||
|
||||
player overlay .top>.variant {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
player overlay controls .time {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
player overlay controls .volume {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 250px) {
|
||||
|
||||
player overlay controls .play,
|
||||
player overlay controls .mute,
|
||||
player overlay controls .fullscreen {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
+415
-292
@@ -11,7 +11,7 @@ async function xmr_media_lazyload_perform(element) {
|
||||
|
||||
async function xmr_media_lazyload_initialize() {
|
||||
// Figure out what to load.
|
||||
let elements = document.querySelectorAll(".block-media > [data-lazyload]");
|
||||
let elements = document.querySelectorAll(".block-this._media > [data-lazyload]");
|
||||
let stack = Array.from(elements);
|
||||
console.debug("Lazily loading " + stack.length + " elements...");
|
||||
|
||||
@@ -21,57 +21,60 @@ async function xmr_media_lazyload_initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
async function xmr_initialize_player(el) {
|
||||
let media = el.querySelector("video");
|
||||
if (!media)
|
||||
el.querySelector("audio");
|
||||
|
||||
let play_pause = el.querySelector(".play");
|
||||
{ // Play/Pause
|
||||
play_pause.update = function() {
|
||||
if (media.paused) {
|
||||
play_pause.classList.remove("playing");
|
||||
play_pause.dataset.symbol = "⏵";
|
||||
play_pause.ariaLabel = "Play";
|
||||
} else if (media.error || media.ended) {
|
||||
play_pause.classList.remove("playing");
|
||||
play_pause.dataset.symbol = "⏹";
|
||||
play_pause.ariaLabel = "Stopped";
|
||||
class XMediaPlayer {
|
||||
constructor(element) {
|
||||
this._media = element;
|
||||
this._variants = new Map();
|
||||
for (let source of this._media.querySelectorAll("source")) {
|
||||
if (source.title) {
|
||||
this._variants.set(source.url, source.title);
|
||||
} else {
|
||||
play_pause.classList.add("playing");
|
||||
play_pause.dataset.symbol = "⏸";
|
||||
play_pause.ariaLabel = "Pause";
|
||||
this._variants.set(source.url, (new URL(source.url)).pathname);
|
||||
}
|
||||
play_pause.innerText = play_pause.dataset.symbol;
|
||||
}
|
||||
play_pause.addEventListener("click", () => {
|
||||
if (media.paused) {
|
||||
media.play();
|
||||
} else {
|
||||
media.pause();
|
||||
}
|
||||
});
|
||||
play_pause.addEventListener("keydown", (ev) => {
|
||||
if (ev.isComposing || ev.keyCode === 229) {
|
||||
// Ignore IME compositing.
|
||||
return;
|
||||
}
|
||||
if (["Space", "Enter"].includes(ev.code)) {
|
||||
play_pause.click();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
});
|
||||
media.addEventListener("play", () => { play_pause.update(); });
|
||||
media.addEventListener("pause", () => { play_pause.update(); });
|
||||
media.addEventListener("ended", () => { play_pause.update(); });
|
||||
media.addEventListener("error", () => { play_pause.update(); });
|
||||
play_pause.update();
|
||||
}
|
||||
|
||||
let playback_time = el.querySelector(".time");
|
||||
{ // Time
|
||||
playback_time.update = function() {
|
||||
// Replace the original video element with a player.
|
||||
this._container = document.createElement("player");
|
||||
this._media.parentElement.replaceChild(this._container, this._media);
|
||||
|
||||
// Insert the original video element. This must be done here, else we have Z-fighting on mobile!
|
||||
this._container.appendChild(this._media);
|
||||
|
||||
// Insert the container for our overlays.
|
||||
this._overlay = document.createElement("overlay");
|
||||
this._container.appendChild(this._overlay);
|
||||
|
||||
// Build the control overlay.
|
||||
this._controls = document.createElement("controls");
|
||||
this._overlay.appendChild(this._controls);
|
||||
// - Play Button
|
||||
this._controlPlay = document.createElement("span");
|
||||
this._controlPlay.classList.add("play", "symbol")
|
||||
this._controlPlay.tabIndex = 0;
|
||||
this._controlPlay.dataset.symbol = "⏵";
|
||||
this._controlPlay.ariaLabel = "Play";
|
||||
this._controlPlay.update = () => {
|
||||
if (this._media.paused) {
|
||||
this._controlPlay.classList.remove("playing");
|
||||
this._controlPlay.dataset.symbol = "⏵";
|
||||
this._controlPlay.ariaLabel = "Play";
|
||||
} else if (this._media.error || this._media.ended) {
|
||||
this._controlPlay.classList.remove("playing");
|
||||
this._controlPlay.dataset.symbol = "⏹";
|
||||
this._controlPlay.ariaLabel = "Stopped";
|
||||
} else {
|
||||
this._controlPlay.classList.add("playing");
|
||||
this._controlPlay.dataset.symbol = "⏸";
|
||||
this._controlPlay.ariaLabel = "Pause";
|
||||
}
|
||||
this._controlPlay.innerText = this._controlPlay.dataset.symbol;
|
||||
}
|
||||
this._controls.appendChild(this._controlPlay);
|
||||
// - Time Display
|
||||
this._controlTime = document.createElement("span");
|
||||
this._controlTime.classList.add("time");
|
||||
this._controlTime.innerHTML = "00:00 / 00:00";
|
||||
this._controlTime.update = () => {
|
||||
function formatSeconds(seconds, with_ms, with_minutes, with_hour) {
|
||||
let result = [];
|
||||
if (isFinite(seconds) && !isNaN(seconds)) {
|
||||
@@ -97,170 +100,386 @@ async function xmr_initialize_player(el) {
|
||||
return result;
|
||||
}
|
||||
|
||||
let duration = formatSeconds(media.duration, true);
|
||||
let current = formatSeconds(media.currentTime, true, duration.length >= 2, duration.length >= 3);
|
||||
let duration = formatSeconds(this._media.duration, true);
|
||||
let current = formatSeconds(this._media.currentTime, true, duration.length >= 2, duration.length >= 3);
|
||||
for (let idx in duration) {
|
||||
current[idx].padStart(duration[idx].length, '0');
|
||||
}
|
||||
|
||||
if (duration.length > 0) {
|
||||
playback_time.innerText = `${current.join(':')} / ${duration.join(':')}`;
|
||||
this._controlTime.innerText = `${current.join(':')} / ${duration.join(':')}`;
|
||||
} else {
|
||||
playback_time.innerText = `${current.join(':')}`;
|
||||
this._controlTime.innerText = `${current.join(':')}`;
|
||||
}
|
||||
}
|
||||
media.addEventListener("timeupdate", () => { playback_time.update(); });
|
||||
media.addEventListener("durationupdate", () => { playback_progress.update(); });
|
||||
media.addEventListener("loadedmetadata", () => { playback_time.update(); });
|
||||
playback_time.update();
|
||||
}
|
||||
|
||||
let playback_progress = el.querySelector(".progress");
|
||||
{ // Progress
|
||||
playback_progress.update = function() {
|
||||
playback_progress.disabled = !media.seekable;
|
||||
playback_progress.min = 0;
|
||||
playback_progress.max = media.duration * 100;
|
||||
playback_progress.value = media.currentTime * 100;
|
||||
this._controls.appendChild(this._controlTime);
|
||||
// - Progress Bar
|
||||
this._controlProgress = document.createElement("input");
|
||||
this._controlProgress.classList.add("progress");
|
||||
this._controlProgress.type = "range";
|
||||
this._controlProgress.tabIndex = 0;
|
||||
this._controlProgress.min = -2147483648;
|
||||
this._controlProgress.max = 2147483647;
|
||||
this._controlProgress.update = () => {
|
||||
let min = parseInt(this._controlVolume.min, 10);
|
||||
let max = parseInt(this._controlVolume.max, 10);
|
||||
let dlt = max - min;
|
||||
this._controlProgress.disabled = !this._media.seekable;
|
||||
this._controlProgress.value = (this._media.currentTime / this._media.duration) * dlt + min;
|
||||
}
|
||||
playback_progress.addEventListener("input", () => {
|
||||
if (isFinite(media.duration)) {
|
||||
media.currentTime = parseInt(playback_progress.value, 10) / 100;
|
||||
}
|
||||
});
|
||||
media.addEventListener("timeupdate", () => { playback_progress.update(); });
|
||||
media.addEventListener("durationupdate", () => { playback_progress.update(); });
|
||||
media.addEventListener("loadeddata", () => { playback_progress.update(); });
|
||||
media.addEventListener("loadedmetadata", () => { playback_progress.update(); });
|
||||
playback_progress.update();
|
||||
}
|
||||
|
||||
let audio_mute = el.querySelector(".mute");
|
||||
{ // Mute
|
||||
audio_mute.update = function() {
|
||||
if (media.muted) {
|
||||
audio_mute.classList.add("muted");
|
||||
audio_mute.dataset.symbol = "🔇";
|
||||
audio_mute.ariaLabel = "Unmute";
|
||||
this._controls.appendChild(this._controlProgress);
|
||||
// - Mute Button
|
||||
this._controlMute = document.createElement("span");
|
||||
this._controlMute.classList.add("mute", "symbol");
|
||||
this._controlMute.tabIndex = 0;
|
||||
this._controlMute.ariaLabel = "Mute";
|
||||
this._controlMute.dataset.symbol = "🔊";
|
||||
this._controlMute.update = () => {
|
||||
if (this._media.muted) {
|
||||
this._controlMute.classList.add("muted");
|
||||
this._controlMute.dataset.symbol = "🔇";
|
||||
this._controlMute.ariaLabel = "Unmute";
|
||||
} else {
|
||||
audio_mute.classList.remove("muted");
|
||||
if (media.volume > 0.5) {
|
||||
audio_mute.dataset.symbol = "🔊";
|
||||
} else if (media.volume > 0.25) {
|
||||
audio_mute.dataset.symbol = "🔉";
|
||||
this._controlMute.classList.remove("muted");
|
||||
if (this._media.volume > 0.5) {
|
||||
this._controlMute.dataset.symbol = "🔊";
|
||||
} else if (this._media.volume > 0.25) {
|
||||
this._controlMute.dataset.symbol = "🔉";
|
||||
} else {
|
||||
audio_mute.dataset.symbol = "🔈";
|
||||
this._controlMute.dataset.symbol = "🔈";
|
||||
}
|
||||
audio_mute.ariaLabel = `Volume: ${(media.volume * 100).toString(10)}%`;
|
||||
this._controlMute.ariaLabel = `Volume: ${(this._media.volume * 100).toString(10)}%`;
|
||||
}
|
||||
audio_mute.innerText = audio_mute.dataset.symbol;
|
||||
this._controlMute.innerText = this._controlMute.dataset.symbol;
|
||||
}
|
||||
audio_mute.addEventListener("click", () => {
|
||||
media.muted = !media.muted;
|
||||
});
|
||||
audio_mute.addEventListener("keydown", (ev) => {
|
||||
if (ev.isComposing || ev.keyCode === 229) {
|
||||
// Ignore IME compositing.
|
||||
return;
|
||||
}
|
||||
if (["Space", "Enter"].includes(ev.code)) {
|
||||
audio_mute.click();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
});
|
||||
media.addEventListener("volumechange", () => {
|
||||
audio_mute.update();
|
||||
});
|
||||
audio_mute.update();
|
||||
}
|
||||
|
||||
let audio_volume = el.querySelector(".volume");
|
||||
{ // Volume
|
||||
audio_volume.min = 0;
|
||||
audio_volume.max = 2147483647;
|
||||
audio_volume.update = function() {
|
||||
let min = parseInt(audio_volume.min, 10);
|
||||
let max = parseInt(audio_volume.max, 10);
|
||||
this._controls.appendChild(this._controlMute);
|
||||
// - Volume Controls
|
||||
this._controlVolume = document.createElement("input");
|
||||
this._controlVolume.classList.add("volume");
|
||||
this._controlVolume.type = "range";
|
||||
this._controlVolume.tabIndex = 0;
|
||||
this._controlVolume.min = -2147483648;
|
||||
this._controlVolume.max = 2147483647;
|
||||
this._controlVolume.value = this._controlVolume.max;
|
||||
this._controlVolume.update = () => {
|
||||
let min = parseInt(this._controlVolume.min, 10);
|
||||
let max = parseInt(this._controlVolume.max, 10);
|
||||
let dlt = max - min;
|
||||
audio_volume.value = (media.logVolume * dlt) + min;
|
||||
audio_volume.ariaLabel = `Volume: ${(media.volume * 100).toString(10)}%`;
|
||||
if (media.muted) {
|
||||
audio_volume.classList.add("muted");
|
||||
this._controlVolume.value = (this._media.volume * dlt) + min;
|
||||
this._controlVolume.ariaLabel = `Volume: ${(this._media.volume * 100).toString(10)}%`;
|
||||
if (this._media.muted) {
|
||||
this._controlVolume.classList.add("muted");
|
||||
} else {
|
||||
audio_volume.classList.remove("muted");
|
||||
this._controlVolume.classList.remove("muted");
|
||||
}
|
||||
}
|
||||
audio_volume.addEventListener("input", () => {
|
||||
let min = parseInt(audio_volume.min, 10);
|
||||
let max = parseInt(audio_volume.max, 10);
|
||||
let val = parseInt(audio_volume.value, 10);
|
||||
let dlt = max - min;
|
||||
let vol = (val + min) / dlt;
|
||||
media.logVolume = vol;
|
||||
media.muted = (media.volume < 0.01);
|
||||
});
|
||||
media.addEventListener("volumechange", () => { audio_volume.update(); });
|
||||
audio_volume.update();
|
||||
}
|
||||
|
||||
let fullscreen = el.querySelector(".fullscreen");
|
||||
{ // Fullscreen
|
||||
fullscreen.update = function() {
|
||||
this._controls.appendChild(this._controlVolume);
|
||||
// - Fullscreen Button
|
||||
this._controlFullscreen = document.createElement("span");
|
||||
this._controlFullscreen.classList.add("fullscreen", "symbol");
|
||||
this._controlFullscreen.tabIndex = 0;
|
||||
this._controlFullscreen.ariaLabel = "Toggle Fullscreen";
|
||||
this._controlFullscreen.dataset.symbol = "⛶";
|
||||
this._controlFullscreen.update = () => {
|
||||
if (document.fullscreenElement) {
|
||||
fullscreen.dataset.symbol = "\u200F⛶";
|
||||
this._controlFullscreen.dataset.symbol = "\u200F⛶";
|
||||
} else {
|
||||
fullscreen.dataset.symbol = "⛶";
|
||||
this._controlFullscreen.dataset.symbol = "⛶";
|
||||
}
|
||||
fullscreen.innerText = fullscreen.dataset.symbol;
|
||||
this._controlFullscreen.innerText = this._controlFullscreen.dataset.symbol;
|
||||
};
|
||||
fullscreen.addEventListener("click", () => {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
el.requestFullscreen();
|
||||
}
|
||||
});
|
||||
fullscreen.addEventListener("keydown", (ev) => {
|
||||
if (ev.isComposing || ev.keyCode === 229) {
|
||||
// Ignore IME compositing.
|
||||
return;
|
||||
}
|
||||
if (["Space", "Enter"].includes(ev.code)) {
|
||||
fullscreen.click();
|
||||
ev.preventDefault();
|
||||
}
|
||||
})
|
||||
el.addEventListener("fullscreenchange", () => {
|
||||
fullscreen.update();
|
||||
});
|
||||
fullscreen.update();
|
||||
this._controls.appendChild(this._controlFullscreen);
|
||||
|
||||
// Now begin listening to all events that are relevant.
|
||||
for (let event of ["Abort", "CanPlay", "CanPlayThrough", "DurationChange", "Emptied", "Encrypted", "Ended", "Error", "LoadedData", "LoadedMetaData", "LoadStart", "Pause", "Play", "Playing", "Progress", "RateChange", "Seeked", "Seeking", "Stalled", "Suspend", "TimeUpdate", "VolumeChange", "Waiting", "DblClick", "Click", "KeyDown"]) {
|
||||
this._media.addEventListener(event.toLowerCase(), (ev) => { this[`_on${event}`](ev); });
|
||||
}
|
||||
for (let event of ["FullscreenChange", "FullscreenError", "KeyDown", "MouseEnter", "MouseLeave", "MouseMove", "Wheel"]) {
|
||||
this._container.addEventListener(event.toLowerCase(), (ev) => { this[`_on${event}`](ev); });
|
||||
}
|
||||
for (let event of ["Click", "KeyDown"]) {
|
||||
this._controlPlay.addEventListener(event.toLowerCase(), (ev) => { this[`_on${event}`](ev); });
|
||||
}
|
||||
for (let event of ["Input", "KeyDown", "Wheel"]) {
|
||||
this._controlProgress.addEventListener(event.toLowerCase(), (ev) => { this[`_on${event}`](ev); });
|
||||
}
|
||||
for (let event of ["Click", "KeyDown"]) {
|
||||
this._controlMute.addEventListener(event.toLowerCase(), (ev) => { this[`_on${event}`](ev); });
|
||||
}
|
||||
for (let event of ["Input", "KeyDown", "Wheel"]) {
|
||||
this._controlVolume.addEventListener(event.toLowerCase(), (ev) => { this[`_on${event}`](ev); });
|
||||
}
|
||||
for (let event of ["Click", "KeyDown"]) {
|
||||
this._controlFullscreen.addEventListener(event.toLowerCase(), (ev) => { this[`_on${event}`](ev); });
|
||||
}
|
||||
|
||||
// And update all controls once.
|
||||
this._controlPlay.update();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
this._controlMute.update();
|
||||
this._controlVolume.update();
|
||||
this._controlFullscreen.update();
|
||||
|
||||
// And tell the media element to load.
|
||||
this._media.load();
|
||||
}
|
||||
|
||||
_hideAudioControlWithoutAudio() {
|
||||
let hasAudio = Boolean(this._media.mozHasAudio)
|
||||
|| Boolean(this._media.webkitAudioDecodedByteCount)
|
||||
|| Boolean(this._media.audioTracks && this._media.audioTracks.length);
|
||||
this._controlMute.style.display = hasAudio ? "" : "none";
|
||||
this._controlVolume.style.display = hasAudio ? "" : "none";
|
||||
}
|
||||
|
||||
// Media Playback Status
|
||||
_onAbort(ev) {
|
||||
this.showOverlay();
|
||||
this._controlPlay.update();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onEnded(ev) {
|
||||
this.showOverlay();
|
||||
this._controlPlay.update();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onError(ev) {
|
||||
this.showOverlay();
|
||||
this._controlPlay.update();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onPlay(ev) {
|
||||
this._controlPlay.update();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onPlaying(ev) {
|
||||
this._controlPlay.update();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onPause(ev) {
|
||||
this.showOverlay();
|
||||
this._controlPlay.update();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onProgress(ev) {
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onRateChange(ev) {
|
||||
this._controlPlay.update();
|
||||
}
|
||||
_onTimeUpdate(ev) {
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onVolumeChange(ev) {
|
||||
this._controlMute.update();
|
||||
this._controlVolume.update();
|
||||
}
|
||||
|
||||
// Media Stream Status
|
||||
_onCanPlay(ev) { }
|
||||
_onCanPlayThrough(ev) { }
|
||||
_onDurationChange(ev) {
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onEmptied(ev) { }
|
||||
_onEncrypted(ev) { }
|
||||
_onLoadedData(ev) {
|
||||
this._hideAudioControlWithoutAudio();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onLoadedMetaData(ev) {
|
||||
this._hideAudioControlWithoutAudio();
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onLoadStart(ev) { }
|
||||
_onSeeked(ev) {
|
||||
this._controlTime.update();
|
||||
this._controlProgress.update();
|
||||
}
|
||||
_onSeeking(ev) { }
|
||||
_onSuspend(ev) { }
|
||||
_onWaiting(ev) { }
|
||||
|
||||
// User Input
|
||||
_onClick(ev) {
|
||||
if ((ev.target == this._controlPlay) || (ev.target == this._media)) {
|
||||
this.togglePlayPause();
|
||||
} else if (ev.target == this._controlMute) {
|
||||
this.toggleMute();
|
||||
} else if (ev.target == this._controlFullscreen) {
|
||||
this.toggleFullscreen();
|
||||
} else {
|
||||
// If we can't handle this, let it fall to the next handler.
|
||||
return
|
||||
}
|
||||
|
||||
// Prevent default behavior and stop propagation.
|
||||
this.showOverlay();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
_onDblClick(ev) {
|
||||
this._controlFullscreen.click();
|
||||
this.showOverlay();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
_onMouseEnter(ev) { }
|
||||
_onMouseMove(ev) {
|
||||
this.showOverlay();
|
||||
}
|
||||
_onMouseLeave(ev) { }
|
||||
_onKeyDown(ev) {
|
||||
// Ignore IME compositing.
|
||||
if (ev.isComposing || ev.keyCode === 229) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (["Space", "Enter"].includes(ev.code)) {
|
||||
// Most likely an attempt to simulate a click.
|
||||
ev.target.click();
|
||||
} else if (["f", "F"].includes(ev.key)) {
|
||||
this._controlFullscreen.click();
|
||||
} else if (["m", "M"].includes(ev.key)) {
|
||||
this._controlMute.click();
|
||||
} else if (ev.code === "Home") {
|
||||
this._media.currentTime = 0;
|
||||
} else if (ev.code === "ArrowLeft") {
|
||||
this._media.currentTime -= 5;
|
||||
} else if (ev.code === "Comma") {
|
||||
this._media.currentTime -= .1;
|
||||
} else if (ev.code === "Period") {
|
||||
this._media.currentTime += .1;
|
||||
} else if (ev.code === "ArrowRight") {
|
||||
this._media.currentTime += 5;
|
||||
} else if (ev.code === "End") {
|
||||
this._media.currentTime = this._media.duration;
|
||||
} else if (ev.code === "ArrowUp") {
|
||||
this._media.volume = Math.max(0, Math.min(this._media.volume + 0.05, 1.0));
|
||||
} else if (ev.code === "ArrowDown") {
|
||||
this._media.volume = Math.max(0, Math.min(this._media.volume - 0.05, 1.0));
|
||||
} else if (["p", "P"].includes(ev.key)) {
|
||||
this._media.preservesPitch = !this._media.preservesPitch;
|
||||
} else if (ev.code === "PageDown") {
|
||||
this._media.playbackRate = Math.max(0.25, Math.min(this._media.playbackRate - 0.05, 4.0));
|
||||
} else if (ev.code === "PageUp") {
|
||||
this._media.playbackRate = Math.max(0.25, Math.min(this._media.playbackRate + 0.05, 4.0));
|
||||
} else if (["r", "R"].includes(ev.key)) {
|
||||
this._media.playbackRate = 1.0;
|
||||
} else {
|
||||
// If we can't handle this, let it fall to the next handler.
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent default behavior and stop propagation.
|
||||
this.showOverlay();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
_onInput(ev) {
|
||||
if (ev.target == this._controlProgress) {
|
||||
ev.preventDefault();
|
||||
if (isFinite(this._media.duration)) {
|
||||
let min = parseInt(this._controlProgress.min, 10);
|
||||
let max = parseInt(this._controlProgress.max, 10);
|
||||
let val = parseInt(this._controlProgress.value, 10);
|
||||
let dlt = max - min;
|
||||
let time = (val - min) / dlt;
|
||||
this._media.currentTime = time * this._media.duration;
|
||||
}
|
||||
} else if (ev.target == this._controlVolume) {
|
||||
let min = parseInt(this._controlVolume.min, 10);
|
||||
let max = parseInt(this._controlVolume.max, 10);
|
||||
let val = parseInt(this._controlVolume.value, 10);
|
||||
let dlt = max - min;
|
||||
let vol = (val - min) / dlt;
|
||||
this._media.volume = vol;
|
||||
this._media.muted = (this._media.volume < 0.01);
|
||||
}
|
||||
}
|
||||
_onChange(ev) { }
|
||||
|
||||
// Control Functions
|
||||
togglePlayPause() {
|
||||
if (this._media.paused) {
|
||||
this._media.play();
|
||||
} else {
|
||||
this._media.pause();
|
||||
}
|
||||
}
|
||||
|
||||
toggleMute() {
|
||||
this._media.muted = !this._media.muted;
|
||||
}
|
||||
|
||||
toggleFullscreen() {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
this._container.requestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
showOverlay() {
|
||||
if (this._overlayTimeout) {
|
||||
clearTimeout(this._overlayTimeout);
|
||||
}
|
||||
|
||||
this._container.classList.remove("hide");
|
||||
this._overlayTimeout = setTimeout(() => { this.hideOverlay(); }, 2500);
|
||||
}
|
||||
|
||||
hideOverlay() {
|
||||
if (this._overlayTimeout) {
|
||||
clearTimeout(this._overlayTimeout);
|
||||
}
|
||||
|
||||
if (!this._media.paused && !this._media.ended && !this._media.error) {
|
||||
this._container.classList.add("hide");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
async function xmr_initialize_player(el) {
|
||||
|
||||
let variant = el.querySelector(".variant");
|
||||
{ // Variants
|
||||
variant.update = function() {
|
||||
variant.update = function () {
|
||||
// Store current state and pause.
|
||||
let paused = media.paused;
|
||||
let muted = media.muted;
|
||||
let volume = media.volume;
|
||||
let time = media.currentTime;
|
||||
media.pause();
|
||||
let paused = this._media.paused;
|
||||
let muted = this._media.muted;
|
||||
let volume = this._media.volume;
|
||||
let time = this._media.currentTime;
|
||||
this._media.pause();
|
||||
play_pause.update();
|
||||
|
||||
// Tell the media source to begin loading.
|
||||
media.src = variant.value;
|
||||
media.load();
|
||||
media.currentTime = time;
|
||||
// Tell the this._media source to begin loading.
|
||||
this._media.src = variant.value;
|
||||
this._media.load();
|
||||
this._media.currentTime = time;
|
||||
|
||||
media.addEventListener("canplay", () => {
|
||||
media.currentTime = time;
|
||||
media.volume = volume;
|
||||
media.muted = muted;
|
||||
this._media.addEventListener("canplay", () => {
|
||||
this._media.currentTime = time;
|
||||
this._media.volume = volume;
|
||||
this._media.muted = muted;
|
||||
if (paused) {
|
||||
media.pause();
|
||||
this._media.pause();
|
||||
} else {
|
||||
media.play();
|
||||
this._media.play();
|
||||
}
|
||||
|
||||
play_pause.update();
|
||||
@@ -279,110 +498,28 @@ async function xmr_initialize_player(el) {
|
||||
option.textContent = k.title;
|
||||
variant.appendChild(option);
|
||||
}
|
||||
variant.value = media.currentSrc;
|
||||
}
|
||||
|
||||
{ // Keyboard/Mouse Controls
|
||||
el.addEventListener("keydown", (ev) => {
|
||||
if (ev.isComposing || ev.keyCode === 229) {
|
||||
// Ignore IME compositing.
|
||||
return;
|
||||
}
|
||||
|
||||
if (["f", "F"].includes(ev.key)) {
|
||||
fullscreen.click();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (["m", "M"].includes(ev.key)) {
|
||||
audio_mute.click();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "Space") {
|
||||
play_pause.click();
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "Home") {
|
||||
media.currentTime = 0;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "ArrowLeft") {
|
||||
media.currentTime -= 5;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "Comma") {
|
||||
media.currentTime -= .1;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "Period") {
|
||||
media.currentTime += .1;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "ArrowRight") {
|
||||
media.currentTime += 5;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "End") {
|
||||
media.currentTime = media.duration;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "ArrowUp") {
|
||||
media.logVolume = Math.max(0, Math.min(media.logVolume + 0.05, 1.0));
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "ArrowDown") {
|
||||
media.logVolume = Math.max(0, Math.min(media.logVolume - 0.05, 1.0));
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (["p", "P"].includes(ev.key)) {
|
||||
media.preservesPitch = !media.preservesPitch;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "PageDown") {
|
||||
media.playbackRate = Math.max(0.25, Math.min(media.playbackRate - 0.05, 4.0));
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (ev.code === "PageUp") {
|
||||
media.playbackRate = Math.max(0.25, Math.min(media.playbackRate + 0.05, 4.0));
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
} else if (["r", "R"].includes(ev.key)) {
|
||||
media.playbackRate = 1.0;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
media.addEventListener("click", () => {
|
||||
play_pause.click();
|
||||
});
|
||||
|
||||
media.addEventListener("dblclick", () => {
|
||||
fullscreen.click();
|
||||
})
|
||||
variant.value = this._media.currentSrc;
|
||||
}
|
||||
|
||||
{ // Hide/Show controls
|
||||
el.showOverlay = function() {
|
||||
el.showOverlay = function () {
|
||||
el.cancelHideOverlay();
|
||||
el.classList.remove("hide");
|
||||
}
|
||||
el.hideOverlay = function() {
|
||||
if (!media.paused && !media.ended && !media.error) {
|
||||
el.classList.add("hide");
|
||||
}
|
||||
el.hideOverlay = function () {
|
||||
}
|
||||
el.delayHideOverlay = function() {
|
||||
el.delayHideOverlay = function () {
|
||||
el.cancelHideOverlay();
|
||||
el.timer = setTimeout(() => { el.hideOverlay(); }, 2500);
|
||||
}
|
||||
el.cancelHideOverlay = function() {
|
||||
el.cancelHideOverlay = function () {
|
||||
if (el.timer) {
|
||||
clearTimeout(el.timer);
|
||||
}
|
||||
}
|
||||
el.addEventListener("mousemove", () => {
|
||||
el.showOverlay();
|
||||
if (!media.paused && !media.ended && !media.error) {
|
||||
if (!this._media.paused && !this._media.ended && !this._media.error) {
|
||||
el.delayHideOverlay();
|
||||
}
|
||||
});
|
||||
@@ -391,34 +528,18 @@ async function xmr_initialize_player(el) {
|
||||
|
||||
{ // Show/Hide Audio controls without audio.
|
||||
function checkAudioPresence() {
|
||||
let hasAudio = Boolean(media.mozHasAudio)
|
||||
|| Boolean(media.webkitAudioDecodedByteCount)
|
||||
|| Boolean(media.audioTracks && media.audioTracks.length);
|
||||
audio_mute.style.display = hasAudio ? "" : "none";
|
||||
audio_volume.style.display = hasAudio ? "" : "none";
|
||||
}
|
||||
media.addEventListener("loadedmetadata", () => { checkAudioPresence() });
|
||||
media.addEventListener("loadeddata", () => { checkAudioPresence() });
|
||||
this._media.addEventListener("loadedmetadata", () => { checkAudioPresence() });
|
||||
this._media.addEventListener("loadeddata", () => { checkAudioPresence() });
|
||||
checkAudioPresence();
|
||||
}
|
||||
|
||||
// Signal the browser to try and load some information.
|
||||
media.load();
|
||||
this._media.load();
|
||||
}
|
||||
*/
|
||||
|
||||
async function xmr_initialize_players() {
|
||||
// Figure out what to initialize.
|
||||
let elements = document.querySelectorAll("media.player");
|
||||
let stack = Array.from(elements);
|
||||
console.debug("Initializing " + stack.length + " players...");
|
||||
|
||||
// Add a lazyloading handler to all entries.
|
||||
for (let el of stack) {
|
||||
xmr_initialize_player(el);
|
||||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// Support for Mobile Devices
|
||||
@@ -426,9 +547,11 @@ async function xmr_initialize_players() {
|
||||
document.querySelector("#header #navigation").classList.toggle("open");
|
||||
});
|
||||
|
||||
// Lazily load Media
|
||||
// Lazily load this._media
|
||||
xmr_media_lazyload_initialize();
|
||||
|
||||
// Initialize media player.
|
||||
xmr_initialize_players();
|
||||
// Initialize this._media player.
|
||||
for (let el of document.querySelectorAll("video")) {
|
||||
el.player = new XMediaPlayer(el);
|
||||
}
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user