Browse Source

improve level calculation

subDesTagesMitExtraKaese 2 years ago
parent
commit
97eec83d81
2 changed files with 45 additions and 13 deletions
  1. 35 9
      static/stammbaum/main.js
  2. 10 4
      static/stammbaum/tree.js

+ 35 - 9
static/stammbaum/main.js

@@ -19,9 +19,9 @@ window.onload = function() {
       id: p[0],
       name: p[1],
       parent_id: p[2],
-      birth_date: p[3],
+      birth_date: p[3] ? new Date(p[3]) : null,
       birth_town: p[4],
-      death_date: p[5],
+      death_date: p[5] ? new Date(p[5]) : null,
       death_town: p[6],
       comment: p[7],
       image: p[8],
@@ -116,14 +116,39 @@ window.onload = function() {
   }
   $('#loader').hide();
   
+  // define levels by the maximum birth date in that level 
+  function calculateLevels(personList) {
+    personList = personList.concat().sort((a, b) => {
+      const dateA = a.birth_date || a.death_date
+      const dateB = b.birth_date || b.death_date
+      return dateA - dateB
+    })
+    let levels = []
+    let currentPersons = []
+    for(const person of personList) {
+      const date = person.birth_date || person.death_date
+      if(!date || !person.hasCard)
+        continue
+      if(person.parent && currentPersons.find(p => person.parent.id === p.id)) {
+        levels.push(date - 1)
+        currentPersons = [person]
+      } else {
+        currentPersons.push(person)
+      }
+    }
+    levels.push(+personList[personList.length - 1].birth_date || +personList[personList.length - 1].death_date)
+    return levels
+  }
+  const levels = calculateLevels(persons)
   /**
    * calculate position of cards
    * @param {*} personList current persons
+   * @param {*} levels reference to levels
    * @param {*} level row of the current card
    * @param {*} accX maximum X positions per layer
    * @returns width of the tree
    */
-  function assignCoords(personList, level=0, accX=[0]) {
+  function assignCoords(personList, levels, level=0, accX=[0]) {
     
     personList = personList.filter(p => p.hasCard);
     const margin = 20;
@@ -134,8 +159,9 @@ window.onload = function() {
       const person = personList[j];
 
       // set y
-      person.level = level;
-      if(person.partner && person.partner.level > level) {
+      const date = person.birth_date || person.death_date
+      person.level = Math.max(level, levels.findIndex(l => l >= +date && date != null));
+      if(person.partner && person.partner.level > person.level) {
         person.level = person.partner.level;
       }
       person.y = person.level * (tree.cardHeight + 40);
@@ -149,7 +175,7 @@ window.onload = function() {
 
       const width = tree.cardWidth * (person.partner == null ? 1 : 2);
       const origAccX = accX.slice();
-      const subWidth = assignCoords(person.children, person.level + 1, accX);
+      const subWidth = assignCoords(person.children, levels, person.level + 1, accX);
 
       const requiredForSiblings = personList.slice(j + 1).reduce((acc, p) => acc + tree.cardWidth * (person.partner == null ? 1 : 2) + margin, 0);
       const remainingWidthAboveChildren = accX[person.level+1] - accX[person.level];
@@ -170,13 +196,13 @@ window.onload = function() {
         person.x = accX[person.level] + margin;
         for (var i = person.level + 1; i < accX.length; i++)
           accX[i] = Math.max(origAccX[i], person.x + width/2 - subWidth/2 - margin);
-        assignCoords(person.children, person.level + 1, accX);
+        assignCoords(person.children, levels, person.level + 1, accX);
       } else {
         // we need to move children under this card to avoid overlap
         person.x = accX[person.level] + margin;
         for (var i = person.level + 1; i < accX.length; i++)
           accX[i] = Math.max(origAccX[i], person.x + width - subWidth - margin);
-        assignCoords(person.children, person.level + 1, accX);
+        assignCoords(person.children, levels, person.level + 1, accX);
         // center this node again
         person.x = Math.max(origAccX[person.level] + margin, accX[person.level + 1] - subWidth / 2 - width / 2);
 
@@ -193,7 +219,7 @@ window.onload = function() {
     }
     return endX - startX;
   }
-  assignCoords(persons.filter(p => p.parent_id == null));
+  assignCoords(persons.filter(p => p.parent_id == null), levels);
   
 
   // draw links

+ 10 - 4
static/stammbaum/tree.js

@@ -109,9 +109,9 @@ class SVGTree {
       <tspan x="${this.cardWidth*.5}" dy="1.2em">${name[2]}</tspan>
     </text>
     <text y="210" text-anchor="middle" class="birth">
-      <tspan class="birth" dy="0" x="${this.cardWidth*.5}">${person.birth_date ? '*' + person.birth_date : ''}</tspan>
+      <tspan class="birth" dy="0" x="${this.cardWidth*.5}">${person.birth_date ? '*' + formatDate(person.birth_date) : ''}</tspan>
       <tspan class="birth-loc" dy="1.2em" x="${this.cardWidth*.5}">${person.birth_town || ''}</tspan>
-      <tspan class="death" dy="1.2em" x="${this.cardWidth*.5}">${person.death_date ? '&dagger;' + person.death_date : ''}</tspan>
+      <tspan class="death" dy="1.2em" x="${this.cardWidth*.5}">${person.death_date ? '&dagger;' + formatDate(person.death_date) : ''}</tspan>
       <tspan class="death-loc" dy="1.2em" x="${this.cardWidth*.5}">${person.death_town || ''}</tspan>
     </text>
     <text y="272">
@@ -129,9 +129,9 @@ class SVGTree {
         <tspan x="${this.cardWidth*1.5}" dy="1.2em">${partner[2]}</tspan>
       </text>
       <text y="210" text-anchor="middle" class="birth">
-        <tspan class="birth" dy="0" x="${this.cardWidth*1.5}">${person.partner.birth_date ? '*' + person.partner.birth_date : ''}</tspan>
+        <tspan class="birth" dy="0" x="${this.cardWidth*1.5}">${person.partner.birth_date ? '*' + formatDate(person.partner.birth_date) : ''}</tspan>
         <tspan class="birth-loc" dy="1.2em" x="${this.cardWidth * 1.5}">${person.partner.birth_town || ''}</tspan>
-        <tspan class="death" dy="1.2em" x="${this.cardWidth*1.5}">${person.partner.death_date ? '&dagger;' + person.partner.death_date : ''}</tspan>
+        <tspan class="death" dy="1.2em" x="${this.cardWidth*1.5}">${person.partner.death_date ? '&dagger;' + formatDate(person.partner.death_date) : ''}</tspan>
         <tspan class="death-loc" dy="1.2em" x="${this.cardWidth * 1.5}">${person.partner.death_town || ''}</tspan>
       </text>
       `;
@@ -233,3 +233,9 @@ function wordWrap(str = "", maxWidth, lines) {
 function html2svg(str) {
   return str.replace("<u>", "*").replace("</u>", "*").replace(/<span .*>|<\/span>/, '');
 }
+function formatDate(date) {
+  if(date == null)
+    return "";
+  const d = new Date(date);
+  return d.toLocaleDateString();
+}