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