Änderungen von Dokument Get Started
Zuletzt geändert von Veronika Kocher am Freitag, 04 Sep. 2026 14:45
Von Version 2.5
bearbeitet von Veronika Kocher
am Donnerstag, 03 Sep. 2026 9:18
am Donnerstag, 03 Sep. 2026 9:18
Änderungskommentar:
Es gibt keinen Kommentar für diese Version
Auf Version 2.6
bearbeitet von Veronika Kocher
am Donnerstag, 03 Sep. 2026 9:34
am Donnerstag, 03 Sep. 2026 9:34
Änderungskommentar:
Es gibt keinen Kommentar für diese Version
Zusammenfassung
-
Seiteneigenschaften (1 geändert, 0 hinzugefügt, 0 gelöscht)
Details
- Seiteneigenschaften
-
- Inhalt
-
... ... @@ -389,20 +389,22 @@ 389 389 390 390 {{html clean="false"}} 391 391 <!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 392 -<style data-sn-horizontal-box-harmonizer=" 1">393 -[data-sn-equal-height-managed ="1"]{box-sizing:border-box}394 - @media(max-width:767px){395 - [data-sn-equal-height-managed="1"]{min-height:0!important}392 +<style data-sn-horizontal-box-harmonizer="4"> 393 +[data-sn-equal-height-managed], 394 +[data-sn-first-section-aligned]{ 395 + box-sizing:border-box; 396 396 } 397 397 </style> 398 -<script data-sn-horizontal-box-harmonizer=" 1">398 +<script data-sn-horizontal-box-harmonizer="4"> 399 399 (function(){ 400 400 "use strict"; 401 401 402 402 var MOBILE_MAX=767; 403 - var ROW_TOLERANCE= 4;403 + var ROW_TOLERANCE=6; 404 404 var MIN_W=150; 405 405 var MIN_H=36; 406 + var MAX_PARENT_CHILDREN=16; 407 + var SEARCH_DEPTH=5; 406 406 407 407 var root= 408 408 document.getElementById("xwikicontent")|| ... ... @@ -412,7 +412,10 @@ 412 412 413 413 if(!root)return; 414 414 415 - var managed=new Set(); 417 + var heightManaged=new Set(); 418 + var sectionManaged=new Set(); 419 + var originalMinHeight=new WeakMap(); 420 + var originalMarginTop=new WeakMap(); 416 416 var raf=0; 417 417 418 418 function num(v){ ... ... @@ -420,64 +420,181 @@ 420 420 return Number.isFinite(n)?n:0; 421 421 } 422 422 423 - function visible(el){ 428 + function visible(el,minW,minH){ 424 424 if(!el||el.nodeType!==1)return false; 430 + 425 425 var s=getComputedStyle(el); 426 - if(s.display==="none"||s.visibility==="hidden"||Number(s.opacity)===0)return false; 432 + 433 + if( 434 + s.display==="none"|| 435 + s.visibility==="hidden"|| 436 + Number(s.opacity)===0 437 + ){ 438 + return false; 439 + } 440 + 427 427 var r=el.getBoundingClientRect(); 428 - return r.width>=MIN_W&&r.height>=MIN_H; 442 + 443 + return ( 444 + r.width>=(minW||1)&& 445 + r.height>=(minH||1) 446 + ); 429 429 } 430 430 431 431 function excluded(el){ 432 - return !el.matches||el.matches( 433 - "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]" 450 + return ( 451 + !el.matches|| 452 + el.matches( 453 + "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]" 454 + ) 434 434 ); 435 435 } 436 436 437 437 function namedLikeBox(el){ 438 - var c=typeof el.className==="string"?el.className:""; 439 - return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 459 + var c= 460 + typeof el.className==="string" 461 + ? el.className 462 + : ""; 463 + 464 + return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c); 440 440 } 441 441 442 442 function boxLike(el){ 443 - if(!visible(el)||excluded(el))return false; 468 + if(!visible(el,MIN_W,MIN_H)||excluded(el))return false; 469 + 444 444 var s=getComputedStyle(el); 445 445 var r=el.getBoundingClientRect(); 472 + 446 446 var border= 447 - num(s.borderTopWidth)+num(s.borderRightWidth)+ 448 - num(s.borderBottomWidth)+num(s.borderLeftWidth); 474 + num(s.borderTopWidth)+ 475 + num(s.borderRightWidth)+ 476 + num(s.borderBottomWidth)+ 477 + num(s.borderLeftWidth); 478 + 449 449 var radius=Math.max( 450 - num(s.borderTopLeftRadius),num(s.borderTopRightRadius), 451 - num(s.borderBottomLeftRadius),num(s.borderBottomRightRadius) 480 + num(s.borderTopLeftRadius), 481 + num(s.borderTopRightRadius), 482 + num(s.borderBottomLeftRadius), 483 + num(s.borderBottomRightRadius) 452 452 ); 453 - var bg=s.backgroundColor&&s.backgroundColor!=="rgba(0, 0, 0, 0)"&&s.backgroundColor!=="transparent"; 454 - var shadow=s.boxShadow&&s.boxShadow!=="none"; 455 - return namedLikeBox(el)||border>=1||(bg&&radius>=3)||(shadow&&r.width>=180); 485 + 486 + var bg= 487 + s.backgroundColor&& 488 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 489 + s.backgroundColor!=="transparent"; 490 + 491 + var shadow= 492 + s.boxShadow&& 493 + s.boxShadow!=="none"; 494 + 495 + return ( 496 + namedLikeBox(el)|| 497 + border>=1|| 498 + (bg&&radius>=3)|| 499 + (shadow&&r.width>=180) 500 + ); 456 456 } 457 457 503 + function saveOriginal(el,map,property){ 504 + if(map.has(el))return; 505 + 506 + map.set(el,{ 507 + value:el.style.getPropertyValue(property), 508 + priority:el.style.getPropertyPriority(property) 509 + }); 510 + } 511 + 512 + function restoreOriginal(el,map,property){ 513 + var original=map.get(el); 514 + 515 + if(original&&original.value){ 516 + el.style.setProperty( 517 + property, 518 + original.value, 519 + original.priority||"" 520 + ); 521 + }else{ 522 + el.style.removeProperty(property); 523 + } 524 + } 525 + 526 + function reset(){ 527 + heightManaged.forEach(function(el){ 528 + restoreOriginal( 529 + el, 530 + originalMinHeight, 531 + "min-height" 532 + ); 533 + 534 + el.removeAttribute( 535 + "data-sn-equal-height-managed" 536 + ); 537 + }); 538 + 539 + sectionManaged.forEach(function(el){ 540 + restoreOriginal( 541 + el, 542 + originalMarginTop, 543 + "margin-top" 544 + ); 545 + 546 + el.removeAttribute( 547 + "data-sn-first-section-aligned" 548 + ); 549 + }); 550 + 551 + heightManaged.clear(); 552 + sectionManaged.clear(); 553 + } 554 + 458 458 function pickTarget(child){ 459 - if(!visible(child))return null; 460 - if(boxLike(child))return child; 556 + if(!visible(child,MIN_W,MIN_H))return null; 461 461 558 + if(boxLike(child)){ 559 + return child; 560 + } 561 + 462 462 var cr=child.getBoundingClientRect(); 463 463 var q=[]; 564 + 464 464 Array.from(child.children||[]).forEach(function(el){ 465 465 q.push({el:el,depth:1}); 466 466 }); 467 467 468 - var best=null,bestScore=-1; 569 + var best=null; 570 + var bestScore=-Infinity; 469 469 470 470 while(q.length){ 471 471 var item=q.shift(); 472 472 var el=item.el; 473 - if(!visible(el))continue; 474 474 576 + if(!visible(el,MIN_W,MIN_H))continue; 577 + 475 475 var r=el.getBoundingClientRect(); 476 476 477 - if(r.width>=cr.width*.72&&boxLike(el)){ 478 - var widthFit=1-Math.min(1,Math.abs(cr.width-r.width)/Math.max(1,cr.width)); 479 - var topFit=1-Math.min(1,Math.abs(cr.top-r.top)/80); 480 - var score=widthFit*5+topFit*2+Math.min(r.height,600)/600; 580 + if( 581 + r.width>=cr.width*.68&& 582 + boxLike(el) 583 + ){ 584 + var widthFit= 585 + 1-Math.min( 586 + 1, 587 + Math.abs(cr.width-r.width)/ 588 + Math.max(1,cr.width) 589 + ); 590 + 591 + var topFit= 592 + 1-Math.min( 593 + 1, 594 + Math.abs(cr.top-r.top)/100 595 + ); 596 + 597 + var score= 598 + widthFit*6+ 599 + topFit*3+ 600 + Math.min(r.height,900)/450+ 601 + Math.min(r.width*r.height,900000)/900000; 602 + 481 481 if(score>bestScore){ 482 482 best=el; 483 483 bestScore=score; ... ... @@ -484,9 +484,12 @@ 484 484 } 485 485 } 486 486 487 - if(item.depth< 3){609 + if(item.depth<SEARCH_DEPTH){ 488 488 Array.from(el.children||[]).forEach(function(next){ 489 - q.push({el:next,depth:item.depth+1}); 611 + q.push({ 612 + el:next, 613 + depth:item.depth+1 614 + }); 490 490 }); 491 491 } 492 492 } ... ... @@ -494,61 +494,392 @@ 494 494 return best; 495 495 } 496 496 497 - function reset(){ 498 - managed.forEach(function(el){ 499 - el.style.removeProperty("min-height"); 500 - el.removeAttribute("data-sn-equal-height-managed"); 501 - }); 502 - managed.clear(); 622 + function groupsByVisualRow(entries){ 623 + var groups=[]; 624 + 625 + entries 626 + .slice() 627 + .sort(function(a,b){ 628 + return ( 629 + a.rect.top-b.rect.top|| 630 + a.rect.left-b.rect.left 631 + ); 632 + }) 633 + .forEach(function(entry){ 634 + var group=null; 635 + 636 + for(var i=0;i<groups.length;i++){ 637 + if( 638 + Math.abs( 639 + groups[i].top- 640 + entry.rect.top 641 + )<=ROW_TOLERANCE 642 + ){ 643 + group=groups[i]; 644 + break; 645 + } 646 + } 647 + 648 + if(!group){ 649 + group={ 650 + top:entry.rect.top, 651 + entries:[] 652 + }; 653 + groups.push(group); 654 + } 655 + 656 + group.entries.push(entry); 657 + }); 658 + 659 + return groups; 503 503 } 504 504 505 - function horizontalLayout(parent){ 506 - if(!visible(parent))return false; 507 - var s=getComputedStyle(parent); 508 - if(s.display==="grid"||s.display==="inline-grid")return true; 509 - if(s.display==="flex"||s.display==="inline-flex"){ 510 - return s.flexDirection==="row"||s.flexDirection==="row-reverse"; 662 + function validHorizontalGroup(group){ 663 + if(group.entries.length<2)return false; 664 + 665 + var lefts= 666 + group.entries 667 + .map(function(e){return e.rect.left;}) 668 + .sort(function(a,b){return a-b;}); 669 + 670 + if( 671 + lefts[lefts.length-1]- 672 + lefts[0]< 673 + 80 674 + ){ 675 + return false; 511 511 } 512 - return false; 677 + 678 + var widths= 679 + group.entries 680 + .map(function(e){return e.rect.width;}) 681 + .filter(function(w){return w>0;}); 682 + 683 + if(widths.length<2)return false; 684 + 685 + var minWidth=Math.min.apply(Math,widths); 686 + var maxWidth=Math.max.apply(Math,widths); 687 + 688 + return ( 689 + maxWidth/ 690 + Math.max(1,minWidth)<= 691 + 1.9 692 + ); 513 513 } 514 514 515 - function rowGroups(entries){ 516 - var groups=[]; 517 - entries.slice().sort(function(a,b){ 518 - return a.rect.top-b.rect.top||a.rect.left-b.rect.left; 519 - }).forEach(function(entry){ 520 - var group=null; 521 - for(var i=0;i<groups.length;i++){ 522 - if(Math.abs(groups[i].top-entry.rect.top)<=ROW_TOLERANCE){ 523 - group=groups[i]; 524 - break; 525 - } 695 + function normalizeText(text){ 696 + return String(text||"") 697 + .replace(/s+/g," ") 698 + .trim() 699 + .toUpperCase(); 700 + } 701 + 702 + function exactKnownFirstSection(el){ 703 + var text=normalizeText(el.textContent); 704 + 705 + return ( 706 + text==="HIER STARTEN"|| 707 + text==="ORGANISIEREN & DOKUMENTIEREN"|| 708 + text==="ENTSCHEIDEN"|| 709 + text==="START HERE"|| 710 + text==="GET STARTED"|| 711 + text==="ORGANISE & DOCUMENT"|| 712 + text==="ORGANIZE & DOCUMENT"|| 713 + text==="DECIDE" 714 + ); 715 + } 716 + 717 + function visuallyFirstSectionBar(card){ 718 + var cardRect=card.getBoundingClientRect(); 719 + var candidates=[]; 720 + 721 + Array.from( 722 + card.querySelectorAll( 723 + "div,p,span,strong,h3,h4,h5,h6" 724 + ) 725 + ).forEach(function(el){ 726 + if(!visible(el,20,6))return; 727 + if(excluded(el))return; 728 + 729 + var r=el.getBoundingClientRect(); 730 + var relativeTop=r.top-cardRect.top; 731 + 732 + if( 733 + relativeTop<45|| 734 + relativeTop>cardRect.height*.72 735 + ){ 736 + return; 526 526 } 527 - if(!group){ 528 - group={top:entry.rect.top,entries:[]}; 529 - groups.push(group); 738 + 739 + var widthRatio= 740 + r.width/ 741 + Math.max(1,cardRect.width); 742 + 743 + if( 744 + widthRatio<.55|| 745 + widthRatio>1.05|| 746 + r.height>54 747 + ){ 748 + return; 530 530 } 531 - group.entries.push(entry); 750 + 751 + var text=normalizeText(el.textContent); 752 + 753 + if( 754 + text.length<2|| 755 + text.length>90 756 + ){ 757 + return; 758 + } 759 + 760 + var style=getComputedStyle(el); 761 + 762 + var bg= 763 + style.backgroundColor&& 764 + style.backgroundColor!=="rgba(0, 0, 0, 0)"&& 765 + style.backgroundColor!=="transparent"; 766 + 767 + var border= 768 + num(style.borderTopWidth)+ 769 + num(style.borderRightWidth)+ 770 + num(style.borderBottomWidth)+ 771 + num(style.borderLeftWidth); 772 + 773 + var mostlyUpper= 774 + text.length>=3&& 775 + text===text.toUpperCase(); 776 + 777 + var exact=exactKnownFirstSection(el); 778 + 779 + var score= 780 + (exact?20:0)+ 781 + (bg?6:0)+ 782 + (border>=1?2:0)+ 783 + (mostlyUpper?4:0)+ 784 + (num(style.fontWeight)>=600?1:0); 785 + 786 + if(score>=7){ 787 + candidates.push({ 788 + el:el, 789 + relativeTop:relativeTop, 790 + width:r.width, 791 + score:score 792 + }); 793 + } 532 532 }); 533 - return groups; 795 + 796 + if(!candidates.length)return null; 797 + 798 + candidates.sort(function(a,b){ 799 + if(a.score!==b.score)return b.score-a.score; 800 + if(Math.abs(a.relativeTop-b.relativeTop)>3){ 801 + return a.relativeTop-b.relativeTop; 802 + } 803 + return b.width-a.width; 804 + }); 805 + 806 + // For exact known labels always prefer the earliest exact match. 807 + var exacts=candidates.filter(function(c){ 808 + return exactKnownFirstSection(c.el); 809 + }); 810 + 811 + if(exacts.length){ 812 + exacts.sort(function(a,b){ 813 + return a.relativeTop-b.relativeTop||b.width-a.width; 814 + }); 815 + return exacts[0].el; 816 + } 817 + 818 + // Generic fallback: earliest high-confidence bar. 819 + candidates.sort(function(a,b){ 820 + return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width; 821 + }); 822 + 823 + return candidates[0].el; 534 534 } 535 535 826 + function alignFirstSections(cards){ 827 + var rows= 828 + cards.map(function(card){ 829 + var bar= 830 + visuallyFirstSectionBar(card); 831 + 832 + if(!bar)return null; 833 + 834 + var cardRect= 835 + card.getBoundingClientRect(); 836 + 837 + var barRect= 838 + bar.getBoundingClientRect(); 839 + 840 + return { 841 + card:card, 842 + bar:bar, 843 + relativeTop: 844 + barRect.top-cardRect.top, 845 + label: 846 + normalizeText(bar.textContent) 847 + }; 848 + }); 849 + 850 + // Conservative: only align when every card in the horizontal row 851 + // has a reliable first section bar. 852 + if( 853 + rows.some(function(row){ 854 + return !row; 855 + }) 856 + ){ 857 + return null; 858 + } 859 + 860 + var targetTop= 861 + Math.max.apply( 862 + Math, 863 + rows.map(function(row){ 864 + return row.relativeTop; 865 + }) 866 + ); 867 + 868 + rows.forEach(function(row){ 869 + var delta= 870 + targetTop- 871 + row.relativeTop; 872 + 873 + if(delta<=1)return; 874 + 875 + saveOriginal( 876 + row.bar, 877 + originalMarginTop, 878 + "margin-top" 879 + ); 880 + 881 + var currentMargin= 882 + num( 883 + getComputedStyle( 884 + row.bar 885 + ).marginTop 886 + ); 887 + 888 + row.bar.style.setProperty( 889 + "margin-top", 890 + ( 891 + currentMargin+ 892 + delta 893 + )+"px" 894 + ); 895 + 896 + row.bar.setAttribute( 897 + "data-sn-first-section-aligned", 898 + "4" 899 + ); 900 + 901 + sectionManaged.add(row.bar); 902 + }); 903 + 904 + return { 905 + labels: 906 + rows.map(function(row){ 907 + return row.label; 908 + }), 909 + targetRelativeTop: 910 + Math.round(targetTop) 911 + }; 912 + } 913 + 914 + function applyGroup(group){ 915 + if(!validHorizontalGroup(group)){ 916 + return null; 917 + } 918 + 919 + var cards=[]; 920 + var seen=new Set(); 921 + 922 + group.entries.forEach(function(entry){ 923 + if(!seen.has(entry.target)){ 924 + seen.add(entry.target); 925 + cards.push(entry.target); 926 + } 927 + }); 928 + 929 + if(cards.length<2)return null; 930 + 931 + var firstSection= 932 + alignFirstSections(cards); 933 + 934 + // The section alignment can change natural card heights. 935 + // Measure only afterwards. 936 + var maxHeight=0; 937 + 938 + cards.forEach(function(card){ 939 + maxHeight=Math.max( 940 + maxHeight, 941 + card.getBoundingClientRect().height 942 + ); 943 + }); 944 + 945 + maxHeight=Math.ceil(maxHeight); 946 + 947 + if(maxHeight<MIN_H)return null; 948 + 949 + cards.forEach(function(card){ 950 + saveOriginal( 951 + card, 952 + originalMinHeight, 953 + "min-height" 954 + ); 955 + 956 + card.style.setProperty( 957 + "min-height", 958 + maxHeight+"px" 959 + ); 960 + 961 + card.setAttribute( 962 + "data-sn-equal-height-managed", 963 + "4" 964 + ); 965 + 966 + heightManaged.add(card); 967 + }); 968 + 969 + return { 970 + cards:cards.length, 971 + height:maxHeight, 972 + firstSection:firstSection 973 + }; 974 + } 975 + 536 536 function run(){ 537 537 reset(); 538 538 539 - if(window.innerWidth<=MOBILE_MAX)return; 979 + if( 980 + window.innerWidth<=MOBILE_MAX 981 + ){ 982 + return; 983 + } 540 540 541 - var parents=Array.from(root.querySelectorAll("*")).filter(function(el){ 542 - return el.children&&el.children.length>=2&&horizontalLayout(el); 543 - }); 985 + var parents= 986 + Array.from( 987 + root.querySelectorAll("*") 988 + ).filter(function(parent){ 989 + return ( 990 + visible(parent,MIN_W,MIN_H)&& 991 + parent.children&& 992 + parent.children.length>=2&& 993 + parent.children.length<=MAX_PARENT_CHILDREN 994 + ); 995 + }); 544 544 997 + var touched=new Set(); 998 + 545 545 parents.forEach(function(parent){ 546 546 var entries=[]; 547 547 548 548 Array.from(parent.children).forEach(function(child){ 549 - if(!visible(child))return; 1003 + if(!visible(child,MIN_W,MIN_H))return; 1004 + 550 550 var target=pickTarget(child); 551 551 if(!target)return; 1007 + 552 552 entries.push({ 553 553 target:target, 554 554 rect:target.getBoundingClientRect() ... ... @@ -557,37 +557,30 @@ 557 557 558 558 if(entries.length<2)return; 559 559 560 - ro wGroups(entries).forEach(function(group){561 - if( group.entries.length<2)return;1016 + groupsByVisualRow(entries).forEach(function(group){ 1017 + if(!validHorizontalGroup(group))return; 562 562 563 - var lefts=group.entries.map(function(e){return e.rect.left;}).sort(function(a,b){return a-b;}); 564 - if(lefts[lefts.length-1]-lefts[0]<80)return; 1019 + var signature= 1020 + group.entries.map(function(entry){ 1021 + return entry.target; 1022 + }); 565 565 566 - var targets=[]; 567 - var seen=new Set(); 1024 + if( 1025 + !signature.some(function(el){ 1026 + return !touched.has(el); 1027 + }) 1028 + ){ 1029 + return; 1030 + } 568 568 569 - group.entries.forEach(function(e){ 570 - if(!seen.has(e.target)){ 571 - seen.add(e.target); 572 - targets.push(e.target); 573 - } 574 - }); 1032 + var applied= 1033 + applyGroup(group); 575 575 576 - if(targets.length<2)return; 577 - 578 - var max=0; 579 - targets.forEach(function(el){ 580 - max=Math.max(max,el.getBoundingClientRect().height); 581 - }); 582 - 583 - max=Math.ceil(max); 584 - if(max<MIN_H)return; 585 - 586 - targets.forEach(function(el){ 587 - el.style.setProperty("min-height",max+"px"); 588 - el.setAttribute("data-sn-equal-height-managed","1"); 589 - managed.add(el); 590 - }); 1035 + if(applied){ 1036 + signature.forEach(function(el){ 1037 + touched.add(el); 1038 + }); 1039 + } 591 591 }); 592 592 }); 593 593 } ... ... @@ -594,6 +594,7 @@ 594 594 595 595 function schedule(){ 596 596 if(raf)cancelAnimationFrame(raf); 1046 + 597 597 raf=requestAnimationFrame(function(){ 598 598 raf=requestAnimationFrame(function(){ 599 599 raf=0; ... ... @@ -605,17 +605,28 @@ 605 605 addEventListener("resize",schedule,{passive:true}); 606 606 addEventListener("load",schedule,{once:true}); 607 607 608 - root.addEventListener("click",function(){ 609 - setTimeout(schedule,0); 610 - },true); 1058 + root.addEventListener( 1059 + "click", 1060 + function(){ 1061 + setTimeout(schedule,0); 1062 + }, 1063 + true 1064 + ); 611 611 1066 + Array.from(root.querySelectorAll("img")).forEach(function(img){ 1067 + if(!img.complete){ 1068 + img.addEventListener("load",schedule,{once:true}); 1069 + } 1070 + }); 1071 + 612 612 if(document.fonts&&document.fonts.ready){ 613 613 document.fonts.ready.then(schedule); 614 614 } 615 615 616 616 schedule(); 617 - setTimeout(schedule,250); 618 - setTimeout(schedule,900); 1077 + setTimeout(schedule,200); 1078 + setTimeout(schedule,650); 1079 + setTimeout(schedule,1400); 619 619 })(); 620 620 </script> 621 621 <!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->