PageSourceSearch

https://nia.eco/wp-content/plugins/nia-pulse/assets/public.js?ver=1.0.13.contour-20260909e

js nia.eco collected 2026-10-02 16:49:38 UTC 10,268 bytes, 36 lines download raw bytes

1(()=>{'use strict';const cfg=window.NiaPulse;if(!cfg)return;const reduced=matchMedia('(prefers-reduced-motion: reduce)');const el=(tag,cls,text)=>{const n=document.createElement(tag);if(cls)n.className=cls;if(text!==undefined)n.textContent=text;return n;};const button=(text,fn)=>{const b=el('button','',text);b.type='button';b.addEventListener('click',fn);return b;};const link=(text,url)=>{const a=el('a','',text);a.href=url;return a;};async function request(path,args={}){const url=new URL(cfg.api+path);Object.entries(args).forEach(([k,v])=>url.searchParams.set(k,v));const r=await fetch(url,{cache:'no-store'});const data=await r.json();if(!r.ok)throw Error(data.message||'Не удалось загрузить. Повторите попытку.');return data;}function read(root){return JSON.parse(root.querySelector('.nps-data').textContent);}function rows(articles,kind){const list=el('ol','nps-rows'+(kind==='story'?' nps-timeline':''));for(const a of articles){const li=el('li');const time=el('time','',a.date);time.dateTime=a.datetime;li.append(time,link(a.title,a.url));list.append(li);}return list;}
2function tile(c){const art=el('article','nps-tile nps-color-'+c.color);art.dataset.chain=c.id;const b=button('',()=>{});b.className='nps-tile-toggle';b.setAttribute('aria-expanded','false');b.setAttribute('aria-controls','nps-detail-'+c.id);b.append(el('span','nps-type',c.label),el('strong','nps-title',c.title),el('span','nps-short',c.short));if(c.articles[0]){const a=c.articles[0];b.append(el('span','nps-latest',a.title));const foot=el('span','nps-tile-foot');const time=el('time','',a.date);time.dateTime=a.datetime;foot.append(time,el('span','',c.total+' материалов · Раскрыть ↗'));b.append(foot);}art.append(b);return art;}
3function detail(c,{auto=true,onClose=()=>{}}={}){
4 const pageSize=4;let offset=0,listRows=[...c.articles],loaded=listRows.length,total=c.total,paused=reduced.matches,busy=false,visible=false,last=0,elapsed=0,position=0,raf=0,destroyed=false,loopDistance=0;
5 const box=el('section','nps-detail nps-color-'+c.color);box.id='nps-detail-'+c.id;box.setAttribute('aria-label',c.title);
6 const head=el('div','nps-detail-heading'),h=el('h3');h.append(link(c.title,c.url));head.append(h,el('span','nps-type',c.label));
7 const windowEl=el('div','nps-motion-window');let list=rows(listRows,c.kind);windowEl.append(list);
8 const controls=el('div','nps-detail-controls'),note=el('span','nps-detail-note');note.role='status';
9 const prev=button('Новее',()=>turn(-1)),next=button('Старее',()=>turn(1)),pause=button('Пауза',()=>{paused=!paused;last=0;elapsed=0;sync();}),close=button('Свернуть',onClose),all=link('Все '+total+' материалов →',c.url);all.className='nps-all';controls.append(prev,next);if(auto)controls.append(pause);controls.append(close,all);box.append(head,windowEl,controls,note);
10 function sync(){prev.disabled=offset===0&&windowEl.scrollTop<1;next.disabled=offset+pageSize>=total;pause.disabled=reduced.matches||total<2;pause.textContent=paused?'Продолжить':'Пауза';pause.setAttribute('aria-pressed',String(paused));}
11 function stop(){paused=true;sync();}
12 function paint(){list=rows(listRows,c.kind);windowEl.replaceChildren(list);windowEl.scrollTop=0;position=0;elapsed=0;loopDistance=0;sync();}
13 async function turn(direction){stop();if(busy)return;busy=true;const top=windowEl.getBoundingClientRect().top;const hidden=[...list.children].filter(li=>!li.dataset.repeat&&li.getBoundingClientRect().bottom<=top+1).length;const newOffset=Math.max(0,Math.min(Math.max(0,total-pageSize),offset+hidden+direction*pageSize));try{const data=await request('chain/'+c.id,{offset:newOffset,limit:pageSize});if(destroyed)return;offset=newOffset;listRows=data.articles;loaded=offset+listRows.length;total=data.total;note.textContent='';paint();}catch(e){if(!destroyed)note.textContent=e.message;}finally{busy=false;}}
14 async function append(){if(busy||loaded>=total||destroyed)return;busy=true;try{const data=await request('chain/'+c.id,{offset:loaded,limit:10});if(destroyed)return;total=data.total;loaded+=data.articles.length;listRows.push(...data.articles);for(const li of [...rows(data.articles,c.kind).children])list.append(li);if(!data.articles.length)loaded=total;sync();}catch(e){if(!destroyed){note.textContent=e.message;stop();}}finally{busy=false;}}
15 function prepareLoop(){if(!list.children.length||loaded<total)return;const original=[...list.children].filter(li=>!li.dataset.repeat),copies=[...list.children].filter(li=>li.dataset.repeat);if(!original.length)return;const naturalHeight=original.at(-1).offsetTop+original.at(-1).offsetHeight-original[0].offsetTop,gap=Math.max(0,windowEl.clientHeight+24-naturalHeight);
15copies.forEach((copy,i)=>{const margin=i%original.length===0?gap+'px':'0px';if(copy.style.marginTop!==margin)copy.style.marginTop=margin;});loopDistance=copies.length?copies[0].offsetTop-original[0].offsetTop:0;let extra=copies.length?list.scrollHeight-loopDistance:0,index=copies.length;while(extra<windowEl.clientHeight+40&&index<500){const copy=original[index%original.length].cloneNode(true);copy.dataset.repeat='1';copy.style.marginTop=index%original.length===0?gap+'px':'0px';copy.setAttribute('aria-hidden','true');for(const a of copy.querySelectorAll('a'))a.tabIndex=-1;list.append(copy);if(index===0)loopDistance=copy.offsetTop-original[0].offsetTop;extra=list.scrollHeight-loopDistance;index++;}}
16 function frame(t){if(destroyed)return;const dt=last?Math.min(t-last,100):0;last=t;if(auto&&!paused&&!reduced.matches&&!document.hidden&&visible){elapsed+=dt;prepareLoop();const max=windowEl.scrollHeight-windowEl.clientHeight;if(loaded<total&&max-windowEl.scrollTop<180)append();if(elapsed>1600&&max>0){position=Math.min(max,position+dt*.008);if(loopDistance&&position>=loopDistance)position%=loopDistance;windowEl.scrollTop=position;prev.disabled=offset===0&&position<1;}}raf=requestAnimationFrame(frame);}
17 // Keep moving after opening with a mouse; pausing is an explicit reader control.
18 windowEl.addEventListener('focusin',stop);
19 const obs=new IntersectionObserver(entries=>{visible=entries[0].isIntersecting;last=0;});obs.observe(box);
20 const reducedChange=()=>{if(reduced.matches)stop();sync();};reduced.addEventListener('change',reducedChange);
21 if(auto)raf=requestAnimationFrame(frame);sync();
22 return {box,stop,destroy(){destroyed=true;cancelAnimationFrame(raf);obs.disconnect();reduced.removeEventListener('change',reducedChange);}};
23}
24for(const root of document.querySelectorAll('[data-nps-home]')){let data=read(root),active=null,openId=0,offset=0,busy=false;const panels=root.querySelector('.nps-home-panels'),status=root.querySelector('.nps-status'),more=root.querySelector('[data-next]'),first=root.querySelector('[data-first]');function close(focus=false){active?.destroy();active=null;const chosen=panels.querySelector('.nps-open');chosen?.querySelector('.nps-detail')?.remove();panels.classList.remove('nps-has-open');panels.querySelectorAll('.nps-tile').forEach(t=>{t.classList.remove('nps-open');t.querySelector('button').setAttribute('aria-expanded','false');});openId=0;if(focus)chosen?.querySelector('button').focus();}function attach(){panels.querySelectorAll('.nps-tile').forEach(t=>t.querySelector('button').onclick=()=>{const id=Number(t.dataset.chain);if(openId===id){close(true);return;}close();const c=data.items.find(x=>x.id===id);openId=id;t.classList.add('nps-open');panels.classList.add('nps-has-open');t.querySelector('button').setAttribute('aria-expanded','true');active=detail(c,{auto:true,onClose:()=>close(true)});t.append(active.box);});}async function batch(start){if(busy)return;busy=true;more.disabled=true;try{const result=await request('catalog',{home:1,offset:start,snapshot:data.snapshot});close();panels.classList.add('nps-changing');await new Promise(r=>setTimeout(r,reduced.matches?0:220));data=result;offset=start;panels.replaceChildren(...data.items.map(tile));attach();panels.classList.remove('nps-changing');first.disabled=!offset;status.textContent='';}catch(e){status.textContent=e.message;}finally{busy=false;more.disabled=!data.more;}}more.onclick=()=>batch(data.offset);first.onclick=()=>batch(Math.max(0,offset-5));root.querySelector('[data-reset]').onclick=()=>close(true);root.addEventListener('keydown',e=>{if(e.key==='Escape')close(true);});attach();}
25// Up to 50 complete tiles belong to one catalogue page. Native scrolling and
26// page links remain usable without JavaScript; JavaScript only opens the ticker.
27for(const root of document.querySelectorAll('[data-nps-catalog]')){
28 const data=read(root),grid=root.querySelector('.nps-catalog-grid');let opened=0,active=null;
29 function close(focus=false){const old=grid.querySelector(`[data-chain="${opened}"] button`);active?.destroy();active=null;grid.querySelector('.nps-detail')?.remove();for(const t of grid.querySelectorAll('.nps-tile')){t.classList.remove('nps-open');t.querySelector('button').setAttribute('aria-expanded','false');}opened=0;if(focus)old?.focus();}
30 function place(){if(!active)return;const tiles=[...grid.querySelectorAll('.nps-tile')],selected=tiles.find(t=>Number(t.dataset.chain)===opened);if(!selected)return;active.box.remove();const top=selected.offsetTop,row=tiles.filter(t=>
30Math.abs(t.offsetTop-top)<3);row.at(-1).after(active.box);}
31 for(const t of grid.querySelectorAll('.nps-tile'))t.querySelector('button').onclick=()=>{const id=Number(t.dataset.chain);if(opened===id){close(true);return;}close();const c=data.items.find(x=>x.id===id);if(!c)return;opened=id;t.classList.add('nps-open');t.querySelector('button').setAttribute('aria-expanded','true');active=detail(c,{auto:true,onClose:()=>close(true)});place();};
32 root.addEventListener('keydown',e=>{if(e.key==='Escape')close(true);});
33 let timer;window.addEventListener('resize',()=>{clearTimeout(timer);timer=setTimeout(place,120);});
34}
35for(const root of document.querySelectorAll('[data-nps-related]')){for(const b of root.querySelectorAll('.nps-switches button'))b.onclick=()=>{for(const other of root.querySelectorAll('.nps-switches button')){const selected=other===b;other.setAttribute('aria-expanded',String(selected));root.querySelector('#'+other.getAttribute('aria-controls')).hidden=!selected;}};}
36})();

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.