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