Changes for page Identify Your Data & Research Outputs
Last modified by Veronika Kocher on Friday, 04 Sep 2026 14:45
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.10
edited by Veronika Kocher
on Thursday, 03 Sep 2026 10:09
on Thursday, 03 Sep 2026 10:09
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -261,15 +261,104 @@ 261 261 </div> 262 262 {{/html}} 263 263 264 -{{html clean="false"}} 264 +\n\n 265 +\n\n{{html clean="false"}} 265 265 <!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 266 -<style data-sn-horizontal-box-harmonizer="4"> 267 -[data-sn-equal-height-managed], 268 -[data-sn-first-section-aligned]{ 267 + 268 +<style data-sn-horizontal-box-harmonizer="7"> 269 +/* ---------- Typography: never justify headings ---------- */ 270 +#xwikicontent h1, 271 +#xwikicontent h2, 272 +#xwikicontent h3, 273 +#xwikicontent h4, 274 +#xwikicontent h5, 275 +#xwikicontent h6, 276 +#xwikicontent .box-title, 277 +#xwikicontent [role="heading"], 278 +#xwikicontent h1 a, 279 +#xwikicontent h2 a, 280 +#xwikicontent h3 a, 281 +#xwikicontent h4 a, 282 +#xwikicontent h5 a, 283 +#xwikicontent h6 a, 284 +#xwikicontent .box-title a, 285 +#xwikicontent [role="heading"] a{ 286 + text-align:left!important; 287 + text-justify:auto!important; 288 + word-spacing:normal!important; 289 +} 290 + 291 +/* ---------- Native XWiki semantic callouts ---------- */ 292 +#xwikicontent .box.infomessage, 293 +#xwikicontent .infomessage, 294 +#xwikicontent .box.warningmessage, 295 +#xwikicontent .warningmessage, 296 +#xwikicontent .box.successmessage, 297 +#xwikicontent .successmessage, 298 +#xwikicontent .box.errormessage, 299 +#xwikicontent .errormessage, 300 +#xwikicontent [data-sn-callout-harmonized="1"]{ 301 + box-sizing:border-box!important; 302 + border-radius:8px!important; 303 + border-top:1px solid rgba(0,0,0,.08)!important; 304 + border-right:1px solid rgba(0,0,0,.08)!important; 305 + border-bottom:1px solid rgba(0,0,0,.08)!important; 306 + border-left:4px solid var(--sn-callout-accent,#21b6d7)!important; 307 + padding:14px 16px!important; 308 + text-align:left!important; 309 + text-justify:auto!important; 310 + word-spacing:normal!important; 311 + box-shadow:none!important; 312 +} 313 + 314 +#xwikicontent .box.infomessage, 315 +#xwikicontent .infomessage{ 316 + --sn-callout-accent:#21b6d7; 317 + background:#eaf7fb!important; 318 +} 319 + 320 +#xwikicontent .box.warningmessage, 321 +#xwikicontent .warningmessage{ 322 + --sn-callout-accent:#f0aa00; 323 + background:#fff8e7!important; 324 +} 325 + 326 +#xwikicontent .box.successmessage, 327 +#xwikicontent .successmessage{ 328 + --sn-callout-accent:#38b76a; 329 + background:#edf9f1!important; 330 +} 331 + 332 +#xwikicontent .box.errormessage, 333 +#xwikicontent .errormessage{ 334 + --sn-callout-accent:#e94b13; 335 + background:#fff1ec!important; 336 +} 337 + 338 +#xwikicontent [data-sn-callout-harmonized="1"] > :first-child, 339 +#xwikicontent .infomessage > :first-child, 340 +#xwikicontent .warningmessage > :first-child, 341 +#xwikicontent .successmessage > :first-child, 342 +#xwikicontent .errormessage > :first-child{ 343 + margin-top:0!important; 344 +} 345 + 346 +#xwikicontent [data-sn-callout-harmonized="1"] > :last-child, 347 +#xwikicontent .infomessage > :last-child, 348 +#xwikicontent .warningmessage > :last-child, 349 +#xwikicontent .successmessage > :last-child, 350 +#xwikicontent .errormessage > :last-child{ 351 + margin-bottom:0!important; 352 +} 353 + 354 +#xwikicontent [data-sn-equal-height-managed], 355 +#xwikicontent [data-sn-first-section-aligned], 356 +#xwikicontent [data-sn-first-content-aligned]{ 269 269 box-sizing:border-box; 270 270 } 271 271 </style> 272 -<script data-sn-horizontal-box-harmonizer="4"> 360 + 361 +<script data-sn-horizontal-box-harmonizer="7"> 273 273 (function(){ 274 274 "use strict"; 275 275 ... ... @@ -277,8 +277,10 @@ 277 277 var ROW_TOLERANCE=6; 278 278 var MIN_W=150; 279 279 var MIN_H=36; 280 - var MAX_PARENT_CHILDREN=1 6;369 + var MAX_PARENT_CHILDREN=18; 281 281 var SEARCH_DEPTH=5; 371 + var RESIZE_DEBOUNCE=220; 372 + var MIN_WIDTH_CHANGE=2; 282 282 283 283 var root= 284 284 document.getElementById("xwikicontent")|| ... ... @@ -290,10 +290,16 @@ 290 290 291 291 var heightManaged=new Set(); 292 292 var sectionManaged=new Set(); 384 + var contentManaged=new Set(); 385 + 293 293 var originalMinHeight=new WeakMap(); 294 294 var originalMarginTop=new WeakMap(); 295 - var raf=0; 296 296 389 + var resizeTimer=0; 390 + var lastWidth=-1; 391 + var hasApplied=false; 392 + var applying=false; 393 + 297 297 function num(v){ 298 298 var n=parseFloat(v); 299 299 return Number.isFinite(n)?n:0; ... ... @@ -320,6 +320,13 @@ 320 320 ); 321 321 } 322 322 420 + function normalizeText(text){ 421 + return String(text||"") 422 + .replace(/\s+/g," ") 423 + .trim() 424 + .toUpperCase(); 425 + } 426 + 323 323 function excluded(el){ 324 324 return ( 325 325 !el.matches|| ... ... @@ -329,57 +329,84 @@ 329 329 ); 330 330 } 331 331 332 - function namedLikeBox(el){ 436 + /* ---------- Custom coloured callouts ---------- */ 437 + 438 + function nativeCallout(el){ 333 333 var c= 334 334 typeof el.className==="string" 335 - ? el.className 441 + ? el.className.toLowerCase() 336 336 : ""; 337 337 338 - return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c); 444 + return ( 445 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c) 446 + ); 339 339 } 340 340 341 - function boxLike(el){342 - if(!visible(el, MIN_W,MIN_H)||excluded(el))return false;449 + function customCallout(el){ 450 + if(!visible(el,220,42)||excluded(el))return false; 343 343 344 - var s=getComputedStyle(el); 345 345 var r=el.getBoundingClientRect(); 346 346 347 - var border= 348 - num(s.borderTopWidth)+ 349 - num(s.borderRightWidth)+ 350 - num(s.borderBottomWidth)+ 351 - num(s.borderLeftWidth); 454 + if(r.height>520)return false; 352 352 353 - var radius=Math.max( 354 - num(s.borderTopLeftRadius), 355 - num(s.borderTopRightRadius), 356 - num(s.borderBottomLeftRadius), 357 - num(s.borderBottomRightRadius) 358 - ); 456 + var s=getComputedStyle(el); 359 359 360 360 var bg= 361 361 s.backgroundColor&& 362 362 s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 363 - s.backgroundColor!=="transparent"; 461 + s.backgroundColor!=="transparent"&& 462 + s.backgroundColor!=="rgb(255, 255, 255)"; 364 364 365 - var shadow= 366 - s.boxShadow&& 367 - s.boxShadow!=="none"; 464 + var left= 465 + num(s.borderLeftWidth); 368 368 369 369 return ( 370 - namedLikeBox(el)|| 371 - border>=1|| 372 - (bg&&radius>=3)|| 373 - (shadow&&r.width>=180) 468 + bg&& 469 + left>=2 374 374 ); 375 375 } 376 376 473 + function harmoniseCustomCallouts(){ 474 + Array.from( 475 + root.querySelectorAll( 476 + "div,aside,section" 477 + ) 478 + ).forEach(function(el){ 479 + if(nativeCallout(el))return; 480 + if(!customCallout(el))return; 481 + 482 + var s=getComputedStyle(el); 483 + 484 + el.setAttribute( 485 + "data-sn-callout-harmonized", 486 + "1" 487 + ); 488 + 489 + if( 490 + s.borderLeftColor 491 + ){ 492 + el.style.setProperty( 493 + "--sn-callout-accent", 494 + s.borderLeftColor 495 + ); 496 + } 497 + }); 498 + } 499 + 500 + /* ---------- Restore only values V7 itself changed ---------- */ 501 + 377 377 function saveOriginal(el,map,property){ 378 378 if(map.has(el))return; 379 379 380 380 map.set(el,{ 381 - value:el.style.getPropertyValue(property), 382 - priority:el.style.getPropertyPriority(property) 506 + value: 507 + el.style.getPropertyValue( 508 + property 509 + ), 510 + priority: 511 + el.style.getPropertyPriority( 512 + property 513 + ) 383 383 }); 384 384 } 385 385 ... ... @@ -393,11 +393,13 @@ 393 393 original.priority||"" 394 394 ); 395 395 }else{ 396 - el.style.removeProperty(property); 527 + el.style.removeProperty( 528 + property 529 + ); 397 397 } 398 398 } 399 399 400 - function reset(){ 533 + function resetRuntime(){ 401 401 heightManaged.forEach(function(el){ 402 402 restoreOriginal( 403 403 el, ... ... @@ -422,16 +422,79 @@ 422 422 ); 423 423 }); 424 424 558 + contentManaged.forEach(function(el){ 559 + restoreOriginal( 560 + el, 561 + originalMarginTop, 562 + "margin-top" 563 + ); 564 + 565 + el.removeAttribute( 566 + "data-sn-first-content-aligned" 567 + ); 568 + }); 569 + 425 425 heightManaged.clear(); 426 426 sectionManaged.clear(); 572 + contentManaged.clear(); 427 427 } 428 428 575 + /* ---------- Card detection ---------- */ 576 + 577 + function namedLikeBox(el){ 578 + var c= 579 + typeof el.className==="string" 580 + ? el.className 581 + : ""; 582 + 583 + return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 584 + } 585 + 586 + function boxLike(el){ 587 + if( 588 + !visible(el,MIN_W,MIN_H)|| 589 + excluded(el) 590 + ){ 591 + return false; 592 + } 593 + 594 + var s=getComputedStyle(el); 595 + var r=el.getBoundingClientRect(); 596 + 597 + var border= 598 + num(s.borderTopWidth)+ 599 + num(s.borderRightWidth)+ 600 + num(s.borderBottomWidth)+ 601 + num(s.borderLeftWidth); 602 + 603 + var radius=Math.max( 604 + num(s.borderTopLeftRadius), 605 + num(s.borderTopRightRadius), 606 + num(s.borderBottomLeftRadius), 607 + num(s.borderBottomRightRadius) 608 + ); 609 + 610 + var bg= 611 + s.backgroundColor&& 612 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 613 + s.backgroundColor!=="transparent"; 614 + 615 + var shadow= 616 + s.boxShadow&& 617 + s.boxShadow!=="none"; 618 + 619 + return ( 620 + namedLikeBox(el)|| 621 + border>=1|| 622 + (bg&&radius>=3)|| 623 + (shadow&&r.width>=180) 624 + ); 625 + } 626 + 429 429 function pickTarget(child){ 430 430 if(!visible(child,MIN_W,MIN_H))return null; 431 431 432 - if(boxLike(child)){ 433 - return child; 434 - } 630 + if(boxLike(child))return child; 435 435 436 436 var cr=child.getBoundingClientRect(); 437 437 var q=[]; ... ... @@ -493,7 +493,7 @@ 493 493 return best; 494 494 } 495 495 496 - function group sByVisualRow(entries){692 + function groupRows(entries){ 497 497 var groups=[]; 498 498 499 499 entries ... ... @@ -533,7 +533,7 @@ 533 533 return groups; 534 534 } 535 535 536 - function valid HorizontalGroup(group){732 + function validRow(group){ 537 537 if(group.entries.length<2)return false; 538 538 539 539 var lefts= ... ... @@ -556,25 +556,26 @@ 556 556 557 557 if(widths.length<2)return false; 558 558 559 - var minW idth=Math.min.apply(Math,widths);560 - varmaxWidth=Math.max.apply(Math,widths);755 + var minW= 756 + Math.min.apply(Math,widths); 561 561 758 + var maxW= 759 + Math.max.apply(Math,widths); 760 + 562 562 return ( 563 - maxW idth/564 - Math.max(1,minW idth)<=762 + maxW/ 763 + Math.max(1,minW)<= 565 565 1.9 566 566 ); 567 567 } 568 568 569 - function normalizeText(text){ 570 - return String(text||"") 571 - .replace(/s+/g," ") 572 - .trim() 573 - .toUpperCase(); 574 - } 768 + /* ---------- Known ARSN first section bars ---------- */ 575 575 576 - function exactKnownFirstSection(el){ 577 - var text=normalizeText(el.textContent); 770 + function knownBar(el){ 771 + var text= 772 + normalizeText( 773 + el.textContent 774 + ); 578 578 579 579 return ( 580 580 text==="HIER STARTEN"|| ... ... @@ -588,150 +588,274 @@ 588 588 ); 589 589 } 590 590 591 - function visuallyFirstSectionBar(card){592 - var cardRect= card.getBoundingClientRect();593 - varcandidates=[];788 + function findKnownBar(card){ 789 + var cardRect= 790 + card.getBoundingClientRect(); 594 594 595 - Array.from( 596 - card.querySelectorAll( 597 - "div,p,span,strong,h3,h4,h5,h6" 792 + var rows= 793 + Array.from( 794 + card.querySelectorAll( 795 + "div,p,span,strong,h3,h4,h5,h6" 796 + ) 598 598 ) 599 - ).forEach(function(el){600 - if(!visible(el,20,6))return; 601 - if( excluded(el))return;798 + .filter(function(el){ 799 + if(!visible(el,20,6))return false; 800 + if(!knownBar(el))return false; 602 602 603 - var r=el.getBoundingClientRect(); 604 - var relativeTop=r.top-cardRect.top; 802 + var r=el.getBoundingClientRect(); 605 605 606 - if( 607 - relativeTop<45|| 608 - relativeTop>cardRect.height*.72 609 - ){ 610 - return; 611 - } 804 + var rel= 805 + r.top- 806 + cardRect.top; 612 612 613 - var widthRatio= 614 - r.width/ 615 - Math.max(1,cardRect.width); 808 + return ( 809 + rel>=35&& 810 + rel<= 811 + cardRect.height*.75 812 + ); 813 + }) 814 + .sort(function(a,b){ 815 + return ( 816 + a.getBoundingClientRect().top- 817 + b.getBoundingClientRect().top 818 + ); 819 + }); 616 616 617 - if( 618 - widthRatio<.55|| 619 - widthRatio>1.05|| 620 - r.height>54 621 - ){ 622 - return; 623 - } 821 + return rows[0]||null; 822 + } 624 624 625 - var text=normalizeText(el.textContent); 824 + function alignKnownBars(cards){ 825 + var rows= 826 + cards.map(function(card){ 827 + var bar= 828 + findKnownBar(card); 626 626 627 - if( 628 - text.length<2|| 629 - text.length>90 630 - ){ 631 - return; 632 - } 830 + if(!bar)return null; 633 633 634 - var style=getComputedStyle(el); 832 + var cr= 833 + card.getBoundingClientRect(); 635 635 636 - var bg= 637 - style.backgroundColor&& 638 - style.backgroundColor!=="rgba(0, 0, 0, 0)"&& 639 - style.backgroundColor!=="transparent"; 835 + var br= 836 + bar.getBoundingClientRect(); 640 640 641 - var border= 642 - num(style.borderTopWidth)+ 643 - num(style.borderRightWidth)+ 644 - num(style.borderBottomWidth)+ 645 - num(style.borderLeftWidth); 838 + return { 839 + bar:bar, 840 + relativeTop: 841 + br.top- 842 + cr.top 843 + }; 844 + }); 646 646 647 - var mostlyUpper= 648 - text.length>=3&& 649 - text===text.toUpperCase(); 846 + if( 847 + rows.some(function(row){ 848 + return !row; 849 + }) 850 + ){ 851 + return false; 852 + } 650 650 651 - var exact=exactKnownFirstSection(el); 854 + var target= 855 + Math.max.apply( 856 + Math, 857 + rows.map(function(row){ 858 + return row.relativeTop; 859 + }) 860 + ); 652 652 653 - var score= 654 - (exact?20:0)+ 655 - (bg?6:0)+ 656 - (border>=1?2:0)+ 657 - (mostlyUpper?4:0)+ 658 - (num(style.fontWeight)>=600?1:0); 862 + rows.forEach(function(row){ 863 + var delta= 864 + target- 865 + row.relativeTop; 659 659 660 - if(score>=7){ 661 - candidates.push({ 662 - el:el, 663 - relativeTop:relativeTop, 664 - width:r.width, 665 - score:score 666 - }); 667 - } 668 - }); 867 + if(delta<=1)return; 669 669 670 - if(!candidates.length)return null; 869 + saveOriginal( 870 + row.bar, 871 + originalMarginTop, 872 + "margin-top" 873 + ); 671 671 672 - candidates.sort(function(a,b){ 673 - if(a.score!==b.score)return b.score-a.score; 674 - if(Math.abs(a.relativeTop-b.relativeTop)>3){ 675 - return a.relativeTop-b.relativeTop; 676 - } 677 - return b.width-a.width; 678 - }); 875 + var current= 876 + num( 877 + getComputedStyle( 878 + row.bar 879 + ).marginTop 880 + ); 679 679 680 - // For exact known labels always prefer the earliest exact match. 681 - var exacts=candidates.filter(function(c){ 682 - return exactKnownFirstSection(c.el); 882 + row.bar.style.setProperty( 883 + "margin-top", 884 + ( 885 + current+ 886 + delta 887 + )+"px" 888 + ); 889 + 890 + row.bar.setAttribute( 891 + "data-sn-first-section-aligned", 892 + "7" 893 + ); 894 + 895 + sectionManaged.add( 896 + row.bar 897 + ); 683 683 }); 684 684 685 - if(exacts.length){ 686 - exacts.sort(function(a,b){ 687 - return a.relativeTop-b.relativeTop||b.width-a.width; 900 + return true; 901 + } 902 + 903 + /* ---------- Generic first content after heading ---------- */ 904 + 905 + function heading(card){ 906 + var cr= 907 + card.getBoundingClientRect(); 908 + 909 + var rows= 910 + Array.from( 911 + card.querySelectorAll( 912 + "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]" 913 + ) 914 + ) 915 + .filter(function(el){ 916 + if(!visible(el,20,8))return false; 917 + 918 + var r=el.getBoundingClientRect(); 919 + 920 + var rel= 921 + r.top- 922 + cr.top; 923 + 924 + return ( 925 + rel>=0&& 926 + rel<= 927 + Math.min( 928 + 160, 929 + cr.height*.45 930 + ) 931 + ); 932 + }) 933 + .sort(function(a,b){ 934 + return ( 935 + a.getBoundingClientRect().top- 936 + b.getBoundingClientRect().top 937 + ); 688 688 }); 689 - return exacts[0].el; 690 - } 691 691 692 - // Generic fallback: earliest high-confidence bar. 693 - candidates.sort(function(a,b){ 694 - return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width; 695 - }); 940 + return rows[0]||null; 941 + } 696 696 697 - return candidates[0].el; 943 + function firstContent(card,h){ 944 + if(!h)return null; 945 + 946 + var cr= 947 + card.getBoundingClientRect(); 948 + 949 + var hr= 950 + h.getBoundingClientRect(); 951 + 952 + var rows= 953 + Array.from( 954 + card.querySelectorAll( 955 + "p,div,ul,ol,dl,blockquote" 956 + ) 957 + ) 958 + .filter(function(el){ 959 + if( 960 + el===h|| 961 + h.contains(el)|| 962 + el.contains(h) 963 + ){ 964 + return false; 965 + } 966 + 967 + if(!visible(el,30,8))return false; 968 + 969 + var text= 970 + String(el.textContent||"") 971 + .replace(/\s+/g," ") 972 + .trim(); 973 + 974 + if(text.length<3)return false; 975 + 976 + var r=el.getBoundingClientRect(); 977 + 978 + if( 979 + r.top< 980 + hr.bottom-1 981 + ){ 982 + return false; 983 + } 984 + 985 + if( 986 + r.top-cr.top> 987 + Math.min( 988 + 280, 989 + cr.height*.65 990 + ) 991 + ){ 992 + return false; 993 + } 994 + 995 + if( 996 + r.height> 997 + cr.height*.58 998 + ){ 999 + return false; 1000 + } 1001 + 1002 + return true; 1003 + }) 1004 + .sort(function(a,b){ 1005 + var ar= 1006 + a.getBoundingClientRect(); 1007 + 1008 + var br= 1009 + b.getBoundingClientRect(); 1010 + 1011 + return ( 1012 + ar.top-br.top|| 1013 + ar.height-br.height 1014 + ); 1015 + }); 1016 + 1017 + return rows[0]||null; 698 698 } 699 699 700 - function align FirstSections(cards){1020 + function alignGeneric(cards){ 701 701 var rows= 702 702 cards.map(function(card){ 703 - var bar=704 - visuallyFirstSectionBar(card);1023 + var h= 1024 + heading(card); 705 705 706 - if(!bar)return null; 1026 + var c= 1027 + firstContent( 1028 + card, 1029 + h 1030 + ); 707 707 708 - var cardRect= 1032 + if(!h||!c)return null; 1033 + 1034 + var cr= 709 709 card.getBoundingClientRect(); 710 710 711 - var barRect=712 - bar.getBoundingClientRect();1037 + var rr= 1038 + c.getBoundingClientRect(); 713 713 714 714 return { 715 - card:card, 716 - bar:bar, 1041 + content:c, 717 717 relativeTop: 718 - barRect.top-cardRect.top, 719 - label: 720 - normalizeText(bar.textContent) 1043 + rr.top-cr.top 721 721 }; 722 722 }); 723 723 724 - // Conservative: only align when every card in the horizontal row 725 - // has a reliable first section bar. 726 726 if( 727 727 rows.some(function(row){ 728 728 return !row; 729 729 }) 730 730 ){ 731 - return null;1052 + return false; 732 732 } 733 733 734 - var target Top=1055 + var target= 735 735 Math.max.apply( 736 736 Math, 737 737 rows.map(function(row){ ... ... @@ -741,54 +741,47 @@ 741 741 742 742 rows.forEach(function(row){ 743 743 var delta= 744 - target Top-1065 + target- 745 745 row.relativeTop; 746 746 747 747 if(delta<=1)return; 748 748 749 749 saveOriginal( 750 - row. bar,1071 + row.content, 751 751 originalMarginTop, 752 752 "margin-top" 753 753 ); 754 754 755 - var current Margin=1076 + var current= 756 756 num( 757 757 getComputedStyle( 758 - row. bar1079 + row.content 759 759 ).marginTop 760 760 ); 761 761 762 - row. bar.style.setProperty(1083 + row.content.style.setProperty( 763 763 "margin-top", 764 764 ( 765 - current Margin+1086 + current+ 766 766 delta 767 767 )+"px" 768 768 ); 769 769 770 - row. bar.setAttribute(771 - "data-sn-first- section-aligned",772 - " 4"1091 + row.content.setAttribute( 1092 + "data-sn-first-content-aligned", 1093 + "7" 773 773 ); 774 774 775 - sectionManaged.add(row.bar); 1096 + contentManaged.add( 1097 + row.content 1098 + ); 776 776 }); 777 777 778 - return { 779 - labels: 780 - rows.map(function(row){ 781 - return row.label; 782 - }), 783 - targetRelativeTop: 784 - Math.round(targetTop) 785 - }; 1101 + return true; 786 786 } 787 787 788 - function applyGroup(group){ 789 - if(!validHorizontalGroup(group)){ 790 - return null; 791 - } 1104 + function applyRow(group){ 1105 + if(!validRow(group))return false; 792 792 793 793 var cards=[]; 794 794 var seen=new Set(); ... ... @@ -800,25 +800,30 @@ 800 800 } 801 801 }); 802 802 803 - if(cards.length<2)return null;1117 + if(cards.length<2)return false; 804 804 805 - var firstSection= 806 - alignFirstSections(cards); 1119 + if( 1120 + !alignKnownBars(cards) 1121 + ){ 1122 + alignGeneric(cards); 1123 + } 807 807 808 - // The section alignment can change natural card heights. 809 - // Measure only afterwards. 810 810 var maxHeight=0; 811 811 812 812 cards.forEach(function(card){ 813 - maxHeight=Math.max( 814 - maxHeight, 815 - card.getBoundingClientRect().height 816 - ); 1128 + maxHeight= 1129 + Math.max( 1130 + maxHeight, 1131 + card.getBoundingClientRect().height 1132 + ); 817 817 }); 818 818 819 - maxHeight=Math.ceil(maxHeight); 1135 + maxHeight= 1136 + Math.ceil( 1137 + maxHeight 1138 + ); 820 820 821 - if(maxHeight<MIN_H)return null;1140 + if(maxHeight<MIN_H)return false; 822 822 823 823 cards.forEach(function(card){ 824 824 saveOriginal( ... ... @@ -834,125 +834,228 @@ 834 834 835 835 card.setAttribute( 836 836 "data-sn-equal-height-managed", 837 - " 4"1156 + "7" 838 838 ); 839 839 840 840 heightManaged.add(card); 841 841 }); 842 842 843 - return { 844 - cards:cards.length, 845 - height:maxHeight, 846 - firstSection:firstSection 847 - }; 1162 + return true; 848 848 } 849 849 850 - function run(){851 - re set();1165 + function calculate(force){ 1166 + if(applying)return; 852 852 1168 + var width= 1169 + Math.round( 1170 + window.innerWidth 1171 + ); 1172 + 1173 + var meaningful= 1174 + lastWidth<0|| 1175 + Math.abs( 1176 + width- 1177 + lastWidth 1178 + )>= 1179 + MIN_WIDTH_CHANGE; 1180 + 853 853 if( 854 - window.innerWidth<=MOBILE_MAX 1182 + hasApplied&& 1183 + !force&& 1184 + !meaningful 855 855 ){ 856 856 return; 857 857 } 858 858 859 - var parents= 860 - Array.from( 861 - root.querySelectorAll("*") 862 - ).filter(function(parent){ 863 - return ( 864 - visible(parent,MIN_W,MIN_H)&& 865 - parent.children&& 866 - parent.children.length>=2&& 867 - parent.children.length<=MAX_PARENT_CHILDREN 868 - ); 869 - }); 1189 + applying=true; 870 870 871 - var touched=new Set(); 1191 + try{ 1192 + harmoniseCustomCallouts(); 872 872 873 - parents.forEach(function(parent){ 874 - var entries=[]; 1194 + if(width<=MOBILE_MAX){ 1195 + if(hasApplied){ 1196 + resetRuntime(); 1197 + } 875 875 876 - Array.from(parent.children).forEach(function(child){ 877 - if(!visible(child,MIN_W,MIN_H))return; 1199 + hasApplied=false; 1200 + lastWidth=width; 1201 + return; 1202 + } 878 878 879 - var target=pickTarget(child); 880 - if(!target)return; 1204 + if(hasApplied){ 1205 + resetRuntime(); 1206 + } 881 881 882 - entries.push({ 883 - target:target, 884 - rect:target.getBoundingClientRect() 1208 + var parents= 1209 + Array.from( 1210 + root.querySelectorAll("*") 1211 + ) 1212 + .filter(function(parent){ 1213 + return ( 1214 + visible( 1215 + parent, 1216 + MIN_W, 1217 + MIN_H 1218 + )&& 1219 + parent.children&& 1220 + parent.children.length>=2&& 1221 + parent.children.length<= 1222 + MAX_PARENT_CHILDREN 1223 + ); 885 885 }); 886 - }); 887 887 888 - if(entries.length<2)return; 1226 + var touched= 1227 + new Set(); 889 889 890 - groupsByVisualRow(entries).forEach(function(group){891 - if(!validHorizontalGroup(group))return;1229 + parents.forEach(function(parent){ 1230 + var entries=[]; 892 892 893 - var signature= 894 - group.entries.map(function(entry){ 895 - return entry.target; 896 - }); 1232 + Array.from( 1233 + parent.children 1234 + ).forEach(function(child){ 1235 + if( 1236 + !visible( 1237 + child, 1238 + MIN_W, 1239 + MIN_H 1240 + ) 1241 + ){ 1242 + return; 1243 + } 897 897 898 - if( 899 - !signature.some(function(el){ 900 - return !touched.has(el); 901 - }) 902 - ){ 903 - return; 904 - } 1245 + var target= 1246 + pickTarget(child); 905 905 906 - var applied= 907 - applyGroup(group); 1248 + if(!target)return; 908 908 909 - if(applied){ 910 - signature.forEach(function(el){ 911 - touched.add(el); 1250 + entries.push({ 1251 + target:target, 1252 + rect: 1253 + target.getBoundingClientRect() 912 912 }); 913 - } 1255 + }); 1256 + 1257 + groupRows( 1258 + entries 1259 + ).forEach(function(group){ 1260 + if(!validRow(group))return; 1261 + 1262 + var targets= 1263 + group.entries.map(function(entry){ 1264 + return entry.target; 1265 + }); 1266 + 1267 + if( 1268 + !targets.some(function(el){ 1269 + return !touched.has(el); 1270 + }) 1271 + ){ 1272 + return; 1273 + } 1274 + 1275 + if(applyRow(group)){ 1276 + targets.forEach(function(el){ 1277 + touched.add(el); 1278 + }); 1279 + } 1280 + }); 914 914 }); 915 - }); 1282 + 1283 + lastWidth=width; 1284 + hasApplied=true; 1285 + }finally{ 1286 + applying=false; 1287 + } 916 916 } 917 917 918 - function schedule(){ 919 - if(raf)cancelAnimationFrame(raf); 1290 + function resize(){ 1291 + if(resizeTimer){ 1292 + clearTimeout( 1293 + resizeTimer 1294 + ); 1295 + } 920 920 921 - raf=requestAnimationFrame(function(){ 922 - raf=requestAnimationFrame(function(){ 923 - raf=0; 924 - run(); 925 - }); 926 - }); 1297 + resizeTimer= 1298 + setTimeout( 1299 + function(){ 1300 + resizeTimer=0; 1301 + calculate(false); 1302 + }, 1303 + RESIZE_DEBOUNCE 1304 + ); 927 927 } 928 928 929 - addEventListener("resize",schedule,{passive:true}); 930 - addEventListener("load",schedule,{once:true}); 1307 + function waitImages(){ 1308 + var images= 1309 + Array.from( 1310 + root.querySelectorAll("img") 1311 + ); 931 931 932 - root.addEventListener( 933 - "click", 934 - function(){ 935 - setTimeout(schedule,0); 936 - }, 937 - true 938 - ); 1313 + return Promise.all( 1314 + images.map(function(img){ 1315 + if(img.complete){ 1316 + return Promise.resolve(); 1317 + } 939 939 940 - Array.from(root.querySelectorAll("img")).forEach(function(img){ 941 - if(!img.complete){ 942 - img.addEventListener("load",schedule,{once:true}); 1319 + return new Promise(function(resolve){ 1320 + var done=function(){ 1321 + resolve(); 1322 + }; 1323 + 1324 + img.addEventListener( 1325 + "load", 1326 + done, 1327 + {once:true} 1328 + ); 1329 + 1330 + img.addEventListener( 1331 + "error", 1332 + done, 1333 + {once:true} 1334 + ); 1335 + }); 1336 + }) 1337 + ); 1338 + } 1339 + 1340 + async function initial(){ 1341 + if( 1342 + document.readyState!== 1343 + "complete" 1344 + ){ 1345 + await new Promise(function(resolve){ 1346 + addEventListener( 1347 + "load", 1348 + resolve, 1349 + {once:true} 1350 + ); 1351 + }); 943 943 } 944 - }); 945 945 946 - if(document.fonts&&document.fonts.ready){ 947 - document.fonts.ready.then(schedule); 1354 + if( 1355 + document.fonts&& 1356 + document.fonts.ready 1357 + ){ 1358 + try{ 1359 + await document.fonts.ready; 1360 + }catch(error){} 1361 + } 1362 + 1363 + await waitImages(); 1364 + 1365 + // Exactly one initial layout calculation. 1366 + calculate(true); 948 948 } 949 949 950 - schedule(); 951 - setTimeout(schedule,200); 952 - setTimeout(schedule,650); 953 - setTimeout(schedule,1400); 1369 + addEventListener( 1370 + "resize", 1371 + resize, 1372 + {passive:true} 1373 + ); 1374 + 1375 + initial(); 954 954 })(); 955 955 </script> 956 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 957 -{{/html}} 958 958 1379 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1380 +{{/html}}\n