let mediaDir = "media/"; let mainContainerEl = document.getElementById("mainContainer"); let playerEl = document.getElementById("player"); let tracksEl = document.getElementById("tracks"); let descriptionEl = document.getElementById("description"); let bigButtonEl = document.getElementById("bigButton"); let controlsEl = document.getElementById("controls"); let scrubberTrackContainerEl = document.getElementById( "scrubberTrackContainer" ); let scrubberTrackPreviewEl = document.getElementById("scrubberTrackPreview"); let scrubberTrackEl = document.getElementById("scrubberTrack"); let scrubberFillEl = document.getElementById("scrubberFill"); let scrubberEl = document.getElementById("scrubber"); let nextTrackEl = document.getElementById("nextTrack"); let prevTrackEl = document.getElementById("prevTrack"); let loopSwitchEl = document.getElementById("loopSwitch"); let titleEl = document.getElementById("title"); let titleContainerEl = document.getElementById("titleContainer"); let mediaColumnEl = document.getElementById("mediaColumn"); let mediaContainerEl = document.getElementById("mediaContainer"); let mediaInfoEl = document.getElementById("mediaInfo"); let mediaImageEl = document.getElementById("mediaImage"); let mediaVideoEl = document.getElementById("mediaVideo"); let volumeContainerEl = document.getElementById("volumeContainer"); let volumeTrackContainerEl = document.getElementById("volumeTrackContainer"); let volumeTrackEl = document.getElementById("volumeTrack"); let volumeFillEl = document.getElementById("volumeFill"); let volumeIconEl = document.getElementById("volumeIcon"); let currentEntry = {}; let media = []; let scrubPosition = 0; let volumeIcons = ["icon-volume-none", "icon-volume-low", "icon-volume-high"]; let volume = 0.8; let muted = false; let loadedFirst = false; let autoPlay = false; let loopMode = "none"; let config = {}; function init() { fetch("config.json") .then((res) => res.json()) .then((data) => { update(data); }) .catch(console.error); } init(); function updateTheme(theme) { config.theme = theme; let rootEl = document.documentElement; if (theme.primaryColor) rootEl.style.setProperty("--primaryColor", theme.primaryColor); if (theme.primaryAltColor) rootEl.style.setProperty("--primaryAltColor", theme.primaryAltColor); if (theme.primaryTextColor) rootEl.style.setProperty("--primaryTextColor", theme.primaryTextColor); if (theme.primaryAltTextColor) rootEl.style.setProperty( "--primaryAltTextColor", theme.primaryAltTextColor ); if (theme.secondaryColor) rootEl.style.setProperty("--secondaryColor", theme.secondaryColor); if (theme.highlightColor) rootEl.style.setProperty("--highlightColor", theme.highlightColor); if (theme.backgroundColor) rootEl.style.setProperty("--backgroundColor", theme.backgroundColor); if (theme.previewStripeColor1) rootEl.style.setProperty( "--previewStripeColor1", theme.previewStripeColor1 ); if (theme.previewStripeColor2) rootEl.style.setProperty( "--previewStripeColor2", theme.previewStripeColor2 ); if (theme.linkColor) rootEl.style.setProperty("--linkColor", theme.linkColor); if (theme.overlayTextColor) rootEl.style.setProperty("--overlayTextColor", theme.overlayTextColor); if (theme.overlayBackgroundColor) rootEl.style.setProperty( "--overlayBackgroundColor", theme.overlayBackgroundColor ); if (theme.layoutStyle) { mainContainerEl.classList.remove("vertical", "horizontal"); mainContainerEl.classList.add(theme.layoutStyle); } if (theme.infoStyle) { mainContainerEl.classList.remove( "info-none", "info-overlaid", "info-below", "info-overlaid-toggle" ); mainContainerEl.classList.add("info-" + theme.infoStyle); } if (theme.titleStyle) { mainContainerEl.classList.remove("title-none", "title-span"); mainContainerEl.classList.add("title-" + theme.titleStyle); } if (theme.contentWidth) document.getElementById("contentContainer").style.maxWidth = theme.contentWidth + "px"; if (theme.nativePlayer) { document.getElementById("audio").classList.add("native"); mediaVideoEl.setAttribute("controls", ""); } else { document.getElementById("audio").classList.remove("native"); mediaVideoEl.removeAttribute("controls"); } if (theme.hideInfoDropdown) { mainContainerEl.classList.add("hide-info"); } else { mainContainerEl.classList.remove("hide-info"); } mediaContainerEl.style.maxWidth = theme.coverSize + "px"; mediaContainerEl.style.maxHeight = theme.coverSize + "px"; mediaColumnEl.style.maxWidth = theme.coverSize + "px"; if (theme.customCSS !== undefined) { document.querySelectorAll("#customCSS").forEach((el) => el.remove()); let styleEl = document.createElement("style"); styleEl.setAttribute("id", "customCSS"); styleEl.innerText = theme.customCSS; document.head.appendChild(styleEl); } } function loadContent(data) { loadCover(data.cover); mediaImageEl.style.width = config.theme.coverSize + "px"; mediaImageEl.style.height = config.theme.coverSize + "px"; if (data.media) loadMedia(data.media); } function updateTitle(title) { if (title) { titleContainerEl.classList.add("active"); config.title = title; titleEl.innerHTML = title; } else { titleContainerEl.classList.remove("active"); } } function updateDescription(description) { if (description === undefined || description === "") { descriptionEl.classList.remove("active"); } else { descriptionEl.classList.add("active"); config.description = description; descriptionEl.innerHTML = description; } } function updateLoopMode(mode) { if (mode === undefined || mode === "") { config.loopModeDefault = "none"; } else { config.loopModeDefault = mode; } loopSwitch(config.loopModeDefault); } function localStorageSet(key, value) { try { localStorage.setItem(key, value); } catch {} } function localStorageGet(key) { let value; try { value = localStorage.getItem(key); } catch { return undefined; } return value; } function update(data) { if (!data) { data = config; } if (!data.theme) { data.theme = {}; } let title = data.title; let theme = data.theme; let description = data.description; config = data; loadContent(data); updateTitle(title); updateDescription(description); updateLoopMode(data.loopModeDefault); updateTheme(theme); updateTrackPreview(); document.title = titleEl.textContent; volume = parseFloat(localStorageGet("volume")); muted = parseInt(localStorageGet("muted")); if (volume && typeof volume === "number") { setVolume(volume, muted); } else { volume = 0.8; muted = false; localStorageSet("volume", volume); } } function loadMedia(list) { if (list.length === 0) { return; } loadedFirst = false; autoPlay = false; bigButtonEl.classList.remove("pause"); media = list.map((entry) => { //return {file: entry.file, title: entry.title}; if (!/:\/\//.test(entry.file)) { //if not a url entry.file = mediaDir + entry.file; } entry.title = entry.title || entry.file; return entry; }); let featureIndex = 0; tracksEl.textContent = ""; media.forEach((entry, i) => { tracksEl.insertAdjacentHTML( "beforeend", `
${i + 1}.
${entry.title}
${ entry.info ? `` : "" }
${ entry.info ? `
${entry.info}
` : "" }
` ); let trackEl = tracksEl.lastChild; entry.trackEl = trackEl; let buttonEl = trackEl.querySelector("button"); if (entry.feature) { featureIndex = i; } if (entry.locked && featureIndex === i) { featureIndex++; } if (entry.info) { let infoContainerEl = trackEl.querySelector(".infoContainer"); trackEl.querySelector(".toggleInfo").addEventListener("click", (e) => { infoContainerEl.style.height = trackEl.querySelector(".info").clientHeight + "px"; entry.infoToggled = infoContainerEl.classList.toggle("active"); if (entry.info && entry.infoToggled) { infoContainerEl.removeAttribute("inert"); } else { infoContainerEl.setAttribute("inert", ""); } if (config.theme.infoStyle === "overlaid-toggle") { if (entry.info && entry.infoToggled) { mediaInfoEl.innerHTML = entry.info; mediaInfoContainer.classList.add("active"); } else { mediaInfoEl.innerHTML = ""; mediaInfoContainer.classList.remove("active"); } } }); } if (!entry.previewFade && entry.previewFade !== false) { entry.previewFade = true; //default true } if (typeof entry.loopCount === "number" && entry.loopCount > 0) { entry.remainingLoops = entry.loopCount; trackEl.classList.add("looped"); buttonEl.setAttribute("title", "loop count"); updateLoops(entry); } if (!entry.locked) { buttonEl.onclick = () => { loadedFirst = true; autoPlay = true; playEntry(entry); }; let loaderEl; if (entry.type === "video") { loaderEl = document.createElement("video"); } else { loaderEl = document.createElement("audio"); } if (entry.previewStart || entry.previewEnd) { entry.preview = true; } let needsPreviewEnd = false; if (!entry.previewEnd) { needsPreviewEnd = true; } entry.originalDuration = (entry.originalDuration && fromHMS(entry.originalDuration)) || 1; entry.previewStart = (entry.previewStart && fromHMS(entry.previewStart)) || 0; entry.previewEnd = (entry.previewEnd && fromHMS(entry.previewEnd)) || entry.originalDuration; entry.previewDuration = entry.previewEnd - entry.previewStart; loaderEl.addEventListener("loadedmetadata", (e) => { entry.duration = e.target.duration; entry.needsDuration = false; entry.previewStart = entry.previewStart || 0; if (needsPreviewEnd) { entry.previewEnd = entry.duration; } entry.originalDuration = Math.max( entry.originalDuration, entry.duration, entry.previewEnd ); entry.previewDuration = entry.previewEnd - entry.previewStart; //make assumptions about the audio start points if (entry.duration < entry.previewDuration) { //smaller than given preview duration //left align to preview entry.audioStart = entry.previewStart; } else if ( entry.duration < entry.originalDuration - entry.previewStart ) { //else, smaller than region between preview start and original end //left align to preview entry.audioStart = entry.previewStart; } else if (entry.duration < entry.originalDuration) { //else, smaller than original duration //right align to original entry.audioStart = entry.originalDuration - entry.duration; } else { //larger than original duration //left align to original entry.audioStart = 0; } entry.audioEnd = entry.audioStart + entry.duration; let durationText = toHMS(entry.duration); if (entry.preview) { durationText += " (preview)"; } trackEl.querySelector(".duration").textContent = durationText; if (entry === currentEntry) { updateTrackPreview(); // updateScrubPosition(entry.previewStart / entry.originalDuration); updateScrubPosition(0); updatePreviewVolume(0); } }); loaderEl.addEventListener("error", (e) => { entry.error = true; entry.errorMessage = e.target.error; removeLoading(entry, true); buttonEl.classList.add("error", "icon-warning"); buttonEl.setAttribute("title", "error loading file"); }); loaderEl.addEventListener("canplay", (e) => { removeLoading(entry, true); if (entry.feature && entry.autoplay) { playerEl.play(); } }); loaderEl.volume = 0; loaderEl.src = entry.file; entry.started = false; entry.loading = true; entry.loaderEl = loaderEl; } }); loadEntry(media[mod(featureIndex, media.length)]); } function loadCover(cover) { if (cover) { let src = cover; if (mediaImageEl.src == src) { return; //already loaded } if (!/:\/\//.test(src)) { //if not a url src = mediaDir + src; } mediaImageEl.src = src; mediaImageEl.classList.add("active"); mediaImageEl.style.visibility = "visible"; } else { mediaImageEl.style.visibility = "hidden"; } } function setCover(cover, size) { if (cover) { config.cover = cover; size && (config.coverSize = size); loadCover(cover); } } playerEl.addEventListener("canplay", (e) => { removeLoading(currentEntry); if (currentEntry.needsDuration) { currentEntry.duration = playerEl.duration; currentEntry.needsDuration = false; } if (autoPlay && !currentEntry.started) { currentEntry.started = true; if (!currentEntry.needsDuration) { playerEl.currentTime = currentEntry.previewStart - currentEntry.audioStart; } playerEl.play(); } if (!loadedFirst) { autoPlay = true; } }); playerEl.addEventListener("waiting", (e) => { setLoading(currentEntry, 0); }); playerEl.addEventListener("play", (e) => { if ( currentEntry.preview && playerEl.currentTime < currentEntry.previewStart - currentEntry.audioStart ) { playerEl.currentTime = currentEntry.previewStart - currentEntry.audioStart; } bigButtonEl.classList.add("pause"); currentEntry.started = true; currentEntry.trackEl.querySelector("button").classList.add("pause"); if (currentEntry.type === "video") { mediaVideoEl.play(); } }); playerEl.addEventListener("pause", (e) => { bigButtonEl.classList.remove("pause"); currentEntry.trackEl.querySelector("button").classList.remove("pause"); if (currentEntry.type === "video") { mediaVideoEl.pause(); } }); playerEl.addEventListener("volumechange", (e) => { if (config.theme.nativePlayer) { volume = e.target.volume; localStorageSet("volume", volume); } if (currentEntry.type === "video") { if (config.theme.nativePlayer) { mediaVideoEl.volume = e.target.volume; } else { mediaVideoEl.volume = 0; } } }); mediaVideoEl.addEventListener("volumechange", (e) => { if (currentEntry.type === "video" && config.theme.nativePlayer) { volume = e.target.volume; localStorageSet("volume", volume); } }); playerEl.addEventListener("timeupdate", (e) => { let buffer = 0.18; if (!scrubberDragged) { if (currentEntry.duration && !currentEntry.needsDuration) { if (currentEntry.started) { let time = e.target.currentTime; if (time > currentEntry.previewEnd - currentEntry.audioStart - buffer) { nextTrack(false); } else { let t = time / currentEntry.duration; updatePreviewVolume(t); updateScrubPosition(t); } } else { } } else { let time = e.target.currentTime; if (time > e.target.duration - buffer) { nextTrack(false); } } } }); playerEl.addEventListener("ended", (e) => { if (!scrubberDragged) { nextTrack(false); } }); mediaVideoEl.addEventListener("ended", (e) => { if (currentEntry.type === "video" && config.theme.nativePlayer) { nextTrack(false); } }); bigButtonEl.addEventListener("click", (e) => { playEntry(currentEntry); }); volumeIconEl.addEventListener("click", (e) => { toggleMute(); }); let volumeDragged = false; volumeTrackContainerEl.addEventListener("mousedown", (e) => { volumeDragged = true; scrubVolume(e.clientX); }); let volumeHovered = false; volumeContainerEl.addEventListener("mouseenter", (e) => { if (!scrubberDragged) { volumeHovered = true; volumeContainerEl.classList.add("hover"); } }); volumeContainerEl.addEventListener("mouseleave", (e) => { volumeHovered = false; if (!volumeDragged) { volumeContainerEl.classList.remove("hover"); } }); function toggleMute() { muted = !muted; setVolume(volume, muted); } function scrubVolume(x) { if (volumeDragged) { let trackX = volumeTrackEl.getBoundingClientRect().x; x -= trackX; let scrubberWidth = 6; let trackWidth = volumeTrackEl.clientWidth; let t = 1 - Math.max( 0, Math.min(1, (x - scrubberWidth / 2) / (trackWidth - scrubberWidth)) ); setVolume(t); } } function endVolumeScrub() { if (!volumeHovered) { volumeContainerEl.classList.remove("hover"); } } function setVolume(vol, mute = false) { volume = vol; localStorageSet("volume", volume); localStorageSet("muted", mute ? 1 : 0); vol = mute ? 0 : vol; if (currentEntry.type === "video") { if (config.theme.nativePlayer) { mediaVideoEl.volume = volume; playerEl.volume = 0; } else { mediaVideoEl.volume = 0; playerEl.volume = vol; } } else { playerEl.volume = vol; } let scrubberWidth = 6; let trackWidth = volumeTrackEl.clientWidth; volumeFillEl.style.left = (1 - vol) * (trackWidth - scrubberWidth) + "px"; volumeIconEl.classList.remove(...volumeIcons); if (vol <= 0) { volumeIconEl.classList.add(volumeIcons[0]); } else if (vol <= 0.5) { volumeIconEl.classList.add(volumeIcons[1]); } else { volumeIconEl.classList.add(volumeIcons[2]); } } document.addEventListener("keydown", (e) => { if (e.key === " " && e.target === document.body) { playEntry(currentEntry); e.preventDefault(); } }); let scrubberDragged = false; scrubberTrackContainerEl.addEventListener("pointerdown", (e) => { scrubberDragged = true; currentEntry.started = true; scrub(e.clientX); }); document.addEventListener("pointerup", (e) => { if (scrubberDragged) { scrubberDragged = false; endScrub(); } if (volumeDragged) { volumeDragged = false; endVolumeScrub(); } }); document.addEventListener("pointermove", (e) => { scrub(e.clientX); scrubVolume(e.clientX); }); document.addEventListener("pointercancel", (e) => { console.log(e); }); nextTrackEl.addEventListener("click", (e) => { nextTrack(); }); prevTrackEl.addEventListener("click", (e) => { prevTrack(); }); loopSwitchEl.addEventListener("click", (e) => { loopSwitch(); }); function updateTrackPreview() { if (currentEntry.needsDuration) { return; } //reset to prevent compounding width calculation issues scrubberTrackPreviewEl.style.removeProperty("margin-left"); scrubberTrackPreviewEl.style.removeProperty("width"); scrubberEl.style.removeProperty("left"); scrubberFillEl.style.removeProperty("width"); if (currentEntry.preview) { let fullWidth = scrubberEl.parentElement.parentElement.clientWidth; scrubberTrackPreviewEl.style.marginLeft = (currentEntry.previewStart / currentEntry.originalDuration) * 100 + "%"; scrubberTrackPreviewEl.style.width = ((currentEntry.previewEnd - currentEntry.previewStart) / currentEntry.originalDuration) * 100 + "%"; } } function updatePreviewVolume(t) { if (currentEntry.preview && currentEntry.previewFade && !muted) { if (currentEntry.needsDuration) { playEntry.volume = 0; } else { //rebase t to full (assumed) duration t = currentEntry.audioStart + t * currentEntry.duration; //clip to preview t = Math.max( currentEntry.previewStart, Math.min(currentEntry.previewEnd, t) ); let inTime = t - currentEntry.previewStart; let outTime = currentEntry.previewEnd - t; playerEl.volume = volume * Math.max(0, Math.min(1, inTime / 1, outTime / 1)); //1 second fade in/out } } } //t: 0-1 value in relation to the actual audio start/end function updateScrubPosition(t) { if (currentEntry.needsDuration) { return; } //rebase t to full (assumed) duration t = currentEntry.audioStart + t * currentEntry.duration; //clip to preview t = Math.max(currentEntry.previewStart, Math.min(currentEntry.previewEnd, t)); scrubPosition = (t - currentEntry.audioStart) / currentEntry.duration; let time = t; //rebase t = t / currentEntry.originalDuration; //relative to preview region let scrubberT = (t * currentEntry.originalDuration - currentEntry.previewStart) / currentEntry.previewDuration; let scrubberWidth = scrubberEl.clientWidth; let trackWidth = scrubberEl.parentElement.clientWidth; scrubberEl.style.left = ((scrubberT * (trackWidth - scrubberWidth)) / trackWidth) * 100 + "%"; scrubberFillEl.style.width = scrubberT * 100 + "%"; //let time = timePosition * currentEntry.duration; let timeText = ""; if (currentEntry.preview) { timeText += "(preview)
"; } timeText += `${toHMS(time)} / ${ currentEntry.originalDuration ? toHMS(currentEntry.originalDuration) : "0:00" }`; controlsEl.querySelector(".time").innerHTML = timeText; } function scrub(x) { if (scrubberDragged) { let trackX = scrubberTrackEl.getBoundingClientRect().x; x -= trackX; let scrubberWidth = scrubberEl.clientWidth; let trackWidth = scrubberEl.parentElement.clientWidth; let t = Math.max( 0, Math.min(1, (x - scrubberWidth / 2) / (trackWidth - scrubberWidth)) ); if (currentEntry.preview) { //rebase t from preview to audio start/end t = (t * currentEntry.previewDuration + (currentEntry.previewStart - currentEntry.audioStart)) / currentEntry.duration; } updateScrubPosition(t); } } function endScrub() { if (currentEntry.loading) { return; } playerEl.currentTime = scrubPosition * playerEl.duration; if (currentEntry.type === "video") { mediaVideoEl.currentTime = scrubPosition * playerEl.duration; } } function canPlay(entry) { return !entry.error && !entry.locked; } function nextTrack(manual = true) { if (!manual && loopMode === "track") { loadEntry(currentEntry); } else if (!manual && currentEntry.remainingLoops > 0) { currentEntry.remainingLoops--; updateLoops(currentEntry); loadEntry(currentEntry); } else { let loop = manual || loopMode === "playlist"; let idx = media.indexOf(currentEntry) + 1; if (!loop && idx >= media.length) { return; } let entry = media[mod(idx, media.length)]; let i = 0; while (!canPlay(entry) && i < media.length) { i++; idx++; if (!loop && idx >= media.length) { return; } entry = media[mod(idx, media.length)]; } loadEntry(entry); } } function prevTrack() { if ( playerEl.currentTime > currentEntry.previewStart - currentEntry.audioStart + 5 ) { playerEl.currentTime = currentEntry.previewStart - currentEntry.audioStart; } else { let idx = media.indexOf(currentEntry) - 1; let entry = media[mod(idx, media.length)]; let i = 0; while (!canPlay(entry) && i < media.length) { i++; idx--; entry = media[mod(idx, media.length)]; } loadEntry(entry); } } function loopSwitch(mode) { loopSwitchEl.classList.remove("icon-loop", "icon-loop-1"); loopSwitchEl.style.opacity = 1; if (mode) { loopMode = mode; } else { if (loopMode === "none") { loopMode = "playlist"; } else if (loopMode === "playlist") { loopMode = "track"; } else { loopMode = "none"; } } if (loopMode === "none") { loopSwitchEl.classList.add("icon-loop"); loopSwitchEl.style.opacity = 0.5; loopSwitchEl.setAttribute("title", "loop off"); } else if (loopMode === "playlist") { loopSwitchEl.classList.add("icon-loop"); loopSwitchEl.setAttribute("title", "loop playlist"); } else { loopSwitchEl.classList.add("icon-loop-1"); loopSwitchEl.setAttribute("title", "loop track"); } } function setLoading(entry, delay = 150) { if (entry.loading) { delay = 0; } if (entry === currentEntry) { bigButtonEl.classList.add("preloading"); setTimeout(() => { if (bigButtonEl.classList.contains("preloading")) { bigButtonEl.classList.remove("preloading"); bigButtonEl.classList.add("loading"); } }, delay); } entry.loading = true; } function removeLoading(entry, track = false) { if (entry === currentEntry) { bigButtonEl.classList.remove("loading", "preloading"); } if (track) { entry.trackEl .querySelector("button") .classList.remove("loading", "preloading"); } entry.loading = false; } function updateLoops(entry) { if (entry.loopCount > 0) { let buttonEl = entry.trackEl.querySelector("button"); buttonEl.setAttribute("loopcount", entry.remainingLoops); // buttonEl.setAttribute('title', 'loop count'); } if (entry === currentEntry) { if (entry.loopCount > 0) { bigButtonEl.setAttribute("loopcount", entry.remainingLoops); } else { bigButtonEl.removeAttribute("loopcount"); } } } function resetLoops(entry) { entry.remainingLoops = entry.loopCount; updateLoops(entry); } function loadEntry(entry) { if (entry.error) { return; } if (entry.locked) { return; } if (entry === currentEntry) { if (entry.type === "video") { mediaVideoEl.currentTime = 0; } else { } playerEl.currentTime = 0; playerEl.play(); return; } currentEntry = entry; media.forEach((thisEntry) => { thisEntry.trackEl.classList.remove("active"); thisEntry.trackEl.querySelector("button").classList.remove("pause"); if (thisEntry !== entry) { resetLoops(thisEntry); } updateLoops(entry); }); if (!currentEntry.duration) { currentEntry.duration = 999; currentEntry.needsDuration = true; } updateTrackPreview(); if (entry.preview) { scrubberTrackContainerEl.classList.add("preview"); updatePreviewVolume(0); } else { scrubberTrackContainerEl.classList.remove("preview"); } if (entry.loopCount > 0) { bigButtonEl.classList.add("looped"); } else { bigButtonEl.classList.remove("looped"); } Array.from(mediaContainerEl.children).forEach((el) => { el.classList.remove("active"); }); if (entry.type === "video") { mediaVideoEl.src = entry.file; mediaVideoEl.classList.add("active"); mediaImageEl.style.visibility = "hidden"; playerEl.classList.add("video"); if (config.theme.nativePlayer) { mediaVideoEl.volume = volume; playerEl.volume = 0; } else { mediaVideoEl.volume = 0; playerEl.volume = volume; } } else { mediaImageEl.classList.add("active"); playerEl.classList.remove("video"); playerEl.volume = volume; mediaVideoEl.pause(); mediaVideoEl.removeAttribute("src"); mediaVideoEl.load(); if (entry.cover) { loadCover(entry.cover); } else { loadCover(config.cover); } } playerEl.src = entry.file; entry.started = false; setLoading(currentEntry); entry.trackEl.classList.add("active"); controlsEl.querySelector(".title").innerHTML = entry.title; if ( entry.info && (config.theme.infoStyle !== "overlaid-toggle" || entry.infoToggled) ) { mediaInfoEl.innerHTML = entry.info; mediaInfoContainer.classList.add("active"); } else { mediaInfoEl.innerHTML = ""; mediaInfoContainer.classList.remove("active"); } } function playEntry(entry) { if (currentEntry === entry) { if (entry.loading) { return; } if (playerEl.paused) { playerEl.play(); entry.trackEl.querySelector("button").classList.add("pause"); } else { playerEl.pause(); } } else { loadEntry(entry); } } function toHMS(secs) { if (isNaN(secs)) { return "00:00"; } let sec_num = Math.max(0, Math.round(secs)); //flooring is more correct, but rounding gives nicer results due to playback event buffering let hours = Math.floor(sec_num / 3600); let minutes = Math.floor(sec_num / 60) % 60; let seconds = sec_num % 60; return [hours, minutes, seconds] .map((v) => (v < 10 ? "0" + v : v)) .filter((v, i) => v !== "00" || i > 0) .join(":"); } function fromHMS(hms) { if (!hms) { return 0; } let groups = ("" + hms).split(":"); if (groups.length < 1) { return 0; } for (let i = 0; i < groups.length; i++) { if (groups[i] === "") { groups[i] = "0"; continue; } if (isNaN(groups[i])) { return 0; } } let seconds = 0; let minutes = 0; let hours = 0; seconds = parseFloat(groups[groups.length - 1]); if (groups.length >= 2) { minutes = parseFloat(groups[groups.length - 2]); } if (groups.length >= 3) { hours = parseFloat(groups[groups.length - 3]); } return (hours * 60 + minutes) * 60 + seconds; } function mod(x, n) { return ((x % n) + n) % n; }