Memory Alpha

Bp/interactive tree script

< User:Bp

39,811pages on
this wiki

I, and others, didn't like the scroll boxes used to shorten the "Appearances" and "References" sections. User:Cid Highwind proposed a way to hide the sections until the user selected to show them (see Forum:Appearances section - suggestion), and I took this idea a little further and wrote a script that allows the trees that contain this information to be collapsed and expanded, while also counting the sub-items so that some meaningful information is immediately available.

Originally, I wrote this to be used only for appearances, but it can be used for other trees as well.

Usage Edit

To use the script, enclose the tree with:

<div class="appear [...]">
* Item
** Item
*** Item
*** Item
** Item
** Item

The class can be used with other classes, like noicon. There is another special class, nocount, which will not add a count of the sub-items to the end of the branches.

Tweaks Edit

If you don't want the script to run, add this line to your User:/monobook.js:

interactiveTrees = 0;

If you want to have the scroll boxes, add this line to your User:/monobook.css:

.appear{ overflow:auto; height:230px; width:75%; float:left; }

To set the minum number of leaves that can be left open, add this line to your User:/monobook.css: (n is the number of leaves)

smallTreeCount = <n>;

To set the string of text that appears at the top of counted lists, add this line to your User:/monobook.css: (put %d where you want the number to appear)

descriptionString = "<s>";

Example Edit

Interactive Non-interactive (source)

Guy Vardaman appearances as Darien Wallace Edit

Pakled appearances Edit

Q appearancesEdit

Guy Vardaman appearances as Darien Wallace Edit

Issues Edit

  • If the user has a languge other than English set in his preferences, the wiki software will serve him Mediawiki:Monobook.js/[that language]. I imagine this is so that the scripts can be multi-language, for example this script might have a different label instead of the English "This list contains %s items." Unfortunately there is no Common.js as there is with Common.css, the script would need to be copied into each language's sub-page. A workaround is being investigated.

Source Edit

The source for the version running on MA is in Mediawiki:common.css and Mediawiki:common.js.

Versions Edit

  • rev 4
    • made the script work nicely with multiple classes
    • added "nocount" class
  • rev 3
    • Fix a bug noticed by User:Renegade54 where the shortening of the page after it is reformated could cause it to lose the place of the named anchor
      • reverted and re-revised (with help from User:Splarka):
        • Firefox fires an onload event when window.location = window.location.hash; So, tried it a different way.
        • Fixed a bug in Safari where the control links were invisible. Safari still has the bug Renegade54 mentioned, because Safari is not very smart. It returns the # with window.location.hash, but it believes that it is part of the bookmark name if you use it.
  • rev 2
    • Changed the label from "%d appearances." to "This list contains %d items." so that the script can be used for other trees besides appearances.
    • Now includes ordered lists (<ol>) in the tree
    • var smallTreeCount now holds the limit number of leaves that cause the tree to be completely visible by default, so it can be set by users in User:/monobook.js
  • rev 1
    • Removed a debug function that I used while writing, but doesn't do anything on MA
  • first release
    • First time uploaded

CSS Edit

.hiddenlist { display:none; }
.visiblelist { display:block; }

.listexpand { text-decoration: none; color: #66BBFF; }
.listexpand:hover { text-decoration: underline; color: #66BBFF; }

JS Edit

// Start "Hidden appearances section/interactive tree" script; by [[User:Bp]]
// -----
function toggleAppearancesPane(eid) {
	e = document.getElementById(eid);
	if (e) { e.className = (e.className == "hiddenlist") ? "visiblelist" : "hiddenlist"; }

function showAppearancesPane(eid) {
	e = document.getElementById(eid);
	if (e) { e.className = "visiblelist"; }

function hideAppearancesPane(eid) {
	e = document.getElementById(eid);
	if (e) { e.className = "hiddenlist"; }
// -----

var tree = 0;
var pane = 0;
var paneListForThisTree = new Array();
var descriptionString = new String("This list contains %d items."); //%d is where the number of items is inserted

var smallTreeCount = 8; // less leaves than this, the tree will be open at first
var interactiveTrees = 1; // set this to 0 in user.js to turn this off

function button(text,onclick,cls) {
	var b = document.createElement('a');
	b.innerHTML = text;
	b.className = cls;
	return b;

function recursiveCountAndMark(e, depth, nocount) {
	var si = e.firstChild;
	var total = 0;
	while(si) {
		var tn = (si.tagName) ? si.tagName.toLowerCase() : '';
		if (tn == "li") { total++; }
		var subtotal = recursiveCountAndMark(si, depth+1, nocount);
		if (tn == "ul" || tn == "ol") {
			if (depth > 1) { = "Pane" + pane++;
				si.className = "hiddenlist";

				si.parentNode.insertBefore(document.createTextNode('('), si);
				si.parentNode.insertBefore(button( (nocount) ? "+/-" : subtotal, "toggleAppearancesPane(\"""\")", "listexpand"), si);
				si.parentNode.insertBefore(document.createTextNode(')'), si);
				total--; // don't count the li that this ul/ol is in
			} else {
				// we are finished and this is the top ul/ol
				if (subtotal < smallTreeCount) { // this small enough they can be visible right away
					for (var i=0;i<paneListForThisTree.length;i++) {
				var allonexec = '{';
				var alloffexec = '{';
				for (var i=0;i<paneListForThisTree.length;i++) {
					allonexec += "showAppearancesPane(\""+paneListForThisTree[i]+"\"); ";
					alloffexec += "hideAppearancesPane(\""+paneListForThisTree[i]+"\"); ";
				allonexec += '}'; alloffexec += '}';

				var ds = (nocount) ? "" : descriptionString.replace(/\%d/g, subtotal);

				si.parentNode.insertBefore(document.createTextNode(ds + ' ('), si);
				si.parentNode.insertBefore(button("show all", allonexec, "listexpand"), si);
				si.parentNode.insertBefore(document.createTextNode(' | '), si);
				si.parentNode.insertBefore(button("hide all", alloffexec, "listexpand"), si);
				si.parentNode.insertBefore(document.createTextNode(')'), si);
		total += subtotal;
		si = si.nextSibling;
	return total;

function doAppearancesTrees() {
	if (!interactiveTrees) { return; }

	var divs = document.getElementsByTagName("div");
	for (var i = 0; i < divs.length; i++) {
		if (divs[i].className.match(/\bappear\b/)) {
			recursiveCountAndMark(divs[i], 0, (divs[i].className.match(/\bnocount\b/)) ? 1 : 0);
			paneListForThisTree = new Array();

	// fix a bug noticed by renegade54
	// jump to the named anchor again
	if (window.location.hash && tree > 0) {
		// still won't work 100% in safari and khtml
		if (navigator.userAgent.indexOf("MSIE") != -1) {
			window.location = window.location.hash; // -- causes Firefox to fire onload events
		} else {
			window.location.hash = window.location.hash;


hookEvent("load", doAppearancesTrees);

On other wikis Edit

A couple people asked to use it one their wikis, which is nice. I'm glad it's useful to someone. As I explained to them, it is CC-by-nc 2.5, like all of MA, so most wiki's that are GFDL or GPL or whatever need to make that explicit, and comply. Also, tell me so I can put it on the list.

Around Wikia's network

Random Wiki