![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /var/www/html/webtrees/resources/views/modules/timeline-chart/ |
Upload File : |
<?php declare(strict_types=1); use Fisharebest\Webtrees\Age; use Fisharebest\Webtrees\Fact; use Fisharebest\Webtrees\Family; use Fisharebest\Webtrees\I18N; use Fisharebest\Webtrees\Individual; /** * @var int $baseyear * @var int $bheight * @var array<int> $birthdays * @var array<int> $birthmonths * @var array<int> $birthyears * @var int $scale * @var int $topyear * @var array<int,Fact> $indifacts * @var array<int,Individual> $individuals */ ?> <script> let bottomy = <?= json_encode(($topyear - $baseyear) * $scale - 5, JSON_THROW_ON_ERROR) ?>; let topy = 0; let baseyear = <?= $baseyear - 25 / $scale ?>; let birthyears = []; let birthmonths = []; let birthdays = []; <?php foreach ($individuals as $c => $indi) : ?> birthyears [<?= json_encode($c, JSON_THROW_ON_ERROR) ?>] = <?= json_encode($birthyears[$indi->xref()] ?? null, JSON_THROW_ON_ERROR) ?>; birthmonths[<?= json_encode($c, JSON_THROW_ON_ERROR) ?>] = <?= json_encode($birthmonths[$indi->xref()] ?? null, JSON_THROW_ON_ERROR) ?>; birthdays [<?= json_encode($c, JSON_THROW_ON_ERROR) ?>] = <?= json_encode($birthdays[$indi->xref()] ?? null, JSON_THROW_ON_ERROR) ?>; <?php endforeach ?> let bheight = <?= json_encode($bheight, JSON_THROW_ON_ERROR) ?>; let scale = <?= json_encode($scale, JSON_THROW_ON_ERROR) ?>; timeline_chart_div = document.getElementById("timeline_chart"); timeline_chart_div.style.height = '<?= json_encode(0 + ($topyear - $baseyear) * $scale * 1.1, JSON_THROW_ON_ERROR) ?>px'; /** * Find the position of an event, relative to an element. * * @param event * @param element */ function clickPosition(event, element) { let xpos = event.pageX; let ypos = event.pageY; if (element.offsetParent) { do { xpos -= element.offsetLeft; ypos -= element.offsetTop; } while (element = element.offsetParent); } return {x: xpos, y: ypos} } let ob = null; let Y = 0; let X = 0; let oldx = 0; let oldlinew = 0; let personnum = 0; let type = 0; let boxmean = 0; function ageCursorMouseDown(divbox, num) { ob = divbox; personnum = num; type = 0; X = ob.offsetLeft; Y = ob.offsetTop; } function factMouseDown(divbox, num, mean) { ob = divbox; personnum = num; boxmean = mean; type = 1; oldx = ob.offsetLeft; oldlinew = 0; } document.onmousemove = function (e) { let textDirection = document.documentElement.dir; if (ob === null) { return true; } let newx = 0; let newy = 0; if (type === 0) { // age boxes newPosition = clickPosition(e, document.getElementById("timeline_chart")); newx = newPosition.x; newy = newPosition.y; if (oldx === 0) { oldx = newx; } if (newy < topy - bheight / 2) { newy = topy - bheight / 2; } if (newy > bottomy) { newy = bottomy - 1; } ob.style.top = newy + "px"; let tyear = (newy + bheight - 4 - topy + scale) / scale + baseyear; let year = Math.floor(tyear); let month = Math.floor(tyear * 12 - year * 12); let day = Math.floor(tyear * 365 - year * 365 - month * 30); let mstamp = year * 365 + month * 30 + day; let bdstamp = birthyears[personnum] * 365 + birthmonths[personnum] * 30 + birthdays[personnum]; let daydiff = mstamp - bdstamp; let ba = 1; if (daydiff < 0) { ba = -1; daydiff = (bdstamp - mstamp); } let yage = Math.floor(daydiff / 365); let mage = Math.floor((daydiff - yage * 365) / 30); let dage = Math.floor(daydiff - yage * 365 - mage * 30); if (dage < 0) { mage = mage - 1; } if (dage < -30) { dage = 30 + dage; } if (mage < 0) { yage = yage - 1; } if (mage < -11) { mage = 12 + mage; } let yearform = document.getElementById('yearform' + personnum); let ageform = document.getElementById('ageform' + personnum); yearform.innerHTML = year + " " + month + " <?= mb_substr(I18N::translate('Month:'), 0, 1) ?> " + day + " <?= mb_substr(I18N::translate('Day:'), 0, 1) ?>"; if (ba * yage > 1 || ba * yage < -1 || ba * yage === 0) { 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) ?>"; } else { 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) ?>"; } let line = document.getElementById('ageline' + personnum); let temp = newx - oldx; if (textDirection === 'rtl') { temp = temp * -1; } line.style.width = (line.width + temp) + "px"; oldx = newx; return false; } else { // fact boxes let linewidth; newPosition = clickPosition(e, document.getElementById("timeline_chart")); newx = newPosition.x; newy = newPosition.y; if (oldx === 0) { oldx = newx; } linewidth = e.pageX; // get diagnal line box let dbox = document.getElementById('dbox' + personnum); let etopy; let ebottomy; // set up limits if (boxmean - 175 < topy) { etopy = topy; } else { etopy = boxmean - 175; } if (boxmean + 175 > bottomy) { ebottomy = bottomy; } else { ebottomy = boxmean + 175; } // check if in the bounds of the limits if (newy < etopy) { newy = etopy; } if (newy > ebottomy) { newy = ebottomy; } // calculate the change in Y position let dy = newy - ob.offsetTop; // check if we are above the starting point and switch the background image if (newy < boxmean) { if (textDirection === 'rtl') { dbox.style.backgroundImage = "url('<?= asset('css/images/dline2.png') ?>')"; dbox.style.backgroundPosition = "0% 0%"; } else { dbox.style.backgroundImage = "url('<?= asset('css/images/dline.png') ?>')"; dbox.style.backgroundPosition = "0% 100%"; } dy = -dy; dbox.style.top = (newy + bheight / 3) + "px"; } else { if (textDirection === 'rtl') { dbox.style.backgroundImage = "url('<?= asset('css/images/dline.png') ?>')"; dbox.style.backgroundPosition = "0% 100%"; } else { dbox.style.backgroundImage = "url('<?= asset('css/images/dline2.png') ?>')"; dbox.style.backgroundPosition = "0% 0%"; } dbox.style.top = (boxmean + bheight / 3) + "px"; } // the new X posistion moves the same as the y position if (textDirection === 'rtl') { newx = dbox.offsetRight + Math.abs(newy - boxmean); } else { newx = dbox.offsetLeft + Math.abs(newy - boxmean); } // set the X position of the box if (textDirection === 'rtl') { ob.style.right = newx + "px"; } else { ob.style.left = newx + "px"; } // set new top positions ob.style.top = newy + "px"; // get the width for the diagnal box let newwidth = (ob.offsetLeft - dbox.offsetLeft); // set the width dbox.style.width = newwidth + "px"; if (textDirection === 'rtl') { dbox.style.right = (dbox.offsetRight - newwidth) + 'px'; } dbox.style.height = newwidth + "px"; // change the line width to the change in the mouse X position line = document.getElementById('boxline' + personnum); if (oldlinew !== 0) { line.width = line.width + (linewidth - oldlinew); } oldlinew = linewidth; oldx = newx; return false; } }; document.onmouseup = function () { ob = null; oldx = 0; } </script> <div id="timeline_chart"> <!-- print the timeline line image --> <div id="line" style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left:22px;' : 'right:22px;' ?> top:0;"> <img src="<?= e(asset('css/images/vline.png')) ?>" width="3" height="<?= 0 + ($topyear - $baseyear) * $scale ?>"> </div> <!-- print divs for the grid --> <div id="scale<?= e($baseyear) ?>" style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>:0; top:-5px; font-size: 7pt; text-align: <?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>;"> <?= $baseyear ?> </div> <?php // at a scale of 25 or higher, show every year $mod = intdiv(25, $scale); if ($mod < 1) { $mod = 1; } for ($i = $baseyear + 1; $i < $topyear; $i++) { if ($i % $mod === 0) { 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') . ';">'; echo $i; echo '</div>'; } } echo ''; ?> <div id="scale<?= e($topyear) ?>" style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>:0; top:<?= ($topyear - $baseyear) * $scale ?>px; font-size: 7pt; text-align:<?= I18N::direction() === 'ltr' ? 'left' : 'right' ?>;"> <?= e($topyear) ?> </div> <?php foreach ($indifacts as $factcount => $event) : ?> <?php $desc = $event->value(); $gdate = $event->date(); $date = $gdate->minimumDate(); $date = $date->convertToCalendar('gregorian'); $year = $date->year(); $month = max(1, $date->month()); $day = max(1, $date->day()); $xoffset = 0 + 22; $yoffset = 0 + ($year - $baseyear) * $scale - $scale; $yoffset = $yoffset + $month / 12 * $scale; $yoffset = $yoffset + $day / 30 * ($scale / 12); $yoffset = (int) $yoffset; $place = (int) ($yoffset / $bheight); $i = 1; $j = 0; $tyoffset = 0; while (isset($placements[$place])) { if ($i === $j) { $tyoffset = $bheight * $i; $i++; } else { $tyoffset = -1 * $bheight * $j; $j++; } $place = (int) (($yoffset + $tyoffset) / $bheight); } $yoffset += $tyoffset; $xoffset += abs($tyoffset); $placements[$place] = $yoffset; 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) . ');">'; echo '<table cellspacing="0" cellpadding="0" border="0" style="cursor: grab;"><tr><td>'; echo '<img src="' . e(asset('css/images/hline.png')) . '" id="boxline' . $factcount . '" height="3" width="10" style="padding-'; if (I18N::direction() === 'ltr') { echo 'left: 3px;">'; } else { echo 'right: 3px;">'; } $col = array_search($event->record(), $individuals, true); if ($col === false) { // Marriage event - use the color of the husband $col = array_search($event->record()->husband(), $individuals, true); } if ($col === false) { // Marriage event - use the color of the wife $col = array_search($event->record()->wife(), $individuals, true); } $col %= 6; echo '</td><td class="person' . $col . '">'; if (count($individuals) > 6) { // We only have six colours, so show naes if more than this number echo $event->record()->fullName() . ' — '; } $record = $event->record(); echo $event->label(); echo ' — '; if ($record instanceof Individual) { echo view('fact-date', ['cal_link' => 'false', 'fact' => $event, 'record' => $record, 'time' => false]); } elseif ($record instanceof Family) { echo $gdate->display(); foreach ($record->spouses() as $spouse) { if ($spouse->getBirthDate()->isOK()) { $age = (string) new Age($spouse->getBirthDate(), $gdate); if ($spouse->sex() === 'F') { echo '<span class="age"> ', I18N::translate('Wife’s age'), ' ', $age, '</span>'; } else { echo '<span class="age"> ', I18N::translate('Husband’s age'), ' ', $age, '</span>'; } } } } echo ' ' . e($desc); if ($event->place()->gedcomName() !== '') { echo ' — ' . $event->place()->shortName(); } // Print spouses names for family events if ($event->record() instanceof Family) { echo ' — <a href="', e($event->record()->url()), '">', $event->record()->fullName(), '</a>'; } echo '</td></tr></table>'; echo '</div>'; if (I18N::direction() === 'ltr') { $img = asset('css/images/dline2.png'); $ypos = '0%'; } else { $img = asset('css/images/dline.png'); $ypos = '100%'; } $dyoffset = $yoffset - $tyoffset + $bheight / 3; if ($tyoffset < 0) { $dyoffset = $yoffset + $bheight / 3; if (I18N::direction() === 'ltr') { $img = asset('css/images/dline.png'); $ypos = '100%'; } else { $img = asset('css/images/dline2.png'); $ypos = '0%'; } } ?> <!-- diagonal line --> <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 ?>;"> </div> <?php endforeach ?> <!-- age cursors --> <?php foreach ($individuals as $p => $indi) : ?> <?php $ageyoffset = 0 + $bheight * $p; ?> <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 ?>);"> <table cellspacing="0" cellpadding="0"> <tr> <td> <img src="<?= e(asset('css/images/hline.png')) ?>" id="ageline<?= $p ?>" width="25" height="3"> </td> <td> <?php if (!empty($birthyears[$indi->xref()])) : ?> <?php $tyear = round(($ageyoffset + $bheight / 2) / $scale) + $baseyear; ?> <table class="person<?= $p % 6 ?>" style="cursor: grab;"> <tr> <td> <?= I18N::translate('Year:') ?> <span id="yearform<?= $p ?>" class="field"> <?= $tyear ?> </span> </td> <td> (<?= I18N::translate('Age') ?> <span id="ageform<?= $p ?>" class="field"><?= $tyear - $birthyears[$indi->xref()] ?></span>) </td> </tr> </table> <?php endif ?> </td> </tr> </table> <br> <br> <br> </div> <br> <br> <br> <br> <?php endforeach ?> </div>