1d70512abSGreg Roach<?php 2d70512abSGreg Roach 310e06497SGreg Roachdeclare(strict_types=1); 410e06497SGreg Roach 5054771e9SGreg Roachuse Fisharebest\Webtrees\Age; 6054771e9SGreg Roachuse Fisharebest\Webtrees\Fact; 754c1ab5eSGreg Roachuse Fisharebest\Webtrees\Family; 854c1ab5eSGreg Roachuse Fisharebest\Webtrees\I18N; 9d70512abSGreg Roachuse Fisharebest\Webtrees\Individual; 10d70512abSGreg Roach 112cebb4b4SGreg Roach/** 122cebb4b4SGreg Roach * @var int $baseyear 132cebb4b4SGreg Roach * @var int $bheight 1436779af1SGreg Roach * @var array<int> $birthdays 1536779af1SGreg Roach * @var array<int> $birthmonths 1636779af1SGreg Roach * @var array<int> $birthyears 172cebb4b4SGreg Roach * @var int $scale 182cebb4b4SGreg Roach * @var int $topyear 19*54f9ed18SGreg Roach * @var array<int,Fact> $indifacts 20*54f9ed18SGreg Roach * @var array<int,Individual> $individuals 212cebb4b4SGreg Roach */ 222cebb4b4SGreg Roach 23d70512abSGreg Roach?> 24eca4a663SGreg Roach 25eca4a663SGreg Roach<script> 26728c8c27SGreg Roach let bottomy = <?= json_encode(($topyear - $baseyear) * $scale - 5, JSON_THROW_ON_ERROR) ?>; 272cebb4b4SGreg Roach let topy = 0; 282cebb4b4SGreg Roach let baseyear = <?= $baseyear - 25 / $scale ?>; 292cebb4b4SGreg Roach let birthyears = []; 302cebb4b4SGreg Roach let birthmonths = []; 312cebb4b4SGreg Roach let birthdays = []; 3254c1ab5eSGreg Roach <?php foreach ($individuals as $c => $indi) : ?> 33728c8c27SGreg Roach birthyears [<?= json_encode($c, JSON_THROW_ON_ERROR) ?>] = <?= json_encode($birthyears[$indi->xref()] ?? null, JSON_THROW_ON_ERROR) ?>; 34728c8c27SGreg Roach birthmonths[<?= json_encode($c, JSON_THROW_ON_ERROR) ?>] = <?= json_encode($birthmonths[$indi->xref()] ?? null, JSON_THROW_ON_ERROR) ?>; 35728c8c27SGreg Roach birthdays [<?= json_encode($c, JSON_THROW_ON_ERROR) ?>] = <?= json_encode($birthdays[$indi->xref()] ?? null, JSON_THROW_ON_ERROR) ?>; 3654c1ab5eSGreg Roach <?php endforeach ?> 37eca4a663SGreg Roach 38728c8c27SGreg Roach let bheight = <?= json_encode($bheight, JSON_THROW_ON_ERROR) ?>; 39728c8c27SGreg Roach let scale = <?= json_encode($scale, JSON_THROW_ON_ERROR) ?>; 40eca4a663SGreg Roach 41eca4a663SGreg Roach timeline_chart_div = document.getElementById("timeline_chart"); 42728c8c27SGreg Roach timeline_chart_div.style.height = '<?= json_encode(0 + ($topyear - $baseyear) * $scale * 1.1, JSON_THROW_ON_ERROR) ?>px'; 43eca4a663SGreg Roach 44eca4a663SGreg Roach /** 45eca4a663SGreg Roach * Find the position of an event, relative to an element. 46eca4a663SGreg Roach * 47eca4a663SGreg Roach * @param event 48eca4a663SGreg Roach * @param element 49eca4a663SGreg Roach */ 50eca4a663SGreg Roach function clickPosition(event, element) { 512cebb4b4SGreg Roach let xpos = event.pageX; 522cebb4b4SGreg Roach let ypos = event.pageY; 53eca4a663SGreg Roach 54eca4a663SGreg Roach if (element.offsetParent) { 55eca4a663SGreg Roach do { 56eca4a663SGreg Roach xpos -= element.offsetLeft; 57eca4a663SGreg Roach ypos -= element.offsetTop; 58eca4a663SGreg Roach } while (element = element.offsetParent); 59eca4a663SGreg Roach } 60eca4a663SGreg Roach 61eca4a663SGreg Roach return {x: xpos, y: ypos} 62eca4a663SGreg Roach } 63eca4a663SGreg Roach 642cebb4b4SGreg Roach let ob = null; 652cebb4b4SGreg Roach let Y = 0; 662cebb4b4SGreg Roach let X = 0; 672cebb4b4SGreg Roach let oldx = 0; 682cebb4b4SGreg Roach let oldlinew = 0; 692cebb4b4SGreg Roach let personnum = 0; 702cebb4b4SGreg Roach let type = 0; 712cebb4b4SGreg Roach let boxmean = 0; 72eca4a663SGreg Roach 73eca4a663SGreg Roach function ageCursorMouseDown(divbox, num) { 74eca4a663SGreg Roach ob = divbox; 75eca4a663SGreg Roach personnum = num; 76eca4a663SGreg Roach type = 0; 77eca4a663SGreg Roach X = ob.offsetLeft; 78eca4a663SGreg Roach Y = ob.offsetTop; 79eca4a663SGreg Roach } 80eca4a663SGreg Roach 81eca4a663SGreg Roach function factMouseDown(divbox, num, mean) { 82eca4a663SGreg Roach ob = divbox; 83eca4a663SGreg Roach personnum = num; 84eca4a663SGreg Roach boxmean = mean; 85eca4a663SGreg Roach type = 1; 86eca4a663SGreg Roach oldx = ob.offsetLeft; 87eca4a663SGreg Roach oldlinew = 0; 88eca4a663SGreg Roach } 89eca4a663SGreg Roach 90eca4a663SGreg Roach document.onmousemove = function (e) { 912cebb4b4SGreg Roach let textDirection = document.documentElement.dir; 92eca4a663SGreg Roach 93eca4a663SGreg Roach if (ob === null) { 94eca4a663SGreg Roach return true; 95eca4a663SGreg Roach } 962cebb4b4SGreg Roach let newx = 0; 972cebb4b4SGreg Roach let newy = 0; 98eca4a663SGreg Roach if (type === 0) { 99eca4a663SGreg Roach // age boxes 100eca4a663SGreg Roach newPosition = clickPosition(e, document.getElementById("timeline_chart")); 101eca4a663SGreg Roach newx = newPosition.x; 102eca4a663SGreg Roach newy = newPosition.y; 103eca4a663SGreg Roach 104eca4a663SGreg Roach if (oldx === 0) { 105eca4a663SGreg Roach oldx = newx; 106eca4a663SGreg Roach } 107eca4a663SGreg Roach if (newy < topy - bheight / 2) { 108eca4a663SGreg Roach newy = topy - bheight / 2; 109eca4a663SGreg Roach } 110eca4a663SGreg Roach if (newy > bottomy) { 111eca4a663SGreg Roach newy = bottomy - 1; 112eca4a663SGreg Roach } 113eca4a663SGreg Roach ob.style.top = newy + "px"; 1142cebb4b4SGreg Roach let tyear = (newy + bheight - 4 - topy + scale) / scale + baseyear; 1152cebb4b4SGreg Roach let year = Math.floor(tyear); 1162cebb4b4SGreg Roach let month = Math.floor(tyear * 12 - year * 12); 1172cebb4b4SGreg Roach let day = Math.floor(tyear * 365 - year * 365 - month * 30); 1182cebb4b4SGreg Roach let mstamp = year * 365 + month * 30 + day; 1192cebb4b4SGreg Roach let bdstamp = birthyears[personnum] * 365 + birthmonths[personnum] * 30 + birthdays[personnum]; 1202cebb4b4SGreg Roach let daydiff = mstamp - bdstamp; 1212cebb4b4SGreg Roach let ba = 1; 122eca4a663SGreg Roach if (daydiff < 0) { 123eca4a663SGreg Roach ba = -1; 124eca4a663SGreg Roach daydiff = (bdstamp - mstamp); 125eca4a663SGreg Roach } 1262cebb4b4SGreg Roach let yage = Math.floor(daydiff / 365); 1272cebb4b4SGreg Roach let mage = Math.floor((daydiff - yage * 365) / 30); 1282cebb4b4SGreg Roach let dage = Math.floor(daydiff - yage * 365 - mage * 30); 129eca4a663SGreg Roach if (dage < 0) { 130eca4a663SGreg Roach mage = mage - 1; 131eca4a663SGreg Roach } 132eca4a663SGreg Roach if (dage < -30) { 133eca4a663SGreg Roach dage = 30 + dage; 134eca4a663SGreg Roach } 135eca4a663SGreg Roach if (mage < 0) { 136eca4a663SGreg Roach yage = yage - 1; 137eca4a663SGreg Roach } 138eca4a663SGreg Roach if (mage < -11) { 139eca4a663SGreg Roach mage = 12 + mage; 140eca4a663SGreg Roach } 1412cebb4b4SGreg Roach let yearform = document.getElementById('yearform' + personnum); 1422cebb4b4SGreg Roach let ageform = document.getElementById('ageform' + personnum); 143eca4a663SGreg Roach yearform.innerHTML = year + " " + month + " <?= mb_substr(I18N::translate('Month:'), 0, 1) ?> " + day + " <?= mb_substr(I18N::translate('Day:'), 0, 1) ?>"; 144eca4a663SGreg Roach if (ba * yage > 1 || ba * yage < -1 || ba * yage === 0) { 145eca4a663SGreg Roach ageform.innerHTML = (ba * yage) + " <?= mb_substr(I18N::translate('years'), 0, 1) ?> " + (ba * mage) + " <?= mb_substr(I18N::translate('Month:'), 0, 1) ?> " + (ba * dage) + " <?= mb_substr(I18N::translate('Day:'), 0, 1) ?>"; 146eca4a663SGreg Roach } else { 147eca4a663SGreg Roach ageform.innerHTML = (ba * yage) + " <?= mb_substr(I18N::translate('Year:'), 0, 1) ?> " + (ba * mage) + " <?= mb_substr(I18N::translate('Month:'), 0, 1) ?> " + (ba * dage) + " <?= mb_substr(I18N::translate('Day:'), 0, 1) ?>"; 148eca4a663SGreg Roach } 1492cebb4b4SGreg Roach let line = document.getElementById('ageline' + personnum); 1502cebb4b4SGreg Roach let temp = newx - oldx; 151eca4a663SGreg Roach 152eca4a663SGreg Roach if (textDirection === 'rtl') { 153eca4a663SGreg Roach temp = temp * -1; 154eca4a663SGreg Roach } 155eca4a663SGreg Roach line.style.width = (line.width + temp) + "px"; 156eca4a663SGreg Roach oldx = newx; 157eca4a663SGreg Roach return false; 158eca4a663SGreg Roach } else { 159eca4a663SGreg Roach // fact boxes 1602cebb4b4SGreg Roach let linewidth; 161eca4a663SGreg Roach newPosition = clickPosition(e, document.getElementById("timeline_chart")); 162eca4a663SGreg Roach newx = newPosition.x; 163eca4a663SGreg Roach newy = newPosition.y; 164eca4a663SGreg Roach if (oldx === 0) { 165eca4a663SGreg Roach oldx = newx; 166eca4a663SGreg Roach } 167eca4a663SGreg Roach linewidth = e.pageX; 168eca4a663SGreg Roach 169eca4a663SGreg Roach // get diagnal line box 1702cebb4b4SGreg Roach let dbox = document.getElementById('dbox' + personnum); 1712cebb4b4SGreg Roach let etopy; 1722cebb4b4SGreg Roach let ebottomy; 173eca4a663SGreg Roach // set up limits 174eca4a663SGreg Roach if (boxmean - 175 < topy) { 175eca4a663SGreg Roach etopy = topy; 176eca4a663SGreg Roach } else { 177eca4a663SGreg Roach etopy = boxmean - 175; 178eca4a663SGreg Roach } 179eca4a663SGreg Roach if (boxmean + 175 > bottomy) { 180eca4a663SGreg Roach ebottomy = bottomy; 181eca4a663SGreg Roach } else { 182eca4a663SGreg Roach ebottomy = boxmean + 175; 183eca4a663SGreg Roach } 184eca4a663SGreg Roach // check if in the bounds of the limits 185eca4a663SGreg Roach if (newy < etopy) { 186eca4a663SGreg Roach newy = etopy; 187eca4a663SGreg Roach } 188eca4a663SGreg Roach if (newy > ebottomy) { 189eca4a663SGreg Roach newy = ebottomy; 190eca4a663SGreg Roach } 191eca4a663SGreg Roach // calculate the change in Y position 1922cebb4b4SGreg Roach let dy = newy - ob.offsetTop; 193eca4a663SGreg Roach // check if we are above the starting point and switch the background image 194eca4a663SGreg Roach 195eca4a663SGreg Roach if (newy < boxmean) { 196eca4a663SGreg Roach if (textDirection === 'rtl') { 197e837ff07SGreg Roach dbox.style.backgroundImage = "url('<?= asset('css/images/dline2.png') ?>')"; 198eca4a663SGreg Roach dbox.style.backgroundPosition = "0% 0%"; 199eca4a663SGreg Roach } else { 200e837ff07SGreg Roach dbox.style.backgroundImage = "url('<?= asset('css/images/dline.png') ?>')"; 201eca4a663SGreg Roach dbox.style.backgroundPosition = "0% 100%"; 202eca4a663SGreg Roach } 203eca4a663SGreg Roach dy = -dy; 204eca4a663SGreg Roach dbox.style.top = (newy + bheight / 3) + "px"; 205eca4a663SGreg Roach } else { 206eca4a663SGreg Roach if (textDirection === 'rtl') { 207e837ff07SGreg Roach dbox.style.backgroundImage = "url('<?= asset('css/images/dline.png') ?>')"; 208eca4a663SGreg Roach dbox.style.backgroundPosition = "0% 100%"; 209eca4a663SGreg Roach } else { 210e837ff07SGreg Roach dbox.style.backgroundImage = "url('<?= asset('css/images/dline2.png') ?>')"; 211eca4a663SGreg Roach dbox.style.backgroundPosition = "0% 0%"; 212eca4a663SGreg Roach } 213eca4a663SGreg Roach 214eca4a663SGreg Roach dbox.style.top = (boxmean + bheight / 3) + "px"; 215eca4a663SGreg Roach } 216a2c8afeaSAlejandro Criado-Pérez // the new X position moves the same as the y position 217eca4a663SGreg Roach if (textDirection === 'rtl') { 218eca4a663SGreg Roach newx = dbox.offsetRight + Math.abs(newy - boxmean); 219eca4a663SGreg Roach } else { 220eca4a663SGreg Roach newx = dbox.offsetLeft + Math.abs(newy - boxmean); 221eca4a663SGreg Roach } 222eca4a663SGreg Roach // set the X position of the box 223eca4a663SGreg Roach if (textDirection === 'rtl') { 224eca4a663SGreg Roach ob.style.right = newx + "px"; 225eca4a663SGreg Roach } else { 226eca4a663SGreg Roach ob.style.left = newx + "px"; 227eca4a663SGreg Roach } 228eca4a663SGreg Roach // set new top positions 229eca4a663SGreg Roach ob.style.top = newy + "px"; 230eca4a663SGreg Roach // get the width for the diagnal box 2312cebb4b4SGreg Roach let newwidth = (ob.offsetLeft - dbox.offsetLeft); 232eca4a663SGreg Roach // set the width 233eca4a663SGreg Roach dbox.style.width = newwidth + "px"; 234eca4a663SGreg Roach if (textDirection === 'rtl') { 235eca4a663SGreg Roach dbox.style.right = (dbox.offsetRight - newwidth) + 'px'; 236eca4a663SGreg Roach } 237eca4a663SGreg Roach dbox.style.height = newwidth + "px"; 238eca4a663SGreg Roach // change the line width to the change in the mouse X position 239eca4a663SGreg Roach line = document.getElementById('boxline' + personnum); 240eca4a663SGreg Roach if (oldlinew !== 0) { 241eca4a663SGreg Roach line.width = line.width + (linewidth - oldlinew); 242eca4a663SGreg Roach } 243eca4a663SGreg Roach oldlinew = linewidth; 244eca4a663SGreg Roach oldx = newx; 245eca4a663SGreg Roach return false; 246eca4a663SGreg Roach } 247eca4a663SGreg Roach }; 248eca4a663SGreg Roach 249eca4a663SGreg Roach document.onmouseup = function () { 250eca4a663SGreg Roach ob = null; 251eca4a663SGreg Roach oldx = 0; 252eca4a663SGreg Roach } 253eca4a663SGreg Roach</script> 254eca4a663SGreg Roach 255eca4a663SGreg Roach<div id="timeline_chart"> 256eca4a663SGreg Roach <!-- print the timeline line image --> 257eca4a663SGreg Roach <div id="line" style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left:22px;' : 'right:22px;' ?> top:0;"> 2582cebb4b4SGreg Roach <img src="<?= e(asset('css/images/vline.png')) ?>" width="3" 2592cebb4b4SGreg Roach height="<?= 0 + ($topyear - $baseyear) * $scale ?>"> 260eca4a663SGreg Roach </div> 261eca4a663SGreg Roach 262eca4a663SGreg Roach <!-- print divs for the grid --> 2632cebb4b4SGreg Roach <div id="scale<?= e($baseyear) ?>" 2642cebb4b4SGreg Roach style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>:0; top:-5px; font-size: 7pt; text-align: <?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>;"> 265eca4a663SGreg Roach <?= $baseyear ?> 266eca4a663SGreg Roach </div> 267eca4a663SGreg Roach <?php 268eca4a663SGreg Roach // at a scale of 25 or higher, show every year 2691a2589c7SGreg Roach $mod = intdiv(25, $scale); 270eca4a663SGreg Roach if ($mod < 1) { 271eca4a663SGreg Roach $mod = 1; 272eca4a663SGreg Roach } 273eca4a663SGreg Roach for ($i = $baseyear + 1; $i < $topyear; $i++) { 274eca4a663SGreg Roach if ($i % $mod === 0) { 275dd71ff6bSGreg Roach echo '<div id="scale' . $i . '" style="position:absolute; ' . (I18N::direction() === 'ltr' ? 'left:0;' : 'right:0;') . ' top:' . (($i - $baseyear) * $scale - $scale / 2) . 'px; font-size: 7pt; text-align:' . (I18N::direction() === 'ltr' ? 'left' : 'right') . ';">'; 276eca4a663SGreg Roach echo $i; 277eca4a663SGreg Roach echo '</div>'; 278eca4a663SGreg Roach } 279eca4a663SGreg Roach } 280eca4a663SGreg Roach echo ''; 281eca4a663SGreg Roach ?> 2822cebb4b4SGreg Roach <div id="scale<?= e($topyear) ?>" 2832cebb4b4SGreg Roach style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>:0; top:<?= ($topyear - $baseyear) * $scale ?>px; font-size: 7pt; text-align:<?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>;"> 284eca4a663SGreg Roach <?= e($topyear) ?> 285eca4a663SGreg Roach </div> 286eca4a663SGreg Roach 287eca4a663SGreg Roach <?php foreach ($indifacts as $factcount => $event) : ?> 288eca4a663SGreg Roach <?php 289eca4a663SGreg Roach $desc = $event->value(); 290eca4a663SGreg Roach $gdate = $event->date(); 291eca4a663SGreg Roach $date = $gdate->minimumDate(); 292eca4a663SGreg Roach $date = $date->convertToCalendar('gregorian'); 293eca4a663SGreg Roach $year = $date->year(); 294eca4a663SGreg Roach $month = max(1, $date->month()); 295eca4a663SGreg Roach $day = max(1, $date->day()); 296eca4a663SGreg Roach $xoffset = 0 + 22; 2972cebb4b4SGreg Roach $yoffset = 0 + ($year - $baseyear) * $scale - $scale; 2982cebb4b4SGreg Roach $yoffset = $yoffset + $month / 12 * $scale; 2992cebb4b4SGreg Roach $yoffset = $yoffset + $day / 30 * ($scale / 12); 300261d6e48SGreg Roach $yoffset = (int) $yoffset; 301eca4a663SGreg Roach $place = (int) ($yoffset / $bheight); 302eca4a663SGreg Roach $i = 1; 303eca4a663SGreg Roach $j = 0; 304eca4a663SGreg Roach $tyoffset = 0; 305eca4a663SGreg Roach while (isset($placements[$place])) { 306eca4a663SGreg Roach if ($i === $j) { 307eca4a663SGreg Roach $tyoffset = $bheight * $i; 308eca4a663SGreg Roach $i++; 309eca4a663SGreg Roach } else { 310eca4a663SGreg Roach $tyoffset = -1 * $bheight * $j; 311eca4a663SGreg Roach $j++; 312eca4a663SGreg Roach } 313eca4a663SGreg Roach $place = (int) (($yoffset + $tyoffset) / $bheight); 314eca4a663SGreg Roach } 315eca4a663SGreg Roach $yoffset += $tyoffset; 316eca4a663SGreg Roach $xoffset += abs($tyoffset); 317eca4a663SGreg Roach $placements[$place] = $yoffset; 318eca4a663SGreg Roach 319261d6e48SGreg Roach echo "<div id=\"fact$factcount\" style=\"position:absolute; " . (I18N::direction() === 'ltr' ? 'left: ' . $xoffset : 'right: ' . $xoffset) . 'px; top:' . $yoffset . 'px; font-size: 8pt; height: ' . $bheight . "px;\" onmousedown=\"factMouseDown(this, '" . $factcount . "', " . ($yoffset - $tyoffset) . ');">'; 320ca8f62c9SGreg Roach echo '<table cellspacing="0" cellpadding="0" border="0" style="cursor: grab;"><tr><td>'; 321f220ef57SGreg Roach echo '<img src="' . e(asset('css/images/hline.png')) . '" id="boxline' . $factcount . '" height="3" width="10" style="padding-'; 322eca4a663SGreg Roach if (I18N::direction() === 'ltr') { 323eca4a663SGreg Roach echo 'left: 3px;">'; 324eca4a663SGreg Roach } else { 325eca4a663SGreg Roach echo 'right: 3px;">'; 326eca4a663SGreg Roach } 327eca4a663SGreg Roach 32822d65e5aSGreg Roach $col = array_search($event->record(), $individuals, true); 329eca4a663SGreg Roach if ($col === false) { 330eca4a663SGreg Roach // Marriage event - use the color of the husband 33122d65e5aSGreg Roach $col = array_search($event->record()->husband(), $individuals, true); 332eca4a663SGreg Roach } 333eca4a663SGreg Roach if ($col === false) { 334eca4a663SGreg Roach // Marriage event - use the color of the wife 33522d65e5aSGreg Roach $col = array_search($event->record()->wife(), $individuals, true); 336eca4a663SGreg Roach } 3372cebb4b4SGreg Roach $col %= 6; 338eca4a663SGreg Roach echo '</td><td class="person' . $col . '">'; 339eca4a663SGreg Roach if (count($individuals) > 6) { 340eca4a663SGreg Roach // We only have six colours, so show naes if more than this number 34139ca88baSGreg Roach echo $event->record()->fullName() . ' — '; 342eca4a663SGreg Roach } 343eca4a663SGreg Roach $record = $event->record(); 344eca4a663SGreg Roach echo $event->label(); 345eca4a663SGreg Roach echo ' — '; 346eca4a663SGreg Roach if ($record instanceof Individual) { 347b315f3e1SGreg Roach echo view('fact-date', ['cal_link' => 'false', 'fact' => $event, 'record' => $record, 'time' => false]); 348eca4a663SGreg Roach } elseif ($record instanceof Family) { 349eca4a663SGreg Roach echo $gdate->display(); 350054771e9SGreg Roach 351054771e9SGreg Roach foreach ($record->spouses() as $spouse) { 352054771e9SGreg Roach if ($spouse->getBirthDate()->isOK()) { 353a5fd6d7cSGreg Roach $age = (string) new Age($spouse->getBirthDate(), $gdate); 354054771e9SGreg Roach if ($spouse->sex() === 'F') { 355a5fd6d7cSGreg Roach echo '<span class="age"> ', I18N::translate('Wife’s age'), ' ', $age, '</span>'; 356eca4a663SGreg Roach } else { 357a5fd6d7cSGreg Roach echo '<span class="age"> ', I18N::translate('Husband’s age'), ' ', $age, '</span>'; 358eca4a663SGreg Roach } 359eca4a663SGreg Roach } 360eca4a663SGreg Roach } 361eca4a663SGreg Roach } 362eca4a663SGreg Roach echo ' ' . e($desc); 36329e68993SGreg Roach if ($event->place()->gedcomName() !== '') { 364392561bbSGreg Roach echo ' — ' . $event->place()->shortName(); 365eca4a663SGreg Roach } 366eca4a663SGreg Roach // Print spouses names for family events 367eca4a663SGreg Roach if ($event->record() instanceof Family) { 36839ca88baSGreg Roach echo ' — <a href="', e($event->record()->url()), '">', $event->record()->fullName(), '</a>'; 369eca4a663SGreg Roach } 370eca4a663SGreg Roach echo '</td></tr></table>'; 371eca4a663SGreg Roach echo '</div>'; 372eca4a663SGreg Roach if (I18N::direction() === 'ltr') { 373e837ff07SGreg Roach $img = asset('css/images/dline2.png'); 374eca4a663SGreg Roach $ypos = '0%'; 375eca4a663SGreg Roach } else { 376e837ff07SGreg Roach $img = asset('css/images/dline.png'); 377eca4a663SGreg Roach $ypos = '100%'; 378eca4a663SGreg Roach } 379dd71ff6bSGreg Roach $dyoffset = $yoffset - $tyoffset + $bheight / 3; 380eca4a663SGreg Roach if ($tyoffset < 0) { 381eca4a663SGreg Roach $dyoffset = $yoffset + $bheight / 3; 382eca4a663SGreg Roach if (I18N::direction() === 'ltr') { 383e837ff07SGreg Roach $img = asset('css/images/dline.png'); 384eca4a663SGreg Roach $ypos = '100%'; 385eca4a663SGreg Roach } else { 386e837ff07SGreg Roach $img = asset('css/images/dline2.png'); 387eca4a663SGreg Roach $ypos = '0%'; 388eca4a663SGreg Roach } 389eca4a663SGreg Roach } 390eca4a663SGreg Roach ?> 391eca4a663SGreg Roach 392eca4a663SGreg Roach <!-- diagonal line --> 393dd71ff6bSGreg Roach <div id="dbox<?= $factcount ?>" style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left: ' . (0 + 25) : 'right: ' . (0 + 25) ?>px; top:<?= $dyoffset ?>px; font-size: 8pt; height: <?= abs($tyoffset) ?>px; width: <?= abs($tyoffset) ?>px; background-image: url('<?= e($img) ?>'); background-position: 0 <?= $ypos ?>;"> 394eca4a663SGreg Roach </div> 395eca4a663SGreg Roach <?php endforeach ?> 396eca4a663SGreg Roach 397eca4a663SGreg Roach <!-- age cursors --> 398eca4a663SGreg Roach <?php foreach ($individuals as $p => $indi) : ?> 399dd71ff6bSGreg Roach <?php $ageyoffset = 0 + $bheight * $p; ?> 400eca4a663SGreg Roach <div id="agebox<?= $p ?>" style="cursor:move; position:absolute; <?= I18N::direction() === 'ltr' ? 'left:20px;' : 'right:20px;' ?> top:<?= $ageyoffset ?>px; height:<?= $bheight ?>px; display:none;" onmousedown="ageCursorMouseDown(this, <?= $p ?>);"> 401eca4a663SGreg Roach <table cellspacing="0" cellpadding="0"> 402eca4a663SGreg Roach <tr> 403eca4a663SGreg Roach <td> 404f220ef57SGreg Roach <img src="<?= e(asset('css/images/hline.png')) ?>" id="ageline<?= $p ?>" width="25" height="3"> 405eca4a663SGreg Roach </td> 406eca4a663SGreg Roach <td> 407eca4a663SGreg Roach <?php if (!empty($birthyears[$indi->xref()])) : ?> 408dd71ff6bSGreg Roach <?php $tyear = round(($ageyoffset + $bheight / 2) / $scale) + $baseyear; ?> 409ca8f62c9SGreg Roach <table class="person<?= $p % 6 ?>" style="cursor: grab;"> 410eca4a663SGreg Roach <tr> 411eca4a663SGreg Roach <td> 412eca4a663SGreg Roach <?= I18N::translate('Year:') ?> 413eca4a663SGreg Roach <span id="yearform<?= $p ?>" class="field"> 414eca4a663SGreg Roach <?= $tyear ?> 415eca4a663SGreg Roach </span> 416eca4a663SGreg Roach </td> 417eca4a663SGreg Roach <td> 4182cebb4b4SGreg Roach (<?= I18N::translate('Age') ?> 4192cebb4b4SGreg Roach <span id="ageform<?= $p ?>" class="field"><?= $tyear - $birthyears[$indi->xref()] ?></span>) 420eca4a663SGreg Roach </td> 421eca4a663SGreg Roach </tr> 422eca4a663SGreg Roach </table> 423eca4a663SGreg Roach <?php endif ?> 424eca4a663SGreg Roach </td> 425eca4a663SGreg Roach </tr> 426eca4a663SGreg Roach </table> 427eca4a663SGreg Roach <br> 428eca4a663SGreg Roach <br> 429eca4a663SGreg Roach <br> 430eca4a663SGreg Roach </div> 431eca4a663SGreg Roach <br> 432eca4a663SGreg Roach <br> 433eca4a663SGreg Roach <br> 434eca4a663SGreg Roach <br> 435eca4a663SGreg Roach <?php endforeach ?> 436eca4a663SGreg Roach</div> 437