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\ModuleInterface; ?> 6<?php use Fisharebest\Webtrees\Module\RelationshipsChartModule; ?> 7<?php use Fisharebest\Webtrees\Services\ModuleService; ?> 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 = app(ModuleService::class)->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 <span title="<?= I18N::translate('Anniversary') ?>"> 212 <?= view('icons/anniversary') ?> 213 </span> 214 </th> 215 <th><?= I18N::translate('Place') ?></th> 216 <th> 217 <i class="icon-children" title="<?= I18N::translate('Children') ?>"></i> 218 </th> 219 <th><?= I18N::translate('Death') ?></th> 220 <th> 221 <span title="<?= I18N::translate('Anniversary') ?>"> 222 <?= view('icons/anniversary') ?> 223 </span> 224 </th> 225 <th><?= I18N::translate('Age') ?></th> 226 <th><?= I18N::translate('Place') ?></th> 227 <th><?= I18N::translate('Last change') ?></th> 228 <th hidden></th> 229 <th hidden></th> 230 <th hidden></th> 231 <th hidden></th> 232 </tr> 233 </thead> 234 <tfoot> 235 <tr> 236 <th colspan="16"> 237 <div class="btn-toolbar"> 238 <div class="btn-group"> 239 <button class="ui-state-default btn-toggle-parents"> 240 <?= I18N::translate('Show parents') ?> 241 </button> 242 <button class="ui-state-default btn-toggle-statistics"> 243 <?= I18N::translate('Show statistics charts') ?> 244 </button> 245 </div> 246 </div> 247 </th> 248 </tr> 249 </tfoot> 250 251 <tbody> 252 <?php foreach ($individuals as $key => $individual) : ?> 253 <tr class="<?= $individual->isPendingDeletion() ? 'old' : ($individual->isPendingAddition() ? 'new' : '') ?>"> 254 <td colspan="2" data-sort="<?= e(str_replace([',', '@P.N.', '@N.N.'], 'AAAA', implode(',', array_reverse(explode(',', $individual->sortName()))))) ?>"> 255 <?php foreach ($individual->getAllNames() as $num => $name) : ?> 256 <a title="<?= $name['type'] === 'NAME' ? '' : GedcomTag::getLabel($name['type'], $individual) ?>" href="<?= e($individual->url()) ?>" class="<?= $num === $individual->getPrimaryName() ? 'name2' : '' ?>"> 257 <?= $name['full'] ?> 258 </a> 259 <?php if ($num === $individual->getPrimaryName()) : ?> 260 <?= $individual->getSexImage() ?> 261 <?php endif ?> 262 <br> 263 <?php endforeach ?> 264 <?= $individual->getPrimaryParentsNames('parents details1', 'none') ?> 265 </td> 266 267 <td hidden data-sort="<?= e(str_replace([',', '@P.N.', '@N.N.'], 'AAAA', $individual->sortName())) ?>"></td> 268 269 <td class="text-center" data-sort="<?= $key ?>"> 270 <?php if ($sosa) : ?> 271 <?php if ($module instanceof RelationshipsChartModule) : ?> 272 <a href="<?= e($module->chartUrl($individuals[1], ['xref2' => $individual->xref()])) ?>" rel="nofollow" title="<?= I18N::translate('Relationships') ?>" rel="nofollow"> 273 <?= I18N::number($key) ?> 274 </a> 275 <?php else : ?> 276 <?= I18N::number($key) ?> 277 <?php endif ?> 278 <?php endif ?> 279 </td> 280 281 <!-- Birth date --> 282 <td data-sort="<?= $individual->getEstimatedBirthDate()->julianDay() ?>"> 283 <?php $birth_dates = $individual->getAllBirthDates(); ?> 284 285 <?php foreach ($birth_dates as $n => $birth_date) : ?> 286 <?= $birth_date->display(true) ?> 287 <br> 288 <?php endforeach ?> 289 </td> 290 291 <!-- Birth anniversary --> 292 <td class="text-center" data-sort="<?= -$individual->getEstimatedBirthDate()->julianDay() ?>"> 293 <?php if (isset($birth_dates[0]) && $birth_dates[0]->gregorianYear() >= 1550 && $birth_dates[0]->gregorianYear() < 2030 && !isset($unique_indis[$individual->xref()])) : ?> 294 <?php $birt_by_decade[(int) ($birth_dates[0]->gregorianYear() / 10) * 10] .= $individual->sex() ?> 295 <?= Date::getAge($birth_dates[0], null) ?> 296 <?php endif ?> 297 </td> 298 299 <!-- Birth place --> 300 <td> 301 <?php foreach ($individual->getAllBirthPlaces() as $n => $birth_place) : ?> 302 <?= $birth_place->shortName(true) ?> 303 <br> 304 <?php endforeach ?> 305 </td> 306 307 <!-- Number of children --> 308 <td class="text-center" data-sort="<?= $individual->numberOfChildren() ?>"> 309 <?= I18N::number($individual->numberOfChildren()) ?> 310 </td> 311 312 <!-- Death date --> 313 <?php $death_dates = $individual->getAllDeathDates() ?> 314 <td data-sort="<?= $individual->getEstimatedDeathDate()->julianDay() ?>"> 315 <?php foreach ($death_dates as $num => $death_date) : ?> 316 <?= $death_date->display(true) ?> 317 <br> 318 <?php endforeach ?> 319 </td> 320 321 <!-- Death anniversary --> 322 <td class="text-center" data-sort="<?= -$individual->getEstimatedDeathDate()->julianDay() ?>"> 323 <?php if (isset($death_dates[0]) && $death_dates[0]->gregorianYear() >= 1550 && $death_dates[0]->gregorianYear() < 2030 && !isset($unique_indis[$individual->xref()])) : ?> 324 <?php $deat_by_decade[(int) ($death_dates[0]->gregorianYear() / 10) * 10] .= $individual->sex() ?> 325 <?= Date::getAge($death_dates[0], null) ?> 326 <?php endif ?> 327 </td> 328 329 <!-- Age at death --> 330 <?php if (isset($birth_dates[0]) && isset($death_dates[0])) : ?> 331 <?php $age_at_death = I18N::number((int) Date::getAgeYears($birth_dates[0], $death_dates[0])); ?> 332 <?php $age_at_death_sort = Date::getAge($birth_dates[0], $death_dates[0]); ?> 333 <?php if (!isset($unique_indis[$individual->xref()]) && $age_at_death >= 0 && $age_at_death <= $max_age) : ?> 334 <?php $deat_by_age[$age_at_death] .= $individual->sex(); ?> 335 <?php endif ?> 336 <?php else : ?> 337 <?php $age_at_death = ''; ?> 338 <?php $age_at_death_sort = PHP_INT_MAX; ?> 339 <?php endif ?> 340 <td class="text-center" data-sort="<?= e($age_at_death_sort) ?>"> 341 <?= e($age_at_death) ?> 342 </td> 343 344 <!-- Death place --> 345 <td> 346 <?php foreach ($individual->getAllDeathPlaces() as $n => $death_place) : ?> 347 <?= $death_place->shortName(true) ?> 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->sex() ?> 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->childFamilies()) : ?> 385 R 386 <?php elseif (!$individual->isDead() && $individual->numberOfChildren() < 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