Web based family history software

file Question Age at event

  • godzil
  • godzil's Avatar Topic Author
  • Offline
  • New Member
  • New Member
More
2 months 1 day ago - 2 months 1 day ago #116610 by godzil
Age at event was created by godzil
Hi,
I recall there was porbably buil-it option do display individual age at event. Now i cant't find it in webtrees nor any module. 
I generated simple JS script pasted in Custom CSS and JS but wondering about another solution

if you want to use this script you need to translate it to your local language - i belive any AI will change phrases for you
Code:
<script> (function () {   'use strict';   if (window.__wtAgeAtEventInjected) return;   window.__wtAgeAtEventInjected = true;   const MONTHS = {     stycznia: 0, styczen: 0, styczeń: 0, styczniem: 0,     lutego: 1, luty: 1, lutym: 1,     marca: 2, marzec: 2, marcem: 2,     kwietnia: 3, kwiecien: 3, kwiecień: 3, kwietniem: 3,     maja: 4, maj: 4, majem: 4,     czerwca: 5, czerwiec: 5, czerwcem: 5,     lipca: 6, lipiec: 6, lipcem: 6,     sierpnia: 7, sierpien: 7, sierpień: 7, sierpniem: 7,     wrzesnia: 8, wrzesien: 8, września: 8, wrzesień: 8, wrzesniem: 8, wrześniem: 8,     pazdziernika: 9, pazdziernik: 9, października: 9, październik: 9, pazdziernikiem: 9, październikiem: 9,     listopada: 10, listopad: 10, listopadem: 10,     grudnia: 11, grudzien: 11, grudzień: 11, grudniem: 11   };   function normalize(text) {     return (text || '')       .toLowerCase()       .normalize('NFD')       .replace(/[\u0300-\u036f]/g, '')       .replace(/\u00a0/g, ' ')       .replace(/\s+/g, ' ')       .trim();   }   function parseExactPolishDate(text) {     const src = normalize(text).replace(/\*/g, '');     let m = src.match(/^(\d{1,2})\s+([\p{L}]+)\s+(\d{4})$/u);     if (m) {       const day = Number(m[1]);       const month = MONTHS[normalize(m[2])];       const year = Number(m[3]);       if (month !== undefined) return new Date(year, month, day);     }     m = src.match(/^([\p{L}]+)\s+(\d{4})$/u);     if (m) {       const month = MONTHS[normalize(m[1])];       const year = Number(m[2]);       if (month !== undefined) return new Date(year, month, 15);     }     m = src.match(/^(\d{4})$/);     if (m) return new Date(Number(m[1]), 6, 1);     return null;   }   function parseDateExpression(text) {     const src = normalize(text).replace(/\*/g, '');     let m;     m = src.match(/^(przed|bef|before)\s+(.+)$/);     if (m) {       const date = parseExactPolishDate(m[2]);       if (date) return { kind: 'before', date };     }     m = src.match(/^(po|aft|after)\s+(.+)$/);     if (m) {       const date = parseExactPolishDate(m[2]);       if (date) return { kind: 'after', date };     }     m = src.match(/^(okolo|około|abt|about|circa|ca\.?)\s+(.+)$/);     if (m) {       const date = parseExactPolishDate(m[2]);       if (date) return { kind: 'about', date };     }     m = src.match(/^(miedzy|między|pomiedzy|pomiędzy|bet|between)\s+(.+?)\s+(a|i|and)\s+(.+)$/);     if (m) {       const start = parseExactPolishDate(m[2]);       const end = parseExactPolishDate(m[4]);       if (start && end) return { kind: 'between', start, end };     }     m = src.match(/^(od|from)\s+(.+?)\s+(do|to)\s+(.+)$/);     if (m) {       const start = parseExactPolishDate(m[2]);       const end = parseExactPolishDate(m[4]);       if (start && end) return { kind: 'fromto', start, end };     }     const exact = parseExactPolishDate(src);     if (exact) return { kind: 'exact', date: exact };     return null;   }   function diffAge(birth, event) {     let years = event.getFullYear() - birth.getFullYear();     let months = event.getMonth() - birth.getMonth();     let days = event.getDate() - birth.getDate();     if (days < 0) {       months -= 1;       const prevMonthLastDay = new Date(event.getFullYear(), event.getMonth(), 0).getDate();       days += prevMonthLastDay;     }     if (months < 0) {       years -= 1;       months += 12;     }     return { years, months, days };   }   function diffDays(start, end) {     const oneDay = 24 * 60 * 60 * 1000;     const startDate = new Date(start.getFullYear(), start.getMonth(), start.getDate());     const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());     return Math.round((endDate - startDate) / oneDay);   }   function pluralDays(n) {     if (n === 1) return 'dzień';     return 'dni';   }   function formatExactAge(age, birthDate, eventDate) {     if (age.years < 0) return null;     if (age.years === 0 && age.months === 0) {       const days = diffDays(birthDate, eventDate);       if (days === 0) return 'w dniu urodzenia';       return `${days} ${pluralDays(days)}`;     }     if (age.years === 0) {       if (age.days > 0) return `${age.months} mies. ${age.days} ${pluralDays(age.days)}`;       return `${age.months} mies.`;     }     if (age.months === 0) {       if (age.days > 0) return `${age.years} l. ${age.days} ${pluralDays(age.days)}`;       return `${age.years} l.`;     }     if (age.days > 0) return `${age.years} l. ${age.months} mies. ${age.days} ${pluralDays(age.days)}`;     return `${age.years} l. ${age.months} mies.`;   }   function formatAgeFromExpression(birthDate, expr) {     if (!expr) return null;     if (expr.kind === 'exact') {       const value = formatExactAge(diffAge(birthDate, expr.date), birthDate, expr.date);       return value ? `wiek: ${value}` : null;     }     if (expr.kind === 'about') {       const value = formatExactAge(diffAge(birthDate, expr.date), birthDate, expr.date);       return value ? `wiek: ok. ${value}` : null;     }     if (expr.kind === 'before') {       const value = formatExactAge(diffAge(birthDate, expr.date), birthDate, expr.date);       return value ? `wiek: maks. ${value}` : null;     }     if (expr.kind === 'after') {       const value = formatExactAge(diffAge(birthDate, expr.date), birthDate, expr.date);       return value ? `wiek: min. ${value}` : null;     }     if (expr.kind === 'between' || expr.kind === 'fromto') {       const startValue = formatExactAge(diffAge(birthDate, expr.start), birthDate, expr.start);       const endValue = formatExactAge(diffAge(birthDate, expr.end), birthDate, expr.end);       if (startValue && endValue) return `wiek: ${startValue} – ${endValue}`;     }     return null;   }   function getFactLabel(row) {     return normalize(row.querySelector('.wt-fact-label')?.textContent || '');   }   function getFactRows() {     return Array.from(document.querySelectorAll('tr')).filter(row => row.querySelector('.wt-fact-label'));   }   function findBirthDate(rows) {     for (const row of rows) {       const label = getFactLabel(row);       if (!/(^urodzenie$|^birth$)/.test(label)) continue;       const dateNodes = row.querySelectorAll('.wt-fact-date-age .date');       for (const node of dateNodes) {         const txt = (node.textContent || '').trim();         const parsed = parseDateExpression(txt);         if (parsed?.kind === 'exact') return parsed.date;         if (parsed?.kind === 'about') return parsed.date;       }     }     return null;   }   function findEventDateExpression(row) {     const dateNodes = row.querySelectorAll('.wt-fact-date-age .date');     for (const node of dateNodes) {       const txt = (node.textContent || '').trim();       const parsed = parseDateExpression(txt);       if (parsed) return parsed;     }     return null;   }   function insertAge(row, birthDate) {     if (row.querySelector('.wt-age-at-event')) return;     const label = getFactLabel(row);     if (/(^urodzenie$|^birth$)/.test(label)) return;     const expr = findEventDateExpression(row);     if (!expr) return;     const text = formatAgeFromExpression(birthDate, expr);     if (!text) return;     const labelNode = row.querySelector('th .wt-fact-label');     if (!labelNode || !labelNode.parentNode) return;     const line = document.createElement('div');     line.className = 'wt-age-at-event';     line.textContent = text;     line.style.display = 'block';     line.style.fontSize = '0.875rem';     line.style.color = 'var(--fgColor-default, #9198a1)';     line.style.lineHeight = '1.35';     line.style.marginTop = '0.2rem';     line.style.fontWeight = 'var(--bs-body-font-weight)';     labelNode.parentNode.insertBefore(line, labelNode.nextSibling);   }   function renderAges() {     const rows = getFactRows();     if (!rows.length) return false;     const birthDate = findBirthDate(rows);     if (!birthDate) return false;     rows.forEach(row => insertAge(row, birthDate));     return true;   }   function boot() {     renderAges();     const observer = new MutationObserver(() => {       renderAges();     });     observer.observe(document.body, { childList: true, subtree: true });     let tries = 0;     const timer = setInterval(() => {       renderAges();       tries += 1;       if (tries > 20) clearInterval(timer);     }, 500);   }   if (document.readyState === 'loading') {     document.addEventListener('DOMContentLoaded', boot);   } else {     boot();   } })(); </script>

Regards
Adrian

webtrees.cytr.us
Last edit: 2 months 1 day ago by godzil.

Please Log in or Create an account to join the conversation.

More
1 month 4 weeks ago #116611 by kiwi
Replied by kiwi on topic Age at event
Webtrees does still display age at an event, but just not all events. 

This forum discussion provides a much simpler solution if that is your problem:
www.webtrees.net/index.php/forum/4-custo...9860-age-of-resident

Please Log in or Create an account to join the conversation.

  • bertkoor
  • bertkoor's Avatar
  • Offline
  • Platinum Member
  • Platinum Member
  • Greetings from Utrecht, Holland
More
1 month 4 weeks ago - 1 month 4 weeks ago #116612 by bertkoor
Replied by bertkoor on topic Age at event

This forum discussion provides a much simpler solution if that is your problem:
www.webtrees.net/index.php/forum/4-custo...9860-age-of-resident
Since then I've published a module which facilitates doing that small change in fact-date.phtml and not losing it on an update.
github.com/BertKoor/wt-module-custom-views

Also, Greg proposed an imho elegant solution:

How about suppressing all "aged 0"?
I'll try to implement that and submit a PR for it.

stamboom.BertKoor.nl runs on webtrees v2.2.6
Last edit: 1 month 4 weeks ago by bertkoor.

Please Log in or Create an account to join the conversation.

Powered by Kunena Forum