PageSourceSearch

https://warsight.com/wp-content/uploads/cpm-embed/cpm-embed.js?ver=1788448648

js warsight.com collected 2026-09-26 17:50:23 UTC 15,978 bytes, 254 lines download raw bytes

1(function(){
2  if(window.__cpmViewer)return; window.__cpmViewer=true;
3  var v,img,count,title,cap,credit,link,panel,bT,bC,bCr,bL,items=[],cur=0,creditLabel='Foto: ',linkDefault='Zum Artikel',cpmvSlug='',cpmvName='';
4  // v0.41.0: privacy-light view beacon. Derive the archiv origin from this
5  // script's own src, fire at most once per slug+kind per page load. No
6  // cookies, no IDs -- the server only keeps aggregate counts.
7  var BASE=(function(){try{var s=document.currentScript&&document.currentScript.src||'';
8    return s.replace(/\/api\/v1\/embed\/cpm-embed\.js.*$/,'');}catch(_){return '';}})();
9  var beaconSent={};
10  function beacon(slug,kind){
11    if(!slug||!BASE)return;var key=slug+'|'+kind;if(beaconSent[key])return;beaconSent[key]=true;
12    var url=BASE+'/api/v1/collections/'+encodeURIComponent(slug)+'/view?kind='+kind;
13    try{if(navigator.sendBeacon){navigator.sendBeacon(url);}
14      else{fetch(url,{method:'POST',keepalive:true,mode:'no-cors'});}}catch(_){}
15  }
16  function beaconRenders(){
17    try{document.querySelectorAll('[data-cpm-json][data-slug],.cpm-gallery-data[data-slug]').forEach(function(el){
18      beacon(el.getAttribute('data-slug'),'render');});}catch(_){}
19  }
20  // v0.42.2: collection-name heading on each Laufband, top-left. We read the
21  // name from the band's existing aria-label (no snippet re-paste); a future
22  // snippet may set data-cpm-heading for a custom title, which wins.
23  function bandTitles(){
24    try{document.querySelectorAll('.cpm-band').forEach(function(b){
25      if(b.getAttribute('data-cpm-titled'))return;
26      var t=b.getAttribute('data-cpm-heading')||b.getAttribute('aria-label')||'';
27      t=(t||'').trim();if(!t||!b.parentNode)return;
28      b.setAttribute('data-cpm-titled','1');
29      var el=document.createElement('div');el.className='cpm-band-title';el.textContent=t;
30      b.parentNode.insertBefore(el,b);  // sits ABOVE the band, on the page
31    });}catch(_){}
32  }
33  function onReady(){beaconRenders();bandTitles();}
34  if(document.readyState!=='loading')onReady();
35  else document.addEventListener('DOMContentLoaded',onReady);
36  // belt-and-suspenders: re-run after full load + a short delay, for themes
37  // that inject the band late. The existing-title check makes this idempotent.
38  window.addEventListener('load',bandTitles);
39  setTimeout(bandTitles,1500);
40  function labelFor(island){return island&&island.getAttribute('data-lang')==='en'?'Photo: ':'Foto: ';}
41  function linkLabelFor(island){return island&&island.getAttribute('data-lang')==='en'?'To the article':'Zum Artikel';}
42  var MAX='<svg viewBox="0 0 24 24"><path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"/></svg>';
43  var MIN='<svg viewBox="0 0 24 24"><path d="M9 4v5H4M15 4v5h5M9 20v-5H4M15 20v-5h5"/></svg>';
44  var KPLAY='<svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>';
45  // Align the right panel's title with the (vertically-centred) image's top
46  // edge. The image top is dynamic (depends on its aspect), so we sync it in JS
47  // and never go below the default 64px button clearance. Skipped on the mobile
48  // stacked layout and in full mode (panel hidden) -> CSS padding takes over.
49  function syncCaptionTop(){
50    if(!v||!panel||!img||!v.classList.contains('open'))return;
51    if(window.innerWidth<=760||v.classList.contains('full')){panel.style.paddingTop='';return;}
52    var top=Math.round(img.getBoundingClientRect().top-v.getBoundingClientRect().top);
53    if(top>0)panel.style.paddingTop=Math.max(64,top)+'px';
54  }
55  function build(){
56    v=document.createElement('div');v.className='cpmv';
57    v.innerHTML=
58      '<div class="cpmv-stage">'
59      +'<div class="cpmv-count"></div>'
60      +'<button class="cpmv-nav cpmv-prev" aria-label="Zurueck">&#8249;</button>'
61      +'<img alt="">'
62      +'<button class="cpmv-nav cpmv-next" aria-label="Weiter">&#8250;</button>'
63      +'</div>'
64      +'<aside class="cpmv-panel"><h3 class="cpmv-title"></h3>'
65      +'<p class="cpmv-cap"></p>'
66      +'<a class="cpmv-link" target="_blank" rel="noopener"></a>'
67      +'<p class="cpmv-credit"></p></aside>'
68      +'<button class="cpmv-play" aria-label="Diashow">'+KPLAY+'</button>'
69      +'<button class="cpmv-max" aria-label="Vollbild">'+MAX+'</button>'
70      +'<button class="cpmv-x" aria-label="Schliessen">&times;</button>'
71      +'<div class="cpmv-bottom"><span class="bt"></span> <span class="bc"></span> <a class="bl" target="_blank" rel="noopener"></a> <span class="bcr c"></span></div>';
72    document.body.appendChild(v);
73    img=v.querySelector('img');count=v.querySelector('.cpmv-count');
74    title=v.querySelector('.cpmv-title');cap=v.querySelector('.cpmv-cap');credit=v.querySelector('.cpmv-credit');link=v.querySelector('.cpmv-link');panel=v.querySelector('.cpmv-panel');
75    bT=v.querySelector('.cpmv-bottom .bt');bC=v.querySelector('.cpmv-bottom .bc');bCr=v.querySelector('.cpmv-bottom .bcr');bL=v.querySelector('.cpmv-bottom .bl');
76    v.querySelector('.cpmv-prev').addEventListener('click',function(e){e.stopPropagation();show(cur-1);});
77    v.querySelector('.cpmv-next').addEventListener('click',function(e){e.stopPropagation();show(cur+1);});
78    v.querySelector('.cpmv-x').addEventListener('click',close);
79    v.querySelector('.cpmv-max').addEventListener('click',function(e){e.stopPropagation();toggleFull();});
80    v.querySelector('.cpmv-play').addEventListener('click',function(e){e.stopPropagation();var its=items.slice();close();kStart(cpmvSlug,its,cpmvName);});
81    v.querySelector('.cpmv-stage').addEventListener('click',function(e){if(e.target===e.currentTarget)close();});
82    document.addEventListener('keydown',function(e){
83      if(!v.classList.contains('open'))return;
84      if(e.key==='Escape'){ if(v.classList.contains('full')){toggleFull();} else {close();} }
85      else if(e.key==='ArrowLeft')show(cur-1);
86      else if(e.key==='ArrowRight')show(cur+1);
87    });
88    window.addEventListener('resize',syncCaptionTop);
89  }
90  function toggleFull(){
91    var f=v.classList.toggle('full');
92    v.querySelector('.cpmv-max').innerHTML=f?MIN:MAX;
93    syncCaptionTop();
94  }
95  function show(i){
96    var n=items.length;cur=((i%n)+n)%n;var it=items[cur];
97    img.onload=syncCaptionTop;  // re-align the title once the new image lays out
98    img.src=it.full;img.alt=it.cap||it.title||'';
99    syncCaptionTop();
100    count.textContent=(cur+1)+' / '+n;
101    title.textContent=it.title||'';title.style.display=it.title?'':'none';
102    cap.textContent=it.cap||'';cap.style.display=it.cap?'':'none';
103    credit.textContent=it.credit?(creditLabel+it.credit):'';credit.style.display=it.credit?'':'none';
104    if(it.art){link.href=it.art;link.textContent=it.artlabel||linkDefault;link.style.display='';
105      bL.href=it.art;bL.textContent=it.artlabel||linkDefault;bL.style.display='';}
106    else{link.style.display='none';link.removeAttribute('href');bL.style.display='none';bL.removeAttribute('href');}
107    bT.textContent=it.title||'';
108    bC.textContent=it.cap||'';
109    bCr.textContent=it.credit?(creditLabel+it.credit):'';
110  }
111  function open(its,i,full){ if(!v)build(); items=its;
112    if(full){v.classList.add('full');v.querySelector('.cpmv-max').innerHTML=MIN;}
113    else{v.classList.remove('full');v.querySelector('.cpmv-max').innerHTML=MAX;}
114    show(i||0); v.classList.add('open'); }
115  function close(){ if(v){v.classList.remove('open','full');img.src='';} }
116  // v0.44.7: resolve a gallery's data element. Prefer the content-bearing
117  // CONTAINER (.cpm-band/.cpm-gallery/.cpm-inline carries data-cpm-json) -- it
118  // survives page builders (WPBakery/wpautop strip a standalone island div).
119  // Fall back to the legacy separate .cpm-gallery-data element.
120  function cpmIsland(slug,fromEl){
121    var el=(fromEl&&fromEl.closest)?fromEl.closest('[data-cpm-json]'):null;
122    if(!el&&slug)el=document.querySelector('[data-cpm-json][data-slug="'+slug+'"]');
123    if(!el&&slug)el=document.querySelector('.cpm-gallery-data[data-slug="'+slug+'"]');
124    return el;
125  }
126  document.addEventListener('click',function(e){
127    var a=e.target.closest?e.target.closest('[data-cpmg-slug]'):null;
128    if(!a)return;
129    var island=cpmIsland(a.getAttribute('data-cpmg-slug'),a);
130    if(!island)return;
131    var its;try{its=JSON.parse((island.getAttribute('data-cpm-json')||island.textContent));}catch(_){return;}
132    if(!its||!its.length)return;
133    e.preventDefault();e.stopPropagation();
134    creditLabel=labelFor(island);linkDefault=linkLabelFor(island);
135    cpmvSlug=a.getAttribute('data-cpmg-slug')||'';
136    cpmvName=(island.getAttribute('aria-label')||island.getAttribute('data-cpm-heading')||'').trim();
137    beacon(cpmvSlug,'open');
138    open(its,parseInt(a.getAttribute('data-cpmg-index')||'0',10));
139  },true);
140  // Programmatic open (used by the inline viewer's maximize button).
141  window.cpmvOpen=function(slug,idx,full){
142    var island=cpmIsland(slug,null);
143    if(!island)return;var its;try{its=JSON.parse((island.getAttribute('data-cpm-json')||island.textContent));}catch(_){return;}
144    if(its&&its.length){creditLabel=labelFor(island);linkDefault=linkLabelFor(island);
145      cpmvSlug=slug||'';cpmvName=(island.getAttribute('aria-label')||island.getAttribute('data-cpm-heading')||'').trim();
146      beacon(slug,'open');open(its,idx||0,full);}
147  };
148  // Inline gallery viewer (the [cpm_viewer] widget).
149  function setInline(w,i){
150    var imgs=w.querySelectorAll('.cpm-inline-img');var n=imgs.length;if(!n)return;
151    i=((i%n)+n)%n;
152    for(var k=0;k<n;k++)imgs[k].classList.toggle('active',k===i);
153    w.setAttribute('data-cur',i);
154    var c=w.querySelector('.cpm-inline-count');if(c)c.textContent=(i+1)+' / '+n;
155    var island=cpmIsland(w.getAttribute('data-slug'),w);
156    var side=w.querySelector('.cpm-inline-side');
157    if(island&&side){try{var it=JSON.parse((island.getAttribute('data-cpm-json')||island.textContent))[i];side.innerHTML='';
158      if(it.title){var t=document.createElement('span');t.className='t';t.textContent=it.title;side.appendChild(t);}
159      if(it.cap){var d=document.createElement('p');d.className='d';d.textContent=it.cap;side.appendChild(d);}
160      if(it.art){var lk=document.createElement('a');lk.className='lk';lk.href=it.art;lk.target='_blank';lk.rel='noopener';lk.textContent=it.artlabel||linkLabelFor(island);side.appendChild(lk);}
161      if(it.credit){var c=document.createElement('p');c.className='cr';c.textContent=labelFor(island)+it.credit;side.appendChild(c);}
162    }catch(_){}}
163  }
164  document.addEventListener('click',function(e){
165    var b=e.target.closest?e.target.closest('.cpm-inline-prev,.cpm-inline-next,.cpm-inline-max'):null;
166    if(!b)return;var w=b.closest('.cpm-inline');if(!w)return;
167    e.preventDefault();e.stopPropagation();
168    var cur=parseInt(w.getAttribute('data-cur')||'0',10);
169    if(b.classList.contains('cpm-inline-max')){if(window.cpmvOpen)window.cpmvOpen(w.getAttribute('data-slug'),cur,true);return;}
170    setInline(w,b.classList.contains('cpm-inline-prev')?cur-1:cur+1);
171  },true);
172  // ---- Kinomode (v0.47.0): fullscreen auto-slideshow over a gallery --------
173  // A play button rides each gallery container; click => the .cpmk overlay
174  // crossfades through every image with Ken-Burns motion. No captions/sidebar,
175  // just play + stop (X / Esc). All motion on: randomized order, smooth
176  // crossfade, dynamic motion, ~5s/pic, CPM logo + collection name bottom-left.
177  var kv,ka,kb,kTop=true,kItems=[],kOrder=[],kPos=0,kTimer=null,kWake=null,KSEC=5,KDUR=11;
178  var kPre=['1,0,0,1.22,-8,-6','1.22,-8,-6,1,0,0','1.08,-9,0,1.2,9,0',
179            '1.08,9,0,1.2,-9,0','1.08,0,-9,1.2,0,9','1.2,7,7,1,-7,-7'];
180  function khash(s){var h=0,i;s=s||'';for(i=0;i<s.length;i++){h=((h<<5)-h+s.charCodeAt(i))|0;}return Math.abs(h);}
181  function kShuffle(a){a=a.slice();for(var i=a.length-1;i>0;i--){var j=Math.floor(Math.random()*(i+1)),t=a[i];a[i]=a[j];a[j]=t;}return a;}
182  function kKB(layer,src){
183    var p=kPre[khash(src)%6].split(','),st=layer.style;
184    st.setProperty('--s0',p[0]);st.setProperty('--x0',p[1]+'%');st.setProperty('--y0',p[2]+'%');
185    st.setProperty('--s1',p[3]);st.setProperty('--x1',p[4]+'%');st.setProperty('--y1',p[5]+'%');
186    var d=(0.2+(khash(src)%4)*0.07)*KDUR;
187    st.animation='none';void layer.offsetWidth;  // restart the keyframe
188    st.animation='cpmk-kb '+KDUR.toFixed(2)+'s linear -'+d.toFixed(2)+'s forwards';
189  }
190  // Screen wake lock: keep the display awake during the slideshow. Feature-
191  // detected; re-acquired on tab re-focus (the OS releases it when hidden).
192  function kWakeOn(){try{if(!navigator.wakeLock||document.visibilityState!=='visible'||!kv||!kv.classList.contains('open'))return;navigator.wakeLock.request('screen').then(function(s){kWake=s;}).catch(function(){});}catch(_){}}
193  function kWakeOff(){try{if(kWake){kWake.release();kWake=null;}}catch(_){}}
194  function kBuild(){
195    kv=document.createElement('div');kv.className='cpmk';
196    kv.innerHTML='<img class="cpmk-l cpmk-a" alt="">'
197      +'<img class="cpmk-l cpmk-b" alt="">'
198      +'<div class="cpmk-brand"><img class="cpmk-logo" alt="CPM" src="'+BASE+'/api/v1/embed/cpm-logo.png">'
199      +'<div class="cpmk-title"></div></div>'
200      +'<button class="cpmk-x" type="button" aria-label="Schliessen">&times;</button>';
201    document.body.appendChild(kv);
202    ka=kv.querySelector('.cpmk-a');kb=kv.querySelector('.cpmk-b');
203    kv.querySelector('.cpmk-x').addEventListener('click',kStop);
204    document.addEventListener('keydown',function(e){
205      if(kv&&kv.classList.contains('open')&&e.key==='Escape')kStop();
206    });
207    document.addEventListener('visibilitychange',function(){if(document.visibilityState==='visible')kWakeOn();});
208  }
209  function kShow(idx){
210    var n=kOrder.length;if(!n)return;kPos=((idx%n)+n)%n;
211    var it=kItems[kOrder[kPos]],src=it.full||it.thumb||'';
212    var top=kTop?kb:ka,under=kTop?ka:kb;
213    kKB(top,src);
214    var reveal=function(){top.classList.add('show');under.classList.remove('show');};
215    top.onload=reveal;top.onerror=reveal;top.src=src;
216    if(top.complete&&top.naturalWidth){top.onload=null;reveal();}
217    kTop=!kTop;
218    var nx=kItems[kOrder[(kPos+1)%n]];if(nx){var pi=new Image();pi.src=nx.full||nx.thumb||'';}
219  }
220  function kTick(){if(kTimer)clearTimeout(kTimer);kTimer=setTimeout(function(){kShow(kPos+1);kTick();},Math.max(2,KSEC)*1000);}
221  var kNameCache={},kCurSlug='';
222  function kFetchName(slug,cb){
223    // The Betrachter (.cpm-inline) container carries no collection name, so
224    // pull it from the public JSON (cross-origin allowed since v0.47.1). Only
225    // cache a non-empty name, so a transient blank never poisons the cache.
226    if(!slug||!BASE){cb('');return;}
227    if(kNameCache[slug]){cb(kNameCache[slug]);return;}
228    try{fetch(BASE+'/api/v1/collections/'+encodeURIComponent(slug)).then(function(r){return r.ok?r.json():null;}).then(function(d){
229      var nm=(d&&d.name)?d.name:'';if(nm)kNameCache[slug]=nm;cb(nm);
230    }).catch(function(){cb('');});}catch(_){cb('');}
231  }
232  function kStart(slug,its,name){
233    if(!its||its.length<1)return;if(!kv)kBuild();
234    kCurSlug=slug||'';
235    kItems=its;kOrder=kShuffle(its.map(function(_,i){return i;}));kPos=0;kTop=true;
236    var tEl=kv.querySelector('.cpmk-title');
237    function setT(nm){tEl.textContent=nm||'';tEl.style.display=nm?'':'none';}
238    setT(name);
239    // Open FIRST, then resolve the name -- kFetchName may call back
240    // synchronously on a cache hit, and the callback's open-guard would
241    // otherwise skip setting the title (the "sometimes no title" bug). The
242    // slug check guards against a stale async result from another collection.
243    kv.classList.add('open');
244    if(!name)kFetchName(slug,function(nm){if(kv&&kv.classList.contains('open')&&slug===kCurSlug)setT(nm);});
245    try{if(kv.requestFullscreen)kv.requestFullscreen();}catch(_){}
246    kShow(0);kTick();beacon(slug,'open');kWakeOn();
247  }
248  function kStop(){
249    if(kTimer){clearTimeout(kTimer);kTimer=null;}
250    kWakeOff();
251    if(kv){kv.classList.remove('open');if(ka)ka.src='';if(kb)kb.src='';}
252    try{if(document.fullscreenElement)document.exitFullscreen();}catch(_){}
253  }
254})();

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.