1"use strict"; 2 3let player; 4 5const CookieStoreV = { 6 get: function(n){ var m=document.cookie.match(new RegExp('(?:^|; )'+encodeURIComponent(n)+'=([^;]*)')); return m?decodeURIComponent(m[1]):null; }, 7 set: function(n,v,days){ if(days===void 0) days=365; var d=new Date(); d.setTime(d.getTime()+days*864e5); document.cookie=encodeURIComponent(n)+"="+encodeURIComponent(v)+";expires="+d.toUTCString()+";path=/;SameSite=Lax"; } 8}; 9function vGet(k){ try{return localStorage.getItem(k)??CookieStoreV.get(k);}catch(e){ return CookieStoreV.get(k); } } 10function vSet(k,v){ try{ localStorage.setItem(k,v); }catch(e){ CookieStoreV.set(k,v); } } 11 12function keyTime(id){ return "media:"+id+":t"; } // currentTime 13function keyDur(id){ return "media:"+id+":d"; } // duration 14function keyWatched(id){ return "media:"+id+":w"; } // "1" -> permanent watched 15 16function getVideoIdFrom(elOrUrl){ 17 if (typeof elOrUrl === "string") return elOrUrl; 18 return (elOrUrl.getAttribute && (elOrUrl.getAttribute("data-media-id") || elOrUrl.getAttribute("data-video"))) ||
19 (elOrUrl.dataset && (elOrUrl.dataset.mediaId || elOrUrl.dataset.video)) || ""; 20} 21function getVideoUrlFrom(el){ 22 var url = (el.getAttribute && (el.getAttribute("data-video") || el.getAttribute("data-src") || el.getAttribute("href"))) || 23 (el.dataset && (el.dataset.video || el.dataset.src)) || ""; 24 url = (url || "").replace(/&/g,"&").trim(); 25 return url || null; 26} 27function humanizeAz(sec){ 28 if (!isFinite(sec) || sec <= 0) return "0 san"; 29 sec = Math.floor(sec); 30 var h = Math.floor(sec/3600); 31 var m = Math.floor((sec%3600)/60); 32 var s = sec % 60; 33 var parts = []; 34 if (h > 0) parts.push(h + " saat"); 35 if (m > 0) parts.push(m + " deq"); 36 if (s > 0 || (h===0 && m===0)) parts.push(s + " san"); 37 return parts.join(" "); 38} 39function setTotalOnce(el, sec){ 40 if (!el || !isFinite(sec) || sec <= 0) return; 41 if (el.dataset && el.dataset.totalFixed === "1") return; // artıq yazılıb 42 el.textContent = humanizeAz(sec); 43 if (el.dataset) el.dataset.totalFixed = "1"; 44} 45 46const metaQueue = []; 47let metaBusy = false; 48let metaVideoEl = null; 49 50function ensureMetaVideo() { 51 if (metaVideoEl) return metaVideoEl; 52 var v = document.createElement("video"); 53 v.preload = "metadata"; 54 v.muted = true; v.playsInline = true; 55 v.style.position = "absolute"; 56 v.style.width = "1px"; 57 v.style.height = "1px"; 58 v.style.opacity = "0"; 59 v.style.pointerEvents = "none"; 60 document.body.appendChild(v); 61 metaVideoEl = v; 62 return v; 63} 64 65function enqueueDurationLoad(card){ 66 var id = getVideoIdFrom(card); 67 var url = getVideoUrlFrom(card); 68 if (!id || !url) return; 69 70 var existing = parseFloat(vGet(keyDur(id)) || "0"); 71 if (existing > 0) { setTotalOnce(card.querySelector(".total-time"), existing); return; } 72 73 // kart artıq növbÉdÉdirsÉ tÉkrar ÉlavÉ etmÉ 74 if (metaQueue.some(function(x){ return x && x.id === id; })) return; 75 76 metaQueue.push({ id:id, url:url, card:card }); 77 drainMetaQueue(); 78} 79 80function drainMetaQueue(){ 81 if (metaBusy || metaQueue.length === 0) return; 82 metaBusy = true; 83 84 var job = metaQueue.shift(); 85 var id = job.id, url = job.url, card = job.card; 86 var v = ensureMetaVideo(); 87 88 var cleanup = function(){ 89 v.src = ""; 90 v.onloadedmetadata = null; 91 v.onerror = null; 92 metaBusy = false; 93 // NövbÉti iÅi UI-nı bloklamadan baÅlat 94 setTimeout(drainMetaQueue, 0); 95 }; 96 97 v.onloadedmetadata = function(){ 98 var dur = v.duration && isFinite(v.duration) ? v.duration : 0; 99 if (dur > 0) { 100 vSet(keyDur(id), String(dur)); 101 setTotalOnce(card.querySelector(".total-time"), dur); 102 } 103 cleanup(); 104 }; 105 v.onerror = cleanup; 106 v.src = url; // metadata yüklÉ 107} 108 109function findVideoCardById(id){ 110 if(!id) return null; 111 var list = document.querySelectorAll(".media-card[data-video]"); 112 for (var i=0;i<list.length;i++){ 113 var c = list[i]; 114 var cid = (c.getAttribute("data-media-id") || c.getAttribute("data-video") || "").trim(); 115 if (cid === id) return c; 116 } 117 return null; 118} 119 120function updateVideoCardById(id){ 121 var card = findVideoCardById(id); 122 if(!card) return; 123 124 var savedT = parseFloat(vGet(keyTime(id)) || "0"); 125 var savedD = parseFloat(vGet(keyDur(id)) || "0"); 126 var watched = vGet(keyWatched(id)) === "1"; 127 var pct = savedD > 0 ? Math.min(100, (savedT / savedD) * 100) : 0; 128 129 var meta = card.querySelector(".media-meta"); 130 if(!meta) return; 131 132 var remainEl = card.querySelector(".remaining-time"); 133 var progBar = card.querySelector(".progress-bar"); 134 var progFill = progBar ? (progBar.querySelector(".progress-fill") || null) : null; 135 var statusTag= card.querySelector(".status-tag"); 136 137 // 1) HÉmiÅÉlik Baxılıb vÉ ya hazırda %>=95 138 if (watched || (savedD > 0 && pct >= 95)) { 139 if (!watched) vSet(keyWatched(id), "1"); 140 141 if (!statusTag) { 142 var leftBox = meta.querySelector(".d-flex.gap-1") || meta.querySelector(".d-flex"); 143 if (leftBox) { 144 statusTag = document.createElement("span"); 145 statusTag.className = "status-tag"; 146 leftBox.insertBefore(statusTag, leftBox.firstChild); 147 } 148 } 149 if (statusTag) statusTag.textContent = "Baxılıb"; 150 151 if (remainEl && remainEl.parentNode) remainEl.parentNode.removeChild(remainEl); 152 if (progBar && progBar.parentNode) progBar.parentNode.removeChild(progBar); 153 return; 154 } 155 156 // 2) Davam edir 157 if (savedD > 0 && pct > 0) { 158 if (statusTag && statusTag.parentNode) statusTag.parentNode.removeChild(statusTag); 159 160 if (!remainEl) { 161 remainEl = document.createElement("div"); 162 remainEl.className = "remaining-time"; 163 meta.appendChild(remainEl); 164 } 165 var remain = Math.max(0, savedD - savedT); 166 var txt = humanizeAz(remain); 167 remainEl.textContent = (txt === "0 san") ? "" : (txt + " qalıb"); 168 169 if (!progBar) { 170 progBar = document.createElement("div"); 171 progBar.className = "progress-bar"; 172 progBar.innerHTML = '<div class="progress-fill" style="width:0%"></div>'; 173 var mc = card.querySelector(".media-content"); 174 if (mc) mc.appendChild(progBar); 175 progFill = progBar.querySelector(".progress-fill"); 176 } else { 177 progFill = progBar.querySelector(".progress-fill") || progFill; 178 } 179 if (progFill) progFill.style.width = pct.toFixed(1) + "%"; 180 return; 181 } 182 183 // 3) Baxılmayıb â status/remaining/progress olmasın 184 if (statusTag && statusTag.parentNode) statusTag.parentNode.removeChild(statusTag); 185 if (remainEl && remainEl.parentNode) remainEl.parentNode.removeChild(remainEl); 186 if (progBar && progBar.parentNode) progBar.parentNode.removeChild(progBar); 187} 188 189function updateVideoCards(){ 190 var list = document.querySelectorAll(".media-card[data-video]"); 191 for (var i=0;i<list.length;i++){ 192 var c = list[i]; 193 enqueueDurationLoad(c); 194 var id = getVideoIdFrom(c); 195 if (id) updateVideoCardById(id); 196 } 197} 198 199var videoCardIO = new IntersectionObserver(function(entries){ 200 for (var i=0;i<entries.length;i++){ 201 var entry = entries[i];
202 if (!entry.isIntersecting) continue; 203 var card = entry.target; 204 videoCardIO.unobserve(card); 205 enqueueDurationLoad(card); 206 // metadata yazıldıqdan sonra UI update üçün biraz gecikme 207 setTimeout(function(c){ return function(){ updateVideoCardById(getVideoIdFrom(c)); }; }(card), 0); 208 } 209},{ root:null, rootMargin:"200px 0px", threshold:0 }); 210 211function bootstrapInitialDurations(){ 212 var all = Array.from(document.querySelectorAll(".media-card[data-video]")); 213 // İlk 8 kart -> dÉrhal; qalanlar -> görünÉndÉ 214 for (var i=0;i<all.length;i++){ 215 if (i < 8) enqueueDurationLoad(all[i]); 216 else videoCardIO.observe(all[i]); 217 } 218} 219 220var moV = new MutationObserver(function(muts){ 221 var added = []; 222 for (var mi=0; mi<muts.length; mi++){ 223 var m = muts[mi]; 224 if (!m.addedNodes) continue; 225 for (var j=0;j<m.addedNodes.length;j++){ 226 var n = m.addedNodes[j]; 227 if (!(n instanceof Element)) continue; 228 if (n.matches && n.matches(".media-card[data-video]")) added.push(n); 229 var inner = n.querySelectorAll ? n.querySelectorAll(".media-card[data-video]") : []; 230 for (var k=0;k<inner.length;k++) added.push(inner[k]); 231 } 232 } 233 if (added.length){ 234 for (var a=0;a<added.length;a++) { 235 enqueueDurationLoad(added[a]); 236 videoCardIO.observe(added[a]); 237 } 238 clearTimeout(moV._t); 239 moV._t = setTimeout(function(){ 240 for (var a=0;a<added.length;a++){ 241 var id = getVideoIdFrom(added[a]); 242 if (id) updateVideoCardById(id); 243 } 244 }, 50); 245 } 246}); 247 248function findVideoUrlFromTrigger(trigger){ 249 var carrier = 250 (trigger.closest && trigger.closest("[data-video]")) || 251 (trigger.querySelector && trigger.querySelector("[data-video]")) || 252 trigger; 253 254 var url = 255 (carrier.dataset && (carrier.dataset.video || carrier.dataset.src)) || 256 (carrier.getAttribute && (carrier.getAttribute("data-video") || carrier.getAttribute("data-src") || carrier.getAttribute("href"))) || 257 ""; 258 259 url = (url || "").replace(/&/g,"&").trim(); 260 return url || null; 261} 262function loadSavedStart(id,fallbackStart,realDuration){ 263 if (fallbackStart===void 0) fallbackStart = 0; 264 var savedT = parseFloat(vGet(keyTime(id)) || "0"); 265 var savedD = parseFloat(vGet(keyDur(id)) || "0"); 266 if (realDuration && savedD && Math.abs(savedD - realDuration) > 1) return fallbackStart || 0; 267 return savedT > 0 ? savedT : (fallbackStart || 0); 268} 269function flushSave(el,id){ 270 if(!el) return; 271 vSet(keyTime(id), String(el.currentTime || 0)); 272 vSet(keyDur(id), String(el.duration || 0)); 273} 274 275document.addEventListener("DOMContentLoaded", function(){ 276 bootstrapInitialDurations(); // ilk 8 dÉrhal, qalanlar görünÉndÉ 277 updateVideoCards(); // status/progress 278 moV.observe(document.body, { childList:true, subtree:true }); 279 280 var modal = document.getElementById("videoModal"); 281 if (!modal) return; 282 283 var overlay = modal.querySelector(".play-overlay"); 284 var modalContent = modal.querySelector(".modal-content"); 285 286 // boÅ link kliklÉrinin qarÅısını al 287 document.addEventListener("click", function(e){ 288 var trigger = e.target.closest ? e.target.closest("[data-bs-target='#videoModal']") : null; 289 if (!trigger) return; 290 if (trigger.matches && trigger.matches("a[href='#']")) e.preventDefault(); 291 }); 292 293 var activeMediaId = null; 294 var saveThrottleTs = 0; 295 var SAVE_INTERVAL_MS = 4000; 296 297 modal.addEventListener("show.bs.modal", function(e){ 298 var trigger = e.relatedTarget; 299 if (!trigger) return; 300 301 var videoUrl = findVideoUrlFromTrigger(trigger); 302 var fallbackStart = parseFloat(trigger.getAttribute("data-current-time") || "0"); 303 if (!videoUrl) { console.warn("Video tapılmadı.", trigger); return; } 304 305 // KöhnÉni tÉmizlÉ 306 if (player) { try{player.destroy();}catch(_e){} player=null; } 307 var olds = modal.querySelectorAll("video#modal-video"); 308 for (var oi=0; oi<olds.length; oi++){ try{olds[oi].pause();}catch(_e){} olds[oi].remove(); } 309 310 // Yeni video 311 var v = document.createElement("video");
312 v.id = "modal-video"; 313 v.className = "plyr w-100 rounded-4"; 314 v.setAttribute("preload","metadata"); 315 v.setAttribute("playsinline",""); 316 v.setAttribute("controls",""); 317 var s = document.createElement("source"); 318 s.src = videoUrl; 319 s.type = /\.webm(\?|$)/i.test(videoUrl) ? "video/webm" : "video/mp4"; 320 v.appendChild(s); 321 322 var container = modal.querySelector(".position-relative") || modalContent; 323 if (overlay && container.contains(overlay)) container.insertBefore(v, overlay); 324 else container.appendChild(v); 325 326 activeMediaId = getVideoIdFrom(trigger) || videoUrl; 327 328 player = new Plyr(v, { 329 seekTime: 15, 330 controls: ['rewind','play','fast-forward','progress','current-time','duration','mute','volume','fullscreen'] 331 }); 332 333 // total-time 334 var card = findVideoCardById(activeMediaId) || { querySelector: function(){ return null; } }; 335 var ensureDur = function(){ 336 var dur = v.duration && isFinite(v.duration) ? v.duration : 0; 337 if (dur > 0) { 338 vSet(keyDur(activeMediaId), String(dur)); 339 var totalEl = card.querySelector ? card.querySelector(".total-time") : null; 340 setTotalOnce(totalEl, dur); 341 } 342 }; 343 344 v.addEventListener("loadedmetadata", function(){ 345 ensureDur(); 346 var start = loadSavedStart(activeMediaId, fallbackStart, v.duration); 347 if (start > 0 && start < (v.duration || Infinity)) v.currentTime = start; 348 }); 349 350 v.addEventListener("timeupdate", function(){ 351 var now = Date.now(); 352 if (now - saveThrottleTs > SAVE_INTERVAL_MS) { 353 vSet(keyTime(activeMediaId), String(v.currentTime || 0)); 354 vSet(keyDur(activeMediaId), String(v.duration || 0)); 355 if (v.duration && v.currentTime / v.duration >= 0.95) vSet(keyWatched(activeMediaId),'1'); 356 saveThrottleTs = now; 357 updateVideoCardById(activeMediaId); 358 } 359 }); 360 361 v.addEventListener("ended", function(){ 362 vSet(keyTime(activeMediaId), String(v.duration || 0)); 363 vSet(keyDur(activeMediaId), String(v.duration || 0)); 364 vSet(keyWatched(activeMediaId),'1'); // permanent 365 updateVideoCardById(activeMediaId); 366 }); 367 368 var visHandler = function(){ if (document.hidden) { flushSave(v, activeMediaId); updateVideoCardById(activeMediaId); } }; 369 document.addEventListener("visibilitychange", visHandler); 370 371 modal.addEventListener("hidden.bs.modal", function(){ 372 flushSave(v, activeMediaId); 373 setTimeout(function(){ updateVideoCardById(activeMediaId); }, 0); 374 375 if (player) { try{player.destroy();}catch(_e){} player=null; } 376 v.remove(); 377 document.removeEventListener("visibilitychange", visHandler); 378 activeMediaId = null; 379 }, { once:true }); 380 381 if (overlay) { 382 overlay.addEventListener("click", function overlayOnce(){ 383 overlay.style.display = "none"; 384 modal.classList.remove("hide-controls"); 385 if (player) player.play(); 386 overlay.removeEventListener("click", overlayOnce); 387 }); 388 } 389 }); 390});
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.