Difference between revisions of "Extension talk:Treeview5.php"

From Organic Design wiki
m (How it works)
(update)
Line 1: Line 1:
 
{{ext-talk-msg|Tree view}}
 
{{ext-talk-msg|Tree view}}
 
Treeview5.1 is a new approach to the core recursive bullet-list code which doesn't require any voodoo, and should be compatible with all MediaWiki versions including 1.12.
 
Treeview5.1 is a new approach to the core recursive bullet-list code which doesn't require any voodoo, and should be compatible with all MediaWiki versions including 1.12.
 +
 +
== Parameters ==
 +
*'''root:'''
 +
*'''id:'''
 +
*'''openlevels:'''
 +
 +
== Livelets ==
 +
The new tree doesn't currently work when included via AJAX because the code in the response is not executed. The livelets code should be updated to execute script tags within responses.
  
 
== How it works ==
 
== How it works ==
Line 21: Line 29:
 
The ''expandTree'' method (the ''#tree'' parser-function hook) then converts all the matched rows into the following general structure:
 
The ''expandTree'' method (the ''#tree'' parser-function hook) then converts all the matched rows into the following general structure:
 
  1{uniq}-{id}-{depth}-{item}2{uniq}
 
  1{uniq}-{id}-{depth}-{item}2{uniq}
Where ''uniq'' is a unique string representing treeview's in general, ''id'' is a unique string representing the current tree, ''depth'' is the depth of the current row with respect to the current tree root, and ''item'' is the wikitext within the current row. The information is "protected" from the parser merely by the fact that it contains no markup characters, but this could be made more robust later.
+
Where ''uniq'' is a unique string representing treeview's in general, ''id'' is a unique string representing the current tree, ''depth'' is the depth of the current row with respect to the current tree root, and ''item'' is the wikitext within the current row. Each row is converted to the new structured format by the private ''formatRow'' method. The information is "protected" from the parser merely by the fact that it contains no markup characters, but this could be made more robust later.
  
 
After the resulting structure has been parsed, the content portions will have been converted into HTML and the information portions remain unchanged. Below is the HTML source of the above example after parsing and printed at the start of the ''renderTree'' method (the ''ParserAfterTidy'' hook).
 
After the resulting structure has been parsed, the content portions will have been converted into HTML and the information portions remain unchanged. Below is the HTML source of the above example after parsing and printed at the start of the ''renderTree'' method (the ''ParserAfterTidy'' hook).
 
<pre>
 
<pre>
1tv47c8d2444a04d-47c8d2447a3e7-1-<a href="/wiki/index.php?title=Toplevl&amp;action=edit" class="new" title="Toplevl">toplevl</a>2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6dadf4-0-<a href="/wiki/index.php?title=Toplevl&amp;action=edit" class="new" title="Toplevl">toplevl</a>2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a3e7-2-bar2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6dadf4-1-bar2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a3e7-3-baz2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6dadf4-2-baz2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a3e7-1-foo2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6dadf4-0-foo2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a3e7-2-<a href="/Bar" title="Bar">Bar</a>2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6dadf4-1-<a href="/Bar" title="Bar">Bar</a>2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a3e7-3-1tv47c8d2444a04d-47c8d244781d7-1-<a href="/Foo" title="Foo">Foo</a>2tv47c8d2444a04d2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6dadf4-2-1tv47cb2fd61165f-47cb2fd6da03a-0-<a href="/Foo" title="Foo">Foo</a>2tv47cb2fd61165f2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d244781d7-2-bar2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6da03a-1-bar2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d244781d7-3-baz2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6da03a-2-baz2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d244781d7-1-foo2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6da03a-0-foo2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d244781d7-2-<a href="/Bar" title="Bar">Bar</a>2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6da03a-1-biz2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d244781d7-2-<a href="/wiki/index.php?title=Baz&amp;action=edit" class="new" title="Baz">Baz</a>2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6da03a-2-1tv47cb2fd61165f-47cb2fd6d9c40-0-<a href="/Bar" title="Bar">bar</a>2tv47cb2fd61165f2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a3e7-2-<a href="/wiki/index.php?title=Baz&amp;action=edit" class="new" title="Baz">Baz</a>2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6d9c40-1-baz2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a3e7-3-1tv47c8d2444a04d-47c8d2447a020-1-<a href="/Bar" title="Bar">bar</a>2tv47c8d2444a04d2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6d9c40-2-biz2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a020-2-baz2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6da03a-1-<a href="/wiki/index.php?title=Baz&amp;action=edit" class="new" title="Baz">Baz</a>2tv47cb2fd61165f
1tv47c8d2444a04d-47c8d2447a020-3-biz2tv47c8d2444a04d
+
1tv47cb2fd61165f-47cb2fd6dadf4-1-<a href="/wiki/index.php?title=Baz&amp;action=edit" class="new" title="Baz">Baz</a>2tv47cb2fd61165f
 +
1tv47cb2fd61165f-47cb2fd6dadf4-2-1tv47cb2fd61165f-47cb2fd6d9c40-0-<a href="/Bar" title="Bar">bar</a>2tv47cb2fd61165f2tv47cb2fd61165f
 +
1tv47cb2fd61165f-47cb2fd6d9c40-1-baz2tv47cb2fd61165f
 +
1tv47cb2fd61165f-47cb2fd6d9c40-2-biz2tv47cb2fd61165f
 
</pre>
 
</pre>
  
The following match and loop will then loop through all the rows no matter what level and extract the values back out
+
The following regular expression is used to create an array, ''$matches'', each item of which contains a list of ''(,$id,$depth,,$icon,$item)'' extracted from the formatted rows in the page.
 
{{code|<php>
 
{{code|<php>
if (preg_match_all("/1$uniq-(.+?)-([0-9]+)-({$uniq}3(.+?){$uniq}4)?(.*?)(?=[12]$uniq)/",$text,$matches,PREG_SET_ORDER)) {
+
preg_match_all("/1$u-(.+?)-([0-9]+)-({$u}3(.+?){$u}4)?(.*?)(?=[12]$u)/",$text,$matches,PREG_SET_ORDER)
foreach ($matches as $n => $row) {
 
list(,$id,$depth,,$icon,$item) = $row;
 
 
</php>}}
 
</php>}}
  
Here is a bullet list of the ''id'', ''depth'' and ''item'' information from the rows when running the above code over the HTML source shown above:
+
Following this extraction of row information into ''$matches'' is a loop that builds a new list called ''$rows'' which contains more detailed information about the rows than ''$matches'', and adjusts the depth values to account for transclused sub-tree's. The ''$rows'' array is a list of ''($id,$depth,$icon,$item,$start)''. ''$id'' is the id of each root-tree, ''$start'' is a boolean indicating whether or not the row is the first in a new tree.
* 47c8d2447a3e7:1,toplevl
 
* 47c8d2447a3e7:2,bar
 
* 47c8d2447a3e7:3,baz
 
* 47c8d2447a3e7:1,foo
 
* 47c8d2447a3e7:2,Bar
 
* 47c8d2447a3e7:3,
 
* 47c8d244781d7:1,Foo
 
* 47c8d244781d7:2,bar
 
* 47c8d244781d7:3,baz
 
* 47c8d244781d7:1,foo
 
* 47c8d244781d7:2,Bar
 
* 47c8d244781d7:2,Baz
 
* 47c8d2447a3e7:2,Baz
 
* 47c8d2447a3e7:3,
 
* 47c8d2447a020:1,bar
 
* 47c8d2447a020:2,baz
 
* 47c8d2447a020:3,biz
 
  
The content of the loop then converts the list into JavaScript statements which result in a ''dTree''. The correct recursive depths are calculated by adding the last depth to the current if its ''id'' is a new one.
+
The main ''dTree'' JavaScript can then be constructed by looping through the ''$rows'' list and converting ordered depth-based information to the parent/child format required by ''dTree''. The index into the $rows'' array is used as the ''dTree'' node identifiers.
 +
 
 +
=== Root tree's and sub-tree's ===
 +
One of the difficulties with this extension has been to do with the difficulty in assessing from within a parser-function whether or not it's at the root level in terms of transclusion-depth. The new version doesn't require voodoo to determine this, it instead does the following pattern match on all the formatted rows in the page after wiki-parsing is complete (in the ''ParserAfterTidy'' hook).
 +
{{code|<php>
 +
if (!preg_match_all("/-1$u-(.+?)-/",$text,$subs)) $subs = array(1 => array());
 +
</php>}}
 +
This results in an array called ''$subs[1]'' which contains all the tree id's which are not transcluded. It does this by checking which
 +
rows have a preceding minus symbol, since top level ones will all be preceded by a ''p'' tag or a line start (see the example output of formatted rows above). An id is at root level if it is not in the ''$subs[1]'' array. This way is not as robust as it could be, and is also more computationally intensive than it could be.
  
 
== See also ==
 
== See also ==
 
*[http://www.destroydrop.com/javascripts/tree/ dTree] (javascript based)
 
*[http://www.destroydrop.com/javascripts/tree/ dTree] (javascript based)
 
*[http://www.silpstream.com/blog/wp-dtree/  Slipstream wp-Dtree] (php based)
 
*[http://www.silpstream.com/blog/wp-dtree/  Slipstream wp-Dtree] (php based)

Revision as of 23:22, 2 March 2008

Info.svg This talk page pertains specifically to the development of this extension. For more general discussion about bugs and usage etc, please refer to the mediawiki.org talk page at MW:Extension talk:Tree view

Treeview5.1 is a new approach to the core recursive bullet-list code which doesn't require any voodoo, and should be compatible with all MediaWiki versions including 1.12.

Parameters

  • root:
  • id:
  • openlevels:

Livelets

The new tree doesn't currently work when included via AJAX because the code in the response is not executed. The livelets code should be updated to execute script tags within responses.

How it works

The initial problem was how to write a parser-function which could generate a tree which could be composed of other transcluded tree's (i.e. parser-functions which are recursively executed forming a larger whole structure together). This seemed impossible since there are no MediaWiki properties available in the environment which reveal the current depth that the parser-function expansion is operating at.

But after thinking about the problem more closely, it turns out that the tree can be constructed without depth information by converting each tree row into a new format containing depth and tree id information which is protected from wiki-parsing. This information can then be converted into tree JavaScript after the parser has finished in the ParserAfterTidy hook.

Here is the wikitext of an example tree which includes two transcluded tree's

*[[toplevl]]
**bar
***baz
*foo
**[[Bar]]
***{{:Foo}}
**[[Baz]]
***{{:Bar}}

The expandTree method (the #tree parser-function hook) then converts all the matched rows into the following general structure:

1{uniq}-{id}-{depth}-{item}2{uniq}

Where uniq is a unique string representing treeview's in general, id is a unique string representing the current tree, depth is the depth of the current row with respect to the current tree root, and item is the wikitext within the current row. Each row is converted to the new structured format by the private formatRow method. The information is "protected" from the parser merely by the fact that it contains no markup characters, but this could be made more robust later.

After the resulting structure has been parsed, the content portions will have been converted into HTML and the information portions remain unchanged. Below is the HTML source of the above example after parsing and printed at the start of the renderTree method (the ParserAfterTidy hook).

1tv47cb2fd61165f-47cb2fd6dadf4-0-<a href="/wiki/index.php?title=Toplevl&action=edit" class="new" title="Toplevl">toplevl</a>2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6dadf4-1-bar2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6dadf4-2-baz2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6dadf4-0-foo2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6dadf4-1-<a href="/Bar" title="Bar">Bar</a>2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6dadf4-2-1tv47cb2fd61165f-47cb2fd6da03a-0-<a href="/Foo" title="Foo">Foo</a>2tv47cb2fd61165f2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6da03a-1-bar2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6da03a-2-baz2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6da03a-0-foo2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6da03a-1-biz2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6da03a-2-1tv47cb2fd61165f-47cb2fd6d9c40-0-<a href="/Bar" title="Bar">bar</a>2tv47cb2fd61165f2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6d9c40-1-baz2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6d9c40-2-biz2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6da03a-1-<a href="/wiki/index.php?title=Baz&action=edit" class="new" title="Baz">Baz</a>2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6dadf4-1-<a href="/wiki/index.php?title=Baz&action=edit" class="new" title="Baz">Baz</a>2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6dadf4-2-1tv47cb2fd61165f-47cb2fd6d9c40-0-<a href="/Bar" title="Bar">bar</a>2tv47cb2fd61165f2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6d9c40-1-baz2tv47cb2fd61165f
1tv47cb2fd61165f-47cb2fd6d9c40-2-biz2tv47cb2fd61165f

The following regular expression is used to create an array, $matches, each item of which contains a list of (,$id,$depth,,$icon,$item) extracted from the formatted rows in the page.

{{{1}}}

Following this extraction of row information into $matches is a loop that builds a new list called $rows which contains more detailed information about the rows than $matches, and adjusts the depth values to account for transclused sub-tree's. The $rows array is a list of ($id,$depth,$icon,$item,$start). $id is the id of each root-tree, $start is a boolean indicating whether or not the row is the first in a new tree.

The main dTree JavaScript can then be constructed by looping through the $rows list and converting ordered depth-based information to the parent/child format required by dTree. The index into the $rows array is used as the dTree node identifiers.

Root tree's and sub-tree's

One of the difficulties with this extension has been to do with the difficulty in assessing from within a parser-function whether or not it's at the root level in terms of transclusion-depth. The new version doesn't require voodoo to determine this, it instead does the following pattern match on all the formatted rows in the page after wiki-parsing is complete (in the ParserAfterTidy hook).

{{{1}}}

This results in an array called $subs[1] which contains all the tree id's which are not transcluded. It does this by checking which rows have a preceding minus symbol, since top level ones will all be preceded by a p tag or a line start (see the example output of formatted rows above). An id is at root level if it is not in the $subs[1] array. This way is not as robust as it could be, and is also more computationally intensive than it could be.

See also