Changes for page Prepare
Last modified by Veronika Kocher on Friday, 18 Sep 2026 16:47
From version 29.8
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 29.6
edited by Veronika Kocher
on Wednesday, 02 Sep 2026 16:48
on Wednesday, 02 Sep 2026 16:48
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -484,699 +484,3 @@ 484 484 485 485 </div> 486 486 {{/html}} 487 - 488 -{{html clean="false"}} 489 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 490 -<style data-sn-horizontal-box-harmonizer="4"> 491 -[data-sn-equal-height-managed], 492 -[data-sn-first-section-aligned]{ 493 - box-sizing:border-box; 494 -} 495 -</style> 496 -<script data-sn-horizontal-box-harmonizer="4"> 497 -(function(){ 498 - "use strict"; 499 - 500 - var MOBILE_MAX=767; 501 - var ROW_TOLERANCE=6; 502 - var MIN_W=150; 503 - var MIN_H=36; 504 - var MAX_PARENT_CHILDREN=16; 505 - var SEARCH_DEPTH=5; 506 - 507 - var root= 508 - document.getElementById("xwikicontent")|| 509 - document.querySelector(".xwiki-rendering-content")|| 510 - document.querySelector("main")|| 511 - document.body; 512 - 513 - if(!root)return; 514 - 515 - var heightManaged=new Set(); 516 - var sectionManaged=new Set(); 517 - var originalMinHeight=new WeakMap(); 518 - var originalMarginTop=new WeakMap(); 519 - var raf=0; 520 - 521 - function num(v){ 522 - var n=parseFloat(v); 523 - return Number.isFinite(n)?n:0; 524 - } 525 - 526 - function visible(el,minW,minH){ 527 - if(!el||el.nodeType!==1)return false; 528 - 529 - var s=getComputedStyle(el); 530 - 531 - if( 532 - s.display==="none"|| 533 - s.visibility==="hidden"|| 534 - Number(s.opacity)===0 535 - ){ 536 - return false; 537 - } 538 - 539 - var r=el.getBoundingClientRect(); 540 - 541 - return ( 542 - r.width>=(minW||1)&& 543 - r.height>=(minH||1) 544 - ); 545 - } 546 - 547 - function excluded(el){ 548 - return ( 549 - !el.matches|| 550 - el.matches( 551 - "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]" 552 - ) 553 - ); 554 - } 555 - 556 - function namedLikeBox(el){ 557 - var c= 558 - typeof el.className==="string" 559 - ? el.className 560 - : ""; 561 - 562 - return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c); 563 - } 564 - 565 - function boxLike(el){ 566 - if(!visible(el,MIN_W,MIN_H)||excluded(el))return false; 567 - 568 - var s=getComputedStyle(el); 569 - var r=el.getBoundingClientRect(); 570 - 571 - var border= 572 - num(s.borderTopWidth)+ 573 - num(s.borderRightWidth)+ 574 - num(s.borderBottomWidth)+ 575 - num(s.borderLeftWidth); 576 - 577 - var radius=Math.max( 578 - num(s.borderTopLeftRadius), 579 - num(s.borderTopRightRadius), 580 - num(s.borderBottomLeftRadius), 581 - num(s.borderBottomRightRadius) 582 - ); 583 - 584 - var bg= 585 - s.backgroundColor&& 586 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 587 - s.backgroundColor!=="transparent"; 588 - 589 - var shadow= 590 - s.boxShadow&& 591 - s.boxShadow!=="none"; 592 - 593 - return ( 594 - namedLikeBox(el)|| 595 - border>=1|| 596 - (bg&&radius>=3)|| 597 - (shadow&&r.width>=180) 598 - ); 599 - } 600 - 601 - function saveOriginal(el,map,property){ 602 - if(map.has(el))return; 603 - 604 - map.set(el,{ 605 - value:el.style.getPropertyValue(property), 606 - priority:el.style.getPropertyPriority(property) 607 - }); 608 - } 609 - 610 - function restoreOriginal(el,map,property){ 611 - var original=map.get(el); 612 - 613 - if(original&&original.value){ 614 - el.style.setProperty( 615 - property, 616 - original.value, 617 - original.priority||"" 618 - ); 619 - }else{ 620 - el.style.removeProperty(property); 621 - } 622 - } 623 - 624 - function reset(){ 625 - heightManaged.forEach(function(el){ 626 - restoreOriginal( 627 - el, 628 - originalMinHeight, 629 - "min-height" 630 - ); 631 - 632 - el.removeAttribute( 633 - "data-sn-equal-height-managed" 634 - ); 635 - }); 636 - 637 - sectionManaged.forEach(function(el){ 638 - restoreOriginal( 639 - el, 640 - originalMarginTop, 641 - "margin-top" 642 - ); 643 - 644 - el.removeAttribute( 645 - "data-sn-first-section-aligned" 646 - ); 647 - }); 648 - 649 - heightManaged.clear(); 650 - sectionManaged.clear(); 651 - } 652 - 653 - function pickTarget(child){ 654 - if(!visible(child,MIN_W,MIN_H))return null; 655 - 656 - if(boxLike(child)){ 657 - return child; 658 - } 659 - 660 - var cr=child.getBoundingClientRect(); 661 - var q=[]; 662 - 663 - Array.from(child.children||[]).forEach(function(el){ 664 - q.push({el:el,depth:1}); 665 - }); 666 - 667 - var best=null; 668 - var bestScore=-Infinity; 669 - 670 - while(q.length){ 671 - var item=q.shift(); 672 - var el=item.el; 673 - 674 - if(!visible(el,MIN_W,MIN_H))continue; 675 - 676 - var r=el.getBoundingClientRect(); 677 - 678 - if( 679 - r.width>=cr.width*.68&& 680 - boxLike(el) 681 - ){ 682 - var widthFit= 683 - 1-Math.min( 684 - 1, 685 - Math.abs(cr.width-r.width)/ 686 - Math.max(1,cr.width) 687 - ); 688 - 689 - var topFit= 690 - 1-Math.min( 691 - 1, 692 - Math.abs(cr.top-r.top)/100 693 - ); 694 - 695 - var score= 696 - widthFit*6+ 697 - topFit*3+ 698 - Math.min(r.height,900)/450+ 699 - Math.min(r.width*r.height,900000)/900000; 700 - 701 - if(score>bestScore){ 702 - best=el; 703 - bestScore=score; 704 - } 705 - } 706 - 707 - if(item.depth<SEARCH_DEPTH){ 708 - Array.from(el.children||[]).forEach(function(next){ 709 - q.push({ 710 - el:next, 711 - depth:item.depth+1 712 - }); 713 - }); 714 - } 715 - } 716 - 717 - return best; 718 - } 719 - 720 - function groupsByVisualRow(entries){ 721 - var groups=[]; 722 - 723 - entries 724 - .slice() 725 - .sort(function(a,b){ 726 - return ( 727 - a.rect.top-b.rect.top|| 728 - a.rect.left-b.rect.left 729 - ); 730 - }) 731 - .forEach(function(entry){ 732 - var group=null; 733 - 734 - for(var i=0;i<groups.length;i++){ 735 - if( 736 - Math.abs( 737 - groups[i].top- 738 - entry.rect.top 739 - )<=ROW_TOLERANCE 740 - ){ 741 - group=groups[i]; 742 - break; 743 - } 744 - } 745 - 746 - if(!group){ 747 - group={ 748 - top:entry.rect.top, 749 - entries:[] 750 - }; 751 - groups.push(group); 752 - } 753 - 754 - group.entries.push(entry); 755 - }); 756 - 757 - return groups; 758 - } 759 - 760 - function validHorizontalGroup(group){ 761 - if(group.entries.length<2)return false; 762 - 763 - var lefts= 764 - group.entries 765 - .map(function(e){return e.rect.left;}) 766 - .sort(function(a,b){return a-b;}); 767 - 768 - if( 769 - lefts[lefts.length-1]- 770 - lefts[0]< 771 - 80 772 - ){ 773 - return false; 774 - } 775 - 776 - var widths= 777 - group.entries 778 - .map(function(e){return e.rect.width;}) 779 - .filter(function(w){return w>0;}); 780 - 781 - if(widths.length<2)return false; 782 - 783 - var minWidth=Math.min.apply(Math,widths); 784 - var maxWidth=Math.max.apply(Math,widths); 785 - 786 - return ( 787 - maxWidth/ 788 - Math.max(1,minWidth)<= 789 - 1.9 790 - ); 791 - } 792 - 793 - function normalizeText(text){ 794 - return String(text||"") 795 - .replace(/s+/g," ") 796 - .trim() 797 - .toUpperCase(); 798 - } 799 - 800 - function exactKnownFirstSection(el){ 801 - var text=normalizeText(el.textContent); 802 - 803 - return ( 804 - text==="HIER STARTEN"|| 805 - text==="ORGANISIEREN & DOKUMENTIEREN"|| 806 - text==="ENTSCHEIDEN"|| 807 - text==="START HERE"|| 808 - text==="GET STARTED"|| 809 - text==="ORGANISE & DOCUMENT"|| 810 - text==="ORGANIZE & DOCUMENT"|| 811 - text==="DECIDE" 812 - ); 813 - } 814 - 815 - function visuallyFirstSectionBar(card){ 816 - var cardRect=card.getBoundingClientRect(); 817 - var candidates=[]; 818 - 819 - Array.from( 820 - card.querySelectorAll( 821 - "div,p,span,strong,h3,h4,h5,h6" 822 - ) 823 - ).forEach(function(el){ 824 - if(!visible(el,20,6))return; 825 - if(excluded(el))return; 826 - 827 - var r=el.getBoundingClientRect(); 828 - var relativeTop=r.top-cardRect.top; 829 - 830 - if( 831 - relativeTop<45|| 832 - relativeTop>cardRect.height*.72 833 - ){ 834 - return; 835 - } 836 - 837 - var widthRatio= 838 - r.width/ 839 - Math.max(1,cardRect.width); 840 - 841 - if( 842 - widthRatio<.55|| 843 - widthRatio>1.05|| 844 - r.height>54 845 - ){ 846 - return; 847 - } 848 - 849 - var text=normalizeText(el.textContent); 850 - 851 - if( 852 - text.length<2|| 853 - text.length>90 854 - ){ 855 - return; 856 - } 857 - 858 - var style=getComputedStyle(el); 859 - 860 - var bg= 861 - style.backgroundColor&& 862 - style.backgroundColor!=="rgba(0, 0, 0, 0)"&& 863 - style.backgroundColor!=="transparent"; 864 - 865 - var border= 866 - num(style.borderTopWidth)+ 867 - num(style.borderRightWidth)+ 868 - num(style.borderBottomWidth)+ 869 - num(style.borderLeftWidth); 870 - 871 - var mostlyUpper= 872 - text.length>=3&& 873 - text===text.toUpperCase(); 874 - 875 - var exact=exactKnownFirstSection(el); 876 - 877 - var score= 878 - (exact?20:0)+ 879 - (bg?6:0)+ 880 - (border>=1?2:0)+ 881 - (mostlyUpper?4:0)+ 882 - (num(style.fontWeight)>=600?1:0); 883 - 884 - if(score>=7){ 885 - candidates.push({ 886 - el:el, 887 - relativeTop:relativeTop, 888 - width:r.width, 889 - score:score 890 - }); 891 - } 892 - }); 893 - 894 - if(!candidates.length)return null; 895 - 896 - candidates.sort(function(a,b){ 897 - if(a.score!==b.score)return b.score-a.score; 898 - if(Math.abs(a.relativeTop-b.relativeTop)>3){ 899 - return a.relativeTop-b.relativeTop; 900 - } 901 - return b.width-a.width; 902 - }); 903 - 904 - // For exact known labels always prefer the earliest exact match. 905 - var exacts=candidates.filter(function(c){ 906 - return exactKnownFirstSection(c.el); 907 - }); 908 - 909 - if(exacts.length){ 910 - exacts.sort(function(a,b){ 911 - return a.relativeTop-b.relativeTop||b.width-a.width; 912 - }); 913 - return exacts[0].el; 914 - } 915 - 916 - // Generic fallback: earliest high-confidence bar. 917 - candidates.sort(function(a,b){ 918 - return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width; 919 - }); 920 - 921 - return candidates[0].el; 922 - } 923 - 924 - function alignFirstSections(cards){ 925 - var rows= 926 - cards.map(function(card){ 927 - var bar= 928 - visuallyFirstSectionBar(card); 929 - 930 - if(!bar)return null; 931 - 932 - var cardRect= 933 - card.getBoundingClientRect(); 934 - 935 - var barRect= 936 - bar.getBoundingClientRect(); 937 - 938 - return { 939 - card:card, 940 - bar:bar, 941 - relativeTop: 942 - barRect.top-cardRect.top, 943 - label: 944 - normalizeText(bar.textContent) 945 - }; 946 - }); 947 - 948 - // Conservative: only align when every card in the horizontal row 949 - // has a reliable first section bar. 950 - if( 951 - rows.some(function(row){ 952 - return !row; 953 - }) 954 - ){ 955 - return null; 956 - } 957 - 958 - var targetTop= 959 - Math.max.apply( 960 - Math, 961 - rows.map(function(row){ 962 - return row.relativeTop; 963 - }) 964 - ); 965 - 966 - rows.forEach(function(row){ 967 - var delta= 968 - targetTop- 969 - row.relativeTop; 970 - 971 - if(delta<=1)return; 972 - 973 - saveOriginal( 974 - row.bar, 975 - originalMarginTop, 976 - "margin-top" 977 - ); 978 - 979 - var currentMargin= 980 - num( 981 - getComputedStyle( 982 - row.bar 983 - ).marginTop 984 - ); 985 - 986 - row.bar.style.setProperty( 987 - "margin-top", 988 - ( 989 - currentMargin+ 990 - delta 991 - )+"px" 992 - ); 993 - 994 - row.bar.setAttribute( 995 - "data-sn-first-section-aligned", 996 - "4" 997 - ); 998 - 999 - sectionManaged.add(row.bar); 1000 - }); 1001 - 1002 - return { 1003 - labels: 1004 - rows.map(function(row){ 1005 - return row.label; 1006 - }), 1007 - targetRelativeTop: 1008 - Math.round(targetTop) 1009 - }; 1010 - } 1011 - 1012 - function applyGroup(group){ 1013 - if(!validHorizontalGroup(group)){ 1014 - return null; 1015 - } 1016 - 1017 - var cards=[]; 1018 - var seen=new Set(); 1019 - 1020 - group.entries.forEach(function(entry){ 1021 - if(!seen.has(entry.target)){ 1022 - seen.add(entry.target); 1023 - cards.push(entry.target); 1024 - } 1025 - }); 1026 - 1027 - if(cards.length<2)return null; 1028 - 1029 - var firstSection= 1030 - alignFirstSections(cards); 1031 - 1032 - // The section alignment can change natural card heights. 1033 - // Measure only afterwards. 1034 - var maxHeight=0; 1035 - 1036 - cards.forEach(function(card){ 1037 - maxHeight=Math.max( 1038 - maxHeight, 1039 - card.getBoundingClientRect().height 1040 - ); 1041 - }); 1042 - 1043 - maxHeight=Math.ceil(maxHeight); 1044 - 1045 - if(maxHeight<MIN_H)return null; 1046 - 1047 - cards.forEach(function(card){ 1048 - saveOriginal( 1049 - card, 1050 - originalMinHeight, 1051 - "min-height" 1052 - ); 1053 - 1054 - card.style.setProperty( 1055 - "min-height", 1056 - maxHeight+"px" 1057 - ); 1058 - 1059 - card.setAttribute( 1060 - "data-sn-equal-height-managed", 1061 - "4" 1062 - ); 1063 - 1064 - heightManaged.add(card); 1065 - }); 1066 - 1067 - return { 1068 - cards:cards.length, 1069 - height:maxHeight, 1070 - firstSection:firstSection 1071 - }; 1072 - } 1073 - 1074 - function run(){ 1075 - reset(); 1076 - 1077 - if( 1078 - window.innerWidth<=MOBILE_MAX 1079 - ){ 1080 - return; 1081 - } 1082 - 1083 - var parents= 1084 - Array.from( 1085 - root.querySelectorAll("*") 1086 - ).filter(function(parent){ 1087 - return ( 1088 - visible(parent,MIN_W,MIN_H)&& 1089 - parent.children&& 1090 - parent.children.length>=2&& 1091 - parent.children.length<=MAX_PARENT_CHILDREN 1092 - ); 1093 - }); 1094 - 1095 - var touched=new Set(); 1096 - 1097 - parents.forEach(function(parent){ 1098 - var entries=[]; 1099 - 1100 - Array.from(parent.children).forEach(function(child){ 1101 - if(!visible(child,MIN_W,MIN_H))return; 1102 - 1103 - var target=pickTarget(child); 1104 - if(!target)return; 1105 - 1106 - entries.push({ 1107 - target:target, 1108 - rect:target.getBoundingClientRect() 1109 - }); 1110 - }); 1111 - 1112 - if(entries.length<2)return; 1113 - 1114 - groupsByVisualRow(entries).forEach(function(group){ 1115 - if(!validHorizontalGroup(group))return; 1116 - 1117 - var signature= 1118 - group.entries.map(function(entry){ 1119 - return entry.target; 1120 - }); 1121 - 1122 - if( 1123 - !signature.some(function(el){ 1124 - return !touched.has(el); 1125 - }) 1126 - ){ 1127 - return; 1128 - } 1129 - 1130 - var applied= 1131 - applyGroup(group); 1132 - 1133 - if(applied){ 1134 - signature.forEach(function(el){ 1135 - touched.add(el); 1136 - }); 1137 - } 1138 - }); 1139 - }); 1140 - } 1141 - 1142 - function schedule(){ 1143 - if(raf)cancelAnimationFrame(raf); 1144 - 1145 - raf=requestAnimationFrame(function(){ 1146 - raf=requestAnimationFrame(function(){ 1147 - raf=0; 1148 - run(); 1149 - }); 1150 - }); 1151 - } 1152 - 1153 - addEventListener("resize",schedule,{passive:true}); 1154 - addEventListener("load",schedule,{once:true}); 1155 - 1156 - root.addEventListener( 1157 - "click", 1158 - function(){ 1159 - setTimeout(schedule,0); 1160 - }, 1161 - true 1162 - ); 1163 - 1164 - Array.from(root.querySelectorAll("img")).forEach(function(img){ 1165 - if(!img.complete){ 1166 - img.addEventListener("load",schedule,{once:true}); 1167 - } 1168 - }); 1169 - 1170 - if(document.fonts&&document.fonts.ready){ 1171 - document.fonts.ready.then(schedule); 1172 - } 1173 - 1174 - schedule(); 1175 - setTimeout(schedule,200); 1176 - setTimeout(schedule,650); 1177 - setTimeout(schedule,1400); 1178 -})(); 1179 -</script> 1180 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1181 -{{/html}} 1182 -