/**
     * {@inhericDoc}
     * @see \MyArtJaub\Webtrees\Mvc\View\AbstractView::renderContent()
     */
    protected function renderContent()
    {
        $nb_found = $this->data->get('stats_gen_nb_found');
        $nb_other = $this->data->get('stats_gen_nb_other');
        $nb_unknown = $this->data->get('stats_gen_nb_unknown');
        $perc_known = Functions::safeDivision($nb_found - $nb_other, $nb_found + $nb_unknown);
        $html = '<div id="geodispersion_summary">
        	<div class="maj-table center">
        		<div class="maj-row">
        			<div class="label">' . I18N::translate('Places found') . '</div>
        			<div class="value">' . I18N::translate('%1$d (%2$s)', $nb_found - $nb_other, I18N::percentage($perc_known)) . '</div>
        		</div>';
        if ($nb_other > 0) {
            $perc_other = Functions::safeDivision($nb_other, $nb_found + $nb_unknown);
            $html .= '<div class="maj-row">
        			<div class="label">' . I18N::translate('Other places') . '</div>
        			<div class="value">' . I18N::translate('%1$d (%2$s)', $nb_other, I18N::percentage($perc_other)) . '</div>
        		</div>';
        }
        $html .= '<div class="maj-row">
        			<div class="label">' . I18N::translate('Places not found') . '</div>
        			<div class="value">' . I18N::translate('%1$d (%2$s)', $nb_unknown, I18N::percentage(1 - $perc_known)) . '</div>
        		</div>
        	</div>
        </div>
        <br/>
		<div id="geodispersion_data">
		' . $this->htmlAnalysisData() . '
		</div>';
        return $html;
    }
 /**
  * {@inheritDoc}
  * @see \MyArtJaub\Webtrees\Module\GeoDispersion\Views\AbstractGeoAnalysisTabGeneralView::htmlAnalysisData()
  */
 protected function htmlAnalysisData()
 {
     $results = $this->data->get('results');
     $analysis_level = $this->data->get('analysis_level');
     $nb_found = $this->data->get('stats_gen_nb_found');
     $nb_other = $this->data->get('stats_gen_nb_other');
     $i = 1;
     $previous_nb = 0;
     $html = '<div class="maj-table center">';
     foreach ($results as $place => $nb) {
         $perc = Functions::safeDivision($nb, $nb_found - $nb_other);
         if ($nb != $previous_nb) {
             $j = I18N::number($i);
         } else {
             $j = '&nbsp;';
         }
         $levels = array_map('trim', explode(',', $place));
         $placename = $levels[$analysis_level - 1];
         if ($placename == '' && $analysis_level > 1) {
             $placename = I18N::translate('Unknown (%s)', $levels[$analysis_level - 2]);
         }
         $html .= '<div class="maj-row">
             <div class="label"><strong>' . $j . '</strong></div>
             <div class="label">' . $placename . '</div>
             <div class="value">' . I18N::translate('%d', $nb) . '</div>
             <div class="value">' . I18N::percentage($perc, 1) . '</div>
          </div>';
         $i++;
         $previous_nb = $nb;
     }
     $html .= '</div>';
     return $html;
 }
예제 #3
0
    /**
     * Render the Ajax response for the sortable table of Sosa individuals
     * @param AjaxController $controller
     */
    protected function renderSosaListIndi(AjaxController $controller)
    {
        global $WT_TREE;
        $listSosa = $this->sosa_provider->getSosaListAtGeneration($this->generation);
        $this->view_bag->set('has_sosa', false);
        if (count($listSosa) > 0) {
            $this->view_bag->set('has_sosa', true);
            $table_id = 'table-sosa-indi-' . Uuid::uuid4();
            $this->view_bag->set('table_id', $table_id);
            $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.fn.dataTableExt.oSort["num-html-asc" ]=function(a,b) {a=parseFloat(a.replace(/<[^<]*>/, "")); b=parseFloat(b.replace(/<[^<]*>/, "")); return (a<b) ? -1 : (a>b ? 1 : 0);};
				jQuery.fn.dataTableExt.oSort["num-html-desc"]=function(a,b) {a=parseFloat(a.replace(/<[^<]*>/, "")); b=parseFloat(b.replace(/<[^<]*>/, "")); return (a>b) ? -1 : (a<b ? 1 : 0);};
            
                jQuery("#' . $table_id . '").dataTable( {
					dom: \'<"H"<"filtersH_' . $table_id . '">T<"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-Sosa */  		{ type: "num", class: "center" },
		                /* 1-ID */ 			{ visible: false },
		                /* 2-givn */ 		{ dataSort: 4,  class: "left"},
						/* 3-surn */ 		{ datasort: 5},
						/* 4-GIVN,SURN */ 	{ type: "unicode", visible: false},
						/* 5-SURN,GIVN */ 	{ type: "unicode", visible: false},
		                /* 6-Birth */		{ dataSort : 7 , class: "center"},
		                /* 7-SORT_BIRT */	{ visible : false},
		                /* 8-BIRT_PLAC */	{ type: "unicode", class: "center"},
		                /* PERSO Modify table to include IsSourced module */
		                /* 9-BIRT_SOUR */   { dataSort : 10, class: "center", visible: ' . (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME) ? 'true' : 'false') . ' },
						/* 10-SORT_BIRTSC */{ visible : false},
		                /* 11-Death */		{ dataSort : 12 , class: "center"},
		                /* 12-SORT_DEAT */	{ visible : false},
		                /* 13-Age */		{ dataSort : 14 , class: "center"},
		                /* 14-AGE */		{ type: "num", visible: false},
		                /* 15-DEAT_PLAC */	{ type: "unicode", class: "center" },
		                /* 16-DEAT_SOUR */	{ dataSort : 17, class: "center", visible: ' . (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME) ? 'true' : 'false') . ' },
		                /* 17-SORT_DEATSC */{ visible : false},
		                /* 18-SEX */		{ visible : false},
		                /* 19-BIRT */		{ visible : false},
		                /* 20-DEAT */		{ visible : false},
		                /* 21-TREE */		{ visible : false}
		                /* END PERSO */
					],
		            sorting: [[0,"asc"]],
					displayLength: 16,
					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("#indi_list_table-charts_' . $table_id . '").slideToggle();
				})
				/* Filter buttons in table header */
				.on("click", "button[data-filter-column]", function() {
					var btn = jQuery(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("#sosa-indi-list").css("visibility", "visible");
		
				jQuery("#btn-toggle-statistics-' . $table_id . '").click();
           ');
            $stats = new Stats($WT_TREE);
            // Bad data can cause "longest life" to be huge, blowing memory limits
            $max_age = min($WT_TREE->getPreference('MAX_ALIVE_AGE'), $stats->LongestLifeAge()) + 1;
            // Inititialise chart data
            $deat_by_age = array();
            for ($age = 0; $age <= $max_age; $age++) {
                $deat_by_age[$age] = '';
            }
            $birt_by_decade = array();
            $deat_by_decade = array();
            for ($year = 1550; $year < 2030; $year += 10) {
                $birt_by_decade[$year] = '';
                $deat_by_decade[$year] = '';
            }
            $unique_indis = array();
            // Don't double-count indis with multiple names.
            $nb_displayed = 0;
            Individual::load($WT_TREE, $listSosa);
            foreach ($listSosa as $sosa => $pid) {
                $person = Individual::getInstance($pid, $WT_TREE);
                if (!$person || !$person->canShowName()) {
                    unset($listSosa[$sosa]);
                    continue;
                }
                $nb_displayed++;
                if ($birth_dates = $person->getAllBirthDates()) {
                    if (FunctionsPrint::isDateWithinChartsRange($birth_dates[0]) && !isset($unique_indis[$person->getXref()])) {
                        $birt_by_decade[(int) ($birth_dates[0]->gregorianYear() / 10) * 10] .= $person->getSex();
                    }
                } else {
                    $birth_dates[0] = new Date('');
                }
                if ($death_dates = $person->getAllDeathDates()) {
                    if (FunctionsPrint::isDateWithinChartsRange($death_dates[0]) && !isset($unique_indis[$person->getXref()])) {
                        $deat_by_decade[(int) ($death_dates[0]->gregorianYear() / 10) * 10] .= $person->getSex();
                    }
                } else {
                    $death_dates[0] = new Date('');
                }
                $age = Date::getAge($birth_dates[0], $death_dates[0], 0);
                if (!isset($unique_indis[$person->getXref()]) && $age >= 0 && $age <= $max_age) {
                    $deat_by_age[$age] .= $person->getSex();
                }
                $listSosa[$sosa] = $person;
                $unique_indis[$person->getXref()] = true;
            }
            $this->view_bag->set('sosa_list', $listSosa);
            $this->view_bag->set('sosa_count', count($listSosa));
            $this->view_bag->set('sosa_theo', pow(2, $this->generation - 1));
            $this->view_bag->set('sosa_ratio', Functions::safeDivision($this->view_bag->get('sosa_count'), $this->view_bag->get('sosa_theo')));
            $this->view_bag->set('sosa_hidden', $this->view_bag->get('sosa_count') - $nb_displayed);
            $this->view_bag->set('chart_births', FunctionsPrintLists::chartByDecade($birt_by_decade, I18N::translate('Decade of birth')));
            $this->view_bag->set('chart_deaths', FunctionsPrintLists::chartByDecade($deat_by_decade, I18N::translate('Decade of death')));
            $this->view_bag->set('chart_ages', FunctionsPrintLists::chartByAge($deat_by_age, I18N::translate('Age related to death year')));
        }
        ViewFactory::make('SosaListIndi', $this, $controller, $this->view_bag)->render();
    }
예제 #4
0
 /**
  * Returns HTML code for a graph showing the dispersion of ancestors across grand-parents
  * @return string HTML code
  */
 private function htmlAncestorDispersionG3()
 {
     $ancestorsDispGen2 = $this->sosa_provider->getAncestorDispersionForGen(3);
     $size = '700x300';
     $color_motmot = 'ffd1dc';
     $color_motfat = 'b998a0';
     $color_fatfat = '577292';
     $color_fatmot = '84beff';
     $color_shared = '777777';
     $total_fatfat = array_key_exists(1, $ancestorsDispGen2) ? $ancestorsDispGen2[1] : 0;
     $total_fatmot = array_key_exists(2, $ancestorsDispGen2) ? $ancestorsDispGen2[2] : 0;
     $total_motfat = array_key_exists(4, $ancestorsDispGen2) ? $ancestorsDispGen2[4] : 0;
     $total_motmot = array_key_exists(8, $ancestorsDispGen2) ? $ancestorsDispGen2[8] : 0;
     $total_sha = array_key_exists(-1, $ancestorsDispGen2) ? $ancestorsDispGen2[-1] : 0;
     $total = $total_fatfat + $total_fatmot + $total_motfat + $total_motmot + $total_sha;
     $chd = $this->arrayToExtendedEncoding(array(4095 * Functions::safeDivision($total_fatfat, $total), 4095 * Functions::safeDivision($total_fatmot, $total), 4095 * Functions::safeDivision($total_sha, $total), 4095 * Functions::safeDivision($total_motfat, $total), 4095 * Functions::safeDivision($total_motmot, $total)));
     $chart_title = I18N::translate('Known Sosa ancestors\' dispersion - G3');
     $chl = \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fatfat') . ' - ' . I18N::percentage(Functions::safeDivision($total_fatfat, $total), 1) . '|' . \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('fatmot') . ' - ' . I18N::percentage(Functions::safeDivision($total_fatmot, $total), 1) . '|' . I18N::translate('Shared') . ' - ' . I18N::percentage(Functions::safeDivision($total_sha, $total), 1) . '|' . \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('motfat') . ' - ' . I18N::percentage(Functions::safeDivision($total_motfat, $total), 1) . '|' . \Fisharebest\Webtrees\Functions\Functions::getRelationshipNameFromPath('motmot') . ' - ' . I18N::percentage(Functions::safeDivision($total_motmot, $total), 1);
     return "<img src=\"https://chart.googleapis.com/chart?cht=p&chp=1.5708&amp;chd=e:{$chd}&amp;chs={$size}&amp;chco={$color_fatfat},{$color_fatmot},{$color_shared},{$color_motfat},{$color_motmot}&amp;chf=bg,s,ffffff00&amp;chl={$chl}\" alt=\"" . $chart_title . "\" title=\"" . $chart_title . "\" />";
 }
예제 #5
0
 /**
  * Returns HTML code for the GeoAnalysis general tab (can be either a map or a table).
  *
  * @param GeoAnalysis $ga Reference GeoAnalysis 
  * @param array $placesGeneralResults Analysis results at a general level
  * @param (null|array) $flags Array of flags
  * @return string HTML code for the general tab
  */
 protected function htmlPlacesAnalysisGeneralTab(GeoAnalysis $ga, $placesGeneralResults, $flags = null)
 {
     global $WT_TREE;
     if (!empty($placesGeneralResults)) {
         $data = new ViewBag();
         $nb_found = $placesGeneralResults['knownsum'];
         $nb_other = 0;
         if (isset($placesGeneralResults['other'])) {
             $nb_other = $placesGeneralResults['other'];
         }
         $nb_unknown = $placesGeneralResults['unknown'];
         $data->set('stats_gen_nb_found', $nb_found);
         $data->set('stats_gen_nb_other', $nb_other);
         $data->set('stats_gen_nb_unknown', $nb_unknown);
         $data->set('use_flags', $ga->getOptions() && $ga->getOptions()->isUsingFlags());
         if ($ga->hasMap()) {
             $max = $placesGeneralResults['max'];
             $map = $ga->getOptions()->getMap();
             $results_by_subdivs = $map->getSubdivisions();
             $places_mappings = $map->getPlacesMappings();
             foreach ($placesGeneralResults['places'] as $location => $count) {
                 $levelvalues = array_reverse(array_map('trim', explode(',', $location)));
                 $level_map = $ga->getAnalysisLevel() - $ga->getOptions()->getMapLevel();
                 if ($level_map >= 0 && $level_map < count($levelvalues)) {
                     $levelref = $levelvalues[0] . '@' . $levelvalues[$level_map];
                     if (!isset($results_by_subdivs[$levelref])) {
                         $levelref = $levelvalues[0];
                     }
                 } else {
                     $levelref = $levelvalues[0];
                 }
                 if (isset($places_mappings[$levelref])) {
                     $levelref = $places_mappings[$levelref];
                 }
                 if (isset($results_by_subdivs[$levelref])) {
                     $count_subd = isset($results_by_subdivs[$levelref]['count']) ? $results_by_subdivs[$levelref]['count'] : 0;
                     $count_subd += $count;
                     $results_by_subdivs[$levelref]['count'] = $count_subd;
                     $results_by_subdivs[$levelref]['transparency'] = Functions::safeDivision($count_subd, $max);
                     if ($ga->getOptions()->isUsingFlags() && $flags) {
                         $results_by_subdivs[$levelref]['place'] = new Place($location, $WT_TREE);
                         $results_by_subdivs[$levelref]['flag'] = $flags[$location];
                     }
                 }
             }
             $data->set('map', $ga->getOptions()->getMap());
             $data->set('results_by_subdivisions', $results_by_subdivs);
             $html = ViewFactory::make('GeoAnalysisTabGeneralMap', $this, new BaseController(), $data)->getHtmlPartial();
         } else {
             $results = $placesGeneralResults['places'];
             arsort($results);
             $data->set('results', $results);
             $data->set('analysis_level', $ga->getAnalysisLevel());
             $html = ViewFactory::make('GeoAnalysisTabGeneralTable', $this, new BaseController(), $data)->getHtmlPartial();
         }
     } else {
         $html = '<p class="warning">' . I18N::translate('No data is available for the general analysis.') . '</p>';
     }
     return $html;
 }
    /**
     * {@inheritDoc}
     * @see \MyArtJaub\Webtrees\Module\GeoDispersion\Views\AbstractGeoAnalysisTabGeneralView::htmlAnalysisData()
     */
    protected function htmlAnalysisData()
    {
        /** @var OutlineMap $map */
        $map = $this->data->get('map');
        $canvas = $map->getCanvas();
        $subdvisions_results = $this->data->get('results_by_subdivisions');
        $nb_found = $this->data->get('stats_gen_nb_found');
        $nb_other = $this->data->get('stats_gen_nb_other');
        $html = '<script>
			var tip = null;
			var tipText = "";
			var over = false;
			var isin = false;

			function addTip(node, txt){
			    jQuery(node).bind({
			    	mouseover : function(){
			    		oldisin = isin;
			    		isin = true;
			    		if(oldisin != isin){
			       			tipText = txt;
			       			tip.stop(true, true).fadeIn();
			       			over = true;
			       		}
			    	},
			    	mouseout : function(){
			    		oldisin = isin;
			    		isin = false;
			    		if(oldisin != isin){
			       			tip.stop(true, true).fadeOut("fast");
			       			over = false;
			       		}
			    	}

			    });
			}
			jQuery(document).ready(function() {
				tip = $("#geodispersion_tip").hide();

				var positionTab = jQuery("#geodispersion-tabs").offset();

				jQuery("#geodispersion_map").mousemove(function(e){
				    if (over){
					  tip.css("left", e.pageX + 20 - positionTab.left).css("top", e.pageY + 20 - positionTab.top);
				      tip.html(tipText);
				    }
				});

				var paper = new Raphael(document.getElementById("geodispersion_map"), ' . $canvas->width . ', ' . $canvas->height . ');
				var background = paper.rect(0, 0, ' . $canvas->width . ', ' . $canvas->height . ');
				background.attr({"fill" : "' . $canvas->background_color . '", "stroke" : "' . $canvas->background_stroke . '", "stroke-width": 1, "stroke-linejoin": "round" });
				var attr = { fill: "' . $canvas->default_color . '", stroke: "' . $canvas->default_stroke . '", "stroke-width": 1, "stroke-linejoin": "round" };
				var map = {};
		';
        foreach ($subdvisions_results as $name => $location) {
            $html .= 'map.area' . $location['id'] . ' = paper.path("' . $location['coord'] . '").attr(attr);';
            if (isset($location['transparency'])) {
                $textToolTip = '<strong>' . $location['displayname'] . '</strong><br/>';
                if ($this->data->get('use_flags') && $location['flag'] != '') {
                    $textToolTip .= '<span class="geodispersion_flag">' . FunctionsPrint::htmlPlaceIcon($location['place'], $location['flag']) . '</span><br/>';
                }
                $textToolTip .= I18N::translate('%d individuals', $location['count']) . '<br/>' . I18N::percentage(Functions::safeDivision($location['count'], $nb_found - $nb_other), 1);
                $html .= 'addTip(map.area' . $location['id'] . '.node, "' . Filter::escapeJs($textToolTip) . '");';
                $html .= 'map.area' . $location['id'] . '.attr({"fill" : "' . $canvas->max_color . '", "fill-opacity" : ' . $location['transparency'] . ' });';
                $html .= 'map.area' . $location['id'] . '.mouseover(function () {' . 'map.area' . $location['id'] . '.stop().animate({"fill" : "' . $canvas->hover_color . '", "fill-opacity" : 1}, 100, "linear");' . '});' . 'map.area' . $location['id'] . '.mouseout(function () {' . 'map.area' . $location['id'] . '.stop().animate({"fill" : "' . $canvas->max_color . '", "fill-opacity" : ' . $location['transparency'] . '}, 100, "linear");' . '});';
            }
        }
        $html .= '});
            </script>
            
            <div id="geodispersion_map"></div>
    	   <div id="geodispersion_tip"></div>';
        return $html;
    }
 /**
  * Returns the HTML code fo display a row of the Top Places found for a generation.
  *
  * @param array $data Data array
  * @param int $analysis_level Level of subdivision of analysis
  * @return string HTML code for Top Places row
  */
 protected function htmlGenerationTopPlacesRow($data, $analysis_level)
 {
     $tmp_places = array();
     $sum_gen = $data['sum'];
     $other = $data['other'];
     foreach ($data['places'] as $placename => $count) {
         if ($placename != 'other') {
             $levels = array_map('trim', explode(',', $placename));
             $placename = '<span title="' . implode(I18N::$list_separator, array_reverse($levels)) . '">' . $levels[$analysis_level - 1] . '</span>';
         } else {
             $placename = I18N::translate('Other places');
         }
         $tmp_places[] = I18N::translate('<strong>%s</strong> [%d - %s]', $placename, $count, I18N::percentage(Functions::safeDivision($count, $sum_gen + $other), 1));
     }
     return implode(I18N::$list_separator, $tmp_places);
 }