/** * {@inheritDoc} * @see \MyArtJaub\Webtrees\Map\MapProviderInterface::getPlaceIcon() */ public function getPlaceIcon(\Fisharebest\Webtrees\Place $place) { if (!$place->isEmpty()) { $place_details = Database::prepare('SELECT SQL_CACHE pl_icon FROM `##placelocation` WHERE pl_id=? ORDER BY pl_place')->execute(array($this->getProviderPlaceId($place)))->fetchOneRow(); if ($place_details) { return WT_MODULES_DIR . 'googlemap/' . $place_details->pl_icon; } } return null; }
echo '</ul>'; echo '</div>'; // close div="find-media-media" } } else { echo '<p>', I18N::translate('No results found.'), '</p>'; } echo '</div>'; } // Output Places if ($type == "place") { echo '<div id="find-output">'; if (!$filter || $all) { $places = Place::allPlaces($WT_TREE); } else { $places = Place::findPlaces($filter, $WT_TREE); } if ($places) { echo '<ul>'; foreach ($places as $place) { echo '<li><a href="#" onclick="pasteid(\'', Filter::escapeJs($place->getGedcomName()), '\');">'; if (!$filter || $all) { echo $place->getReverseName(); // When displaying all names, sort/display by the country, then region, etc. } else { echo $place->getFullName(); // When we’ve searched for a place, sort by this place } echo '</a></li>'; } echo '</ul>
/** * {@inhericDoc} * @see \MyArtJaub\Webtrees\Mvc\View\AbstractView::renderContent() */ protected function renderContent() { if ($this->data->get('has_sosa', false)) { $table_id = $this->data->get('table_id'); ?> <div id="sosa-fam-list" class="sosa-list"> <table id="<?php echo $table_id; ?> "> <thead> <tr> <th colspan="24"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" data-filter-column="22" data-filter-value="N" class="ui-state-default" title="<?php echo I18N::translate('Show individuals who are alive or couples where both partners are alive.'); ?> " > <?php echo I18N::translate('Both alive'); ?> </button> <button type="button" data-filter-column="22" data-filter-value="W" class="ui-state-default" title="<?php echo I18N::translate('Show couples where only the female partner is deceased.'); ?> " > <?php echo I18N::translate('Widower'); ?> </button> <button type="button" data-filter-column="22" data-filter-value="H" class="ui-state-default" title="<?php echo I18N::translate('Show couples where only the male partner is deceased.'); ?> " > <?php echo I18N::translate('Widow'); ?> </button> <button type="button" data-filter-column="22" data-filter-value="Y" class="ui-state-default" title="<?php echo I18N::translate('Show individuals who are dead or couples where both partners are deceased.'); ?> " > <?php echo I18N::translate('Both dead'); ?> </button> </div> <div class="btn-group"> <button type="button" data-filter-column="23" data-filter-value="R" class="ui-state-default" title="<?php echo 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.'); ?> " > <?php echo I18N::translate('Roots'); ?> </button> <button type="button" data-filter-column="23" data-filter-value="L" class="ui-state-default" title="<?php echo I18N::translate('Show “leaves” couples or individuals. These are individuals who are alive but have no children recorded in the database.'); ?> " > <?php echo I18N::translate('Leaves'); ?> </button> </div> <div class="btn-group"> <button type="button" data-filter-column="21" data-filter-value="U" class="ui-state-default" title="<?php echo I18N::translate('Show couples with an unknown marriage date.'); ?> " > <?php echo GedcomTag::getLabel('MARR'); ?> </button> <button type="button" data-filter-column="21" data-filter-value="YES" class="ui-state-default" title="<?php echo I18N::translate('Show couples who married more than 100 years ago.'); ?> " > <?php echo GedcomTag::getLabel('MARR'); ?> >100 </button> <button type="button" data-filter-column="21" data-filter-value="Y100" class="ui-state-default" title="<?php echo I18N::translate('Show couples who married within the last 100 years.'); ?> " > <?php echo GedcomTag::getLabel('MARR'); ?> <=100 </button> <button type="button" data-filter-column="21" data-filter-value="D" class="ui-state-default" title="<?php echo I18N::translate('Show divorced couples.'); ?> " > <?php echo GedcomTag::getLabel('DIV'); ?> </button> <button type="button" data-filter-column="21" data-filter-value="M" class="ui-state-default" title="<?php echo I18N::translate('Show couples where either partner married more than once.'); ?> " > <?php echo I18N::translate('Multiple marriages'); ?> </button> </div> </div> </th> </tr> <tr> <th><?php echo I18N::translate('Sosa'); ?> </th> <th>SOSA</th> <th><?php echo GedcomTag::getLabel('GIVN'); ?> </th> <th><?php echo GedcomTag::getLabel('SURN'); ?> </th> <th>HUSB:GIVN_SURN</th> <th>HUSB:SURN_GIVN</th> <th><?php echo GedcomTag::getLabel('AGE'); ?> </th> <th>AGE</th> <th><?php echo GedcomTag::getLabel('GIVN'); ?> </th> <th><?php echo GedcomTag::getLabel('SURN'); ?> </th> <th>WIFE:GIVN_SURN</th> <th>WIFE:SURN_GIVN</th> <th><?php echo GedcomTag::getLabel('AGE'); ?> </th> <th>AGE</th> <th><?php echo GedcomTag::getLabel('MARR'); ?> </th> <th>MARR:DATE</th> <th><?php echo GedcomTag::getLabel('PLAC'); ?> </th>'; <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { ?> <th><i class="icon-source" title="<?php echo I18N::translate('Sourced marriage'); ?> " border="0"></i></th> <th>SORT_MARRSC</th> <?php } else { ?> <th> </th> <th></th> <?php } ?> <th><i class="icon-children" title="<?php echo I18N::translate('Children'); ?> "></i></th> <th>NCHI</th> <th>MARR</th> <th>DEAT</th> <th>TREE</th> </tr> </thead> <tbody> <?php foreach ($this->data->get('sosa_list') as $sosa => $family) { /** @var \Fisharebest\Webtrees\Family $person */ //PERSO Create decorator for Family $dfamily = new Family($family); $husb = $family->getHusband(); if (is_null($husb)) { $husb = new Individual('H', '0 @H@ INDI', null, $family->getTree()); } $dhusb = new \MyArtJaub\Webtrees\Individual($husb); $wife = $family->getWife(); if (is_null($wife)) { $wife = new Individual('W', '0 @W@ INDI', null, $family->getTree()); } $dwife = new \MyArtJaub\Webtrees\Individual($wife); $mdate = $family->getMarriageDate(); if ($family->isPendingAddtion()) { $class = ' class="new"'; } elseif ($family->isPendingDeletion()) { $class = ' class="old"'; } else { $class = ''; } ?> <tr <?php echo $class; ?> > <td class="transparent"><?php echo I18N::translate('%1$d/%2$d', $sosa, ($sosa + 1) % 10); ?> </td> <td class="transparent"><?php echo $sosa; ?> </td> <!-- HUSBAND --> <td colspan="2"> <?php foreach ($husb->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $husb)) . '"'; } if ($num == $husb->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $husb->getSexImage(); list($surn, $givn) = explode(',', $name['sort']); } else { $class = ''; $sex_image = ''; } ?> <a <?php echo $title . ' ' . $class; ?> href="<?php echo $husb->getHtmlUrl(); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($name['full']); ?> </a> <?php echo $sex_image . FunctionsPrint::formatSosaNumbers($dhusb->getSosaNumbers(), 1, 'smaller'); ?> <br/> <?php } echo $husb->getPrimaryParentsNames('parents details1', 'none'); ?> </td> <!-- Dummy column to match colspan in header --> <td style="display:none;"></td> <td> <?php echo Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . 'AAAA' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)); ?> </td> <td> <?php echo Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . 'AAAA' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)); ?> </td> <?php $hdate = $husb->getBirthDate(); ?> <td><?php Date::getAge($hdate, $mdate, 2); ?> </td> <td><?php Date::getAge($hdate, $mdate, 1); ?> </td> <!-- WIFE --> <td colspan="2"> <?php foreach ($wife->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $wife)) . '"'; } if ($num == $wife->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $wife->getSexImage(); list($surn, $givn) = explode(',', $name['sort']); } else { $class = ''; $sex_image = ''; } ?> <a <?php echo $title . ' ' . $class; ?> href="<?php echo $wife->getHtmlUrl(); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($name['full']); ?> </a> <?php echo $sex_image . FunctionsPrint::formatSosaNumbers($dwife->getSosaNumbers(), 1, 'smaller'); ?> <br/> <?php } echo $wife->getPrimaryParentsNames('parents details1', 'none'); ?> </td> <!-- Dummy column to match colspan in header --> <td style="display:none;"></td> <td> <?php echo Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . 'AAAA' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)); ?> </td> <td> <?php echo Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . 'AAAA' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)); ?> </td> <?php $wdate = $wife->getBirthDate(); ?> <td><?php Date::getAge($wdate, $mdate, 2); ?> </td> <td><?php Date::getAge($wdate, $mdate, 1); ?> </td> <td><?php if ($marriage_dates = $family->getAllMarriageDates()) { foreach ($marriage_dates as $n => $marriage_date) { if ($n) { echo '<br>'; } ?> <div><?php echo $marriage_date->display(true); ?> </div> <?php } } elseif ($family->getFacts('_NMR')) { echo I18N::translate('no'); } elseif ($family->getFacts('MARR')) { echo I18N::translate('yes'); } else { echo ' '; } ?> </td> <td><?php echo $marriage_dates ? $marriage_date->julianDay() : 0; ?> </td> <td><?php foreach ($family->getAllMarriagePlaces() as $n => $marriage_place) { $tmp = new Place($marriage_place, $family->getTree()); if ($n) { ?> <br><?php } ?> <a href="'<?php echo $tmp->getURL(); ?> " title="<?php echo strip_tags($tmp->getFullName()); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($tmp->getShortName()); ?> </a> <?php } ?> </td> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { $isMSourced = $dfamily->isMarriageSourced(); ?> <td><?php echo FunctionsPrint::formatIsSourcedIcon('E', $isMSourced, 'MARR', 1, 'medium'); ?> </td> <td><?php echo $isMSourced; ?> </td> <?php } else { ?> <td> </td> <td></td> <?php } ?> <?php $nchi = $family->getNumberOfChildren(); ?> <td><?php echo I18N::number($nchi); ?> </td> <td><?php echo $nchi; ?> </td> <td><?php if (!$mdate->isOK()) { echo 'U'; } else { if (Date::compare($mdate, new Date(date('Y') - 100)) > 0) { echo 'Y100'; } else { echo 'YES'; } } if ($family->getFacts(WT_EVENTS_DIV)) { echo 'D'; } if (count($husb->getSpouseFamilies()) > 1 || count($wife->getSpouseFamilies()) > 1) { echo 'M'; } ?> </td> <td><?php if ($husb->isDead() && $wife->isDead()) { echo 'Y'; } if ($husb->isDead() && !$wife->isDead()) { if ($wife->getSex() == 'F') { echo 'H'; } if ($wife->getSex() == 'M') { echo 'W'; } // male partners } if (!$husb->isDead() && $wife->isDead()) { if ($husb->getSex() == 'M') { echo 'W'; } if ($husb->getSex() == 'F') { echo 'H'; } // female partners } if (!$husb->isDead() && !$wife->isDead()) { echo 'N'; } ?> </td> <td><?php if (!$husb->getChildFamilies() && !$wife->getChildFamilies()) { echo 'R'; } elseif (!$husb->isDead() && !$wife->isDead() && $family->getNumberOfChildren() < 1) { echo 'L'; } else { echo ' '; } ?> </td> </tr> <?php } ?> </tbody> <tfoot> <tr> <th colspan="24"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" class="ui-state-default btn-toggle-parents"> <?php echo I18N::translate('Show parents'); ?> </button> <button id="btn-toggle-statistics-<?php echo $table_id; ?> " type="button" class="ui-state-default btn-toggle-statistics"> <?php echo I18N::translate('Show statistics charts'); ?> </button> </div> </div> </th> </tr> </tfoot> </table> <div id="fam_list_table-charts_<?php echo $table_id; ?> " style="display:none"> <table class="list-charts"> <tr> <td><?php echo $this->data->get('chart_births'); ?> </td> <td><?php echo $this->data->get('chart_marriages'); ?> </td> </tr> <tr> <td colspan="2"><?php echo $this->data->get('chart_ages'); ?> </td> </tr> </table> </div> </div> <?php } else { ?> <p class="warning"><?php echo I18N::translate('No family has been found for generation %d', $this->data->get('generation')); ?> </p> <?php } }
/** * print fact PLACe TEMPle STATus * * @param Fact $event gedcom fact record * @param bool $anchor to print a link to placelist * @param bool $sub_records to print place subrecords * @param bool $lds to print LDS TEMPle and STATus * * @return string HTML */ public static function formatFactPlace(Fact $event, $anchor = false, $sub_records = false, $lds = false) { if ($anchor) { // Show the full place name, for facts/events tab $html = '<a href="' . $event->getPlace()->getURL() . '">' . $event->getPlace()->getFullName() . '</a>'; } else { // Abbreviate the place name, for chart boxes return ' - ' . $event->getPlace()->getShortName(); } if ($sub_records) { $placerec = Functions::getSubRecord(2, '2 PLAC', $event->getGedcom()); if (!empty($placerec)) { if (preg_match_all('/\\n3 (?:_HEB|ROMN) (.+)/', $placerec, $matches)) { foreach ($matches[1] as $match) { $wt_place = new Place($match, $event->getParent()->getTree()); $html .= ' - ' . $wt_place->getFullName(); } } $map_lati = ""; $cts = preg_match('/\\d LATI (.*)/', $placerec, $match); if ($cts > 0) { $map_lati = $match[1]; $html .= '<br><span class="label">' . GedcomTag::getLabel('LATI') . ': </span>' . $map_lati; } $map_long = ''; $cts = preg_match('/\\d LONG (.*)/', $placerec, $match); if ($cts > 0) { $map_long = $match[1]; $html .= ' <span class="label">' . GedcomTag::getLabel('LONG') . ': </span>' . $map_long; } if ($map_lati && $map_long) { $map_lati = trim(strtr($map_lati, "NSEW,�", " - -. ")); // S5,6789 ==> -5.6789 $map_long = trim(strtr($map_long, "NSEW,�", " - -. ")); // E3.456� ==> 3.456 $html .= ' <a rel="nofollow" href="https://maps.google.com/maps?q=' . $map_lati . ',' . $map_long . '" class="icon-googlemaps" title="' . I18N::translate('Google Maps™') . '"></a>'; $html .= ' <a rel="nofollow" href="https://www.bing.com/maps/?lvl=15&cp=' . $map_lati . '~' . $map_long . '" class="icon-bing" title="' . I18N::translate('Bing Maps™') . '"></a>'; $html .= ' <a rel="nofollow" href="https://www.openstreetmap.org/#map=15/' . $map_lati . '/' . $map_long . '" class="icon-osm" title="' . I18N::translate('OpenStreetMap™') . '"></a>'; } if (preg_match('/\\d NOTE (.*)/', $placerec, $match)) { $html .= '<br>' . self::printFactNotes($placerec, 3); } } } if ($lds) { if (preg_match('/2 TEMP (.*)/', $event->getGedcom(), $match)) { $html .= '<br>' . I18N::translate('LDS temple') . ': ' . GedcomCodeTemp::templeName($match[1]); } if (preg_match('/2 STAT (.*)/', $event->getGedcom(), $match)) { $html .= '<br>' . I18N::translate('Status') . ': ' . GedcomCodeStat::statusName($match[1]); if (preg_match('/3 DATE (.*)/', $event->getGedcom(), $match)) { $date = new Date($match[1]); $html .= ', ' . GedcomTag::getLabel('STAT:DATE') . ': ' . $date->display(); } } } return $html; }
/** * A list of common marriage places. * * @return string */ public function commonMarriagePlacesList() { $places = $this->statsPlaces('FAM', 'MARR'); $top10 = array(); $i = 1; arsort($places); foreach ($places as $place => $count) { $tmp = new Place($place, $this->tree); $place = '<a href="' . $tmp->getURL() . '" class="list_item">' . $tmp->getFullName() . '</a>'; $top10[] = '<li>' . $place . ' - ' . I18N::number($count) . '</li>'; if ($i++ == 10) { break; } } $top10 = implode('', $top10); return '<ul>' . $top10 . '</ul>'; }
/** * {@inhericDoc} * @see \MyArtJaub\Webtrees\Mvc\View\AbstractView::renderContent() */ protected function renderContent() { if ($this->data->get('has_sosa', false)) { $table_id = $this->data->get('table_id'); ?> <div id="sosa-indi-list" class="sosa-list"> <table id="<?php echo $table_id; ?> "> <thead> <tr> <th colspan="22"> <div class="btn-toolbar"> <div class="btn-group"> <button class="ui-state-default" data-filter-column="18" data-filter-value="M" title="<?php echo I18N::translate('Show only males.'); ?> " type="button" ><?php echo Individual::sexImage('M', 'large'); ?> </button> <button class="ui-state-default" data-filter-column="18" data-filter-value="F" title="<?php echo I18N::translate('Show only females.'); ?> " type="button" > <?php echo Individual::sexImage('F', 'large'); ?> </button> <button class="ui-state-default" data-filter-column="18" data-filter-value="U" title="<?php echo I18N::translate('Show only individuals for whom the gender is not known.'); ?> " type="button" > <?php echo Individual::sexImage('U', 'large'); ?> </button> </div> <div class="btn-group"> <button class="ui-state-default" data-filter-column="20" data-filter-value="N" title="<?php echo I18N::translate('Show individuals who are alive or couples where both partners are alive.'); ?> " type="button" > <?php echo I18N::translate('Alive'); ?> </button> <button class="ui-state-default" data-filter-column="20" data-filter-value="Y" title="<?php echo I18N::translate('Show individuals who are dead or couples where both partners are deceased.'); ?> " type="button" > <?php echo I18N::translate('Dead'); ?> </button> <button class="ui-state-default" data-filter-column="20" data-filter-value="YES" title="<?php echo I18N::translate('Show individuals who died more than 100 years ago.'); ?> " type="button" ><?php echo GedcomTag::getLabel('DEAT'); ?> >100 </button> <button class="ui-state-default" data-filter-column="20" data-filter-value="Y100" title="<?php echo I18N::translate('Show individuals who died within the last 100 years.'); ?> " type="button" ><?php echo GedcomTag::getLabel('DEAT'); ?> <=100 </button> </div> <div class="btn-group"> <button class="ui-state-default" data-filter-column="19" data-filter-value="YES" title="<?php echo I18N::translate('Show individuals born more than 100 years ago.'); ?> " type="button" ><?php echo GedcomTag::getLabel('BIRT'); ?> >100 </button> <button class="ui-state-default" data-filter-column="19" data-filter-value="Y100" title="<?php echo I18N::translate('Show individuals born within the last 100 years.'); ?> " type="button" ><?php echo GedcomTag::getLabel('BIRT'); ?> <=100 </button> </div> <div class="btn-group"> <button class="ui-state-default" data-filter-column="21" data-filter-value="R" title="<?php echo 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.'); ?> " type="button" > <?php echo I18N::translate('Roots'); ?> </button> <button class="ui-state-default" data-filter-column="21" data-filter-value="L" title="<?php echo I18N::translate('Show “leaves” couples or individuals. These are individuals who are alive but have no children recorded in the database.'); ?> " type="button" > <?php echo I18N::translate('Leaves'); ?> </button> </div> </div> </th> </tr> <tr> <th><?php echo I18N::translate('Sosa'); ?> </th> <th><?php echo GedcomTag::getLabel('INDI'); ?> </th> <th><?php echo GedcomTag::getLabel('GIVN'); ?> </th> <th><?php echo GedcomTag::getLabel('SURN'); ?> </th> <th>GIVN</th> <th>SURN</th> <th><?php echo GedcomTag::getLabel('BIRT'); ?> </th> <th>SORT_BIRT</th> <th><?php echo GedcomTag::getLabel('PLAC'); ?> </th> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { ?> <th><i class="icon-source" title="<?php echo I18N::translate('Sourced birth'); ?> " border="0"></i></th> <th>SORT_BIRTSC</th> <?php } else { ?> <th></th> <th></th> <?php } ?> <th><?php echo GedcomTag::getLabel('DEAT'); ?> </th> <th>SORT_DEAT</th> <th><?php echo GedcomTag::getLabel('AGE'); ?> </th> <th>AGE</th> <th><?php echo GedcomTag::getLabel('PLAC'); ?> </th> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { ?> <th><i class="icon-source" title="<?php echo I18N::translate('Sourced death'); ?> " border="0"></i></th> <th>SORT_DEATSC</th> <?php } else { ?> <th></th> <th></th> <?php } ?> <th>SEX</th> <th>BIRT</th> <th>DEAT</th> <th>TREE</th> </tr> </thead> <tbody> <?php foreach ($this->data->get('sosa_list') as $sosa => $person) { /** @var \Fisharebest\Webtrees\Individual $person */ if ($person->isPendingAddtion()) { $class = ' class="new"'; } elseif ($person->isPendingDeletion()) { $class = ' class="old"'; } else { $class = ''; } $dperson = new \MyArtJaub\Webtrees\Individual($person); ?> <tr <?php echo $class; ?> > <td class="transparent"><?php echo $sosa; ?> </td> <td class="transparent"><?php echo $person->getXref(); ?> </td> <td colspan="2"> <?php foreach ($person->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $person)) . '"'; } if ($num == $person->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $person->getSexImage(); list($surn, $givn) = explode(',', $name['sort']); } else { $class = ''; $sex_image = ''; } ?> <a <?php echo $title . ' ' . $class; ?> href="<?php echo $person->getHtmlUrl(); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($name['full']); ?> </a> <?php echo $sex_image . FunctionsPrint::formatSosaNumbers($dperson->getSosaNumbers(), 1, 'smaller'); ?> <br/> <?php } echo $person->getPrimaryParentsNames('parents details1', 'none'); ?> </td> <td style="display:none;"></td> <td> <?php echo Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . 'AAAA' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)); ?> </td> <td> <?php echo Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . 'AAAA' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)); ?> </td> <td> <?php if ($birth_dates = $person->getAllBirthDates()) { foreach ($birth_dates as $num => $birth_date) { if ($num) { ?> <br/><?php } ?> <?php echo $birth_date->display(true); } } else { $birth_date = new Date(''); if ($person->getTree()->getPreference('SHOW_EST_LIST_DATES')) { $birth_date = $person->getEstimatedBirthDate(); echo $birth_date->display(true); } else { echo ' '; } $birth_dates[0] = new Date(''); } ?> </td> <td><?php echo $birth_date->julianDay(); ?> </td> <td> <?php foreach ($person->getAllBirthPlaces() as $n => $birth_place) { $tmp = new \Fisharebest\Webtrees\Place($birth_place, $person->getTree()); if ($n) { ?> <br><?php } ?> <a href="'<?php echo $tmp->getURL(); ?> " title="<?php echo strip_tags($tmp->getFullName()); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($tmp->getShortName()); ?> </a> <?php } ?> </td> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { $isBSourced = $dperson->isBirthSourced(); ?> <td><?php echo FunctionsPrint::formatIsSourcedIcon('E', $isBSourced, 'BIRT', 1, 'medium'); ?> </td> <td><?php echo $isBSourced; ?> </td> <?php } else { ?> <td> </td> <td></td> <?php } ?> <td> <?php if ($death_dates = $person->getAllDeathDates()) { foreach ($death_dates as $num => $death_date) { if ($num) { ?> <br/><?php } ?> <?php echo $death_date->display(true); } } else { $death_date = $person->getEstimatedDeathDate(); if ($person->getTree()->getPreference('SHOW_EST_LIST_DATES') && $death_date->minimumJulianDay() < WT_CLIENT_JD) { echo $death_date->display(true); } elseif ($person->isDead()) { echo I18N::translate('yes'); $death_date = new Date(''); } else { echo ' '; $death_date = new Date(''); } $death_dates[0] = new Date(''); } ?> </td> <td><?php echo $death_date->julianDay(); ?> </td> <td><?php echo Date::getAge($birth_dates[0], $death_dates[0], 2); ?> </td> <td><?php echo Date::getAge($birth_dates[0], $death_dates[0], 1); ?> </td> <td> <?php foreach ($person->getAllDeathPlaces() as $n => $death_place) { $tmp = new Place($death_place, $person->getTree()); if ($n) { ?> <br><?php } ?> <a href="'<?php echo $tmp->getURL(); ?> " title="<?php echo strip_tags($tmp->getFullName()); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($tmp->getShortName()); ?> </a> <?php } ?> </td> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { $isDSourced = $dperson->isDeathSourced(); ?> <td><?php echo FunctionsPrint::formatIsSourcedIcon('E', $isDSourced, 'DEAT', 1, 'medium'); ?> </td> <td><?php echo $isDSourced; ?> </td> <?php } else { ?> <td> </td> <td></td> <?php } ?> <td><?php echo $person->getSex(); ?> </td> <td> <?php if (!$person->canShow() || Date::compare($birth_date, new Date(date('Y') - 100)) > 0) { echo 'Y100'; } else { echo 'YES'; } ?> </td> <td> <?php if (Date::compare($death_dates[0], new Date(date('Y') - 100)) > 0) { echo 'Y100'; } elseif ($death_dates[0]->minimumJulianDay() || $person->isDead()) { echo 'YES'; } else { echo 'N'; } ?> </td> <td> <?php if (!$person->getChildFamilies()) { echo 'R'; } elseif (!$person->isDead() && $person->getNumberOfChildren() < 1) { echo 'L'; } else { echo ' '; } ?> </td> </tr> <?php } ?> </tbody> <tfoot> <tr> <th class="ui-state-default" colspan="22"> <div class="center"> <?php echo I18N::translate('Number of Sosa ancestors: %1$s known / %2$s theoretical (%3$s)', I18N::number($this->data->get('sosa_count')), I18N::number($this->data->get('sosa_theo')), I18N::percentage($this->data->get('sosa_ratio'), 2)); ?> <?php if ($this->data->get('sosa_hidden') > 0) { echo '[' . I18N::translate('%s hidden', I18N::number($this->data->get('sosa_hidden'))) . ']'; } ?> </div> </th> </tr> <tr> <th colspan="22"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" class="ui-state-default btn-toggle-parents"> <?php echo I18N::translate('Show parents'); ?> </button> <button id="btn-toggle-statistics-<?php echo $table_id; ?> " type="button" class="ui-state-default btn-toggle-statistics"> <?php echo I18N::translate('Show statistics charts'); ?> </button> </div> </div> </th> </tr> </tfoot> </table> <div id="indi_list_table-charts_<?php echo $table_id; ?> " style="display:none"> <table class="list-charts"> <tr> <td><?php echo $this->data->get('chart_births'); ?> </td> <td><?php echo $this->data->get('chart_deaths'); ?> </td> </tr> <tr> <td colspan="2"><?php echo $this->data->get('chart_ages'); ?> </td> </tr> </table> </div> </div> <?php } }
/** * Print places * * @param Place $place * @param type $tree * @return string */ private function printPlace($place, $tree) { if ($this->options('show_places') == true) { $place = new Place($place, $tree); $html = ' ' . I18N::translateContext('before placesnames', 'in '); if ($this->options('use_gedcom_places') == true) { $html .= $place->getShortName(); } else { $country = $this->options('country'); $new_place = array_reverse(explode(", ", $place->getGedcomName())); if (!empty($country) && $new_place[0] == $country) { unset($new_place[0]); $html .= '<span dir="auto">' . Filter::escapeHtml(implode(', ', array_reverse($new_place))) . '</span>'; } else { $html .= $place->getFullName(); } } return $html; } }
/** * XML <GedcomValue/> * * @param array $attrs an array of key value pairs for the attributes */ private function gedcomValueStartHandler($attrs) { global $WT_TREE; $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $this->gedrec, $match)) { $id = $match[1]; } if (isset($attrs['newline']) && $attrs['newline'] == "1") { $useBreak = "1"; } else { $useBreak = "0"; } $tag = $attrs['tag']; if (!empty($tag)) { if ($tag == "@desc") { $value = $this->desc; $value = trim($value); $this->current_element->addText($value); } if ($tag == "@id") { $this->current_element->addText($id); } else { $tag = str_replace("@fact", $this->fact, $tag); if (empty($attrs['level'])) { $temp = explode(" ", trim($this->gedrec)); $level = $temp[0]; if ($level == 0) { $level++; } } else { $level = $attrs['level']; } $tags = preg_split('/[: ]/', $tag); $value = $this->getGedcomValue($tag, $level, $this->gedrec); switch (end($tags)) { case 'DATE': $tmp = new Date($value); $value = $tmp->display(); break; case 'PLAC': $tmp = new Place($value, $WT_TREE); $value = $tmp->getShortName(); break; } if ($useBreak == "1") { // Insert <br> when multiple dates exist. // This works around a TCPDF bug that incorrectly wraps RTL dates on LTR pages $value = str_replace('(', '<br>(', $value); $value = str_replace('<span dir="ltr"><br>', '<br><span dir="ltr">', $value); $value = str_replace('<span dir="rtl"><br>', '<br><span dir="rtl">', $value); if (substr($value, 0, 6) == '<br>') { $value = substr($value, 6); } } $tmp = explode(':', $tag); if (in_array(end($tmp), array('NOTE', 'TEXT'))) { $value = Filter::formatText($value, $WT_TREE); // We'll strip HTML in addText() } $this->current_element->addText($value); } } }
if ($n == (int) ($num_places / 3 * 2)) { echo '</ul></td><td class="list_value_wrap"><ul>'; } } elseif ($n == (int) ($num_places / 2)) { echo '</ul></td><td class="list_value_wrap"><ul>'; } } echo '</ul></td></tr>'; echo '</table>'; } echo '<h4><a href="placelist.php?display=hierarchy">', I18N::translate('Show places in hierarchy'), '</a></h4>'; break; case 'hierarchy': $gm_module = Module::getModuleByName('googlemap'); // Find this place and its ID $place = new Place(implode(', ', array_reverse($parent)), $WT_TREE); $place_id = $place->getPlaceId(); $child_places = $place->getChildPlaces(); $numfound = count($child_places); //-- if the number of places found is 0 then automatically redirect to search page if ($numfound == 0) { $action = 'show'; } echo '<h2>', $controller->getPageTitle(); // Breadcrumbs if ($place_id) { $parent_place = $place->getParentPlace(); while ($parent_place->getPlaceId()) { echo ', <a href="', $parent_place->getURL(), '" dir="auto">', $parent_place->getPlaceName(), '</a>'; $parent_place = $parent_place->getParentPlace(); }
/** * Print a table of families * * @param Family[] $datalist * * @return string */ public static function familyTable($datalist) { global $WT_TREE, $controller; $table_id = 'table-fam-' . Uuid::uuid4(); // lists requires a unique ID in case there are multiple lists per page $controller->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL)->addInlineJavascript(' jQuery.fn.dataTableExt.oSort["unicode-asc" ]=function(a,b) {return a.replace(/<[^<]*>/, "").localeCompare(b.replace(/<[^<]*>/, ""))}; jQuery.fn.dataTableExt.oSort["unicode-desc"]=function(a,b) {return b.replace(/<[^<]*>/, "").localeCompare(a.replace(/<[^<]*>/, ""))}; jQuery("#' . $table_id . '").dataTable( { dom: \'<"H"<"filtersH_' . $table_id . '"><"dt-clear">pf<"dt-clear">irl>t<"F"pl<"dt-clear"><"filtersF_' . $table_id . '">>\', ' . I18N::datatablesI18N() . ', jQueryUI: true, autoWidth: false, processing: true, retrieve: true, columns: [ /* 0 husb givn */ {dataSort: 2}, /* 1 husb surn */ {dataSort: 3}, /* 2 GIVN,SURN */ {type: "unicode", visible: false}, /* 3 SURN,GIVN */ {type: "unicode", visible: false}, /* 4 age */ {dataSort: 5, class: "center"}, /* 5 AGE */ {type: "num", visible: false}, /* 6 wife givn */ {dataSort: 8}, /* 7 wife surn */ {dataSort: 9}, /* 8 GIVN,SURN */ {type: "unicode", visible: false}, /* 9 SURN,GIVN */ {type: "unicode", visible: false}, /* 10 age */ {dataSort: 11, class: "center"}, /* 11 AGE */ {type: "num", visible: false}, /* 12 marr date */ {dataSort: 13}, /* 13 MARR:DATE */ {visible: false}, /* 14 anniv */ {dataSort: 13, class: "center"}, /* 15 marr plac */ {type: "unicode"}, /* 16 children */ {dataSort: 17, class: "center"}, /* 17 NCHI */ {type: "num", visible: false}, /* 18 CHAN */ {dataSort: 19, visible: ' . ($WT_TREE->getPreference('SHOW_LAST_CHANGE') ? 'true' : 'false') . '}, /* 19 CHAN_sort */ {visible: false}, /* 20 MARR */ {visible: false}, /* 21 DEAT */ {visible: false}, /* 22 TREE */ {visible: false} ], sorting: [[1, "asc"]], displayLength: 20, pagingType: "full_numbers" }); jQuery("#' . $table_id . '") /* Hide/show parents */ .on("click", ".btn-toggle-parents", function() { jQuery(this).toggleClass("ui-state-active"); jQuery(".parents", jQuery(this).closest("table").DataTable().rows().nodes()).slideToggle(); }) /* Hide/show statistics */ .on("click", ".btn-toggle-statistics", function() { jQuery(this).toggleClass("ui-state-active"); jQuery("#fam_list_table-charts_' . $table_id . '").slideToggle(); }) /* Filter buttons in table header */ .on("click", "button[data-filter-column]", function() { var btn = $(this); // De-activate the other buttons in this button group btn.siblings().removeClass("ui-state-active"); // Apply (or clear) this filter var col = jQuery("#' . $table_id . '").DataTable().column(btn.data("filter-column")); if (btn.hasClass("ui-state-active")) { btn.removeClass("ui-state-active"); col.search("").draw(); } else { btn.addClass("ui-state-active"); col.search(btn.data("filter-value")).draw(); } }); jQuery(".fam-list").css("visibility", "visible"); jQuery(".loading-image").css("display", "none"); '); $stats = new Stats($WT_TREE); $max_age = max($stats->oldestMarriageMaleAge(), $stats->oldestMarriageFemaleAge()) + 1; //-- init chart data $marr_by_age = array(); for ($age = 0; $age <= $max_age; $age++) { $marr_by_age[$age] = ''; } $birt_by_decade = array(); $marr_by_decade = array(); for ($year = 1550; $year < 2030; $year += 10) { $birt_by_decade[$year] = ''; $marr_by_decade[$year] = ''; } $html = ' <div class="loading-image"> </div> <div class="fam-list"> <table id="' . $table_id . '"> <thead> <tr> <th colspan="23"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" data-filter-column="21" data-filter-value="N" class="ui-state-default" title="' . I18N::translate('Show individuals who are alive or couples where both partners are alive.') . '" > ' . I18N::translate('Both alive') . ' </button> <button type="button" data-filter-column="21" data-filter-value="W" class="ui-state-default" title="' . I18N::translate('Show couples where only the female partner is deceased.') . '" > ' . I18N::translate('Widower') . ' </button> <button type="button" data-filter-column="21" data-filter-value="H" class="ui-state-default" title="' . I18N::translate('Show couples where only the male partner is deceased.') . '" > ' . I18N::translate('Widow') . ' </button> <button type="button" data-filter-column="21" data-filter-value="Y" class="ui-state-default" title="' . I18N::translate('Show individuals who are dead or couples where both partners are deceased.') . '" > ' . I18N::translate('Both dead') . ' </button> </div> <div class="btn-group"> <button type="button" data-filter-column="22" data-filter-value="R" class="ui-state-default" 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.') . '" > ' . I18N::translate('Roots') . ' </button> <button type="button" data-filter-column="22" data-filter-value="L" class="ui-state-default" title="' . I18N::translate('Show “leaves” couples or individuals. These are individuals who are alive but have no children recorded in the database.') . '" > ' . I18N::translate('Leaves') . ' </button> </div> <div class="btn-group"> <button type="button" data-filter-column="20" data-filter-value="U" class="ui-state-default" title="' . I18N::translate('Show couples with an unknown marriage date.') . '" > ' . GedcomTag::getLabel('MARR') . ' </button> <button type="button" data-filter-column="20" data-filter-value="YES" class="ui-state-default" title="' . I18N::translate('Show couples who married more than 100 years ago.') . '" > ' . GedcomTag::getLabel('MARR') . '>100 </button> <button type="button" data-filter-column="20" data-filter-value="Y100" class="ui-state-default" title="' . I18N::translate('Show couples who married within the last 100 years.') . '" > ' . GedcomTag::getLabel('MARR') . '<=100 </button> <button type="button" data-filter-column="20" data-filter-value="D" class="ui-state-default" title="' . I18N::translate('Show divorced couples.') . '" > ' . GedcomTag::getLabel('DIV') . ' </button> <button type="button" data-filter-column="20" data-filter-value="M" class="ui-state-default" title="' . I18N::translate('Show couples where either partner married more than once.') . '" > ' . I18N::translate('Multiple marriages') . ' </button> </div> </div> </th> </tr> <tr> <th>' . GedcomTag::getLabel('GIVN') . '</th> <th>' . GedcomTag::getLabel('SURN') . '</th> <th>HUSB:GIVN_SURN</th> <th>HUSB:SURN_GIVN</th> <th>' . GedcomTag::getLabel('AGE') . '</th> <th>AGE</th> <th>' . GedcomTag::getLabel('GIVN') . '</th> <th>' . GedcomTag::getLabel('SURN') . '</th> <th>WIFE:GIVN_SURN</th> <th>WIFE:SURN_GIVN</th> <th>' . GedcomTag::getLabel('AGE') . '</th> <th>AGE</th> <th>' . GedcomTag::getLabel('MARR') . '</th> <th>MARR:DATE</th> <th><i class="icon-reminder" title="' . I18N::translate('Anniversary') . '"></i></th> <th>' . GedcomTag::getLabel('PLAC') . '</th> <th><i class="icon-children" title="' . I18N::translate('Children') . '"></i></th> <th>NCHI</th> <th>' . GedcomTag::getLabel('CHAN') . '</th> <th>CHAN</th> <th>MARR</th> <th>DEAT</th> <th>TREE</th> </tr> </thead> <tfoot> <tr> <th colspan="23"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" class="ui-state-default btn-toggle-parents"> ' . I18N::translate('Show parents') . ' </button> <button type="button" class="ui-state-default btn-toggle-statistics"> ' . I18N::translate('Show statistics charts') . ' </button> </div> </div> </th> </tr> </tfoot> <tbody>'; $d100y = new Date(date('Y') - 100); // 100 years ago foreach ($datalist as $family) { //-- Retrieve husband and wife $husb = $family->getHusband(); if (is_null($husb)) { $husb = new Individual('H', '0 @H@ INDI', null, $family->getTree()); } $wife = $family->getWife(); if (is_null($wife)) { $wife = new Individual('W', '0 @W@ INDI', null, $family->getTree()); } if (!$family->canShow()) { continue; } if ($family->isPendingAddtion()) { $class = ' class="new"'; } elseif ($family->isPendingDeletion()) { $class = ' class="old"'; } else { $class = ''; } $html .= '<tr' . $class . '>'; //-- Husband name(s) $html .= '<td colspan="2">'; foreach ($husb->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $husb)) . '"'; } if ($num == $husb->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $husb->getSexImage(); list($surn, $givn) = explode(',', $name['sort']); } else { $class = ''; $sex_image = ''; } // Only show married names if they are the name we are filtering by. if ($name['type'] != '_MARNM' || $num == $husb->getPrimaryName()) { $html .= '<a ' . $title . ' href="' . $family->getHtmlUrl() . '"' . $class . '>' . FunctionsPrint::highlightSearchHits($name['full']) . '</a>' . $sex_image . '<br>'; } } // Husband parents $html .= $husb->getPrimaryParentsNames('parents details1', 'none'); $html .= '</td>'; // Dummy column to match colspan in header $html .= '<td style="display:none;"></td>'; //-- Husb GIVN // Use "AAAA" as a separator (instead of ",") as Javascript.localeCompare() ignores // punctuation and "ANN,ROACH" would sort after "ANNE,ROACH", instead of before it. // Similarly, @N.N. would sort as NN. $html .= '<td>' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . 'AAAA' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . '</td>'; $html .= '<td>' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . 'AAAA' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . '</td>'; $mdate = $family->getMarriageDate(); //-- Husband age $hdate = $husb->getBirthDate(); if ($hdate->isOK() && $mdate->isOK()) { if ($hdate->gregorianYear() >= 1550 && $hdate->gregorianYear() < 2030) { $birt_by_decade[(int) ($hdate->gregorianYear() / 10) * 10] .= $husb->getSex(); } $hage = Date::getAge($hdate, $mdate, 0); if ($hage >= 0 && $hage <= $max_age) { $marr_by_age[$hage] .= $husb->getSex(); } } $html .= '<td>' . Date::getAge($hdate, $mdate, 2) . '</td><td>' . Date::getAge($hdate, $mdate, 1) . '</td>'; //-- Wife name(s) $html .= '<td colspan="2">'; foreach ($wife->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $wife)) . '"'; } if ($num == $wife->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $wife->getSexImage(); list($surn, $givn) = explode(',', $name['sort']); } else { $class = ''; $sex_image = ''; } // Only show married names if they are the name we are filtering by. if ($name['type'] != '_MARNM' || $num == $wife->getPrimaryName()) { $html .= '<a ' . $title . ' href="' . $family->getHtmlUrl() . '"' . $class . '>' . FunctionsPrint::highlightSearchHits($name['full']) . '</a>' . $sex_image . '<br>'; } } // Wife parents $html .= $wife->getPrimaryParentsNames('parents details1', 'none'); $html .= '</td>'; // Dummy column to match colspan in header $html .= '<td style="display:none;"></td>'; //-- Wife GIVN //-- Husb GIVN // Use "AAAA" as a separator (instead of ",") as Javascript.localeCompare() ignores // punctuation and "ANN,ROACH" would sort after "ANNE,ROACH", instead of before it. // Similarly, @N.N. would sort as NN. $html .= '<td>' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . 'AAAA' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . '</td>'; $html .= '<td>' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . 'AAAA' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . '</td>'; $mdate = $family->getMarriageDate(); //-- Wife age $wdate = $wife->getBirthDate(); if ($wdate->isOK() && $mdate->isOK()) { if ($wdate->gregorianYear() >= 1550 && $wdate->gregorianYear() < 2030) { $birt_by_decade[(int) ($wdate->gregorianYear() / 10) * 10] .= $wife->getSex(); } $wage = Date::getAge($wdate, $mdate, 0); if ($wage >= 0 && $wage <= $max_age) { $marr_by_age[$wage] .= $wife->getSex(); } } $html .= '<td>' . Date::getAge($wdate, $mdate, 2) . '</td><td>' . Date::getAge($wdate, $mdate, 1) . '</td>'; //-- Marriage date $html .= '<td>'; if ($marriage_dates = $family->getAllMarriageDates()) { foreach ($marriage_dates as $n => $marriage_date) { if ($n) { $html .= '<br>'; } $html .= '<div>' . $marriage_date->display(true) . '</div>'; } if ($marriage_dates[0]->gregorianYear() >= 1550 && $marriage_dates[0]->gregorianYear() < 2030) { $marr_by_decade[(int) ($marriage_dates[0]->gregorianYear() / 10) * 10] .= $husb->getSex() . $wife->getSex(); } } elseif ($family->getFacts('_NMR')) { $html .= I18N::translate('no'); } elseif ($family->getFacts('MARR')) { $html .= I18N::translate('yes'); } else { $html .= ' '; } $html .= '</td>'; //-- Event date (sortable)hidden by datatables code $html .= '<td>'; if ($marriage_dates) { $html .= $marriage_date->julianDay(); } else { $html .= 0; } $html .= '</td>'; //-- Marriage anniversary $html .= '<td>' . Date::getAge($mdate, null, 2) . '</td>'; //-- Marriage place $html .= '<td>'; foreach ($family->getAllMarriagePlaces() as $n => $marriage_place) { $tmp = new Place($marriage_place, $family->getTree()); if ($n) { $html .= '<br>'; } $html .= '<a href="' . $tmp->getURL() . '" title="' . strip_tags($tmp->getFullName()) . '">'; $html .= FunctionsPrint::highlightSearchHits($tmp->getShortName()) . '</a>'; } $html .= '</td>'; //-- Number of children $nchi = $family->getNumberOfChildren(); $html .= '<td>' . I18N::number($nchi) . '</td><td>' . $nchi . '</td>'; //-- Last change $html .= '<td>' . $family->LastChangeTimestamp() . '</td>'; $html .= '<td>' . $family->LastChangeTimestamp(true) . '</td>'; //-- Sorting by marriage date $html .= '<td>'; if (!$family->canShow() || !$mdate->isOK()) { $html .= 'U'; } else { if (Date::compare($mdate, $d100y) > 0) { $html .= 'Y100'; } else { $html .= 'YES'; } } if ($family->getFacts(WT_EVENTS_DIV)) { $html .= 'D'; } if (count($husb->getSpouseFamilies()) > 1 || count($wife->getSpouseFamilies()) > 1) { $html .= 'M'; } $html .= '</td>'; //-- Sorting alive/dead $html .= '<td>'; if ($husb->isDead() && $wife->isDead()) { $html .= 'Y'; } if ($husb->isDead() && !$wife->isDead()) { if ($wife->getSex() == 'F') { $html .= 'H'; } if ($wife->getSex() == 'M') { $html .= 'W'; } // male partners } if (!$husb->isDead() && $wife->isDead()) { if ($husb->getSex() == 'M') { $html .= 'W'; } if ($husb->getSex() == 'F') { $html .= 'H'; } // female partners } if (!$husb->isDead() && !$wife->isDead()) { $html .= 'N'; } $html .= '</td>'; //-- Roots or Leaves $html .= '<td>'; if (!$husb->getChildFamilies() && !$wife->getChildFamilies()) { $html .= 'R'; } elseif (!$husb->isDead() && !$wife->isDead() && $family->getNumberOfChildren() < 1) { $html .= 'L'; } else { $html .= ' '; } $html .= '</td> </tr>'; } $html .= ' </tbody> </table> <div id="fam_list_table-charts_' . $table_id . '" style="display:none"> <table class="list-charts"> <tr> <td> ' . self::chartByDecade($birt_by_decade, I18N::translate('Decade of birth')) . ' </td> <td> ' . self::chartByDecade($marr_by_decade, I18N::translate('Decade of marriage')) . ' </td> </tr> <tr> <td colspan="2"> ' . self::chartByAge($marr_by_age, I18N::translate('Age in year of marriage')) . ' </td> </tr> </table> </div> </div>'; return $html; }
/** * Return HTML code to include a flag icon * * @param \Fisharebest\Webtrees\Place $place * @param string $icon_path * @param number $size * @return string HTML code of the inserted flag */ public static function htmlPlaceIcon(\Fisharebest\Webtrees\Place $place, $icon_path, $size = 50) { return '<img class="flag_gm_h' . $size . '" src="' . $icon_path . '" title="' . $place->getGedcomName() . '" alt="' . $place->getGedcomName() . '" />'; }
/** * Print a table of families * * @param Family[] $families * * @return string */ public static function familyTable($families) { global $WT_TREE, $controller; $table_id = 'table-fam-' . Uuid::uuid4(); // lists requires a unique ID in case there are multiple lists per page $controller->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL)->addInlineJavascript(' jQuery.fn.dataTableExt.oSort["text-asc"] = textCompareAsc; jQuery.fn.dataTableExt.oSort["text-desc"] = textCompareDesc; jQuery("#' . $table_id . '").dataTable( { dom: \'<"H"<"filtersH_' . $table_id . '"><"dt-clear">pf<"dt-clear">irl>t<"F"pl<"dt-clear"><"filtersF_' . $table_id . '">>\', ' . I18N::datatablesI18N() . ', jQueryUI: true, autoWidth: false, processing: true, retrieve: true, columns: [ /* Given names */ { type: "text" }, /* Surnames */ { type: "text" }, /* Age */ { type: "num" }, /* Given names */ { type: "text" }, /* Surnames */ { type: "text" }, /* Age */ { type: "num" }, /* Marriage date */ { type: "num" }, /* Anniversary */ { type: "num" }, /* Marriage place */ { type: "text" }, /* Children */ { type: "num" }, /* Last change */ { visible: ' . ($WT_TREE->getPreference('SHOW_LAST_CHANGE') ? 'true' : 'false') . ' }, /* Filter marriage */ { sortable: false }, /* Filter alive/dead */ { sortable: false }, /* Filter tree */ { sortable: false } ], sorting: [[1, "asc"]], displayLength: 20, pagingType: "full_numbers" }); jQuery("#' . $table_id . '") /* Hide/show parents */ .on("click", ".btn-toggle-parents", function() { jQuery(this).toggleClass("ui-state-active"); jQuery(".parents", jQuery(this).closest("table").DataTable().rows().nodes()).slideToggle(); }) /* Hide/show statistics */ .on("click", ".btn-toggle-statistics", function() { jQuery(this).toggleClass("ui-state-active"); jQuery("#fam_list_table-charts_' . $table_id . '").slideToggle(); }) /* Filter buttons in table header */ .on("click", "button[data-filter-column]", function() { var btn = $(this); // De-activate the other buttons in this button group btn.siblings().removeClass("ui-state-active"); // Apply (or clear) this filter var col = jQuery("#' . $table_id . '").DataTable().column(btn.data("filter-column")); if (btn.hasClass("ui-state-active")) { btn.removeClass("ui-state-active"); col.search("").draw(); } else { btn.addClass("ui-state-active"); col.search(btn.data("filter-value")).draw(); } }); jQuery(".fam-list").css("visibility", "visible"); jQuery(".loading-image").css("display", "none"); '); $stats = new Stats($WT_TREE); $max_age = max($stats->oldestMarriageMaleAge(), $stats->oldestMarriageFemaleAge()) + 1; // init chart data $marr_by_age = array(); for ($age = 0; $age <= $max_age; $age++) { $marr_by_age[$age] = ''; } $birt_by_decade = array(); $marr_by_decade = array(); for ($year = 1550; $year < 2030; $year += 10) { $birt_by_decade[$year] = ''; $marr_by_decade[$year] = ''; } $html = ' <div class="loading-image"></div> <div class="fam-list"> <table id="' . $table_id . '"> <thead> <tr> <th colspan="14"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" data-filter-column="12" data-filter-value="N" class="ui-state-default" title="' . I18N::translate('Show individuals who are alive or couples where both partners are alive.') . '" > ' . I18N::translate('Both alive') . ' </button> <button type="button" data-filter-column="12" data-filter-value="W" class="ui-state-default" title="' . I18N::translate('Show couples where only the female partner is dead.') . '" > ' . I18N::translate('Widower') . ' </button> <button type="button" data-filter-column="12" data-filter-value="H" class="ui-state-default" title="' . I18N::translate('Show couples where only the male partner is dead.') . '" > ' . I18N::translate('Widow') . ' </button> <button type="button" data-filter-column="12" data-filter-value="Y" class="ui-state-default" title="' . I18N::translate('Show individuals who are dead or couples where both partners are dead.') . '" > ' . I18N::translate('Both dead') . ' </button> </div> <div class="btn-group"> <button type="button" data-filter-column="13" data-filter-value="R" class="ui-state-default" 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.') . '" > ' . I18N::translate('Roots') . ' </button> <button type="button" data-filter-column="13" data-filter-value="L" class="ui-state-default" title="' . I18N::translate('Show “leaves” couples or individuals. These are individuals who are alive but have no children recorded in the database.') . '" > ' . I18N::translate('Leaves') . ' </button> </div> <div class="btn-group"> <button type="button" data-filter-column="11" data-filter-value="U" class="ui-state-default" title="' . I18N::translate('Show couples with an unknown marriage date.') . '" > ' . GedcomTag::getLabel('MARR') . ' </button> <button type="button" data-filter-column="11" data-filter-value="YES" class="ui-state-default" title="' . I18N::translate('Show couples who married more than 100 years ago.') . '" > ' . GedcomTag::getLabel('MARR') . '>100 </button> <button type="button" data-filter-column="11" data-filter-value="Y100" class="ui-state-default" title="' . I18N::translate('Show couples who married within the last 100 years.') . '" > ' . GedcomTag::getLabel('MARR') . '<=100 </button> <button type="button" data-filter-column="11" data-filter-value="D" class="ui-state-default" title="' . I18N::translate('Show divorced couples.') . '" > ' . GedcomTag::getLabel('DIV') . ' </button> <button type="button" data-filter-column="11" data-filter-value="M" class="ui-state-default" title="' . I18N::translate('Show couples where either partner married more than once.') . '" > ' . I18N::translate('Multiple marriages') . ' </button> </div> </div> </th> </tr> <tr> <th>' . GedcomTag::getLabel('GIVN') . '</th> <th>' . GedcomTag::getLabel('SURN') . '</th> <th>' . GedcomTag::getLabel('AGE') . '</th> <th>' . GedcomTag::getLabel('GIVN') . '</th> <th>' . GedcomTag::getLabel('SURN') . '</th> <th>' . GedcomTag::getLabel('AGE') . '</th> <th>' . GedcomTag::getLabel('MARR') . '</th> <th><i class="icon-reminder" title="' . I18N::translate('Anniversary') . '"></i></th> <th>' . GedcomTag::getLabel('PLAC') . '</th> <th><i class="icon-children" title="' . I18N::translate('Children') . '"></i></th> <th>' . GedcomTag::getLabel('CHAN') . '</th> <th hidden></th> <th hidden></th> <th hidden></th> </tr> </thead> <tfoot> <tr> <th colspan="14"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" class="ui-state-default btn-toggle-parents"> ' . I18N::translate('Show parents') . ' </button> <button type="button" class="ui-state-default btn-toggle-statistics"> ' . I18N::translate('Show statistics charts') . ' </button> </div> </div> </th> </tr> </tfoot> <tbody>'; $hundred_years_ago = new Date(date('Y') - 100); foreach ($families as $family) { // Retrieve husband and wife $husb = $family->getHusband(); if (is_null($husb)) { $husb = new Individual('H', '0 @H@ INDI', null, $family->getTree()); } $wife = $family->getWife(); if (is_null($wife)) { $wife = new Individual('W', '0 @W@ INDI', null, $family->getTree()); } if (!$family->canShow()) { continue; } if ($family->isPendingAddtion()) { $class = ' class="new"'; } elseif ($family->isPendingDeletion()) { $class = ' class="old"'; } else { $class = ''; } $html .= '<tr' . $class . '>'; // Husband name(s) // Extract Given names and Surnames for sorting list($surn_givn, $givn_surn) = self::sortableNames($husb); $html .= '<td colspan="2" data-sort="' . Filter::escapeHtml($givn_surn) . '">'; foreach ($husb->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $husb)) . '"'; } if ($num == $husb->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $husb->getSexImage(); } else { $class = ''; $sex_image = ''; } // Only show married names if they are the name we are filtering by. if ($name['type'] != '_MARNM' || $num == $husb->getPrimaryName()) { $html .= '<a ' . $title . ' href="' . $family->getHtmlUrl() . '"' . $class . '>' . FunctionsPrint::highlightSearchHits($name['full']) . '</a>' . $sex_image . '<br>'; } } // Husband parents $html .= $husb->getPrimaryParentsNames('parents details1', 'none'); $html .= '</td>'; // Hidden column for sortable name $html .= '<td hidden data-sort="' . Filter::escapeHtml($surn_givn) . '"></td>'; // Husband age $mdate = $family->getMarriageDate(); $hdate = $husb->getBirthDate(); if ($hdate->isOK() && $mdate->isOK()) { if ($hdate->gregorianYear() >= 1550 && $hdate->gregorianYear() < 2030) { $birt_by_decade[(int) ($hdate->gregorianYear() / 10) * 10] .= $husb->getSex(); } $hage = Date::getAge($hdate, $mdate, 0); if ($hage >= 0 && $hage <= $max_age) { $marr_by_age[$hage] .= $husb->getSex(); } } $html .= '<td class="center" data=-sort="' . Date::getAge($hdate, $mdate, 1) . '">' . Date::getAge($hdate, $mdate, 2) . '</td>'; // Wife name(s) // Extract Given names and Surnames for sorting list($surn_givn, $givn_surn) = self::sortableNames($wife); $html .= '<td colspan="2" data-sort="' . Filter::escapeHtml($givn_surn) . '">'; foreach ($wife->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $wife)) . '"'; } if ($num == $wife->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $wife->getSexImage(); } else { $class = ''; $sex_image = ''; } // Only show married names if they are the name we are filtering by. if ($name['type'] != '_MARNM' || $num == $wife->getPrimaryName()) { $html .= '<a ' . $title . ' href="' . $family->getHtmlUrl() . '"' . $class . '>' . FunctionsPrint::highlightSearchHits($name['full']) . '</a>' . $sex_image . '<br>'; } } // Wife parents $html .= $wife->getPrimaryParentsNames('parents details1', 'none'); $html .= '</td>'; // Hidden column for sortable name $html .= '<td hidden data-sort="' . Filter::escapeHtml($surn_givn) . '"></td>'; // Wife age $mdate = $family->getMarriageDate(); $wdate = $wife->getBirthDate(); if ($wdate->isOK() && $mdate->isOK()) { if ($wdate->gregorianYear() >= 1550 && $wdate->gregorianYear() < 2030) { $birt_by_decade[(int) ($wdate->gregorianYear() / 10) * 10] .= $wife->getSex(); } $wage = Date::getAge($wdate, $mdate, 0); if ($wage >= 0 && $wage <= $max_age) { $marr_by_age[$wage] .= $wife->getSex(); } } $html .= '<td class="center" data-sort="' . Date::getAge($wdate, $mdate, 1) . '">' . Date::getAge($wdate, $mdate, 2) . '</td>'; // Marriage date $html .= '<td data-sort="' . $family->getMarriageDate()->julianDay() . '">'; if ($marriage_dates = $family->getAllMarriageDates()) { foreach ($marriage_dates as $n => $marriage_date) { if ($n) { $html .= '<br>'; } $html .= '<div>' . $marriage_date->display(true) . '</div>'; } if ($marriage_dates[0]->gregorianYear() >= 1550 && $marriage_dates[0]->gregorianYear() < 2030) { $marr_by_decade[(int) ($marriage_dates[0]->gregorianYear() / 10) * 10] .= $husb->getSex() . $wife->getSex(); } } elseif ($family->getFacts('_NMR')) { $html .= I18N::translate('no'); } elseif ($family->getFacts('MARR')) { $html .= I18N::translate('yes'); } else { $html .= ' '; } $html .= '</td>'; // Marriage anniversary $html .= '<td class="center" data-sort="' . -$family->getMarriageDate()->julianDay() . '">' . Date::getAge($family->getMarriageDate(), null, 2) . '</td>'; // Marriage place $html .= '<td>'; foreach ($family->getAllMarriagePlaces() as $n => $marriage_place) { $tmp = new Place($marriage_place, $family->getTree()); if ($n) { $html .= '<br>'; } $html .= '<a href="' . $tmp->getURL() . '" title="' . strip_tags($tmp->getFullName()) . '">'; $html .= FunctionsPrint::highlightSearchHits($tmp->getShortName()) . '</a>'; } $html .= '</td>'; // Number of children $html .= '<td class="center" data-sort="' . $family->getNumberOfChildren() . '">' . I18N::number($family->getNumberOfChildren()) . '</td>'; // Last change $html .= '<td data-sort="' . $family->lastChangeTimestamp(true) . '">' . $family->lastChangeTimestamp() . '</td>'; // Filter by marriage date $html .= '<td hidden>'; if (!$family->canShow() || !$mdate->isOK()) { $html .= 'U'; } else { if (Date::compare($mdate, $hundred_years_ago) > 0) { $html .= 'Y100'; } else { $html .= 'YES'; } } if ($family->getFacts(WT_EVENTS_DIV)) { $html .= 'D'; } if (count($husb->getSpouseFamilies()) > 1 || count($wife->getSpouseFamilies()) > 1) { $html .= 'M'; } $html .= '</td>'; // Filter by alive/dead $html .= '<td hidden>'; if ($husb->isDead() && $wife->isDead()) { $html .= 'Y'; } if ($husb->isDead() && !$wife->isDead()) { if ($wife->getSex() == 'F') { $html .= 'H'; } if ($wife->getSex() == 'M') { $html .= 'W'; } // male partners } if (!$husb->isDead() && $wife->isDead()) { if ($husb->getSex() == 'M') { $html .= 'W'; } if ($husb->getSex() == 'F') { $html .= 'H'; } // female partners } if (!$husb->isDead() && !$wife->isDead()) { $html .= 'N'; } $html .= '</td>'; // Filter by roots/leaves $html .= '<td hidden>'; if (!$husb->getChildFamilies() && !$wife->getChildFamilies()) { $html .= 'R'; } elseif (!$husb->isDead() && !$wife->isDead() && $family->getNumberOfChildren() === 0) { $html .= 'L'; } $html .= '</td> </tr>'; } $html .= ' </tbody> </table> <div id="fam_list_table-charts_' . $table_id . '" style="display:none"> <table class="list-charts"> <tr> <td>' . self::chartByDecade($birt_by_decade, I18N::translate('Decade of birth')) . '</td> <td>' . self::chartByDecade($marr_by_decade, I18N::translate('Decade of marriage')) . '</td> </tr> <tr> <td colspan="2">' . self::chartByAge($marr_by_age, I18N::translate('Age in year of marriage')) . '</td> </tr> </table> </div> </div>'; return $html; }