1class QualitySelector{constructor(container,options={}){this.container=container,this.qualities=options.qualities||[],this.currentQuality=options.currentQuality||null,this.onChange=options.onChange||(()=>{}),this.isMobile=window.innerWidth<=768,this.init(),window.addEventListener("resize",()=>{const wasMobile=this.isMobile;this.isMobile=window.innerWidth<=768,wasMobile!==this.isMobile&&this.render()})}init(){this.container?this.render():console.error("Quality selector container not found")}render(){if(0===this.qualities.length)return void(this.container.innerHTML="");if(!this.currentQuality){const priorityOrder=["1080p","720p","360p"];for(const quality of priorityOrder){if(this.qualities.find(q=>q.quality===quality)){this.currentQuality=quality;break}}}const html=this.isMobile?this.renderMobile():this.renderDesktop();this.container.innerHTML=html,this.attachEvents()}renderDesktop(){return 1===this.qualities.length?`\n <div class="quality-selector">\n <button class="quality-btn active single-quality" disabled>\n ${this.qualities[0].label}\n </button>\n </div>\n `:`\n <div class="quality-selector">\n ${this.qualities.map(q=>`\n <button class="quality-btn ${q.quality===this.currentQuality?"active":""}" \n data-quality="${q.quality}"\n data-whep-url="${q.whepUrl}">\n <span class="quality-label ${this.getQualityClass(q.quality)}">${q.label}</span>\n </button>\n `).join("")}\n </div>\n `}renderMobile(){const current=this.qualities.find(q=>q.quality===this.currentQuality),currentLabel=current?current.label:"HD";return 1===this.qualities.length?`\n <div class="quality-selector">\n <div class="quality-dropdown">\n <button class="quality-dropdown-btn single-quality" disabled>\n <span class="quality-label ${this.getQualityClass(this.currentQuality)}">${currentLabel}</span>\n </button>\n </div>\n </div>\n `:`\n <div class="quality-selector">\n <div class="quality-dropdown">\n <button class="quality-dropdown-btn" id="qualityDropdownBtn">\n <span class="quality-label ${this.getQualityClass(this.currentQuality)}">${currentLabel}</span>\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">\n <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />\n </svg>\n </button>\n <div class="quality-dropdown-menu" id="qualityDropdownMenu">\n ${this.qualities.map(q=>`\n <div class="quality-dropdown-item ${q.quality===this.currentQuality?"active":""}"\n data-quality="${q.quality}"\n data-whep-url="${q.whepUrl}">\n <span class="quality-label ${this.getQualityClass(q.quality)}">${q.label}</span>\n <svg class="check-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">\n <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />\n </svg>\n </div>\n `).join("")}\n </div>\n </div>\n </div>\n `}getQualityClass(quality){return{"1080p":"full-hd","720p":"hd","360p":"sd"}[quality]||"hd"}attachEvents(){this.isMobile?this.attachMobileEvents():this.attachDesktopEvents()}attachDesktopEvents(){this.container.querySelectorAll(".quality-btn:not([disabled])").forEach(btn=>{btn.addEventListener("click",e=>{const quality=e.currentTarget.dataset.quality,whepUrl=e.currentTarget.dataset.whepUrl;this.selectQuality(quality,whepUrl)})})}attachMobileEvents(){const dropdownBtn=this.container.querySelector("#qualityDropdownBtn"),dropdownMenu=this.container.querySelector("#qualityDropdownMenu"),items=this.container.querySelectorAll(".quality-dropdown-item");dropdownBtn&&!dropdownBtn.disabled&&dropdownMenu&&(dropdownBtn.addEventListener("click",e=>{e.stopPropagation(),dropdownBtn.classList.toggle("open"),dropdownMenu.classList.toggle("show")}),document.addEventListener("click",e=>{this.container.contains(e.target)||(dropdownBtn.classList.remove("open"),dropdownMenu.classList.remove("show"))}
1)),items.forEach(item=>{item.addEventListener("click",e=>{const quality=e.currentTarget.dataset.quality,whepUrl=e.currentTarget.dataset.whepUrl;this.selectQuality(quality,whepUrl),dropdownBtn&&dropdownMenu&&(dropdownBtn.classList.remove("open"),dropdownMenu.classList.remove("show"))})})}selectQuality(quality,whepUrl){quality!==this.currentQuality&&(this.currentQuality,this.currentQuality=quality,this.render(),this.onChange(quality,whepUrl))}updateQualities(qualities){this.qualities=qualities,this.render()}setCurrentQuality(quality){this.currentQuality=quality,this.render()}}window.QualitySelector=QualitySelector;
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.