xref: /webtrees/resources/views/lists/families-table.phtml (revision 37231d1e839cad24e911f38c73f4dc77a58e3eec)
1<?php use Fisharebest\Webtrees\Date; ?>
2<?php use Fisharebest\Webtrees\GedcomTag; ?>
3<?php use Fisharebest\Webtrees\I18N; ?>
4<?php use Fisharebest\Webtrees\Individual; ?>
5<?php use Fisharebest\Webtrees\View; ?>
6<?php use Ramsey\Uuid\Uuid; ?>
7
8<?php
9$table_id = 'table-fam-' . Uuid::uuid4()->toString(); // lists requires a unique ID in case there are multiple lists per page
10$hundred_years_ago = new Date(date('Y') - 100);
11?>
12
13<?php View::push('javascript') ?>
14<script>
15    $("#<?= e($table_id) ?>").dataTable( {
16dom: '<"H"<"filtersH_<?= e($table_id) ?>"><"dt-clear">pf<"dt-clear">irl>t<"F"pl<"dt-clear"><"filtersF_<?= e($table_id) ?>">>',
17<?= I18N::datatablesI18N() ?>,
18autoWidth: false,
19processing: true,
20retrieve: true,
21columns: [
22/* Given names         */ { type: "text" },
23/* Surnames            */ { type: "text" },
24/* Age                 */ { type: "num" },
25/* Given names         */ { type: "text" },
26/* Surnames            */ { type: "text" },
27/* Age                 */ { type: "num" },
28/* Marriage date       */ { type: "num" },
29/* Anniversary         */ { type: "num" },
30/* Marriage place      */ { type: "text" },
31/* Children            */ { type: "num" },
32/* Last change         */ { visible: <?= json_encode((bool) $tree->getPreference('SHOW_LAST_CHANGE')) ?> },
33/* Filter marriage     */ { sortable: false },
34/* Filter alive/dead   */ { sortable: false },
35/* Filter tree         */ { sortable: false }
36],
37sorting: [[1, "asc"]],
38displayLength: 20,
39pagingType: "full_numbers"
40})
41/* Hide/show parents */
42.on("click", ".btn-toggle-parents", function() {
43$(this).toggleClass("ui-state-active");
44$(".parents", $(this).closest("table").DataTable().rows().nodes()).slideToggle();
45})
46/* Hide/show statistics */
47.on("click",  ".btn-toggle-statistics", function() {
48$(this).toggleClass("ui-state-active");
49$("#family-charts-<?= e($table_id) ?>").slideToggle();
50})
51/* Filter buttons in table header */
52.on("click", "button[data-filter-column]", function() {
53var btn = $(this);
54// De-activate the other buttons in this button group
55btn.siblings().removeClass("active");
56// Apply (or clear) this filter
57var col = $("#<?= e($table_id) ?>").DataTable().column(btn.data("filter-column"));
58if (btn.hasClass("active")) {
59col.search("").draw();
60} else {
61col.search(btn.data("filter-value")).draw();
62}
63});
64</script>
65<?php View::endpush() ?>
66
67<?php
68$max_age = (int) $tree->getPreference('MAX_ALIVE_AGE');
69
70// init chart data
71$marr_by_age = [];
72for ($age = 0; $age <= $max_age; $age++) {
73    $marr_by_age[$age] = '';
74}
75$birt_by_decade = [];
76$marr_by_decade = [];
77for ($year = 1550; $year < 2030; $year += 10) {
78    $birt_by_decade[$year] = '';
79    $marr_by_decade[$year] = '';
80}
81?>
82
83<div class="fam-list">
84    <table id="<?= e($table_id) ?>">
85        <thead>
86            <tr>
87                <th colspan="14">
88                    <div class="btn-toolbar d-flex justify-content-between mb-2">
89                        <div class="btn-group" data-toggle="buttons">
90                            <button
91                                class="btn btn-secondary"
92                                data-filter-column="12"
93                                data-filter-value="N"
94                                title="' . I18N::translate('Show individuals who are alive or couples where both partners are alive.') ?>"
95                            >
96                                <?= I18N::translate('Both alive') ?>
97                            </button>
98                            <button
99                                class="btn btn-secondary"
100                                data-filter-column="12"
101                                data-filter-value="W"
102                                title="<?= I18N::translate('Show couples where only the female partner is dead.') ?>"
103                            >
104                                <?= I18N::translate('Widower') ?>
105                            </button>
106                            <button
107                                class="btn btn-secondary"
108                                data-filter-column="12"
109                                data-filter-value="H"
110                                title="<?= I18N::translate('Show couples where only the male partner is dead.') ?>"
111                            >
112                                <?= I18N::translate('Widow') ?>
113                            </button>
114                            <button
115                                class="btn btn-secondary"
116                                data-filter-column="12"
117                                data-filter-value="Y"
118                                title="<?= I18N::translate('Show individuals who are dead or couples where both partners are dead.') ?>"
119                            >
120                                <?= I18N::translate('Both dead') ?>
121                            </button>
122                        </div>
123                        <div class="btn-group" data-toggle="buttons">
124                            <button
125                                class="btn btn-secondary"
126                                data-filter-column="13"
127                                data-filter-value="R"
128                                title="<?= I18N::translate('Show “roots” couples or individuals. These individuals may also be called “patriarchs”. They are individuals who have no parents recorded in the database.') ?>"
129                            >
130                                <?= I18N::translate('Roots') ?>
131                            </button>
132                            <button
133                                class="btn btn-secondary"
134                                data-filter-column="13"
135                                data-filter-value="L"
136                                title="<?= I18N::translate('Show “leaves” couples or individuals. These are individuals who are alive but have no children recorded in the database.') ?>"
137                            >
138                                <?= I18N::translate('Leaves') ?>
139                            </button>
140                        </div>
141                        <div class="btn-group" data-toggle="buttons">
142                            <button
143                                class="btn btn-secondary"
144                                data-filter-column="11"
145                                data-filter-value="U"
146                                title="<?= I18N::translate('Show couples with an unknown marriage date.') ?>"
147                            >
148                                <?= I18N::translate('Marriage') ?>
149                            </button>
150                            <button
151                                class="btn btn-secondary"
152                                data-filter-column="11"
153                                data-filter-value="YES"
154                                title="<?= I18N::translate('Show couples who married more than 100 years ago.') ?>"
155                            >
156                                <?= I18N::translate('Marriage') ?>&gt;100
157                            </button>
158                            <button
159                                class="btn btn-secondary"
160                                data-filter-column="11"
161                                data-filter-value="Y100"
162                                title="<?= I18N::translate('Show couples who married within the last 100 years.') ?>"
163                            >
164                                <?= I18N::translate('Marriage') ?>&lt;=100
165                            </button>
166                            <button
167                                class="btn btn-secondary"
168                                data-filter-column="11"
169                                data-filter-value="D"
170                                title="<?= I18N::translate('Show divorced couples.') ?>"
171                            >
172                                <?= I18N::translate('Divorce') ?>
173                            </button>
174                            <button
175                                class="btn btn-secondary"
176                                data-filter-column="11"
177                                data-filter-value="M"
178                                title="<?= I18N::translate('Show couples where either partner married more than once.') ?>"
179                            >
180                                <?= I18N::translate('Multiple marriages') ?>
181                            </button>
182                        </div>
183                    </div>
184                </th>
185            </tr>
186            <tr>
187                <th><?= I18N::translate('Given names') ?></th>
188                <th><?= I18N::translate('Surname') ?></th>
189                <th><?= I18N::translate('Age') ?></th>
190                <th><?= I18N::translate('Given names') ?></th>
191                <th><?= I18N::translate('Surname') ?></th>
192                <th><?= I18N::translate('Age') ?></th>
193                <th><?= I18N::translate('Marriage') ?></th>
194                <th><i class="icon-reminder" title="<?= I18N::translate('Anniversary') ?>"></i></th>
195                <th><?= I18N::translate('Place') ?></th>
196                <th><i class="icon-children" title="<?= I18N::translate('Children') ?>"></i></th>
197                <th><?= I18N::translate('Last change') ?></th>
198                <th hidden></th>
199                <th hidden></th>
200                <th hidden></th>
201            </tr>
202        </thead>
203
204        <tfoot>
205            <tr>
206                <th colspan="14">
207                    <div class="btn-toolbar">
208                        <div class="btn-group">
209                            <button class="ui-state-default btn-toggle-parents">
210                                <?= I18N::translate('Show parents') ?>
211                            </button>
212                            <button class="ui-state-default btn-toggle-statistics">
213                                <?= I18N::translate('Show statistics charts') ?>
214                            </button>
215                        </div>
216                    </div>
217                </th>
218            </tr>
219        </tfoot>
220        <tbody>
221
222        <?php foreach ($families as $family) : ?>
223            <?php $husb = $family->getHusband() ?? new Individual('H', '0 @H@ INDI', null, $family->getTree()) ?>
224            <?php $wife = $family->getWife() ?? new Individual('W', '0 @W@ INDI', null, $family->getTree()) ?>
225
226            <tr class="<?= $family->isPendingDeletion() ? 'old' : ($family->isPendingAddition() ? 'new' : '') ?>">
227                <!-- Husband name -->
228                <td colspan="2" data-sort="<?= e(str_replace([',', '@P.N.', '@N.N.'], 'AAAA', implode(',', array_reverse(explode(',', $husb->getSortName()))))) ?>">
229                    <?php foreach ($husb->getAllNames() as $num => $name) : ?>
230                        <?php if ($name['type'] != '_MARNM' || $num == $husb->getPrimaryName()) : ?>
231                        <a title="<?= $name['type'] === 'NAME' ? '' : GedcomTag::getLabel($name['type'], $husb) ?>" href="<?= e($family->url()) ?>" class="<?= $num === $husb->getPrimaryName() ? 'name2' : '' ?>">
232                            <?= $name['full'] ?>
233                        </a>
234                            <?php if ($num === $husb->getPrimaryName()) : ?>
235                                <?= $husb->getSexImage() ?>
236                            <?php endif ?>
237                        <br>
238                        <?php endif ?>
239                    <?php endforeach ?>
240                    <?= $husb->getPrimaryParentsNames('parents details1', 'none') ?>
241                </td>
242
243                <td hidden data-sort="<?= e(str_replace([',', '@P.N.', '@N.N.'], 'AAAA', $husb->getSortName())) ?>"></td>
244
245                <!-- Husband age -->
246                <?php
247                $mdate = $family->getMarriageDate();
248                $hdate = $husb->getBirthDate();
249                if ($hdate->isOK() && $mdate->isOK()) {
250                    if ($hdate->gregorianYear() >= 1550 && $hdate->gregorianYear() < 2030) {
251                        $birt_by_decade[(int) ($hdate->gregorianYear() / 10) * 10] .= $husb->getSex();
252                    }
253                    $hage = Date::getAgeYears($hdate, $mdate);
254                    if ($hage >= 0 && $hage <= $max_age) {
255                        $marr_by_age[$hage] .= $husb->getSex();
256                    }
257                }
258                ?>
259                <td class="center" data-sort="<?= Date::getAgeDays($hdate, $mdate) ?>">
260                    <?= Date::getAge($hdate, $mdate) ?>
261                </td>
262
263                <!-- Wife name -->
264                <td colspan="2" data-sort="<?= e(str_replace([',', '@P.N.', '@N.N.'], 'AAAA', implode(',', array_reverse(explode(',', $wife->getSortName()))))) ?>">
265                    <?php foreach ($wife->getAllNames() as $num => $name) : ?>
266                        <?php if ($name['type'] != '_MARNM' || $num == $wife->getPrimaryName()) : ?>
267                            <a title="<?= $name['type'] === 'NAME' ? '' : GedcomTag::getLabel($name['type'], $wife) ?>" href="<?= e($family->url()) ?>" class="<?= $num === $wife->getPrimaryName() ? 'name2' : '' ?>">
268                                <?= $name['full'] ?>
269                            </a>
270                            <?php if ($num === $wife->getPrimaryName()) : ?>
271                                <?= $wife->getSexImage() ?>
272                            <?php endif ?>
273                            <br>
274                        <?php endif ?>
275                    <?php endforeach ?>
276                    <?= $wife->getPrimaryParentsNames('parents details1', 'none') ?>
277                </td>
278
279                <td hidden data-sort="<?= e(str_replace([',', '@P.N.', '@N.N.'], 'AAAA', $wife->getSortName())) ?>"></td>
280
281                <!-- Wife age -->
282                <?php
283                $wdate = $wife->getBirthDate();
284                if ($wdate->isOK() && $mdate->isOK()) {
285                    if ($wdate->gregorianYear() >= 1550 && $wdate->gregorianYear() < 2030) {
286                        $birt_by_decade[(int) ($wdate->gregorianYear() / 10) * 10] .= $wife->getSex();
287                    }
288                    $wage = Date::getAgeYears($wdate, $mdate);
289                    if ($wage >= 0 && $wage <= $max_age) {
290                        $marr_by_age[$wage] .= $wife->getSex();
291                    }
292                }
293                ?>
294
295                <td class="center" data-sort="<?= Date::getAgeDays($wdate, $mdate) ?>">
296                    <?= Date::getAge($wdate, $mdate) ?>
297                </td>
298
299                <!-- Marriage date -->
300                <td data-sort="<?= $family->getMarriageDate()->julianDay() ?>">
301                    <?php if ($marriage_dates = $family->getAllMarriageDates()) : ?>
302                        <?php foreach ($marriage_dates as $n => $marriage_date) : ?>
303                            <div><?= $marriage_date->display(true) ?></div>
304                        <?php endforeach ?>
305                        <?php if ($marriage_dates[0]->gregorianYear() >= 1550 && $marriage_dates[0]->gregorianYear() < 2030) : ?>
306                            <?php $marr_by_decade[(int) ($marriage_dates[0]->gregorianYear() / 10) * 10] .= $husb->getSex() . $wife->getSex() ?>
307                        <?php endif ?>
308                    <?php elseif ($family->getFacts('_NMR')) : ?>
309                        <?= I18N::translate('no') ?>
310                    <?php elseif ($family->getFacts('MARR')) : ?>
311                            <?= I18N::translate('yes') ?>
312                    <?php endif ?>
313                </td>
314
315                <!-- Marriage anniversary -->
316                <td class="center" data-sort="<?= -$family->getMarriageDate()->julianDay() ?>">
317                    <?= Date::getAge($family->getMarriageDate(), null) ?>
318                </td>
319
320                <!-- Marriage place -->
321                <td>
322                    <?php foreach ($family->getAllMarriagePlaces() as $n => $marriage_place) : ?>
323                        <a href="<?= $marriage_place->getURL() ?>" title="<?= strip_tags($marriage_place->getFullName()) ?>">
324                            <?= $marriage_place->getShortName() ?>
325                        </a>
326                        <br>
327                    <?php endforeach ?>
328                </td>
329
330                <!-- Number of children -->
331                <td class="center" data-sort="<?= $family->getNumberOfChildren() ?>">
332                    <?= I18N::number($family->getNumberOfChildren()) ?>
333                </td>
334
335                <!-- Last change -->
336                <td data-sort="<?= $family->lastChangeTimestamp(true) ?>">
337                    <?= $family->lastChangeTimestamp() ?>
338                </td>
339
340                <!-- Filter by marriage date -->
341                <td hidden>
342                    <?php if (!$family->canShow() || !$mdate->isOK()) : ?>
343                        U
344                    <?php elseif (Date::compare($mdate, $hundred_years_ago) > 0) : ?>
345                        Y100
346                    <?php else : ?>
347                        YES
348                    <?php endif ?>
349                    <?php if ($family->getFacts(WT_EVENTS_DIV)) : ?>
350                        D
351                    <?php endif ?>
352                    <?php if (count($husb->getSpouseFamilies()) > 1 || count($wife->getSpouseFamilies()) > 1) : ?>
353                        M
354                    <?php endif ?>
355                </td>
356
357                <!-- Filter by alive/dead -->
358                <td hidden>
359                    <?php if ($husb->isDead() && $wife->isDead()) : ?>
360                        Y
361                    <?php endif ?>
362                    <?php if ($husb->isDead() && !$wife->isDead()) : ?>
363                        <?php if ($wife->getSex() == 'F') : ?>
364                            H
365                        <?php endif ?>
366                        <?php if ($wife->getSex() == 'M') : ?>
367                            W
368                        <?php endif ?>
369                    <?php endif ?>
370                    <?php if (!$husb->isDead() && $wife->isDead()) : ?>
371                        <?php if ($husb->getSex() == 'M') : ?>
372                            W
373                        <?php endif ?>
374                        <?php if ($husb->getSex() == 'F') : ?>
375                            H
376                        <?php endif ?>
377                    <?php endif ?>
378                    <?php if (!$husb->isDead() && !$wife->isDead()) : ?>
379                        N
380                    <?php endif ?>
381                </td>
382
383                <!-- Filter by roots/leaves -->
384                <td hidden>
385                    <?php if (!$husb->getChildFamilies() && !$wife->getChildFamilies()) : ?>
386                        R
387                    <?php elseif (!$husb->isDead() && !$wife->isDead() && $family->getNumberOfChildren() === 0) : ?>
388                        L
389                    <?php endif ?>
390                </td>
391            </tr>
392        <?php endforeach ?>
393        </tbody>
394    </table>
395
396    <div id="family-charts-<?= e($table_id) ?>" style="display:none">
397        <table class="list-charts">
398            <tr>
399                <td>
400                    <?= view('lists/chart-by-decade', ['data' => $birt_by_decade, 'title' => I18N::translate('Decade of birth')]) ?>
401        </td>
402        <td>
403                    <?= view('lists/chart-by-decade', ['data' => $marr_by_decade, 'title' => I18N::translate('Decade of marriage')]) ?>
404                </td>
405            </tr>
406            <tr>
407                <td colspan="2">
408                    <?= view('lists/chart-by-age', ['data' => $marr_by_age, 'title' => I18N::translate('Age in year of marriage')]) ?>
409                </td>
410            </tr>
411        </table>
412    </div>
413</div>
414