Difference between revisions of "Extension:Treeview5.php"
(addJS put back in, double loading was due to Extension:DTree) |
(remove flags array from returned tag function results) |
||
| Line 5: | Line 5: | ||
# - Author: http://www.organicdesign.co.nz/nad | # - Author: http://www.organicdesign.co.nz/nad | ||
# - Started: (Version5) 2007-10-24{{Category:Extensions in progress|Treeview5}} | # - Started: (Version5) 2007-10-24{{Category:Extensions in progress|Treeview5}} | ||
| − | + | ||
if (!defined('MEDIAWIKI')) die('Not an entry point.'); | if (!defined('MEDIAWIKI')) die('Not an entry point.'); | ||
| − | + | ||
define('TREEVIEW5_VERSION','5.0.0, 2007-10-24'); | define('TREEVIEW5_VERSION','5.0.0, 2007-10-24'); | ||
| − | + | ||
# 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(); | ||
| Line 23: | Line 23: | ||
if (!isset($wgTreeViewImages['node'])) $wgTreeViewImages['node'] = 'Node.gif'; | if (!isset($wgTreeViewImages['node'])) $wgTreeViewImages['node'] = 'Node.gif'; | ||
if (!isset($wgTreeViewImages['last'])) $wgTreeViewImages['last'] = 'Lastnode.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(); | ||
| − | + | ||
$wgTreeView5Magic = "tree"; # the parser-function name for trees | $wgTreeView5Magic = "tree"; # the parser-function name for trees | ||
$wgTreeViewIndent = 0; # the number of pixels each level indents by (0 means doc-icon width) | $wgTreeViewIndent = 0; # the number of pixels each level indents by (0 means doc-icon width) | ||
| Line 32: | Line 32: | ||
$wgExtensionFunctions[] = 'wfSetupTreeView5'; | $wgExtensionFunctions[] = 'wfSetupTreeView5'; | ||
$wgHooks['LanguageGetMagic'][] = 'wfTreeView5LanguageGetMagic'; | $wgHooks['LanguageGetMagic'][] = 'wfTreeView5LanguageGetMagic'; | ||
| − | + | ||
$wgExtensionCredits['parserhook'][] = array( | $wgExtensionCredits['parserhook'][] = array( | ||
'name' => 'Treeview5', | 'name' => 'Treeview5', | ||
| Line 40: | Line 40: | ||
'version' => TREEVIEW5_VERSION | 'version' => TREEVIEW5_VERSION | ||
); | ); | ||
| − | + | ||
class TreeView5 { | class TreeView5 { | ||
| − | + | ||
var $version = TREEVIEW5_VERSION; | var $version = TREEVIEW5_VERSION; | ||
var $width = 16; | var $width = 16; | ||
| Line 48: | Line 48: | ||
var $uid = ''; | var $uid = ''; | ||
var $js = 0; | var $js = 0; | ||
| − | + | ||
# Constructor | # Constructor | ||
function TreeView5() { | function TreeView5() { | ||
| Line 67: | Line 67: | ||
$wgParser->setFunctionHook($wgTreeView5Magic,array($this,'Tree')); | $wgParser->setFunctionHook($wgTreeView5Magic,array($this,'Tree')); | ||
} | } | ||
| − | + | ||
# Restructure recursive trees into a single bullet list surrounded by internal treeview5 tags | # Restructure recursive trees into a single bullet list surrounded by internal treeview5 tags | ||
function Tree(&$parser) { | function Tree(&$parser) { | ||
| Line 92: | Line 92: | ||
function treeview($text,$argv,&$parser) { | function treeview($text,$argv,&$parser) { | ||
global $wgTreeViewImages; | global $wgTreeViewImages; | ||
| − | + | ||
$id = $argv['id']; | $id = $argv['id']; | ||
$uid = $this->uid; | $uid = $this->uid; | ||
| Line 124: | Line 124: | ||
# Parse 1 - link syntax etc parsed | # Parse 1 - link syntax etc parsed | ||
$counter = 0; | $counter = 0; | ||
| − | + | ||
$uid = "a"; | $uid = "a"; | ||
foreach ($matches as $row) { | foreach ($matches as $row) { | ||
| Line 137: | Line 137: | ||
$dtree .= "document.write($uid);\n"; | $dtree .= "document.write($uid);\n"; | ||
print "DTREE=>\n$dtree"; | print "DTREE=>\n$dtree"; | ||
| − | + | ||
# Parse 2 | # Parse 2 | ||
# for ($row = count($rows)-1; $row >= 0; $row--) { | # for ($row = count($rows)-1; $row >= 0; $row--) { | ||
| Line 186: | Line 186: | ||
# return "<table cellpadding=0 cellspacing=0 class='tree-view' id='tv$id' title='Extension:Treeview (ver $ver)'>\n$tree</table>"; | # return "<table cellpadding=0 cellspacing=0 class='tree-view' id='tv$id' title='Extension:Treeview (ver $ver)'>\n$tree</table>"; | ||
| − | + | return("<script>\n<!--\n$dtree-->\n</script>"); | |
# Return result with available parser flags | # Return result with available parser flags | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
Revision as of 20:53, 23 February 2008
<?php
- MediaWiki Treeview ExtensionTemplate:Php
In computer programming, "Voodoo", or "Magic" refers to techniques that are secret or not widely known, and may be deliberately kept secret. The Jargon File makes a distinction between "deep magic", which refers to code based on esoteric theoretical knowledge; "black magic" (voodoo), which refers to code based on techniques that appear to work but which lack a theoretical explanation; and "heavy wizardry", which refers to code based on obscure or undocumented intricacies of particular hardware or software.
At Organic Design the most common of these is extending an instance's class at runtime after it has been instantiated, a technique that can be used to provide additional hooks into existing code without requiring modification of code-base files. Another is reading in a class file, declaring it under a different name, then sub-classing that with a new class of the original name - that way the environment uses the new extended class thinking it's the original one.
See also
- Adding a variable to a class instance at runtime - demonstrated in many different languages
- - 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: (Version5) 2007-10-24Category:Extensions in progress
if (!defined('MEDIAWIKI')) die('Not an entry point.');
define('TREEVIEW5_VERSION','5.0.0, 2007-10-24');
- 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();
$wgTreeView5Magic = "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[] = 'wfSetupTreeView5'; $wgHooks['LanguageGetMagic'][] = 'wfTreeView5LanguageGetMagic';
$wgExtensionCredits['parserhook'][] = array( 'name' => 'Treeview5', 'author' => 'User:Nad', 'url' => 'http://www.mediawiki.org/wiki/Extension:Treeview', 'description' => 'Extends the wiki parser to allow bullet and numbered lists to work with recursion and optionally allows these to be rendered as collapsible trees', 'version' => TREEVIEW5_VERSION );
class TreeView5 {
var $version = TREEVIEW5_VERSION; var $width = 16;
- var $uniq = array();
var $uid = ; var $js = 0;
# Constructor function TreeView5() { global $wgParser,$wgTreeView5Magic,$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($wgTreeView5Magic,array($this,'Tree')); }
# Restructure recursive trees into a single bullet list surrounded by internal treeview5 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.+?-treeview5(.+?)-.+?-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("treeview5$id",array($this,'treeview')); return "<treeview5$id $args>$text</treeview5$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 = ; $dtree = "a = new dTree('a');\n"; # 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 - link syntax etc parsed $counter = 0;
$uid = "a"; foreach ($matches as $row) { list(,$depth,,$icon,$item) = $row; if ($depth > $cols) $lasts[$cols = $depth] = true; $rows[] = array($depth,$icon,$item);
$dtree .= "${uid}.add($counter, " . ($depth-1) . ", '$item');\n"; $counter++; }
$dtree .= "document.write($uid);\n"; print "DTREE=>\n$dtree";
# 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 .= "$fg";
- }
- $lasts[$depth] = false;
# Add the icon and the item content and append a table row to the tree definition
- $td .= "<img id='tvf$id$row' src='$icon'/>";
- $td .= "$item";
- $tree = "<tr$show depth='$depth' id='tvr$id$row'>$td\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 .= "";
- $tree = "$td\n$tree";
- return "\n$tree
";
return("<script>\n\n</script>"); # Return result with available parser flags }
# 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['TreeView5'])) return; $wgJS['TreeView5'] = 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\" src=\"/wiki/extensions/treeview/dtree.js\"></script>\n");
- $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 wfSetupTreeView5() { global $wgTreeView5; $wgTreeView5 = new TreeView5(); $wgTreeView5->addJS(); # Make code unconditional for now due to parser caching }
- Needed in MediaWiki >1.8.0 for magic word hooks to work properly
function wfTreeView5LanguageGetMagic(&$magicWords,$langCode = 0) { global $wgTreeView5,$wgTreeView5Magic; $magicWords[$wgTreeView5Magic] = array(0,$wgTreeView5Magic); return true; } ?>



