PageSourceSearch

https://www.sante-corps-esprit.com/wp-content/themes/Core/assets/freemium/audio-player.js?ver=1786460174

js sante-corps-esprit.com collected 2026-10-02 10:30:49 UTC 9,037 bytes, 194 lines download raw bytes

1// ElevenLabs sticky audio player — externalized. Guard DOMContentLoaded:
2// init queries #ppl-audio-bar (rendered in wp_footer priority 35) → wait for DOM ready.
3(function () {
4    function pplAudioInit() {
5    (function () {
6        var LS_KEY = 'ppl_audio_session';
7        var bar = document.getElementById('ppl-audio-bar');
8        if (!bar) return;
9
10        var seek    = bar.querySelector('.ppl-audio-bar__seek');
11        var cover   = bar.querySelector('.ppl-audio-bar__cover');
12        var trackEl = bar.querySelector('.ppl-audio-bar__track');
13        var epEl    = bar.querySelector('.ppl-audio-bar__episode');
14        var curEl   = bar.querySelector('.ppl-audio-bar__cur');
15        var totEl   = bar.querySelector('.ppl-audio-bar__tot');
16        var playBtn = bar.querySelector('.ppl-audio-bar__play');
17        var prevBtn = bar.querySelector('.ppl-audio-bar__prev');
18        var nextBtn = bar.querySelector('.ppl-audio-bar__next');
19        var closeBtn= bar.querySelector('.ppl-audio-bar__close');
20        var speedSel= bar.querySelector('.ppl-audio-bar__speed');
21
22        var SPEEDS = [1, 1.25, 1.5, 1.75, 2];
23        var audio = new Audio();
24        audio.preload = 'none';
25
26        function applyRate() {
27            var r = (session && session.rate) ? session.rate : 1;
28            audio.playbackRate = r;
29            if (speedSel) speedSel.value = String(r);
30        }
31        var session = null;   // { episode: {id,title,cover,tracks:[{title,url}]}, idx, pos }
32        var saveTick = 0;
33
34        function fmt(s) {
35            if (!isFinite(s)) return '–:––';
36            s = Math.max(0, Math.floor(s));
37            return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0');
38        }
39        function load() {
40            try { return JSON.parse(localStorage.getItem(LS_KEY) || 'null'); } catch (e) { return null; }
41        }
42        function save() {
43            if (!session) return;
44            session.pos = audio.currentTime || session.pos || 0;
45            session.paused = audio.paused;
46            if (isFinite(audio.duration)) session.dur = audio.duration;
47            try { localStorage.setItem(LS_KEY, JSON.stringify(session)); } catch (e) {}
48        }
49        function clear() {
50            try { localStorage.removeItem(LS_KEY); } catch (e) {}
51        }
52
53        function render() {
54            var tr = session.episode.tracks[session.idx];
55            trackEl.textContent = tr.title;
56            epEl.textContent = session.episode.title;
57            if (session.episode.cover) { cover.src = session.episode.cover; cover.hidden = false; }
58            else cover.hidden = true;
59            prevBtn.disabled = session.idx <= 0;
60            nextBtn.disabled = session.idx >= session.episode.tracks.length - 1;
61            bar.hidden = false;
62            document.body.classList.add('ppl-audio-bar-open');
63        }
64
65        function setTrack(idx, pos) {
66            var p = pos != null ? pos : 0;
67            session.idx = idx;
68            session.pos = p;
69            if (pos == null) delete session.dur;
70            audio.src = session.episode.tracks[idx].url;
71            applyRate();
72            if (p) {
73                audio.addEventListener('loadedmetadata', function () { audio.currentTime = p; }, { once: true });
74            }
75            curEl.textContent = fmt(p);
76            var knownDur = (p && session.dur) ? session.dur : NaN;
77            totEl.textContent = fmt(knownDur);
78            var pct = (p && isFinite(knownDur)) ? Math.round((p / knownDur) * 1000) : 0;
79            seek.value = pct;
80            seek.style.setProperty('--pp', (pct / 10) + '%');
81            render();
82            save();
83            document.dispatchEvent(new CustomEvent('pplaudio:track', {
84                detail: { episodeId: session.episode.id, idx: idx }
85            }));
86        }
87
88        function show(sess, autoplay) {
89            session = sess;
90            if (!session.rate || SPEEDS.indexOf(session.rate) === -1) session.rate = 1;
91            setTrack(sess.idx || 0, sess.pos || 0);
92            if (autoplay) audio.play().catch(function () { /* blocked → wait for click */ });
93        }
94
95        /* ── Public API ─────────────────────────────────────────────── */
96        window.PPLAudio = {
97            playEpisode: function (episode, idx) {
98                show({ episode: episode, idx: idx || 0, pos: 0 }, true);
99            },
100            toggleTrack: function (episodeId, idx) {
101                if (session && session.episode.id === episodeId && session.idx === idx) {
102                    if (audio.paused) audio.play(); else audio.pause();
103                    return;
104                }
105                return false;
106            },
107            pause: function () { if (!audio.paused) audio.pause(); },
108            state: function () {
109                return session ? { episodeId: session.episode.id, idx: session.idx, playing: !audio.paused } : null;
110            }
111        };
112
113        window.addEventListener('message', function (e) {
114            if (e.origin !== window.location.origin) return;
115            if (e.data && e.data.type === 'ppl:viewer-audio-play') audio.pause();
116        });
117
118        /* ── Controls ────────────────────────────────────────────────── */
119        playBtn.addEventListener('click', function () {
120            if (audio.paused) audio.play(); else audio.pause();
121        });
122        prevBtn.addEventListener('click', function () {
123            if (session && session.idx > 0) { setTrack(session.idx - 1); audio.play(); }
124        });
125        nextBtn.addEventListener('click', function () {
126            if (session && session.idx < session.episode.tracks.length - 1) { setTrack(session.idx + 1); audio.play(); }
127        });
128        closeBtn.addEventListener('click', function () {
129            audio.pause();
130            audio.removeAttribute('src');
131            bar.hidden = true;
132            document.body.classList.remove('ppl-audio-bar-open');
133            session = null;
134            clear();
135            document.dispatchEvent(new CustomEvent('pplaudio:stop'));
136        });
137        seek.addEventListener('input', function () {
138            if (isFinite(audio.duration)) audio.currentTime = (seek.value / 1000) * audio.duration;
139        });
140        if (speedSel) speedSel.addEventListener('change', function () {
141            if (!session) return;
142            var r = parseFloat(speedSel.value) || 1;
143            session.rate = SPEEDS.indexOf(r) !== -1 ? r : 1;
144            applyRate();
145            save();
146        });
147
148        /* ── Audio events ─────────────────────────────────────────────── */
149        audio.addEventListener('play',  function () {
150            bar.classList.add('is-playing');
151            save();
152            document.dispatchEvent(new CustomEvent('pplaudio:play',  { detail: window.PPLAudio.state() }));
153        });
154        audio.addEventListener('pause', function () {
155            bar.classList.remove('is-playing');
156            save();
157            document.dispatchEvent(new CustomEvent('pplaudio:pause', { detail: window.PPLAudio.state() }));
158        });
159        audio.addEventListener('loadedmetadata', function () {
160            totEl.textContent = fmt(audio.duration);
161            if (isFinite(audio.duration)) session.dur = audio.duration;
162            applyRate(); // some browsers reset playbackRate on source load
163        });
164        audio.addEventListener('timeupdate', function () {
165            if (!isFinite(audio.duration)) return;
166            var p = Math.round((audio.currentTime / audio.duration) * 1000);
167            seek.value = p;
168            seek.style.setProperty('--pp', (p / 10) + '%');
169            curEl.textContent = fmt(audio.currentTime);
170            if (Date.now() - saveTick > 3000) { saveTick = Date.now(); save(); }
171        });
172        audio.addEventListener('ended', function () {
173            if (session && session.idx < session.episode.tracks.length - 1) {
174                setTrack(session.idx + 1);
175                audio.play();
176            } else {
177                session.pos = 0;
178                save();
179            }
180        });
181        window.addEventListener('pagehide', save);
182
183        /* ── Session resume on page load ─────────────────── */
184        var prev = load();
185        if (prev && prev.episode && prev.episode.tracks && prev.episode.tracks[prev.idx]) {
186            // Auto-resume only if playback was active when leaving page
187            // (paused by user → respect pause). If browser blocks auto
187play, bar shows paused at saved position.
188            show(prev, !prev.paused);
189        }
190    })();
191    }
192    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', pplAudioInit);
193    else pplAudioInit();
194})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.