1(() => { 2 'use strict'; 3 4 if (window.__swWavDemoDownloadV1) return; 5 window.__swWavDemoDownloadV1 = true; 6 7 const JOB_RE = /^[a-f0-9]{32}$/i; 8 9 function cleanJob(value) { 10 const job = String(value || '').trim().toLowerCase(); 11 return JOB_RE.test(job) ? job : ''; 12 } 13 14 function jobFromUrl(value) { 15 try { 16 const url = new URL(value, window.location.origin); 17 return cleanJob(url.searchParams.get('job')); 18 } catch (_) { 19 return ''; 20 } 21 } 22 23 function resolveJob() { 24 const locationJob = cleanJob(new URLSearchParams(window.location.search).get('job')); 25 if (locationJob) return locationJob; 26 27 const candidates = document.querySelectorAll( 28 '#resultModal a[href*="job="], #resultModal [data-job], body [data-job]' 29 ); 30 31 for (const node of candidates) { 32 const dataJob = cleanJob(node.getAttribute('data-job')); 33 if (dataJob) return dataJob; 34 35 const hrefJob = jobFromUrl(node.getAttribute('href') || ''); 36 if (hrefJob) return hrefJob; 37 } 38 39 return ''; 40 } 41 42 function wavHref(job, kind) { 43 const url = new URL('/minus_demo_wav_download.php', window.location.origin); 44 url.searchParams.set('job', job); 45 url.searchParams.set('kind', kind); 46 return url.pathname + url.search; 47 } 48 49 function isPaidState() { 50 const state = String(document.body && document.body.dataset ? document.body.dataset.pageState || '' : '').toLowerCase(); 51 if (state === 'paid' || state === 'paid-processing') return true; 52 const hero = document.getElementById('paidHeroDownload'); 53 if (hero && !hero.classList.contains('is-hidden') && hero.getAttribute('aria-hidden') !== 'true') return true; 54 return false; 55 } 56 57 function setButton(id, job, kind, text) { 58 const button = document.getElementById(id); 59 if (!button || !job) return; 60 if (isPaidState() || button.classList.contains('is-paid-download')) { 61 button.removeAttribute('data-sw-wav-demo'); 62 return; 63 } 64 65 const expected = wavHref(job, kind); 66 67 if (button.getAttribute('href') !== expected) { 68 button.setAttribute('href', expected); 69 } 70 71 button.setAttribute('download', ''); 72 button.setAttribute('rel', 'nofollow'); 73 button.setAttribute('data-sw-wav-demo', '1'); 74 button.setAttribute('aria-label', text); 75 76 if (button.textContent.trim() !== text) { 77 button.textContent = text; 78 } 79 } 80 81 function apply() { 82 if (isPaidState()) return; 83 const job = resolveJob(); 84 if (!job) return; 85 86 /* 87 * Ðажно: audio.src не менÑем. 88 * ÐÐ»ÐµÐµÑ Ð¿ÑÐ¾Ð´Ð¾Ð»Ð¶Ð°ÐµÑ ÑлÑÑаÑÑ ÑÑÑеÑÑвÑÑÑий MP3 preview stream. 89 */ 90 setButton('demoMinus', job, 'instrumental', 'СкаÑаÑÑ Ð´ÐµÐ¼Ð¾ WAV'); 91 setButton('demoVocal', job, 'vocals', 'СкаÑаÑÑ Ð´ÐµÐ¼Ð¾ вокала WAV'); 92 } 93 94 function start() { 95 apply(); 96 97 document.addEventListener('sunowave:result-ready', apply); 98 document.addEventListener('sw:result-ready', apply); 99 window.addEventListener('pageshow', apply); 100 101 /* 102 * ÐаÑиÑа Ð¾Ñ ÑÑаÑÑÑ JS-ÑлоÑв, коÑоÑÑе обновлÑÑÑ href ÑпÑÑÑÑ Ð½ÐµÑколÑко ÑекÑнд. 103 */ 104 let ticks = 0; 105 const timer = window.setInterval(() => { 106 ticks += 1; 107 apply(); 108 if (ticks >= 20 || isPaidState()) window.clearInterval(timer); 109 }, 1200); 110 } 111 112 if (document.readyState === 'loading') { 113 document.addEventListener('DOMContentLoaded', start, { once: true }); 114 } else { 115 start(); 116 } 117})();
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.