PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / audio-player / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/audio-player/frontend.js

169 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 /* ── Helpers ──────────────────────────────────────────────────────────── */
5 function formatTime(secs) {
6 if (isNaN(secs) || secs < 0) return '0:00';
7 var m = Math.floor(secs / 60);
8 var s = Math.floor(secs % 60);
9 return m + ':' + (s < 10 ? '0' : '') + s;
10 }
11
12 /* ── Build SVG element ────────────────────────────────────────────────── */
13 function svgIcon(d, size) {
14 size = size || 22;
15 var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
16 svg.setAttribute('viewBox', '0 0 24 24');
17 svg.setAttribute('fill', 'currentColor');
18 svg.setAttribute('width', size);
19 svg.setAttribute('height', size);
20 var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
21 path.setAttribute('d', d);
22 svg.appendChild(path);
23 return svg;
24 }
25
26 var PLAY_PATH = 'M8 5v14l11-7z';
27 var PAUSE_PATH = 'M6 19h4V5H6v14zm8-14v14h4V5h-4z';
28
29 /* ── Init one player ──────────────────────────────────────────────────── */
30 function initAudioPlayer(wrapper) {
31 var playerEl = wrapper.querySelector('.bkbg-ap-player');
32 if (!playerEl) return;
33
34 var audioUrl = playerEl.dataset.audioUrl;
35 var audioType = playerEl.dataset.audioType || 'audio/mpeg';
36 if (!audioUrl) return;
37
38 var autoplay = playerEl.dataset.autoplay === '1';
39 var loop = playerEl.dataset.loop === '1';
40 var preload = playerEl.dataset.preload || 'metadata';
41 var showVolume = playerEl.dataset.showVolume !== '0';
42 var showSpeed = playerEl.dataset.showSpeed !== '0';
43
44 /* Audio element */
45 var audio = new Audio();
46 audio.src = audioUrl;
47 audio.preload = preload;
48 audio.loop = loop;
49 if (autoplay) { audio.autoplay = true; }
50
51 /* DOM refs */
52 var playBtn = playerEl.querySelector('.bkbg-ap-play-btn');
53 var progressTrack = playerEl.querySelector('.bkbg-ap-progress-track');
54 var progressFill = playerEl.querySelector('.bkbg-ap-progress-fill');
55 var progressThumb = playerEl.querySelector('.bkbg-ap-progress-thumb');
56 var currentEl = playerEl.querySelector('.bkbg-ap-current');
57 var durationEl = playerEl.querySelector('.bkbg-ap-duration');
58 var volSlider = playerEl.querySelector('.bkbg-ap-vol-slider');
59 var speedBtn = playerEl.querySelector('.bkbg-ap-speed-btn');
60
61 /* ── Build play button icons ────────────────────────────────────── */
62 if (playBtn) {
63 playBtn.innerHTML = '';
64 var iconPlay = svgIcon(PLAY_PATH, 22);
65 iconPlay.classList.add('bkbg-ap-icon-play');
66 var iconPause = svgIcon(PAUSE_PATH, 22);
67 iconPause.classList.add('bkbg-ap-icon-pause');
68 iconPause.style.display = 'none';
69 playBtn.appendChild(iconPlay);
70 playBtn.appendChild(iconPause);
71 }
72
73 /* ── Play/Pause ─────────────────────────────────────────────────── */
74 function updatePlayState(playing) {
75 wrapper.classList.toggle('bkbg-ap-playing', playing);
76 if (!playBtn) return;
77 var ip = playBtn.querySelector('.bkbg-ap-icon-play');
78 var ipa = playBtn.querySelector('.bkbg-ap-icon-pause');
79 if (ip) ip.style.display = playing ? 'none' : 'block';
80 if (ipa) ipa.style.display = playing ? 'block' : 'none';
81 playBtn.setAttribute('aria-label', playing ? 'Pause' : 'Play');
82 }
83
84 if (playBtn) {
85 playBtn.addEventListener('click', function () {
86 if (audio.paused) {
87 audio.play().catch(function () {});
88 } else {
89 audio.pause();
90 }
91 });
92 }
93
94 audio.addEventListener('play', function () { updatePlayState(true); });
95 audio.addEventListener('pause', function () { updatePlayState(false); });
96 audio.addEventListener('ended', function () { updatePlayState(false); });
97
98 /* ── Progress ───────────────────────────────────────────────────── */
99 audio.addEventListener('loadedmetadata', function () {
100 if (durationEl) durationEl.textContent = formatTime(audio.duration);
101 });
102
103 audio.addEventListener('timeupdate', function () {
104 if (!audio.duration) return;
105 var pct = (audio.currentTime / audio.duration) * 100;
106 if (progressFill) progressFill.style.width = pct + '%';
107 if (progressThumb) progressThumb.style.left = pct + '%';
108 if (currentEl) currentEl.textContent = formatTime(audio.currentTime);
109 });
110
111 /* Seek by clicking the track */
112 function seek(e) {
113 if (!progressTrack || !audio.duration) return;
114 var rect = progressTrack.getBoundingClientRect();
115 var x = (e.touches ? e.touches[0].clientX : e.clientX) - rect.left;
116 var pct = Math.min(1, Math.max(0, x / rect.width));
117 audio.currentTime = pct * audio.duration;
118 }
119
120 if (progressTrack) {
121 var seeking = false;
122 progressTrack.addEventListener('mousedown', function (e) {
123 seeking = true;
124 seek(e);
125 });
126 progressTrack.addEventListener('touchstart', function (e) {
127 seeking = true;
128 seek(e);
129 }, { passive: true });
130 document.addEventListener('mousemove', function (e) { if (seeking) seek(e); });
131 document.addEventListener('touchmove', function (e) { if (seeking) seek(e); }, { passive: true });
132 document.addEventListener('mouseup', function () { seeking = false; });
133 document.addEventListener('touchend', function () { seeking = false; });
134 }
135
136 /* ── Volume ─────────────────────────────────────────────────────── */
137 if (volSlider && showVolume) {
138 volSlider.value = audio.volume;
139 volSlider.addEventListener('input', function () {
140 audio.volume = parseFloat(volSlider.value);
141 });
142 }
143
144 /* ── Playback speed ─────────────────────────────────────────────── */
145 var SPEEDS = [0.5, 0.75, 1, 1.25, 1.5, 2];
146 var speedIdx = 2; // default 1×
147
148 if (speedBtn && showSpeed) {
149 speedBtn.addEventListener('click', function () {
150 speedIdx = (speedIdx + 1) % SPEEDS.length;
151 audio.playbackRate = SPEEDS[speedIdx];
152 speedBtn.textContent = SPEEDS[speedIdx] + '×';
153 });
154 }
155 }
156
157 /* ── Init all players on page ─────────────────────────────────────────── */
158 function initAll() {
159 var wrappers = document.querySelectorAll('.bkbg-ap-wrapper');
160 wrappers.forEach(initAudioPlayer);
161 }
162
163 if (document.readyState === 'loading') {
164 document.addEventListener('DOMContentLoaded', initAll);
165 } else {
166 initAll();
167 }
168 })();
169