summaryrefslogtreecommitdiff
path: root/modules_v3/tree
diff options
context:
space:
mode:
authorfisharebest <fisharebest@gmail.com>2011-08-04 19:03:17 +0000
committerfisharebest <fisharebest@gmail.com>2011-08-04 19:03:17 +0000
commit3a66749533ae4ec372c95f7b0a6363efa4f5d294 (patch)
tree48931d265ee51c08f56820a767237975b00ebc3a /modules_v3/tree
parentd83d060a1ac10dc72134c3d4804e89b04cc68ad6 (diff)
downloadwebtrees-3a66749533ae4ec372c95f7b0a6363efa4f5d294.tar.gz
webtrees-3a66749533ae4ec372c95f7b0a6363efa4f5d294.tar.bz2
webtrees-3a66749533ae4ec372c95f7b0a6363efa4f5d294.zip
#821050 - Error calling page after update to 1.2.2
Diffstat (limited to 'modules_v3/tree')
-rw-r--r--modules_v3/tree/class_treeview.php458
-rw-r--r--modules_v3/tree/css/styles/black/black.css121
-rw-r--r--modules_v3/tree/css/styles/black/button.gifbin0 -> 1291 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treebottom.gifbin0 -> 1012 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treebottomleft.gifbin0 -> 2124 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treebottomright.gifbin0 -> 2173 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treeleft.gifbin0 -> 717 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treeright.gifbin0 -> 715 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treetop.gifbin0 -> 1024 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treetopleft.gifbin0 -> 2132 bytes
-rw-r--r--modules_v3/tree/css/styles/black/treetopright.gifbin0 -> 2147 bytes
-rw-r--r--modules_v3/tree/css/styles/black/vline.jpgbin0 -> 672 bytes
-rw-r--r--modules_v3/tree/css/styles/black/vline_b.gifbin0 -> 75 bytes
-rw-r--r--modules_v3/tree/css/styles/black/vline_t.gifbin0 -> 75 bytes
-rw-r--r--modules_v3/tree/css/styles/default/button.gifbin0 -> 1297 bytes
-rw-r--r--modules_v3/tree/css/styles/default/default.css61
-rw-r--r--modules_v3/tree/css/styles/default/vline.jpgbin0 -> 672 bytes
-rw-r--r--modules_v3/tree/css/styles/default/vline_b.gifbin0 -> 75 bytes
-rw-r--r--modules_v3/tree/css/styles/default/vline_t.gifbin0 -> 75 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/button.gifbin0 -> 1237 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/parchemin_gris.css37
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/tree.jpgbin0 -> 920 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treebottom.gifbin0 -> 270 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treebottomleft.gifbin0 -> 2121 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treebottomright.gifbin0 -> 1830 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treeleft.gifbin0 -> 117 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treeright.gifbin0 -> 106 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treetop.gifbin0 -> 166 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treetopleft.gifbin0 -> 2487 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_gris/treetopright.gifbin0 -> 1268 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/button.gifbin0 -> 1261 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/papier.jpgbin0 -> 1144 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/parchemin_jauni.css69
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/tree.jpgbin0 -> 911 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treebottom.gifbin0 -> 273 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treebottomleft.gifbin0 -> 2204 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treebottomright.gifbin0 -> 2517 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treeleft.gifbin0 -> 287 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treeright.gifbin0 -> 164 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treetop.gifbin0 -> 306 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treetopleft.gifbin0 -> 2613 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/treetopright.gifbin0 -> 1789 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/vline.jpgbin0 -> 734 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/vline_b.gifbin0 -> 75 bytes
-rw-r--r--modules_v3/tree/css/styles/parchemin_jauni/vline_t.gifbin0 -> 75 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/button.gifbin0 -> 642 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/tree.jpgbin0 -> 947 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treebottom.gifbin0 -> 2004 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treebottomleft.gifbin0 -> 3470 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treebottomright.gifbin0 -> 3467 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treeleft.gifbin0 -> 1895 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treeright.gifbin0 -> 1895 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treetop.gifbin0 -> 2002 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treetopleft.gifbin0 -> 3463 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/treetopright.gifbin0 -> 3464 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/vline.jpgbin0 -> 675 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/vline_b.gifbin0 -> 82 bytes
-rw-r--r--modules_v3/tree/css/styles/simple/vline_t.gifbin0 -> 131 bytes
-rw-r--r--modules_v3/tree/css/tree.jpgbin0 -> 947 bytes
-rw-r--r--modules_v3/tree/css/treebottom.gifbin0 -> 2004 bytes
-rw-r--r--modules_v3/tree/css/treebottomleft.gifbin0 -> 3470 bytes
-rw-r--r--modules_v3/tree/css/treebottomright.gifbin0 -> 3467 bytes
-rw-r--r--modules_v3/tree/css/treeleft.gifbin0 -> 1895 bytes
-rw-r--r--modules_v3/tree/css/treeright.gifbin0 -> 1895 bytes
-rw-r--r--modules_v3/tree/css/treetop.gifbin0 -> 2002 bytes
-rw-r--r--modules_v3/tree/css/treetopleft.gifbin0 -> 3463 bytes
-rw-r--r--modules_v3/tree/css/treetopright.gifbin0 -> 3464 bytes
-rw-r--r--modules_v3/tree/css/treeview.css335
-rw-r--r--modules_v3/tree/css/treeview_print.css17
-rw-r--r--modules_v3/tree/css/vline.jpgbin0 -> 675 bytes
-rw-r--r--modules_v3/tree/css/vline_b.gifbin0 -> 82 bytes
-rw-r--r--modules_v3/tree/css/vline_t.gifbin0 -> 131 bytes
-rw-r--r--modules_v3/tree/help_text.php87
-rw-r--r--modules_v3/tree/images/alignLeft.pngbin0 -> 1195 bytes
-rw-r--r--modules_v3/tree/images/alignRight.pngbin0 -> 1197 bytes
-rw-r--r--modules_v3/tree/images/center.pngbin0 -> 351 bytes
-rw-r--r--modules_v3/tree/images/compact.pngbin0 -> 295 bytes
-rw-r--r--modules_v3/tree/images/dates.pngbin0 -> 379 bytes
-rw-r--r--modules_v3/tree/images/print.pngbin0 -> 1160 bytes
-rw-r--r--modules_v3/tree/images/zoom0.pngbin0 -> 466 bytes
-rw-r--r--modules_v3/tree/js/treeview.js568
-rw-r--r--modules_v3/tree/module.php157
82 files changed, 1910 insertions, 0 deletions
diff --git a/modules_v3/tree/class_treeview.php b/modules_v3/tree/class_treeview.php
new file mode 100644
index 0000000000..7a43196194
--- /dev/null
+++ b/modules_v3/tree/class_treeview.php
@@ -0,0 +1,458 @@
+<?php
+// Class file for the tree navigator
+//
+// Note : NEVER use person or family id as ids because a same person could
+// appear more than once in the tree.
+//
+// webtrees: Web based Family History software
+// Copyright (C) 2011 webtrees development team.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// $Id$
+
+if (!defined('WT_WEBTREES')) {
+ header('HTTP/1.0 403 Forbidden');
+ exit;
+}
+
+require_once 'includes/functions/functions_charts.php';
+
+class TreeView {
+ var $name;
+ var $allPartners;
+
+ /**
+ * Treeview Constructor
+ * @param string $name the name of the TreeView object's instance
+ */
+ function __construct($name='tree') {
+ $this->name = $name;
+
+ // Read if all partners must be shown or not
+ $allPartners = safe_GET('allPartners');
+ // if allPartners not specified in url, we try to read the cookie
+ if ($allPartners == '') {
+ if (isset($_COOKIE['allPartners']))
+ $allPartners = $_COOKIE['allPartners'];
+ else
+ $allPartners = 'true'; // That is now the default value
+ }
+ $allPartners = ($allPartners == 'true' ? true : false);
+ $this->allPartners = $allPartners;
+ }
+
+ /**
+ * Draw the viewport which creates the draggable/zoomable framework
+ * Size is set by the container, as the viewport can scale itself automatically
+ * @param string $rootPersonId the id of the root person
+ * @param int $generations number of generations to draw
+ */
+ public function drawViewport($rootPersonId, $generations, $style) {
+ global $GEDCOM, $WT_IMAGES;
+
+ $rootPersonId = check_rootid($rootPersonId);
+ $rootPerson = WT_Person::getInstance($rootPersonId);
+ if (is_null($rootPerson))
+ $rootPerson = new WT_Person('');
+
+ if (WT_SCRIPT_NAME == 'individual.php')
+ $path = 'individual.php?pid='.$rootPerson->getXref().'&ged='.$GEDCOM.'&allPartners='.($this->allPartners ? "false" : "true").'#tree';
+ else
+ $path = 'module.php?mod=tree&mod_action=treeview&rootid='.$rootPerson->getXref().'&allPartners='.($this->allPartners ? "false" : "true");
+ $r = '<a name="tv_content"></a><div id="'.$this->name.'_out" dir="ltr" class="tv_out">';
+
+ // Read styles (20 maxi) in a hidden list
+ $sd = WT_MODULES_DIR.'tree/css/styles/';
+ $rs = '<ul id="tvStylesSubmenu">';
+ $cs = '<img src="'.$sd.'default/button.gif" alt="d" onclick="'.$this->name.'Handler.style(\''.$sd.'\', \'default\', this);" title="'.WT_I18N::translate('Style').'" />';
+ $rs .= '<li class="tv_button'.($style == '' || $style=='default' ? ' tvPressed' : '').'">'.$cs.'</li>';
+ $nbStyles = 1;
+ if (@is_dir($sd) && @is_readable($sd) && ($d=@opendir($sd))) {
+ while (($s = readdir($d)) !== false && ($nbStyles < 20)) {
+ if ($s[0] == '.' || $s=='default' || !is_dir($sd.$s))
+ continue;
+ $sHTML = '<img src="'.$sd.$s.'/button.gif" alt="'.$s[0].'" onclick="'.$this->name.'Handler.style(\''.$sd.'\', \''.$s.'\', this);" title="'.WT_I18N::translate('Style').'" />';
+ if ($s == $style) {
+ $cs = $sHTML;
+ $pressedState = ' tvPressed';
+ }
+ else
+ $pressedState ='';
+ $rs .= '<li class="tv_button'.$pressedState.'">'.$sHTML.'</li>';
+ $nbStyles++;
+ }
+ }
+ $rs .= '</ul>';
+
+ // Add the toolbar
+ $r.=
+ '<div id="tv_tools"><ul>'.
+ // TODO: can we change the toolbar's orientation automatically, when it is dragged to a vertical/horizontal edge?
+ '<li id="tvToolsHandler" title="'.WT_I18N::translate('Move the toolbar').'"></li>'.
+ '<li id="tvbZoomIn" class="tv_button"><img src="'.$WT_IMAGES['zoomin'].'" alt="'.WT_I18N::translate('Zoom in').'" title="'.WT_I18N::translate('Zoom in').'" /></li>'.
+ '<li id="tvbZoomOut" class="tv_button"><img src="'.$WT_IMAGES['zoomout'].'" alt="'.WT_I18N::translate('Zoom out').'" title="'.WT_I18N::translate('Zoom out').'" /></li>'.
+ '<li id="tvbNoZoom" class="tv_button"><img src="'.WT_MODULES_DIR.'tree/images/zoom0.png" alt="'.WT_I18N::translate('Reset').'" title="'.WT_I18N::translate('Reset').'" /></li>'.
+ '<li id="tvbLeft" class="tv_button"><img src="'.$WT_IMAGES['ldarrow'].'" alt="'.WT_I18N::translate('Align left').'" title="'.WT_I18N::translate('Align left').'" /></li>'.
+ '<li id="tvbCenter" class="tv_button"><img src="'.$WT_IMAGES['center'].'" alt="'./* I18N: verb/action */ WT_I18N::translate('Center').'" title="'.WT_I18N::translate('Center').'" /></li>'.
+ '<li id="tvbRight" class="tv_button"><img src="'.$WT_IMAGES['rdarrow'].'" alt="'.WT_I18N::translate('Align right').'" title="'.WT_I18N::translate('Align right').'" /></li>'.
+ '<li id="tvbDates" class="tv_button tvPressed"><img src="'.WT_MODULES_DIR.'tree/images/dates.png" alt="'.WT_I18N::translate('Show year of birth and death').'" title="'.WT_I18N::translate('Show year of birth and death').'" /></li>'.
+ '<li id="tvbCompact" class="tv_button"><img src="'.WT_MODULES_DIR.'tree/images/compact.png" alt="'.WT_I18N::translate('Use compact layout').'" title="'.WT_I18N::translate('Use compact layout').'" /></li>'.
+ // TODO: this is temporarily disabled (as it sends a flood of AJAX requests?)
+ //'<li id="tvbOpen" class="tv_button"><img src="'.$WT_IMAGES["media"].'" alt="o" title="'.WT_I18N::translate('Show all details').'" /></li>'.
+ //'<li id="tvbClose" class="tv_button"><img src="'.$WT_IMAGES["fambook"].'" alt="f" title="'.WT_I18N::translate('Hide all details').'" /></li>'.
+ // If the position/order of the style button moves, update TreeViewHandler() in treeview.js
+ '<li id="tvStyleButton" class="tv_button">'.$cs.'</li>'.
+ '<li id="tvbPrint" class="tv_button"><img src="'.WT_MODULES_DIR.'tree/images/print.png" alt="p" title="'./* I18N: verb/action */ WT_I18N::translate('Print').'" /></li>'.
+ '<li class="tv_button'.($this->allPartners ? ' tvPressed' : '').'"><a href="'.$path.'"><img src="'.$WT_IMAGES["sfamily"].'" alt="'.WT_I18N::translate('Show all spouses and ancestors').'" title="'.WT_I18N::translate('Show all spouses and ancestors').'" /></a></li>';
+ if (safe_GET('mod_action') != 'treeview') {
+ $r.='<li class="tv_button"><a href="module.php?mod=tree&mod_action=treeview&rootid='.$rootPerson->getXref().'#tv_content" title="'. /* I18N: Button label - view this chart in full-screen mode */ WT_I18N::translate('Full screen').'"><img src="'.$WT_IMAGES["fscreen"].'" alt="full screen" /></a></li>';
+ }
+ // Help, and hidden loading image
+ $r.='<li class="tv_button">'.help_link("TV_MODULE", 'tree').'</li>
+ <li class="tv_button" id="'.$this->name.'_loading"><img src="images/loading.gif" alt="Loading..." /></li>
+</ul>'.$rs;
+ $r.='</div><div id="'.$this->name.'_in" class="tv_in">';
+ $parent = null;
+ $r.=$this->drawPerson($rootPerson, $generations, 0, $parent, '', true);
+ $r.='</div></div>'; // Close the tv_in and the tv_out div
+ $r.='<script type="text/javascript">var '.$this->name.'Handler = new TreeViewHandler("'.$this->name.'", '.($this->allPartners ? 'true' : 'false').', '.$nbStyles.');</script>';
+ return $r;
+ }
+
+ /**
+ * Return a JSON structure to a JSON request
+ * @param string $list list of JSON requests
+ */
+ public function getPersons($list) {
+ $list = explode(';', $list);
+ $r = array();
+ foreach($list as $jsonRequest) {
+ $firstLetter = substr($jsonRequest, 0, 1);
+ $jsonRequest = substr($jsonRequest, 1);
+ switch($firstLetter) {
+ case 'c':
+ $fidlist = explode(',', $jsonRequest);
+ $flist = array();
+ foreach($fidlist as $fid)
+ $flist[] = WT_Family::getInstance($fid);
+ $r[] = $this->drawChildren($flist, 1, true);
+ break;
+ case 'p':
+ $params = explode('@', $jsonRequest);
+ $fid = $params[0];
+ $order = $params[1];
+ $f = WT_Family::getInstance($fid);
+ $p = $f->getHusband();
+ $r[] = $this->drawPerson($f->getHusband(), 0, 1, $f, $order);
+ break;
+ }
+ }
+ return json_encode($r);
+ }
+
+ /**
+ * Get the details for a person and their life partner(s)
+ * @param string $pid the person id to return the details for
+ */
+ public function getDetails($pid) {
+
+ $person = WT_Person::getInstance($pid);
+
+ $r = $this->getPersonDetails($person, $person, null);
+ foreach ($person->getSpouseFamilies() as $family) {
+ if (!empty($family)) {
+ $partner = $family->getSpouse($person);
+ if (!empty($partner))
+ $r .= $this->getPersonDetails($person, $partner, $family);
+ }
+ }
+ return $r;
+ }
+
+ /**
+ * Get full resolution medias
+ * @param string $medias the list of medias to return
+ */
+ public function getMedias($medias) {
+ $medias = explode(';', $medias);
+ $nb = count($medias);
+ $r = array();
+ for ($i=0; $i<$nb; $i++) {
+ $mid = $medias[$i];
+ $m = WT_Media::getInstance($mid);
+ $r[] = $m->getServerFilename();
+ }
+ return json_encode($r);
+ }
+
+
+ /**
+ * Return the details for a person
+ * @param Person $person the person to return the details for
+ */
+ private function getPersonDetails($personGroup, $person, $family) {
+ global $WT_IMAGES;
+
+ $r = '<div class="tv'.$person->getSex().' tv_person_expanded">';
+ $r .= $this->getThumbnail($personGroup, $person);
+ $r .= '<a class="tv_link" href="'.$person->getHtmlUrl().'">'.$person->getFullName().'</a> <a href="module.php?mod=tree&mod_action=treeview&allPartners='.($this->allPartners ? 'true' : 'false').'&rootid='.$person->getXref().'" title="'.WT_I18N::translate('Interactive tree of %s', htmlspecialchars(strip_tags($person->getFullName()))).'"><img src="'.$WT_IMAGES['tree'].'" class="tv_link tv_treelink" /></a>';
+ $r .= '<br /><b>'.WT_Gedcom_Tag::getAbbreviation('BIRT').'</b> '.$person->getBirthDate()->Display().' '.$person->getBirthPlace();
+ if ($family) {
+ $r .= '<br /><b>'.WT_Gedcom_Tag::getAbbreviation('MARR').'</b> '.$family->getMarriageDate()->Display().' <a href="'.$family->getHtmlUrl().'"><img src="'.$WT_IMAGES['button_family'].'" class="tv_link tv_treelink" title="'.htmlspecialchars(strip_tags($family->getFullName())).'" /></a>'.$family->getMarriagePlace();
+ }
+ if ($person->isDead())
+ $r .= '<br /><b>'.WT_Gedcom_Tag::getAbbreviation('DEAT').'</b> '.$person->getDeathDate()->Display().' '.$person->getDeathPlace();
+ $r.= '</div>';
+ return $r;
+ }
+
+ /**
+ * Draw the children for some families
+ * @param Array $familyList array of families to draw the children for
+ * @param int $gen number of generations to draw
+ * @param boolean $ajax setted to true for an ajax call
+ */
+ private function drawChildren($familyList, $gen=1, $ajax=false) {
+ $r ='';
+ $flWithChildren = array();
+ $f2load = array();
+ $tc = 0;
+ foreach($familyList as $f) {
+ if (empty($f))
+ continue;
+ $nbcf = $f->getNumberOfChildren();
+ if ($nbcf > 0) {
+ $flWithChildren[] = $f;
+ $f2load[] = $f->getXref();
+ $tc += $nbcf;
+ }
+ }
+ if ($tc) {
+ $f2load = implode(',', $f2load);
+ if (!$ajax)
+ $r .= '<td align="right"'.($gen == 0 ? ' abbr="c'.$f2load.'"' : '').'>';
+ $nbc = 0;
+ foreach($flWithChildren as $f) {
+ foreach ($f->getChildren() as $child) {
+ $nbc++;
+ if ($tc == 1)
+ $co = 'c'; // unique
+ elseif ($nbc == 1)
+ $co = 't'; // first
+ elseif($nbc == $tc)
+ $co = 'b'; //last
+ else
+ $co = 'h';
+ $fam = null;
+ $r .= $this->drawPerson($child, $gen-1, -1, $fam, $co);
+ }
+ }
+ if (!$ajax)
+ $r .= '</td>'.$this->drawHorizontalLine();
+ }
+ return $r;
+ }
+
+ /**
+ * Draw a person in the tree
+ * @param Person $person The Person object to draw the box for
+ * @param int $gen The number of generations up or down to print
+ * @param int $state Whether we are going up or down the tree, -1 for descendents +1 for ancestors
+ * @param Family $pfamily
+ * @param string $order first (1), last(2), unique(0), or empty. Required for drawing lines between boxes
+ *
+ * Notes : "spouse" means explicitely married partners. Thus, the word "partner"
+ * (for "life partner") here fits much better than "spouse" or "mate"
+ * to translate properly the modern french meaning of "conjoint"
+ */
+ private function drawPerson($person, $gen, $state=0, $pfamily, $order, $isRoot=false) {
+ global $TEXT_DIRECTION;
+
+ if ($gen < 0 || empty($person))
+ return;
+
+ if (!empty($pfamily))
+ $partner = $pfamily->getSpouse($person);
+ else {
+ $partner = $person->getCurrentSpouse();
+ $fams = $person->getSpouseFamilies();
+ $pfamily = end($fams);
+ }
+
+ if ($isRoot)
+ $r = '<table id="tvTreeBorder" class="tv_tree"><tbody><tr><td id="tv_tree_topleft"></td><td id="tv_tree_top"><div>'.
+ WT_I18N::translate('Interactive tree of %s',$person->getFullName()).
+ '</div></td><td id="tv_tree_topright"></td></tr><tr><td id="tv_tree_left"></td><td>';
+ else $r = '';
+ /* height 1% : this hack enable the div auto-dimensionning in td for FF & Chrome */
+ $r .= '<table class="tv_tree"'.($isRoot ? ' id="tv_tree"' : '').' style="height: 1%"><tbody><tr>';
+
+ if ($state<=0) {
+ // draw children
+ $r.=$this->drawChildren($person->getSpouseFamilies(), $gen);
+ } else {
+ // draw the parent's lines
+ $r .= $this->drawVerticalLine($order).$this->drawHorizontalLine();
+ }
+
+ /* draw the person. Do NOT add person or family id as an id, since a same person could appear more than once in the tree !!! */
+ // Fixing the width for td to the box initial width when the person is the root person fix a rare bug that happen when a person without child and without known parents is the root person : an unwanted white rectangle appear at the right of the person's boxes, otherwise.
+ $r .= '<td'.($isRoot ? ' style="width:1px"' : '').'><div class="tv_box'.($isRoot ? ' rootPerson' : '').'" dir="'.$TEXT_DIRECTION.'" style="text-align: '.($TEXT_DIRECTION=="rtl" ? "right":"left").'; direction: '.$TEXT_DIRECTION.'" abbr="'.$person->getXref().'" onclick="'.$this->name.'Handler.expandBox(this, event);">';
+ $r .= $this->drawPersonName($person);
+ $fop = Array(); // $fop is fathers of partners
+ if (!is_null($partner)) {
+ $sfams = $person->getSpouseFamilies();
+ foreach ($sfams as $famid=>$family) {
+ $p = $family->getSpouse($person);
+ if (!empty($p)) {
+ if (($p->equals($partner)) || $this->allPartners) {
+ $pf = $p->getPrimaryChildFamily();
+ if (!empty($pf))
+ $fop[] = Array($pf->getHusband(), $pf);
+ $r .= $this->drawPersonName($p);
+ if (!$this->allPartners)
+ break; // we can stop here the foreach loop
+ }
+ }
+ }
+ }
+ $r .= '</div></td>';
+
+ $fatherFamily = $person->getPrimaryChildFamily();
+ if (!empty($fatherFamily))
+ $father = $fatherFamily->getHusband();
+ if (!empty($father) || count($fop) || ($state < 0))
+ $r .= $this->drawHorizontalLine();
+
+ /* draw the parents */
+ if ($state >= 0 && (!empty($father) || count($fop))) {
+ $unique = (empty($father) || count($fop) == 0);
+ $r .= '<td align="left"><table class="tv_tree"><tbody>';
+ if (!empty($father)) {
+ $u = ($unique ? 'c' : 't');
+ $r .= '<tr><td '.($gen == 0 ? ' abbr="p'.$fatherFamily->getXref().'@'.$u.'"' : '').'>';
+ $r .= $this->drawPerson($father, $gen-1, 1, $fatherFamily, $u);
+ $r .= '</td></tr>';
+ }
+ if (count($fop)) {
+ $n = 0;
+ $nb = count($fop);
+ foreach($fop as $p) {
+ $n++;
+ $u = ($unique ? 'c' : ($n == $nb || empty($p[1]) || !$this->allPartners ? 'b' : 'h'));
+ $r .= '<tr><td '.($gen == 0 ? ' abbr="p'.$p[1]->getXref().'@'.$u.'"' : '').'>'.$this->drawPerson($p[0], $gen-1, 1, $p[1], $u).'</td></tr>';
+ }
+ }
+ $r .= '</tbody></table></td>';
+ }
+ if ($state < 0) {
+ $r .= $this->drawVerticalLine($order);
+ }
+ $r .= '</tr></tbody></table>';
+ if ($isRoot)
+ $r .= '</td><td id="tv_tree_right"></td></tr><tr><td id="tv_tree_bottomleft"></td><td id="tv_tree_bottom"></td><td id="tv_tree_bottomright"></td></tr></tbody></table>';
+ return $r;
+ }
+
+ /**
+ * Draw a person name preceded by sex icon, with parents as tooltip
+ * @param WT_Person $p a person
+ */
+ private function drawPersonName($p) {
+ if ($this->allPartners) {
+ $f = $p->getPrimaryChildFamily();
+ if ($f) {
+ switch ($p->getSex()) {
+ case 'M':
+ $title=' title="'.htmlspecialchars(strip_tags(/* I18N: e.g. "Son of [father name & mother name]" */ WT_I18N::translate('Son of %s', $f->getFullName()))).'"';
+ break;
+ case 'F':
+ $title=' title="'.htmlspecialchars(strip_tags(/* I18N: e.g. "Daughter of [father name & mother name]" */ WT_I18N::translate('Daughter of %s', $f->getFullName()))).'"';
+ break;
+ case 'U':
+ $title=' title="'.htmlspecialchars(strip_tags(/* I18N: e.g. "Child of [father name & mother name]" */ WT_I18N::translate('Child of %s', $f->getFullName()))).'"';
+ break;
+ }
+ } else {
+ $title='';
+ }
+ }
+ else
+ $title = '';
+ $sex = $p->getSex();
+ switch($sex) {
+ case 'M':
+ $sexSymbol = WT_UTF8_MALE;
+ break;
+ case 'F':
+ $sexSymbol = WT_UTF8_FEMALE;
+ break;
+ default:
+ $sexSymbol = WT_UTF8_NO_SEX;
+ break;
+ }
+ $r = '<div class="tv'.$sex.'"'.$title.'><span class="dates">'.$p->getLifeSpan().'</span><a href="'.$p->getHtmlUrl().'"><span class="tvSexSymbol tv'.$sex.' tv_link">'.$sexSymbol.'</span></a>&nbsp;'.$p->getFullName().'</div>';
+ return $r;
+ }
+
+ /**
+ * Get the thumbnail image for the given person
+ *
+ * @param Person $person
+ * @return string
+ */
+ private function getThumbnail($personGroup, $person) {
+ global $MULTI_MEDIA, $SHOW_HIGHLIGHT_IMAGES;
+
+ $thumbnail="";
+ if ($MULTI_MEDIA && $SHOW_HIGHLIGHT_IMAGES) {
+ $object=$person->findHighlightedMedia();
+ $img_title=PrintReady(htmlspecialchars($person->getFullName()));
+ if (!empty($object)) {
+ $mediaobject=WT_Media::getInstance($object['mid']);
+ $thumbnail=$mediaobject->displayMedia(array('display_type'=>'treeview','img_title'=>$img_title,'clearbox'=>'tvlb'.$personGroup->getXref()));
+ } else {
+ $thumbnail=display_silhouette(array('sex'=>$person->getSex(),'display_type'=>'treeview','img_title'=>$img_title)); // may return ''
+ }
+ }
+
+ return $thumbnail;
+ }
+
+ /**
+ * Draw a vertical line
+ * @param string order $order A parameter that set how to draw this line
+ * with auto-redimensionning capabilities
+ * WARNING : some tricky hacks are required in CSS to ensure cross-browser compliance
+ * some browsers shows an image, which imply a size limit in height,
+ * and some other browsers (ex: firefox) shows a <div> tag, which have no size limit in height
+ * Therefore, Firefox is a good choice to print very big trees.
+ */
+ private function drawVerticalLine($order) {
+ $r = '<td class="tv_vline tv_vline_'.$order.'"><div class="tv_vline tv_vline_'.$order.'"></div></td>';
+ return $r;
+ }
+
+ /**
+ * Draw an horizontal line
+ */
+ private function drawHorizontalLine() {
+ $r = '<td class="tv_hline"><div class="tv_hline"></div></td>';
+ return $r;
+ }
+
+}
+
diff --git a/modules_v3/tree/css/styles/black/black.css b/modules_v3/tree/css/styles/black/black.css
new file mode 100644
index 0000000000..9c47cd57a7
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/black.css
@@ -0,0 +1,121 @@
+.tv_out {
+ background: #000;
+}
+/* Border (also have class table.tv_tree) */
+table#tvTreeBorder td#tv_tree_topleft {
+ background: url(treetopleft.gif);
+}
+table#tvTreeBorder td#tv_tree_top {
+ background: url(treetop.gif) repeat-x;
+}
+table#tvTreeBorder td#tv_tree_topright {
+ background: url(treetopright.gif);
+}
+table#tvTreeBorder td#tv_tree_left {
+ background: url(treeleft.gif) repeat-y;
+}
+table#tvTreeBorder td#tv_tree_right {
+ background: url(treeright.gif) repeat-y;
+}
+table#tvTreeBorder td#tv_tree_bottomleft {
+ background: url(treebottomleft.gif);
+}
+table#tvTreeBorder td#tv_tree_bottom {
+ background: url(treebottom.gif) repeat-x;
+}
+table#tvTreeBorder td#tv_tree_bottomright {
+ background: url(treebottomright.gif);
+}
+table#tvTreeBorder td#tv_tree_top div{
+ font-family: fantasy;
+ font-size: 16px;
+ color: #4fff8f;
+}
+/* tree */
+table#tvTreeBorder td, #tv_tree {
+ background: #000;
+}
+#tv_tree div.tv_box .date{
+ color: #dfdfff;
+}
+#tv_tree div.tv_box div.tvM {
+ background: #000012;
+ color: #efffff;
+}
+#tv_tree div.tv_box div.tvF {
+ background: #120000;
+ color: #ffefef;
+}
+#tv_tree div.tv_box a {
+ color: #4fff8f;
+}
+#tv_tree div.tv_box a:hover {
+ color: #df0000;
+}
+
+/* horizontal and vertical lines color */
+#tv_tree div.tv_vline, #tv_tree div.tv_hline {
+ background-color: #8fdfaf;
+}
+#tv_tree table.tv_tree td.tv_vline_h {
+ background-image: url(vline.jpg);
+}
+#tv_tree table.tv_tree td.tv_vline_t {
+ background-image: url(vline_t.gif);
+}
+#tv_tree table.tv_tree td.tv_vline_b {
+ background-image: url(vline_b.gif);
+}
+/* Person or couple(s) box style */
+#tv_tree div.tv_box {
+ border: thin inset #00ffef;
+ background: #000;
+ border-radius: 2px;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -khtml-border-radius: 2px;
+ box-shadow: 2px 2px 12px #2f8f4f;
+ -webkit-box-shadow: 2px 2px 12px #2f8f4f;
+ -moz-box-shadow: 2px 2px 12px #2f8f4f;
+ -khtml-box-shadow: 2px 2px 12px #2f8f4f;
+ filter: progid:DXImageTransform.Microsoft.dropShadow(color=#2f8f4f, offX=2, offY=2, positive=true);
+}
+#tv_tree div.tv_box span.tvM {
+ color: #00ffff;
+}
+#tv_tree div.tv_box span.tvF {
+ color: #ffef00;
+}
+/* The toolbox style. Button's images come from the active theme */
+#tv_tools, #tvStylesSubmenu {
+ background-color: #00af8f;
+ border: 1px outset #004f8f;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ -khtml-border-radius: 4px;
+ border-radius: 4px;
+ box-shadow: 2px 2px 12px #2f8f4f;
+ -moz-box-shadow: 2px 2px 12px #2f8f4f;
+ -webkit-box-shadow: 2px 2px 12px #2f8f4f;
+ -khtml-box-shadow: 2px 2px 12px #2f8f4f;
+ filter: progid:DXImageTransform.Microsoft.dropShadow(color=#2f8f4f, offX=2, offY=2, positive=true);
+}
+#tv_tools li.tv_button {
+ border: thin solid #00af8f;
+ background-color: #00af8f;
+}
+#tv_tools li.tv_button:hover {
+ background: #8fefaf;
+ border: thin outset #00fffd;
+}
+#tv_tools li.tvPressed {
+ border: thin inset #008888;
+}
+#tvToolsHandler {
+ border: thin inset #004f8f;
+}
+
+#tvToolsHandler:hover {
+ border: thin outset #004f8f;
+ background-color: #00ffaf;
+} \ No newline at end of file
diff --git a/modules_v3/tree/css/styles/black/button.gif b/modules_v3/tree/css/styles/black/button.gif
new file mode 100644
index 0000000000..9470561a4c
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/button.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treebottom.gif b/modules_v3/tree/css/styles/black/treebottom.gif
new file mode 100644
index 0000000000..7e0b81e1cd
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treebottom.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treebottomleft.gif b/modules_v3/tree/css/styles/black/treebottomleft.gif
new file mode 100644
index 0000000000..0a4500c582
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treebottomleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treebottomright.gif b/modules_v3/tree/css/styles/black/treebottomright.gif
new file mode 100644
index 0000000000..bd5fdfa35c
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treebottomright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treeleft.gif b/modules_v3/tree/css/styles/black/treeleft.gif
new file mode 100644
index 0000000000..c79f398007
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treeleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treeright.gif b/modules_v3/tree/css/styles/black/treeright.gif
new file mode 100644
index 0000000000..b1fb162550
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treeright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treetop.gif b/modules_v3/tree/css/styles/black/treetop.gif
new file mode 100644
index 0000000000..d08813ba7b
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treetop.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treetopleft.gif b/modules_v3/tree/css/styles/black/treetopleft.gif
new file mode 100644
index 0000000000..077ee16885
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treetopleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/treetopright.gif b/modules_v3/tree/css/styles/black/treetopright.gif
new file mode 100644
index 0000000000..1b7ad6d3c2
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/treetopright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/vline.jpg b/modules_v3/tree/css/styles/black/vline.jpg
new file mode 100644
index 0000000000..0d04b39433
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/vline.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/vline_b.gif b/modules_v3/tree/css/styles/black/vline_b.gif
new file mode 100644
index 0000000000..f4a8cab167
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/vline_b.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/black/vline_t.gif b/modules_v3/tree/css/styles/black/vline_t.gif
new file mode 100644
index 0000000000..bfd7160ad0
--- /dev/null
+++ b/modules_v3/tree/css/styles/black/vline_t.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/default/button.gif b/modules_v3/tree/css/styles/default/button.gif
new file mode 100644
index 0000000000..2ea4932a0a
--- /dev/null
+++ b/modules_v3/tree/css/styles/default/button.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/default/default.css b/modules_v3/tree/css/styles/default/default.css
new file mode 100644
index 0000000000..12da27556c
--- /dev/null
+++ b/modules_v3/tree/css/styles/default/default.css
@@ -0,0 +1,61 @@
+/* Border (also have class table.tv_tree) */
+table#tvTreeBorder td#tv_tree_topleft {
+ background: none;
+}
+table#tvTreeBorder td#tv_tree_top {
+ background: none;
+}
+table#tvTreeBorder td#tv_tree_top div{
+ font-family: Arial, Verdana, sans-serif;
+ font-size: 18px;
+}
+table#tvTreeBorder td#tv_tree_topright {
+ background: none;
+}
+table#tvTreeBorder td#tv_tree_left {
+ background: none;
+}
+table#tvTreeBorder td#tv_tree_right {
+ background: none;
+}
+table#tvTreeBorder td#tv_tree_bottomleft {
+ background: none;
+}
+table#tvTreeBorder td#tv_tree_bottom {
+ background: none;
+}
+table#tvTreeBorder td#tv_tree_bottomright {
+ background: none;
+}
+/* tree */
+table#tvTreeBorder td, #tv_tree {
+ background: none;
+}
+#tv_tree div.tv_box div.tvM, #tv_tree div.tv_box div.tvF {
+ background: none;
+ color: #000;
+}
+/* horizontal and vertical lines color */
+#tv_tree div.tv_vline, #tv_tree div.tv_hline {
+ background-color: #999;
+}
+#tv_tree table.tv_tree td.tv_vline_h {
+ background-image: url(vline.jpg);
+}
+#tv_tree table.tv_tree td.tv_vline_t {
+ background-image: url(vline_t.gif);
+}
+#tv_tree table.tv_tree td.tv_vline_b {
+ background-image: url(vline_b.gif);
+}
+/* Person or couple(s) box style */
+#tv_tree div.tv_box {
+ border: thin outset #000;
+}
+#tv_tree div.tv_box div.tvM, #tv_tree .tv_box div.tvF {
+ border: 0;
+ margin: 0;
+ padding: 0;
+ padding-left: 4px;
+ padding-right: 4px;
+} \ No newline at end of file
diff --git a/modules_v3/tree/css/styles/default/vline.jpg b/modules_v3/tree/css/styles/default/vline.jpg
new file mode 100644
index 0000000000..0bc05d5fac
--- /dev/null
+++ b/modules_v3/tree/css/styles/default/vline.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/default/vline_b.gif b/modules_v3/tree/css/styles/default/vline_b.gif
new file mode 100644
index 0000000000..78d660d161
--- /dev/null
+++ b/modules_v3/tree/css/styles/default/vline_b.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/default/vline_t.gif b/modules_v3/tree/css/styles/default/vline_t.gif
new file mode 100644
index 0000000000..de4f11226e
--- /dev/null
+++ b/modules_v3/tree/css/styles/default/vline_t.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/button.gif b/modules_v3/tree/css/styles/parchemin_gris/button.gif
new file mode 100644
index 0000000000..a9b8543bf0
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/button.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/parchemin_gris.css b/modules_v3/tree/css/styles/parchemin_gris/parchemin_gris.css
new file mode 100644
index 0000000000..b454df32a6
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/parchemin_gris.css
@@ -0,0 +1,37 @@
+/* Border (also have class table.tv_tree) */
+table#tvTreeBorder td#tv_tree_topleft {
+ background: url(treetopleft.gif);
+}
+table#tvTreeBorder td#tv_tree_top {
+ background: url(treetop.gif) repeat-x;
+}
+table#tvTreeBorder td#tv_tree_topright {
+ background: url(treetopright.gif);
+}
+table#tvTreeBorder td#tv_tree_left {
+ background: url(treeleft.gif) repeat-y;
+}
+table#tvTreeBorder td#tv_tree_right {
+ background: url(treeright.gif) repeat-y;
+}
+table#tvTreeBorder td#tv_tree_bottomleft {
+ background: url(treebottomleft.gif);
+}
+table#tvTreeBorder td#tv_tree_bottom {
+ background: url(treebottom.gif) repeat-x;
+}
+table#tvTreeBorder td#tv_tree_bottomright {
+ background: url(treebottomright.gif);
+}
+table#tvTreeBorder td#tv_tree_top div{
+ font-family: Comic Sans MS, cursive;
+ font-size: 18px;
+}
+
+/* tree */
+#tv_tree {
+ background: url(tree.jpg);
+}
+#tv_tree div.tv_box div.tvM, #tv_tree div.tv_box div.tvF {
+ font-family: Comic Sans MS, cursive;
+} \ No newline at end of file
diff --git a/modules_v3/tree/css/styles/parchemin_gris/tree.jpg b/modules_v3/tree/css/styles/parchemin_gris/tree.jpg
new file mode 100644
index 0000000000..a313c0ac32
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/tree.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treebottom.gif b/modules_v3/tree/css/styles/parchemin_gris/treebottom.gif
new file mode 100644
index 0000000000..44fd1c0974
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treebottom.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treebottomleft.gif b/modules_v3/tree/css/styles/parchemin_gris/treebottomleft.gif
new file mode 100644
index 0000000000..a707bd5ca6
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treebottomleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treebottomright.gif b/modules_v3/tree/css/styles/parchemin_gris/treebottomright.gif
new file mode 100644
index 0000000000..52e747cf79
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treebottomright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treeleft.gif b/modules_v3/tree/css/styles/parchemin_gris/treeleft.gif
new file mode 100644
index 0000000000..699aed79fe
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treeleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treeright.gif b/modules_v3/tree/css/styles/parchemin_gris/treeright.gif
new file mode 100644
index 0000000000..ed032ce0d2
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treeright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treetop.gif b/modules_v3/tree/css/styles/parchemin_gris/treetop.gif
new file mode 100644
index 0000000000..d9f0c14c64
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treetop.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treetopleft.gif b/modules_v3/tree/css/styles/parchemin_gris/treetopleft.gif
new file mode 100644
index 0000000000..7e9d5cb1aa
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treetopleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_gris/treetopright.gif b/modules_v3/tree/css/styles/parchemin_gris/treetopright.gif
new file mode 100644
index 0000000000..205a0b9bb9
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_gris/treetopright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/button.gif b/modules_v3/tree/css/styles/parchemin_jauni/button.gif
new file mode 100644
index 0000000000..f2c40a1f15
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/button.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/papier.jpg b/modules_v3/tree/css/styles/parchemin_jauni/papier.jpg
new file mode 100644
index 0000000000..5d17a79758
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/papier.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/parchemin_jauni.css b/modules_v3/tree/css/styles/parchemin_jauni/parchemin_jauni.css
new file mode 100644
index 0000000000..0a1afa9a03
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/parchemin_jauni.css
@@ -0,0 +1,69 @@
+/* Border (also have class table.tv_tree) */
+table#tvTreeBorder td#tv_tree_topleft {
+ background: url(treetopleft.gif);
+}
+table#tvTreeBorder td#tv_tree_top {
+ background: url(treetop.gif) repeat-x;
+}
+table#tvTreeBorder td#tv_tree_top div{
+ font-family: Times new Roman, Times, serif;
+ font-size: 18px;
+}
+table#tvTreeBorder td#tv_tree_topright {
+ background: url(treetopright.gif);
+}
+table#tvTreeBorder td#tv_tree_left {
+ background: url(treeleft.gif) repeat-y;
+}
+table#tvTreeBorder td#tv_tree_right {
+ background: url(treeright.gif) repeat-y;
+}
+table#tvTreeBorder td#tv_tree_bottomleft {
+ background: url(treebottomleft.gif);
+}
+table#tvTreeBorder td#tv_tree_bottom {
+ background: url(treebottom.gif) repeat-x;
+}
+table#tvTreeBorder td#tv_tree_bottomright {
+ background: url(treebottomright.gif);
+}
+/* tree */
+#tv_tree {
+ background: url(tree.jpg);
+}
+/* Person or couple(s) box style */
+#tv_tree div.tv_box {
+ border: thin outset #6f2f00;
+ border-radius: 8px;
+ -moz-border-radius: 8px;
+ -webkit-border-radius: 8px;
+ -khtml-border-radius: 8px;
+ box-shadow: 1px 1px 2px #cfcf8f;
+ -webkit-box-shadow: 1px 1px 2px #cfcf8f;
+ -moz-box-shadow: 1px 1px 2px #cfcf8f;
+ -khtml-box-shadow: 1px 1px 2px #dfdcfcf8ff00;
+ filter: progid:DXImageTransform.Microsoft.dropShadow(color=#cfcf8f, offX=1, offY=1, positive=true);
+}
+#tv_tree div.tv_box div.tvM, #tv_tree div.tv_box div.tvF {
+ font-family: Times new Roman, Times, serif;
+ font-size: 120%;
+ border-radius: 8px;
+ -moz-border-radius: 8px;
+ -webkit-border-radius: 8px;
+ -khtml-border-radius: 8px;
+ background: url(papier.jpg);
+ color: #180000;
+}
+/* horizontal and vertical lines color */
+#tv_tree div.tv_vline, #tv_tree div.tv_hline {
+ background-color: #002f6f;
+}
+#tv_tree table.tv_tree td.tv_vline_h {
+ background-image: url(vline.jpg);
+}
+#tv_tree table.tv_tree td.tv_vline_t {
+ background-image: url(vline_t.gif);
+}
+#tv_tree table.tv_tree td.tv_vline_b {
+ background-image: url(vline_b.gif);
+} \ No newline at end of file
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/tree.jpg b/modules_v3/tree/css/styles/parchemin_jauni/tree.jpg
new file mode 100644
index 0000000000..65a11c6741
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/tree.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treebottom.gif b/modules_v3/tree/css/styles/parchemin_jauni/treebottom.gif
new file mode 100644
index 0000000000..7b50105084
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treebottom.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treebottomleft.gif b/modules_v3/tree/css/styles/parchemin_jauni/treebottomleft.gif
new file mode 100644
index 0000000000..dd695bc371
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treebottomleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treebottomright.gif b/modules_v3/tree/css/styles/parchemin_jauni/treebottomright.gif
new file mode 100644
index 0000000000..5b55be458f
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treebottomright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treeleft.gif b/modules_v3/tree/css/styles/parchemin_jauni/treeleft.gif
new file mode 100644
index 0000000000..1a3e3b205a
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treeleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treeright.gif b/modules_v3/tree/css/styles/parchemin_jauni/treeright.gif
new file mode 100644
index 0000000000..5af2d0f7dd
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treeright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treetop.gif b/modules_v3/tree/css/styles/parchemin_jauni/treetop.gif
new file mode 100644
index 0000000000..5a268d1b09
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treetop.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treetopleft.gif b/modules_v3/tree/css/styles/parchemin_jauni/treetopleft.gif
new file mode 100644
index 0000000000..70616f7b0e
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treetopleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/treetopright.gif b/modules_v3/tree/css/styles/parchemin_jauni/treetopright.gif
new file mode 100644
index 0000000000..e210b81557
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/treetopright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/vline.jpg b/modules_v3/tree/css/styles/parchemin_jauni/vline.jpg
new file mode 100644
index 0000000000..bb3d1ff5a2
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/vline.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/vline_b.gif b/modules_v3/tree/css/styles/parchemin_jauni/vline_b.gif
new file mode 100644
index 0000000000..7fc46853cb
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/vline_b.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/parchemin_jauni/vline_t.gif b/modules_v3/tree/css/styles/parchemin_jauni/vline_t.gif
new file mode 100644
index 0000000000..3d53d0bf2c
--- /dev/null
+++ b/modules_v3/tree/css/styles/parchemin_jauni/vline_t.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/button.gif b/modules_v3/tree/css/styles/simple/button.gif
new file mode 100644
index 0000000000..88bf6b9690
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/button.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/tree.jpg b/modules_v3/tree/css/styles/simple/tree.jpg
new file mode 100644
index 0000000000..f9dc4568fe
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/tree.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treebottom.gif b/modules_v3/tree/css/styles/simple/treebottom.gif
new file mode 100644
index 0000000000..45cbf21e31
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treebottom.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treebottomleft.gif b/modules_v3/tree/css/styles/simple/treebottomleft.gif
new file mode 100644
index 0000000000..28ab0e3b18
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treebottomleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treebottomright.gif b/modules_v3/tree/css/styles/simple/treebottomright.gif
new file mode 100644
index 0000000000..854ad30506
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treebottomright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treeleft.gif b/modules_v3/tree/css/styles/simple/treeleft.gif
new file mode 100644
index 0000000000..4254f50bec
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treeleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treeright.gif b/modules_v3/tree/css/styles/simple/treeright.gif
new file mode 100644
index 0000000000..8fea9e674e
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treeright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treetop.gif b/modules_v3/tree/css/styles/simple/treetop.gif
new file mode 100644
index 0000000000..980a027b88
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treetop.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treetopleft.gif b/modules_v3/tree/css/styles/simple/treetopleft.gif
new file mode 100644
index 0000000000..b3666ec05f
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treetopleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/treetopright.gif b/modules_v3/tree/css/styles/simple/treetopright.gif
new file mode 100644
index 0000000000..c410879184
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/treetopright.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/vline.jpg b/modules_v3/tree/css/styles/simple/vline.jpg
new file mode 100644
index 0000000000..4138974ee0
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/vline.jpg
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/vline_b.gif b/modules_v3/tree/css/styles/simple/vline_b.gif
new file mode 100644
index 0000000000..c29c4106d7
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/vline_b.gif
Binary files differ
diff --git a/modules_v3/tree/css/styles/simple/vline_t.gif b/modules_v3/tree/css/styles/simple/vline_t.gif
new file mode 100644
index 0000000000..f37cf7d9f5
--- /dev/null
+++ b/modules_v3/tree/css/styles/simple/vline_t.gif
Binary files differ
diff --git a/modules_v3/tree/css/tree.jpg b/modules_v3/tree/css/tree.jpg
new file mode 100644
index 0000000000..f9dc4568fe
--- /dev/null
+++ b/modules_v3/tree/css/tree.jpg
Binary files differ
diff --git a/modules_v3/tree/css/treebottom.gif b/modules_v3/tree/css/treebottom.gif
new file mode 100644
index 0000000000..45cbf21e31
--- /dev/null
+++ b/modules_v3/tree/css/treebottom.gif
Binary files differ
diff --git a/modules_v3/tree/css/treebottomleft.gif b/modules_v3/tree/css/treebottomleft.gif
new file mode 100644
index 0000000000..28ab0e3b18
--- /dev/null
+++ b/modules_v3/tree/css/treebottomleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/treebottomright.gif b/modules_v3/tree/css/treebottomright.gif
new file mode 100644
index 0000000000..854ad30506
--- /dev/null
+++ b/modules_v3/tree/css/treebottomright.gif
Binary files differ
diff --git a/modules_v3/tree/css/treeleft.gif b/modules_v3/tree/css/treeleft.gif
new file mode 100644
index 0000000000..4254f50bec
--- /dev/null
+++ b/modules_v3/tree/css/treeleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/treeright.gif b/modules_v3/tree/css/treeright.gif
new file mode 100644
index 0000000000..8fea9e674e
--- /dev/null
+++ b/modules_v3/tree/css/treeright.gif
Binary files differ
diff --git a/modules_v3/tree/css/treetop.gif b/modules_v3/tree/css/treetop.gif
new file mode 100644
index 0000000000..980a027b88
--- /dev/null
+++ b/modules_v3/tree/css/treetop.gif
Binary files differ
diff --git a/modules_v3/tree/css/treetopleft.gif b/modules_v3/tree/css/treetopleft.gif
new file mode 100644
index 0000000000..b3666ec05f
--- /dev/null
+++ b/modules_v3/tree/css/treetopleft.gif
Binary files differ
diff --git a/modules_v3/tree/css/treetopright.gif b/modules_v3/tree/css/treetopright.gif
new file mode 100644
index 0000000000..c410879184
--- /dev/null
+++ b/modules_v3/tree/css/treetopright.gif
Binary files differ
diff --git a/modules_v3/tree/css/treeview.css b/modules_v3/tree/css/treeview.css
new file mode 100644
index 0000000000..14cbb8bb16
--- /dev/null
+++ b/modules_v3/tree/css/treeview.css
@@ -0,0 +1,335 @@
+/** CSS for TreeView module - Daniel Faivre, 2011
+ *
+ * WARNING : DO NOT edit this file !!! To create a theme for the treeview module,
+ * just add in your theme's CSS file the properties you want to customize according to your theme
+ * All the properties that can be styled in your own theme are followed with the comment "customizable"
+ * CSS classes should allways be declared under their container to avoid unwanted side effects and speed-up CSS drawing.
+ *
+ * DO NOT change ANYTHING else : changing others parameters without extreme caution AND complete cross-browser validation DESTROY the tree design !!!
+ *
+ * Treeview styles: this module can print pretty big trees and offer different styles for the tree itself, for screen, printing, or both.
+ * Look at the embedded samples in the /treeview/css/styles directory to learn how to make your own tree styles.
+ */
+
+.tv_out {
+ position: relative;
+ overflow: hidden;
+ height: 100%;
+ width: 100%;
+ border: thin solid #dfdfdf; /* customizable */
+ min-height: 500px; /* customizable, not mandatory, but should be set to have allways something to display */
+ max-height: 10000px; /* customizable, not mandatory, but should be set not too high to limit the size of ajax requests and not too low to enable whole big trees printing */
+ /* background: #fffff8; /* customizable */
+}
+.tv_out img {
+ border: 0;
+}
+
+.tv_in {
+ clear: both;
+ position: relative; /* required for re-calculating size on ajax updates */
+ left: 0;
+ top: 0;
+ cursor: move;
+ display: inline-block; /* prevent from blinking on IE */
+}
+.tv_in table.tv_tree, .tv_in table.tv_tree tbody, .tv_in table.tv_tree tr, .tv_in table.tv_tree td {
+ border: 0 none;
+ padding: 0;
+ margin: 0;
+ background: none;
+}
+.tv_in table.tv_tree {
+ border-collapse: collapse;
+}
+
+/* Border (also need, and have, class table.tv_tree) */
+table#tvTreeBorder td#tv_tree_topleft {
+ height: 50px;
+ width: 50px;
+ background: url(treetopleft.gif); /* customizable */
+}
+table#tvTreeBorder td#tv_tree_top {
+ height: 50px;
+ text-align: center;
+ vertical-align: bottom;
+ background: url(treetop.gif) repeat-x; /* customizable */
+}
+table#tvTreeBorder td#tv_tree_top div{
+ font-family: Garamond, Times, serif; /* customizable */
+ font-size: 16px; /* customizable */
+}
+table#tvTreeBorder td#tv_tree_topright {
+ height: 50px;
+ width: 50px;
+ background: url(treetopright.gif); /* customizable */
+}
+table#tvTreeBorder td#tv_tree_left {
+ width: 50px;
+ min-width: 50px;
+ background: url(treeleft.gif) repeat-y; /* customizable */
+}
+table#tvTreeBorder td#tv_tree_right {
+ width: 50px;
+ min-width: 50px;
+ background: url(treeright.gif) repeat-y; /* customizable */
+}
+table#tvTreeBorder td#tv_tree_bottomleft {
+ height: 50px;
+ width: 50px;
+ background: url(treebottomleft.gif); /* customizable */
+}
+table#tvTreeBorder td#tv_tree_bottom {
+ height: 50px;
+ background: url(treebottom.gif) repeat-x; /* customizable */
+}
+table#tvTreeBorder td#tv_tree_bottomright {
+ height: 50px;
+ width: 50px;
+ background: url(treebottomright.gif); /* customizable */
+}
+
+/* tree */
+#tv_tree {
+ background: url(tree.jpg); /* customizable */
+}
+/* horizontal and vertical lines color */
+#tv_tree div.tv_vline, #tv_tree div.tv_hline {
+ background-color: #81A9CB; /* customizable : should be the same color than in background images of td.tv_vline_x */
+}
+
+/* TD container for a vertical line */
+#tv_tree table.tv_tree td.tv_vline {
+ width: 1px;
+ background-repeat: repeat-x;
+ background-position: 50% 50%;
+ height: 100%; /* required */
+}
+#tv_tree table.tv_tree td.tv_vline_h {
+ background-image: url(vline.jpg); /* customizable : image color must be the same color than div.tv_vline and div.tv_hline */
+}
+#tv_tree table.tv_tree td.tv_vline_t {
+ vertical-align: bottom;
+ background-image: url(vline_t.gif); /* customizable : image color must be the same color than div.tv_vline and div.tv_hline */
+}
+#tv_tree table.tv_tree td.tv_vline_b {
+ vertical-align: top;
+ background-image: url(vline_b.gif); /* customizable : image color must be the same color than div.tv_vline and div.tv_hline */
+}
+#tv_tree table.tv_tree td.tv_vline_c, .tv_in table.tv_tree td.tv_vline_h {
+ vertical-align: middle;
+}
+#tv_tree table.tv_tree td.tv_vline_c {
+ height: 1px;
+}
+/* vertical line drawing */
+#tv_tree table.tv_tree div.tv_vline {
+ width: 1px;
+}
+#tv_tree table.tv_tree div.tv_vline_t, #tv_tree table.tv_tree div.tv_vline_b {
+ height: 50%;
+}
+#tv_tree table.tv_tree div.tv_vline_c {
+ height: 1px;
+ overflow: hidden; /* required for IE */
+}
+#tv_tree table.tv_tree div.tv_vline_h {
+ height: 100%;
+}
+
+/* horizontal line drawing */
+#tv_tree td.tv_hline, #tv_tree div.tv_hline {
+ overflow: hidden; /* required for IE */
+ width: 8px; /* customizable */
+}
+#tv_tree div.tv_hline {
+ height: 1px;
+}
+
+/* Person or couple(s) box style */
+#tv_tree div.tv_box {
+ border: thin outset #81A9CB; /* customizable */
+ background: #fffdfd; /* customizable */
+ margin-top: 2px;
+ margin-bottom: 2px;
+ padding: 0;
+ width: 180px; /* customizable: initial box width */
+ cursor: help; /* customizable */
+ border-collapse: collapse; /* required */
+ border-radius: 4px; /* customizable */
+ -moz-border-radius: 4px; /* customizable */
+ -webkit-border-radius: 4px; /* customizable */
+ -khtml-border-radius: 4px; /* customizable */
+ box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ -webkit-box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ -moz-box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ -khtml-box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ filter: progid:DXImageTransform.Microsoft.dropShadow(color=#cfcfdf, offX=1, offY=1, positive=true); /* customizable */
+}
+#tv_tree div.boxExpanded {
+ width: 250px; /* customizable: initial expanded box width */
+}
+#tv_tree div.tv_box div.tvM {
+ background: #f5fdff; /* customizable */
+ color: #220000; /* customizable */
+}
+#tv_tree div.tv_box div.tvF {
+ background: #fff8f5; /* customizable */
+ color: #000022; /* customizable */
+}
+#tv_tree div.tv_box span.tvSexSymbol {
+ font-weight: bold;
+ font-family: x-large, serif; /*Arial Unicode MS, monospace; /* customizable, BUT test required for ALL browsers */
+ vertical-align: top;
+ margin: 1px;
+}
+#tv_tree div.tv_box span.tvM {
+ color: #8f8fdf; /* customizable */
+}
+#tv_tree div.tv_box span.tvF {
+ color: #df8f8f; /* customizable */
+}
+
+#tv_tree div.tv_box div.tvM, #tv_tree .tv_box div.tvF {
+ border: 0;
+ margin: 0;
+ padding: 1px;
+ padding-left: 4px;
+ padding-right: 4px;
+ border-radius: 4px; /* customizable */
+ -moz-border-radius: 4px; /* customizable */
+ -webkit-border-radius: 4px; /* customizable */
+ -khtml-border-radius: 4px; /* customizable */
+}
+#tv_tree div.tv_box i.dates {
+ float: right;
+ font-size: 75%;
+ margin-left: 4px;
+}
+#tv_tree div.tv_box img.tv_treelink {
+ height: 15px;
+ width: 15px;
+ float: right;
+}
+#tv_tree div.tv_box img.tv_box_loading {
+ height: 12px;
+ width: 12px;
+ margin: 2px;
+ float: right;
+}
+#tv_tree div.tv_box div.tv_person_expanded {
+ min-height: 50px;
+ padding: 2px;
+}
+#tv_tree div.tv_box img.pedigree_image_portrait, #tv_tree div.tv_box img.pedigree_image_landscape {
+ max-width: 50px;
+ _width: 50px; /* hack for IE versions that do not understand max-width */
+ max-height: 50px;
+ margin: 2px;
+}
+#tv_tree div.tv_box div.tv_person_expanded a {
+ font-weight: bold;
+}
+
+/* The toolbox style. Button's images come from the active theme */
+#tv_tools, #tvStylesSubmenu {
+ display: inline-block;
+ position: absolute;
+ left: 0;
+ top: 0;
+ padding: 0;
+ margin: 0; /* required */
+ z-index: 90; /* should be < 100 because 100 is the z-index of WT menus */
+ background-color: #efefef; /* customizable */
+ border: 1px outset #dfdfdf; /* customizable */
+ -moz-border-radius: 4px; /* customizable */
+ -webkit-border-radius: 4px; /* customizable */
+ -khtml-border-radius: 4px; /* customizable */
+ border-radius: 4px; /* customizable */
+ box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ -webkit-box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ -moz-box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ -khtml-box-shadow: 1px 1px 2px #cfcfdf; /* customizable */
+ filter: progid:DXImageTransform.Microsoft.dropShadow(color=#cfcfdf, offX=1, offY=1, positive=true); /* customizable */
+}
+
+/* styles submenu */
+#tvStylesSubmenu {
+ display: none;
+ left: 0;
+ top: 0;
+ z-index: 91; /* just over tv_tools */
+}
+
+#tv_tools ul {
+ list-style: none;
+ margin: 0;
+ padding: 0; /* required */
+}
+#tv_tools li.tv_button {
+ float: left;
+ position: relative;
+ padding: 0; /* required */
+ margin: 0;
+ width: 24px;
+ height: 24px;
+ text-align: center;
+ vertical-align: middle;
+ border: thin solid #efefef; /* customizable */
+ background-color: #efefef; /* customizable */
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ -khtml-border-radius: 4px;
+ border-radius: 4px;
+}
+#tvStylesSubmenu li.tv_button {
+ float : none;
+}
+#tv_tools li.tv_button a {
+ margin: 0;
+ display: block;
+}
+#tv_tools li.tv_button:hover {
+ background: #fffdfd; /* customizable */
+ border: thin outset #fdfffd; /* customizable */
+ cursor: pointer;
+}
+.tv_button a:hover, a:active {
+ background: #fffdfd; /* customizable */
+}
+#tv_tools li.tvPressed {
+ border: thin inset #ffffff; /* customizable */
+}
+#tv_tools ul li img {
+ border: none;
+ margin: 0;
+ padding: 0;
+ max-width: 22px;
+ max-height: 22px;
+ _width: 22px; /* hack for ie */
+ _height: 22px; /* hack for ie */
+ cursor: pointer;
+ text-align: center;
+ vertical-align: middle;
+}
+#tv_tools ul li a.help img.icon {
+ margin: 0;
+ margin-top: 3px;
+ padding: 0;
+ width: 15px;
+ height: 15px;
+}
+
+#tvToolsHandler {
+ float: left;
+ cursor: move;
+ height: 22px;
+ width: 2px;
+ border: thin inset #f6f6f6; /* customizable */
+ margin: 2px;
+ overflow: hidden; /* required for IE */
+}
+
+#tvToolsHandler:hover {
+ border: thin outset #f6f6f6; /* customizable */
+}
diff --git a/modules_v3/tree/css/treeview_print.css b/modules_v3/tree/css/treeview_print.css
new file mode 100644
index 0000000000..3723ce6732
--- /dev/null
+++ b/modules_v3/tree/css/treeview_print.css
@@ -0,0 +1,17 @@
+/**
+ * This file is a printing CSS for the TreeView module
+ *
+ * dF 2011
+ */
+
+#header, #tv_tools, #tv_tree div.tv_box img.tv_treelink, #tv_tree .default_thumbnail {
+ display : none;
+}
+
+.tv_out {
+ top: 0;
+ left: 0;
+ border: 0 none;
+ overflow: visible; /* avoid cutting big trees by this html element */
+ background: none;
+} \ No newline at end of file
diff --git a/modules_v3/tree/css/vline.jpg b/modules_v3/tree/css/vline.jpg
new file mode 100644
index 0000000000..4138974ee0
--- /dev/null
+++ b/modules_v3/tree/css/vline.jpg
Binary files differ
diff --git a/modules_v3/tree/css/vline_b.gif b/modules_v3/tree/css/vline_b.gif
new file mode 100644
index 0000000000..c29c4106d7
--- /dev/null
+++ b/modules_v3/tree/css/vline_b.gif
Binary files differ
diff --git a/modules_v3/tree/css/vline_t.gif b/modules_v3/tree/css/vline_t.gif
new file mode 100644
index 0000000000..f37cf7d9f5
--- /dev/null
+++ b/modules_v3/tree/css/vline_t.gif
Binary files differ
diff --git a/modules_v3/tree/help_text.php b/modules_v3/tree/help_text.php
new file mode 100644
index 0000000000..c340b17be8
--- /dev/null
+++ b/modules_v3/tree/help_text.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * TreeView Module help text.
+ *
+ * This file is included from the application help_text.php script.
+ * It simply needs to set $title and $text for the help topic $help_topic
+ *
+ * webtrees: Web based Family History software
+ * Copyright (C) 2011 Daniel Faivre
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * @version $Id$
+ */
+
+if (!defined('WT_WEBTREES')) {
+ header('HTTP/1.0 403 Forbidden');
+ exit;
+}
+
+$imgStyle = ' style="height: 22px; width: 22px; border: 0 none"';
+switch ($help) {
+ /* This help text need updating before it can be used. Too much embedded formatting, untranslated alt-text (do we need images here?), irrelevant mention of printing details (does a "printer" icon need help?), does "zoom in/out" really need help?
+case 'TV_MODULE':
+ $title = WT_I18N::translate('Interactive tree');
+ $text = WT_I18N::translate('An interactive tree showing all the ancestors and descendants of a person.').
+ '<br /><br />'.
+ WT_I18N::translate('Commands').':'.'<br /><table><tbody>'.
+ '<tr><td><img src="'.$WT_IMAGES['zoomin'].'"'.$imgStyle.' alt="zoomin" /></td><td>'.
+ WT_I18N::translate('Zoom in : enlarge texts and person\'s boxes.').'</td></tr>'.
+ '<tr><td><img src="'.$WT_IMAGES['zoomout'].'"'.$imgStyle.' alt="zoomout" /></td><td>'.
+ WT_I18N::translate('Zoom out : reduce texts and person\'s boxes.').'</td></tr>'.
+ '<tr><td><img src="'.WT_MODULES_DIR.'/tree/images/zoom0.png"'.$imgStyle.' alt="nozoom" /></td><td>'.
+ WT_I18N::translate('No zoom.').'</td></tr>'.
+ '<tr><td><img src="'.$WT_IMAGES['ldarrow'].'"'.$imgStyle.'alt="alignLeft" /></td><td>'.
+ WT_I18N::translate('Align on top left corner. Useful before printing.').'</td></tr>'.
+ '<tr><td><img src="'.$WT_IMAGES['patriarch'].'"'.$imgStyle.' alt="center" /></td><td>'.
+ WT_I18N::translate('Center on the root person.').'</td></tr>'.
+ '<tr><td><img src="'.$WT_IMAGES['rdarrow'].'"'.$imgStyle.' alt="alignRight" /></td><td>'.
+ WT_I18N::translate('Align on top right corner.').'</td></tr>'.
+ '<tr><td><img src="'.WT_MODULES_DIR.'/tree/images/dates.png"'.$imgStyle.' alt="hide dates" /></td><td>'.
+ WT_I18N::translate('Hide/show dates on small boxes.').'</td></tr>'.
+ '<tr><td><img src="'.WT_MODULES_DIR.'/tree/images/compact.png"'.$imgStyle.' alt="c/e" /></td><td>'.
+ WT_I18N::translate('Compact tree / fixed boxes : switch beetween fixed-width boxes and compact tree. <i>fixed-width</i> display one generation\'s boxes in one column, and <i>compact</i> display more persons on the same area.').'</td></tr>'.
+ // function not enabled yet
+ // '<tr><td><img src="'.$WT_IMAGES['media'].'"'.$imgStyle.' alt="open" /></td><td>'.
+ // WT_I18N::translate('Open details for all displayed boxes. Could be long.').'</td></tr>'.
+ '<tr><td><img src="'.$WT_IMAGES["fambook"].'"'.$imgStyle.' alt="close" /></td><td>'.
+ WT_I18N::translate('Close all opened boxes.').'</td></tr>'.
+ '<tr><td><img src="'.WT_MODULES_DIR.'/tree/images/print.png"'.$imgStyle.' alt="print" /></td><td>'.
+ WT_I18N::translate('Download full resolution medias instead of thumbnails for opened person\'s boxes and open the print dialog when done.').'</td></tr>'.
+ '<tr><td><img src="'.$WT_IMAGES["sfamily"].'"'.$imgStyle.' alt="partners" /></td><td>'.
+ WT_I18N::translate('Show / hide multiples life partners or spouses.').'</td></tr>'.
+ '</tbody></table>'.
+ WT_I18N::translate('
+- when you drag, align or center the tree, person\'s boxes are loaded and added until the tree is completely loaded.
+
+- the treeview toolbar is draggable everywhere you want on the tree view.
+
+- you can directly access to an individual record with one click on a person\'s gender icon.
+
+- a click elsewhere on a family\'s box load and display more detailed informations about this family. When details are displayed, you can click on the tree icon beside a person\'s name to go to these person\'s interactive TreeView, or on the family\'s icon beside a life partner to go to these family\'s page. If the Lightbox module is enabled, a click on the person\'s thumbnail, when exists, open the associated image in the lightbox. When a person have some life partners, the lightbox display the main medias of these partners as a diaporama.
+
+- your preferences are stored in local cookies: zoom level, fixed or compact, switch last / all life partners, style.
+
+<u>Printing tips:</u>
+- to print a big tree on one big sheet, you can set a big paper size and print in a file (you can find large format printing services almost everywhere).
+- you can display details for the persons you want before printing the tree in a "What-You-See-Is-What-You-Get" mode.
+- to print the lines between person boxes, enable the printing of background colors and images in your browser\'s settings.
+- you can play with the TreeView zoom feature and the printing paper size setting to print any tree.
+- if you encounter some printing issues on Linux systems, you can change the print-to-file driver, from lpr to kprinter (even if you don\'t use KDE). In Firefox, that is set in the "about:config" page.
+');
+ break;
+*/
+}
diff --git a/modules_v3/tree/images/alignLeft.png b/modules_v3/tree/images/alignLeft.png
new file mode 100644
index 0000000000..104b6b5f1c
--- /dev/null
+++ b/modules_v3/tree/images/alignLeft.png
Binary files differ
diff --git a/modules_v3/tree/images/alignRight.png b/modules_v3/tree/images/alignRight.png
new file mode 100644
index 0000000000..3f2a81092f
--- /dev/null
+++ b/modules_v3/tree/images/alignRight.png
Binary files differ
diff --git a/modules_v3/tree/images/center.png b/modules_v3/tree/images/center.png
new file mode 100644
index 0000000000..5e70627b6b
--- /dev/null
+++ b/modules_v3/tree/images/center.png
Binary files differ
diff --git a/modules_v3/tree/images/compact.png b/modules_v3/tree/images/compact.png
new file mode 100644
index 0000000000..07b092d1ed
--- /dev/null
+++ b/modules_v3/tree/images/compact.png
Binary files differ
diff --git a/modules_v3/tree/images/dates.png b/modules_v3/tree/images/dates.png
new file mode 100644
index 0000000000..f358f9057f
--- /dev/null
+++ b/modules_v3/tree/images/dates.png
Binary files differ
diff --git a/modules_v3/tree/images/print.png b/modules_v3/tree/images/print.png
new file mode 100644
index 0000000000..c1dad25728
--- /dev/null
+++ b/modules_v3/tree/images/print.png
Binary files differ
diff --git a/modules_v3/tree/images/zoom0.png b/modules_v3/tree/images/zoom0.png
new file mode 100644
index 0000000000..9a30355549
--- /dev/null
+++ b/modules_v3/tree/images/zoom0.png
Binary files differ
diff --git a/modules_v3/tree/js/treeview.js b/modules_v3/tree/js/treeview.js
new file mode 100644
index 0000000000..79bf2e244b
--- /dev/null
+++ b/modules_v3/tree/js/treeview.js
@@ -0,0 +1,568 @@
+/**
+ * Class TreeViewHandler
+ * (c) Daniel Faivre 2011
+ *
+ * Tips :
+ * - for loops are much faster than using each
+ * - return false is required in functions
+ */
+function TreeViewHandler(treeviewInstance, allPartners, nbStyles) {
+ this.treeview = jQuery("#" + treeviewInstance + "_in");
+ this.loadingImage = jQuery("#" + treeviewInstance + "_loading");
+ this.toolbox = jQuery("#tv_tools");
+ this.buttons = jQuery(".tv_button:first", this.toolbox);
+ this.toolboxOrientation = (this.toolbox.find("#tvToolsHandler").css("float") != "left") ? 'v' : 'h';
+ this.nbStyles = nbStyles;
+ this.zoom = 100; // in percent
+ this.boxWidth = this.treeview.find(".tv_box:first").width(); // store the initial box width
+ if (isNaN(this.boxWidth))
+ this.boxWidth = 180; // default family box width
+ this.boxExpandedWidth = 250; // default expanded family box width
+ this.cookieDays = 360; // lifetime of preferences memory, in days
+ this.ajaxUrl = "module.php?mod=tree&instance=" + treeviewInstance +
+ "&allPartners=" + (allPartners ? "true" : "false") +
+ "&mod_action=";
+
+ this.container = this.treeview.parent(); // Store the container element ("#" + treeviewInstance + "_out")
+ this.auto_box_width = false;
+ this.showDates = true;
+ this.updating = false;
+ this.overLevel = 0; // internal var for handling submenus
+
+ var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
+
+ // Restore user preferences
+ if (readCookie("zoom") != null) {
+ tv.setZoom(parseInt(readCookie("zoom")) / 100);
+ }
+ if (readCookie("compact") == "true") {
+ tv.compact();
+ }
+ // set/reset the cookie allPartners
+ if (readCookie("allPartners") != allPartners)
+ createCookie("allPartners", allPartners, this.cookieDays);
+
+ // Define the draggables
+ tv.toolbox.draggable({
+ handle: "#tvToolsHandler",
+ cursor: "move",
+ containment: "#" + treeviewInstance + "_out",
+ snap: "#" + treeviewInstance + "_out",
+ snapMode: "inner",
+ snapTolerance: 10
+ });
+ tv.treeview.draggable({
+ cursor: "move",
+ stop: function(event, ui) {
+ tv.updateTree();
+ }
+ });
+
+ // define the toolbox submenu's functions
+ tv.toolbox.find("#tvStyleButton,#tvStylesSubmenu").each(function(index, tvStyleButton) {
+ var submenu = tv.toolbox.find("#tvStylesSubmenu");
+ tvStyleButton.onmouseover = function() {
+ tv.overLevel++;
+ var bw = tv.buttons.outerWidth(true);
+ var bm = (tv.buttons.outerWidth(true) - tv.buttons.outerWidth()) / 2;
+ if (tv.toolboxOrientation != 'v') {
+ var deltaX = 6 + 8 * bw; // align with the 8th button
+ var deltaY = bw;
+ }
+ else {
+ var deltaX = bw;
+ var deltaY = 6 + 8 * (bw-bm); // align with the 8th button
+ }
+ submenu.css("left", deltaX);
+ submenu.css("top", deltaY);
+ submenu.css("display", "block");
+ }
+ tvStyleButton.onmouseout = function() {
+ tv.overLevel--;
+ window.setTimeout(function(){if (tv.overLevel < 1) jQuery(submenu).css("display", "none");}, 200);
+ }
+ });
+ // Add click handlers to buttons
+ tv.toolbox.find("#tvToolsHandler").each(function(index, tvthandler) {
+ tvthandler.ondblclick = function() {
+ //tv.changeToolsOrientation();
+ var toolbox = "#tvToolsHandler, li.tv_button";
+ var submenu = tv.toolbox.find("#tvStylesSubmenu");
+ if (tv.toolbox.find(toolbox).css("float") == "left") {
+ tv.toolbox.find(toolbox).css("float", "none");
+ submenu.css("width", tv.nbStyles * tv.buttons.outerWidth(true));
+ submenu.find("li.tv_button").css("float", "left");
+ jQuery("#tvToolsHandler", tv.toolbox).css("height", "2px").css("width", "22px");
+ tv.toolboxOrientation = 'v';
+ }
+ else {
+ tv.toolbox.find(toolbox).css("float", "left");
+ submenu.css("width", tv.buttons.outerWidth(true));
+ submenu.find("li.tv_button").css("float", "none");
+ jQuery("#tvToolsHandler", tv.toolbox).css("height", "22px").css("width", "2px");
+ tv.toolboxOrientation = 'h';
+ }
+ return false;
+ }
+ });
+ tv.toolbox.find("#tvbZoomIn").each(function(index, tvbZoomIn) {
+ tvbZoomIn.onclick = function() {
+ tv.setZoom(1.1, tvbZoomIn);
+ }
+ });
+ tv.toolbox.find("#tvbZoomOut").each(function(index, tvbZoomOut) {
+ tvbZoomOut.onclick = function() {
+ tv.setZoom(0.9, tvbZoomOut);
+ }
+ });
+ tv.toolbox.find("#tvbNoZoom").each(function(index, tvbNoZoom) {
+ tvbNoZoom.onclick = function() {
+ tv.setZoom(0, tvbNoZoom);
+ }
+ });
+ tv.toolbox.find("#tvbLeft").each(function(index, tvLeft) {
+ var b = jQuery(tvLeft, tv.toolbox);
+ tvLeft.onclick = function() {
+ b.addClass("tvPressed");
+ tv.align("left", b);
+ }
+ });
+ tv.toolbox.find("#tvbCenter").each(function(index, tvCenter) {
+ tvCenter.onclick = function() {
+ tv.centerOnRoot();
+ }
+ });
+ tv.toolbox.find("#tvbRight").each(function(index, tvRight) {
+ var b = jQuery(tvRight, tv.toolbox);
+ tvRight.onclick = function() {
+ b.addClass("tvPressed");
+ tv.align("right", b);
+ }
+ });
+ tv.toolbox.find("#tvbDates").each(function(index, tvbDates) {
+ var b = jQuery(tvbDates, tv.toolbox);
+ tvbDates.onclick = function() {
+ if (tv.showDates) {
+ s = 'none';
+ b.removeClass("tvPressed");
+ tv.showDates = false;
+ }
+ else {
+ s = 'inline';
+ b.addClass("tvPressed");
+ tv.showDates = true;
+ }
+ tv.treeview.find(".tv_box .dates").css("display", s);
+ }
+ });
+ tv.toolbox.find("#tvbCompact").each(function(index, tvCompact) {
+ tvCompact.onclick = function() {
+ tv.compact();
+ }
+ });
+ tv.toolbox.find("#tvbPrint").each(function(index, tvbPrint) {
+ tvbPrint.onclick = function() {
+ tv.print(tvbPrint);
+ }
+ });
+ tv.toolbox.find("#tvbOpen").each(function(index, tvbOpen) {
+ var b = jQuery(tvbOpen, tv.toolbox);
+ tvbOpen.onclick = function() {
+ b.addClass("tvPressed");
+ tv.setLoading();
+ var e = jQuery.Event("click");
+ tv.treeview.find(".tv_box:not(.boxExpanded)").each(function(index, box){
+ var pos = jQuery(box, tv.treeview).offset();
+ if ((pos.left >= tv.leftMin) && (pos.left <= tv.leftMax) && (pos.top >= tv.topMin) && (pos.top <= tv.topMax))
+ tv.expandBox(box,e);
+ });
+ b.removeClass("tvPressed");
+ tv.setComplete();
+ }
+ });
+ tv.toolbox.find("#tvbClose").each(function(index, tvbClose) {
+ var b = jQuery(tvbClose,tv.toolbox );
+ tvbClose.onclick = function() {
+ b.addClass("tvPressed");
+ tv.setLoading();
+ tv.treeview.find(".tv_box.boxExpanded").each(function(index, box){
+ jQuery(box).css("display", "none").removeClass("boxExpanded").parent().find(".tv_box.collapsedContent").css("display", "block");
+ });
+ b.removeClass("tvPressed");
+ tv.setComplete();
+ }
+ });
+
+ // Intercept the scroll event to keep the toolbox available
+ jQuery(window).scroll(function(){
+ if (jQuery(window).scrollTop() > tv.container.offset().top)
+ tv.toolbox.css("position", "fixed");
+ else
+ tv.toolbox.css("position", "absolute");
+ });
+
+ tv.centerOnRoot(); // fire ajax update if needed, which call setComplete() when all is loaded
+ return false;
+}
+/**
+ * Class TreeView setLoading method
+ */
+TreeViewHandler.prototype.setLoading = function() {
+ this.treeview.css("cursor", "wait");
+ this.loadingImage.css("display", "block");
+}
+/**
+ * Class TreeView setComplete method
+ */
+TreeViewHandler.prototype.setComplete = function() {
+ this.treeview.css("cursor", "move");
+ this.loadingImage.css("display", "none");
+}
+
+/**
+ * Class TreeView getSize method
+ * Store the viewport current size
+ */
+TreeViewHandler.prototype.getSize = function() {
+ var tv = this;
+ // retrieve the current container bounding box
+ var container = tv.container.parent();
+ var offset = container.offset();
+ tv.leftMin = offset.left;
+ tv.leftMax = tv.leftMin + container.innerWidth();
+ tv.topMin = offset.top;
+ tv.topMax = tv.topMin + container.innerHeight();
+ /*
+ var frm = jQuery("#tvTreeBorder");
+ tv.treeview.css("width", frm.width());
+ tv.treeview.css("height", frm.height());*/
+}
+
+/**
+ * Class TreeView updateTree method
+ * Perform ajax requests to complete the tree after drag
+ * param boolean @center center on root person when done
+ */
+TreeViewHandler.prototype.updateTree = function(center, button) {
+ var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
+ var toLoad = new Array();
+ var elts = new Array();
+ this.getSize();
+
+ // check which td with datafld attribute are within the container bounding box
+ // and therefore need to be dynamically loaded
+ tv.treeview.find("td[abbr]").each(function(index, el) {
+ el = jQuery(el, tv.treeview);
+ var pos = el.offset();
+ if ((pos.left >= tv.leftMin) && (pos.left <= tv.leftMax) && (pos.top >= tv.topMin) && (pos.top <= tv.topMax)) {
+ toLoad.push(el.attr("abbr"));
+ elts.push(el);
+ }
+ });
+ // if some boxes need update, we perform an ajax request
+ if (toLoad.length > 0) {
+ tv.updating = true;
+ tv.setLoading();
+ jQuery.ajax({
+ url: tv.ajaxUrl + "getPersons",
+ dataType: "json",
+ data: "q=" + toLoad.join(";"),
+ success: function(ret) {
+ var nb = elts.length;
+ var rootEl = jQuery(".rootPerson", this.treeview);
+ var l = rootEl.offset().left;
+ for (var i=0;i<nb;i++) {
+ elts[i].removeAttr("abbr").html(ret[i]);
+ }
+ // repositionning
+ tv.treeview.offset({left: tv.treeview.offset().left - rootEl.offset().left +l});
+ // we now ajust the draggable treeview size to its content size
+ tv.getSize();
+ },
+ complete: function() {
+ if (tv.treeview.find("td[abbr]").length)
+ tv.updateTree(center, button); // recursive call
+ // the added boxes need that in mode compact boxes
+ if (tv.auto_box_width)
+ tv.treeview.find(".tv_box").css("width", "auto");
+ tv.updating = true; // avoid an unuseful recursive call when all requested persons are loaded
+ if (center == true)
+ tv.centerOnRoot();
+ if (button)
+ button.removeClass("tvPressed");
+ tv.setComplete();
+ tv.updating = false;
+ },
+ timeout: function() {
+ if (button)
+ button.removeClass("tvPressed");
+ tv.updating = false;
+ tv.setComplete();
+ }
+ });
+ }
+ else {
+ if (button)
+ button.removeClass("tvPressed");
+ tv.setComplete();
+ }
+ return false;
+}
+
+/**
+ * Class TreeView setZoom method
+ */
+TreeViewHandler.prototype.setZoom = function(zoom, button) {
+ this.treeview.css("cursor", "wait");
+ jQuery(button).addClass("tvPressed");
+ if (zoom == 0)
+ this.zoom = 100;
+ else
+ this.zoom *= zoom;
+ this.treeview.css("font-size", this.zoom + "%");
+
+ // we zoom the person boxes only if boxes width is fixed
+ if (!this.auto_box_width) {
+ jQuery(".tv_box:not(.expanded)", this.treeview).css("width", this.boxWidth * (this.zoom / 100) + "px");
+ jQuery(".boxExpanded", this.treeview).css("width", this.boxExpandedWidth * (this.zoom / 100) + "px");
+ }
+ createCookie("zoom", this.zoom.toString(), this.cookieDays);
+ jQuery(button).removeClass("tvPressed");
+ this.treeview.css("cursor", "move");
+ return false;
+}
+
+/**
+ * Class TreeView compacte method
+ */
+TreeViewHandler.prototype.compact = function() {
+ var tv = this;
+ var b = jQuery("#tvbCompact", tv.toolbox);
+ tv.setLoading();
+ if (!tv.auto_box_width) {
+ tv.treeview.find(".tv_box").css("width", "auto");
+ tv.auto_box_width = true;
+ if (!readCookie("compact"))
+ createCookie("compact", true, tv.cookieDays);
+ if (!tv.updating)
+ tv.updateTree();
+ b.addClass("tvPressed");
+ }
+ else {
+ var w = tv.boxWidth * (tv.zoom / 100) + "px";
+ var ew = tv.boxExpandedWidth * (tv.zoom / 100) + "px";
+ tv.treeview.find(".tv_box:not(boxExpanded)", tv.treeview).css("width", w);
+ tv.treeview.find(".boxExpanded", tv.treeview).css("width", ew);
+ tv.auto_box_width = false;
+ if (readCookie("compact"))
+ createCookie("compact", false, tv.cookieDays);
+ b.removeClass("tvPressed");
+ }
+ tv.setComplete();
+ return false;
+}
+
+
+/**
+ * Class TreeView align method
+ */
+TreeViewHandler.prototype.align = function(alignment, button) {
+ this.setLoading();
+ switch (alignment) {
+ case "left":
+ this.treeview.offset({left: this.container.offset().left, top: this.container.offset().top});
+ break;
+ case "right":
+ this.treeview.offset({left: this.container.offset().left + this.container.width() - this.treeview.width(), top: this.container.offset().top});
+ break;
+ default:
+ return false;
+ }
+ if (!this.updating)
+ this.updateTree(false, button);
+ return false;
+}
+
+/**
+ * Class TreeView centerOnRoot method
+ */
+TreeViewHandler.prototype.centerOnRoot = function() {
+ this.loadingImage.css("display", "block");
+ var tvc = this.container;
+ var tvcW = tvc.innerWidth() / 2;
+ if(isNaN(tvcW))
+ return false;
+ var tvcH = tvc.innerHeight() / 2;
+ var el = jQuery(".rootPerson", this.treeview);
+ var dLeft = tvc.offset().left + this.treeview.offset().left + tvcW - el.offset().left - el.outerWidth()/2;
+ var dTop = tvc.offset().top + this.treeview.offset().top + tvcH - el.offset().top - el.outerHeight()/2;
+ this.treeview.offset({left: dLeft, top: dTop});
+
+ if (!this.updating)
+ this.updateTree(true);
+ return false;
+}
+
+/**
+ * Class TreeView style method
+ * param string @style the style directory
+ */
+TreeViewHandler.prototype.style = function(stylepath, style, el) {
+ jQuery("#tvCSS").remove();
+ jQuery("#tvStylesSubmenu .tv_button").removeClass("tvPressed");
+ if (style)
+ jQuery("head").append('<link id="tvCSS" rel="stylesheet" type="text/css" href="' + stylepath + style + '/' + style + '.css">');
+ jQuery(el).parent().addClass("tvPressed");
+ jQuery("#tvStyleButton").html(jQuery(el).clone());
+ createCookie("tvStyle", style, this.cookieDays)
+}
+
+/**
+ * Class TreeView expandBox method
+ * param string @box the person box element
+ * param string @event the call event
+ * param string @pid the person id
+ *
+ * called ONLY for elements which have NOT the class tv_link to avoid unuseful requests to the server
+ */
+TreeViewHandler.prototype.expandBox = function(box, event) {
+ var t = jQuery(event.target);
+ if (t.hasClass("tv_link"))
+ return false;
+
+ var box = jQuery(box, this.treeview);
+ var bc = box.parent(); // bc is Box Container
+ var pid = box.attr("abbr");
+ var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
+ var expanded;
+ var collapsed;
+
+ if (bc.hasClass("detailsLoaded")) {
+ collapsed = bc.find(".collapsedContent");
+ expanded = bc.find(".tv_box:not(.collapsedContent)");
+ }
+ else {
+ // Cache the box content as an hidden person's box in the box's parent element
+ expanded = box;
+ collapsed = box.clone();
+ bc.append(collapsed.addClass("collapsedContent").css("display", "none"));
+ // we add a waiting image at the right side of the box
+ // TODO : manage rtl (left side instead of right in rtl mode)
+ var loadingImage = this.loadingImage.find("img").clone().addClass("tv_box_loading").css("display", "block");
+ box.prepend(loadingImage);
+ tv.updating = true;
+ tv.setLoading();
+ // perform the Ajax request and load the result in the box
+ box.load(tv.ajaxUrl + "getDetails&pid=" + pid, function() {
+ // If Lightbox module is active, we reinitialize it for the new links
+ if (typeof CB_Init == "function") {
+ CB_Init();
+ }
+ box.css("width", tv.boxExpandedWidth * (tv.zoom / 100) + "px");
+ loadingImage.remove();
+ bc.addClass("detailsLoaded");
+ tv.setComplete();
+ tv.updating = false;
+ });
+ }
+ if (box.hasClass("boxExpanded")) {
+ expanded.css("display", "none");
+ collapsed.css("display", "block");
+ box.removeClass("boxExpanded");
+ }
+ else {
+ expanded.css("display", "block");
+ collapsed.css("display", "none");
+ expanded.addClass("boxExpanded");
+ }
+ // we must ajust the draggable treeview size to its content size
+ this.getSize();
+ return false;
+}
+
+/**
+ * Class TreeView print method :load full resolution medias for opened details boxes, and open the print dialog after
+ */
+TreeViewHandler.prototype.print = function() {
+ var tv = this;
+ var medias = this.treeview.find(".boxExpanded .pedigree_image_portrait, .boxExpanded .pedigree_image_landscape").not(".HiRes");
+ if (medias.length) {
+ var ml = new Array();
+ tv.img2load = new Array();
+ medias.each(function(index, media) {
+ var alt = jQuery(media).attr("alt");
+ if (alt.length) {
+ ml.push(jQuery(media).attr("alt"));
+ tv.img2load.push(media);
+ }
+ });
+ tv.updating = true;
+ tv.setLoading();
+ jQuery.ajax({
+ url: tv.ajaxUrl + "getMedias",
+ dataType: "json",
+ data: "q=" + ml.join(";"),
+ success: function(ret) {
+ var nb = tv.img2load.length;
+ for (var i=0;i<nb;i++) {
+ tv.img2load[i].src = ret[i];
+ }
+ },
+ complete: function() {
+ tv.printWhenLoaded();
+ },
+ timeout: function() {
+ tv.updating = false;
+ tv.setComplete();
+ }
+ });
+ }
+ else
+ window.print();
+}
+
+/**
+ * Class TreeView printIfLoaded method :a callback function called when loading medias is pending
+ */
+TreeViewHandler.prototype.printWhenLoaded = function() {
+ var tv = this;
+ var nb = nbImg = tv.img2load.length;
+ for (var i=0;i<nbImg;i++) {
+ if (tv.img2load[i].complete) {
+ jQuery(tv.img2load[i]).addClass("HiRes");
+ nb--;
+ }
+ }
+ if (nb > 0)
+ window.setTimeout(tv.printWhenLoaded(), 200);
+ tv.setComplete();
+ tv.updating = false;
+ window.print();
+}
+
+function createCookie(name,value,days) {
+ if (days) {
+ var date = new Date();
+ date.setTime(date.getTime()+(days*24*60*60*1000));
+ var expires = "; expires="+date.toGMTString();
+ }
+ else var expires = "";
+ document.cookie = name+"="+value+expires+"; path=/";
+}
+
+function readCookie(name) {
+ var nameEQ = name + "=";
+ var ca = document.cookie.split(';');
+ for(var i=0;i < ca.length;i++) {
+ var c = ca[i];
+ while (c.charAt(0)==' ')
+ c = c.substring(1,c.length);
+ if (c.indexOf(nameEQ) == 0)
+ return c.substring(nameEQ.length,c.length);
+ }
+ return null;
+}
+
+function eraseCookie(name) {
+ createCookie(name,"",-1);
+}
diff --git a/modules_v3/tree/module.php b/modules_v3/tree/module.php
new file mode 100644
index 0000000000..0ff810b229
--- /dev/null
+++ b/modules_v3/tree/module.php
@@ -0,0 +1,157 @@
+<?php
+// TreeView module class
+//
+// Tip : you could change the number of generations loaded before ajax calls both in individual page and in treeview page to optimize speed and server load
+//
+// Copyright (C) 2011 webtrees development team
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// $Id$
+
+if (!defined('WT_WEBTREES')) {
+ header('HTTP/1.0 403 Forbidden');
+ exit;
+}
+
+class tree_WT_Module extends WT_Module implements WT_Module_Tab {
+ var $headers; // CSS and script to include in the top of <head> section, before theme's CSS
+ var $style; // the name of the active style, or false
+ var $css; // a customized CSS to load AFTER theme's CSS if $style is defined
+ var $js; // the TreeViewHandler javascript
+
+ function __construct() {
+ // define the module inclusions for the page header
+ $this->headers = '<link rel="stylesheet" type="text/css" href="'.WT_MODULES_DIR.$this->getName().'/css/treeview.css" />';
+ $this->js = '<script type="text/javascript" language="javascript" src="'.WT_MODULES_DIR.$this->getName().'/js/treeview.js"></script>';
+
+ // Retrieve the user's personalized style
+ if (isset($_COOKIE['tvStyle'])) {
+ $this->style = $_COOKIE['tvStyle'];
+ $this->css = '<link id="tvCSS" rel="stylesheet" type="text/css" href="'.WT_MODULES_DIR.$this->getName().'/css/styles/'.$this->style.'/'.$this->style.'.css" />';
+ }
+ else {
+ $this->style = false;
+ $this->css = '';
+ }
+ $this->css .= '<link rel="stylesheet" type="text/css" href="'.WT_MODULES_DIR.$this->getName().'/css/treeview_print.css" media="print" />';
+ }
+
+ // Extend WT_Module. This title should be normalized when this module will be added officially
+ public function getTitle() {
+ return /* I18N: Name of a module */ WT_I18N::translate('Interactive tree');
+ }
+
+ // Extend WT_Module
+ public function getDescription() {
+ return /* I18N: Description of the "Interactive tree" module */ WT_I18N::translate('An interactive tree, showing all the ancestors and descendants of a person.');
+ }
+
+ // Implement WT_Module_Tab
+ public function defaultTabOrder() {
+ return 68;
+ }
+
+ // Implement WT_Module_Tab
+ public function getJSCallback() {
+ return '';
+}
+
+ // Implement WT_Module_Tab
+ public function getTabContent() {
+ require_once WT_MODULES_DIR.$this->getName().'/class_treeview.php';
+ $tv = new TreeView('tvTab');
+ $r = $tv->drawViewport($this->controller->pid, 3, $this->style);
+ return $r;
+ }
+
+ // Implement WT_Module_Tab
+ public function hasTabContent() {
+ return true;
+ }
+ // Implement WT_Module_Tab
+ public function isGrayedOut() {
+ return false;
+ }
+ // Implement WT_Module_Tab
+ public function canLoadAjax() {
+ return true;
+ }
+
+ // Implement WT_Module_Tab
+ public function getPreLoadContent() {
+ // a workaround to the lack of a proper method of class Module to insert css and scripts in <head> where needed
+ // the required loading order is : headers, theme, css
+ return $this->js.'<script language="javascript" type="text/javascript">jQuery("head").prepend(\''.$this->headers.'\').append(\''.$this->css.'\');</script>';
+ }
+
+ // Extend WT_Module
+ // We define here actions to proceed when called, either by Ajax or not
+ public function modAction($mod_action) {
+ require_once WT_MODULES_DIR.$this->getName().'/class_treeview.php';
+ switch($mod_action) {
+ case 'treeview':
+ $tvName = 'tv';
+ $rootid = safe_GET('rootid');
+ $rootid = check_rootid($rootid);
+ $tv = new TreeView('tv');
+ ob_start();
+ $person=WT_Person::getInstance($rootid);
+ print_header(WT_I18N::translate('Interactive tree of %s', $person->getFullName()));
+ if (WT_USE_LIGHTBOX) {
+ require WT_MODULES_DIR.'lightbox/functions/lb_call_js.php';
+ }
+ $header = ob_get_clean();
+ // we do this trick to insert headers js calls and css
+ // should be improved as soon as webtrees will have provided a way to do that
+ // in a more proper way (a method of Module object to insert its css and scripts calls in the <head>)
+ // The CSS inserted here could be overided by cascading style sheet mechanism
+ // when relevant properties are defined in the theme's CSS
+ $header = str_replace('<head>', '<head>'.$this->headers, $header);
+ // If TreeView was personalized, include the custom CSS at the end of the header, to "cascade" previously loaded CSS
+ $header = str_replace('</head>', $this->js.$this->css.'</head>', $header);
+ echo $header;
+ echo $tv->drawViewport($rootid, 4, $this->style);
+ print_footer();
+ break;
+
+ case 'getDetails':
+ header('Content-Type: text/html; charset=UTF-8');
+ $pid = safe_GET('pid');
+ $i = safe_GET('instance');
+ $tv = new TreeView($i);
+ echo $tv->getDetails($pid);
+ break;
+
+ case 'getPersons':
+ $q = $_REQUEST["q"];
+ $i = safe_GET('instance');
+ $tv = new TreeView($i);
+ echo $tv->getPersons($q);
+ break;
+
+ // dynamically load full medias instead of thumbnails for opened boxes before printing
+ case 'getMedias':
+ $q = $_REQUEST["q"];
+ $i = safe_GET('instance');
+ $tv = new TreeView($i);
+ echo $tv->getMedias($q);
+ break;
+
+ default:
+ header('HTTP/1.0 404 Not Found');
+ }
+ }
+}