Changes for page Plan Your Data Management

Last modified by Veronika Kocher on Friday, 04 Sep 2026 14:45

From version 4.9
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:34
Change comment: There is no comment for this version
To version 4.8
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:18
Change comment: There is no comment for this version

Summary

Details

Page properties
Content
... ... @@ -259,22 +259,20 @@
259 259  
260 260  {{html clean="false"}}
261 261  <!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
262 -<style data-sn-horizontal-box-harmonizer="4">
263 -[data-sn-equal-height-managed],
264 -[data-sn-first-section-aligned]{
265 - box-sizing:border-box;
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}
266 266  }
267 267  </style>
268 -<script data-sn-horizontal-box-harmonizer="4">
268 +<script data-sn-horizontal-box-harmonizer="1">
269 269  (function(){
270 270   "use strict";
271 271  
272 272   var MOBILE_MAX=767;
273 - var ROW_TOLERANCE=6;
273 + var ROW_TOLERANCE=4;
274 274   var MIN_W=150;
275 275   var MIN_H=36;
276 - var MAX_PARENT_CHILDREN=16;
277 - var SEARCH_DEPTH=5;
278 278  
279 279   var root=
280 280   document.getElementById("xwikicontent")||
... ... @@ -284,10 +284,7 @@
284 284  
285 285   if(!root)return;
286 286  
287 - var heightManaged=new Set();
288 - var sectionManaged=new Set();
289 - var originalMinHeight=new WeakMap();
290 - var originalMarginTop=new WeakMap();
285 + var managed=new Set();
291 291   var raf=0;
292 292  
293 293   function num(v){
... ... @@ -295,181 +295,64 @@
295 295   return Number.isFinite(n)?n:0;
296 296   }
297 297  
298 - function visible(el,minW,minH){
293 + function visible(el){
299 299   if(!el||el.nodeType!==1)return false;
300 -
301 301   var s=getComputedStyle(el);
302 -
303 - if(
304 - s.display==="none"||
305 - s.visibility==="hidden"||
306 - Number(s.opacity)===0
307 - ){
308 - return false;
309 - }
310 -
296 + if(s.display==="none"||s.visibility==="hidden"||Number(s.opacity)===0)return false;
311 311   var r=el.getBoundingClientRect();
312 -
313 - return (
314 - r.width>=(minW||1)&&
315 - r.height>=(minH||1)
316 - );
298 + return r.width>=MIN_W&&r.height>=MIN_H;
317 317   }
318 318  
319 319   function excluded(el){
320 - return (
321 - !el.matches||
322 - el.matches(
323 - "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]"
324 - )
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]"
325 325   );
326 326   }
327 327  
328 328   function namedLikeBox(el){
329 - var c=
330 - typeof el.className==="string"
331 - ? el.className
332 - : "";
333 -
334 - return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c);
308 + var c=typeof el.className==="string"?el.className:"";
309 + return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c);
335 335   }
336 336  
337 337   function boxLike(el){
338 - if(!visible(el,MIN_W,MIN_H)||excluded(el))return false;
339 -
313 + if(!visible(el)||excluded(el))return false;
340 340   var s=getComputedStyle(el);
341 341   var r=el.getBoundingClientRect();
342 -
343 343   var border=
344 - num(s.borderTopWidth)+
345 - num(s.borderRightWidth)+
346 - num(s.borderBottomWidth)+
347 - num(s.borderLeftWidth);
348 -
317 + num(s.borderTopWidth)+num(s.borderRightWidth)+
318 + num(s.borderBottomWidth)+num(s.borderLeftWidth);
349 349   var radius=Math.max(
350 - num(s.borderTopLeftRadius),
351 - num(s.borderTopRightRadius),
352 - num(s.borderBottomLeftRadius),
353 - num(s.borderBottomRightRadius)
320 + num(s.borderTopLeftRadius),num(s.borderTopRightRadius),
321 + num(s.borderBottomLeftRadius),num(s.borderBottomRightRadius)
354 354   );
355 -
356 - var bg=
357 - s.backgroundColor&&
358 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
359 - s.backgroundColor!=="transparent";
360 -
361 - var shadow=
362 - s.boxShadow&&
363 - s.boxShadow!=="none";
364 -
365 - return (
366 - namedLikeBox(el)||
367 - border>=1||
368 - (bg&&radius>=3)||
369 - (shadow&&r.width>=180)
370 - );
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);
371 371   }
372 372  
373 - function saveOriginal(el,map,property){
374 - if(map.has(el))return;
375 -
376 - map.set(el,{
377 - value:el.style.getPropertyValue(property),
378 - priority:el.style.getPropertyPriority(property)
379 - });
380 - }
381 -
382 - function restoreOriginal(el,map,property){
383 - var original=map.get(el);
384 -
385 - if(original&&original.value){
386 - el.style.setProperty(
387 - property,
388 - original.value,
389 - original.priority||""
390 - );
391 - }else{
392 - el.style.removeProperty(property);
393 - }
394 - }
395 -
396 - function reset(){
397 - heightManaged.forEach(function(el){
398 - restoreOriginal(
399 - el,
400 - originalMinHeight,
401 - "min-height"
402 - );
403 -
404 - el.removeAttribute(
405 - "data-sn-equal-height-managed"
406 - );
407 - });
408 -
409 - sectionManaged.forEach(function(el){
410 - restoreOriginal(
411 - el,
412 - originalMarginTop,
413 - "margin-top"
414 - );
415 -
416 - el.removeAttribute(
417 - "data-sn-first-section-aligned"
418 - );
419 - });
420 -
421 - heightManaged.clear();
422 - sectionManaged.clear();
423 - }
424 -
425 425   function pickTarget(child){
426 - if(!visible(child,MIN_W,MIN_H))return null;
329 + if(!visible(child))return null;
330 + if(boxLike(child))return child;
427 427  
428 - if(boxLike(child)){
429 - return child;
430 - }
431 -
432 432   var cr=child.getBoundingClientRect();
433 433   var q=[];
434 -
435 435   Array.from(child.children||[]).forEach(function(el){
436 436   q.push({el:el,depth:1});
437 437   });
438 438  
439 - var best=null;
440 - var bestScore=-Infinity;
338 + var best=null,bestScore=-1;
441 441  
442 442   while(q.length){
443 443   var item=q.shift();
444 444   var el=item.el;
343 + if(!visible(el))continue;
445 445  
446 - if(!visible(el,MIN_W,MIN_H))continue;
447 -
448 448   var r=el.getBoundingClientRect();
449 449  
450 - if(
451 - r.width>=cr.width*.68&&
452 - boxLike(el)
453 - ){
454 - var widthFit=
455 - 1-Math.min(
456 - 1,
457 - Math.abs(cr.width-r.width)/
458 - Math.max(1,cr.width)
459 - );
460 -
461 - var topFit=
462 - 1-Math.min(
463 - 1,
464 - Math.abs(cr.top-r.top)/100
465 - );
466 -
467 - var score=
468 - widthFit*6+
469 - topFit*3+
470 - Math.min(r.height,900)/450+
471 - Math.min(r.width*r.height,900000)/900000;
472 -
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;
473 473   if(score>bestScore){
474 474   best=el;
475 475   bestScore=score;
... ... @@ -476,12 +476,9 @@
476 476   }
477 477   }
478 478  
479 - if(item.depth<SEARCH_DEPTH){
357 + if(item.depth<3){
480 480   Array.from(el.children||[]).forEach(function(next){
481 - q.push({
482 - el:next,
483 - depth:item.depth+1
484 - });
359 + q.push({el:next,depth:item.depth+1});
485 485   });
486 486   }
487 487   }
... ... @@ -489,392 +489,61 @@
489 489   return best;
490 490   }
491 491  
492 - function groupsByVisualRow(entries){
493 - var groups=[];
494 -
495 - entries
496 - .slice()
497 - .sort(function(a,b){
498 - return (
499 - a.rect.top-b.rect.top||
500 - a.rect.left-b.rect.left
501 - );
502 - })
503 - .forEach(function(entry){
504 - var group=null;
505 -
506 - for(var i=0;i<groups.length;i++){
507 - if(
508 - Math.abs(
509 - groups[i].top-
510 - entry.rect.top
511 - )<=ROW_TOLERANCE
512 - ){
513 - group=groups[i];
514 - break;
515 - }
516 - }
517 -
518 - if(!group){
519 - group={
520 - top:entry.rect.top,
521 - entries:[]
522 - };
523 - groups.push(group);
524 - }
525 -
526 - group.entries.push(entry);
527 - });
528 -
529 - return groups;
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();
530 530   }
531 531  
532 - function validHorizontalGroup(group){
533 - if(group.entries.length<2)return false;
534 -
535 - var lefts=
536 - group.entries
537 - .map(function(e){return e.rect.left;})
538 - .sort(function(a,b){return a-b;});
539 -
540 - if(
541 - lefts[lefts.length-1]-
542 - lefts[0]<
543 - 80
544 - ){
545 - return false;
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";
546 546   }
547 -
548 - var widths=
549 - group.entries
550 - .map(function(e){return e.rect.width;})
551 - .filter(function(w){return w>0;});
552 -
553 - if(widths.length<2)return false;
554 -
555 - var minWidth=Math.min.apply(Math,widths);
556 - var maxWidth=Math.max.apply(Math,widths);
557 -
558 - return (
559 - maxWidth/
560 - Math.max(1,minWidth)<=
561 - 1.9
562 - );
382 + return false;
563 563   }
564 564  
565 - function normalizeText(text){
566 - return String(text||"")
567 - .replace(/s+/g," ")
568 - .trim()
569 - .toUpperCase();
570 - }
571 -
572 - function exactKnownFirstSection(el){
573 - var text=normalizeText(el.textContent);
574 -
575 - return (
576 - text==="HIER STARTEN"||
577 - text==="ORGANISIEREN & DOKUMENTIEREN"||
578 - text==="ENTSCHEIDEN"||
579 - text==="START HERE"||
580 - text==="GET STARTED"||
581 - text==="ORGANISE & DOCUMENT"||
582 - text==="ORGANIZE & DOCUMENT"||
583 - text==="DECIDE"
584 - );
585 - }
586 -
587 - function visuallyFirstSectionBar(card){
588 - var cardRect=card.getBoundingClientRect();
589 - var candidates=[];
590 -
591 - Array.from(
592 - card.querySelectorAll(
593 - "div,p,span,strong,h3,h4,h5,h6"
594 - )
595 - ).forEach(function(el){
596 - if(!visible(el,20,6))return;
597 - if(excluded(el))return;
598 -
599 - var r=el.getBoundingClientRect();
600 - var relativeTop=r.top-cardRect.top;
601 -
602 - if(
603 - relativeTop<45||
604 - relativeTop>cardRect.height*.72
605 - ){
606 - return;
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;
395 + }
607 607   }
608 -
609 - var widthRatio=
610 - r.width/
611 - Math.max(1,cardRect.width);
612 -
613 - if(
614 - widthRatio<.55||
615 - widthRatio>1.05||
616 - r.height>54
617 - ){
618 - return;
397 + if(!group){
398 + group={top:entry.rect.top,entries:[]};
399 + groups.push(group);
619 619   }
620 -
621 - var text=normalizeText(el.textContent);
622 -
623 - if(
624 - text.length<2||
625 - text.length>90
626 - ){
627 - return;
628 - }
629 -
630 - var style=getComputedStyle(el);
631 -
632 - var bg=
633 - style.backgroundColor&&
634 - style.backgroundColor!=="rgba(0, 0, 0, 0)"&&
635 - style.backgroundColor!=="transparent";
636 -
637 - var border=
638 - num(style.borderTopWidth)+
639 - num(style.borderRightWidth)+
640 - num(style.borderBottomWidth)+
641 - num(style.borderLeftWidth);
642 -
643 - var mostlyUpper=
644 - text.length>=3&&
645 - text===text.toUpperCase();
646 -
647 - var exact=exactKnownFirstSection(el);
648 -
649 - var score=
650 - (exact?20:0)+
651 - (bg?6:0)+
652 - (border>=1?2:0)+
653 - (mostlyUpper?4:0)+
654 - (num(style.fontWeight)>=600?1:0);
655 -
656 - if(score>=7){
657 - candidates.push({
658 - el:el,
659 - relativeTop:relativeTop,
660 - width:r.width,
661 - score:score
662 - });
663 - }
401 + group.entries.push(entry);
664 664   });
665 -
666 - if(!candidates.length)return null;
667 -
668 - candidates.sort(function(a,b){
669 - if(a.score!==b.score)return b.score-a.score;
670 - if(Math.abs(a.relativeTop-b.relativeTop)>3){
671 - return a.relativeTop-b.relativeTop;
672 - }
673 - return b.width-a.width;
674 - });
675 -
676 - // For exact known labels always prefer the earliest exact match.
677 - var exacts=candidates.filter(function(c){
678 - return exactKnownFirstSection(c.el);
679 - });
680 -
681 - if(exacts.length){
682 - exacts.sort(function(a,b){
683 - return a.relativeTop-b.relativeTop||b.width-a.width;
684 - });
685 - return exacts[0].el;
686 - }
687 -
688 - // Generic fallback: earliest high-confidence bar.
689 - candidates.sort(function(a,b){
690 - return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width;
691 - });
692 -
693 - return candidates[0].el;
403 + return groups;
694 694   }
695 695  
696 - function alignFirstSections(cards){
697 - var rows=
698 - cards.map(function(card){
699 - var bar=
700 - visuallyFirstSectionBar(card);
701 -
702 - if(!bar)return null;
703 -
704 - var cardRect=
705 - card.getBoundingClientRect();
706 -
707 - var barRect=
708 - bar.getBoundingClientRect();
709 -
710 - return {
711 - card:card,
712 - bar:bar,
713 - relativeTop:
714 - barRect.top-cardRect.top,
715 - label:
716 - normalizeText(bar.textContent)
717 - };
718 - });
719 -
720 - // Conservative: only align when every card in the horizontal row
721 - // has a reliable first section bar.
722 - if(
723 - rows.some(function(row){
724 - return !row;
725 - })
726 - ){
727 - return null;
728 - }
729 -
730 - var targetTop=
731 - Math.max.apply(
732 - Math,
733 - rows.map(function(row){
734 - return row.relativeTop;
735 - })
736 - );
737 -
738 - rows.forEach(function(row){
739 - var delta=
740 - targetTop-
741 - row.relativeTop;
742 -
743 - if(delta<=1)return;
744 -
745 - saveOriginal(
746 - row.bar,
747 - originalMarginTop,
748 - "margin-top"
749 - );
750 -
751 - var currentMargin=
752 - num(
753 - getComputedStyle(
754 - row.bar
755 - ).marginTop
756 - );
757 -
758 - row.bar.style.setProperty(
759 - "margin-top",
760 - (
761 - currentMargin+
762 - delta
763 - )+"px"
764 - );
765 -
766 - row.bar.setAttribute(
767 - "data-sn-first-section-aligned",
768 - "4"
769 - );
770 -
771 - sectionManaged.add(row.bar);
772 - });
773 -
774 - return {
775 - labels:
776 - rows.map(function(row){
777 - return row.label;
778 - }),
779 - targetRelativeTop:
780 - Math.round(targetTop)
781 - };
782 - }
783 -
784 - function applyGroup(group){
785 - if(!validHorizontalGroup(group)){
786 - return null;
787 - }
788 -
789 - var cards=[];
790 - var seen=new Set();
791 -
792 - group.entries.forEach(function(entry){
793 - if(!seen.has(entry.target)){
794 - seen.add(entry.target);
795 - cards.push(entry.target);
796 - }
797 - });
798 -
799 - if(cards.length<2)return null;
800 -
801 - var firstSection=
802 - alignFirstSections(cards);
803 -
804 - // The section alignment can change natural card heights.
805 - // Measure only afterwards.
806 - var maxHeight=0;
807 -
808 - cards.forEach(function(card){
809 - maxHeight=Math.max(
810 - maxHeight,
811 - card.getBoundingClientRect().height
812 - );
813 - });
814 -
815 - maxHeight=Math.ceil(maxHeight);
816 -
817 - if(maxHeight<MIN_H)return null;
818 -
819 - cards.forEach(function(card){
820 - saveOriginal(
821 - card,
822 - originalMinHeight,
823 - "min-height"
824 - );
825 -
826 - card.style.setProperty(
827 - "min-height",
828 - maxHeight+"px"
829 - );
830 -
831 - card.setAttribute(
832 - "data-sn-equal-height-managed",
833 - "4"
834 - );
835 -
836 - heightManaged.add(card);
837 - });
838 -
839 - return {
840 - cards:cards.length,
841 - height:maxHeight,
842 - firstSection:firstSection
843 - };
844 - }
845 -
846 846   function run(){
847 847   reset();
848 848  
849 - if(
850 - window.innerWidth<=MOBILE_MAX
851 - ){
852 - return;
853 - }
409 + if(window.innerWidth<=MOBILE_MAX)return;
854 854  
855 - var parents=
856 - Array.from(
857 - root.querySelectorAll("*")
858 - ).filter(function(parent){
859 - return (
860 - visible(parent,MIN_W,MIN_H)&&
861 - parent.children&&
862 - parent.children.length>=2&&
863 - parent.children.length<=MAX_PARENT_CHILDREN
864 - );
865 - });
411 + var parents=Array.from(root.querySelectorAll("*")).filter(function(el){
412 + return el.children&&el.children.length>=2&&horizontalLayout(el);
413 + });
866 866  
867 - var touched=new Set();
868 -
869 869   parents.forEach(function(parent){
870 870   var entries=[];
871 871  
872 872   Array.from(parent.children).forEach(function(child){
873 - if(!visible(child,MIN_W,MIN_H))return;
874 -
419 + if(!visible(child))return;
875 875   var target=pickTarget(child);
876 876   if(!target)return;
877 -
878 878   entries.push({
879 879   target:target,
880 880   rect:target.getBoundingClientRect()
... ... @@ -883,30 +883,37 @@
883 883  
884 884   if(entries.length<2)return;
885 885  
886 - groupsByVisualRow(entries).forEach(function(group){
887 - if(!validHorizontalGroup(group))return;
430 + rowGroups(entries).forEach(function(group){
431 + if(group.entries.length<2)return;
888 888  
889 - var signature=
890 - group.entries.map(function(entry){
891 - return entry.target;
892 - });
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;
893 893  
894 - if(
895 - !signature.some(function(el){
896 - return !touched.has(el);
897 - })
898 - ){
899 - return;
900 - }
436 + var targets=[];
437 + var seen=new Set();
901 901  
902 - var applied=
903 - applyGroup(group);
439 + group.entries.forEach(function(e){
440 + if(!seen.has(e.target)){
441 + seen.add(e.target);
442 + targets.push(e.target);
443 + }
444 + });
904 904  
905 - if(applied){
906 - signature.forEach(function(el){
907 - touched.add(el);
908 - });
909 - }
446 + if(targets.length<2)return;
447 +
448 + var max=0;
449 + targets.forEach(function(el){
450 + max=Math.max(max,el.getBoundingClientRect().height);
451 + });
452 +
453 + max=Math.ceil(max);
454 + if(max<MIN_H)return;
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);
460 + });
910 910   });
911 911   });
912 912   }
... ... @@ -913,7 +913,6 @@
913 913  
914 914   function schedule(){
915 915   if(raf)cancelAnimationFrame(raf);
916 -
917 917   raf=requestAnimationFrame(function(){
918 918   raf=requestAnimationFrame(function(){
919 919   raf=0;
... ... @@ -925,28 +925,17 @@
925 925   addEventListener("resize",schedule,{passive:true});
926 926   addEventListener("load",schedule,{once:true});
927 927  
928 - root.addEventListener(
929 - "click",
930 - function(){
931 - setTimeout(schedule,0);
932 - },
933 - true
934 - );
478 + root.addEventListener("click",function(){
479 + setTimeout(schedule,0);
480 + },true);
935 935  
936 - Array.from(root.querySelectorAll("img")).forEach(function(img){
937 - if(!img.complete){
938 - img.addEventListener("load",schedule,{once:true});
939 - }
940 - });
941 -
942 942   if(document.fonts&&document.fonts.ready){
943 943   document.fonts.ready.then(schedule);
944 944   }
945 945  
946 946   schedule();
947 - setTimeout(schedule,200);
948 - setTimeout(schedule,650);
949 - setTimeout(schedule,1400);
487 + setTimeout(schedule,250);
488 + setTimeout(schedule,900);
950 950  })();
951 951  </script>
952 952  <!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->