PageSourceSearch

https://hugesounds.com/templates/HugeSound/js/hs-player.js?v=20260831-1

js hugesounds.com collected 2026-10-09 04:45:36 UTC 12,063 bytes, 445 lines download raw bytes

1(function () {
2	'use strict';
3
4	var BAR_COUNT = 72;
5
6	function t(key, fallback) {
7		var dict = window.HSLang || {};
8		return dict[key] || fallback;
9	}
10
11	function qs(sel, root) {
12		return (root || document).querySelector(sel);
13	}
14
15	function qsa(sel, root) {
16		return Array.prototype.slice.call((root || document).querySelectorAll(sel));
17	}
18
19	function mulberry32(a) {
20		return function () {
21			a |= 0;
22			a = (a + 0x6D2B79F5) | 0;
23			var t = Math.imul(a ^ (a >>> 15), 1 | a);
24			t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
25			return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
26		};
27	}
28
29	function makeWave(el, seed, count) {
30		if (!el) return [];
31		var rand = mulberry32(Math.abs(parseInt(seed, 10) || 1) * 9973);
32		var env = 0.45;
33		var html = '';
34		var i, h;
35		for (i = 0; i < count; i++) {
36			env += (rand() - 0.48) * 0.28;
37			if (env < 0.16) env = 0.16;
38			if (env > 1) env = 1;
39			h = (0.22 + rand() * 0.78) * env * 100;
40			html += '<span class="hs-bar" style="height:' + h.toFixed(1) + '%"></span>';
41		}
42		el.innerHTML = html;
43		return Array.prototype.slice.call(el.children);
44	}
45
46	function pointerX(e) {
47		if (e.touches && e.touches.length) return e.touches[0].clientX;
48		return e.clientX;
49	}
50
51	function waveHit(waveEl) {
52		var bars = qsa('.hs-bar', waveEl);
53		if (bars.length) {
54			var a = bars[0].getBoundingClientRect();
55			var b = bars[bars.length - 1].getBoundingClientRect();
56			var width = b.right - a.left;
57			if (width > 1) return { left: a.left, width: width };
58		}
59		var rect = waveEl.getBoundingClientRect();
60		return { left: rect.left, width: rect.width };
61	}
62
63	function seekRatio(e, waveEl) {
64		var hit = waveHit(waveEl);
65		if (!hit.width) return 0;
66		var p = (pointerX(e) - hit.left) / hit.width;
67		if (p < 0) p = 0;
68		if (p > 1) p = 1;
69		return p;
70	}
71
72	function setWaveProgress(el, p) {
73		if (!el) return;
74		if (p < 0) p = 0;
75		if (p > 1) p = 1;
76		el.style.setProperty('--p', (p * 100).toFixed(2) + '%');
77	}
78
79	function bindWaveSeek(waveEl, getAudio, onSeeking, onPaint) {
80		if (!waveEl) return;
81		var seeking = false;
82		function setSeeking(on) {
83			seeking = on;
84			if (onSeeking) onSeeking(on);
85		}
86		function seekFromEvent(e) {
87			var audio = getAudio();
88			if (!audio) return;
89			var dur = audio.duration;
90			if (!isFinite(dur) || dur <= 0) return;
91			var p = seekRatio(e, waveEl);
92			audio.currentTime = p * dur;
93			if (onPaint) onPaint(p);
94		}
95		waveEl.addEventListener('pointerdown', function (e) {
96			if (e.button) return;
97			e.preventDefault();
98			e.stopPropagation();
99			setSeeking(true);
100			try { waveEl.setPointerCapture(e.pointerId); } catch (err) {}
101			seekFromEvent(e);
102		});
103		waveEl.addEventListener('pointermove', function (e) {
104			if (seeking) seekFromEvent(e);
105		});
106		waveEl.addEventListener('pointerup', function () {
107			setSeeking(false);
108		});
109		waveEl.addEventListener('pointercancel', function () {
110			setSeeking(false);
111		});
112	}
113
114	function paintWave(bars, progress) {
115		if (!bars || !bars.length) return;
116		var k = progress * bars.length;
117		for (var i = 0; i < bars.length; i++) {
118			if (i < k) bars[i].classList.add('is-on');
119			else bars[i].classList.remove('is-on');
120		}
121	}
122
123	function fmt(sec) {
124		if (!isFinite(sec) || sec < 0) return '0:00';
125		sec = Math.floor(sec);
126		var m = Math.floor(sec / 60);
127		var s = sec % 60;
128		return m + ':' + (s < 10 ? '0' : '') + s;
129	}
130
131	function parseData() {
132		var node = qs('#hs-audio-data');
133		if (!node) return {};
134		try {
135			return JSON.parse(node.textContent || '{}');
136		} catch (e) {
137			return {};
138		}
139	}
140
141	function toast(text) {
142		var el = qs('#hs-toast');
143		if (!el) return;
144		el.textContent = text;
145		el.hidden = false;
146		el.classList.add('is-on');
147		clearTimeout(toast._t);
148		toast._t = setTimeout(function () {
149			el.classList.remove('is-on');
150			setTimeout(function () {
151				el.hidden = true;
152			}, 250);
153		}, 1800);
154	}
155
156	function copyText(text) {
157		if (navigator.clipboard && navigator.clipboard.writeText) {
158			return navigator.clipboard.writeText(text);
159		}
160		return new Promise(function (resolve, reject) {
161			var ta = document.createElement('textarea');
162			ta.value = text;
163			ta.setAttribute('readonly', '');
164			ta.style.position = 'fixed';
165			ta.style.left = '-9999px';
166			document.body.appendChild(ta);
167			ta.select();
168			try {
169				document.execCommand('copy');
170				resolve();
171			} catch (e) {
172				reject(e);
173			}
174			document.body.removeChild(ta);
175		});
176	}
177
178	function isTypingTarget(el) {
179		if (!el) return false;
180		var tag = el.tagName;
181		return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
182	}
183
184	function initShare() {
185		var url = window.location.href;
186		var title = document.title || '';
187		qsa('[data-share]').forEach(function (a) {
188			var net = a.getAttribute('data-share');
189			var href = '#';
190			if (net === 'vk') href = 'https://vk.com/share.php?url=' + encodeURIComponent(url);
191			else if (net === 'tg') href = 'https://t.me/share/url?url=' + encodeURIComponent(url) + '&text=' + encodeURIComponent(title);
192			else if (net === 'wa') href = 'https://api.whatsapp.com/send?text=' + encodeURIComponent(title + ' ' + url);
193			else if (net === 'ok') href = 'https://connect.ok.ru/offer?url=' + encodeURIComponent(url) + '&title=' + encodeURIComponent(title);
194			a.href = href;
195		});
196	}
197
198	function initMain() {
199		var root = qs('#hs-sound');
200		if (!root) return null;
201
202		var audio = qs('#hs-audio', root);
203		var playBtn = qs('#hs-play', root);
204		var waveEl = qs('#hs-wave', root);
205		var loopBtn = qs('#hs-loop', root);
206		var copyBtn = qs('#hs-copy');
207		var seed = root.getAttribute('data-id') || '1';
208		var bars = makeWave(waveEl, seed, BAR_COUNT);
209		var data = parseData();
210		var seeking = false;
211
212		if (data.sizeLabel) {
213			var sizeChip = qs('#hs-chip-size');
214			var sizeBtn = qs('#hs-dl-size');
215			if (sizeChip) {
216				sizeChip.textContent = data.sizeLabel;
217			}
218			if (sizeBtn) sizeBtn.textContent = '· ' + data.sizeLabel;
219		}
220
221		function setPlaying(on) {
222			root.classList.toggle('is-playing', on);
223			playBtn.setAttribute('aria-label', on ? t('pause', 'Пауза') : t('play', 'Слушать'));
224		}
225
226		function syncTime() {
227			var cur = audio.currentTime || 0;
228			var dur = audio.duration;
229			qs('#hs-cur').textContent = fmt(cur);
230			qs('#hs-dur').textContent = isFinite(dur) ? fmt(dur) : '0:00';
231			if (isFinite(dur) && dur > 0) {
232				paintWave(bars, cur / dur);
233				waveEl.setAttribute('aria-valuenow', String(Math.round((cur / dur) * 100)));
234			}
235		}
236
237		function toggle() {
238			if (audio.paused) {
239				pauseRelated();
240				var p = audio.play();
241				if (p && p.catch) p.catch(function () {});
242			} else {
243				audio.pause();
244			}
245		}
246
247		function seekFromEvent(e) {
248			var dur = audio.duration;
249			if (!isFinite(dur) || dur <= 0) return;
250			var p = seekRatio(e, waveEl);
251			audio.currentTime = p * dur;
252			paintWave(bars, p);
253		}
254
255		playBtn.addEventListener('click', toggle);
256
257		audio.addEventListener('play', function () {
258			setPlaying(true);
259		});
260		audio.addEventListener('pause', function () {
261			setPlaying(false);
262		});
263		audio.addEventListener('ended', function () {
264			if (!audio.loop) {
265				setPlaying(false);
266				paintWave(bars, 1);
267			}
268		});
269		audio.addEventListener('timeupdate', function () {
270			if (!seeking) syncTime();
271		});
272		audio.addEventListener('loadedmetadata', function () {
273			syncTime();
274			var dur = audio.duration;
275			if (isFinite(dur) && dur > 0) {
276				var chip = qs('#hs-chip-time');
277				if (chip) chip.textContent = fmt(dur);
278			}
279		});
280
281		waveEl.addEventListener('pointerdown', function (e) {
282			seeking = true;
283			waveEl.setPointerCapture(e.pointerId);
284			seekFromEvent(e);
285		});
286		waveEl.addEventListener('pointermove', function (e) {
287			if (seeking) seekFromEvent(e);
288		});
289		waveEl.addEventListener('pointerup', function () {
290			seeking = false;
291		});
292		waveEl.addEventListener('pointercancel', function () {
293			seeking = false;
294		});
295		waveEl.addEventListener('keydown', function (e) {
296			var dur = audio.duration;
297			if (!isFinite(dur) || dur <= 0) return;
298			if (e.key === 'ArrowLeft') {
299				e.preventDefault();
300				audio.currentTime = Math.max(0, audio.currentTime - 2);
301			}
302			if (e.key === 'ArrowRight') {
303				e.preventDefault();
304				audio.currentTime = Math.min(dur, audio.currentTime + 2);
305			}
306		});
307
308		if (loopBtn) {
309			loopBtn.addEventListener('click', function () {
310				audio.loop = !audio.loop;
311				loopBtn.classList.toggle('is-on', audio.loop);
312				loopBtn.setAttribute('aria-pressed', audio.loop ? 'true' : 'false');
313				toast(audio.loop ? t('loop_on', 'Повтор включён') : t('loop_off', 'Повтор выключен'));
314			});
315		}
316
317		if (copyBtn) {
318			copyBtn.addEventListener('click', function () {
319				copyText(window.location.href).then(function () {
320					toast(t('copied', 'Ссылка скопирована'));
321				}).catch(function () {
322					toast(t('copy_fail', 'Не удалось скопировать'));
323				});
324			});
325		}
326
327		document.addEventListener('keydown', function (e) {
328			if (isTypingTarget(e.target)) return;
329			if (e.code === 'Space' || e.key === ' ') {
330				e.preventDefault();
331				toggle();
332			}
333			if (e.key === 'l' || e.key === 'L' || e.key === 'д' || e.key === 'Д') {
334				if (loopBtn) loopBtn.click();
335			}
336		});
337
338		return {
339			audio: audio,
340			pause: function () {
341				audio.pause();
342			}
343		};
344	}
345
346	var relatedAudio = qs('#hs-rel-audio');
347	var currentRel = null;
348
349	function pauseRelated() {
350		if (relatedAudio && !relatedAudio.paused) relatedAudio.pause();
351		if (currentRel) {
352			currentRel.classList.remove('is-playing');
353			setWaveProgress(qs('.hs-rel-wave', currentRel), 0);
354		}
355		currentRel = null;
356	}
357
358	function initRelated(main) {
359		if (!relatedAudio) {
360			relatedAudio = document.createElement('audio');
361			relatedAudio.id = 'hs-rel-audio';
362			relatedAudio.preload = 'none';
363			document.body.appendChild(relatedAudio);
364		}
365		var relSeeking = false;
366		qsa('.hs-rel, .hs-track').forEach(function (item) {
367			var wave = qs('.hs-rel-wave', item);
368			var btn = qs('.hs-rel-play', item);
369			function playItem() {
370				var src = item.getAttribute('data-src') || '';
371				if (!src) return false;
372				if (currentRel === item && !relatedAudio.paused) return true;
373				if (main && main.pause) main.pause();
374				if (currentRel && currentRel !== item) {
375					currentRel.classList.remove('is-playing');
376					setWaveProgress(qs('.hs-rel-wave', currentRel), 0);
377				}
378				currentRel = item;
379				if (relatedAudio.getAttribute('src') !== src) {
380					relatedAudio.src = src;
381				}
382				var p = relatedAudio.play();
383				if (p && p.catch) p.catch(function () {});
384				return true;
385			}
386			if (btn) {
387				btn.addEventListener('click', function (e) {
388					e.preventDefault();
389					e.stopPropagation();
390					if (currentRel === item && !relatedAudio.paused) {
391						relatedAudio.pause();
392						return;
393					}
394					playItem();
395				});
396			}
397			if (wave) {
398				wave.addEventListener('pointerdown', function (e) {
399					if (e.button) return;
400					playItem();
401				});
402				bindWaveSeek(wave, function () {
403					return currentRel === item ? relatedAudio : null;
404				}, function (on) {
405					relSeeking = on;
406				}, function (p) {
407					setWaveProgress(wave, p);
408				});
409			}
410		});
411
412		relatedAudio.addEventListener('play', function () {
413			if (currentRel) currentRel.classList.add('is-playing');
414		});
415		relatedAudio.addEventListener('pause', function () {
416			if (currentRel) currentRel.classList.remove('is-playing');
417		});
418		relatedAudio.addEventListener('ended', function () {
419			pauseRelated();
420		});
421		relatedAudio.addEventListener('timeupdate', function () {
422			if (!currentRel || relSeeking) return;
423			var dur = relatedAudio.duration;
424			if (isFinite(dur) && dur > 0) {
425				setWaveProgress(qs('.hs-rel-wave', currentRel), relatedAudio.currentTime / dur);
426			}
427		});
428	}
429
430	function ready(fn) {
431		if (document.readyState === 'loading') {
432			document.addEventListener('DOMContentLoaded', fn);
433		} else {
434			fn();
435		}
436	}
437
438	ready(function () {
439		var story = qs('.hs-story');
440		if (story && !String(story.textContent || '').replace(/\s+/g, '')) story.style.display = 'none';
441		initShare();
442		var main = initMain();
443		initRelated(main);
444	});
445})();

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.