diff --git a/src/AudioPlayer.js b/src/AudioPlayer.js index 42d5ea4..3f47cb6 100644 --- a/src/AudioPlayer.js +++ b/src/AudioPlayer.js @@ -2,11 +2,7 @@ import { mergeClasses, mergeIcons, mergeArt } from "./AudioPlayerStyles.js"; import { loadProviders } from "./AudioPlayerProviders.js"; import { elem } from "./AudioPlayerHelpers.js"; import { createAudioElement } from "./AudioPlayerMedia.js"; -import { - initBibleList, - handleBibleButtonClick, - initBookList, -} from "./AudioPlayerBibleList.js"; +import { initBibleList, handleBibleButtonClick, initBookList } from "./AudioPlayerBibleList.js"; import { chapterList, handleBookChange, updateBookList } from "./AudioPlayerChapterList.js"; export default class AudioPlayer { @@ -26,6 +22,7 @@ export default class AudioPlayer { this.art = mergeArt(options.art); this.results = []; this.query = ""; + this.titles = options?.titles ?? []; this.view = "bible"; this.idPrefix = options?.idPrefix ?? "audio-player"; this.views = { diff --git a/src/AudioPlayerBibleList.js b/src/AudioPlayerBibleList.js index af092c5..4ca850a 100644 --- a/src/AudioPlayerBibleList.js +++ b/src/AudioPlayerBibleList.js @@ -1,7 +1,7 @@ import { elem } from './AudioPlayerHelpers.js' import { fuzzySearch } from './AudioPlayerSearch.js'; -import {selectBible, setCurrentChapter} from './AudioPlayerProviders.js' -import { updateCurrentBibleBlock, updateBookList, handleChapterChange, chapterList } from './AudioPlayerChapterList.js'; +import { selectBible } from './AudioPlayerProviders.js' +import { updateCurrentBibleBlock, updateBookList } from './AudioPlayerChapterList.js'; export function initBibleList(ctx) { ctx.bibleListContainer.innerHTML = ''; @@ -36,10 +36,10 @@ function updateBibleGrid(ctx) { } function createBibleButton(ctx, bible) { - const button = elem('button', { - className: ctx.class.bibleButton.wrapper, - onclick: () => handleBibleButtonClick(ctx, bible) - }); + const buttonWrap = elem('div', {className: ctx.class.bibleButton.wrapper}); + + const button = elem('button', {className: ctx.class.bibleButton.button, onclick: () => handleBibleButtonClick(ctx, bible)}); + buttonWrap.appendChild(button) button.dataset.testId = bible.id; button.setAttribute('aria-label', bible.tv ?? bible.tt); @@ -61,10 +61,51 @@ function createBibleButton(ctx, bible) { button.appendChild(bibleListButtonLanguage); button.appendChild(bibleListButtonTitle); - return button; + if(bible.dl) { + const downloadButton = elem('button', { + className: ctx.class.bibleButton.download, + innerHTML: ctx.icons.download, + onclick:() => handleBibleDownload(ctx, bible)}) + buttonWrap.appendChild(downloadButton) + } + + return buttonWrap; +} + +export async function handleBibleDownload(ctx, bible) { + try { + if (!bible.dl) { + console.log("Bible object does not contain a valid download URL"); + return; + } + const dialog = elem('dialog', {className: ctx.class.bibleDownloadDialog.wrapper}); + const message = elem("div", {innerHTML: ctx?.download_text ?? `
`}); + const copyright = elem("div", { innerHTML: ` +

${bible.audio_copyright}

+

${bible.text_copyright}

` + }); + dialog.append(message, copyright); + const downloadButton = elem("button",{className: ctx.class.bibleDownloadDialog.button_download,textContent: `Download ${bible.dl_size ?? ''}`}); + downloadButton.addEventListener("click", () => { + const anchor = document.body.appendChild(elem('a', { href: bible.dl, download: '' })); + anchor.click(); + anchor.remove(); + dialog.close(); + dialog.remove(); + }); + dialog.appendChild(downloadButton); + const cancelButton = elem("button", {className: ctx.class.bibleDownloadDialog.cancel, textContent: "Cancel"}); + cancelButton.addEventListener("click", () => {dialog.close();document.body.removeChild(dialog);}); + dialog.appendChild(cancelButton); + document.body.appendChild(dialog); + dialog.showModal(); + } catch (error) { + console.error("An error occurred while trying to display the dialog:", error); + } } export async function handleBibleButtonClick(ctx, bible) { + if (bible.tp === "hark") { ctx.view = "book"; ctx.currentBible = bible; @@ -79,7 +120,6 @@ export async function handleBibleButtonClick(ctx, bible) { } } - export function initBookList(ctx) { const searchInput = elem('input', { type: 'search', diff --git a/src/AudioPlayerHelpers.js b/src/AudioPlayerHelpers.js index fef317c..c7f025b 100644 --- a/src/AudioPlayerHelpers.js +++ b/src/AudioPlayerHelpers.js @@ -1,6 +1,5 @@ export function elem(tag, props = {}) { const el = document.createElement(tag); - for (const [key, val] of Object.entries(props)) { if (key === 'style' && typeof val === 'object') { Object.assign(el.style, val); @@ -8,7 +7,6 @@ export function elem(tag, props = {}) { el[key] = val; } } - return el; } @@ -21,4 +19,14 @@ export function formatTime(timeInSeconds) { export const parseTimestampToSeconds = (timestampStr) => { const [hours, minutes, seconds] = timestampStr.split(':'); return (parseInt(hours, 10) * 3600) + (parseInt(minutes, 10) * 60) + parseFloat(seconds); -}; \ No newline at end of file +} + +HTMLDialogElement.prototype.triggerShow = HTMLDialogElement.prototype.showModal; +HTMLDialogElement.prototype.showModal = function() { + this.triggerShow(); + this.onclick = event => { + let rect = this.getBoundingClientRect(); + if(event.clientY < rect.top || event.clientY > rect.bottom) return this.close(); + if(event.clientX < rect.left || event.clientX > rect.right) return this.close(); + } +} \ No newline at end of file diff --git a/src/AudioPlayerProviders.js b/src/AudioPlayerProviders.js index 1aa2033..da6effe 100644 --- a/src/AudioPlayerProviders.js +++ b/src/AudioPlayerProviders.js @@ -13,53 +13,22 @@ export async function loadProviders(player) { player.bibles = player.bibles.concat(await providerFunctions[provider]()); } } -} - -export async function harkList(country_id = 'all', provider = 'all') { - const baseBibles = await fetch(`${BASE_API_URL}/api/bibles`).then(response => response.json()); - let bibles = await fetch(`${BASE_CONTENT_URL}/bibles/audio-new/index.txt`).then(response => response.text()); - - let output = []; - - bibles = bibles.split('\n'); - let unmatchedBibles = []; - bibles.forEach(bible => { - let bible_id = bible.split('_')[0]; - if (bible_id.includes('-')) { - bible_id = bible.split('-')[0]; - } - let found = false; - - for (let i = 0; i < baseBibles.length; i++) { - const baseBible = baseBibles[i]; - if (bible_id === baseBible.id) { - output.push({ - id: bible, - abbr: baseBible.id, - iso: baseBible.iso, - ln: baseBible.ln, - tt: baseBible.tt, - tv: baseBible.tv, - ci: baseBible.ci, - cn: baseBible.cn, - tp: "hark" - }); - found = true; - break; // Exit loop once match is found - } + for (let i = 0; i < player.bibles.length; i++) { + let customTitle = player.titles[player.bibles[i].id]; + if(customTitle) { + player.bibles[i].tt = customTitle.tt; + player.bibles[i].tv = customTitle.tv; } - - if (!found) { - unmatchedBibles.push(bible_id); // Add unmatched bible_id to array - } - }); - - if (unmatchedBibles.length > 0) { - //console.log("Unmatched bible_ids:", unmatchedBibles); - } else { - //console.log("All bible_ids matched in output."); } +} +export async function harkList(country_id = 'all', provider = 'all') { + const bibles = await fetch(`${BASE_CONTENT_URL}/bibles/audio-new/index.json`).then(response => response.json()); + const output = bibles.map(bible => ({ + ...bible, + tp: "hark", + dl: (bible.dl) ? `${BASE_CONTENT_URL}/bibles/audio-new/${bible.id}.zip` : "" + })); if (country_id !== 'all') { output = output.filter(bible => bible.ci === country_id); } @@ -130,7 +99,6 @@ export async function harkSelect(id) { } export async function dbpList(country_id) { - let initial_path = `https://4.dbt.io/api/bibles?v=4&key=${key}&media=audio`; if (country_id) { initial_path += '&country=' + country_id; diff --git a/src/AudioPlayerStyles.js b/src/AudioPlayerStyles.js index 39b1fca..88c5adb 100644 --- a/src/AudioPlayerStyles.js +++ b/src/AudioPlayerStyles.js @@ -1,102 +1,113 @@ const defaultClasses = { - playerHeader: 'select-none ', - playerContainer: 'select-none w-full mx-auto max-w-7xl', - bibleListContainer: 'select-none ', - chapterListContainer: 'select-none relative w-full max-w-4xl mx-auto', - bibleListGrid: 'select-none grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3', - bibleBlockInfoWrap: 'select-none flex flex-row justify-between gap-4 max-w-md w-full mx-auto bg-stone-100 border border-stone-200 mt-12 p-3', - bibleBlock: 'select-none flex flex-col justify-between text-sm text-center md:text-base lg:text-lg font-semibold text-black', - bibleBlockTitleGroup: 'select-none flex-shrink truncate', - bibleBlockVernacular: 'select-none truncate text-sm mb-1', - bibleBlockTitle: 'select-none truncate text-2xl font-semibold', - bibleBlockLanguageGroup: 'select-none ', - bibleBlockIso: 'select-none text-sm', - bibleBlockButtonGroup: 'select-none flex flex-col justify-between', + playerHeader: '', + playerContainer: 'w-full mx-auto max-w-7xl', + bibleListContainer: '', + chapterListContainer: 'relative w-full max-w-4xl mx-auto', + bibleListGrid: 'grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3', - container: 'select-none audio-player-container mx-auto max-w-7xl w-full', - audio: 'select-none ', - controlsContainer: 'select-none controls-container flex flex-col', - navRow: 'select-none flex flex-row items-center justify-center gap-4 py-4 bg-stone-100 border border-stone-200 w-full max-w-md mx-auto', - prevBookButton: 'select-none prev-book-button flex justify-center items-center', - prevChapterButton: 'select-none prev-chapter-button flex justify-center items-center', - playPauseButton: 'select-none play-pause-button flex justify-center items-center', - playPauseIcon: 'select-none icon-play', - nextChapterButton: 'select-none next-chapter-button flex justify-center items-center', - nextBookButton: 'select-none next-book-button flex justify-center items-center', - controlRow2: 'select-none grid grid-cols-5 mb-1', - leftControls: 'select-none flex flex-row justify-center items-center col-span-2 space-x-6', + bibleBlockInfoWrap: 'flex flex-row justify-between gap-4 max-w-md w-full mx-auto bg-stone-100 border border-stone-200 mt-12 p-3', + bibleBlock: 'flex flex-col justify-between text-sm text-center md:text-base lg:text-lg font-semibold text-black', + bibleBlockTitleGroup: 'flex-shrink truncate', + bibleBlockVernacular: 'truncate text-sm mb-1', + bibleBlockTitle: 'truncate text-2xl font-semibold', + bibleBlockLanguageGroup: '', + bibleBlockIso: 'text-sm', + bibleBlockButtonGroup: 'flex flex-col justify-between', + + container: 'audio-player-container mx-auto max-w-7xl w-full', + audio: '', + controlsContainer: 'controls-container flex flex-col', + navRow: 'flex flex-row items-center justify-center gap-4 py-4 bg-stone-100 border border-stone-200 w-full max-w-md mx-auto', + prevBookButton: 'prev-book-button flex justify-center items-center', + prevChapterButton: 'prev-chapter-button flex justify-center items-center', + playPauseButton: 'play-pause-button flex justify-center items-center', + playPauseIcon: 'icon-play', + nextChapterButton: 'next-chapter-button flex justify-center items-center', + nextBookButton: 'next-book-button flex justify-center items-center', + controlRow2: 'grid grid-cols-5 mb-1', + leftControls: 'flex flex-row justify-center items-center col-span-2 space-x-6', playbackRate: { - wrapper: 'select-none flex mx-auto w-full max-w-md justify-center px-8 py-2 bg-stone-100 text-xs', - display: 'select-none mx-1 text-stone-400 text-sm', - increase: 'select-none w-6 h-6 border-2 rounded-2xl text-stone-500', - decrease: 'select-none w-6 h-6 border-2 rounded-2xl text-stone-500', - disabled: 'select-none opacity-50' + wrapper: 'flex mx-auto w-full max-w-md justify-center px-8 py-2 bg-stone-100 text-xs', + display: 'mx-1 text-stone-400 text-sm', + increase: 'w-6 h-6 border-2 rounded-2xl text-stone-500', + decrease: 'w-6 h-6 border-2 rounded-2xl text-stone-500', + disabled: 'opacity-50' }, - rightControls: 'select-none flex flex-row justify-center items-center col-span-2 space-x-6', - playSpeedControl: 'select-none flex flex-row justify-center items-center text-xs', + rightControls: 'flex flex-row justify-center items-center col-span-2 space-x-6', + playSpeedControl: 'flex flex-row justify-center items-center text-xs', decrementIcon: 'size-6', incrementIcon: 'size-6', - decreaseSpeedButton: 'select-none w-6 h-6 border-2 rounded-2xl hover:border-blue-600 dark:hover:border-white text-stone-500 dark:hover:text-white', - increaseSpeedButton: 'select-none w-6 h-6 border-2 rounded-2xl hover:border-blue-600 dark:hover:border-white text-stone-500 dark:hover:text-white', - prevSkipButton: 'select-none flex justify-center items-center text-stone-400 hover:text-blue-600 dark:text-white dark:hover:text-blue-400', - nextSkipButton: 'select-none flex justify-center items-center text-stone-400 hover:text-blue-600 dark:text-white dark:hover:text-blue-400', + decreaseSpeedButton: 'w-6 h-6 border-2 rounded-2xl hover:border-blue-600 dark:hover:border-white text-stone-500 dark:hover:text-white', + increaseSpeedButton: 'w-6 h-6 border-2 rounded-2xl hover:border-blue-600 dark:hover:border-white text-stone-500 dark:hover:text-white', + prevSkipButton: 'flex justify-center items-center text-stone-400 hover:text-blue-600 dark:text-white dark:hover:text-blue-400', + nextSkipButton: 'flex justify-center items-center text-stone-400 hover:text-blue-600 dark:text-white dark:hover:text-blue-400', progress: { - container: 'select-none flex mx-auto w-full max-w-md justify-around px-1 pt-4 bg-stone-100 text-xs', - wrapper: 'select-none mx-auto min-w-80 mx-3 w-3/4 sm:w-5/6 h-3 rounded-lg relative border bg-gradient-to-br shadow-inner border-stone-300 from-white to-stone-200 dark:from-neutral-50 dark:to-stone-400 border-stone-500', - barInner: 'select-none h-3 w-0 bg-blue-600 rounded-md', - circleTip: 'select-none absolute top-1/2 transform -translate-y-1/2 -translate-x-1/2 w-5 h-5 bg-blue-600 rounded-full border border-blue-500', - currentTimeDisplay: 'select-none text-black', - durationDisplay: 'select-none text-black', - tick: 'select-none w-[1.5px] absolute top-0 h-full bg-stone-400' + container: 'flex mx-auto w-full max-w-md justify-around px-1 pt-4 bg-stone-100 text-xs', + wrapper: 'mx-auto min-w-80 mx-3 w-3/4 sm:w-5/6 h-3 rounded-lg relative border bg-gradient-to-br shadow-inner border-stone-300 from-white to-stone-200 dark:from-neutral-50 dark:to-stone-400 border-stone-500', + barInner: 'h-3 w-0 bg-blue-600 rounded-md', + circleTip: 'absolute top-1/2 transform -translate-y-1/2 -translate-x-1/2 w-5 h-5 bg-blue-600 rounded-full border border-blue-500', + currentTimeDisplay: 'text-black', + durationDisplay: 'text-black', + tick: 'w-[1.5px] absolute top-0 h-full bg-stone-400' }, - mediaPlayerWrap: 'select-none w-full flex flex-col justify-center', - mediaPlayerHeader: 'select-none ', - mediaPlayerBody: 'select-none ', - mediaPlayerNavRow: 'select-none grid grid-cols-5 px-2 text-stone-700 dark:text-stone-300 divide-x divide-stone-500 dark:divide-stone-600', - bibleListNavButton: 'select-none ', - bookListNavButton: 'select-none ', - chapterListNavButton: 'select-none ', + mediaPlayerWrap: 'w-full flex flex-col justify-center', + mediaPlayerHeader: '', + mediaPlayerBody: '', + mediaPlayerNavRow: 'grid grid-cols-5 px-2 text-stone-700 dark:text-stone-300 divide-x divide-stone-500 dark:divide-stone-600', + bibleListNavButton: '', + bookListNavButton: '', + chapterListNavButton: '', - volumeRow: 'select-none flex mx-auto w-full max-w-md justify-center items-center px-8 bg-stone-100 text-xs', - volumeControl: 'select-none volume-control w-full', - volumeInput: 'select-none w-full', - volumeLabel: 'select-none flex flex-row pl-2 mx-4 w-1/2', + volumeRow: 'flex mx-auto w-full max-w-md justify-center items-center px-8 bg-stone-100 text-xs', + volumeControl: 'volume-control w-full', + volumeInput: 'w-full', + volumeLabel: 'flex flex-row pl-2 mx-4 w-1/2', - selectBookChapterWrap: 'select-none relative bg-stone-100 flex flex-row gap-2 w-full max-w-md mx-auto', - selectBook: 'select-none inline-flex items-center gap-x-1.5 bg-stone-100 hover:bg-stone-200 px-3 py-2 w-full', - selectChapter: 'select-none inline-flex items-center text-center bg-stone-100 w-12 hover:bg-stone-200 border-none appearance-none', - selectVerseSeparator: 'select-none inline-flex items-center bg-stone-100', + selectBookChapterWrap: 'relative bg-stone-100 flex flex-row gap-2 w-full max-w-md mx-auto', + selectBook: 'inline-flex items-center gap-x-1.5 bg-stone-100 hover:bg-stone-200 px-3 py-2 w-full', + selectChapter: 'inline-flex items-center text-center bg-stone-100 w-12 hover:bg-stone-200 border-none appearance-none', + selectVerseSeparator: 'inline-flex items-center bg-stone-100', selectVerse: "inline-flex items-center text-center bg-stone-100 w-12 hover:bg-stone-200 border-none appearance-none", bibleButton: { - wrapper: 'select-none flex flex-row bg-stone-100 border border-stone-200 rounded min-h-20 hover:bg-stone-200', - languageWrap: 'select-none py-1 bg-stone-200 h-full w-24 flex flex-col justify-center items-center', - language: 'select-none text-sm font-medium text-stone-900', - iso: 'select-none truncate font-mono mt-1 text-sm text-stone-500', - titleWrap: 'select-none py-1 h-full w-full flex flex-col justify-center items-center', - title: 'select-none line-clamp-2 text-center text-sm font-medium text-stone-900', - vernacular: 'select-none line-clamp-1 text-sm text-stone-500', + wrapper: 'relative bg-stone-100 border border-stone-200 rounded min-h-20', + button: 'flex flex-row bg-stone-100 h-full w-full hover:bg-stone-200', + languageWrap: 'py-1 bg-stone-200 h-full w-24 flex flex-col justify-center items-center', + language: 'text-sm font-medium text-stone-900', + iso: 'truncate font-mono mt-1 text-sm text-stone-500', + titleWrap: 'py-1 h-full w-full flex flex-col justify-center items-center', + title: 'line-clamp-2 text-center text-sm font-medium text-stone-900', + vernacular: 'text-sm text-stone-500 max-w-64', + download: 'absolute text-stone-500 right-0 bottom-0 rounded-tl size-8 flex justify-center items-center bg-stone-200 hover:bg-stone-300' + }, + + bibleDownloadDialog: { + wrapper: 'p-4 shadow-lg text-center', + button_download: 'px-5 py-2 mx-1 bg-blue-500 text-white rounded cursor-pointer', + cancel: 'px-5 py-2 mx-1 bg-red-600 text-white rounded cursor-pointer', + audio_copyright: 'block text-stone-600', + text_copyright: 'block text-stone-600 text-sm', }, - sleepTimerButton: 'select-none sleep-timer-button group block py-1.5 px-1', - sleepTimerDuration: 'select-none text-xs pl-1 pt-2 inline-block timer-display', - sleepTimerWrap: 'select-none flex flex-row justify-center align-start text-stone-400 hover:text-blue-600', - searchWrapper: 'select-none mx-auto flex items-center w-1/3 my-3', - searchInput: 'select-none px-4 py-2 w-full max-w-7xl mx-auto bg-white border border-stone-200', + sleepTimerButton: 'sleep-timer-button group block py-1.5 px-1', + sleepTimerDuration: 'text-xs pl-1 pt-2 inline-block timer-display', + sleepTimerWrap: 'flex flex-row justify-center align-start text-stone-400 hover:text-blue-600', + searchWrapper: 'mx-auto flex items-center w-1/3 my-3', + searchInput: 'px-4 py-2 w-full max-w-7xl mx-auto bg-white border border-stone-200', - searchInputContainer: 'select-none flex w-full max-w-xl mx-auto my-4', - bookListContainer: 'select-none w-full', - bookListGrid: 'select-none grid grid-cols-3 md:grid-cols-4 gap-2', - bookListButton: 'select-none bg-stone-100 border rounded md:rounded-lg', - bookListButtonActive: 'select-none bg-stone-100 border border-stone-300', - bookListTitle: 'select-none font-medium text-sm lg:text-base', - bookListId: 'select-none w-full flex justify-end opacity-60 text-sm mr-8', - chapterButton: 'select-none bg-stone-100/90 w-12 h-12 m-2 border border-stone-700 rounded text-lg hover:bg-stone-300', - chapterButtonActive: 'select-none bg-stone-500 text-stone-100' + searchInputContainer: 'flex w-full max-w-xl mx-auto my-4', + bookListContainer: 'w-full', + bookListGrid: 'grid grid-cols-3 md:grid-cols-4 gap-2', + bookListButton: 'bg-stone-100 border rounded md:rounded-lg', + bookListButtonActive: 'bg-stone-100 border border-stone-300', + bookListTitle: 'font-medium text-sm lg:text-base', + bookListId: 'w-full flex justify-end opacity-60 text-sm mr-8', + chapterButton: 'bg-stone-100/90 w-12 h-12 m-2 border border-stone-700 rounded text-lg hover:bg-stone-300', + chapterButtonActive: 'bg-stone-500 text-stone-100' }; /** @@ -137,8 +148,7 @@ const defaultIcons = { play: ``, pause: ``, volumeIcon: ``, - - + download: `` } export const mergeIcons = (customIcons = {}) => { diff --git a/src/MediaSleepTimer.js b/src/MediaSleepTimer.js index 7bf4997..eac9faf 100644 --- a/src/MediaSleepTimer.js +++ b/src/MediaSleepTimer.js @@ -2,7 +2,6 @@ import { elem, formatTime } from "./AudioPlayerHelpers.js"; export function createVolumeAndSleepControls(ctx) { const volumeRow = elem('div', { className: ctx.class.volumeRow }); - const volumeInput = elem('input', { type: 'range', min: '0', @@ -13,10 +12,7 @@ export function createVolumeAndSleepControls(ctx) { value: ctx.audio.volume, 'aria-label': 'Volume Control' }); - volumeInput.addEventListener('input', () => { - ctx.audio.volume = parseFloat(volumeInput.value); - }); - + volumeInput.addEventListener('input', () => {ctx.audio.volume = parseFloat(volumeInput.value)}); const volumeLabel = elem('label', { htmlFor: 'volume-control', className: ctx.class.volumeLabel, @@ -25,24 +21,18 @@ export function createVolumeAndSleepControls(ctx) { volumeLabel.appendChild(volumeInput); volumeRow.appendChild(volumeLabel); - const sleepTimerButton = elem('button', { - className: ctx.class.sleepTimerButton, - innerHTML: ctx.icons.sleepTimer, - 'aria-label': 'Sleep Timer' - }); + const sleepTimerButton = createSleepTimer(ctx, volumeInput); + volumeRow.appendChild(sleepTimerButton) + return volumeRow; +} +function createSleepTimer(ctx, volumeInput) { + const sleepTimerButton = elem('button', {className: ctx.class.sleepTimerButton,innerHTML: ctx.icons.sleepTimer,'aria-label': 'Sleep Timer'}); let sleepTimer = null; let elapsedTime = 0; const sleepDuration = 1 * 60 * 1000; - - const sleepTimerDuration = elem('span', { - className: ctx.class.sleepTimerDuration, - textContent: formatTime(sleepDuration / 1000), - 'aria-live': 'polite' - }); - + const sleepTimerDuration = elem('span', {className: ctx.class.sleepTimerDuration,textContent: formatTime(sleepDuration / 1000),'aria-live': 'polite'}); sleepTimerButton.appendChild(sleepTimerDuration); - sleepTimerButton.addEventListener('click', () => { if (sleepTimer) { clearInterval(sleepTimer); @@ -81,8 +71,5 @@ export function createVolumeAndSleepControls(ctx) { sleepIcon.setAttribute('stroke-dashoffset', (1 - percentageElapsed) * dashArray); } } - - volumeRow.appendChild(sleepTimerButton); - - return volumeRow; + return sleepTimerButton; } diff --git a/src/demo/blue-theme.html b/src/demo/blue-theme.html index 749cd97..fbf9550 100644 --- a/src/demo/blue-theme.html +++ b/src/demo/blue-theme.html @@ -11,17 +11,389 @@