Changes for page Plan Your Data Management
Last modified by Veronika Kocher on Friday, 04 Sep 2026 14:45
From version 4.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
To version 4.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
-
... ... @@ -257,22 +257,115 @@ 257 257 </div> 258 258 {{/html}} 259 259 260 -{{html clean="false"}} 260 +\n\n 261 +\n\n{{html clean="false"}} 261 261 <!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 262 -<style data-sn-horizontal-box-harmonizer="1"> 263 -[data-sn-equal-height-managed="1"]{box-sizing:border-box} 264 -@media(max-width:767px){ 265 - [data-sn-equal-height-managed="1"]{min-height:0!important} 263 + 264 +<style data-sn-horizontal-box-harmonizer="7"> 265 +/* ---------- Typography: never justify headings ---------- */ 266 +#xwikicontent h1, 267 +#xwikicontent h2, 268 +#xwikicontent h3, 269 +#xwikicontent h4, 270 +#xwikicontent h5, 271 +#xwikicontent h6, 272 +#xwikicontent .box-title, 273 +#xwikicontent [role="heading"], 274 +#xwikicontent h1 a, 275 +#xwikicontent h2 a, 276 +#xwikicontent h3 a, 277 +#xwikicontent h4 a, 278 +#xwikicontent h5 a, 279 +#xwikicontent h6 a, 280 +#xwikicontent .box-title a, 281 +#xwikicontent [role="heading"] a{ 282 + text-align:left!important; 283 + text-justify:auto!important; 284 + word-spacing:normal!important; 266 266 } 286 + 287 +/* ---------- Native XWiki semantic callouts ---------- */ 288 +#xwikicontent .box.infomessage, 289 +#xwikicontent .infomessage, 290 +#xwikicontent .box.warningmessage, 291 +#xwikicontent .warningmessage, 292 +#xwikicontent .box.successmessage, 293 +#xwikicontent .successmessage, 294 +#xwikicontent .box.errormessage, 295 +#xwikicontent .errormessage, 296 +#xwikicontent [data-sn-callout-harmonized="1"]{ 297 + box-sizing:border-box!important; 298 + border-radius:8px!important; 299 + border-top:1px solid rgba(0,0,0,.08)!important; 300 + border-right:1px solid rgba(0,0,0,.08)!important; 301 + border-bottom:1px solid rgba(0,0,0,.08)!important; 302 + border-left:4px solid var(--sn-callout-accent,#21b6d7)!important; 303 + padding:14px 16px!important; 304 + text-align:left!important; 305 + text-justify:auto!important; 306 + word-spacing:normal!important; 307 + box-shadow:none!important; 308 +} 309 + 310 +#xwikicontent .box.infomessage, 311 +#xwikicontent .infomessage{ 312 + --sn-callout-accent:#21b6d7; 313 + background:#eaf7fb!important; 314 +} 315 + 316 +#xwikicontent .box.warningmessage, 317 +#xwikicontent .warningmessage{ 318 + --sn-callout-accent:#f0aa00; 319 + background:#fff8e7!important; 320 +} 321 + 322 +#xwikicontent .box.successmessage, 323 +#xwikicontent .successmessage{ 324 + --sn-callout-accent:#38b76a; 325 + background:#edf9f1!important; 326 +} 327 + 328 +#xwikicontent .box.errormessage, 329 +#xwikicontent .errormessage{ 330 + --sn-callout-accent:#e94b13; 331 + background:#fff1ec!important; 332 +} 333 + 334 +#xwikicontent [data-sn-callout-harmonized="1"] > :first-child, 335 +#xwikicontent .infomessage > :first-child, 336 +#xwikicontent .warningmessage > :first-child, 337 +#xwikicontent .successmessage > :first-child, 338 +#xwikicontent .errormessage > :first-child{ 339 + margin-top:0!important; 340 +} 341 + 342 +#xwikicontent [data-sn-callout-harmonized="1"] > :last-child, 343 +#xwikicontent .infomessage > :last-child, 344 +#xwikicontent .warningmessage > :last-child, 345 +#xwikicontent .successmessage > :last-child, 346 +#xwikicontent .errormessage > :last-child{ 347 + margin-bottom:0!important; 348 +} 349 + 350 +#xwikicontent [data-sn-equal-height-managed], 351 +#xwikicontent [data-sn-first-section-aligned], 352 +#xwikicontent [data-sn-first-content-aligned]{ 353 + box-sizing:border-box; 354 +} 267 267 </style> 268 -<script data-sn-horizontal-box-harmonizer="1"> 356 + 357 +<script data-sn-horizontal-box-harmonizer="7"> 269 269 (function(){ 270 270 "use strict"; 271 271 272 272 var MOBILE_MAX=767; 273 - var ROW_TOLERANCE= 4;362 + var ROW_TOLERANCE=6; 274 274 var MIN_W=150; 275 275 var MIN_H=36; 365 + var MAX_PARENT_CHILDREN=18; 366 + var SEARCH_DEPTH=5; 367 + var RESIZE_DEBOUNCE=220; 368 + var MIN_WIDTH_CHANGE=2; 276 276 277 277 var root= 278 278 document.getElementById("xwikicontent")|| ... ... @@ -282,72 +282,297 @@ 282 282 283 283 if(!root)return; 284 284 285 - var managed=new Set(); 286 - var raf=0; 378 + var heightManaged=new Set(); 379 + var sectionManaged=new Set(); 380 + var contentManaged=new Set(); 287 287 382 + var originalMinHeight=new WeakMap(); 383 + var originalMarginTop=new WeakMap(); 384 + 385 + var resizeTimer=0; 386 + var lastWidth=-1; 387 + var hasApplied=false; 388 + var applying=false; 389 + 288 288 function num(v){ 289 289 var n=parseFloat(v); 290 290 return Number.isFinite(n)?n:0; 291 291 } 292 292 293 - function visible(el){ 395 + function visible(el,minW,minH){ 294 294 if(!el||el.nodeType!==1)return false; 397 + 295 295 var s=getComputedStyle(el); 296 - if(s.display==="none"||s.visibility==="hidden"||Number(s.opacity)===0)return false; 399 + 400 + if( 401 + s.display==="none"|| 402 + s.visibility==="hidden"|| 403 + Number(s.opacity)===0 404 + ){ 405 + return false; 406 + } 407 + 297 297 var r=el.getBoundingClientRect(); 298 - return r.width>=MIN_W&&r.height>=MIN_H; 409 + 410 + return ( 411 + r.width>=(minW||1)&& 412 + r.height>=(minH||1) 413 + ); 299 299 } 300 300 416 + function normalizeText(text){ 417 + return String(text||"") 418 + .replace(/\s+/g," ") 419 + .trim() 420 + .toUpperCase(); 421 + } 422 + 301 301 function excluded(el){ 302 - return !el.matches||el.matches( 303 - "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]" 424 + return ( 425 + !el.matches|| 426 + el.matches( 427 + "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]" 428 + ) 304 304 ); 305 305 } 306 306 432 + /* ---------- Custom coloured callouts ---------- */ 433 + 434 + function nativeCallout(el){ 435 + var c= 436 + typeof el.className==="string" 437 + ? el.className.toLowerCase() 438 + : ""; 439 + 440 + return ( 441 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c) 442 + ); 443 + } 444 + 445 + function customCallout(el){ 446 + if(!visible(el,220,42)||excluded(el))return false; 447 + 448 + var r=el.getBoundingClientRect(); 449 + 450 + if(r.height>520)return false; 451 + 452 + var s=getComputedStyle(el); 453 + 454 + var bg= 455 + s.backgroundColor&& 456 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 457 + s.backgroundColor!=="transparent"&& 458 + s.backgroundColor!=="rgb(255, 255, 255)"; 459 + 460 + var left= 461 + num(s.borderLeftWidth); 462 + 463 + return ( 464 + bg&& 465 + left>=2 466 + ); 467 + } 468 + 469 + function harmoniseCustomCallouts(){ 470 + Array.from( 471 + root.querySelectorAll( 472 + "div,aside,section" 473 + ) 474 + ).forEach(function(el){ 475 + if(nativeCallout(el))return; 476 + if(!customCallout(el))return; 477 + 478 + var s=getComputedStyle(el); 479 + 480 + el.setAttribute( 481 + "data-sn-callout-harmonized", 482 + "1" 483 + ); 484 + 485 + if( 486 + s.borderLeftColor 487 + ){ 488 + el.style.setProperty( 489 + "--sn-callout-accent", 490 + s.borderLeftColor 491 + ); 492 + } 493 + }); 494 + } 495 + 496 + /* ---------- Restore only values V7 itself changed ---------- */ 497 + 498 + function saveOriginal(el,map,property){ 499 + if(map.has(el))return; 500 + 501 + map.set(el,{ 502 + value: 503 + el.style.getPropertyValue( 504 + property 505 + ), 506 + priority: 507 + el.style.getPropertyPriority( 508 + property 509 + ) 510 + }); 511 + } 512 + 513 + function restoreOriginal(el,map,property){ 514 + var original=map.get(el); 515 + 516 + if(original&&original.value){ 517 + el.style.setProperty( 518 + property, 519 + original.value, 520 + original.priority||"" 521 + ); 522 + }else{ 523 + el.style.removeProperty( 524 + property 525 + ); 526 + } 527 + } 528 + 529 + function resetRuntime(){ 530 + heightManaged.forEach(function(el){ 531 + restoreOriginal( 532 + el, 533 + originalMinHeight, 534 + "min-height" 535 + ); 536 + 537 + el.removeAttribute( 538 + "data-sn-equal-height-managed" 539 + ); 540 + }); 541 + 542 + sectionManaged.forEach(function(el){ 543 + restoreOriginal( 544 + el, 545 + originalMarginTop, 546 + "margin-top" 547 + ); 548 + 549 + el.removeAttribute( 550 + "data-sn-first-section-aligned" 551 + ); 552 + }); 553 + 554 + contentManaged.forEach(function(el){ 555 + restoreOriginal( 556 + el, 557 + originalMarginTop, 558 + "margin-top" 559 + ); 560 + 561 + el.removeAttribute( 562 + "data-sn-first-content-aligned" 563 + ); 564 + }); 565 + 566 + heightManaged.clear(); 567 + sectionManaged.clear(); 568 + contentManaged.clear(); 569 + } 570 + 571 + /* ---------- Card detection ---------- */ 572 + 307 307 function namedLikeBox(el){ 308 - var c=typeof el.className==="string"?el.className:""; 574 + var c= 575 + typeof el.className==="string" 576 + ? el.className 577 + : ""; 578 + 309 309 return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 310 310 } 311 311 312 312 function boxLike(el){ 313 - if(!visible(el)||excluded(el))return false; 583 + if( 584 + !visible(el,MIN_W,MIN_H)|| 585 + excluded(el) 586 + ){ 587 + return false; 588 + } 589 + 314 314 var s=getComputedStyle(el); 315 315 var r=el.getBoundingClientRect(); 592 + 316 316 var border= 317 - num(s.borderTopWidth)+num(s.borderRightWidth)+ 318 - num(s.borderBottomWidth)+num(s.borderLeftWidth); 594 + num(s.borderTopWidth)+ 595 + num(s.borderRightWidth)+ 596 + num(s.borderBottomWidth)+ 597 + num(s.borderLeftWidth); 598 + 319 319 var radius=Math.max( 320 - num(s.borderTopLeftRadius),num(s.borderTopRightRadius), 321 - num(s.borderBottomLeftRadius),num(s.borderBottomRightRadius) 600 + num(s.borderTopLeftRadius), 601 + num(s.borderTopRightRadius), 602 + num(s.borderBottomLeftRadius), 603 + num(s.borderBottomRightRadius) 322 322 ); 323 - var bg=s.backgroundColor&&s.backgroundColor!=="rgba(0, 0, 0, 0)"&&s.backgroundColor!=="transparent"; 324 - var shadow=s.boxShadow&&s.boxShadow!=="none"; 325 - return namedLikeBox(el)||border>=1||(bg&&radius>=3)||(shadow&&r.width>=180); 605 + 606 + var bg= 607 + s.backgroundColor&& 608 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 609 + s.backgroundColor!=="transparent"; 610 + 611 + var shadow= 612 + s.boxShadow&& 613 + s.boxShadow!=="none"; 614 + 615 + return ( 616 + namedLikeBox(el)|| 617 + border>=1|| 618 + (bg&&radius>=3)|| 619 + (shadow&&r.width>=180) 620 + ); 326 326 } 327 327 328 328 function pickTarget(child){ 329 - if(!visible(child))return null; 624 + if(!visible(child,MIN_W,MIN_H))return null; 625 + 330 330 if(boxLike(child))return child; 331 331 332 332 var cr=child.getBoundingClientRect(); 333 333 var q=[]; 630 + 334 334 Array.from(child.children||[]).forEach(function(el){ 335 335 q.push({el:el,depth:1}); 336 336 }); 337 337 338 - var best=null,bestScore=-1; 635 + var best=null; 636 + var bestScore=-Infinity; 339 339 340 340 while(q.length){ 341 341 var item=q.shift(); 342 342 var el=item.el; 343 - if(!visible(el))continue; 344 344 642 + if(!visible(el,MIN_W,MIN_H))continue; 643 + 345 345 var r=el.getBoundingClientRect(); 346 346 347 - if(r.width>=cr.width*.72&&boxLike(el)){ 348 - var widthFit=1-Math.min(1,Math.abs(cr.width-r.width)/Math.max(1,cr.width)); 349 - var topFit=1-Math.min(1,Math.abs(cr.top-r.top)/80); 350 - var score=widthFit*5+topFit*2+Math.min(r.height,600)/600; 646 + if( 647 + r.width>=cr.width*.68&& 648 + boxLike(el) 649 + ){ 650 + var widthFit= 651 + 1-Math.min( 652 + 1, 653 + Math.abs(cr.width-r.width)/ 654 + Math.max(1,cr.width) 655 + ); 656 + 657 + var topFit= 658 + 1-Math.min( 659 + 1, 660 + Math.abs(cr.top-r.top)/100 661 + ); 662 + 663 + var score= 664 + widthFit*6+ 665 + topFit*3+ 666 + Math.min(r.height,900)/450+ 667 + Math.min(r.width*r.height,900000)/900000; 668 + 351 351 if(score>bestScore){ 352 352 best=el; 353 353 bestScore=score; ... ... @@ -354,9 +354,12 @@ 354 354 } 355 355 } 356 356 357 - if(item.depth< 3){675 + if(item.depth<SEARCH_DEPTH){ 358 358 Array.from(el.children||[]).forEach(function(next){ 359 - q.push({el:next,depth:item.depth+1}); 677 + q.push({ 678 + el:next, 679 + depth:item.depth+1 680 + }); 360 360 }); 361 361 } 362 362 } ... ... @@ -364,130 +364,692 @@ 364 364 return best; 365 365 } 366 366 367 - function reset(){ 368 - managed.forEach(function(el){ 369 - el.style.removeProperty("min-height"); 370 - el.removeAttribute("data-sn-equal-height-managed"); 371 - }); 372 - managed.clear(); 688 + function groupRows(entries){ 689 + var groups=[]; 690 + 691 + entries 692 + .slice() 693 + .sort(function(a,b){ 694 + return ( 695 + a.rect.top-b.rect.top|| 696 + a.rect.left-b.rect.left 697 + ); 698 + }) 699 + .forEach(function(entry){ 700 + var group=null; 701 + 702 + for(var i=0;i<groups.length;i++){ 703 + if( 704 + Math.abs( 705 + groups[i].top- 706 + entry.rect.top 707 + )<=ROW_TOLERANCE 708 + ){ 709 + group=groups[i]; 710 + break; 711 + } 712 + } 713 + 714 + if(!group){ 715 + group={ 716 + top:entry.rect.top, 717 + entries:[] 718 + }; 719 + groups.push(group); 720 + } 721 + 722 + group.entries.push(entry); 723 + }); 724 + 725 + return groups; 373 373 } 374 374 375 - function horizontalLayout(parent){ 376 - if(!visible(parent))return false; 377 - var s=getComputedStyle(parent); 378 - if(s.display==="grid"||s.display==="inline-grid")return true; 379 - if(s.display==="flex"||s.display==="inline-flex"){ 380 - return s.flexDirection==="row"||s.flexDirection==="row-reverse"; 728 + function validRow(group){ 729 + if(group.entries.length<2)return false; 730 + 731 + var lefts= 732 + group.entries 733 + .map(function(e){return e.rect.left;}) 734 + .sort(function(a,b){return a-b;}); 735 + 736 + if( 737 + lefts[lefts.length-1]- 738 + lefts[0]< 739 + 80 740 + ){ 741 + return false; 381 381 } 382 - return false; 743 + 744 + var widths= 745 + group.entries 746 + .map(function(e){return e.rect.width;}) 747 + .filter(function(w){return w>0;}); 748 + 749 + if(widths.length<2)return false; 750 + 751 + var minW= 752 + Math.min.apply(Math,widths); 753 + 754 + var maxW= 755 + Math.max.apply(Math,widths); 756 + 757 + return ( 758 + maxW/ 759 + Math.max(1,minW)<= 760 + 1.9 761 + ); 383 383 } 384 384 385 - function rowGroups(entries){ 386 - var groups=[]; 387 - entries.slice().sort(function(a,b){ 388 - return a.rect.top-b.rect.top||a.rect.left-b.rect.left; 389 - }).forEach(function(entry){ 390 - var group=null; 391 - for(var i=0;i<groups.length;i++){ 392 - if(Math.abs(groups[i].top-entry.rect.top)<=ROW_TOLERANCE){ 393 - group=groups[i]; 394 - break; 764 + /* ---------- Known ARSN first section bars ---------- */ 765 + 766 + function knownBar(el){ 767 + var text= 768 + normalizeText( 769 + el.textContent 770 + ); 771 + 772 + return ( 773 + text==="HIER STARTEN"|| 774 + text==="ORGANISIEREN & DOKUMENTIEREN"|| 775 + text==="ENTSCHEIDEN"|| 776 + text==="START HERE"|| 777 + text==="GET STARTED"|| 778 + text==="ORGANISE & DOCUMENT"|| 779 + text==="ORGANIZE & DOCUMENT"|| 780 + text==="DECIDE" 781 + ); 782 + } 783 + 784 + function findKnownBar(card){ 785 + var cardRect= 786 + card.getBoundingClientRect(); 787 + 788 + var rows= 789 + Array.from( 790 + card.querySelectorAll( 791 + "div,p,span,strong,h3,h4,h5,h6" 792 + ) 793 + ) 794 + .filter(function(el){ 795 + if(!visible(el,20,6))return false; 796 + if(!knownBar(el))return false; 797 + 798 + var r=el.getBoundingClientRect(); 799 + 800 + var rel= 801 + r.top- 802 + cardRect.top; 803 + 804 + return ( 805 + rel>=35&& 806 + rel<= 807 + cardRect.height*.75 808 + ); 809 + }) 810 + .sort(function(a,b){ 811 + return ( 812 + a.getBoundingClientRect().top- 813 + b.getBoundingClientRect().top 814 + ); 815 + }); 816 + 817 + return rows[0]||null; 818 + } 819 + 820 + function alignKnownBars(cards){ 821 + var rows= 822 + cards.map(function(card){ 823 + var bar= 824 + findKnownBar(card); 825 + 826 + if(!bar)return null; 827 + 828 + var cr= 829 + card.getBoundingClientRect(); 830 + 831 + var br= 832 + bar.getBoundingClientRect(); 833 + 834 + return { 835 + bar:bar, 836 + relativeTop: 837 + br.top- 838 + cr.top 839 + }; 840 + }); 841 + 842 + if( 843 + rows.some(function(row){ 844 + return !row; 845 + }) 846 + ){ 847 + return false; 848 + } 849 + 850 + var target= 851 + Math.max.apply( 852 + Math, 853 + rows.map(function(row){ 854 + return row.relativeTop; 855 + }) 856 + ); 857 + 858 + rows.forEach(function(row){ 859 + var delta= 860 + target- 861 + row.relativeTop; 862 + 863 + if(delta<=1)return; 864 + 865 + saveOriginal( 866 + row.bar, 867 + originalMarginTop, 868 + "margin-top" 869 + ); 870 + 871 + var current= 872 + num( 873 + getComputedStyle( 874 + row.bar 875 + ).marginTop 876 + ); 877 + 878 + row.bar.style.setProperty( 879 + "margin-top", 880 + ( 881 + current+ 882 + delta 883 + )+"px" 884 + ); 885 + 886 + row.bar.setAttribute( 887 + "data-sn-first-section-aligned", 888 + "7" 889 + ); 890 + 891 + sectionManaged.add( 892 + row.bar 893 + ); 894 + }); 895 + 896 + return true; 897 + } 898 + 899 + /* ---------- Generic first content after heading ---------- */ 900 + 901 + function heading(card){ 902 + var cr= 903 + card.getBoundingClientRect(); 904 + 905 + var rows= 906 + Array.from( 907 + card.querySelectorAll( 908 + "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]" 909 + ) 910 + ) 911 + .filter(function(el){ 912 + if(!visible(el,20,8))return false; 913 + 914 + var r=el.getBoundingClientRect(); 915 + 916 + var rel= 917 + r.top- 918 + cr.top; 919 + 920 + return ( 921 + rel>=0&& 922 + rel<= 923 + Math.min( 924 + 160, 925 + cr.height*.45 926 + ) 927 + ); 928 + }) 929 + .sort(function(a,b){ 930 + return ( 931 + a.getBoundingClientRect().top- 932 + b.getBoundingClientRect().top 933 + ); 934 + }); 935 + 936 + return rows[0]||null; 937 + } 938 + 939 + function firstContent(card,h){ 940 + if(!h)return null; 941 + 942 + var cr= 943 + card.getBoundingClientRect(); 944 + 945 + var hr= 946 + h.getBoundingClientRect(); 947 + 948 + var rows= 949 + Array.from( 950 + card.querySelectorAll( 951 + "p,div,ul,ol,dl,blockquote" 952 + ) 953 + ) 954 + .filter(function(el){ 955 + if( 956 + el===h|| 957 + h.contains(el)|| 958 + el.contains(h) 959 + ){ 960 + return false; 395 395 } 396 - } 397 - if(!group){ 398 - group={top:entry.rect.top,entries:[]}; 399 - groups.push(group); 400 - } 401 - group.entries.push(entry); 962 + 963 + if(!visible(el,30,8))return false; 964 + 965 + var text= 966 + String(el.textContent||"") 967 + .replace(/\s+/g," ") 968 + .trim(); 969 + 970 + if(text.length<3)return false; 971 + 972 + var r=el.getBoundingClientRect(); 973 + 974 + if( 975 + r.top< 976 + hr.bottom-1 977 + ){ 978 + return false; 979 + } 980 + 981 + if( 982 + r.top-cr.top> 983 + Math.min( 984 + 280, 985 + cr.height*.65 986 + ) 987 + ){ 988 + return false; 989 + } 990 + 991 + if( 992 + r.height> 993 + cr.height*.58 994 + ){ 995 + return false; 996 + } 997 + 998 + return true; 999 + }) 1000 + .sort(function(a,b){ 1001 + var ar= 1002 + a.getBoundingClientRect(); 1003 + 1004 + var br= 1005 + b.getBoundingClientRect(); 1006 + 1007 + return ( 1008 + ar.top-br.top|| 1009 + ar.height-br.height 1010 + ); 1011 + }); 1012 + 1013 + return rows[0]||null; 1014 + } 1015 + 1016 + function alignGeneric(cards){ 1017 + var rows= 1018 + cards.map(function(card){ 1019 + var h= 1020 + heading(card); 1021 + 1022 + var c= 1023 + firstContent( 1024 + card, 1025 + h 1026 + ); 1027 + 1028 + if(!h||!c)return null; 1029 + 1030 + var cr= 1031 + card.getBoundingClientRect(); 1032 + 1033 + var rr= 1034 + c.getBoundingClientRect(); 1035 + 1036 + return { 1037 + content:c, 1038 + relativeTop: 1039 + rr.top-cr.top 1040 + }; 1041 + }); 1042 + 1043 + if( 1044 + rows.some(function(row){ 1045 + return !row; 1046 + }) 1047 + ){ 1048 + return false; 1049 + } 1050 + 1051 + var target= 1052 + Math.max.apply( 1053 + Math, 1054 + rows.map(function(row){ 1055 + return row.relativeTop; 1056 + }) 1057 + ); 1058 + 1059 + rows.forEach(function(row){ 1060 + var delta= 1061 + target- 1062 + row.relativeTop; 1063 + 1064 + if(delta<=1)return; 1065 + 1066 + saveOriginal( 1067 + row.content, 1068 + originalMarginTop, 1069 + "margin-top" 1070 + ); 1071 + 1072 + var current= 1073 + num( 1074 + getComputedStyle( 1075 + row.content 1076 + ).marginTop 1077 + ); 1078 + 1079 + row.content.style.setProperty( 1080 + "margin-top", 1081 + ( 1082 + current+ 1083 + delta 1084 + )+"px" 1085 + ); 1086 + 1087 + row.content.setAttribute( 1088 + "data-sn-first-content-aligned", 1089 + "7" 1090 + ); 1091 + 1092 + contentManaged.add( 1093 + row.content 1094 + ); 402 402 }); 403 - return groups; 1096 + 1097 + return true; 404 404 } 405 405 406 - function ru n(){407 - rese t();1100 + function applyRow(group){ 1101 + if(!validRow(group))return false; 408 408 409 - if(window.innerWidth<=MOBILE_MAX)return; 1103 + var cards=[]; 1104 + var seen=new Set(); 410 410 411 - var parents=Array.from(root.querySelectorAll("*")).filter(function(el){ 412 - return el.children&&el.children.length>=2&&horizontalLayout(el); 1106 + group.entries.forEach(function(entry){ 1107 + if(!seen.has(entry.target)){ 1108 + seen.add(entry.target); 1109 + cards.push(entry.target); 1110 + } 413 413 }); 414 414 415 - parents.forEach(function(parent){ 416 - var entries=[]; 1113 + if(cards.length<2)return false; 417 417 418 - Array.from(parent.children).forEach(function(child){ 419 - if(!visible(child))return; 420 - var target=pickTarget(child); 421 - if(!target)return; 422 - entries.push({ 423 - target:target, 424 - rect:target.getBoundingClientRect() 425 - }); 426 - }); 1115 + if( 1116 + !alignKnownBars(cards) 1117 + ){ 1118 + alignGeneric(cards); 1119 + } 427 427 428 - if(entries.length<2)return;1121 + var maxHeight=0; 429 429 430 - rowGroups(entries).forEach(function(group){ 431 - if(group.entries.length<2)return; 1123 + cards.forEach(function(card){ 1124 + maxHeight= 1125 + Math.max( 1126 + maxHeight, 1127 + card.getBoundingClientRect().height 1128 + ); 1129 + }); 432 432 433 - var lefts=group.entries.map(function(e){return e.rect.left;}).sort(function(a,b){return a-b;}); 434 - if(lefts[lefts.length-1]-lefts[0]<80)return; 1131 + maxHeight= 1132 + Math.ceil( 1133 + maxHeight 1134 + ); 435 435 436 - var targets=[]; 437 - var seen=new Set(); 1136 + if(maxHeight<MIN_H)return false; 438 438 439 - group.entries.forEach(function(e){ 440 - if(!seen.has(e.target)){ 441 - seen.add(e.target); 442 - targets.push(e.target); 443 - } 1138 + cards.forEach(function(card){ 1139 + saveOriginal( 1140 + card, 1141 + originalMinHeight, 1142 + "min-height" 1143 + ); 1144 + 1145 + card.style.setProperty( 1146 + "min-height", 1147 + maxHeight+"px" 1148 + ); 1149 + 1150 + card.setAttribute( 1151 + "data-sn-equal-height-managed", 1152 + "7" 1153 + ); 1154 + 1155 + heightManaged.add(card); 1156 + }); 1157 + 1158 + return true; 1159 + } 1160 + 1161 + function calculate(force){ 1162 + if(applying)return; 1163 + 1164 + var width= 1165 + Math.round( 1166 + window.innerWidth 1167 + ); 1168 + 1169 + var meaningful= 1170 + lastWidth<0|| 1171 + Math.abs( 1172 + width- 1173 + lastWidth 1174 + )>= 1175 + MIN_WIDTH_CHANGE; 1176 + 1177 + if( 1178 + hasApplied&& 1179 + !force&& 1180 + !meaningful 1181 + ){ 1182 + return; 1183 + } 1184 + 1185 + applying=true; 1186 + 1187 + try{ 1188 + harmoniseCustomCallouts(); 1189 + 1190 + if(width<=MOBILE_MAX){ 1191 + if(hasApplied){ 1192 + resetRuntime(); 1193 + } 1194 + 1195 + hasApplied=false; 1196 + lastWidth=width; 1197 + return; 1198 + } 1199 + 1200 + if(hasApplied){ 1201 + resetRuntime(); 1202 + } 1203 + 1204 + var parents= 1205 + Array.from( 1206 + root.querySelectorAll("*") 1207 + ) 1208 + .filter(function(parent){ 1209 + return ( 1210 + visible( 1211 + parent, 1212 + MIN_W, 1213 + MIN_H 1214 + )&& 1215 + parent.children&& 1216 + parent.children.length>=2&& 1217 + parent.children.length<= 1218 + MAX_PARENT_CHILDREN 1219 + ); 444 444 }); 445 445 446 - if(targets.length<2)return; 1222 + var touched= 1223 + new Set(); 447 447 448 - var max=0; 449 - targets.forEach(function(el){ 450 - max=Math.max(max,el.getBoundingClientRect().height); 1225 + parents.forEach(function(parent){ 1226 + var entries=[]; 1227 + 1228 + Array.from( 1229 + parent.children 1230 + ).forEach(function(child){ 1231 + if( 1232 + !visible( 1233 + child, 1234 + MIN_W, 1235 + MIN_H 1236 + ) 1237 + ){ 1238 + return; 1239 + } 1240 + 1241 + var target= 1242 + pickTarget(child); 1243 + 1244 + if(!target)return; 1245 + 1246 + entries.push({ 1247 + target:target, 1248 + rect: 1249 + target.getBoundingClientRect() 1250 + }); 451 451 }); 452 452 453 - max=Math.ceil(max); 454 - if(max<MIN_H)return; 1253 + groupRows( 1254 + entries 1255 + ).forEach(function(group){ 1256 + if(!validRow(group))return; 455 455 456 - targets.forEach(function(el){ 457 - el.style.setProperty("min-height",max+"px"); 458 - el.setAttribute("data-sn-equal-height-managed","1"); 459 - managed.add(el); 1258 + var targets= 1259 + group.entries.map(function(entry){ 1260 + return entry.target; 1261 + }); 1262 + 1263 + if( 1264 + !targets.some(function(el){ 1265 + return !touched.has(el); 1266 + }) 1267 + ){ 1268 + return; 1269 + } 1270 + 1271 + if(applyRow(group)){ 1272 + targets.forEach(function(el){ 1273 + touched.add(el); 1274 + }); 1275 + } 460 460 }); 461 461 }); 462 - }); 1278 + 1279 + lastWidth=width; 1280 + hasApplied=true; 1281 + }finally{ 1282 + applying=false; 1283 + } 463 463 } 464 464 465 - function schedule(){ 466 - if(raf)cancelAnimationFrame(raf); 467 - raf=requestAnimationFrame(function(){ 468 - raf=requestAnimationFrame(function(){ 469 - raf=0; 470 - run(); 471 - }); 472 - }); 1286 + function resize(){ 1287 + if(resizeTimer){ 1288 + clearTimeout( 1289 + resizeTimer 1290 + ); 1291 + } 1292 + 1293 + resizeTimer= 1294 + setTimeout( 1295 + function(){ 1296 + resizeTimer=0; 1297 + calculate(false); 1298 + }, 1299 + RESIZE_DEBOUNCE 1300 + ); 473 473 } 474 474 475 - addEventListener("resize",schedule,{passive:true}); 476 - addEventListener("load",schedule,{once:true}); 1303 + function waitImages(){ 1304 + var images= 1305 + Array.from( 1306 + root.querySelectorAll("img") 1307 + ); 477 477 478 - root.addEventListener("click",function(){ 479 - setTimeout(schedule,0); 480 - },true); 1309 + return Promise.all( 1310 + images.map(function(img){ 1311 + if(img.complete){ 1312 + return Promise.resolve(); 1313 + } 481 481 482 - if(document.fonts&&document.fonts.ready){ 483 - document.fonts.ready.then(schedule); 1315 + return new Promise(function(resolve){ 1316 + var done=function(){ 1317 + resolve(); 1318 + }; 1319 + 1320 + img.addEventListener( 1321 + "load", 1322 + done, 1323 + {once:true} 1324 + ); 1325 + 1326 + img.addEventListener( 1327 + "error", 1328 + done, 1329 + {once:true} 1330 + ); 1331 + }); 1332 + }) 1333 + ); 484 484 } 485 485 486 - schedule(); 487 - setTimeout(schedule,250); 488 - setTimeout(schedule,900); 1336 + async function initial(){ 1337 + if( 1338 + document.readyState!== 1339 + "complete" 1340 + ){ 1341 + await new Promise(function(resolve){ 1342 + addEventListener( 1343 + "load", 1344 + resolve, 1345 + {once:true} 1346 + ); 1347 + }); 1348 + } 1349 + 1350 + if( 1351 + document.fonts&& 1352 + document.fonts.ready 1353 + ){ 1354 + try{ 1355 + await document.fonts.ready; 1356 + }catch(error){} 1357 + } 1358 + 1359 + await waitImages(); 1360 + 1361 + // Exactly one initial layout calculation. 1362 + calculate(true); 1363 + } 1364 + 1365 + addEventListener( 1366 + "resize", 1367 + resize, 1368 + {passive:true} 1369 + ); 1370 + 1371 + initial(); 489 489 })(); 490 490 </script> 491 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 492 -{{/html}} 493 493 1375 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1376 +{{/html}}\n