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">‹</button>' 61 +'<img alt="">' 62 +'<button class="cpmv-nav cpmv-next" aria-label="Weiter">›</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">×</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">×</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.