/** * Return a list of facts * * @return Fact[] */ public function getFacts() { $facts = $this->record->getFacts(); // Add some dummy facts to show additional information if ($this->record->fileExists()) { // get height and width of image, when available $imgsize = $this->record->getImageAttributes(); if (!empty($imgsize['WxH'])) { $facts[] = new Fact('1 __IMAGE_SIZE__ ' . $imgsize['WxH'], $this->record, 0); } //Prints the file size $facts[] = new Fact('1 __FILE_SIZE__ ' . $this->record->getFilesize(), $this->record, 0); } Functions::sortFacts($facts); return $facts; }
/** * Get all the facts for an individual which contain notes. * * @return Fact[] */ private function getFactsWithNotes() { global $controller; if ($this->facts === null) { $facts = $controller->record->getFacts(); foreach ($controller->record->getSpouseFamilies() as $family) { if ($family->canShow()) { foreach ($family->getFacts() as $fact) { $facts[] = $fact; } } } $this->facts = array(); foreach ($facts as $fact) { if (preg_match('/(?:^1|\\n\\d) NOTE/', $fact->getGedcom())) { $this->facts[] = $fact; } } Functions::sortFacts($this->facts); } return $this->facts; }
/** * Build a map for an individual. * * @param Individual $indi */ private function buildIndividualMap(Individual $indi) { $GM_MAX_ZOOM = $this->getSetting('GM_MAX_ZOOM'); $indifacts = $indi->getFacts(); foreach ($indi->getSpouseFamilies() as $family) { $indifacts = array_merge($indifacts, $family->getFacts()); } Functions::sortFacts($indifacts); // Create the markers list array $gmarks = array(); $i = 0; foreach ($indifacts as $fact) { if (!$fact->getPlace()->isEmpty()) { $ctla = preg_match("/\\d LATI (.*)/", $fact->getGedcom(), $match1); $ctlo = preg_match("/\\d LONG (.*)/", $fact->getGedcom(), $match2); if ($fact->getParent() instanceof Family) { $spouse = $fact->getParent()->getSpouse($indi); } else { $spouse = null; } if ($ctla && $ctlo) { $i++; $gmarks[$i] = array('class' => 'optionbox', 'date' => $fact->getDate()->display(true), 'fact_label' => $fact->getLabel(), 'image' => $spouse ? $spouse->displayImage() : Theme::theme()->icon($fact), 'info' => $fact->getValue(), 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $match1[1]), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $match2[1]), 'name' => $spouse ? '<a href="' . $spouse->getHtmlUrl() . '"' . $spouse->getFullName() . '</a>' : '', 'pl_icon' => '', 'place' => $fact->getPlace()->getFullName(), 'sv_bearing' => '0', 'sv_elevation' => '0', 'sv_lati' => '0', 'sv_long' => '0', 'sv_zoom' => '0', 'tooltip' => $fact->getPlace()->getGedcomName()); } else { $latlongval = $this->getLatitudeAndLongitudeFromPlaceLocation($fact->getPlace()->getGedcomName()); if ($latlongval && $latlongval->pl_lati && $latlongval->pl_long) { $i++; $gmarks[$i] = array('class' => 'optionbox', 'date' => $fact->getDate()->display(true), 'fact_label' => $fact->getLabel(), 'image' => $spouse ? $spouse->displayImage() : Theme::theme()->icon($fact), 'info' => $fact->getValue(), 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $latlongval->pl_lati), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $latlongval->pl_long), 'name' => $spouse ? '<a href="' . $spouse->getHtmlUrl() . '"' . $spouse->getFullName() . '</a>' : '', 'pl_icon' => $latlongval->pl_icon, 'place' => $fact->getPlace()->getFullName(), 'sv_bearing' => $latlongval->sv_bearing, 'sv_elevation' => $latlongval->sv_elevation, 'sv_lati' => $latlongval->sv_lati, 'sv_long' => $latlongval->sv_long, 'sv_zoom' => $latlongval->sv_zoom, 'tooltip' => $fact->getPlace()->getGedcomName()); if ($GM_MAX_ZOOM > $latlongval->pl_zoom) { $GM_MAX_ZOOM = $latlongval->pl_zoom; } } } } } // Add children to the markers list array foreach ($indi->getSpouseFamilies() as $family) { foreach ($family->getChildren() as $child) { $birth = $child->getFirstFact('BIRT'); if ($birth) { $birthrec = $birth->getGedcom(); if (!$birth->getPlace()->isEmpty()) { $ctla = preg_match('/\\n4 LATI (.+)/', $birthrec, $match1); $ctlo = preg_match('/\\n4 LONG (.+)/', $birthrec, $match2); if ($ctla && $ctlo) { $i++; $gmarks[$i] = array('date' => $birth->getDate()->display(true), 'image' => $child->displayImage(), 'info' => '', 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $match1[1]), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $match2[1]), 'name' => '<a href="' . $child->getHtmlUrl() . '"' . $child->getFullName() . '</a>', 'pl_icon' => '', 'place' => $birth->getPlace()->getFullName(), 'sv_bearing' => '0', 'sv_elevation' => '0', 'sv_lati' => '0', 'sv_long' => '0', 'sv_zoom' => '0', 'tooltip' => $birth->getPlace()->getGedcomName()); switch ($child->getSex()) { case 'F': $gmarks[$i]['fact_label'] = I18N::translate('daughter'); $gmarks[$i]['class'] = 'person_boxF'; break; case 'M': $gmarks[$i]['fact_label'] = I18N::translate('son'); $gmarks[$i]['class'] = 'person_box'; break; default: $gmarks[$i]['fact_label'] = I18N::translate('child'); $gmarks[$i]['class'] = 'person_boxNN'; break; } } else { $latlongval = $this->getLatitudeAndLongitudeFromPlaceLocation($birth->getPlace()->getGedcomName()); if ($latlongval && $latlongval->pl_lati && $latlongval->pl_long) { $i++; $gmarks[$i] = array('date' => $birth->getDate()->display(true), 'image' => $child->displayImage(), 'info' => '', 'lat' => str_replace(array('N', 'S', ','), array('', '-', '.'), $latlongval->pl_lati), 'lng' => str_replace(array('E', 'W', ','), array('', '-', '.'), $latlongval->pl_long), 'name' => '<a href="' . $child->getHtmlUrl() . '"' . $child->getFullName() . '</a>', 'pl_icon' => $latlongval->pl_icon, 'place' => $birth->getPlace()->getFullName(), 'sv_bearing' => $latlongval->sv_bearing, 'sv_elevation' => $latlongval->sv_elevation, 'sv_lati' => $latlongval->sv_lati, 'sv_long' => $latlongval->sv_long, 'sv_zoom' => $latlongval->sv_zoom, 'tooltip' => $birth->getPlace()->getGedcomName()); switch ($child->getSex()) { case 'M': $gmarks[$i]['fact_label'] = I18N::translate('son'); $gmarks[$i]['class'] = 'person_box'; break; case 'F': $gmarks[$i]['fact_label'] = I18N::translate('daughter'); $gmarks[$i]['class'] = 'person_boxF'; break; default: $gmarks[$i]['fact_label'] = I18N::translate('child'); $gmarks[$i]['class'] = 'option_boxNN'; break; } if ($GM_MAX_ZOOM > $latlongval->pl_zoom) { $GM_MAX_ZOOM = $latlongval->pl_zoom; } } } } } } } // *** ENABLE STREETVIEW *** $STREETVIEW = $this->getSetting('GM_USE_STREETVIEW'); ?> <script> // this variable will collect the html which will eventually be placed in the side_bar var side_bar_html = ''; var map_center = new google.maps.LatLng(0,0); var gmarkers = []; var gicons = []; var map = null; var head = ''; var dir = ''; var svzoom = ''; var infowindow = new google.maps.InfoWindow({}); gicons["red"] = new google.maps.MarkerImage("https://maps.google.com/mapfiles/marker.png", new google.maps.Size(20, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34) ); var iconImage = new google.maps.MarkerImage("https://maps.google.com/mapfiles/marker.png", new google.maps.Size(20, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34) ); var iconShadow = new google.maps.MarkerImage("https://www.google.com/mapfiles/shadow50.png", new google.maps.Size(37, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34) ); var iconShape = { coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0], type: "poly" }; function getMarkerImage(iconColor) { if (typeof(iconColor) === 'undefined' || iconColor === null) { iconColor = 'red'; } if (!gicons[iconColor]) { gicons[iconColor] = new google.maps.MarkerImage('//maps.google.com/mapfiles/marker'+ iconColor +'.png', new google.maps.Size(20, 34), new google.maps.Point(0,0), new google.maps.Point(9, 34)); } return gicons[iconColor]; } var sv2_bear = null; var sv2_elev = null; var sv2_zoom = null; var placer = null; // A function to create the marker and set up the event window function createMarker(latlng, html, tooltip, sv_lati, sv_long, sv_bearing, sv_elevation, sv_zoom, sv_point, marker_icon) { var contentString = '<div id="iwcontent">'+html+'</div>'; // Use flag icon (if defined) instead of regular marker icon if (marker_icon) { var icon_image = new google.maps.MarkerImage(WT_STATIC_URL+WT_MODULES_DIR+'googlemap/'+marker_icon, new google.maps.Size(25, 15), new google.maps.Point(0,0), new google.maps.Point(12, 15)); var icon_shadow = new google.maps.MarkerImage(WT_STATIC_URL+WT_MODULES_DIR+'googlemap/images/flag_shadow.png', new google.maps.Size(35, 45), // Shadow size new google.maps.Point(0,0), // Shadow origin new google.maps.Point(1, 45) // Shadow anchor is base of flagpole ); } else { var icon_image = getMarkerImage('red'); var icon_shadow = iconShadow; } // Decide if marker point is Regular (latlng) or StreetView (sv_point) derived if (sv_point == '(0, 0)' || sv_point == '(null, null)') { placer = latlng; } else { placer = sv_point; } // Define the marker var marker = new google.maps.Marker({ position: placer, icon: icon_image, shadow: icon_shadow, map: map, title: tooltip, zIndex: Math.round(latlng.lat()*-100000)<<5 }); // Store the tab and event info as marker properties marker.sv_lati = sv_lati; marker.sv_long = sv_long; marker.sv_point = sv_point; if (sv_bearing == '') { marker.sv_bearing = 0; } else { marker.sv_bearing = sv_bearing; } if (sv_elevation == '') { marker.sv_elevation = 5; } else { marker.sv_elevation = sv_elevation; } if (sv_zoom == '' || sv_zoom == 0 || sv_zoom == 1) { marker.sv_zoom = 1.2; } else { marker.sv_zoom = sv_zoom; } marker.sv_latlng = new google.maps.LatLng(sv_lati, sv_long); gmarkers.push(marker); // Open infowindow when marker is clicked google.maps.event.addListener(marker, 'click', function() { infowindow.close(); infowindow.setContent(contentString); infowindow.open(map, marker); var panoramaOptions = { position: marker.position, mode: 'html5', navigationControl: false, linksControl: false, addressControl: false, pov: { heading: sv_bearing, pitch: sv_elevation, zoom: sv_zoom } }; // Use jquery for info window tabs google.maps.event.addListener(infowindow, 'domready', function() { //jQuery code here jQuery('#EV').click(function() { document.tabLayerEV = document.getElementById("EV"); document.tabLayerEV.style.background = '#ffffff'; document.tabLayerEV.style.paddingBottom = '1px'; <?php if ($STREETVIEW) { ?> document.tabLayerSV = document.getElementById("SV"); document.tabLayerSV.style.background = '#cccccc'; document.tabLayerSV.style.paddingBottom = '0px'; <?php } ?> document.panelLayer1 = document.getElementById("pane1"); document.panelLayer1.style.display = 'block'; <?php if ($STREETVIEW) { ?> document.panelLayer2 = document.getElementById("pane2"); document.panelLayer2.style.display = 'none'; <?php } ?> }); jQuery('#SV').click(function() { document.tabLayerEV = document.getElementById("EV"); document.tabLayerEV.style.background = '#cccccc'; document.tabLayerEV.style.paddingBottom = '0px'; <?php if ($STREETVIEW) { ?> document.tabLayerSV = document.getElementById("SV"); document.tabLayerSV.style.background = '#ffffff'; document.tabLayerSV.style.paddingBottom = '1px'; <?php } ?> document.panelLayer1 = document.getElementById("pane1"); document.panelLayer1.style.display = 'none'; <?php if ($STREETVIEW) { ?> document.panelLayer2 = document.getElementById("pane2"); document.panelLayer2.style.display = 'block'; <?php } ?> var panorama = new google.maps.StreetViewPanorama(document.getElementById("pano"), panoramaOptions); setTimeout(function() { panorama.setVisible(true); }, 100); setTimeout(function() { panorama.setVisible(true); }, 500); }); }); }); } // Opens Marker infowindow when corresponding Sidebar item is clicked function myclick(i) { infowindow.close(); google.maps.event.trigger(gmarkers[i], 'click'); return false; } // Home control // returns the user to the original map position ... loadMap() function // This constructor takes the control DIV as an argument. function HomeControl(controlDiv, map) { // Set CSS styles for the DIV containing the control // Setting padding to 5 px will offset the control from the edge of the map controlDiv.style.paddingTop = '5px'; controlDiv.style.paddingRight = '0px'; // Set CSS for the control border var controlUI = document.createElement('DIV'); controlUI.style.backgroundColor = 'white'; controlUI.style.borderStyle = 'solid'; controlUI.style.borderWidth = '2px'; controlUI.style.cursor = 'pointer'; controlUI.style.textAlign = 'center'; controlUI.title = ''; controlDiv.appendChild(controlUI); // Set CSS for the control interior var controlText = document.createElement('DIV'); controlText.style.fontFamily = 'Arial,sans-serif'; controlText.style.fontSize = '12px'; controlText.style.paddingLeft = '15px'; controlText.style.paddingRight = '15px'; controlText.innerHTML = '<b><?php echo I18N::translate('Redraw map'); ?> </b>'; controlUI.appendChild(controlText); // Setup the click event listeners: simply set the map to original LatLng google.maps.event.addDomListener(controlUI, 'click', function() { loadMap(); }); } function loadMap() { // Create the map and mapOptions var mapOptions = { zoom: 7, center: map_center, mapTypeId: google.maps.MapTypeId.<?php echo $this->getSetting('GM_MAP_TYPE'); ?> , mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU // DEFAULT, DROPDOWN_MENU, HORIZONTAL_BAR }, navigationControl: true, navigationControlOptions: { position: google.maps.ControlPosition.TOP_RIGHT, // BOTTOM, BOTTOM_LEFT, LEFT, TOP, etc style: google.maps.NavigationControlStyle.SMALL // ANDROID, DEFAULT, SMALL, ZOOM_PAN }, streetViewControl: false, // Show Pegman or not scrollwheel: false }; map = new google.maps.Map(document.getElementById('map_pane'), mapOptions); // Close any infowindow when map is clicked google.maps.event.addListener(map, 'click', function() { infowindow.close(); }); // Create the Home DIV and call the HomeControl() constructor in this DIV. var homeControlDiv = document.createElement('DIV'); var homeControl = new HomeControl(homeControlDiv, map); homeControlDiv.index = 1; map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); // Add the markers to the map from the $gmarks array var locations = [ <?php foreach ($gmarks as $n => $gmark) { ?> <?php echo $n ? ',' : ''; ?> { "event": "<?php echo Filter::escapeJs($gmark['fact_label']); ?> ", "lat": "<?php echo Filter::escapeJs($gmark['lat']); ?> ", "lng": "<?php echo Filter::escapeJs($gmark['lng']); ?> ", "date": "<?php echo Filter::escapeJs($gmark['date']); ?> ", "info": "<?php echo Filter::escapeJs($gmark['info']); ?> ", "name": "<?php echo Filter::escapeJs($gmark['name']); ?> ", "place": "<?php echo Filter::escapeJs($gmark['place']); ?> ", "tooltip": "<?php echo Filter::escapeJs($gmark['tooltip']); ?> ", "image": "<?php echo Filter::escapeJs($gmark['image']); ?> ", "pl_icon": "<?php echo Filter::escapeJs($gmark['pl_icon']); ?> ", "sv_lati": "<?php echo Filter::escapeJs($gmark['sv_lati']); ?> ", "sv_long": "<?php echo Filter::escapeJs($gmark['sv_long']); ?> ", "sv_bearing": "<?php echo Filter::escapeJs($gmark['sv_bearing']); ?> ", "sv_elevation": "<?php echo Filter::escapeJs($gmark['sv_elevation']); ?> ", "sv_zoom": "<?php echo Filter::escapeJs($gmark['sv_zoom']); ?> " } <?php } ?> ]; // Group the markers by location var location_groups = []; for (var key in locations) { if (!location_groups.hasOwnProperty(locations[key].place)) { location_groups[locations[key].place] = []; } location_groups[locations[key].place].push(locations[key]); } // Set the Marker bounds var bounds = new google.maps.LatLngBounds (); var key; // Iterate over each location for (key in location_groups) { var locations = location_groups[key]; // Iterate over each marker at this location var event_details = ''; for (var j in locations) { var location = locations[j]; if (location.info && location.name) { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span> ' + location.info + '<br><b>' + location.name + '</b><br>' + location.date + '<br></p></td></tr></table>'; } else if (location.name) { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span><br><b>' + location.name + '</b><br>' + location.date + '<br></p></td></tr></table>'; } else if (location.info) { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span> ' + location.info + '<br>' + location.date + '<br></p></td></tr></table>'; } else { event_details += '<table><tr><td class="highlt_img">' + location.image + '</td><td><p><span id="sp1">' + location.event + '</span><br>' + location.date + '<br></p></td></tr></table>'; } } // All locations are the same in each group, so create a marker with the first var location = location_groups[key][0]; var html = '<div class="infowindow">' + '<div id="gmtabs">' + '<ul class="tabs" >' + '<li><a href="#event" id="EV"><?php echo I18N::translate('Events'); ?> </a></li>' + <?php if ($STREETVIEW) { ?> '<li><a href="#sview" id="SV"><?php echo I18N::translate('Google Street View™'); ?> </a></li>' + <?php } ?> '</ul>' + '<div class="panes">' + '<div id="pane1">' + '<h4 id="iwhead">' + location.place + '</h4>' + event_details + '</div>' + <?php if ($STREETVIEW) { ?> '<div id="pane2">' + '<h4 id="iwhead">' + location.place + '</h4>' + '<div id="pano"></div>' + '</div>' + <?php } ?> '</div>' + '</div>' + '</div>'; // create the marker var point = new google.maps.LatLng(location.lat, location.lng); // Place Latitude, Longitude var sv_point = new google.maps.LatLng(location.sv_lati, location.sv_long); // StreetView Latitude and Longitide var zoomLevel = <?php echo $GM_MAX_ZOOM; ?> ; var marker = createMarker(point, html, location.tooltip, location.sv_lati, location.sv_long, location.sv_bearing, location.sv_elevation, location.sv_zoom, sv_point, location.pl_icon); // if streetview coordinates are available, use them for marker, // else use the place coordinates if (sv_point && sv_point != "(0, 0)") { var myLatLng = sv_point; } else { var myLatLng = point; } // Correct zoom level when only one marker is present if (location_groups.length == 1) { bounds.extend(myLatLng); map.setZoom(zoomLevel); map.setCenter(myLatLng); } else { bounds.extend(myLatLng); map.fitBounds(bounds); // Correct zoom level when multiple markers have the same coordinates var listener1 = google.maps.event.addListenerOnce(map, "idle", function() { if (map.getZoom() > zoomLevel) { map.setZoom(zoomLevel); } google.maps.event.removeListener(listener1); }); } } // end loop through location markers } // end loadMap() </script> <?php // Create the normal googlemap sidebar of events and children echo '<div style="overflow: auto; overflow-x: hidden; overflow-y: auto; height:', $this->getSetting('GM_YSIZE'), 'px;"><table class="facts_table">'; foreach ($gmarks as $key => $gmark) { echo '<tr>'; echo '<td class="facts_label">'; echo '<a href="#" onclick="return myclick(\'', Filter::escapeHtml($key), '\')">', $gmark['fact_label'], '</a></td>'; echo '<td class="', $gmark['class'], '" style="white-space: normal">'; if ($gmark['info']) { echo '<span class="field">', Filter::escapeHtml($gmark['info']), '</span><br>'; } if ($gmark['name']) { echo $gmark['name'], '<br>'; } echo $gmark['place'], '<br>'; if ($gmark['date']) { echo $gmark['date'], '<br>'; } echo '</td>'; echo '</tr>'; } echo '</table></div><br>'; }
/** * Populate the timeline * * @return int */ public function fillTimeline() { $rows = array(); $maxY = self::CHART_TOP; //base case if (!$this->people) { return $maxY; } foreach ($this->people as $person) { $bdate = $this->getCalendarDate($person->getEstimatedBirthDate()->minimumJulianDay()); $ddate = $this->getCalendarDate($person->getEstimatedDeathDate()->maximumJulianDay()); $birthYear = $bdate->y; $age = min($ddate->y, $this->currentYear) - $birthYear; // truncate the bar at the current year $width = max(9, $age * self::PIXELS_PER_YEAR); // min width is width of sex icon $startPos = ($birthYear - $this->timelineMinYear) * self::PIXELS_PER_YEAR; //-- calculate a good Y top value $Y = self::CHART_TOP; $ready = false; while (!$ready) { if (!isset($rows[$Y])) { $ready = true; $rows[$Y]['x1'] = $startPos; $rows[$Y]['x2'] = $startPos + $width; } else { if ($rows[$Y]['x1'] > $startPos + $width) { $ready = true; $rows[$Y]['x1'] = $startPos; } elseif ($rows[$Y]['x2'] < $startPos) { $ready = true; $rows[$Y]['x2'] = $startPos + $width; } else { //move down a line $Y += self::BAR_SPACING; } } } $facts = $person->getFacts(); foreach ($person->getSpouseFamilies() as $family) { foreach ($family->getFacts() as $fact) { $facts[] = $fact; } } Functions::sortFacts($facts); $that = $this; // PHP5.3 cannot access $this inside a closure $acceptedFacts = array_filter($facts, function (Fact $fact) use($that) { return in_array($fact->getTag(), $that->facts) && $fact->getDate()->isOK() || ($that->place_obj || $that->startDate) && $that->checkFact($fact); }); $eventList = array(); foreach ($acceptedFacts as $fact) { $tag = $fact->getTag(); //-- if the fact is a generic EVENt then get the qualifying TYPE if ($tag == "EVEN") { $tag = $fact->getAttribute('TYPE'); } $eventList[] = array('label' => GedcomTag::getLabel($tag), 'date' => $fact->getDate()->display(), 'place' => $fact->getPlace()->getFullName()); } $direction = I18N::direction() === 'ltr' ? 'left' : 'right'; $lifespan = ' ' . $person->getLifeSpan(); // put the space here so its included in the length calcs $sex = $person->getSex(); $popupClass = strtr($sex, array('M' => '', 'U' => 'NN')); $color = $sex === 'U' ? '' : sprintf("background-color: %s", $this->colors[$sex]->getNextColor()); // following lines are a nasty method of approximating // the width of a string in pixels from the character count $name_length = mb_strlen(strip_tags($person->getFullName())) * 6.5; $short_name_length = mb_strlen(strip_tags($person->getShortName())) * 6.5; $lifespan_length = mb_strlen(strip_tags($lifespan)) * 6.5; if ($width > $name_length + $lifespan_length) { $printName = $person->getFullName(); $abbrLifespan = $lifespan; } elseif ($width > $name_length) { $printName = $person->getFullName(); $abbrLifespan = '…'; } elseif ($width > $short_name_length) { $printName = $person->getShortName(); $abbrLifespan = ''; } else { $printName = ''; $abbrLifespan = ''; } // Bar framework printf(' <div class="person_box%s" style="top:%spx; %s:%spx; width:%spx; %s"> <div class="itr">%s %s %s <div class="popup person_box%s"> <div> <a href="%s">%s%s</a> </div>', $popupClass, $Y, $direction, $startPos, $width, $color, $person->getSexImage(), $printName, $abbrLifespan, $popupClass, $person->getHtmlUrl(), $person->getFullName(), $lifespan); // Add events to popup foreach ($eventList as $event) { printf("<div>%s: %s %s</div>", $event['label'], $event['date'], $event['place']); } echo '</div>' . '</div>' . '</div>'; // class=$popupclass $maxY = max($maxY, $Y); } return $maxY; }
/** * Print the facts */ public function printFamilyFacts() { global $linkToID; $linkToID = $this->record->getXref(); // -- Tell addmedia.php what to link to $indifacts = $this->record->getFacts(); if ($indifacts) { Functions::sortFacts($indifacts); foreach ($indifacts as $fact) { FunctionsPrintFacts::printFact($fact, $this->record); } } else { echo '<tr><td class="messagebox" colspan="2">', I18N::translate('No facts exist for this family.'), '</td></tr>'; } if (Auth::isEditor($this->record->getTree())) { FunctionsPrint::printAddNewFact($this->record->getXref(), $indifacts, 'FAM'); echo '<tr><td class="descriptionbox">'; echo I18N::translate('Note'); echo '</td><td class="optionbox">'; echo "<a href=\"#\" onclick=\"return add_new_record('" . $this->record->getXref() . "','NOTE');\">", I18N::translate('Add a note'), '</a>'; echo '</td></tr>'; echo '<tr><td class="descriptionbox">'; echo I18N::translate('Shared note'); echo '</td><td class="optionbox">'; echo "<a href=\"#\" onclick=\"return add_new_record('" . $this->record->getXref() . "','SHARED_NOTE');\">", I18N::translate('Add a shared note'), '</a>'; echo '</td></tr>'; if ($this->record->getTree()->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($this->record->getTree())) { echo '<tr><td class="descriptionbox">'; echo I18N::translate('Media object'); echo '</td><td class="optionbox">'; echo "<a href=\"#\" onclick=\"window.open('addmedia.php?action=showmediaform&linktoid=" . $this->record->getXref() . "', '_blank', edit_window_specs); return false;\">", I18N::translate('Add a media object'), '</a>'; echo FunctionsPrint::helpLink('OBJE'); echo '<br>'; echo "<a href=\"#\" onclick=\"window.open('inverselink.php?linktoid=" . $this->record->getXref() . "&linkto=family', '_blank', find_window_specs); return false;\">", I18N::translate('Link to an existing media object'), '</a>'; echo '</td></tr>'; } echo '<tr><td class="descriptionbox">'; echo I18N::translate('Source'); echo '</td><td class="optionbox">'; echo "<a href=\"#\" onclick=\"return add_new_record('" . $this->record->getXref() . "','SOUR');\">", I18N::translate('Add a source citation'), '</a>'; echo '</td></tr>'; } }
/** {@inheritdoc} */ public function getTabContent() { global $controller; $EXPAND_HISTO_EVENTS = false; $indifacts = array(); // The individual’s own facts foreach ($controller->record->getFacts() as $fact) { switch ($fact->getTag()) { case 'SEX': case 'NAME': case 'SOUR': case 'OBJE': case 'NOTE': case 'FAMC': case 'FAMS': break; default: if (!array_key_exists('extra_info', Module::getActiveSidebars($controller->record->getTree())) || !ExtraInformationModule::showFact($fact)) { $indifacts[] = $fact; } break; } } // Add spouse-family facts foreach ($controller->record->getSpouseFamilies() as $family) { foreach ($family->getFacts() as $fact) { switch ($fact->getTag()) { case 'SOUR': case 'NOTE': case 'OBJE': case 'CHAN': case '_UID': case 'RIN': case 'HUSB': case 'WIFE': case 'CHIL': break; default: $indifacts[] = $fact; break; } } $spouse = $family->getSpouse($controller->record); if ($spouse) { foreach (self::spouseFacts($controller->record, $spouse) as $fact) { $indifacts[] = $fact; } } foreach (self::childFacts($controller->record, $family, '_CHIL', '') as $fact) { $indifacts[] = $fact; } } foreach (self::parentFacts($controller->record, 1) as $fact) { $indifacts[] = $fact; } foreach (self::historicalFacts($controller->record) as $fact) { $indifacts[] = $fact; } foreach (self::associateFacts($controller->record) as $fact) { $indifacts[] = $fact; } Functions::sortFacts($indifacts); ob_start(); echo '<table class="facts_table">'; echo '<tbody>'; if (!$indifacts) { echo '<tr><td colspan="2" class="facts_value">', I18N::translate('There are no facts for this individual.'), '</td></tr>'; } echo '<tr><td colspan="2" class="descriptionbox rela"><form action="?"><input id="checkbox_rela_facts" type="checkbox" '; echo $controller->record->getTree()->getPreference('EXPAND_RELATIVES_EVENTS') ? 'checked' : ''; echo ' onclick="jQuery(\'tr.rela\').toggle();"><label for="checkbox_rela_facts">', I18N::translate('Events of close relatives'), '</label>'; if (file_exists(Site::getPreference('INDEX_DIRECTORY') . 'histo.' . WT_LOCALE . '.php')) { echo ' <input id="checkbox_histo" type="checkbox" '; echo $EXPAND_HISTO_EVENTS ? 'checked' : ''; echo ' onclick="jQuery(\'tr.histo\').toggle();"><label for="checkbox_histo">', I18N::translate('Historical facts'), '</label>'; } echo '</form></td></tr>'; foreach ($indifacts as $fact) { FunctionsPrintFacts::printFact($fact, $controller->record); } //-- new fact link if ($controller->record->canEdit()) { FunctionsPrint::printAddNewFact($controller->record->getXref(), $indifacts, 'INDI'); } echo '</tbody>'; echo '</table>'; if (!$controller->record->getTree()->getPreference('EXPAND_RELATIVES_EVENTS')) { echo '<script>jQuery("tr.rela").toggle();</script>'; } if (!$EXPAND_HISTO_EVENTS) { echo '<script>jQuery("tr.histo").toggle();</script>'; } return '<div id="' . $this->getName() . '_content">' . ob_get_clean() . '</div>'; }
/** * The facts and events for this record. * * @param string $filter * @param bool $sort * @param int|null $access_level * @param bool $override Include private records, to allow us to implement $SHOW_PRIVATE_RELATIONSHIPS and $SHOW_LIVING_NAMES. * * @return Fact[] */ public function getFacts($filter = null, $sort = false, $access_level = null, $override = false) { if ($access_level === null) { $access_level = Auth::accessLevel($this->tree); } $facts = array(); if ($this->canShow($access_level) || $override) { foreach ($this->facts as $fact) { if (($filter === null || preg_match('/^' . $filter . '$/', $fact->getTag())) && $fact->canShow($access_level)) { $facts[] = $fact; } } } if ($sort) { Functions::sortFacts($facts); } return $facts; }
/** * XML <Facts> * * @param array $attrs an array of key value pairs for the attributes */ private function factsStartHandler($attrs) { global $WT_TREE; $this->process_repeats++; if ($this->process_repeats > 1) { return; } array_push($this->repeats_stack, array($this->repeats, $this->repeat_bytes)); $this->repeats = array(); $this->repeat_bytes = xml_get_current_line_number($this->parser); $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $this->gedrec, $match)) { $id = $match[1]; } $tag = ""; if (isset($attrs['ignore'])) { $tag .= $attrs['ignore']; } if (preg_match("/\\\$(.+)/", $tag, $match)) { $tag = $this->vars[$match[1]]['id']; } $record = GedcomRecord::getInstance($id, $WT_TREE); if (empty($attrs['diff']) && !empty($id)) { $facts = $record->getFacts(); Functions::sortFacts($facts); $this->repeats = array(); $nonfacts = explode(',', $tag); foreach ($facts as $event) { if (!in_array($event->getTag(), $nonfacts)) { $this->repeats[] = $event->getGedcom(); } } } else { foreach ($record->getFacts() as $fact) { if ($fact->isPendingAddition() && $fact->getTag() !== 'CHAN') { $this->repeats[] = $fact->getGedcom(); } } } }
/** * Build a map for an individual. * * @param Individual $indi */ private function buildIndividualMap(Individual $indi) { $GM_MAX_ZOOM = $this->getSetting('GM_MAX_ZOOM'); $facts = $indi->getFacts(); foreach ($indi->getSpouseFamilies() as $family) { $facts = array_merge($facts, $family->getFacts()); // Add birth of children from this family to the facts array foreach ($family->getChildren() as $child) { $facts[] = $child->getFirstFact('BIRT'); } } $facts = array_values(array_filter($facts, function ($item) { // remove null facts (child without birth event) and // facts without places return !is_null($item) && !$item->getPlace()->isEmpty(); })); Functions::sortFacts($facts); // At this point we have an array of valid sorted facts // so now build the data structures needed for the map display $events = array(); $unique_places = array(); foreach ($facts as $fact) { $place_data = $this->getPlaceData($fact); if (!empty($place_data)) { $index = $place_data['index']; if ($place_data['mapdata']['pl_zoom']) { $GM_MAX_ZOOM = min($GM_MAX_ZOOM, $place_data['mapdata']['pl_zoom']); } // Produce the html for the sidebar $parent = $fact->getParent(); if ($parent instanceof Individual && $parent->getXref() !== $indi->getXref()) { // Childs birth $name = '<a href="' . $parent->getHtmlUrl() . '">' . $parent->getFullName() . '</a>'; $label = strtr($parent->getSex(), array('F' => I18N::translate('Birth of a daughter'), 'M' => I18N::translate('Birth of a son'), 'U' => I18N::translate('Birth of a child'))); $class = 'person_box' . strtr($parent->getSex(), array('F' => 'F', 'M' => '', 'U' => 'NN')); $evtStr = '<div class="gm-event">' . $label . '<div><strong>' . $name . '</strong></div>' . $fact->getDate()->display(true) . '</div>'; } else { $spouse = $parent instanceof Family ? $parent->getSpouse($indi) : null; $name = $spouse ? '<a href="' . $spouse->getHtmlUrl() . '">' . $spouse->getFullName() . '</a>' : ''; $label = $fact->getLabel(); $class = 'optionbox'; if ($fact->getValue() && $spouse) { $evtStr = '<div class="gm-event">' . $label . '<div>' . $fact->getValue() . '</div><strong>' . $name . '</strong>' . $fact->getDate()->display(true) . '</div>'; } elseif ($spouse) { $evtStr = '<div class="gm-event">' . $label . '<div><strong>' . $name . '</strong></div>' . $fact->getDate()->display(true) . '</div>'; } elseif ($fact->getValue()) { $evtStr = '<div class="gm-event">' . $label . '<div> ' . $fact->getValue() . '</div>' . $fact->getDate()->display(true) . '</div>'; } else { $evtStr = '<div class="gm-event">' . $label . '<div>' . $fact->getDate()->display(true) . '</div></div>'; } } if (empty($unique_places[$index])) { $unique_places[$index] = $place_data['mapdata']; } $unique_places[$index]['events'] .= $evtStr; $events[] = array('class' => $class, 'fact_label' => $label, 'date' => $fact->getDate()->display(true), 'info' => $fact->getValue(), 'name' => $name, 'place' => '<a href="' . $fact->getPlace()->getURL() . '">' . $fact->getPlace()->getFullName() . '</a>', 'placeid' => $index); } } if (!empty($events)) { $places = array_keys($unique_places); ob_start(); // Create the normal googlemap sidebar of events and children echo '<div class="gm-events"><table class="facts_table">'; foreach ($events as $event) { $index = array_search($event['placeid'], $places); echo '<tr>'; echo '<td class="facts_label">'; echo '<a href="#" onclick="return openInfowindow(\'', $index, '\')">', $event['fact_label'], '</a></td>'; echo '<td class="', $event['class'], '">'; if ($event['info']) { echo '<div><span class="field">', Filter::escapeHtml($event['info']), '</span></div>'; } if ($event['name']) { echo '<div>', $event['name'], '</div>'; } echo '<div>', $event['place'], '</div>'; if ($event['date']) { echo '<div>', $event['date'], '</div>'; } echo '</td>'; echo '</tr>'; } echo '</table></div>'; // *** ENABLE STREETVIEW *** $STREETVIEW = (bool) $this->getSetting('GM_USE_STREETVIEW'); ?> <script> var map_center = new google.maps.LatLng(0, 0); var gmarkers = []; var gicons = []; var map = null; var head = ''; var dir = ''; var svzoom = ''; var infowindow = new google.maps.InfoWindow({}); gicons["red"] = { url: "https://maps.google.com/mapfiles/marker.png", size: google.maps.Size(20, 34), origin: google.maps.Point(0, 0), anchor: google.maps.Point(9, 34) }; var iconImage = { url: "https://maps.google.com/mapfiles/marker.png", size: new google.maps.Size(20, 34), origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(9, 34) }; var iconShape = { coord: [9, 0, 6, 1, 4, 2, 2, 4, 0, 8, 0, 12, 1, 14, 2, 16, 5, 19, 7, 23, 8, 26, 9, 30, 9, 34, 11, 34, 11, 30, 12, 26, 13, 24, 14, 21, 16, 18, 18, 16, 20, 12, 20, 8, 18, 4, 16, 2, 15, 1, 13, 0], type: "poly" }; function getMarkerImage(iconColor) { if (typeof(iconColor) === 'undefined' || iconColor === null) { iconColor = 'red'; } if (!gicons[iconColor]) { gicons[iconColor] = { url: '//maps.google.com/mapfiles/marker' + iconColor + '.png', size: new google.maps.Size(20, 34), origin: new google.maps.Point(0, 0), anchor: google.maps.Point(9, 34) }; } return gicons[iconColor]; } var sv2_bear = null; var sv2_elev = null; var sv2_zoom = null; var placer = null; // A function to create the marker and set up the event window function createMarker(latlng, html, tooltip, sv_lati, sv_long, sv_bearing, sv_elevation, sv_zoom, sv_point, marker_icon) { // Use flag icon (if defined) instead of regular marker icon if (marker_icon) { var icon_image = { url: WT_STATIC_URL + WT_MODULES_DIR + 'googlemap/' + marker_icon, size: new google.maps.Size(25, 15), origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(12, 15) }; } else { var icon_image = getMarkerImage('red'); } // Decide if marker point is Regular (latlng) or StreetView (sv_point) derived if (sv_point == '(0, 0)' || sv_point == '(null, null)') { placer = latlng; } else { placer = sv_point; } // Define the marker var marker = new google.maps.Marker({ position: placer, icon: icon_image, map: map, title: tooltip, zIndex: Math.round(latlng.lat() * -100000) << 5 }); // Store the tab and event info as marker properties marker.sv_lati = sv_lati; marker.sv_long = sv_long; marker.sv_point = sv_point; if (sv_bearing == '') { marker.sv_bearing = 0; } else { marker.sv_bearing = sv_bearing; } if (sv_elevation == '') { marker.sv_elevation = 5; } else { marker.sv_elevation = sv_elevation; } if (sv_zoom == '' || sv_zoom == 0 || sv_zoom == 1) { marker.sv_zoom = 1.2; } else { marker.sv_zoom = sv_zoom; } marker.sv_latlng = new google.maps.LatLng(sv_lati, sv_long); gmarkers.push(marker); // Open infowindow when marker is clicked google.maps.event.addListener(marker, 'click', function() { infowindow.close(); infowindow.setContent(html); infowindow.open(map, marker); var panoramaOptions = { position: marker.position, mode: 'html5', navigationControl: false, linksControl: false, addressControl: false, pov: { heading: sv_bearing, pitch: sv_elevation, zoom: sv_zoom } }; // Tabs within the info-windows. <?php if ($STREETVIEW) { ?> google.maps.event.addListener(infowindow, 'domready', function() { jQuery('#gm-tab-events').click(function () { document.getElementById("gm-tab-events").classList.add('gm-tab-active'); document.getElementById("gm-tab-streetview").classList.remove('gm-tab-active'); document.getElementById("gm-pane-events").style.display = 'block'; document.getElementById("gm-pane-streetview").style.display = 'none'; return false; }); jQuery('#gm-tab-streetview').click(function () { document.getElementById("gm-tab-events").classList.remove('gm-tab-active'); document.getElementById("gm-tab-streetview").classList.add('gm-tab-active'); document.getElementById("gm-pane-events").style.display = 'none'; document.getElementById("gm-pane-streetview").style.display = 'block'; var panorama = new google.maps.StreetViewPanorama(document.querySelector(".gm-streetview"), panoramaOptions); return false; }); }); <?php } ?> }); } // Opens Marker infowindow when corresponding Sidebar item is clicked function openInfowindow(i) { infowindow.close(); google.maps.event.trigger(gmarkers[i], 'click'); return false; } function loadMap() { // Create the map and mapOptions var mapOptions = { zoom: 7, center: map_center, mapTypeId: google.maps.MapTypeId.<?php echo $this->getSetting('GM_MAP_TYPE'); ?> , mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU // DEFAULT, DROPDOWN_MENU, HORIZONTAL_BAR }, navigationControl: true, navigationControlOptions: { position: google.maps.ControlPosition.TOP_RIGHT, // BOTTOM, BOTTOM_LEFT, LEFT, TOP, etc style: google.maps.NavigationControlStyle.SMALL // ANDROID, DEFAULT, SMALL, ZOOM_PAN }, streetViewControl: true, scrollwheel: true }; map = new google.maps.Map(document.querySelector('.gm-map'), mapOptions); // Close any infowindow when map is clicked google.maps.event.addListener(map, 'click', function() { infowindow.close(); }); // Add the markers to the map // Group the markers by location var locations = <?php echo json_encode($unique_places); ?> ; // Set the Marker bounds var bounds = new google.maps.LatLngBounds(); var zoomLevel = <?php echo $GM_MAX_ZOOM; ?> ; jQuery.each(locations, function(index, location) { var point = new google.maps.LatLng(location.lat, location.lng); // Place Latitude, Longitude var sv_point = new google.maps.LatLng(location.sv_lati, location.sv_long); // StreetView Latitude and Longitide var html = '<div class="gm-info-window">' + '<div class="gm-info-window-header">' + location.place + '</div>' + '<ul class="gm-tabs">' + '<li class="gm-tab gm-tab-active" id="gm-tab-events"><a href="#"><?php echo I18N::translate('Events'); ?> </a></li>' + <?php if ($STREETVIEW) { ?> '<li class="gm-tab" id="gm-tab-streetview"><a href="#"><?php echo I18N::translate('Google Street View™'); ?> </a></li>' + <?php } ?> '</ul>' + '<div class="gm-panes">' + '<div class="gm-pane" id="gm-pane-events">' + location.events + '</div>' + <?php if ($STREETVIEW) { ?> '<div class="gm-pane" id="gm-pane-streetview" hidden><div class="gm-streetview"></div></div>' + <?php } ?> '</div>' + '</div>'; createMarker(point, html, location.tooltip, location.sv_lati, location.sv_long, location.sv_bearing, location.sv_elevation, location.sv_zoom, sv_point, location.pl_icon); // if streetview coordinates are available, use them for marker, // else use the place coordinates if (sv_point && sv_point != "(0, 0)") { var myLatLng = sv_point; } else { var myLatLng = point; } bounds.extend(myLatLng); }); // end loop through location markers map.setCenter(bounds.getCenter()); map.fitBounds(bounds); google.maps.event.addListenerOnce(map, "bounds_changed", function(event) { if (this.getZoom() > zoomLevel) { this.setZoom(zoomLevel); } }); } // end loadMap() </script> <?php $html = ob_get_clean(); } else { $html = ''; } return $html; }
// at a scale of 25 or higher, show every year $mod = 25 / $controller->scale; if ($mod < 1) { $mod = 1; } for ($i = $controller->baseyear + 1; $i < $controller->topyear; $i++) { if ($i % $mod === 0) { echo '<div id="scale' . $i . '" style="position:absolute; ' . (I18N::direction() === 'ltr' ? 'left: ' . $basexoffset : 'right: ' . $basexoffset) . 'px; top:' . ($baseyoffset + ($i - $controller->baseyear) * $controller->scale - $controller->scale / 2) . 'px; font-size: 7pt; text-align:' . (I18N::direction() === 'ltr' ? 'left' : 'right') . ';">'; echo $i . '—'; echo '</div>'; } } echo '<div id="scale' . $controller->topyear . '" style="position:absolute; ' . (I18N::direction() === 'ltr' ? 'left: ' . $basexoffset : 'right: ' . $basexoffset) . 'px; top:' . ($baseyoffset + ($controller->topyear - $controller->baseyear) * $controller->scale) . 'px; font-size: 7pt; text-align:' . (I18N::direction() === 'ltr' ? 'left' : 'right') . ';">'; echo $controller->topyear . '—'; echo '</div>'; Functions::sortFacts($controller->indifacts); $factcount = 0; foreach ($controller->indifacts as $fact) { $controller->printTimeFact($fact); $factcount++; } // print the age boxes foreach ($controller->people as $p => $indi) { $pid = $indi->getXref(); $ageyoffset = $baseyoffset + $controller->bheight * $p; $col = $p % 6; ?> <div id="agebox<?php echo $p; ?> " style="cursor:move; position:absolute; <?php
global $WT_TREE; use Fisharebest\Webtrees\Functions\Functions; define('WT_SCRIPT_NAME', 'expand_view.php'); require './includes/session.php'; header('Content-Type: text/html; charset=UTF-8'); $individual = Individual::getInstance(Filter::get('pid', WT_REGEX_XREF), $WT_TREE); if (!$individual || !$individual->canShow()) { return I18N::translate('Private'); } $facts = $individual->getFacts(); foreach ($individual->getSpouseFamilies() as $family) { foreach ($family->getFacts() as $fact) { $facts[] = $fact; } } Functions::sortFacts($facts); foreach ($facts as $fact) { switch ($fact->getTag()) { case 'ADDR': case 'ALIA': case 'ASSO': case 'CHAN': case 'CHIL': case 'EMAIL': case 'FAMC': case 'FAMS': case 'HUSB': case 'NAME': case 'NOTE': case 'OBJE': case 'PHON':