Wiki source code of Data Protection & Ethics

Version 5.11 by Veronika Kocher on Thursday, 03 Sep 2026 13:04

Show last authors
1 Assess personal data, confidentiality, consent, sensitive materials and ethical considerations early in the project.
2
3 == Overview ==
4
5 Add a concise explanation of this topic and why it matters for Art & Research projects.
6
7 == What you need to know ==
8
9 * Key concepts
10 * Relevant requirements
11 * Important distinctions
12
13 == What you need to do ==
14
15 1. Identify what applies to your project.
16 2. Document the relevant decisions.
17 3. Use appropriate institutional services and support where needed.
18
19 == Key questions ==
20
21 * What needs to be decided?
22 * Who is responsible?
23 * What needs to be documented?
24 * Are there legal, ethical or technical constraints?
25 * What needs to happen before the next project phase?
26
27 == Services & Tools ==
28
29 Add links to relevant institutional services, infrastructure and tools.
30
31 == Info Sheets & Checklists ==
32
33 Add links to related Info Sheets, checklists and templates.
34
35 == Tutorials ==
36
37
38 {{html}}<span data-arsn-coming-soon="true" style="display:inline-block;margin:6px 0 8px 0;padding:4px 9px;border-radius:14px;background:#fff4ee;border:1px solid #efd9cc;color:#8a4d36;font-size:11px;font-weight:700;letter-spacing:.065em;line-height:1.2;">COMING SOON</span>{{/html}}
39 Add links to step-by-step tutorials for this topic.
40
41 == Related Topics ==
42
43 Add links to related pages in Enable, Work & Manage, and Publish & Share.
44
45 == Who is responsible? ==
46
47
48 {{info title="Service routing"}}
49 **Primary specialist service(s):** Data Protection Officer for personal-data questions; project/host unit and the applicable ethics or funder route for ethical review.
50
51 **Role of Support Kunst und Forschung (SKF):** Coordinates project and funder requirements and helps route specialist review; it is not the data-protection authority.
52 {{/info}}
53
54 If you are unsure which route applies, start with the service named above. For funded or project-based research where several units are involved, SKF can coordinate the project route.
55
56 {{html}}
57 <!-- ARSN_SEARCH_TERMS_START -->
58 <details class="arsn-search-terms" style="margin-top:28px;padding-top:10px;border-top:1px solid #eee;">
59 <summary style="cursor:pointer;color:#666;font-size:13px;">Search terms &amp; related topics</summary>
60 <div style="margin-top:9px;color:#555;font-size:13px;">
61 <p style="margin:0 0 8px 0;">
62 This topic can also be found through related terms, synonyms and common search queries.
63 Select a term to search the Art &amp; Research Services Navigator.
64 </p>
65 <p style="margin:0;"><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=art%20and%20research#arsn-search-input" class="arsn-search-term" data-search-term="art and research" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">art and research</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=enable#arsn-search-input" class="arsn-search-term" data-search-term="enable" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">enable</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=data%20protection#arsn-search-input" class="arsn-search-term" data-search-term="data protection" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">data protection</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=personal%20data#arsn-search-input" class="arsn-search-term" data-search-term="personal data" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">personal data</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=gdpr#arsn-search-input" class="arsn-search-term" data-search-term="gdpr" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">gdpr</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=ethics#arsn-search-input" class="arsn-search-term" data-search-term="ethics" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">ethics</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=consent#arsn-search-input" class="arsn-search-term" data-search-term="consent" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">consent</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=sensitive%20data#arsn-search-input" class="arsn-search-term" data-search-term="sensitive data" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">sensitive data</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=confidentiality#arsn-search-input" class="arsn-search-term" data-search-term="confidentiality" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">confidentiality</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=data%20privacy#arsn-search-input" class="arsn-search-term" data-search-term="data privacy" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">data privacy</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=dsgvo#arsn-search-input" class="arsn-search-term" data-search-term="dsgvo" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">dsgvo</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=anonymisation#arsn-search-input" class="arsn-search-term" data-search-term="anonymisation" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">anonymisation</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=anonymization#arsn-search-input" class="arsn-search-term" data-search-term="anonymization" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">anonymization</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=pseudonymisation#arsn-search-input" class="arsn-search-term" data-search-term="pseudonymisation" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">pseudonymisation</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=pseudonymization#arsn-search-input" class="arsn-search-term" data-search-term="pseudonymization" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">pseudonymization</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=datenschutz#arsn-search-input" class="arsn-search-term" data-search-term="datenschutz" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">datenschutz</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=einwilligung#arsn-search-input" class="arsn-search-term" data-search-term="einwilligung" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">einwilligung</a></p>
66 </div>
67 </details>
68 <!-- ARSN_SEARCH_TERMS_END -->
69 {{/html}}
70
71 {{html clean="false"}}
72 <!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START -->
73
74 <style data-sn-service-navigator-master="1">
75 /* =========================================================
76 MASTER TYPOGRAPHY
77 ========================================================= */
78 #xwikicontent h1,
79 #xwikicontent h2,
80 #xwikicontent h3,
81 #xwikicontent h4,
82 #xwikicontent h5,
83 #xwikicontent h6,
84 #xwikicontent .box-title,
85 #xwikicontent [role="heading"],
86 #xwikicontent h1 a,
87 #xwikicontent h2 a,
88 #xwikicontent h3 a,
89 #xwikicontent h4 a,
90 #xwikicontent h5 a,
91 #xwikicontent h6 a,
92 #xwikicontent .box-title a,
93 #xwikicontent [role="heading"] a{
94 text-align:left!important;
95 text-justify:auto!important;
96 word-spacing:normal!important;
97 }
98
99 /* =========================================================
100 COMING SOON / IN VORBEREITUNG
101 ========================================================= */
102 .sn-coming-soon-badge{
103 display:inline-block;
104 vertical-align:middle;
105 margin-left:10px;
106 padding:4px 8px;
107 border-radius:14px;
108 border:1px solid #efd9cc;
109 background:#fff4ee;
110 color:#8a4d36;
111 font-size:11px;
112 font-weight:700;
113 letter-spacing:.055em;
114 line-height:1.2;
115 white-space:nowrap;
116 }
117
118 /* =========================================================
119 NATIVE / DETAIL CALLOUT GEOMETRY
120 Preserve existing backgrounds.
121 ========================================================= */
122 #xwikicontent .arsn-info,
123 #xwikicontent .dmp-info,
124 #xwikicontent .ido-info,
125 #xwikicontent .pp-info,
126 #xwikicontent .infomessage{
127 box-sizing:border-box!important;
128 border-left:4px solid #21b6d7!important;
129 border-radius:8px;
130 text-align:left!important;
131 word-spacing:normal!important;
132 }
133
134 #xwikicontent .arsn-warn,
135 #xwikicontent .dmp-warn,
136 #xwikicontent .ido-warn,
137 #xwikicontent .pp-warn,
138 #xwikicontent .warn,
139 #xwikicontent .warning,
140 #xwikicontent .warningmessage,
141 #xwikicontent .errormessage{
142 box-sizing:border-box!important;
143 border-left:4px solid #e94b13!important;
144 border-radius:8px;
145 text-align:left!important;
146 word-spacing:normal!important;
147 }
148
149 [data-sn-master-equal-height],
150 [data-sn-master-first-row]{
151 box-sizing:border-box;
152 }
153 </style>
154
155 <script data-sn-service-navigator-master="1">
156 (function(){
157 "use strict";
158
159 var PAGE_KIND="detail";
160 var PLACEHOLDER=true;
161 var PLACEHOLDER_LABEL="COMING SOON";
162
163 var MOBILE_MAX=767;
164 var ROW_TOLERANCE=6;
165 var RESIZE_DEBOUNCE=220;
166
167 var root=
168 document.getElementById("xwikicontent")||
169 document.querySelector(".xwiki-rendering-content")||
170 document.querySelector("main")||
171 document.body;
172
173 if(!root)return;
174
175 var managedHeight=new Set();
176 var managedMargin=new Set();
177 var originalHeight=new WeakMap();
178 var originalMargin=new WeakMap();
179
180 var resizeTimer=0;
181 var running=false;
182
183 var THEMES=[
184 {
185 name:"BLUE",
186 accent:"#21b6d7",
187 bg:"#eaf7fb",
188 text:"#315d68",
189 labels:[
190 "HIER STARTEN",
191 "ENTSCHEIDEN",
192 "ÜBERPRÜFEN & ANPASSEN",
193 "START HERE",
194 "DECIDE",
195 "REVIEW & ADAPT"
196 ]
197 },
198 {
199 name:"RED",
200 accent:"#e94b13",
201 bg:"#fff1ec",
202 text:"#8a4d36",
203 labels:[
204 "PLANEN & ORGANISIEREN",
205 "ORGANISIEREN & DOKUMENTIEREN",
206 "PUBLIZIEREN & PRÄSENTIEREN",
207 "PLAN & ORGANISE",
208 "PLAN & ORGANIZE",
209 "ORGANISE & DOCUMENT",
210 "ORGANIZE & DOCUMENT",
211 "PUBLISH & PRESENT"
212 ]
213 },
214 {
215 name:"YELLOW",
216 accent:"#f0aa00",
217 bg:"#fff8e7",
218 text:"#785b17",
219 labels:[
220 "SCHÜTZEN & KLÄREN",
221 "STANDARDISIEREN & IDENTIFIZIEREN",
222 "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN",
223 "PROTECT & CLARIFY",
224 "STANDARDISE & IDENTIFY",
225 "STANDARDIZE & IDENTIFY",
226 "OPEN, REUSE & MAKE FINDABLE"
227 ]
228 },
229 {
230 name:"GREEN",
231 accent:"#38b76a",
232 bg:"#edf9f1",
233 text:"#3f7451",
234 labels:[
235 "INFRASTRUKTUR EINRICHTEN",
236 "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN",
237 "SPEICHERN & ZUGRIFF STEUERN",
238 "REPOSITORIUM, ERHALTEN & ÜBERGEBEN",
239 "SET UP INFRASTRUCTURE",
240 "SET UP INFRASTRUCTURE & COLLABORATION",
241 "STORE & CONTROL ACCESS",
242 "REPOSITORY, PRESERVE & HAND OVER"
243 ]
244 }
245 ];
246
247 function num(value){
248 var n=parseFloat(value);
249 return Number.isFinite(n)?n:0;
250 }
251
252 function norm(value){
253 return String(value||"")
254 .replace(/\s+/g," ")
255 .trim()
256 .toUpperCase();
257 }
258
259 function visible(el){
260 if(!el||el.nodeType!==1)return false;
261
262 var style=getComputedStyle(el);
263 var rect=el.getBoundingClientRect();
264
265 return (
266 style.display!=="none"&&
267 style.visibility!=="hidden"&&
268 rect.width>20&&
269 rect.height>4
270 );
271 }
272
273 function saveStyle(el,map,property){
274 if(map.has(el))return;
275
276 map.set(el,{
277 value:el.style.getPropertyValue(property),
278 priority:el.style.getPropertyPriority(property)
279 });
280 }
281
282 function restoreStyle(el,map,property){
283 var original=map.get(el);
284
285 if(original&&original.value){
286 el.style.setProperty(
287 property,
288 original.value,
289 original.priority||""
290 );
291 }else{
292 el.style.removeProperty(property);
293 }
294 }
295
296 function resetRuntime(){
297 managedHeight.forEach(function(el){
298 restoreStyle(
299 el,
300 originalHeight,
301 "min-height"
302 );
303 el.removeAttribute(
304 "data-sn-master-equal-height"
305 );
306 });
307
308 managedMargin.forEach(function(el){
309 restoreStyle(
310 el,
311 originalMargin,
312 "margin-top"
313 );
314 el.removeAttribute(
315 "data-sn-master-first-row"
316 );
317 });
318
319 managedHeight.clear();
320 managedMargin.clear();
321 }
322
323 function themeFor(text){
324 var value=norm(text);
325
326 for(var i=0;i<THEMES.length;i++){
327 for(var j=0;j<THEMES[i].labels.length;j++){
328 var label=THEMES[i].labels[j];
329
330 if(
331 value===label||
332 value.indexOf(label+" ")===0||
333 value.indexOf(label+" -")===0||
334 value.indexOf(label+" ·")===0
335 ){
336 return THEMES[i];
337 }
338 }
339 }
340
341 return null;
342 }
343
344 /* =======================================================
345 PLACEHOLDER BADGE
346 ======================================================= */
347
348 function applyPlaceholderBadge(){
349 if(!PLACEHOLDER)return;
350
351 if(
352 document.querySelector(
353 ".sn-coming-soon-badge"
354 )
355 ){
356 return;
357 }
358
359 var title=
360 document.querySelector(
361 "#document-title"
362 )||
363 document.querySelector(
364 "h1"
365 );
366
367 if(!title)return;
368
369 var badge=
370 document.createElement(
371 "span"
372 );
373
374 badge.className=
375 "sn-coming-soon-badge";
376
377 badge.textContent=
378 PLACEHOLDER_LABEL;
379
380 badge.setAttribute(
381 "aria-label",
382 PLACEHOLDER_LABEL
383 );
384
385 title.appendChild(
386 badge
387 );
388 }
389
390 /* =======================================================
391 DETAIL PAGE OWN-ACCENT PROPAGATION
392 ======================================================= */
393
394 function parseRGB(value){
395 var match=String(value||"").match(
396 /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i
397 );
398
399 if(!match)return null;
400
401 return [
402 Number(match[1]),
403 Number(match[2]),
404 Number(match[3])
405 ];
406 }
407
408 function distance(a,b){
409 return Math.sqrt(
410 Math.pow(a[0]-b[0],2)+
411 Math.pow(a[1]-b[1],2)+
412 Math.pow(a[2]-b[2],2)
413 );
414 }
415
416 function paletteMatch(cssColor){
417 var rgb=parseRGB(cssColor);
418
419 if(!rgb)return null;
420
421 var palette=[
422 {hex:"#21b6d7",rgb:[33,182,215]},
423 {hex:"#e94b13",rgb:[233,75,19]},
424 {hex:"#f0aa00",rgb:[240,170,0]},
425 {hex:"#38b76a",rgb:[56,183,106]}
426 ];
427
428 var best=null;
429 var bestDistance=Infinity;
430
431 palette.forEach(function(item){
432 var d=distance(rgb,item.rgb);
433
434 if(d<bestDistance){
435 best=item;
436 bestDistance=d;
437 }
438 });
439
440 return bestDistance<=30
441 ?best
442 :null;
443 }
444
445 function propagateDetailAccents(){
446 if(PAGE_KIND!=="detail")return;
447
448 Array.from(
449 root.querySelectorAll(
450 ".arsn-call,.dmp-call,.ido-call,.pp-call,"+
451 ".arsn-source,.dmp-source,.ido-source,.pp-source"
452 )
453 ).forEach(function(el){
454 if(!visible(el))return;
455
456 var style=getComputedStyle(el);
457
458 if(
459 num(style.borderTopWidth)>=2
460 ){
461 var match=
462 paletteMatch(
463 style.borderTopColor
464 );
465
466 if(match){
467 el.style.setProperty(
468 "border-left",
469 "4px solid "+match.hex,
470 "important"
471 );
472 }
473 }
474 });
475
476 // Warning families: explicit safety override.
477 Array.from(
478 root.querySelectorAll(
479 ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+
480 ".warn,.warning,.warningmessage,.errormessage"
481 )
482 ).forEach(function(el){
483 if(!visible(el))return;
484
485 el.style.setProperty(
486 "border-left",
487 "4px solid #e94b13",
488 "important"
489 );
490 });
491
492 // Info families: explicit orientation override.
493 Array.from(
494 root.querySelectorAll(
495 ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage"
496 )
497 ).forEach(function(el){
498 if(!visible(el))return;
499
500 el.style.setProperty(
501 "border-left",
502 "4px solid #21b6d7",
503 "important"
504 );
505 });
506 }
507
508 /* =======================================================
509 OVERVIEW SEMANTIC THEME PALETTE
510 ======================================================= */
511
512 function smallestThemeHeaders(){
513 return Array.from(
514 root.querySelectorAll(
515 "div,span,p,strong,h3,h4,h5,h6"
516 )
517 ).filter(function(el){
518 if(!visible(el))return false;
519 if(!themeFor(el.textContent))return false;
520
521 return !Array.from(
522 el.children||[]
523 ).some(function(child){
524 return !!themeFor(
525 child.textContent
526 );
527 });
528 });
529 }
530
531 function findOverviewCard(header){
532 var node=header.parentElement;
533 var candidates=[];
534
535 while(node&&node!==root){
536 var rect=node.getBoundingClientRect();
537 var style=getComputedStyle(node);
538
539 var border=
540 num(style.borderTopWidth)+
541 num(style.borderRightWidth)+
542 num(style.borderBottomWidth)+
543 num(style.borderLeftWidth);
544
545 if(
546 rect.width>=220&&
547 rect.width<=800&&
548 rect.height>=120&&
549 border>=1
550 ){
551 candidates.push(node);
552 }
553
554 node=node.parentElement;
555 }
556
557 if(!candidates.length)return null;
558
559 candidates.sort(function(a,b){
560 return (
561 b.getBoundingClientRect().height-
562 a.getBoundingClientRect().height
563 );
564 });
565
566 return candidates[0];
567 }
568
569 function rowCandidates(link,card){
570 var result=[];
571 var cardRect=
572 card.getBoundingClientRect();
573
574 var node=link;
575
576 while(node&&node!==card){
577 if(visible(node)){
578 var rect=
579 node.getBoundingClientRect();
580
581 if(
582 rect.height<=105&&
583 rect.width>=
584 cardRect.width*.50&&
585 rect.width<=
586 cardRect.width*1.03
587 ){
588 result.push(node);
589 }
590 }
591
592 node=node.parentElement;
593 }
594
595 return result;
596 }
597
598 function chooseOuterRow(
599 candidates,
600 link
601 ){
602 if(!candidates.length){
603 return link;
604 }
605
606 var bordered=
607 candidates.filter(function(el){
608 return (
609 num(
610 getComputedStyle(el)
611 .borderLeftWidth
612 )>=1
613 );
614 });
615
616 var pool=
617 bordered.length
618 ?bordered
619 :candidates;
620
621 pool.sort(function(a,b){
622 var ar=
623 a.getBoundingClientRect();
624
625 var br=
626 b.getBoundingClientRect();
627
628 return (
629 ar.left-br.left||
630 br.width-ar.width
631 );
632 });
633
634 return pool[0]||link;
635 }
636
637 function applyOverviewPalette(){
638 if(PAGE_KIND!=="overview"){
639 return [];
640 }
641
642 var headers=
643 smallestThemeHeaders()
644 .map(function(el){
645 return {
646 el:el,
647 theme:
648 themeFor(
649 el.textContent
650 ),
651 card:
652 findOverviewCard(
653 el
654 )
655 };
656 })
657 .filter(function(row){
658 return !!row.card;
659 });
660
661 var unique=[];
662 var seenHeaders=new Set();
663
664 headers.forEach(function(row){
665 var key=
666 row.theme.name+
667 "|"+
668 Math.round(
669 row.card
670 .getBoundingClientRect()
671 .left
672 )+
673 "|"+
674 Math.round(
675 row.el
676 .getBoundingClientRect()
677 .top
678 );
679
680 if(!seenHeaders.has(key)){
681 seenHeaders.add(key);
682 unique.push(row);
683 }
684 });
685
686 unique.forEach(function(row){
687 var headerRect=
688 row.el
689 .getBoundingClientRect();
690
691 row.el.style.setProperty(
692 "background",
693 row.theme.bg,
694 "important"
695 );
696
697 row.el.style.setProperty(
698 "color",
699 row.theme.text,
700 "important"
701 );
702
703 row.el.style.setProperty(
704 "text-align",
705 "left",
706 "important"
707 );
708
709 row.el.style.setProperty(
710 "word-spacing",
711 "normal",
712 "important"
713 );
714
715 var later=
716 unique
717 .filter(function(other){
718 return (
719 other.card===row.card&&
720 other.el
721 .getBoundingClientRect()
722 .top>
723 headerRect.top+2
724 );
725 })
726 .sort(function(a,b){
727 return (
728 a.el
729 .getBoundingClientRect()
730 .top-
731 b.el
732 .getBoundingClientRect()
733 .top
734 );
735 });
736
737 var stopTop=
738 later.length
739 ?later[0].el
740 .getBoundingClientRect()
741 .top
742 :Infinity;
743
744 Array.from(
745 row.card.querySelectorAll("a")
746 ).forEach(function(link){
747 if(!visible(link))return;
748
749 var rect=
750 link.getBoundingClientRect();
751
752 if(
753 rect.top<=
754 headerRect.bottom-2||
755 rect.top>=
756 stopTop-2
757 ){
758 return;
759 }
760
761 var candidates=
762 rowCandidates(
763 link,
764 row.card
765 );
766
767 var target=
768 chooseOuterRow(
769 candidates,
770 link
771 );
772
773 candidates.forEach(function(el){
774 el.style.setProperty(
775 "border-left",
776 "0 solid transparent",
777 "important"
778 );
779 });
780
781 target.style.setProperty(
782 "border-left",
783 "3px solid "+
784 row.theme.accent,
785 "important"
786 );
787
788 target.style.setProperty(
789 "box-sizing",
790 "border-box",
791 "important"
792 );
793 });
794 });
795
796 return unique;
797 }
798
799 /* =======================================================
800 OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW
801 ======================================================= */
802
803 function alignOverviewCards(headers){
804 if(
805 PAGE_KIND!=="overview"||
806 window.innerWidth<=MOBILE_MAX
807 ){
808 return;
809 }
810
811 var cards=[];
812 var seen=new Set();
813
814 headers.forEach(function(row){
815 if(!seen.has(row.card)){
816 seen.add(row.card);
817 cards.push(row.card);
818 }
819 });
820
821 if(cards.length<2){
822 return;
823 }
824
825 // Group cards by actual top position.
826 var groups=[];
827
828 cards.forEach(function(card){
829 var top=
830 card.getBoundingClientRect().top;
831
832 var group=null;
833
834 for(var i=0;i<groups.length;i++){
835 if(
836 Math.abs(
837 groups[i].top-top
838 )<=ROW_TOLERANCE
839 ){
840 group=groups[i];
841 break;
842 }
843 }
844
845 if(!group){
846 group={
847 top:top,
848 cards:[]
849 };
850 groups.push(group);
851 }
852
853 group.cards.push(card);
854 });
855
856 groups.forEach(function(group){
857 if(group.cards.length<2){
858 return;
859 }
860
861 var firstHeaders=
862 group.cards.map(function(card){
863 var candidates=
864 headers
865 .filter(function(row){
866 return row.card===card;
867 })
868 .sort(function(a,b){
869 return (
870 a.el
871 .getBoundingClientRect()
872 .top-
873 b.el
874 .getBoundingClientRect()
875 .top
876 );
877 });
878
879 return candidates.length
880 ?candidates[0]
881 :null;
882 });
883
884 if(
885 !firstHeaders.some(function(row){
886 return !row;
887 })
888 ){
889 var targetTop=
890 Math.max.apply(
891 Math,
892 firstHeaders.map(function(row){
893 return (
894 row.el
895 .getBoundingClientRect()
896 .top-
897 row.card
898 .getBoundingClientRect()
899 .top
900 );
901 })
902 );
903
904 firstHeaders.forEach(function(row){
905 var relativeTop=
906 row.el
907 .getBoundingClientRect()
908 .top-
909 row.card
910 .getBoundingClientRect()
911 .top;
912
913 var delta=
914 targetTop-relativeTop;
915
916 if(delta>1){
917 saveStyle(
918 row.el,
919 originalMargin,
920 "margin-top"
921 );
922
923 var current=
924 num(
925 getComputedStyle(
926 row.el
927 ).marginTop
928 );
929
930 row.el.style.setProperty(
931 "margin-top",
932 (
933 current+delta
934 )+"px"
935 );
936
937 row.el.setAttribute(
938 "data-sn-master-first-row",
939 "1"
940 );
941
942 managedMargin.add(
943 row.el
944 );
945 }
946 });
947 }
948
949 var maxHeight=0;
950
951 group.cards.forEach(function(card){
952 maxHeight=
953 Math.max(
954 maxHeight,
955 card
956 .getBoundingClientRect()
957 .height
958 );
959 });
960
961 maxHeight=
962 Math.ceil(maxHeight);
963
964 group.cards.forEach(function(card){
965 saveStyle(
966 card,
967 originalHeight,
968 "min-height"
969 );
970
971 card.style.setProperty(
972 "min-height",
973 maxHeight+"px"
974 );
975
976 card.setAttribute(
977 "data-sn-master-equal-height",
978 "1"
979 );
980
981 managedHeight.add(
982 card
983 );
984 });
985 });
986 }
987
988 /* =======================================================
989 DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY
990 ======================================================= */
991
992 function equaliseDetailGrids(){
993 if(
994 PAGE_KIND!=="detail"||
995 window.innerWidth<=MOBILE_MAX
996 ){
997 return;
998 }
999
1000 var selectors=[
1001 ".arsn-grid",
1002 ".arsn-grid-2",
1003 ".arsn-grid-3",
1004 ".dmp-grid",
1005 ".ido-grid",
1006 ".pp-grid"
1007 ];
1008
1009 selectors.forEach(function(selector){
1010 Array.from(
1011 root.querySelectorAll(selector)
1012 ).forEach(function(grid){
1013 var children=
1014 Array.from(
1015 grid.children||[]
1016 ).filter(visible);
1017
1018 if(children.length<2){
1019 return;
1020 }
1021
1022 var groups=[];
1023
1024 children.forEach(function(child){
1025 var top=
1026 child
1027 .getBoundingClientRect()
1028 .top;
1029
1030 var group=null;
1031
1032 for(var i=0;i<groups.length;i++){
1033 if(
1034 Math.abs(
1035 groups[i].top-top
1036 )<=ROW_TOLERANCE
1037 ){
1038 group=groups[i];
1039 break;
1040 }
1041 }
1042
1043 if(!group){
1044 group={
1045 top:top,
1046 items:[]
1047 };
1048 groups.push(group);
1049 }
1050
1051 group.items.push(child);
1052 });
1053
1054 groups.forEach(function(group){
1055 if(group.items.length<2){
1056 return;
1057 }
1058
1059 var maxHeight=0;
1060
1061 group.items.forEach(function(item){
1062 maxHeight=
1063 Math.max(
1064 maxHeight,
1065 item
1066 .getBoundingClientRect()
1067 .height
1068 );
1069 });
1070
1071 maxHeight=
1072 Math.ceil(maxHeight);
1073
1074 group.items.forEach(function(item){
1075 saveStyle(
1076 item,
1077 originalHeight,
1078 "min-height"
1079 );
1080
1081 item.style.setProperty(
1082 "min-height",
1083 maxHeight+"px"
1084 );
1085
1086 item.setAttribute(
1087 "data-sn-master-equal-height",
1088 "1"
1089 );
1090
1091 managedHeight.add(item);
1092 });
1093 });
1094 });
1095 });
1096 }
1097
1098 /* =======================================================
1099 RUN / RESPONSIVE SCHEDULING
1100 ======================================================= */
1101
1102 function run(){
1103 if(running)return;
1104
1105 running=true;
1106
1107 try{
1108 resetRuntime();
1109 applyPlaceholderBadge();
1110 propagateDetailAccents();
1111
1112 var headers=
1113 applyOverviewPalette();
1114
1115 if(
1116 window.innerWidth>
1117 MOBILE_MAX
1118 ){
1119 alignOverviewCards(
1120 headers
1121 );
1122
1123 equaliseDetailGrids();
1124 }
1125 }finally{
1126 running=false;
1127 }
1128 }
1129
1130 function onResize(){
1131 if(resizeTimer){
1132 clearTimeout(
1133 resizeTimer
1134 );
1135 }
1136
1137 resizeTimer=
1138 setTimeout(
1139 function(){
1140 resizeTimer=0;
1141 run();
1142 },
1143 RESIZE_DEBOUNCE
1144 );
1145 }
1146
1147 async function waitForReady(){
1148 if(
1149 document.readyState!=="complete"
1150 ){
1151 await new Promise(function(resolve){
1152 window.addEventListener(
1153 "load",
1154 resolve,
1155 {once:true}
1156 );
1157 });
1158 }
1159
1160 if(
1161 document.fonts&&
1162 document.fonts.ready
1163 ){
1164 try{
1165 await document.fonts.ready;
1166 }catch(error){}
1167 }
1168
1169 var images=
1170 Array.from(
1171 root.querySelectorAll("img")
1172 );
1173
1174 await Promise.all(
1175 images.map(function(img){
1176 if(img.complete){
1177 return Promise.resolve();
1178 }
1179
1180 return new Promise(function(resolve){
1181 var done=function(){
1182 resolve();
1183 };
1184
1185 img.addEventListener(
1186 "load",
1187 done,
1188 {once:true}
1189 );
1190
1191 img.addEventListener(
1192 "error",
1193 done,
1194 {once:true}
1195 );
1196 });
1197 })
1198 );
1199
1200 run();
1201 }
1202
1203 window.addEventListener(
1204 "resize",
1205 onResize,
1206 {passive:true}
1207 );
1208
1209 waitForReady();
1210 })();
1211 </script>
1212
1213 <!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END -->
1214 {{/html}}