457 lines
34 KiB
HTML
457 lines
34 KiB
HTML
<div class="section-head">
|
||
<span class="section-icon"><span class="mdi mdi-newspaper-variant-outline"></span></span>
|
||
<div class="section-title">
|
||
<h2>Magazines</h2>
|
||
<p>Listen to a magazine one article at a time — from its true beginning to its true end, without adverts, sidebars or a neighbouring piece spliced into the middle.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── Library ──────────────────────────────────────────────────────── -->
|
||
<div id="mag-view-library">
|
||
<div class="card mag-new">
|
||
<h3>Add a magazine or paper</h3>
|
||
<div class="reader-source-grid">
|
||
<div class="reader-paste-panel">
|
||
<div class="reader-source-method">
|
||
<span class="mdi mdi-file-document-edit-outline"></span>
|
||
<div><strong>Import & Metadata</strong><span>Select a PDF file or configure optional title and issue details.</span></div>
|
||
</div>
|
||
<div class="mag-new-grid" style="margin-top: 4px; margin-bottom: 4px;">
|
||
<label for="mag-new-title">Title <span class="muted">(optional)</span>
|
||
<input id="mag-new-title" type="text" placeholder="Auto-filled from PDF filename if blank" autocomplete="off">
|
||
</label>
|
||
<label for="mag-new-issue">Issue <span class="muted">(optional)</span>
|
||
<input id="mag-new-issue" type="text" placeholder="e.g. September 2026" autocomplete="off">
|
||
</label>
|
||
</div>
|
||
<div class="reader-paste-actions" style="margin-top: auto; padding-top: 6px;">
|
||
<label class="btn-primary btn-sm reader-file-pick" id="mag-browse-btn" title="Choose a PDF file or page images (PNG/JPEG) from your computer">
|
||
<span class="mdi mdi-folder-open-outline"></span> Durchsuchen
|
||
<input type="file" id="mag-new-file" accept="application/pdf,image/png,image/jpeg" multiple style="display:none">
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="reader-dropzone" id="mag-dropzone" style="cursor: pointer;">
|
||
<span class="mdi mdi-cloud-upload-outline reader-dropzone-icon" id="mag-dropzone-icon"></span>
|
||
<strong id="mag-dropzone-title">Drop a PDF or page images</strong>
|
||
<span class="note" id="mag-dropzone-note">Scanned issues work too — pages without selectable text are read with OCR.</span>
|
||
<div class="mag-dropzone-progress" id="mag-dropzone-progress" hidden>
|
||
<div class="mag-dropzone-progress-bar"></div>
|
||
</div>
|
||
<label class="btn-secondary btn-sm reader-file-pick" id="mag-dropzone-pick-btn" title="Choose a PDF file or page images (PNG/JPEG)">
|
||
<span class="mdi mdi-file-upload-outline"></span> Import PDF or images
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card mag-find">
|
||
<h3>Find an issue online</h3>
|
||
<p class="note">Search the Internet Archive and any OPDS catalogue you have set up (Calibre-Web, Kavita, Komga). Only freely downloadable PDFs are listed; check the licence shown before you use one.</p>
|
||
<form class="mag-find-form" id="mag-find-form" onsubmit="magFindSearch(event)" role="search">
|
||
<label for="mag-find-source">Source
|
||
<select id="mag-find-source"></select>
|
||
</label>
|
||
<label for="mag-find-query" class="mag-find-query">Search
|
||
<input id="mag-find-query" type="search" maxlength="200" autocomplete="off" placeholder="e.g. Scientific American 1923">
|
||
</label>
|
||
<button type="submit" class="btn-primary btn-sm" id="mag-find-btn"><span class="mdi mdi-magnify" aria-hidden="true"></span> Search</button>
|
||
</form>
|
||
<details class="mag-cat" id="mag-cat">
|
||
<summary>Your catalogues (OPDS)</summary>
|
||
<p class="note">Add your own library (Calibre-Web, Kavita, Komga) or any OPDS address. If it needs a login, enter the username and the <strong>name of the environment variable</strong> that holds the password — the password itself is never stored here.</p>
|
||
<ul class="mag-cat-list" id="mag-cat-list"></ul>
|
||
<form class="mag-cat-form" id="mag-cat-form" onsubmit="magCatAdd(event)">
|
||
<label for="mag-cat-name">Name <input id="mag-cat-name" type="text" maxlength="80" autocomplete="off" placeholder="My NAS"></label>
|
||
<label for="mag-cat-url">Address <input id="mag-cat-url" type="url" required maxlength="500" autocomplete="off" placeholder="http://nas.local:8083/opds/"></label>
|
||
<label for="mag-cat-user">Username <span class="muted">(optional)</span> <input id="mag-cat-user" type="text" maxlength="120" autocomplete="off"></label>
|
||
<label for="mag-cat-env">Password variable <span class="muted">(optional)</span> <input id="mag-cat-env" type="text" maxlength="64" autocomplete="off" placeholder="NAS_OPDS_PASSWORD" pattern="[A-Z_][A-Z0-9_]*"></label>
|
||
<button type="submit" class="btn-secondary btn-sm"><span class="mdi mdi-plus" aria-hidden="true"></span> Add catalogue</button>
|
||
</form>
|
||
<p class="note" id="mag-cat-status" role="status" aria-live="polite"></p>
|
||
</details>
|
||
<p class="note" id="mag-find-status" role="status" aria-live="polite"></p>
|
||
<ul class="mag-find-results" id="mag-find-results"></ul>
|
||
</div>
|
||
|
||
<h3>Your magazines</h3>
|
||
<div id="mag-library-list" class="mag-grid"></div>
|
||
</div>
|
||
|
||
<!-- ── Contents ─────────────────────────────────────────────────────── -->
|
||
<div id="mag-view-contents" hidden>
|
||
<div class="mag-bar">
|
||
<button type="button" class="btn-sm" onclick="magBackToLibrary()">
|
||
<span class="mdi mdi-arrow-left"></span> All magazines
|
||
</button>
|
||
<h3 id="mag-doc-title" contenteditable="true" spellcheck="false" title="Click to edit the magazine title"
|
||
onblur="magCommitDocField(this, 'title')"
|
||
onkeydown="if(event.key==='Enter'){event.preventDefault();this.blur();}">Magazine</h3>
|
||
<input id="mag-doc-issue" type="text" class="mag-doc-issue-input" placeholder="Issue, e.g. September 2026"
|
||
title="Issue date -- used for the year/month in exported MP3 filenames"
|
||
onblur="magCommitDocField(this, 'issue')"
|
||
onkeydown="if(event.key==='Enter'){this.blur();}">
|
||
<div class="mag-bar-actions">
|
||
<button type="button" class="btn-sm" id="mag-quality-run-btn" onclick="magQualityRun()"
|
||
title="Fix every page automatically (boxes, inset pull quotes, missed text, misread words, spelling) and list the pages that still need a look">
|
||
<span class="mdi mdi-clipboard-check-outline"></span> <span class="mag-qrun-label">Auto-fix all pages</span>
|
||
</button>
|
||
<button type="button" class="btn-sm" id="mag-contents-view-toggle" onclick="magToggleContentsView()" title="Switch between an article list and a page-by-page thumbnail grid">
|
||
<span class="mdi mdi-view-grid-outline"></span> Thumbnails
|
||
</button>
|
||
<span class="mag-cols-control" id="mag-cols-control" hidden>
|
||
<label for="mag-cols-range">Columns</label>
|
||
<input type="range" id="mag-cols-range" min="1" max="12" step="1" value="8" oninput="magSetPagesCols(this.value)">
|
||
<span id="mag-cols-value" class="muted">8</span>
|
||
</span>
|
||
<button type="button" class="btn-sm" id="mag-contents-select-toggle" aria-pressed="false" onclick="magContentsToggleSelect()" title="Select several articles to approve or reject at once">
|
||
<span class="mdi mdi-checkbox-multiple-marked-outline"></span> Select
|
||
</button>
|
||
<button type="button" class="btn-sm" id="mag-playlist-toggle" aria-pressed="false" onclick="magTogglePlaylist()"
|
||
title="Show every article with a generated MP3, in reading order, with a player">
|
||
<span class="mdi mdi-playlist-music-outline"></span> Playlist
|
||
</button>
|
||
<button type="button" class="btn-sm" id="mag-driving-open" onclick="magOpenDriving()"
|
||
title="Open the magazine playlist with large, distraction-free controls">
|
||
<span class="mdi mdi-car-outline"></span> Driving mode
|
||
</button>
|
||
<button type="button" class="btn-sm" id="mag-share-book" onclick="magShare()"
|
||
aria-label="Share a link that opens this magazine in driving mode" title="Share a link that opens this magazine in driving mode">
|
||
<span class="mdi mdi-share-variant-outline" aria-hidden="true"></span> Share
|
||
</button>
|
||
<button type="button" class="btn-sm primary" onclick="magPlayAll()">
|
||
<span class="mdi mdi-playlist-play"></span> Play all articles
|
||
</button>
|
||
<button type="button" class="btn-sm" onclick="magIngest()">
|
||
<span class="mdi mdi-refresh"></span> Re-run detection
|
||
</button>
|
||
<button type="button" class="btn-sm" onclick="magReocrMagazine()" title="Send every page through the configured OCR engine again, then re-detect articles">
|
||
<span class="mdi mdi-text-recognition"></span> OCR again (whole magazine)
|
||
</button>
|
||
<button type="button" class="btn-sm" id="mag-refine-all-figures-btn" onclick="magRefineAllFigures()"
|
||
title="Batch-check figure boundaries on every page in this magazine">
|
||
<span class="mdi mdi-image-auto-adjust"></span> Fix all figure boundaries
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="mag-quality-report" class="mag-quality-report" role="region" aria-label="Quality check result" aria-live="polite" hidden></div>
|
||
<div id="mag-contents-bulkbar" class="mag-bulkbar" hidden></div>
|
||
<div class="mag-audio-export">
|
||
<label for="mag-audio-voice">Narrator for exported MP3s</label>
|
||
<select id="mag-audio-voice"></select>
|
||
<label for="mag-audio-interview-voice">Interview voice 2 (optional)</label>
|
||
<select id="mag-audio-interview-voice" title="When an article contains two recurring speaker labels, the second speaker uses this voice. Normal articles are unaffected.">
|
||
<option value="">— use narrator only —</option>
|
||
</select>
|
||
<button type="button" class="btn-sm" id="mag-audio-export-btn" onclick="magGenerateAllAudio()"
|
||
title="Render every approved article that doesn't already have an MP3 -- title, author, cover image and full text embedded as tags -- for a phone's own music/podcast player or a car head unit. Safe to click again after an aborted run: already-generated articles are skipped.">
|
||
<span class="mdi mdi-file-music-outline"></span> Generate all audio (MP3)
|
||
</button>
|
||
<button type="button" class="btn-sm" id="mag-audio-rebuild-btn" onclick="magGenerateAllAudio(true)"
|
||
title="Rebuild every approved MP3 using the latest OCR cleanup, pronunciation and interview-voice settings. Existing files are replaced.">
|
||
<span class="mdi mdi-refresh"></span> Regenerate all MP3s
|
||
</button>
|
||
<a class="btn-sm" id="mag-audio-zip-link" href="#" hidden download>
|
||
<span class="mdi mdi-folder-zip-outline"></span> Download all (ZIP)
|
||
</a>
|
||
<a class="btn-sm" id="mag-epub-link" href="#" hidden download
|
||
title="An EPUB 3 book whose text highlights while the audio plays (Media Overlays). Approved articles that already have audio.">
|
||
<span class="mdi mdi-book-open-page-variant-outline" aria-hidden="true"></span> EPUB with audio
|
||
</a>
|
||
<span class="mag-audio-export-progress-wrap" hidden id="mag-audio-export-progress-wrap">
|
||
<progress id="mag-audio-export-progress" max="1" value="0"></progress>
|
||
<span id="mag-audio-export-count" class="muted"></span>
|
||
</span>
|
||
<span id="mag-audio-export-status" class="muted" role="status" aria-live="polite"></span>
|
||
</div>
|
||
<div id="mag-playlist" class="mag-playlist" hidden>
|
||
<div class="mag-playlist-heading">
|
||
<div>
|
||
<strong>Magazine playlist</strong>
|
||
<span class="muted">Page · article · duration</span>
|
||
</div>
|
||
<label class="mag-karaoke-toggle" title="Highlight the sentence and word approximately as the MP3 plays">
|
||
<input type="checkbox" id="mag-playlist-karaoke" checked onchange="magPlaylistSync()">
|
||
Follow spoken text
|
||
</label>
|
||
</div>
|
||
<div class="mag-playlist-player">
|
||
<img id="mag-playlist-cover" class="mag-playlist-cover" alt="" hidden>
|
||
<div class="mag-playlist-nowplaying">
|
||
<strong id="mag-playlist-title">—</strong>
|
||
<span id="mag-playlist-sub" class="muted"></span>
|
||
<audio id="mag-playlist-audio" controls preload="none" style="width:100%"></audio>
|
||
</div>
|
||
<button type="button" class="btn-sm" onclick="magShareCurrent()" title="Share a link to this article" aria-label="Share a link to this article">
|
||
<span class="mdi mdi-share-variant-outline" aria-hidden="true"></span>
|
||
</button>
|
||
<button type="button" class="btn-sm" onclick="magTogglePlaylist()" title="Close playlist" aria-label="Close playlist">
|
||
<span class="mdi mdi-close"></span>
|
||
</button>
|
||
</div>
|
||
<ol id="mag-playlist-tracks" class="mag-playlist-tracks"></ol>
|
||
<div id="mag-playlist-companion" class="mag-playlist-companion" hidden>
|
||
<figure id="mag-playlist-visual" class="mag-playlist-visual" hidden></figure>
|
||
<div>
|
||
<div id="mag-playlist-sync-note" class="mag-playlist-sync-note muted">Text timing is estimated from the MP3 position.</div>
|
||
<article id="mag-playlist-transcript" class="mag-playlist-transcript" aria-label="Article transcript"></article>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="mag-ingest-status" class="mag-status" hidden></div>
|
||
<!-- Decorative "watch it work" visualisation -- the essential
|
||
progress information (percentage, page count, done/failed) is
|
||
in #mag-ingest-status above, which is what a screen reader user
|
||
needs; this panel adds nothing beyond that but noisy churn. -->
|
||
<div id="mag-ingest-preview" class="mag-ingest-preview" hidden aria-hidden="true">
|
||
<div class="mag-ingest-preview-side">
|
||
<span class="mag-ingest-preview-label">Page <span id="mag-ingest-preview-stage"></span></span>
|
||
<div class="mag-ingest-preview-canvas">
|
||
<img id="mag-ingest-preview-img" alt="Page currently being read">
|
||
<div id="mag-ingest-preview-boxes" class="mag-ingest-preview-boxes"></div>
|
||
</div>
|
||
<div id="mag-ingest-preview-legend" class="mag-ingest-preview-legend"></div>
|
||
</div>
|
||
<div class="mag-ingest-preview-resize" id="mag-ingest-preview-resize" role="separator" aria-orientation="vertical" aria-label="Resize page and recognised text panes" title="Drag to resize page and recognised text panes"></div>
|
||
<div class="mag-ingest-preview-side">
|
||
<span class="mag-ingest-preview-label">Recognised text</span>
|
||
<div id="mag-ingest-preview-text" class="mag-ingest-preview-text"></div>
|
||
</div>
|
||
</div>
|
||
<div id="mag-contents"></div>
|
||
</div>
|
||
|
||
<!-- ── Review (Stage D) ─────────────────────────────────────────────── -->
|
||
<div id="mag-view-review" hidden>
|
||
<div class="mag-bar">
|
||
<h3>Review article boundaries</h3>
|
||
</div>
|
||
<div id="mag-review"></div>
|
||
</div>
|
||
|
||
<!-- ── Reading ──────────────────────────────────────────────────────── -->
|
||
<div id="mag-view-read" hidden>
|
||
<div class="mag-bar">
|
||
<button type="button" class="btn-sm" onclick="magBackToContents()">
|
||
<span class="mdi mdi-arrow-left"></span> Contents
|
||
</button>
|
||
<div class="mag-read-id">
|
||
<h3 id="mag-read-title">Article</h3>
|
||
<span id="mag-read-by" class="muted"></span>
|
||
<span id="mag-read-pages" class="muted"></span>
|
||
</div>
|
||
<button type="button" class="btn-sm" onclick="magToggleDriving()" title="Large controls for listening without looking at the screen">
|
||
<span class="mdi mdi-car-outline"></span> Driving mode
|
||
</button>
|
||
</div>
|
||
|
||
<div class="mag-controls">
|
||
<div class="mag-voice-pick">
|
||
<label for="mag-voice">Narrator</label>
|
||
<select id="mag-voice"></select>
|
||
</div>
|
||
<button type="button" class="btn primary" id="mag-play" onclick="magPlay()"
|
||
aria-label="Play narration">
|
||
<span class="mdi mdi-play"></span> Listen
|
||
</button>
|
||
<button type="button" class="btn" id="mag-prepare" onclick="magPrepareAudio()"
|
||
title="Synthesise the whole article now, so it plays straight through without waiting sentence by sentence">
|
||
<span class="mdi mdi-waveform"></span> Prepare audio
|
||
</button>
|
||
<span id="mag-prep-status" class="muted" role="status" aria-live="polite"></span>
|
||
<span id="mag-read-progress" class="muted" aria-live="polite"></span>
|
||
<span id="mag-queue-progress" class="muted" aria-live="polite"></span>
|
||
<label class="mag-karaoke-toggle" title="Highlight each word approximately as it is spoken">
|
||
<input type="checkbox" id="mag-karaoke-cb" checked onchange="TTVC.magazine.karaoke = this.checked">
|
||
Word highlighting
|
||
</label>
|
||
<label class="mag-karaoke-toggle" title="Speak each figure's description where it appears, if one has been generated in review. Takes effect next time this article is opened.">
|
||
<input type="checkbox" id="mag-read-descriptions">
|
||
Read figure descriptions
|
||
</label>
|
||
<div class="mag-pane-tabs" role="group" aria-label="Reading view">
|
||
<button type="button" class="btn-sm active" data-mag-pane="reflow"
|
||
aria-pressed="true" onclick="magSetPane('reflow')">Article</button>
|
||
<button type="button" class="btn-sm" data-mag-pane="pdf"
|
||
aria-pressed="false" onclick="magSetPane('pdf')">Original page</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="mag-pane-reflow" class="mag-pane">
|
||
<div id="mag-read-image" class="mag-read-image" hidden></div>
|
||
<div id="mag-article" class="mag-article"></div>
|
||
</div>
|
||
|
||
<div id="mag-pane-pdf" class="mag-pane" hidden>
|
||
<div class="mag-page-wrap">
|
||
<img id="mag-page-img" alt="">
|
||
<div id="mag-page-box" class="mag-page-box" hidden></div>
|
||
</div>
|
||
<p id="mag-page-label" class="muted"></p>
|
||
</div>
|
||
|
||
<!-- Pronunciation and spelling -->
|
||
<details class="card mag-checks" id="mag-checks" ontoggle="magChecksToggled(this)">
|
||
<summary><span class="mdi mdi-spellcheck"></span> Pronunciation & spelling — check this article</summary>
|
||
<div id="mag-checks-body" aria-live="polite"></div>
|
||
</details>
|
||
|
||
<!-- Podcast mode -->
|
||
<details class="card mag-podcast">
|
||
<summary><span class="mdi mdi-podcast"></span> Podcast mode — discuss this article</summary>
|
||
<p class="muted">Two or three hosts discuss the article for someone who has not read it. The script is written by the configured LLM from the article text; it will not invent facts, but it is a generated discussion, not the author’s words.</p>
|
||
<div class="mag-hosts">
|
||
<div class="mag-voice-pick"><label for="mag-host-a">Host A</label><select id="mag-host-a"></select></div>
|
||
<div class="mag-voice-pick"><label for="mag-host-b">Host B</label><select id="mag-host-b"></select></div>
|
||
<div class="mag-voice-pick"><label for="mag-host-c">Host C <span class="muted">(optional)</span></label><select id="mag-host-c"></select></div>
|
||
</div>
|
||
<div class="mag-podcast-actions">
|
||
<button type="button" class="btn" id="mag-podcast-gen" onclick="magGeneratePodcast()">Generate script</button>
|
||
<button type="button" class="btn primary" id="mag-podcast-play" onclick="magPlayPodcast()" hidden>Play podcast</button>
|
||
</div>
|
||
<div id="mag-podcast-script"></div>
|
||
</details>
|
||
</div>
|
||
|
||
<div id="mag-share-sheet" class="mag-share-sheet" role="dialog" aria-label="Share link" hidden>
|
||
<label for="mag-share-link">Copy this link</label>
|
||
<input type="text" id="mag-share-link" readonly>
|
||
<button type="button" class="btn-sm" onclick="magShareClose()">Close</button>
|
||
</div>
|
||
|
||
<!-- ── Driving mode overlay ─────────────────────────────────────────── -->
|
||
<!-- Large controls, minimal text, no interaction required beyond play/
|
||
pause/skip -- reuses whatever is already playing rather than its
|
||
own playback path. -->
|
||
<div id="mag-driving" class="mag-driving" hidden role="dialog" aria-label="Driving mode" data-view="split">
|
||
<!-- Layout: top bar / flexible content / controls dock. The dock is never scrolled or overlapped. -->
|
||
<div class="mag-driving-top">
|
||
<button type="button" class="mag-driving-share" onclick="magShareCurrent()" aria-label="Share a link to this article" title="Share a link to this article">
|
||
<span class="mdi mdi-share-variant-outline" aria-hidden="true"></span>
|
||
</button>
|
||
<div class="mag-driving-menuwrap">
|
||
<button type="button" class="mag-driving-menubtn" id="mag-driving-menubtn" aria-expanded="false" aria-controls="mag-driving-menu"
|
||
aria-label="Display menu: Split" title="Display menu">
|
||
<span class="mdi mdi-view-split-horizontal" aria-hidden="true"></span><span class="mag-driving-view-label" id="mag-driving-menulabel">Split</span>
|
||
</button>
|
||
<div class="mag-driving-menu" id="mag-driving-menu" role="group" aria-label="Display options" hidden>
|
||
<div class="mag-menu-sec" id="mag-menu-sec-view">View</div>
|
||
<div role="radiogroup" aria-labelledby="mag-menu-sec-view" class="mag-menu-views">
|
||
<button type="button" role="radio" aria-checked="false" tabindex="-1" data-view="picture"><span class="mdi mdi-image-outline" aria-hidden="true"></span><span class="mag-menu-label">Picture<small>whole picture, no text</small></span><span class="mag-radio" aria-hidden="true"></span></button>
|
||
<button type="button" role="radio" aria-checked="false" tabindex="-1" data-view="text"><span class="mdi mdi-text-long" aria-hidden="true"></span><span class="mag-menu-label">Text<small>whole text, no picture</small></span><span class="mag-radio" aria-hidden="true"></span></button>
|
||
<button type="button" role="radio" aria-checked="true" tabindex="-1" data-view="split"><span class="mdi mdi-view-split-horizontal" aria-hidden="true"></span><span class="mag-menu-label">Split<small>picture and text, amount below</small></span><span class="mag-radio" aria-hidden="true"></span></button>
|
||
</div>
|
||
<hr role="separator">
|
||
<div class="mag-menu-sec" id="mag-menu-sec-amount">Text in Split view</div>
|
||
<div role="radiogroup" aria-labelledby="mag-menu-sec-amount" class="mag-seg mag-seg-amount">
|
||
<button type="button" role="radio" aria-checked="true" tabindex="-1" data-amount="sentence" title="Only the sentence being read, large"><span>Sentence</span><span class="mdi mdi-check mag-seg-check" aria-hidden="true"></span></button>
|
||
<button type="button" role="radio" aria-checked="false" tabindex="-1" data-amount="context" title="The sentence with the previous and next one dimmed"><span>Context</span><span class="mdi mdi-check mag-seg-check" aria-hidden="true"></span></button>
|
||
<button type="button" role="radio" aria-checked="false" tabindex="-1" data-amount="paragraph" title="The whole paragraph with the current sentence marked"><span>Paragraph</span><span class="mdi mdi-check mag-seg-check" aria-hidden="true"></span></button>
|
||
</div>
|
||
<hr role="separator">
|
||
<div class="mag-menu-sec" id="mag-menu-sec-show">Show</div>
|
||
<div role="group" aria-labelledby="mag-menu-sec-show">
|
||
<button type="button" role="switch" aria-checked="true" tabindex="-1" class="mag-menu-switch" id="mag-driving-text-toggle" onclick="magDrivingToggleText()"
|
||
title="Show or hide the text being read"><span class="mag-menu-label">Show text</span><span class="mag-sw" aria-hidden="true"><span class="mag-sw-thumb"><span class="mdi mdi-check mag-sw-on"></span><span class="mdi mdi-close mag-sw-off"></span></span></span></button>
|
||
<button type="button" role="switch" aria-checked="true" tabindex="-1" class="mag-menu-switch" id="mag-driving-image-toggle" onclick="magDrivingToggleImages()"
|
||
title="Show or hide the article's pictures"><span class="mag-menu-label">Show pictures</span><span class="mag-sw" aria-hidden="true"><span class="mag-sw-thumb"><span class="mdi mdi-check mag-sw-on"></span><span class="mdi mdi-close mag-sw-off"></span></span></span></button>
|
||
<button type="button" role="switch" aria-checked="false" tabindex="-1" class="mag-menu-switch" id="mag-driving-collapse" aria-controls="mag-driving-content"
|
||
onclick="magDrivingToggleCollapsed()"><span class="mag-menu-label">Minimize text and picture</span><span class="mag-sw" aria-hidden="true"><span class="mag-sw-thumb"><span class="mdi mdi-check mag-sw-on"></span><span class="mdi mdi-close mag-sw-off"></span></span></span></button>
|
||
</div>
|
||
<hr role="separator">
|
||
<div class="mag-menu-sec" id="mag-menu-sec-play">Playback</div>
|
||
<div role="group" aria-labelledby="mag-menu-sec-play">
|
||
<button type="button" role="switch" aria-checked="true" tabindex="-1" class="mag-menu-switch" id="mag-driving-autonext" onclick="magDrivingToggleAutonext()"
|
||
title="When an article ends, continue with the next one that has audio"><span class="mag-menu-label">Play next article automatically</span><span class="mag-sw" aria-hidden="true"><span class="mag-sw-thumb"><span class="mdi mdi-check mag-sw-on"></span><span class="mdi mdi-close mag-sw-off"></span></span></span></button>
|
||
</div>
|
||
<hr role="separator">
|
||
<div class="mag-menu-sec" id="mag-menu-sec-theme">Theme</div>
|
||
<div role="radiogroup" aria-labelledby="mag-menu-sec-theme" class="mag-seg">
|
||
<button type="button" role="radio" aria-checked="false" tabindex="-1" data-theme-choice="light"><span class="mdi mdi-white-balance-sunny" aria-hidden="true"></span><span>Light</span><span class="mdi mdi-check mag-seg-check" aria-hidden="true"></span></button>
|
||
<button type="button" role="radio" aria-checked="true" tabindex="-1" data-theme-choice="auto" title="Follow the system setting"><span class="mdi mdi-theme-light-dark" aria-hidden="true"></span><span>Auto</span><span class="mdi mdi-check mag-seg-check" aria-hidden="true"></span></button>
|
||
<button type="button" role="radio" aria-checked="false" tabindex="-1" data-theme-choice="dark"><span class="mdi mdi-weather-night" aria-hidden="true"></span><span>Dark</span><span class="mdi mdi-check mag-seg-check" aria-hidden="true"></span></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="mag-driving-indexbtn" id="mag-driving-indexbtn" aria-haspopup="dialog" aria-expanded="false" aria-controls="mag-driving-index"
|
||
aria-label="Article index" title="Article index" onclick="magDrivingIndexToggle()">
|
||
<span class="mdi mdi-format-list-numbered" aria-hidden="true"></span><span class="mag-driving-view-label">Index</span>
|
||
</button>
|
||
<span class="mag-driving-topspacer"></span>
|
||
<button type="button" class="mag-driving-exit" onclick="magToggleDriving()" aria-label="Exit driving mode">
|
||
<span class="mdi mdi-close" aria-hidden="true"></span>
|
||
</button>
|
||
</div>
|
||
<div class="mag-driving-content" id="mag-driving-content">
|
||
<button type="button" class="mag-driving-start" id="mag-driving-start" onclick="magDrivingStart()" hidden>
|
||
<span class="mdi mdi-play-circle-outline" aria-hidden="true"></span> Tap to play
|
||
</button>
|
||
<div class="mag-driving-head">
|
||
<h2 id="mag-driving-title">Article</h2>
|
||
<p id="mag-driving-by" class="muted"></p>
|
||
<p id="mag-driving-endstate" class="mag-driving-endstate" hidden><span class="mdi mdi-flag-checkered" aria-hidden="true"></span> End of magazine</p>
|
||
<div id="mag-driving-announce" class="sr-only" role="status" aria-live="polite" aria-atomic="true"></div>
|
||
<div id="mag-driving-queue" class="mag-driving-queue" hidden>
|
||
<span id="mag-queue-progress-2" class="muted"></span>
|
||
</div>
|
||
</div>
|
||
<div class="mag-driving-stagewrap">
|
||
<figure id="mag-driving-visual" class="mag-driving-visual" hidden>
|
||
<div class="mag-driving-stage" id="mag-driving-stage" tabindex="0" role="group"
|
||
aria-label="Picture. Zoom with the buttons, the plus and minus keys, the mouse wheel or by pinching. Double-tap to zoom. Escape resets.">
|
||
<div class="mag-driving-pz" id="mag-driving-pz"></div>
|
||
</div>
|
||
<div class="mag-driving-zoomctl" role="group" aria-label="Zoom">
|
||
<button type="button" id="mag-driving-zoom-out" aria-label="Zoom out" title="Zoom out" onclick="magDrivingZoomBy(1/1.5)"><span class="mdi mdi-magnify-minus-outline" aria-hidden="true"></span></button>
|
||
<button type="button" id="mag-driving-zoom-in" aria-label="Zoom in" title="Zoom in" onclick="magDrivingZoomBy(1.5)"><span class="mdi mdi-magnify-plus-outline" aria-hidden="true"></span></button>
|
||
<button type="button" id="mag-driving-zoom-reset" aria-label="Reset zoom" title="Reset zoom" onclick="magDrivingZoomReset()"><span class="mdi mdi-fit-to-screen-outline" aria-hidden="true"></span></button>
|
||
</div>
|
||
<figcaption id="mag-driving-cap"></figcaption>
|
||
</figure>
|
||
<p id="mag-driving-noimg" class="mag-driving-noimg muted" hidden>No picture for this part of the article.</p>
|
||
</div>
|
||
<div id="mag-driving-lyrics" class="mag-driving-lyrics" role="group" aria-live="off" aria-label="Article text" hidden></div>
|
||
<div class="mag-driving-full-wrap">
|
||
<div id="mag-driving-full" class="mag-driving-full" role="group" aria-live="off" tabindex="0"
|
||
aria-label="Whole article text. Arrow keys move between sentences, Enter plays from the sentence."></div>
|
||
<button type="button" class="mag-driving-backcur" id="mag-driving-backcur" hidden onclick="magDrivingBackToCurrent()">
|
||
<span class="mdi mdi-crosshairs-gps" aria-hidden="true"></span> Back to current
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="mag-driving-index" id="mag-driving-index" role="dialog" aria-label="Article index" hidden>
|
||
<div class="mag-driving-index-head">
|
||
<h3 id="mag-driving-index-title">Articles</h3>
|
||
<button type="button" id="mag-driving-index-close" aria-label="Close the article index" title="Close" onclick="magDrivingIndexClose()"><span class="mdi mdi-close" aria-hidden="true"></span></button>
|
||
</div>
|
||
<ul class="mag-driving-index-list" id="mag-driving-index-list" aria-labelledby="mag-driving-index-title"></ul>
|
||
</div>
|
||
<div class="mag-driving-dock">
|
||
<div class="mag-driving-seek">
|
||
<input type="range" id="mag-driving-seek" min="0" max="1000" value="0" step="1"
|
||
aria-label="Position in article" oninput="magDrivingSeek(this.value)">
|
||
<div class="mag-driving-time" id="mag-driving-time" aria-live="off">0:00 / 0:00</div>
|
||
<button type="button" class="mag-driving-opt" id="mag-driving-speed" onclick="magDrivingCycleSpeed()"
|
||
aria-label="Playback speed 1×. Press to change" title="Playback speed">1×</button>
|
||
</div>
|
||
<div class="mag-driving-controls">
|
||
<button type="button" class="mag-driving-btn is-small" onclick="magDrivingPrevious()" aria-label="Previous article" title="Previous article">
|
||
<span class="mdi mdi-skip-previous"></span>
|
||
</button>
|
||
<button type="button" class="mag-driving-btn" onclick="magDrivingSkip(-15)" aria-label="Back 15 seconds" title="Back 15 seconds">
|
||
<span class="mdi mdi-rewind-15"></span>
|
||
</button>
|
||
<button type="button" class="mag-driving-btn mag-driving-play" id="mag-driving-play" onclick="magDrivingTogglePlayback()" aria-label="Play">
|
||
<span class="mdi mdi-play"></span>
|
||
</button>
|
||
<button type="button" class="mag-driving-btn" onclick="magDrivingSkip(15)" aria-label="Forward 15 seconds" title="Forward 15 seconds">
|
||
<span class="mdi mdi-fast-forward-15"></span>
|
||
</button>
|
||
<button type="button" class="mag-driving-btn is-small" onclick="magDrivingNext()" aria-label="Next article" title="Next article">
|
||
<span class="mdi mdi-skip-next"></span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|