Changes for page Copyright, Rights & Licences
Last modified by Veronika Kocher on Friday, 18 Sep 2026 16:47
From version 5.9
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:34
on Thursday, 03 Sep 2026 9:34
Change comment:
There is no comment for this version
To version 5.8
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:18
on Thursday, 03 Sep 2026 9:18
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -70,22 +70,20 @@ 70 70 71 71 {{html clean="false"}} 72 72 <!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 73 -<style data-sn-horizontal-box-harmonizer=" 4">74 -[data-sn-equal-height-managed] ,75 - [data-sn-first-section-aligned]{76 - box-sizing:border-box;73 +<style data-sn-horizontal-box-harmonizer="1"> 74 +[data-sn-equal-height-managed="1"]{box-sizing:border-box} 75 +@media(max-width:767px){ 76 + [data-sn-equal-height-managed="1"]{min-height:0!important} 77 77 } 78 78 </style> 79 -<script data-sn-horizontal-box-harmonizer=" 4">79 +<script data-sn-horizontal-box-harmonizer="1"> 80 80 (function(){ 81 81 "use strict"; 82 82 83 83 var MOBILE_MAX=767; 84 - var ROW_TOLERANCE= 6;84 + var ROW_TOLERANCE=4; 85 85 var MIN_W=150; 86 86 var MIN_H=36; 87 - var MAX_PARENT_CHILDREN=16; 88 - var SEARCH_DEPTH=5; 89 89 90 90 var root= 91 91 document.getElementById("xwikicontent")|| ... ... @@ -95,10 +95,7 @@ 95 95 96 96 if(!root)return; 97 97 98 - var heightManaged=new Set(); 99 - var sectionManaged=new Set(); 100 - var originalMinHeight=new WeakMap(); 101 - var originalMarginTop=new WeakMap(); 96 + var managed=new Set(); 102 102 var raf=0; 103 103 104 104 function num(v){ ... ... @@ -106,181 +106,64 @@ 106 106 return Number.isFinite(n)?n:0; 107 107 } 108 108 109 - function visible(el ,minW,minH){104 + function visible(el){ 110 110 if(!el||el.nodeType!==1)return false; 111 - 112 112 var s=getComputedStyle(el); 113 - 114 - if( 115 - s.display==="none"|| 116 - s.visibility==="hidden"|| 117 - Number(s.opacity)===0 118 - ){ 119 - return false; 120 - } 121 - 107 + if(s.display==="none"||s.visibility==="hidden"||Number(s.opacity)===0)return false; 122 122 var r=el.getBoundingClientRect(); 123 - 124 - return ( 125 - r.width>=(minW||1)&& 126 - r.height>=(minH||1) 127 - ); 109 + return r.width>=MIN_W&&r.height>=MIN_H; 128 128 } 129 129 130 130 function excluded(el){ 131 - return ( 132 - !el.matches|| 133 - el.matches( 134 - "button,input,select,textarea,option,label,img,svg,canvas,table,thead,tbody,tfoot,tr,td,th,summary,script,style,noscript,template,.btn,.chip,[role=button]" 135 - ) 113 + return !el.matches||el.matches( 114 + "button,input,select,textarea,option,label,img,svg,canvas,table,thead,tbody,tfoot,tr,td,th,summary,script,style,noscript,template,.btn,.chip,[role=button]" 136 136 ); 137 137 } 138 138 139 139 function namedLikeBox(el){ 140 - var c= 141 - typeof el.className==="string" 142 - ? el.className 143 - : ""; 144 - 145 - return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c); 119 + var c=typeof el.className==="string"?el.className:""; 120 + return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 146 146 } 147 147 148 148 function boxLike(el){ 149 - if(!visible(el,MIN_W,MIN_H)||excluded(el))return false; 150 - 124 + if(!visible(el)||excluded(el))return false; 151 151 var s=getComputedStyle(el); 152 152 var r=el.getBoundingClientRect(); 153 - 154 154 var border= 155 - num(s.borderTopWidth)+ 156 - num(s.borderRightWidth)+ 157 - num(s.borderBottomWidth)+ 158 - num(s.borderLeftWidth); 159 - 128 + num(s.borderTopWidth)+num(s.borderRightWidth)+ 129 + num(s.borderBottomWidth)+num(s.borderLeftWidth); 160 160 var radius=Math.max( 161 - num(s.borderTopLeftRadius), 162 - num(s.borderTopRightRadius), 163 - num(s.borderBottomLeftRadius), 164 - num(s.borderBottomRightRadius) 131 + num(s.borderTopLeftRadius),num(s.borderTopRightRadius), 132 + num(s.borderBottomLeftRadius),num(s.borderBottomRightRadius) 165 165 ); 166 - 167 - var bg= 168 - s.backgroundColor&& 169 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 170 - s.backgroundColor!=="transparent"; 171 - 172 - var shadow= 173 - s.boxShadow&& 174 - s.boxShadow!=="none"; 175 - 176 - return ( 177 - namedLikeBox(el)|| 178 - border>=1|| 179 - (bg&&radius>=3)|| 180 - (shadow&&r.width>=180) 181 - ); 134 + var bg=s.backgroundColor&&s.backgroundColor!=="rgba(0, 0, 0, 0)"&&s.backgroundColor!=="transparent"; 135 + var shadow=s.boxShadow&&s.boxShadow!=="none"; 136 + return namedLikeBox(el)||border>=1||(bg&&radius>=3)||(shadow&&r.width>=180); 182 182 } 183 183 184 - function saveOriginal(el,map,property){ 185 - if(map.has(el))return; 186 - 187 - map.set(el,{ 188 - value:el.style.getPropertyValue(property), 189 - priority:el.style.getPropertyPriority(property) 190 - }); 191 - } 192 - 193 - function restoreOriginal(el,map,property){ 194 - var original=map.get(el); 195 - 196 - if(original&&original.value){ 197 - el.style.setProperty( 198 - property, 199 - original.value, 200 - original.priority||"" 201 - ); 202 - }else{ 203 - el.style.removeProperty(property); 204 - } 205 - } 206 - 207 - function reset(){ 208 - heightManaged.forEach(function(el){ 209 - restoreOriginal( 210 - el, 211 - originalMinHeight, 212 - "min-height" 213 - ); 214 - 215 - el.removeAttribute( 216 - "data-sn-equal-height-managed" 217 - ); 218 - }); 219 - 220 - sectionManaged.forEach(function(el){ 221 - restoreOriginal( 222 - el, 223 - originalMarginTop, 224 - "margin-top" 225 - ); 226 - 227 - el.removeAttribute( 228 - "data-sn-first-section-aligned" 229 - ); 230 - }); 231 - 232 - heightManaged.clear(); 233 - sectionManaged.clear(); 234 - } 235 - 236 236 function pickTarget(child){ 237 - if(!visible(child,MIN_W,MIN_H))return null; 140 + if(!visible(child))return null; 141 + if(boxLike(child))return child; 238 238 239 - if(boxLike(child)){ 240 - return child; 241 - } 242 - 243 243 var cr=child.getBoundingClientRect(); 244 244 var q=[]; 245 - 246 246 Array.from(child.children||[]).forEach(function(el){ 247 247 q.push({el:el,depth:1}); 248 248 }); 249 249 250 - var best=null; 251 - var bestScore=-Infinity; 149 + var best=null,bestScore=-1; 252 252 253 253 while(q.length){ 254 254 var item=q.shift(); 255 255 var el=item.el; 154 + if(!visible(el))continue; 256 256 257 - if(!visible(el,MIN_W,MIN_H))continue; 258 - 259 259 var r=el.getBoundingClientRect(); 260 260 261 - if( 262 - r.width>=cr.width*.68&& 263 - boxLike(el) 264 - ){ 265 - var widthFit= 266 - 1-Math.min( 267 - 1, 268 - Math.abs(cr.width-r.width)/ 269 - Math.max(1,cr.width) 270 - ); 271 - 272 - var topFit= 273 - 1-Math.min( 274 - 1, 275 - Math.abs(cr.top-r.top)/100 276 - ); 277 - 278 - var score= 279 - widthFit*6+ 280 - topFit*3+ 281 - Math.min(r.height,900)/450+ 282 - Math.min(r.width*r.height,900000)/900000; 283 - 158 + if(r.width>=cr.width*.72&&boxLike(el)){ 159 + var widthFit=1-Math.min(1,Math.abs(cr.width-r.width)/Math.max(1,cr.width)); 160 + var topFit=1-Math.min(1,Math.abs(cr.top-r.top)/80); 161 + var score=widthFit*5+topFit*2+Math.min(r.height,600)/600; 284 284 if(score>bestScore){ 285 285 best=el; 286 286 bestScore=score; ... ... @@ -287,12 +287,9 @@ 287 287 } 288 288 } 289 289 290 - if(item.depth< SEARCH_DEPTH){168 + if(item.depth<3){ 291 291 Array.from(el.children||[]).forEach(function(next){ 292 - q.push({ 293 - el:next, 294 - depth:item.depth+1 295 - }); 170 + q.push({el:next,depth:item.depth+1}); 296 296 }); 297 297 } 298 298 } ... ... @@ -300,392 +300,61 @@ 300 300 return best; 301 301 } 302 302 303 - function groupsByVisualRow(entries){ 304 - var groups=[]; 305 - 306 - entries 307 - .slice() 308 - .sort(function(a,b){ 309 - return ( 310 - a.rect.top-b.rect.top|| 311 - a.rect.left-b.rect.left 312 - ); 313 - }) 314 - .forEach(function(entry){ 315 - var group=null; 316 - 317 - for(var i=0;i<groups.length;i++){ 318 - if( 319 - Math.abs( 320 - groups[i].top- 321 - entry.rect.top 322 - )<=ROW_TOLERANCE 323 - ){ 324 - group=groups[i]; 325 - break; 326 - } 327 - } 328 - 329 - if(!group){ 330 - group={ 331 - top:entry.rect.top, 332 - entries:[] 333 - }; 334 - groups.push(group); 335 - } 336 - 337 - group.entries.push(entry); 338 - }); 339 - 340 - return groups; 178 + function reset(){ 179 + managed.forEach(function(el){ 180 + el.style.removeProperty("min-height"); 181 + el.removeAttribute("data-sn-equal-height-managed"); 182 + }); 183 + managed.clear(); 341 341 } 342 342 343 - function validHorizontalGroup(group){ 344 - if(group.entries.length<2)return false; 345 - 346 - var lefts= 347 - group.entries 348 - .map(function(e){return e.rect.left;}) 349 - .sort(function(a,b){return a-b;}); 350 - 351 - if( 352 - lefts[lefts.length-1]- 353 - lefts[0]< 354 - 80 355 - ){ 356 - return false; 186 + function horizontalLayout(parent){ 187 + if(!visible(parent))return false; 188 + var s=getComputedStyle(parent); 189 + if(s.display==="grid"||s.display==="inline-grid")return true; 190 + if(s.display==="flex"||s.display==="inline-flex"){ 191 + return s.flexDirection==="row"||s.flexDirection==="row-reverse"; 357 357 } 358 - 359 - var widths= 360 - group.entries 361 - .map(function(e){return e.rect.width;}) 362 - .filter(function(w){return w>0;}); 363 - 364 - if(widths.length<2)return false; 365 - 366 - var minWidth=Math.min.apply(Math,widths); 367 - var maxWidth=Math.max.apply(Math,widths); 368 - 369 - return ( 370 - maxWidth/ 371 - Math.max(1,minWidth)<= 372 - 1.9 373 - ); 193 + return false; 374 374 } 375 375 376 - function normalizeText(text){ 377 - return String(text||"") 378 - .replace(/s+/g," ") 379 - .trim() 380 - .toUpperCase(); 381 - } 382 - 383 - function exactKnownFirstSection(el){ 384 - var text=normalizeText(el.textContent); 385 - 386 - return ( 387 - text==="HIER STARTEN"|| 388 - text==="ORGANISIEREN & DOKUMENTIEREN"|| 389 - text==="ENTSCHEIDEN"|| 390 - text==="START HERE"|| 391 - text==="GET STARTED"|| 392 - text==="ORGANISE & DOCUMENT"|| 393 - text==="ORGANIZE & DOCUMENT"|| 394 - text==="DECIDE" 395 - ); 396 - } 397 - 398 - function visuallyFirstSectionBar(card){ 399 - var cardRect=card.getBoundingClientRect(); 400 - var candidates=[]; 401 - 402 - Array.from( 403 - card.querySelectorAll( 404 - "div,p,span,strong,h3,h4,h5,h6" 405 - ) 406 - ).forEach(function(el){ 407 - if(!visible(el,20,6))return; 408 - if(excluded(el))return; 409 - 410 - var r=el.getBoundingClientRect(); 411 - var relativeTop=r.top-cardRect.top; 412 - 413 - if( 414 - relativeTop<45|| 415 - relativeTop>cardRect.height*.72 416 - ){ 417 - return; 196 + function rowGroups(entries){ 197 + var groups=[]; 198 + entries.slice().sort(function(a,b){ 199 + return a.rect.top-b.rect.top||a.rect.left-b.rect.left; 200 + }).forEach(function(entry){ 201 + var group=null; 202 + for(var i=0;i<groups.length;i++){ 203 + if(Math.abs(groups[i].top-entry.rect.top)<=ROW_TOLERANCE){ 204 + group=groups[i]; 205 + break; 206 + } 418 418 } 419 - 420 - var widthRatio= 421 - r.width/ 422 - Math.max(1,cardRect.width); 423 - 424 - if( 425 - widthRatio<.55|| 426 - widthRatio>1.05|| 427 - r.height>54 428 - ){ 429 - return; 208 + if(!group){ 209 + group={top:entry.rect.top,entries:[]}; 210 + groups.push(group); 430 430 } 431 - 432 - var text=normalizeText(el.textContent); 433 - 434 - if( 435 - text.length<2|| 436 - text.length>90 437 - ){ 438 - return; 439 - } 440 - 441 - var style=getComputedStyle(el); 442 - 443 - var bg= 444 - style.backgroundColor&& 445 - style.backgroundColor!=="rgba(0, 0, 0, 0)"&& 446 - style.backgroundColor!=="transparent"; 447 - 448 - var border= 449 - num(style.borderTopWidth)+ 450 - num(style.borderRightWidth)+ 451 - num(style.borderBottomWidth)+ 452 - num(style.borderLeftWidth); 453 - 454 - var mostlyUpper= 455 - text.length>=3&& 456 - text===text.toUpperCase(); 457 - 458 - var exact=exactKnownFirstSection(el); 459 - 460 - var score= 461 - (exact?20:0)+ 462 - (bg?6:0)+ 463 - (border>=1?2:0)+ 464 - (mostlyUpper?4:0)+ 465 - (num(style.fontWeight)>=600?1:0); 466 - 467 - if(score>=7){ 468 - candidates.push({ 469 - el:el, 470 - relativeTop:relativeTop, 471 - width:r.width, 472 - score:score 473 - }); 474 - } 212 + group.entries.push(entry); 475 475 }); 476 - 477 - if(!candidates.length)return null; 478 - 479 - candidates.sort(function(a,b){ 480 - if(a.score!==b.score)return b.score-a.score; 481 - if(Math.abs(a.relativeTop-b.relativeTop)>3){ 482 - return a.relativeTop-b.relativeTop; 483 - } 484 - return b.width-a.width; 485 - }); 486 - 487 - // For exact known labels always prefer the earliest exact match. 488 - var exacts=candidates.filter(function(c){ 489 - return exactKnownFirstSection(c.el); 490 - }); 491 - 492 - if(exacts.length){ 493 - exacts.sort(function(a,b){ 494 - return a.relativeTop-b.relativeTop||b.width-a.width; 495 - }); 496 - return exacts[0].el; 497 - } 498 - 499 - // Generic fallback: earliest high-confidence bar. 500 - candidates.sort(function(a,b){ 501 - return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width; 502 - }); 503 - 504 - return candidates[0].el; 214 + return groups; 505 505 } 506 506 507 - function alignFirstSections(cards){ 508 - var rows= 509 - cards.map(function(card){ 510 - var bar= 511 - visuallyFirstSectionBar(card); 512 - 513 - if(!bar)return null; 514 - 515 - var cardRect= 516 - card.getBoundingClientRect(); 517 - 518 - var barRect= 519 - bar.getBoundingClientRect(); 520 - 521 - return { 522 - card:card, 523 - bar:bar, 524 - relativeTop: 525 - barRect.top-cardRect.top, 526 - label: 527 - normalizeText(bar.textContent) 528 - }; 529 - }); 530 - 531 - // Conservative: only align when every card in the horizontal row 532 - // has a reliable first section bar. 533 - if( 534 - rows.some(function(row){ 535 - return !row; 536 - }) 537 - ){ 538 - return null; 539 - } 540 - 541 - var targetTop= 542 - Math.max.apply( 543 - Math, 544 - rows.map(function(row){ 545 - return row.relativeTop; 546 - }) 547 - ); 548 - 549 - rows.forEach(function(row){ 550 - var delta= 551 - targetTop- 552 - row.relativeTop; 553 - 554 - if(delta<=1)return; 555 - 556 - saveOriginal( 557 - row.bar, 558 - originalMarginTop, 559 - "margin-top" 560 - ); 561 - 562 - var currentMargin= 563 - num( 564 - getComputedStyle( 565 - row.bar 566 - ).marginTop 567 - ); 568 - 569 - row.bar.style.setProperty( 570 - "margin-top", 571 - ( 572 - currentMargin+ 573 - delta 574 - )+"px" 575 - ); 576 - 577 - row.bar.setAttribute( 578 - "data-sn-first-section-aligned", 579 - "4" 580 - ); 581 - 582 - sectionManaged.add(row.bar); 583 - }); 584 - 585 - return { 586 - labels: 587 - rows.map(function(row){ 588 - return row.label; 589 - }), 590 - targetRelativeTop: 591 - Math.round(targetTop) 592 - }; 593 - } 594 - 595 - function applyGroup(group){ 596 - if(!validHorizontalGroup(group)){ 597 - return null; 598 - } 599 - 600 - var cards=[]; 601 - var seen=new Set(); 602 - 603 - group.entries.forEach(function(entry){ 604 - if(!seen.has(entry.target)){ 605 - seen.add(entry.target); 606 - cards.push(entry.target); 607 - } 608 - }); 609 - 610 - if(cards.length<2)return null; 611 - 612 - var firstSection= 613 - alignFirstSections(cards); 614 - 615 - // The section alignment can change natural card heights. 616 - // Measure only afterwards. 617 - var maxHeight=0; 618 - 619 - cards.forEach(function(card){ 620 - maxHeight=Math.max( 621 - maxHeight, 622 - card.getBoundingClientRect().height 623 - ); 624 - }); 625 - 626 - maxHeight=Math.ceil(maxHeight); 627 - 628 - if(maxHeight<MIN_H)return null; 629 - 630 - cards.forEach(function(card){ 631 - saveOriginal( 632 - card, 633 - originalMinHeight, 634 - "min-height" 635 - ); 636 - 637 - card.style.setProperty( 638 - "min-height", 639 - maxHeight+"px" 640 - ); 641 - 642 - card.setAttribute( 643 - "data-sn-equal-height-managed", 644 - "4" 645 - ); 646 - 647 - heightManaged.add(card); 648 - }); 649 - 650 - return { 651 - cards:cards.length, 652 - height:maxHeight, 653 - firstSection:firstSection 654 - }; 655 - } 656 - 657 657 function run(){ 658 658 reset(); 659 659 660 - if( 661 - window.innerWidth<=MOBILE_MAX 662 - ){ 663 - return; 664 - } 220 + if(window.innerWidth<=MOBILE_MAX)return; 665 665 666 - var parents= 667 - Array.from( 668 - root.querySelectorAll("*") 669 - ).filter(function(parent){ 670 - return ( 671 - visible(parent,MIN_W,MIN_H)&& 672 - parent.children&& 673 - parent.children.length>=2&& 674 - parent.children.length<=MAX_PARENT_CHILDREN 675 - ); 676 - }); 222 + var parents=Array.from(root.querySelectorAll("*")).filter(function(el){ 223 + return el.children&&el.children.length>=2&&horizontalLayout(el); 224 + }); 677 677 678 - var touched=new Set(); 679 - 680 680 parents.forEach(function(parent){ 681 681 var entries=[]; 682 682 683 683 Array.from(parent.children).forEach(function(child){ 684 - if(!visible(child,MIN_W,MIN_H))return; 685 - 230 + if(!visible(child))return; 686 686 var target=pickTarget(child); 687 687 if(!target)return; 688 - 689 689 entries.push({ 690 690 target:target, 691 691 rect:target.getBoundingClientRect() ... ... @@ -694,30 +694,37 @@ 694 694 695 695 if(entries.length<2)return; 696 696 697 - groupsByVisualRow(entries).forEach(function(group){698 - if( !validHorizontalGroup(group))return;241 + rowGroups(entries).forEach(function(group){ 242 + if(group.entries.length<2)return; 699 699 700 - var signature= 701 - group.entries.map(function(entry){ 702 - return entry.target; 703 - }); 244 + var lefts=group.entries.map(function(e){return e.rect.left;}).sort(function(a,b){return a-b;}); 245 + if(lefts[lefts.length-1]-lefts[0]<80)return; 704 704 705 - if( 706 - !signature.some(function(el){ 707 - return !touched.has(el); 708 - }) 709 - ){ 710 - return; 711 - } 247 + var targets=[]; 248 + var seen=new Set(); 712 712 713 - var applied= 714 - applyGroup(group); 250 + group.entries.forEach(function(e){ 251 + if(!seen.has(e.target)){ 252 + seen.add(e.target); 253 + targets.push(e.target); 254 + } 255 + }); 715 715 716 - if(applied){ 717 - signature.forEach(function(el){ 718 - touched.add(el); 719 - }); 720 - } 257 + if(targets.length<2)return; 258 + 259 + var max=0; 260 + targets.forEach(function(el){ 261 + max=Math.max(max,el.getBoundingClientRect().height); 262 + }); 263 + 264 + max=Math.ceil(max); 265 + if(max<MIN_H)return; 266 + 267 + targets.forEach(function(el){ 268 + el.style.setProperty("min-height",max+"px"); 269 + el.setAttribute("data-sn-equal-height-managed","1"); 270 + managed.add(el); 271 + }); 721 721 }); 722 722 }); 723 723 } ... ... @@ -724,7 +724,6 @@ 724 724 725 725 function schedule(){ 726 726 if(raf)cancelAnimationFrame(raf); 727 - 728 728 raf=requestAnimationFrame(function(){ 729 729 raf=requestAnimationFrame(function(){ 730 730 raf=0; ... ... @@ -736,28 +736,17 @@ 736 736 addEventListener("resize",schedule,{passive:true}); 737 737 addEventListener("load",schedule,{once:true}); 738 738 739 - root.addEventListener( 740 - "click", 741 - function(){ 742 - setTimeout(schedule,0); 743 - }, 744 - true 745 - ); 289 + root.addEventListener("click",function(){ 290 + setTimeout(schedule,0); 291 + },true); 746 746 747 - Array.from(root.querySelectorAll("img")).forEach(function(img){ 748 - if(!img.complete){ 749 - img.addEventListener("load",schedule,{once:true}); 750 - } 751 - }); 752 - 753 753 if(document.fonts&&document.fonts.ready){ 754 754 document.fonts.ready.then(schedule); 755 755 } 756 756 757 757 schedule(); 758 - setTimeout(schedule,200); 759 - setTimeout(schedule,650); 760 - setTimeout(schedule,1400); 298 + setTimeout(schedule,250); 299 + setTimeout(schedule,900); 761 761 })(); 762 762 </script> 763 763 <!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->