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.