Änderungen von Dokument Art & Research Services Navigator
Zuletzt geändert von Veronika Kocher am Freitag, 18 Sep. 2026 16:47
Von Version 9.4
bearbeitet von Veronika Kocher
am Donnerstag, 03 Sep. 2026 10:09
am Donnerstag, 03 Sep. 2026 10:09
Änderungskommentar:
Es gibt keinen Kommentar für diese Version
Auf Version 9.3
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
-
... ... @@ -635,104 +635,15 @@ 635 635 {{/info}} 636 636 ))) 637 637 638 -\n\n 639 -\n\n{{html clean="false"}} 638 +{{html clean="false"}} 640 640 <!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 641 - 642 -<style data-sn-horizontal-box-harmonizer="7"> 643 -/* ---------- Typography: never justify headings ---------- */ 644 -#xwikicontent h1, 645 -#xwikicontent h2, 646 -#xwikicontent h3, 647 -#xwikicontent h4, 648 -#xwikicontent h5, 649 -#xwikicontent h6, 650 -#xwikicontent .box-title, 651 -#xwikicontent [role="heading"], 652 -#xwikicontent h1 a, 653 -#xwikicontent h2 a, 654 -#xwikicontent h3 a, 655 -#xwikicontent h4 a, 656 -#xwikicontent h5 a, 657 -#xwikicontent h6 a, 658 -#xwikicontent .box-title a, 659 -#xwikicontent [role="heading"] a{ 660 - text-align:left!important; 661 - text-justify:auto!important; 662 - word-spacing:normal!important; 663 -} 664 - 665 -/* ---------- Native XWiki semantic callouts ---------- */ 666 -#xwikicontent .box.infomessage, 667 -#xwikicontent .infomessage, 668 -#xwikicontent .box.warningmessage, 669 -#xwikicontent .warningmessage, 670 -#xwikicontent .box.successmessage, 671 -#xwikicontent .successmessage, 672 -#xwikicontent .box.errormessage, 673 -#xwikicontent .errormessage, 674 -#xwikicontent [data-sn-callout-harmonized="1"]{ 675 - box-sizing:border-box!important; 676 - border-radius:8px!important; 677 - border-top:1px solid rgba(0,0,0,.08)!important; 678 - border-right:1px solid rgba(0,0,0,.08)!important; 679 - border-bottom:1px solid rgba(0,0,0,.08)!important; 680 - border-left:4px solid var(--sn-callout-accent,#21b6d7)!important; 681 - padding:14px 16px!important; 682 - text-align:left!important; 683 - text-justify:auto!important; 684 - word-spacing:normal!important; 685 - box-shadow:none!important; 686 -} 687 - 688 -#xwikicontent .box.infomessage, 689 -#xwikicontent .infomessage{ 690 - --sn-callout-accent:#21b6d7; 691 - background:#eaf7fb!important; 692 -} 693 - 694 -#xwikicontent .box.warningmessage, 695 -#xwikicontent .warningmessage{ 696 - --sn-callout-accent:#f0aa00; 697 - background:#fff8e7!important; 698 -} 699 - 700 -#xwikicontent .box.successmessage, 701 -#xwikicontent .successmessage{ 702 - --sn-callout-accent:#38b76a; 703 - background:#edf9f1!important; 704 -} 705 - 706 -#xwikicontent .box.errormessage, 707 -#xwikicontent .errormessage{ 708 - --sn-callout-accent:#e94b13; 709 - background:#fff1ec!important; 710 -} 711 - 712 -#xwikicontent [data-sn-callout-harmonized="1"] > :first-child, 713 -#xwikicontent .infomessage > :first-child, 714 -#xwikicontent .warningmessage > :first-child, 715 -#xwikicontent .successmessage > :first-child, 716 -#xwikicontent .errormessage > :first-child{ 717 - margin-top:0!important; 718 -} 719 - 720 -#xwikicontent [data-sn-callout-harmonized="1"] > :last-child, 721 -#xwikicontent .infomessage > :last-child, 722 -#xwikicontent .warningmessage > :last-child, 723 -#xwikicontent .successmessage > :last-child, 724 -#xwikicontent .errormessage > :last-child{ 725 - margin-bottom:0!important; 726 -} 727 - 728 -#xwikicontent [data-sn-equal-height-managed], 729 -#xwikicontent [data-sn-first-section-aligned], 730 -#xwikicontent [data-sn-first-content-aligned]{ 640 +<style data-sn-horizontal-box-harmonizer="4"> 641 +[data-sn-equal-height-managed], 642 +[data-sn-first-section-aligned]{ 731 731 box-sizing:border-box; 732 732 } 733 733 </style> 734 - 735 -<script data-sn-horizontal-box-harmonizer="7"> 646 +<script data-sn-horizontal-box-harmonizer="4"> 736 736 (function(){ 737 737 "use strict"; 738 738 ... ... @@ -740,10 +740,8 @@ 740 740 var ROW_TOLERANCE=6; 741 741 var MIN_W=150; 742 742 var MIN_H=36; 743 - var MAX_PARENT_CHILDREN=1 8;654 + var MAX_PARENT_CHILDREN=16; 744 744 var SEARCH_DEPTH=5; 745 - var RESIZE_DEBOUNCE=220; 746 - var MIN_WIDTH_CHANGE=2; 747 747 748 748 var root= 749 749 document.getElementById("xwikicontent")|| ... ... @@ -755,16 +755,10 @@ 755 755 756 756 var heightManaged=new Set(); 757 757 var sectionManaged=new Set(); 758 - var contentManaged=new Set(); 759 - 760 760 var originalMinHeight=new WeakMap(); 761 761 var originalMarginTop=new WeakMap(); 669 + var raf=0; 762 762 763 - var resizeTimer=0; 764 - var lastWidth=-1; 765 - var hasApplied=false; 766 - var applying=false; 767 - 768 768 function num(v){ 769 769 var n=parseFloat(v); 770 770 return Number.isFinite(n)?n:0; ... ... @@ -791,13 +791,6 @@ 791 791 ); 792 792 } 793 793 794 - function normalizeText(text){ 795 - return String(text||"") 796 - .replace(/\s+/g," ") 797 - .trim() 798 - .toUpperCase(); 799 - } 800 - 801 801 function excluded(el){ 802 802 return ( 803 803 !el.matches|| ... ... @@ -807,84 +807,57 @@ 807 807 ); 808 808 } 809 809 810 - /* ---------- Custom coloured callouts ---------- */ 811 - 812 - function nativeCallout(el){ 706 + function namedLikeBox(el){ 813 813 var c= 814 814 typeof el.className==="string" 815 - ? el.className .toLowerCase()709 + ? el.className 816 816 : ""; 817 817 818 - return ( 819 - /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c) 820 - ); 712 + return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c); 821 821 } 822 822 823 - function customCallout(el){824 - if(!visible(el, 220,42)||excluded(el))return false;715 + function boxLike(el){ 716 + if(!visible(el,MIN_W,MIN_H)||excluded(el))return false; 825 825 718 + var s=getComputedStyle(el); 826 826 var r=el.getBoundingClientRect(); 827 827 828 - if(r.height>520)return false; 721 + var border= 722 + num(s.borderTopWidth)+ 723 + num(s.borderRightWidth)+ 724 + num(s.borderBottomWidth)+ 725 + num(s.borderLeftWidth); 829 829 830 - var s=getComputedStyle(el); 727 + var radius=Math.max( 728 + num(s.borderTopLeftRadius), 729 + num(s.borderTopRightRadius), 730 + num(s.borderBottomLeftRadius), 731 + num(s.borderBottomRightRadius) 732 + ); 831 831 832 832 var bg= 833 833 s.backgroundColor&& 834 834 s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 835 - s.backgroundColor!=="transparent"&& 836 - s.backgroundColor!=="rgb(255, 255, 255)"; 737 + s.backgroundColor!=="transparent"; 837 837 838 - var left= 839 - num(s.borderLeftWidth); 739 + var shadow= 740 + s.boxShadow&& 741 + s.boxShadow!=="none"; 840 840 841 841 return ( 842 - bg&& 843 - left>=2 744 + namedLikeBox(el)|| 745 + border>=1|| 746 + (bg&&radius>=3)|| 747 + (shadow&&r.width>=180) 844 844 ); 845 845 } 846 846 847 - function harmoniseCustomCallouts(){ 848 - Array.from( 849 - root.querySelectorAll( 850 - "div,aside,section" 851 - ) 852 - ).forEach(function(el){ 853 - if(nativeCallout(el))return; 854 - if(!customCallout(el))return; 855 - 856 - var s=getComputedStyle(el); 857 - 858 - el.setAttribute( 859 - "data-sn-callout-harmonized", 860 - "1" 861 - ); 862 - 863 - if( 864 - s.borderLeftColor 865 - ){ 866 - el.style.setProperty( 867 - "--sn-callout-accent", 868 - s.borderLeftColor 869 - ); 870 - } 871 - }); 872 - } 873 - 874 - /* ---------- Restore only values V7 itself changed ---------- */ 875 - 876 876 function saveOriginal(el,map,property){ 877 877 if(map.has(el))return; 878 878 879 879 map.set(el,{ 880 - value: 881 - el.style.getPropertyValue( 882 - property 883 - ), 884 - priority: 885 - el.style.getPropertyPriority( 886 - property 887 - ) 755 + value:el.style.getPropertyValue(property), 756 + priority:el.style.getPropertyPriority(property) 888 888 }); 889 889 } 890 890 ... ... @@ -898,13 +898,11 @@ 898 898 original.priority||"" 899 899 ); 900 900 }else{ 901 - el.style.removeProperty( 902 - property 903 - ); 770 + el.style.removeProperty(property); 904 904 } 905 905 } 906 906 907 - function reset Runtime(){774 + function reset(){ 908 908 heightManaged.forEach(function(el){ 909 909 restoreOriginal( 910 910 el, ... ... @@ -929,79 +929,16 @@ 929 929 ); 930 930 }); 931 931 932 - contentManaged.forEach(function(el){ 933 - restoreOriginal( 934 - el, 935 - originalMarginTop, 936 - "margin-top" 937 - ); 938 - 939 - el.removeAttribute( 940 - "data-sn-first-content-aligned" 941 - ); 942 - }); 943 - 944 944 heightManaged.clear(); 945 945 sectionManaged.clear(); 946 - contentManaged.clear(); 947 947 } 948 948 949 - /* ---------- Card detection ---------- */ 950 - 951 - function namedLikeBox(el){ 952 - var c= 953 - typeof el.className==="string" 954 - ? el.className 955 - : ""; 956 - 957 - return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 958 - } 959 - 960 - function boxLike(el){ 961 - if( 962 - !visible(el,MIN_W,MIN_H)|| 963 - excluded(el) 964 - ){ 965 - return false; 966 - } 967 - 968 - var s=getComputedStyle(el); 969 - var r=el.getBoundingClientRect(); 970 - 971 - var border= 972 - num(s.borderTopWidth)+ 973 - num(s.borderRightWidth)+ 974 - num(s.borderBottomWidth)+ 975 - num(s.borderLeftWidth); 976 - 977 - var radius=Math.max( 978 - num(s.borderTopLeftRadius), 979 - num(s.borderTopRightRadius), 980 - num(s.borderBottomLeftRadius), 981 - num(s.borderBottomRightRadius) 982 - ); 983 - 984 - var bg= 985 - s.backgroundColor&& 986 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 987 - s.backgroundColor!=="transparent"; 988 - 989 - var shadow= 990 - s.boxShadow&& 991 - s.boxShadow!=="none"; 992 - 993 - return ( 994 - namedLikeBox(el)|| 995 - border>=1|| 996 - (bg&&radius>=3)|| 997 - (shadow&&r.width>=180) 998 - ); 999 - } 1000 - 1001 1001 function pickTarget(child){ 1002 1002 if(!visible(child,MIN_W,MIN_H))return null; 1003 1003 1004 - if(boxLike(child))return child; 806 + if(boxLike(child)){ 807 + return child; 808 + } 1005 1005 1006 1006 var cr=child.getBoundingClientRect(); 1007 1007 var q=[]; ... ... @@ -1063,7 +1063,7 @@ 1063 1063 return best; 1064 1064 } 1065 1065 1066 - function groupRow s(entries){870 + function groupsByVisualRow(entries){ 1067 1067 var groups=[]; 1068 1068 1069 1069 entries ... ... @@ -1103,7 +1103,7 @@ 1103 1103 return groups; 1104 1104 } 1105 1105 1106 - function valid Row(group){910 + function validHorizontalGroup(group){ 1107 1107 if(group.entries.length<2)return false; 1108 1108 1109 1109 var lefts= ... ... @@ -1126,26 +1126,25 @@ 1126 1126 1127 1127 if(widths.length<2)return false; 1128 1128 1129 - var minW= 1130 - Math.min.apply(Math,widths);933 + var minWidth=Math.min.apply(Math,widths); 934 + var maxWidth=Math.max.apply(Math,widths); 1131 1131 1132 - var maxW= 1133 - Math.max.apply(Math,widths); 1134 - 1135 1135 return ( 1136 - maxW/ 1137 - Math.max(1,minW)<= 937 + maxWidth/ 938 + Math.max(1,minWidth)<= 1138 1138 1.9 1139 1139 ); 1140 1140 } 1141 1141 1142 - /* ---------- Known ARSN first section bars ---------- */ 943 + function normalizeText(text){ 944 + return String(text||"") 945 + .replace(/s+/g," ") 946 + .trim() 947 + .toUpperCase(); 948 + } 1143 1143 1144 - function knownBar(el){ 1145 - var text= 1146 - normalizeText( 1147 - el.textContent 1148 - ); 950 + function exactKnownFirstSection(el){ 951 + var text=normalizeText(el.textContent); 1149 1149 1150 1150 return ( 1151 1151 text==="HIER STARTEN"|| ... ... @@ -1159,274 +1159,150 @@ 1159 1159 ); 1160 1160 } 1161 1161 1162 - function findKnownBar(card){1163 - var cardRect= 1164 - card.getBoundingClientRect();965 + function visuallyFirstSectionBar(card){ 966 + var cardRect=card.getBoundingClientRect(); 967 + var candidates=[]; 1165 1165 1166 - var rows= 1167 - Array.from( 1168 - card.querySelectorAll( 1169 - "div,p,span,strong,h3,h4,h5,h6" 1170 - ) 969 + Array.from( 970 + card.querySelectorAll( 971 + "div,p,span,strong,h3,h4,h5,h6" 1171 1171 ) 1172 - .filter(function(el){1173 - if(!visible(el,20,6))returnfalse;1174 - if(!knownBar(el))returnfalse;973 + ).forEach(function(el){ 974 + if(!visible(el,20,6))return; 975 + if(excluded(el))return; 1175 1175 1176 - var r=el.getBoundingClientRect(); 977 + var r=el.getBoundingClientRect(); 978 + var relativeTop=r.top-cardRect.top; 1177 1177 1178 - var rel= 1179 - r.top- 1180 - cardRect.top; 980 + if( 981 + relativeTop<45|| 982 + relativeTop>cardRect.height*.72 983 + ){ 984 + return; 985 + } 1181 1181 1182 - return ( 1183 - rel>=35&& 1184 - rel<= 1185 - cardRect.height*.75 1186 - ); 1187 - }) 1188 - .sort(function(a,b){ 1189 - return ( 1190 - a.getBoundingClientRect().top- 1191 - b.getBoundingClientRect().top 1192 - ); 1193 - }); 987 + var widthRatio= 988 + r.width/ 989 + Math.max(1,cardRect.width); 1194 1194 1195 - return rows[0]||null; 1196 - } 991 + if( 992 + widthRatio<.55|| 993 + widthRatio>1.05|| 994 + r.height>54 995 + ){ 996 + return; 997 + } 1197 1197 1198 - function alignKnownBars(cards){ 1199 - var rows= 1200 - cards.map(function(card){ 1201 - var bar= 1202 - findKnownBar(card); 999 + var text=normalizeText(el.textContent); 1203 1203 1204 - if(!bar)return null; 1001 + if( 1002 + text.length<2|| 1003 + text.length>90 1004 + ){ 1005 + return; 1006 + } 1205 1205 1206 - var cr= 1207 - card.getBoundingClientRect(); 1008 + var style=getComputedStyle(el); 1208 1208 1209 - var br= 1210 - bar.getBoundingClientRect(); 1010 + var bg= 1011 + style.backgroundColor&& 1012 + style.backgroundColor!=="rgba(0, 0, 0, 0)"&& 1013 + style.backgroundColor!=="transparent"; 1211 1211 1212 - return { 1213 - bar:bar, 1214 - relativeTop: 1215 - br.top- 1216 - cr.top 1217 - }; 1218 - }); 1015 + var border= 1016 + num(style.borderTopWidth)+ 1017 + num(style.borderRightWidth)+ 1018 + num(style.borderBottomWidth)+ 1019 + num(style.borderLeftWidth); 1219 1219 1220 - if( 1221 - rows.some(function(row){ 1222 - return !row; 1223 - }) 1224 - ){ 1225 - return false; 1226 - } 1021 + var mostlyUpper= 1022 + text.length>=3&& 1023 + text===text.toUpperCase(); 1227 1227 1228 - var target= 1229 - Math.max.apply( 1230 - Math, 1231 - rows.map(function(row){ 1232 - return row.relativeTop; 1233 - }) 1234 - ); 1025 + var exact=exactKnownFirstSection(el); 1235 1235 1236 - rows.forEach(function(row){ 1237 - var delta= 1238 - target- 1239 - row.relativeTop; 1027 + var score= 1028 + (exact?20:0)+ 1029 + (bg?6:0)+ 1030 + (border>=1?2:0)+ 1031 + (mostlyUpper?4:0)+ 1032 + (num(style.fontWeight)>=600?1:0); 1240 1240 1241 - if(delta<=1)return; 1034 + if(score>=7){ 1035 + candidates.push({ 1036 + el:el, 1037 + relativeTop:relativeTop, 1038 + width:r.width, 1039 + score:score 1040 + }); 1041 + } 1042 + }); 1242 1242 1243 - saveOriginal( 1244 - row.bar, 1245 - originalMarginTop, 1246 - "margin-top" 1247 - ); 1044 + if(!candidates.length)return null; 1248 1248 1249 - var current= 1250 - num( 1251 - getComputedStyle( 1252 - row.bar 1253 - ).marginTop 1254 - ); 1046 + candidates.sort(function(a,b){ 1047 + if(a.score!==b.score)return b.score-a.score; 1048 + if(Math.abs(a.relativeTop-b.relativeTop)>3){ 1049 + return a.relativeTop-b.relativeTop; 1050 + } 1051 + return b.width-a.width; 1052 + }); 1255 1255 1256 - row.bar.style.setProperty( 1257 - "margin-top", 1258 - ( 1259 - current+ 1260 - delta 1261 - )+"px" 1262 - ); 1263 - 1264 - row.bar.setAttribute( 1265 - "data-sn-first-section-aligned", 1266 - "7" 1267 - ); 1268 - 1269 - sectionManaged.add( 1270 - row.bar 1271 - ); 1054 + // For exact known labels always prefer the earliest exact match. 1055 + var exacts=candidates.filter(function(c){ 1056 + return exactKnownFirstSection(c.el); 1272 1272 }); 1273 1273 1274 - return true; 1275 - } 1276 - 1277 - /* ---------- Generic first content after heading ---------- */ 1278 - 1279 - function heading(card){ 1280 - var cr= 1281 - card.getBoundingClientRect(); 1282 - 1283 - var rows= 1284 - Array.from( 1285 - card.querySelectorAll( 1286 - "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]" 1287 - ) 1288 - ) 1289 - .filter(function(el){ 1290 - if(!visible(el,20,8))return false; 1291 - 1292 - var r=el.getBoundingClientRect(); 1293 - 1294 - var rel= 1295 - r.top- 1296 - cr.top; 1297 - 1298 - return ( 1299 - rel>=0&& 1300 - rel<= 1301 - Math.min( 1302 - 160, 1303 - cr.height*.45 1304 - ) 1305 - ); 1306 - }) 1307 - .sort(function(a,b){ 1308 - return ( 1309 - a.getBoundingClientRect().top- 1310 - b.getBoundingClientRect().top 1311 - ); 1059 + if(exacts.length){ 1060 + exacts.sort(function(a,b){ 1061 + return a.relativeTop-b.relativeTop||b.width-a.width; 1312 1312 }); 1063 + return exacts[0].el; 1064 + } 1313 1313 1314 - return rows[0]||null; 1315 - } 1066 + // Generic fallback: earliest high-confidence bar. 1067 + candidates.sort(function(a,b){ 1068 + return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width; 1069 + }); 1316 1316 1317 - function firstContent(card,h){ 1318 - if(!h)return null; 1319 - 1320 - var cr= 1321 - card.getBoundingClientRect(); 1322 - 1323 - var hr= 1324 - h.getBoundingClientRect(); 1325 - 1326 - var rows= 1327 - Array.from( 1328 - card.querySelectorAll( 1329 - "p,div,ul,ol,dl,blockquote" 1330 - ) 1331 - ) 1332 - .filter(function(el){ 1333 - if( 1334 - el===h|| 1335 - h.contains(el)|| 1336 - el.contains(h) 1337 - ){ 1338 - return false; 1339 - } 1340 - 1341 - if(!visible(el,30,8))return false; 1342 - 1343 - var text= 1344 - String(el.textContent||"") 1345 - .replace(/\s+/g," ") 1346 - .trim(); 1347 - 1348 - if(text.length<3)return false; 1349 - 1350 - var r=el.getBoundingClientRect(); 1351 - 1352 - if( 1353 - r.top< 1354 - hr.bottom-1 1355 - ){ 1356 - return false; 1357 - } 1358 - 1359 - if( 1360 - r.top-cr.top> 1361 - Math.min( 1362 - 280, 1363 - cr.height*.65 1364 - ) 1365 - ){ 1366 - return false; 1367 - } 1368 - 1369 - if( 1370 - r.height> 1371 - cr.height*.58 1372 - ){ 1373 - return false; 1374 - } 1375 - 1376 - return true; 1377 - }) 1378 - .sort(function(a,b){ 1379 - var ar= 1380 - a.getBoundingClientRect(); 1381 - 1382 - var br= 1383 - b.getBoundingClientRect(); 1384 - 1385 - return ( 1386 - ar.top-br.top|| 1387 - ar.height-br.height 1388 - ); 1389 - }); 1390 - 1391 - return rows[0]||null; 1071 + return candidates[0].el; 1392 1392 } 1393 1393 1394 - function align Generic(cards){1074 + function alignFirstSections(cards){ 1395 1395 var rows= 1396 1396 cards.map(function(card){ 1397 - var h=1398 - heading(card);1077 + var bar= 1078 + visuallyFirstSectionBar(card); 1399 1399 1400 - var c= 1401 - firstContent( 1402 - card, 1403 - h 1404 - ); 1080 + if(!bar)return null; 1405 1405 1406 - if(!h||!c)return null; 1407 - 1408 - var cr= 1082 + var cardRect= 1409 1409 card.getBoundingClientRect(); 1410 1410 1411 - var r r=1412 - c.getBoundingClientRect();1085 + var barRect= 1086 + bar.getBoundingClientRect(); 1413 1413 1414 1414 return { 1415 - content:c, 1089 + card:card, 1090 + bar:bar, 1416 1416 relativeTop: 1417 - rr.top-cr.top 1092 + barRect.top-cardRect.top, 1093 + label: 1094 + normalizeText(bar.textContent) 1418 1418 }; 1419 1419 }); 1420 1420 1098 + // Conservative: only align when every card in the horizontal row 1099 + // has a reliable first section bar. 1421 1421 if( 1422 1422 rows.some(function(row){ 1423 1423 return !row; 1424 1424 }) 1425 1425 ){ 1426 - return false;1105 + return null; 1427 1427 } 1428 1428 1429 - var target= 1108 + var targetTop= 1430 1430 Math.max.apply( 1431 1431 Math, 1432 1432 rows.map(function(row){ ... ... @@ -1436,47 +1436,54 @@ 1436 1436 1437 1437 rows.forEach(function(row){ 1438 1438 var delta= 1439 - target- 1118 + targetTop- 1440 1440 row.relativeTop; 1441 1441 1442 1442 if(delta<=1)return; 1443 1443 1444 1444 saveOriginal( 1445 - row. content,1124 + row.bar, 1446 1446 originalMarginTop, 1447 1447 "margin-top" 1448 1448 ); 1449 1449 1450 - var current= 1129 + var currentMargin= 1451 1451 num( 1452 1452 getComputedStyle( 1453 - row. content1132 + row.bar 1454 1454 ).marginTop 1455 1455 ); 1456 1456 1457 - row. content.style.setProperty(1136 + row.bar.style.setProperty( 1458 1458 "margin-top", 1459 1459 ( 1460 - current+ 1139 + currentMargin+ 1461 1461 delta 1462 1462 )+"px" 1463 1463 ); 1464 1464 1465 - row. content.setAttribute(1466 - "data-sn-first-con tent-aligned",1467 - " 7"1144 + row.bar.setAttribute( 1145 + "data-sn-first-section-aligned", 1146 + "4" 1468 1468 ); 1469 1469 1470 - contentManaged.add( 1471 - row.content 1472 - ); 1149 + sectionManaged.add(row.bar); 1473 1473 }); 1474 1474 1475 - return true; 1152 + return { 1153 + labels: 1154 + rows.map(function(row){ 1155 + return row.label; 1156 + }), 1157 + targetRelativeTop: 1158 + Math.round(targetTop) 1159 + }; 1476 1476 } 1477 1477 1478 - function applyRow(group){ 1479 - if(!validRow(group))return false; 1162 + function applyGroup(group){ 1163 + if(!validHorizontalGroup(group)){ 1164 + return null; 1165 + } 1480 1480 1481 1481 var cards=[]; 1482 1482 var seen=new Set(); ... ... @@ -1488,30 +1488,25 @@ 1488 1488 } 1489 1489 }); 1490 1490 1491 - if(cards.length<2)return false;1177 + if(cards.length<2)return null; 1492 1492 1493 - if( 1494 - !alignKnownBars(cards) 1495 - ){ 1496 - alignGeneric(cards); 1497 - } 1179 + var firstSection= 1180 + alignFirstSections(cards); 1498 1498 1182 + // The section alignment can change natural card heights. 1183 + // Measure only afterwards. 1499 1499 var maxHeight=0; 1500 1500 1501 1501 cards.forEach(function(card){ 1502 - maxHeight= 1503 - Math.max( 1504 - maxHeight, 1505 - card.getBoundingClientRect().height 1506 - ); 1187 + maxHeight=Math.max( 1188 + maxHeight, 1189 + card.getBoundingClientRect().height 1190 + ); 1507 1507 }); 1508 1508 1509 - maxHeight= 1510 - Math.ceil( 1511 - maxHeight 1512 - ); 1193 + maxHeight=Math.ceil(maxHeight); 1513 1513 1514 - if(maxHeight<MIN_H)return false;1195 + if(maxHeight<MIN_H)return null; 1515 1515 1516 1516 cards.forEach(function(card){ 1517 1517 saveOriginal( ... ... @@ -1527,228 +1527,125 @@ 1527 1527 1528 1528 card.setAttribute( 1529 1529 "data-sn-equal-height-managed", 1530 - " 7"1211 + "4" 1531 1531 ); 1532 1532 1533 1533 heightManaged.add(card); 1534 1534 }); 1535 1535 1536 - return true; 1217 + return { 1218 + cards:cards.length, 1219 + height:maxHeight, 1220 + firstSection:firstSection 1221 + }; 1537 1537 } 1538 1538 1539 - function calculate(force){1540 - if(applying)return;1224 + function run(){ 1225 + reset(); 1541 1541 1542 - var width= 1543 - Math.round( 1544 - window.innerWidth 1545 - ); 1546 - 1547 - var meaningful= 1548 - lastWidth<0|| 1549 - Math.abs( 1550 - width- 1551 - lastWidth 1552 - )>= 1553 - MIN_WIDTH_CHANGE; 1554 - 1555 1555 if( 1556 - hasApplied&& 1557 - !force&& 1558 - !meaningful 1228 + window.innerWidth<=MOBILE_MAX 1559 1559 ){ 1560 1560 return; 1561 1561 } 1562 1562 1563 - applying=true; 1233 + var parents= 1234 + Array.from( 1235 + root.querySelectorAll("*") 1236 + ).filter(function(parent){ 1237 + return ( 1238 + visible(parent,MIN_W,MIN_H)&& 1239 + parent.children&& 1240 + parent.children.length>=2&& 1241 + parent.children.length<=MAX_PARENT_CHILDREN 1242 + ); 1243 + }); 1564 1564 1565 - try{ 1566 - harmoniseCustomCallouts(); 1245 + var touched=new Set(); 1567 1567 1568 - if(width<=MOBILE_MAX){ 1569 - if(hasApplied){ 1570 - resetRuntime(); 1571 - } 1247 + parents.forEach(function(parent){ 1248 + var entries=[]; 1572 1572 1573 - hasApplied=false; 1574 - lastWidth=width; 1575 - return; 1576 - } 1250 + Array.from(parent.children).forEach(function(child){ 1251 + if(!visible(child,MIN_W,MIN_H))return; 1577 1577 1578 - if(hasApplied){ 1579 - resetRuntime(); 1580 - } 1253 + var target=pickTarget(child); 1254 + if(!target)return; 1581 1581 1582 - var parents= 1583 - Array.from( 1584 - root.querySelectorAll("*") 1585 - ) 1586 - .filter(function(parent){ 1587 - return ( 1588 - visible( 1589 - parent, 1590 - MIN_W, 1591 - MIN_H 1592 - )&& 1593 - parent.children&& 1594 - parent.children.length>=2&& 1595 - parent.children.length<= 1596 - MAX_PARENT_CHILDREN 1597 - ); 1256 + entries.push({ 1257 + target:target, 1258 + rect:target.getBoundingClientRect() 1598 1598 }); 1260 + }); 1599 1599 1600 - var touched= 1601 - new Set(); 1262 + if(entries.length<2)return; 1602 1602 1603 - pa rents.forEach(function(parent){1604 - var entries=[];1264 + groupsByVisualRow(entries).forEach(function(group){ 1265 + if(!validHorizontalGroup(group))return; 1605 1605 1606 - Array.from( 1607 - parent.children 1608 - ).forEach(function(child){ 1609 - if( 1610 - !visible( 1611 - child, 1612 - MIN_W, 1613 - MIN_H 1614 - ) 1615 - ){ 1616 - return; 1617 - } 1618 - 1619 - var target= 1620 - pickTarget(child); 1621 - 1622 - if(!target)return; 1623 - 1624 - entries.push({ 1625 - target:target, 1626 - rect: 1627 - target.getBoundingClientRect() 1267 + var signature= 1268 + group.entries.map(function(entry){ 1269 + return entry.target; 1628 1628 }); 1629 - }); 1630 1630 1631 - groupRows( 1632 - entries 1633 - ).forEach(function(group){ 1634 - if(!validRow(group))return; 1272 + if( 1273 + !signature.some(function(el){ 1274 + return !touched.has(el); 1275 + }) 1276 + ){ 1277 + return; 1278 + } 1635 1635 1636 - var targets= 1637 - group.entries.map(function(entry){ 1638 - return entry.target; 1639 - }); 1280 + var applied= 1281 + applyGroup(group); 1640 1640 1641 - if( 1642 - !targets.some(function(el){ 1643 - return !touched.has(el); 1644 - }) 1645 - ){ 1646 - return; 1647 - } 1648 - 1649 - if(applyRow(group)){ 1650 - targets.forEach(function(el){ 1651 - touched.add(el); 1652 - }); 1653 - } 1654 - }); 1283 + if(applied){ 1284 + signature.forEach(function(el){ 1285 + touched.add(el); 1286 + }); 1287 + } 1655 1655 }); 1656 - 1657 - lastWidth=width; 1658 - hasApplied=true; 1659 - }finally{ 1660 - applying=false; 1661 - } 1289 + }); 1662 1662 } 1663 1663 1664 - function resize(){ 1665 - if(resizeTimer){ 1666 - clearTimeout( 1667 - resizeTimer 1668 - ); 1669 - } 1292 + function schedule(){ 1293 + if(raf)cancelAnimationFrame(raf); 1670 1670 1671 - resizeTimer= 1672 - setTimeout( 1673 - function(){ 1674 - resizeTimer=0; 1675 - calculate(false); 1676 - }, 1677 - RESIZE_DEBOUNCE 1678 - ); 1295 + raf=requestAnimationFrame(function(){ 1296 + raf=requestAnimationFrame(function(){ 1297 + raf=0; 1298 + run(); 1299 + }); 1300 + }); 1679 1679 } 1680 1680 1681 - function waitImages(){ 1682 - var images= 1683 - Array.from( 1684 - root.querySelectorAll("img") 1685 - ); 1303 + addEventListener("resize",schedule,{passive:true}); 1304 + addEventListener("load",schedule,{once:true}); 1686 1686 1687 - return Promise.all( 1688 - images.map(function(img){ 1689 - if(img.complete){ 1690 - return Promise.resolve(); 1691 - } 1306 + root.addEventListener( 1307 + "click", 1308 + function(){ 1309 + setTimeout(schedule,0); 1310 + }, 1311 + true 1312 + ); 1692 1692 1693 - return new Promise(function(resolve){ 1694 - var done=function(){ 1695 - resolve(); 1696 - }; 1697 - 1698 - img.addEventListener( 1699 - "load", 1700 - done, 1701 - {once:true} 1702 - ); 1703 - 1704 - img.addEventListener( 1705 - "error", 1706 - done, 1707 - {once:true} 1708 - ); 1709 - }); 1710 - }) 1711 - ); 1712 - } 1713 - 1714 - async function initial(){ 1715 - if( 1716 - document.readyState!== 1717 - "complete" 1718 - ){ 1719 - await new Promise(function(resolve){ 1720 - addEventListener( 1721 - "load", 1722 - resolve, 1723 - {once:true} 1724 - ); 1725 - }); 1314 + Array.from(root.querySelectorAll("img")).forEach(function(img){ 1315 + if(!img.complete){ 1316 + img.addEventListener("load",schedule,{once:true}); 1726 1726 } 1318 + }); 1727 1727 1728 - if( 1729 - document.fonts&& 1730 - document.fonts.ready 1731 - ){ 1732 - try{ 1733 - await document.fonts.ready; 1734 - }catch(error){} 1735 - } 1736 - 1737 - await waitImages(); 1738 - 1739 - // Exactly one initial layout calculation. 1740 - calculate(true); 1320 + if(document.fonts&&document.fonts.ready){ 1321 + document.fonts.ready.then(schedule); 1741 1741 } 1742 1742 1743 - addEventListener( 1744 - "resize", 1745 - resize, 1746 - {passive:true} 1747 - ); 1748 - 1749 - initial(); 1324 + schedule(); 1325 + setTimeout(schedule,200); 1326 + setTimeout(schedule,650); 1327 + setTimeout(schedule,1400); 1750 1750 })(); 1751 1751 </script> 1752 - 1753 1753 <!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1754 -{{/html}}\n 1331 +{{/html}} 1332 +