From OrganicDesign Wiki
| Legacy: This article describes a concept that has been superseded in the course of ongoing development on the Organic Design wiki. Please do not develop this any further or base work on this concept, this is only useful for a historic record of work done. You may find a link to the currently used concept or function in this article, if not you can contact the author to find out what has taken the place of this legacy item.
|
|
<?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
if (!defined('MEDIAWIKI')) die('Not an entry point.');
define('TREEVIEW_VERSION','3.6.2, 2007-09-02');
# Set any unset images to default titles
if (!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';
# Keep track of JavaScript added to page to avoid doubleups
if (!isset($wgJS)) $wgJS = array();
$wgTreeViewMagic = "tree"; # the parser-function name for trees
$wgExtensionFunctions[] = 'wfSetupTreeView';
$wgHooks['LanguageGetMagic'][] = 'wfTreeViewLanguageGetMagic';
$wgExtensionCredits['parserhook'][] = array(
'name' => 'Treeview',
'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' => TREEVIEW_VERSION
);
class TreeView {
var $version = TREEVIEW_VERSION;
var $width = 16;
var $token = '@@@';
var $id = 1;
var $js = 0;
var $info;
var $args;
# Constructor
function TreeView($magic) {
global $wgParser,$wgHooks,$wgTreeViewImages;
$this->info = array();
$this->args = array();
# Set hooks
$wgParser->setFunctionHook($magic,array($this,'Tree'));
$wgParser->setHook('TreeViewRowStart',array($this,'RowStart'));
$wgParser->setHook('TreeViewRowEnd',array($this,'RowEnd'));
# Convert image titles to file paths and obtain pixel width of items
foreach ($wgTreeViewImages as $k => $v) {
$title = Title::newFromText($v,NS_IMAGE);
$image = Image::newFromTitle($title);
if ($image && $image->exists()) {
$wgTreeViewImages[$k] = $image->getURL();
if ($k == 'plus') $this->width = $image->getWidth();
}
}
# Obtain the width of tree items (use 16px as default if unobtainable)
}
# Restructure recursive trees to single root trees surrounded by $magic tags
function Tree(&$parser) {
$args = array();
foreach (func_get_args() as $arg) if (!is_object($arg)) {
if (preg_match('/^(.+?)=(.+)$/',$arg,$match)) $args[$match[1]] = $match[2]; else $args[] = $arg;
}
$text = $args[0];
$tree = '';
$token = $this->token;
$ver = $this->version;
$id = uniqid();
if (count($parser->mTemplatePath)) $tree = "*O$token\n$text\n*C$token";
elseif (preg_match_all("/^(\\*+)(.$token)? *(.*?) *$/m",$text,$match)) {
$this->args[$id] = $args;
$this->info[$id] = array();
$nest = array();
$ld = '';
$row = -1;
foreach ($match[1] as $i => $indent) {
if ($sub = $match[2][$i]) $sub == "O$token" ? $nest[] = substr($ld,0,-1) : array_pop($nest);
elseif ($item = $match[3][$i]) {
$this->info[$id][++$row] = strlen($indent.join('',$nest))-1;
$tree .= "<TreeViewRowStart>$id,$row</TreeViewRowStart>$item<TreeViewRowEnd/>\n";
}
$ld = $indent;
}
$tree = "<table class='tree-view' id='tv$id' title='Extension:Treeview (ver $ver)'>\n$tree</table>";
}
return $tree;
}
# Convert each row into HTML
function RowStart($text,$argv,&$parser) {
global $wgTreeViewImages;
list($id,$row) = split(',',$text);
$args = $this->args[$id];
$info = $this->info[$id];
$width = $this->width;
$depth = $info[$row];
$next = isset($info[$row+1]) ? $info[$row+1] : 0;
$plus = isset($args['plus']) ? $args['plus'] : $wgTreeViewImages['plus'];
$minus = isset($args['minus']) ? $args['minus'] : $wgTreeViewImages['minus'];
$opened = isset($args['opened']) ? $args['opened'] : $wgTreeViewImages['opened'];
$closed = isset($args['closed']) ? $args['closed'] : $wgTreeViewImages['closed'];
$spacer = isset($args['spacer']) ? $args['spacer'] : $wgTreeViewImages['spacer'];
$doc = isset($args['doc']) ? $args['doc'] : $wgTreeViewImages['doc'];
$default = isset($args['openlevels']) ? $args['openlevels'] : 0;
$show = $depth > $default ? ' style="display:none"' : '';
if ($depth >= $default) { $open = $plus; $icon = $closed; } else { $open = $minus; $icon = $opened; }
if ($depth >= $next) { $open = "<img src='$spacer' width='$width'/>"; $icon = $doc; }
else $open = "<a href='javascript:toggleTreeviewItem(\"$id\",$row)'><img id='tvi$id$row' src='$open'/></a>";
return "<tr$show class='tree-row' depth='$depth' id='tvr$id$row'>"
. "<td valign='bottom'><img src='$spacer' width='".($depth*$width)."' height='1'/>$open"
. " <img id='tvf$id$row' src='$icon'/> ";
}
function RowEnd($text,$argv,&$parser) {
return "</td></tr>\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['TreeView'])) return;
$wgJS['TreeView'] = true;
$plus = $wgTreeViewImages['plus'];
$minus = $wgTreeViewImages['minus'];
$opened = $wgTreeViewImages['opened'];
$closed = $wgTreeViewImages['closed'];
$spacer = $wgTreeViewImages['spacer'];
$doc = $wgTreeViewImages['doc'];
$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);
fld.setAttribute("src",close ? closed : opened);
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);
}
}
}</script>');
}
}
# Called from $wgExtensionFunctions array when initialising extensions
function wfSetupTreeView() {
global $wgTreeView,$wgTreeViewMagic,$wgVersion;
$wgTreeView = new TreeView($wgTreeViewMagic);
$wgTreeView->addJS(); # Make code unconditional for now due to parser caching
}
# Needed in MediaWiki >1.8.0 for magic word hooks to work properly
function wfTreeViewLanguageGetMagic(&$magicWords,$langCode = 0) {
global $wgTreeViewMagic;
$magicWords[$wgTreeViewMagic] = array(0,$wgTreeViewMagic);
return true;
}
?>