Difference between revisions of "Extension:Treeview4.php"
From Organic Design wiki
(5.0.2 - $id not $uid for per-tree id's ($uid is used by voodoo only)) |
m (formatting) |
||
(6 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | {{legacy|the [[MW:Extension:TreeAndMenu|TreeAndMenu extension]]}}{{voodoo}} | ||
+ | <source lang="php"> | ||
<?php | <?php | ||
− | + | # MediaWiki Treeview Extension | |
− | + | # - See http://www.mediawiki.org/wiki/Extension:Tree_view for installation and usage details | |
− | + | # - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html) | |
− | + | # - Author: http://www.organicdesign.co.nz/nad | |
− | + | # - Started: (Version4) 2007-09-06 | |
− | + | ||
− | |||
− | |||
if (!defined('MEDIAWIKI')) die('Not an entry point.'); | if (!defined('MEDIAWIKI')) die('Not an entry point.'); | ||
− | + | ||
− | define(' | + | define('TREEVIEW4_VERSION','4.0.9, 2007-12-29'); |
− | + | ||
# Set any unset images to default titles | # Set any unset images to default titles | ||
if (!isset($wgTreeViewImages) || !is_array($wgTreeViewImages)) $wgTreeViewImages = array(); | if (!isset($wgTreeViewImages) || !is_array($wgTreeViewImages)) $wgTreeViewImages = array(); | ||
+ | if (!isset($wgTreeViewImages['plus'])) $wgTreeViewImages['plus'] = 'Plus.gif'; | ||
+ | if (!isset($wgTreeViewImages['minus'])) $wgTreeViewImages['minus'] = 'Minus.gif'; | ||
+ | if (!isset($wgTreeViewImages['opened'])) $wgTreeViewImages['opened'] = 'Folder_opn_sml_yel.gif'; | ||
+ | if (!isset($wgTreeViewImages['closed'])) $wgTreeViewImages['closed'] = 'Folder_sml_yel.gif'; | ||
+ | if (!isset($wgTreeViewImages['doc'])) $wgTreeViewImages['doc'] = 'Doc-icon.gif'; | ||
+ | if (!isset($wgTreeViewImages['spacer'])) $wgTreeViewImages['spacer'] = 'Blank.gif'; | ||
+ | # These images are needed if you have $wgTreeViewShowLines set | ||
+ | if (!isset($wgTreeViewImages['vert'])) $wgTreeViewImages['vert'] = 'Vertline.gif'; | ||
+ | if (!isset($wgTreeViewImages['node'])) $wgTreeViewImages['node'] = 'Node.gif'; | ||
+ | if (!isset($wgTreeViewImages['last'])) $wgTreeViewImages['last'] = 'Lastnode.gif'; | ||
+ | |||
# Keep track of JavaScript added to page to avoid doubleups | # Keep track of JavaScript added to page to avoid doubleups | ||
if (!isset($wgJS)) $wgJS = array(); | if (!isset($wgJS)) $wgJS = array(); | ||
− | + | ||
− | $ | + | $wgTreeView4Magic = "tree"; # the parser-function name for trees |
+ | $wgTreeViewIndent = 0; # the number of pixels each level indents by (0 means doc-icon width) | ||
$wgTreeViewShowLines = false; # whether to render the dotted lines joining nodes | $wgTreeViewShowLines = false; # whether to render the dotted lines joining nodes | ||
− | $wgExtensionFunctions[] = ' | + | $wgExtensionFunctions[] = 'wfSetupTreeView4'; |
− | $wgHooks['LanguageGetMagic'][] = ' | + | $wgHooks['LanguageGetMagic'][] = 'wfTreeView4LanguageGetMagic'; |
− | + | ||
$wgExtensionCredits['parserhook'][] = array( | $wgExtensionCredits['parserhook'][] = array( | ||
− | 'name' => ' | + | 'name' => 'Treeview4', |
− | 'author' => '[http://www.organicdesign.co.nz/nad | + | 'author' => '[http://www.organicdesign.co.nz/nad User:Nad]', |
'url' => 'http://www.mediawiki.org/wiki/Extension:Treeview', | 'url' => 'http://www.mediawiki.org/wiki/Extension:Treeview', | ||
− | 'description' => ' | + | 'description' => 'Allows dynamic tree-views to be made with bullet-list syntax', |
− | + | 'version' => TREEVIEW4_VERSION | |
− | |||
− | 'version' => | ||
); | ); | ||
− | + | ||
− | class | + | class TreeView4 { |
− | + | ||
− | var $version = | + | var $version = TREEVIEW4_VERSION; |
− | var $ | + | var $width = 16; |
− | var $ | + | var $uniq = array(); |
− | var $ | + | var $uid = ''; |
− | var $ | + | var $js = 0; |
− | + | ||
− | + | # Constructor | |
− | + | function TreeView4() { | |
− | + | global $wgParser,$wgHooks,$wgTreeView4Magic,$wgTreeViewIconMagic,$wgTreeViewImages,$wgTreeViewIndent; | |
− | function | ||
− | global $wgParser,$ | ||
# Convert image titles to file paths and obtain pixel width of items | # Convert image titles to file paths and obtain pixel width of items | ||
+ | if ($wgTreeViewIndent) $this->width = $wgTreeViewIndent; | ||
foreach ($wgTreeViewImages as $k => $v) { | foreach ($wgTreeViewImages as $k => $v) { | ||
$title = Title::newFromText($v,NS_IMAGE); | $title = Title::newFromText($v,NS_IMAGE); | ||
$image = Image::newFromTitle($title); | $image = Image::newFromTitle($title); | ||
− | if ($image && $image->exists()) $wgTreeViewImages[$k] = $image->getURL(); | + | if ($image && $image->exists()) { |
+ | $wgTreeViewImages[$k] = $image->getURL(); | ||
+ | if ($wgTreeViewIndent < 1 && $k == 'doc') $this->width = $image->getWidth(); | ||
+ | } | ||
} | } | ||
− | |||
− | |||
$this->uid = uniqid('TVUNIQ'); | $this->uid = uniqid('TVUNIQ'); | ||
− | $ | + | $wgParser->setFunctionHook($wgTreeView4Magic,array($this,'Tree')); |
− | + | } | |
− | + | ||
− | + | # Restructure recursive trees into a single bullet list surrounded by internal treeview4 tags | |
− | |||
− | |||
− | |||
− | |||
function Tree(&$parser) { | function Tree(&$parser) { | ||
global $wgParser; | global $wgParser; | ||
− | $id = uniqid( | + | $id = uniqid(); |
$args = "id='$id'"; | $args = "id='$id'"; | ||
foreach (func_get_args() as $arg) if (!is_object($arg)) { | foreach (func_get_args() as $arg) if (!is_object($arg)) { | ||
Line 75: | Line 81: | ||
# Black magic | # Black magic | ||
$text = $this->uniq[$id] = preg_replace( | $text = $this->uniq[$id] = preg_replace( | ||
− | '/^\\*(\\**)\\s*(\\x07UNIQ.+?- | + | '/^\\*(\\**)\\s*(\\x07UNIQ.+?-treeview4(.+?)-.+?-QINU\\x07?)/me', |
'$this->uniq["$3"] ? preg_replace("/^(\\*+)/m","$1\$1",$this->uniq["$3"]) : "$1$2"', | '$this->uniq["$3"] ? preg_replace("/^(\\*+)/m","$1\$1",$this->uniq["$3"]) : "$1$2"', | ||
$text | $text | ||
Line 81: | Line 87: | ||
# And a little more voodoo here | # And a little more voodoo here | ||
− | $wgParser->setHook(" | + | $wgParser->setHook("treeview4$id",array($this,'treeview')); |
− | return "< | + | return "<treeview4$id $args>$text</treeview4$id>"; |
} | } | ||
− | + | # Convert a bullet list into a treeview | |
− | |||
− | |||
function treeview($text,$argv,&$parser) { | function treeview($text,$argv,&$parser) { | ||
− | global $wgTreeViewImages | + | global $wgTreeViewImages; |
− | + | ||
− | $id | + | $id = $argv['id']; |
− | $uid | + | $uid = $this->uid; |
− | $ | + | $ver = $this->version; |
− | + | $width = $this->width; | |
+ | $plus = $wgTreeViewImages['plus']; | ||
+ | $minus = $wgTreeViewImages['minus']; | ||
+ | $opened = $wgTreeViewImages['opened']; | ||
+ | $closed = $wgTreeViewImages['closed']; | ||
+ | $spacer = $wgTreeViewImages['spacer']; | ||
+ | $doc = $wgTreeViewImages['doc']; | ||
+ | $vert = $wgTreeViewImages['vert']; | ||
+ | $node = $wgTreeViewImages['node']; | ||
+ | $last = $wgTreeViewImages['last']; | ||
+ | $default = isset($argv['openlevels']) ? $argv['openlevels']+1 : 1; | ||
+ | $rows = array(); | ||
+ | $lasts = array(); | ||
+ | $cols = 0; | ||
+ | $next = 0; | ||
+ | $tree = ''; | ||
+ | |||
# Protect the asterisk structure and wiki-parse the bullet tree | # Protect the asterisk structure and wiki-parse the bullet tree | ||
$text = preg_replace("/(?<=\\*)\\s*\\[\\[Image:(.+?)\\]\\]/","{$uid}3$1{$uid}4",$text); | $text = preg_replace("/(?<=\\*)\\s*\\[\\[Image:(.+?)\\]\\]/","{$uid}3$1{$uid}4",$text); | ||
Line 103: | Line 123: | ||
# Extract the valid rows and process if any | # Extract the valid rows and process if any | ||
if (preg_match_all("/1{$uid}([0-9]+)-({$uid}3(.+?){$uid}4)?(.+?){$uid}2/",$text,$matches,PREG_SET_ORDER)) { | if (preg_match_all("/1{$uid}([0-9]+)-({$uid}3(.+?){$uid}4)?(.+?){$uid}2/",$text,$matches,PREG_SET_ORDER)) { | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | # | + | # Parse 1 |
− | |||
− | |||
− | |||
foreach ($matches as $row) { | foreach ($matches as $row) { | ||
list(,$depth,,$icon,$item) = $row; | list(,$depth,,$icon,$item) = $row; | ||
if ($depth > $cols) $lasts[$cols = $depth] = true; | if ($depth > $cols) $lasts[$cols = $depth] = true; | ||
− | $ | + | $rows[] = array($depth,$icon,$item); |
− | $ | + | } |
− | $ | + | |
− | $ | + | # Parse 2 |
− | + | for ($row = count($rows)-1; $row >= 0; $row--) { | |
+ | list($depth,$i,$item) = $rows[$row]; | ||
+ | $diff = $depth - $next; | ||
+ | $show = $depth > $default ? " style='display:none'" : ""; | ||
+ | $span = $cols+2-$depth; | ||
+ | $span = $span == 1 ? "" : " colspan='$span'"; | ||
+ | $td = ""; | ||
+ | $ibg = ""; | ||
+ | |||
+ | # Determine the open/close link and the folder/doc icon | ||
+ | if ($depth >= $default) { $open = $plus; $icon = $closed; } | ||
+ | else { $open = $minus; $icon = $opened; $ibg = " style='background: url($vert) 0 10px no-repeat'"; } | ||
+ | if ($depth >= $next) { $open = "<img src='$spacer' width='$width'/>"; $icon = $doc; $ibg = ''; } | ||
+ | else $open = "<a href='javascript:toggleTreeviewItem(\"$id\",$row)'><img id='tvi$id$row' src='$open'/></a>"; | ||
+ | |||
+ | # Handle custom image | ||
+ | if ($i) { | ||
+ | $i = Image::newFromTitle(Title::newFromText($i,NS_IMAGE)); | ||
+ | if ($i && $i->exists()) $icon = $i->getURL(); | ||
+ | } | ||
+ | |||
+ | # Construct the dotted joining lines and position the open/close link in the last one | ||
+ | if ($diff > 0) $lasts[$depth] = true; | ||
+ | for ($col = $depth+1; $col < $cols; $col++) $lasts[$col] = true; | ||
+ | for ($col = 1; $col <= $depth; $col++) { | ||
+ | if ($diff > 1 && $col > $next && $col < $depth-1) $lasts[$col] = true; | ||
+ | if ($col == $depth) { $fg = $open; $bg = $lasts[$col] ? $last : $node; } | ||
+ | else { $fg = ""; $bg = $lasts[$col] ? $spacer : $vert; } | ||
+ | $td .= "<td style='background: url($bg) no-repeat'>$fg</td>"; | ||
+ | } | ||
+ | $lasts[$depth] = false; | ||
+ | |||
+ | # Add the icon and the item content and append a table row to the tree definition | ||
+ | $td .= "<td class='tree-icon'><img id='tvf$id$row' src='$icon'/></td>"; | ||
+ | $td .= "<td class='tree-text'$span>$item</td>"; | ||
+ | $tree = "<tr$show depth='$depth' id='tvr$id$row'>$td</tr>\n$tree"; | ||
+ | $next = $depth; | ||
+ | } | ||
} | } | ||
− | + | # This invisible row at the start fixes a bug making some text items not maximum width | |
− | + | $td = ''; | |
+ | for ($col = 1; $col <= $cols+1; $col++) $td .= "<td width=0/>"; | ||
+ | $tree = "<tr>$td<td width=100%/></tr>\n$tree"; | ||
+ | |||
+ | return "<table cellpadding=0 cellspacing=0 class='tree-view' id='tv$id' title='Extension:Treeview (ver $ver)'>\n$tree</table>"; | ||
} | } | ||
− | + | # Protect asterisk bullet structure from wiki parser | |
− | |||
− | |||
− | |||
− | |||
− | |||
function protectTree($m) { | function protectTree($m) { | ||
return "1{$this->uid}".strlen($m[1])."-$m[2]{$this->uid}2\n"; | return "1{$this->uid}".strlen($m[1])."-$m[2]{$this->uid}2\n"; | ||
} | } | ||
− | + | # Add the javascript to the output object if not added yet and there is at least one tree | |
− | |||
− | |||
function addJS() { | function addJS() { | ||
− | global $wgOut,$wgJS,$wgJsMimeType; | + | global $wgOut,$wgTreeViewImages,$wgJS,$wgJsMimeType; |
− | if (isset($wgJS[' | + | if (isset($wgJS['TreeView4'])) return; |
− | $wgJS[' | + | $wgJS['TreeView4'] = true; |
− | $wgOut->addScript( | + | $plus = $wgTreeViewImages['plus']; |
+ | $minus = $wgTreeViewImages['minus']; | ||
+ | $opened = $wgTreeViewImages['opened']; | ||
+ | $closed = $wgTreeViewImages['closed']; | ||
+ | $spacer = $wgTreeViewImages['spacer']; | ||
+ | $doc = $wgTreeViewImages['doc']; | ||
+ | $vert = $wgTreeViewImages['vert']; | ||
+ | $wgOut->addScript('<script type="'.$wgJsMimeType.'"> | ||
+ | function toggleTreeviewItem(id,row) { | ||
+ | var plus = "'.$plus.'"; | ||
+ | var minus = "'.$minus.'"; | ||
+ | var opened = "'.$opened.'"; | ||
+ | var closed = "'.$closed.'"; | ||
+ | var doc = "'.$doc.'"; | ||
+ | var item = document.getElementById("tvr"+id+row); | ||
+ | var next = document.getElementById("tvr"+id+(row+1)); | ||
+ | var depth = 0+item.getAttribute("depth"); | ||
+ | var close = next.style.display != "none"; | ||
+ | var img = document.getElementById("tvi"+id+row); | ||
+ | var fld = document.getElementById("tvf"+id+row); | ||
+ | var src = fld.getAttribute("src"); | ||
+ | if (src == opened) fld.setAttribute("src",closed); | ||
+ | if (src == closed) fld.setAttribute("src",opened); | ||
+ | fld.setAttribute("style",close ? "" : "background:url('.$vert.') repeat-y"); | ||
+ | img.setAttribute("src",close ? plus : minus); | ||
+ | while ((item = document.getElementById("tvr"+id+(++row))) && (0+item.getAttribute("depth") > depth)) { | ||
+ | if (close) item.style.display = "none"; | ||
+ | else if (depth == item.getAttribute("depth")-1) { | ||
+ | item.style.display = ""; | ||
+ | if (img = document.getElementById("tvi"+id+row)) img.setAttribute("src",plus); | ||
+ | if (fld = document.getElementById("tvf"+id+row)) | ||
+ | if (fld.getAttribute("src") == opened) { | ||
+ | fld.setAttribute("src",closed); | ||
+ | fld.serAttribute("style",""); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | }</script>'); | ||
+ | } | ||
} | } | ||
− | |||
− | + | # Called from $wgExtensionFunctions array when initialising extensions | |
− | + | function wfSetupTreeView4() { | |
− | + | global $wgTreeView4; | |
− | function | + | $wgTreeView4 = new TreeView4(); |
− | global $ | + | $wgTreeView4->addJS(); # Make code unconditional for now due to parser caching |
− | $ | ||
− | $ | ||
} | } | ||
− | + | # Needed in MediaWiki >1.8.0 for magic word hooks to work properly | |
− | + | function wfTreeView4LanguageGetMagic(&$magicWords,$langCode = 0) { | |
− | + | global $wgTreeView4,$wgTreeView4Magic; | |
− | function | + | $magicWords[$wgTreeView4Magic] = array(0,$wgTreeView4Magic); |
− | global $ | ||
− | $magicWords[$ | ||
return true; | return true; | ||
} | } | ||
+ | </source> |
Latest revision as of 14:55, 31 October 2016
<?php
# MediaWiki Treeview Extension
# - See http://www.mediawiki.org/wiki/Extension:Tree_view for installation and usage details
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
# - Author: http://www.organicdesign.co.nz/nad
# - Started: (Version4) 2007-09-06
if (!defined('MEDIAWIKI')) die('Not an entry point.');
define('TREEVIEW4_VERSION','4.0.9, 2007-12-29');
# Set any unset images to default titles
if (!isset($wgTreeViewImages) || !is_array($wgTreeViewImages)) $wgTreeViewImages = array();
if (!isset($wgTreeViewImages['plus'])) $wgTreeViewImages['plus'] = 'Plus.gif';
if (!isset($wgTreeViewImages['minus'])) $wgTreeViewImages['minus'] = 'Minus.gif';
if (!isset($wgTreeViewImages['opened'])) $wgTreeViewImages['opened'] = 'Folder_opn_sml_yel.gif';
if (!isset($wgTreeViewImages['closed'])) $wgTreeViewImages['closed'] = 'Folder_sml_yel.gif';
if (!isset($wgTreeViewImages['doc'])) $wgTreeViewImages['doc'] = 'Doc-icon.gif';
if (!isset($wgTreeViewImages['spacer'])) $wgTreeViewImages['spacer'] = 'Blank.gif';
# These images are needed if you have $wgTreeViewShowLines set
if (!isset($wgTreeViewImages['vert'])) $wgTreeViewImages['vert'] = 'Vertline.gif';
if (!isset($wgTreeViewImages['node'])) $wgTreeViewImages['node'] = 'Node.gif';
if (!isset($wgTreeViewImages['last'])) $wgTreeViewImages['last'] = 'Lastnode.gif';
# Keep track of JavaScript added to page to avoid doubleups
if (!isset($wgJS)) $wgJS = array();
$wgTreeView4Magic = "tree"; # the parser-function name for trees
$wgTreeViewIndent = 0; # the number of pixels each level indents by (0 means doc-icon width)
$wgTreeViewShowLines = false; # whether to render the dotted lines joining nodes
$wgExtensionFunctions[] = 'wfSetupTreeView4';
$wgHooks['LanguageGetMagic'][] = 'wfTreeView4LanguageGetMagic';
$wgExtensionCredits['parserhook'][] = array(
'name' => 'Treeview4',
'author' => '[http://www.organicdesign.co.nz/nad User:Nad]',
'url' => 'http://www.mediawiki.org/wiki/Extension:Treeview',
'description' => 'Allows dynamic tree-views to be made with bullet-list syntax',
'version' => TREEVIEW4_VERSION
);
class TreeView4 {
var $version = TREEVIEW4_VERSION;
var $width = 16;
var $uniq = array();
var $uid = '';
var $js = 0;
# Constructor
function TreeView4() {
global $wgParser,$wgHooks,$wgTreeView4Magic,$wgTreeViewIconMagic,$wgTreeViewImages,$wgTreeViewIndent;
# Convert image titles to file paths and obtain pixel width of items
if ($wgTreeViewIndent) $this->width = $wgTreeViewIndent;
foreach ($wgTreeViewImages as $k => $v) {
$title = Title::newFromText($v,NS_IMAGE);
$image = Image::newFromTitle($title);
if ($image && $image->exists()) {
$wgTreeViewImages[$k] = $image->getURL();
if ($wgTreeViewIndent < 1 && $k == 'doc') $this->width = $image->getWidth();
}
}
$this->uid = uniqid('TVUNIQ');
$wgParser->setFunctionHook($wgTreeView4Magic,array($this,'Tree'));
}
# Restructure recursive trees into a single bullet list surrounded by internal treeview4 tags
function Tree(&$parser) {
global $wgParser;
$id = uniqid();
$args = "id='$id'";
foreach (func_get_args() as $arg) if (!is_object($arg)) {
if (preg_match('/^(.+?=.+)$/',$arg,$m)) $args .= " $arg"; else $text = $arg;
}
# Black magic
$text = $this->uniq[$id] = preg_replace(
'/^\\*(\\**)\\s*(\\x07UNIQ.+?-treeview4(.+?)-.+?-QINU\\x07?)/me',
'$this->uniq["$3"] ? preg_replace("/^(\\*+)/m","$1\$1",$this->uniq["$3"]) : "$1$2"',
$text
);
# And a little more voodoo here
$wgParser->setHook("treeview4$id",array($this,'treeview'));
return "<treeview4$id $args>$text</treeview4$id>";
}
# Convert a bullet list into a treeview
function treeview($text,$argv,&$parser) {
global $wgTreeViewImages;
$id = $argv['id'];
$uid = $this->uid;
$ver = $this->version;
$width = $this->width;
$plus = $wgTreeViewImages['plus'];
$minus = $wgTreeViewImages['minus'];
$opened = $wgTreeViewImages['opened'];
$closed = $wgTreeViewImages['closed'];
$spacer = $wgTreeViewImages['spacer'];
$doc = $wgTreeViewImages['doc'];
$vert = $wgTreeViewImages['vert'];
$node = $wgTreeViewImages['node'];
$last = $wgTreeViewImages['last'];
$default = isset($argv['openlevels']) ? $argv['openlevels']+1 : 1;
$rows = array();
$lasts = array();
$cols = 0;
$next = 0;
$tree = '';
# Protect the asterisk structure and wiki-parse the bullet tree
$text = preg_replace("/(?<=\\*)\\s*\\[\\[Image:(.+?)\\]\\]/","{$uid}3$1{$uid}4",$text);
$text = preg_replace_callback("/^(\\*+)(.*?)$/m",array($this,'protectTree'),$text);
$out = $parser->parse($text,$parser->mTitle,$parser->mOptions,false,false);
$text = $out->getText();
# Extract the valid rows and process if any
if (preg_match_all("/1{$uid}([0-9]+)-({$uid}3(.+?){$uid}4)?(.+?){$uid}2/",$text,$matches,PREG_SET_ORDER)) {
# Parse 1
foreach ($matches as $row) {
list(,$depth,,$icon,$item) = $row;
if ($depth > $cols) $lasts[$cols = $depth] = true;
$rows[] = array($depth,$icon,$item);
}
# Parse 2
for ($row = count($rows)-1; $row >= 0; $row--) {
list($depth,$i,$item) = $rows[$row];
$diff = $depth - $next;
$show = $depth > $default ? " style='display:none'" : "";
$span = $cols+2-$depth;
$span = $span == 1 ? "" : " colspan='$span'";
$td = "";
$ibg = "";
# Determine the open/close link and the folder/doc icon
if ($depth >= $default) { $open = $plus; $icon = $closed; }
else { $open = $minus; $icon = $opened; $ibg = " style='background: url($vert) 0 10px no-repeat'"; }
if ($depth >= $next) { $open = "<img src='$spacer' width='$width'/>"; $icon = $doc; $ibg = ''; }
else $open = "<a href='javascript:toggleTreeviewItem(\"$id\",$row)'><img id='tvi$id$row' src='$open'/></a>";
# Handle custom image
if ($i) {
$i = Image::newFromTitle(Title::newFromText($i,NS_IMAGE));
if ($i && $i->exists()) $icon = $i->getURL();
}
# Construct the dotted joining lines and position the open/close link in the last one
if ($diff > 0) $lasts[$depth] = true;
for ($col = $depth+1; $col < $cols; $col++) $lasts[$col] = true;
for ($col = 1; $col <= $depth; $col++) {
if ($diff > 1 && $col > $next && $col < $depth-1) $lasts[$col] = true;
if ($col == $depth) { $fg = $open; $bg = $lasts[$col] ? $last : $node; }
else { $fg = ""; $bg = $lasts[$col] ? $spacer : $vert; }
$td .= "<td style='background: url($bg) no-repeat'>$fg</td>";
}
$lasts[$depth] = false;
# Add the icon and the item content and append a table row to the tree definition
$td .= "<td class='tree-icon'><img id='tvf$id$row' src='$icon'/></td>";
$td .= "<td class='tree-text'$span>$item</td>";
$tree = "<tr$show depth='$depth' id='tvr$id$row'>$td</tr>\n$tree";
$next = $depth;
}
}
# This invisible row at the start fixes a bug making some text items not maximum width
$td = '';
for ($col = 1; $col <= $cols+1; $col++) $td .= "<td width=0/>";
$tree = "<tr>$td<td width=100%/></tr>\n$tree";
return "<table cellpadding=0 cellspacing=0 class='tree-view' id='tv$id' title='Extension:Treeview (ver $ver)'>\n$tree</table>";
}
# Protect asterisk bullet structure from wiki parser
function protectTree($m) {
return "1{$this->uid}".strlen($m[1])."-$m[2]{$this->uid}2\n";
}
# Add the javascript to the output object if not added yet and there is at least one tree
function addJS() {
global $wgOut,$wgTreeViewImages,$wgJS,$wgJsMimeType;
if (isset($wgJS['TreeView4'])) return;
$wgJS['TreeView4'] = true;
$plus = $wgTreeViewImages['plus'];
$minus = $wgTreeViewImages['minus'];
$opened = $wgTreeViewImages['opened'];
$closed = $wgTreeViewImages['closed'];
$spacer = $wgTreeViewImages['spacer'];
$doc = $wgTreeViewImages['doc'];
$vert = $wgTreeViewImages['vert'];
$wgOut->addScript('<script type="'.$wgJsMimeType.'">
function toggleTreeviewItem(id,row) {
var plus = "'.$plus.'";
var minus = "'.$minus.'";
var opened = "'.$opened.'";
var closed = "'.$closed.'";
var doc = "'.$doc.'";
var item = document.getElementById("tvr"+id+row);
var next = document.getElementById("tvr"+id+(row+1));
var depth = 0+item.getAttribute("depth");
var close = next.style.display != "none";
var img = document.getElementById("tvi"+id+row);
var fld = document.getElementById("tvf"+id+row);
var src = fld.getAttribute("src");
if (src == opened) fld.setAttribute("src",closed);
if (src == closed) fld.setAttribute("src",opened);
fld.setAttribute("style",close ? "" : "background:url('.$vert.') repeat-y");
img.setAttribute("src",close ? plus : minus);
while ((item = document.getElementById("tvr"+id+(++row))) && (0+item.getAttribute("depth") > depth)) {
if (close) item.style.display = "none";
else if (depth == item.getAttribute("depth")-1) {
item.style.display = "";
if (img = document.getElementById("tvi"+id+row)) img.setAttribute("src",plus);
if (fld = document.getElementById("tvf"+id+row))
if (fld.getAttribute("src") == opened) {
fld.setAttribute("src",closed);
fld.serAttribute("style","");
}
}
}
}</script>');
}
}
# Called from $wgExtensionFunctions array when initialising extensions
function wfSetupTreeView4() {
global $wgTreeView4;
$wgTreeView4 = new TreeView4();
$wgTreeView4->addJS(); # Make code unconditional for now due to parser caching
}
# Needed in MediaWiki >1.8.0 for magic word hooks to work properly
function wfTreeView4LanguageGetMagic(&$magicWords,$langCode = 0) {
global $wgTreeView4,$wgTreeView4Magic;
$magicWords[$wgTreeView4Magic] = array(0,$wgTreeView4Magic);
return true;
}