xref: /webtrees/resources/views/modules/timeline-chart/chart.phtml (revision 39ca88ba08cefcfcaf891abfcf748f9c808eb326)
1eca4a663SGreg Roach<?php use Fisharebest\Webtrees\Date; ?>
2eca4a663SGreg Roach<?php use Fisharebest\Webtrees\Family; ?>
3eca4a663SGreg Roach<?php use Fisharebest\Webtrees\Functions\FunctionsDate; ?>
4eca4a663SGreg Roach<?php use Fisharebest\Webtrees\Functions\FunctionsPrint; ?>
5eca4a663SGreg Roach<?php use Fisharebest\Webtrees\I18N; ?>
6eca4a663SGreg Roach<?php use Fisharebest\Webtrees\Individual; ?>
78136679eSGreg Roach<?php use Fisharebest\Webtrees\Module\ModuleThemeInterface; ?>
8eca4a663SGreg Roach
9eca4a663SGreg Roach<script>
10eca4a663SGreg Roach  var bottomy     = <?= ($topyear - $baseyear) * $scale - 5 ?>;
11eca4a663SGreg Roach  var topy        = 0;
12eca4a663SGreg Roach  var baseyear    = <?= $baseyear - (25 / $scale) ?>;
13eca4a663SGreg Roach  var birthyears  = [];
14eca4a663SGreg Roach  var birthmonths = [];
15eca4a663SGreg Roach  var birthdays   = [];
16eca4a663SGreg Roach    <?php
17eca4a663SGreg Roach    foreach ($individuals as $c => $indi) {
18eca4a663SGreg Roach        if (!empty($birthyears[$indi->xref()])) {
19eca4a663SGreg Roach            echo 'birthyears[' . $c . ']=' . $birthyears[$indi->xref()] . ';';
20eca4a663SGreg Roach        }
21eca4a663SGreg Roach        if (!empty($birthmonths[$indi->xref()])) {
22eca4a663SGreg Roach            echo 'birthmonths[' . $c . ']=' . $birthmonths[$indi->xref()] . ';';
23eca4a663SGreg Roach        }
24eca4a663SGreg Roach        if (!empty($birthdays[$indi->xref()])) {
25eca4a663SGreg Roach            echo 'birthdays[' . $c . ']=' . $birthdays[$indi->xref()] . ';';
26eca4a663SGreg Roach        }
27eca4a663SGreg Roach    }
28eca4a663SGreg Roach    ?>
29eca4a663SGreg Roach
30eca4a663SGreg Roach  var bheight = <?= $bheight ?>;
31eca4a663SGreg Roach  var scale   = <?= $scale ?>;
32eca4a663SGreg Roach
33eca4a663SGreg Roach  timeline_chart_div              = document.getElementById("timeline_chart");
34eca4a663SGreg Roach  timeline_chart_div.style.height = '<?= 0 + ($topyear - $baseyear) * $scale * 1.1 ?>px';
35eca4a663SGreg Roach
36eca4a663SGreg Roach  /**
37eca4a663SGreg Roach   * Find the position of an event, relative to an element.
38eca4a663SGreg Roach   *
39eca4a663SGreg Roach   * @param event
40eca4a663SGreg Roach   * @param element
41eca4a663SGreg Roach   */
42eca4a663SGreg Roach  function clickPosition(event, element) {
43eca4a663SGreg Roach    var xpos = event.pageX;
44eca4a663SGreg Roach    var ypos = event.pageY;
45eca4a663SGreg Roach
46eca4a663SGreg Roach    if (element.offsetParent) {
47eca4a663SGreg Roach      do {
48eca4a663SGreg Roach        xpos -= element.offsetLeft;
49eca4a663SGreg Roach        ypos -= element.offsetTop;
50eca4a663SGreg Roach      } while (element = element.offsetParent);
51eca4a663SGreg Roach    }
52eca4a663SGreg Roach
53eca4a663SGreg Roach    return {x: xpos, y: ypos}
54eca4a663SGreg Roach  }
55eca4a663SGreg Roach
56eca4a663SGreg Roach  var ob        = null;
57eca4a663SGreg Roach  var Y         = 0;
58eca4a663SGreg Roach  var X         = 0;
59eca4a663SGreg Roach  var oldx      = 0;
60eca4a663SGreg Roach  var oldlinew  = 0;
61eca4a663SGreg Roach  var personnum = 0;
62eca4a663SGreg Roach  var type      = 0;
63eca4a663SGreg Roach  var boxmean   = 0;
64eca4a663SGreg Roach
65eca4a663SGreg Roach  function ageCursorMouseDown(divbox, num) {
66eca4a663SGreg Roach    ob        = divbox;
67eca4a663SGreg Roach    personnum = num;
68eca4a663SGreg Roach    type      = 0;
69eca4a663SGreg Roach    X         = ob.offsetLeft;
70eca4a663SGreg Roach    Y         = ob.offsetTop;
71eca4a663SGreg Roach  }
72eca4a663SGreg Roach
73eca4a663SGreg Roach  function factMouseDown(divbox, num, mean) {
74eca4a663SGreg Roach    ob        = divbox;
75eca4a663SGreg Roach    personnum = num;
76eca4a663SGreg Roach    boxmean   = mean;
77eca4a663SGreg Roach    type      = 1;
78eca4a663SGreg Roach    oldx      = ob.offsetLeft;
79eca4a663SGreg Roach    oldlinew  = 0;
80eca4a663SGreg Roach  }
81eca4a663SGreg Roach
82eca4a663SGreg Roach  document.onmousemove = function (e) {
83eca4a663SGreg Roach    var textDirection = document.documentElement.dir;
84eca4a663SGreg Roach
85eca4a663SGreg Roach    if (ob === null) {
86eca4a663SGreg Roach      return true;
87eca4a663SGreg Roach    }
88eca4a663SGreg Roach    var newx = 0;
89eca4a663SGreg Roach    var newy = 0;
90eca4a663SGreg Roach    if (type === 0) {
91eca4a663SGreg Roach      // age boxes
92eca4a663SGreg Roach      newPosition = clickPosition(e, document.getElementById("timeline_chart"));
93eca4a663SGreg Roach      newx        = newPosition.x;
94eca4a663SGreg Roach      newy        = newPosition.y;
95eca4a663SGreg Roach
96eca4a663SGreg Roach      if (oldx === 0) {
97eca4a663SGreg Roach        oldx = newx;
98eca4a663SGreg Roach      }
99eca4a663SGreg Roach      if (newy < topy - bheight / 2) {
100eca4a663SGreg Roach        newy = topy - bheight / 2;
101eca4a663SGreg Roach      }
102eca4a663SGreg Roach      if (newy > bottomy) {
103eca4a663SGreg Roach        newy = bottomy - 1;
104eca4a663SGreg Roach      }
105eca4a663SGreg Roach      ob.style.top = newy + "px";
106eca4a663SGreg Roach      var tyear    = (newy + bheight - 4 - topy + scale) / scale + baseyear;
107eca4a663SGreg Roach      var year     = Math.floor(tyear);
108eca4a663SGreg Roach      var month    = Math.floor(tyear * 12 - year * 12);
109eca4a663SGreg Roach      var day      = Math.floor(tyear * 365 - year * 365 - month * 30);
110eca4a663SGreg Roach      var mstamp   = year * 365 + month * 30 + day;
111eca4a663SGreg Roach      var bdstamp  = birthyears[personnum] * 365 + birthmonths[personnum] * 30 + birthdays[personnum];
112eca4a663SGreg Roach      var daydiff  = mstamp - bdstamp;
113eca4a663SGreg Roach      var ba       = 1;
114eca4a663SGreg Roach      if (daydiff < 0) {
115eca4a663SGreg Roach        ba      = -1;
116eca4a663SGreg Roach        daydiff = (bdstamp - mstamp);
117eca4a663SGreg Roach      }
118eca4a663SGreg Roach      var yage = Math.floor(daydiff / 365);
119eca4a663SGreg Roach      var mage = Math.floor((daydiff - yage * 365) / 30);
120eca4a663SGreg Roach      var dage = Math.floor(daydiff - yage * 365 - mage * 30);
121eca4a663SGreg Roach      if (dage < 0) {
122eca4a663SGreg Roach        mage = mage - 1;
123eca4a663SGreg Roach      }
124eca4a663SGreg Roach      if (dage < -30) {
125eca4a663SGreg Roach        dage = 30 + dage;
126eca4a663SGreg Roach      }
127eca4a663SGreg Roach      if (mage < 0) {
128eca4a663SGreg Roach        yage = yage - 1;
129eca4a663SGreg Roach      }
130eca4a663SGreg Roach      if (mage < -11) {
131eca4a663SGreg Roach        mage = 12 + mage;
132eca4a663SGreg Roach      }
133eca4a663SGreg Roach      var yearform       = document.getElementById('yearform' + personnum);
134eca4a663SGreg Roach      var ageform        = document.getElementById('ageform' + personnum);
135eca4a663SGreg Roach      yearform.innerHTML = year + "      " + month + " <?= mb_substr(I18N::translate('Month:'), 0, 1) ?>   " + day + " <?= mb_substr(I18N::translate('Day:'), 0, 1) ?>";
136eca4a663SGreg Roach      if (ba * yage > 1 || ba * yage < -1 || ba * yage === 0) {
137eca4a663SGreg 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) ?>";
138eca4a663SGreg Roach      } else {
139eca4a663SGreg 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) ?>";
140eca4a663SGreg Roach      }
141eca4a663SGreg Roach      var line = document.getElementById('ageline' + personnum);
142eca4a663SGreg Roach      var temp = newx - oldx;
143eca4a663SGreg Roach
144eca4a663SGreg Roach      if (textDirection === 'rtl') {
145eca4a663SGreg Roach        temp = temp * -1;
146eca4a663SGreg Roach      }
147eca4a663SGreg Roach      line.style.width = (line.width + temp) + "px";
148eca4a663SGreg Roach      oldx             = newx;
149eca4a663SGreg Roach      return false;
150eca4a663SGreg Roach    } else {
151eca4a663SGreg Roach      // fact boxes
152eca4a663SGreg Roach      var linewidth;
153eca4a663SGreg Roach      newPosition = clickPosition(e, document.getElementById("timeline_chart"));
154eca4a663SGreg Roach      newx        = newPosition.x;
155eca4a663SGreg Roach      newy        = newPosition.y;
156eca4a663SGreg Roach      if (oldx === 0) {
157eca4a663SGreg Roach        oldx = newx;
158eca4a663SGreg Roach      }
159eca4a663SGreg Roach      linewidth = e.pageX;
160eca4a663SGreg Roach
161eca4a663SGreg Roach      // get diagnal line box
162eca4a663SGreg Roach      var dbox = document.getElementById('dbox' + personnum);
163eca4a663SGreg Roach      var etopy;
164eca4a663SGreg Roach      var ebottomy;
165eca4a663SGreg Roach      // set up limits
166eca4a663SGreg Roach      if (boxmean - 175 < topy) {
167eca4a663SGreg Roach        etopy = topy;
168eca4a663SGreg Roach      } else {
169eca4a663SGreg Roach        etopy = boxmean - 175;
170eca4a663SGreg Roach      }
171eca4a663SGreg Roach      if (boxmean + 175 > bottomy) {
172eca4a663SGreg Roach        ebottomy = bottomy;
173eca4a663SGreg Roach      } else {
174eca4a663SGreg Roach        ebottomy = boxmean + 175;
175eca4a663SGreg Roach      }
176eca4a663SGreg Roach      // check if in the bounds of the limits
177eca4a663SGreg Roach      if (newy < etopy) {
178eca4a663SGreg Roach        newy = etopy;
179eca4a663SGreg Roach      }
180eca4a663SGreg Roach      if (newy > ebottomy) {
181eca4a663SGreg Roach        newy = ebottomy;
182eca4a663SGreg Roach      }
183eca4a663SGreg Roach      // calculate the change in Y position
184eca4a663SGreg Roach      var dy = newy - ob.offsetTop;
185eca4a663SGreg Roach      // check if we are above the starting point and switch the background image
186eca4a663SGreg Roach
187eca4a663SGreg Roach      if (newy < boxmean) {
188eca4a663SGreg Roach        if (textDirection === 'rtl') {
189e837ff07SGreg Roach          dbox.style.backgroundImage    = "url('<?= asset('css/images/dline2.png') ?>')";
190eca4a663SGreg Roach          dbox.style.backgroundPosition = "0% 0%";
191eca4a663SGreg Roach        } else {
192e837ff07SGreg Roach          dbox.style.backgroundImage    = "url('<?= asset('css/images/dline.png') ?>')";
193eca4a663SGreg Roach          dbox.style.backgroundPosition = "0% 100%";
194eca4a663SGreg Roach        }
195eca4a663SGreg Roach        dy             = -dy;
196eca4a663SGreg Roach        dbox.style.top = (newy + bheight / 3) + "px";
197eca4a663SGreg Roach      } else {
198eca4a663SGreg Roach        if (textDirection === 'rtl') {
199e837ff07SGreg Roach          dbox.style.backgroundImage    = "url('<?= asset('css/images/dline.png') ?>')";
200eca4a663SGreg Roach          dbox.style.backgroundPosition = "0% 100%";
201eca4a663SGreg Roach        } else {
202e837ff07SGreg Roach          dbox.style.backgroundImage    = "url('<?= asset('css/images/dline2.png') ?>')";
203eca4a663SGreg Roach          dbox.style.backgroundPosition = "0% 0%";
204eca4a663SGreg Roach        }
205eca4a663SGreg Roach
206eca4a663SGreg Roach        dbox.style.top = (boxmean + bheight / 3) + "px";
207eca4a663SGreg Roach      }
208eca4a663SGreg Roach      // the new X posistion moves the same as the y position
209eca4a663SGreg Roach      if (textDirection === 'rtl') {
210eca4a663SGreg Roach        newx = dbox.offsetRight + Math.abs(newy - boxmean);
211eca4a663SGreg Roach      } else {
212eca4a663SGreg Roach        newx = dbox.offsetLeft + Math.abs(newy - boxmean);
213eca4a663SGreg Roach      }
214eca4a663SGreg Roach      // set the X position of the box
215eca4a663SGreg Roach      if (textDirection === 'rtl') {
216eca4a663SGreg Roach        ob.style.right = newx + "px";
217eca4a663SGreg Roach      } else {
218eca4a663SGreg Roach        ob.style.left = newx + "px";
219eca4a663SGreg Roach      }
220eca4a663SGreg Roach      // set new top positions
221eca4a663SGreg Roach      ob.style.top     = newy + "px";
222eca4a663SGreg Roach      // get the width for the diagnal box
223eca4a663SGreg Roach      var newwidth     = (ob.offsetLeft - dbox.offsetLeft);
224eca4a663SGreg Roach      // set the width
225eca4a663SGreg Roach      dbox.style.width = newwidth + "px";
226eca4a663SGreg Roach      if (textDirection === 'rtl') {
227eca4a663SGreg Roach        dbox.style.right = (dbox.offsetRight - newwidth) + 'px';
228eca4a663SGreg Roach      }
229eca4a663SGreg Roach      dbox.style.height = newwidth + "px";
230eca4a663SGreg Roach      // change the line width to the change in the mouse X position
231eca4a663SGreg Roach      line              = document.getElementById('boxline' + personnum);
232eca4a663SGreg Roach      if (oldlinew !== 0) {
233eca4a663SGreg Roach        line.width = line.width + (linewidth - oldlinew);
234eca4a663SGreg Roach      }
235eca4a663SGreg Roach      oldlinew = linewidth;
236eca4a663SGreg Roach      oldx     = newx;
237eca4a663SGreg Roach      return false;
238eca4a663SGreg Roach    }
239eca4a663SGreg Roach  };
240eca4a663SGreg Roach
241eca4a663SGreg Roach  document.onmouseup = function () {
242eca4a663SGreg Roach    ob   = null;
243eca4a663SGreg Roach    oldx = 0;
244eca4a663SGreg Roach  }
245eca4a663SGreg Roach</script>
246eca4a663SGreg Roach
247eca4a663SGreg Roach<div id="timeline_chart">
248eca4a663SGreg Roach    <!-- print the timeline line image -->
249eca4a663SGreg Roach    <div id="line" style="position:absolute; <?= I18N::direction() === 'ltr' ? 'left:22px;' : 'right:22px;' ?> top:0;">
250e837ff07SGreg Roach        <img src="<?= e(asset('css/images/vline.png')) ?>" width="3" height="<?= 0 + ($topyear - $baseyear) * $scale ?>">
251eca4a663SGreg Roach    </div>
252eca4a663SGreg Roach
253eca4a663SGreg Roach    <!-- print divs for the grid -->
254eca4a663SGreg Roach    <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' ?>;">
255eca4a663SGreg Roach        <?= $baseyear ?>
256eca4a663SGreg Roach    </div>
257eca4a663SGreg Roach    <?php
258eca4a663SGreg Roach    // at a scale of 25 or higher, show every year
259eca4a663SGreg Roach    $mod = 25 / $scale;
260eca4a663SGreg Roach    if ($mod < 1) {
261eca4a663SGreg Roach        $mod = 1;
262eca4a663SGreg Roach    }
263eca4a663SGreg Roach    for ($i = $baseyear + 1; $i < $topyear; $i++) {
264eca4a663SGreg Roach        if ($i % $mod === 0) {
265eca4a663SGreg 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') . ';">';
266eca4a663SGreg Roach            echo $i;
267eca4a663SGreg Roach            echo '</div>';
268eca4a663SGreg Roach        }
269eca4a663SGreg Roach    }
270eca4a663SGreg Roach    echo '';
271eca4a663SGreg Roach    ?>
272eca4a663SGreg Roach    <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' ?>;">
273eca4a663SGreg Roach        <?= e($topyear) ?>
274eca4a663SGreg Roach    </div>
275eca4a663SGreg Roach
276eca4a663SGreg Roach    <?php foreach ($indifacts as $factcount => $event) : ?>
277eca4a663SGreg Roach        <?php
278eca4a663SGreg Roach        $desc     = $event->value();
279eca4a663SGreg Roach        $gdate    = $event->date();
280eca4a663SGreg Roach        $date     = $gdate->minimumDate();
281eca4a663SGreg Roach        $date     = $date->convertToCalendar('gregorian');
282eca4a663SGreg Roach        $year     = $date->year();
283eca4a663SGreg Roach        $month    = max(1, $date->month());
284eca4a663SGreg Roach        $day      = max(1, $date->day());
285eca4a663SGreg Roach        $xoffset  = 0 + 22;
286eca4a663SGreg Roach        $yoffset  = 0 + (($year - $baseyear) * $scale) - ($scale);
287eca4a663SGreg Roach        $yoffset  = $yoffset + (($month / 12) * $scale);
288eca4a663SGreg Roach        $yoffset  = $yoffset + (($day / 30) * ($scale / 12));
289eca4a663SGreg Roach        $yoffset  = (int) ($yoffset);
290eca4a663SGreg Roach        $place    = (int) ($yoffset / $bheight);
291eca4a663SGreg Roach        $i        = 1;
292eca4a663SGreg Roach        $j        = 0;
293eca4a663SGreg Roach        $tyoffset = 0;
294eca4a663SGreg Roach        while (isset($placements[$place])) {
295eca4a663SGreg Roach            if ($i === $j) {
296eca4a663SGreg Roach                $tyoffset = $bheight * $i;
297eca4a663SGreg Roach                $i++;
298eca4a663SGreg Roach            } else {
299eca4a663SGreg Roach                $tyoffset = -1 * $bheight * $j;
300eca4a663SGreg Roach                $j++;
301eca4a663SGreg Roach            }
302eca4a663SGreg Roach            $place = (int) (($yoffset + $tyoffset) / $bheight);
303eca4a663SGreg Roach        }
304eca4a663SGreg Roach        $yoffset            += $tyoffset;
305eca4a663SGreg Roach        $xoffset            += abs($tyoffset);
306eca4a663SGreg Roach        $placements[$place] = $yoffset;
307eca4a663SGreg Roach
308eca4a663SGreg 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) . ');">';
309eca4a663SGreg Roach        echo '<table cellspacing="0" cellpadding="0" border="0" style="cursor: hand;"><tr><td>';
310e837ff07SGreg Roach        echo '<img src="' . e(asset('css/images/hline.png')) . '" name="boxline' . $factcount . '" id="boxline' . $factcount . '" height="3" width="10" style="padding-';
311eca4a663SGreg Roach        if (I18N::direction() === 'ltr') {
312eca4a663SGreg Roach            echo 'left: 3px;">';
313eca4a663SGreg Roach        } else {
314eca4a663SGreg Roach            echo 'right: 3px;">';
315eca4a663SGreg Roach        }
316eca4a663SGreg Roach
317eca4a663SGreg Roach        $col = array_search($event->record(), $individuals);
318eca4a663SGreg Roach        if ($col === false) {
319eca4a663SGreg Roach            // Marriage event - use the color of the husband
320*39ca88baSGreg Roach            $col = array_search($event->record()->husband(), $individuals);
321eca4a663SGreg Roach        }
322eca4a663SGreg Roach        if ($col === false) {
323eca4a663SGreg Roach            // Marriage event - use the color of the wife
324*39ca88baSGreg Roach            $col = array_search($event->record()->wife(), $individuals);
325eca4a663SGreg Roach        }
326eca4a663SGreg Roach        $col = $col % 6;
327eca4a663SGreg Roach        echo '</td><td class="person' . $col . '">';
328eca4a663SGreg Roach        if (count($individuals) > 6) {
329eca4a663SGreg Roach            // We only have six colours, so show naes if more than this number
330*39ca88baSGreg Roach            echo $event->record()->fullName() . ' — ';
331eca4a663SGreg Roach        }
332eca4a663SGreg Roach        $record = $event->record();
333eca4a663SGreg Roach        echo $event->label();
334eca4a663SGreg Roach        echo ' — ';
335eca4a663SGreg Roach        if ($record instanceof Individual) {
336eca4a663SGreg Roach            echo FunctionsPrint::formatFactDate($event, $record, false, false);
337eca4a663SGreg Roach        } elseif ($record instanceof Family) {
338eca4a663SGreg Roach            echo $gdate->display();
339*39ca88baSGreg Roach            if ($record->husband() && $record->husband()->getBirthDate()->isOK()) {
340*39ca88baSGreg Roach                $ageh = FunctionsDate::getAgeAtEvent(Date::getAgeGedcom($record->husband()->getBirthDate(), $gdate));
341eca4a663SGreg Roach            } else {
342eca4a663SGreg Roach                $ageh = null;
343eca4a663SGreg Roach            }
344*39ca88baSGreg Roach            if ($record->wife() && $record->wife()->getBirthDate()->isOK()) {
345*39ca88baSGreg Roach                $agew = FunctionsDate::getAgeAtEvent(Date::getAgeGedcom($record->wife()->getBirthDate(), $gdate));
346eca4a663SGreg Roach            } else {
347eca4a663SGreg Roach                $agew = null;
348eca4a663SGreg Roach            }
349eca4a663SGreg Roach            if ($ageh && $agew) {
350eca4a663SGreg Roach                echo '<span class="age"> ', I18N::translate('Husband’s age'), ' ', $ageh, ' ', I18N::translate('Wife’s age'), ' ', $agew, '</span>';
351eca4a663SGreg Roach            } elseif ($ageh) {
352eca4a663SGreg Roach                echo '<span class="age"> ', I18N::translate('Age'), ' ', $ageh, '</span>';
353eca4a663SGreg Roach            } elseif ($agew) {
354eca4a663SGreg Roach                echo '<span class="age"> ', I18N::translate('Age'), ' ', $ageh, '</span>';
355eca4a663SGreg Roach            }
356eca4a663SGreg Roach        }
357eca4a663SGreg Roach        echo ' ' . e($desc);
35829e68993SGreg Roach        if ($event->place()->gedcomName() !== '') {
359392561bbSGreg Roach            echo ' — ' . $event->place()->shortName();
360eca4a663SGreg Roach        }
361eca4a663SGreg Roach        // Print spouses names for family events
362eca4a663SGreg Roach        if ($event->record() instanceof Family) {
363*39ca88baSGreg Roach            echo ' — <a href="', e($event->record()->url()), '">', $event->record()->fullName(), '</a>';
364eca4a663SGreg Roach        }
365eca4a663SGreg Roach        echo '</td></tr></table>';
366eca4a663SGreg Roach        echo '</div>';
367eca4a663SGreg Roach        if (I18N::direction() === 'ltr') {
368e837ff07SGreg Roach            $img  = asset('css/images/dline2.png');
369eca4a663SGreg Roach            $ypos = '0%';
370eca4a663SGreg Roach        } else {
371e837ff07SGreg Roach            $img  = asset('css/images/dline.png');
372eca4a663SGreg Roach            $ypos = '100%';
373eca4a663SGreg Roach        }
374eca4a663SGreg Roach        $dyoffset = ($yoffset - $tyoffset) + $bheight / 3;
375eca4a663SGreg Roach        if ($tyoffset < 0) {
376eca4a663SGreg Roach            $dyoffset = $yoffset + $bheight / 3;
377eca4a663SGreg Roach            if (I18N::direction() === 'ltr') {
378e837ff07SGreg Roach                $img  = asset('css/images/dline.png');
379eca4a663SGreg Roach                $ypos = '100%';
380eca4a663SGreg Roach            } else {
381e837ff07SGreg Roach                $img  = asset('css/images/dline2.png');
382eca4a663SGreg Roach                $ypos = '0%';
383eca4a663SGreg Roach            }
384eca4a663SGreg Roach        }
385eca4a663SGreg Roach        ?>
386eca4a663SGreg Roach
387eca4a663SGreg Roach        <!-- diagonal line -->
388e837ff07SGreg 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 ?>;">
389eca4a663SGreg Roach        </div>
390eca4a663SGreg Roach    <?php endforeach ?>
391eca4a663SGreg Roach
392eca4a663SGreg Roach    <!-- age cursors -->
393eca4a663SGreg Roach    <?php foreach ($individuals as $p => $indi) : ?>
394eca4a663SGreg Roach        <?php $ageyoffset = 0 + ($bheight * $p); ?>
395eca4a663SGreg 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 ?>);">
396eca4a663SGreg Roach            <table cellspacing="0" cellpadding="0">
397eca4a663SGreg Roach                <tr>
398eca4a663SGreg Roach                    <td>
399e837ff07SGreg Roach                        <img src="<?= e(asset('css/images/hline.png')) ?>" name="ageline<?= $p ?>" id="ageline<?= $p ?>" width="25" height="3">
400eca4a663SGreg Roach                    </td>
401eca4a663SGreg Roach                    <td>
402eca4a663SGreg Roach                        <?php if (!empty($birthyears[$indi->xref()])) : ?>
403eca4a663SGreg Roach                            <?php $tyear = round(($ageyoffset + ($bheight / 2)) / $scale) + $baseyear; ?>
404eca4a663SGreg Roach                            <table class="person<?= $p % 6 ?>" style="cursor: hand;">
405eca4a663SGreg Roach                                <tr>
406eca4a663SGreg Roach                                    <td>
407eca4a663SGreg Roach                                        <?= I18N::translate('Year:') ?>
408eca4a663SGreg Roach                                        <span id="yearform<?= $p ?>" class="field">
409eca4a663SGreg Roach                                            <?= $tyear ?>
410eca4a663SGreg Roach                                        </span>
411eca4a663SGreg Roach                                    </td>
412eca4a663SGreg Roach                                    <td>
413eca4a663SGreg Roach                                        (<?= I18N::translate('Age') ?> <span id="ageform<?= $p ?>" class="field"><?= $tyear - $birthyears[$indi->xref()] ?></span>)
414eca4a663SGreg Roach                                    </td>
415eca4a663SGreg Roach                                </tr>
416eca4a663SGreg Roach                            </table>
417eca4a663SGreg Roach                        <?php endif ?>
418eca4a663SGreg Roach                    </td>
419eca4a663SGreg Roach                </tr>
420eca4a663SGreg Roach            </table>
421eca4a663SGreg Roach            <br>
422eca4a663SGreg Roach            <br>
423eca4a663SGreg Roach            <br>
424eca4a663SGreg Roach        </div>
425eca4a663SGreg Roach        <br>
426eca4a663SGreg Roach        <br>
427eca4a663SGreg Roach        <br>
428eca4a663SGreg Roach        <br>
429eca4a663SGreg Roach    <?php endforeach ?>
430eca4a663SGreg Roach</div>
431