Help-style indexing

  • Apache
  • Mandrakelinux

Most help files can be accessed via an index. As you type in keywords, the index jumps to the first article that matches what you are typing. You can scroll through the index and press Enter or double-click the index entry and load the help article.

This article explains how to create this functionality for MediaWiki.

Updates for MediaWiki 1.4.4 edit

I'm trying for minimal changes to the original scripts in 1.4.4.

LocalSettings.php edit

First, the code for activating the popup is in LocalSettings.php where you would normally modify the navigation urls. Add a line for your index as your normally would ( see the FAQ page), but make the href code like this:

$wgNavigationLinks = array (
	array( 'text'=>'mainpage', etc... etc... etc...),
	array( 'text'=>'index', 	'href'=>'<a href="http://yoursite.com/images/articleindex.htm" onClick="window.open(\'http://yoursite.com/images/articleindex.htm\',\'wikiindex\',\'width=244,height=480,resizable=no,scrollbars=no,toolbar=no,location=no,directories=no,status=no,menubar=no,copyhistory=no\'); return false;">'));

This will generate a popup window when the Index link is clicked. I used the standard MediaWiki:Index method of naming the link.

Now to properly insert this coding into the Quickbar without the normal HTML encoding changes and such, you need to make a small change in two scripts - /includes/SkinTemplate.php and /skins/MonoBook.php.

SkinTemplate.php edit

Modify the buildNavigationUrls() function to check for the href element of the array to start with '<a href'. When it sees such an element, just store that whole set of text as the href element and don't try to turn it into a URL.

if ($text != '-') {
	$dest = wfMsgForContent( $link['href'] );
	wfProfileIn( "$fname-{$link['text']}2" );
	if (substr($link['href'],0,7) == "<a href")
		$dest_url = $link['href'];
	else
		$dest_url = $this->makeInternalOrExternalUrl( $dest );
        $result[] = array('text' => $text,
                          'href' => $dest_url,
		          'id' => 'n-'.$link['text']);

MonoBook.php edit

The need in /skins/MonoBook.php is similar - you need to let the code flow through without modification. Find the <div section with id="p-nav". Test for the same <a href text in the nav link and let it flow through without modification:

<?php foreach($this->data['navigation_urls'] as $navlink) { ?>
  <li id="<?php echo htmlspecialchars($navlink['id'])?>"><?php
 if (substr($navlink['href'],0,7) == "<a href")
 	echo $navlink['href'];
 else {
 	echo '<a href="' . htmlspecialchars($navlink['href']) . '">';
 } ?><?php echo htmlspecialchars($navlink['text']) ?></a></li><?php } ?>

Most of the instructions listed in the 1.3 section below are still applicable, but I'll be updating this page as I update 1.4.4 and try to avoid modifying the default scripts as much as possible. --MHart 19:49, 18 May 2005 (UTC)[reply]

Original for MediaWiki 1.3 edit

First, edit includes/SpecialPage.php and add the BuildIndex.php page that you'll be creating. Find this entry:

$wgSpecialPages = array(...

and add at the bottom:

"BuildIndex"         => new SpecialPage( "BuildIndex" )

Make sure you add a , comma after the last entry before adding BuildIndex. Next you'll need to create the special page. I copied SpecialAllpages.php since it has much of the code already. Change the name to SpecialBuildIndex.php and start hacking!

  • Comment out the if ($sections) part
  • Modify the first "SELECT cur_title stuff to NOT limit - that way you get it all.
$sql = "SELECT cur_title $fromwhere $order";
  • Then create a variable to store the HTML you'll be building for the index:
$IndexPage = "";
  • Then there's lots of JavaScript to create to make it all work properly. Just download my copy from here to get it all. What the JavaScript does is:
    1. Keep the focus on the index page
    2. Handles up arrow, down arrow, page up, and page down and translates those to actions against the list of articles. This is so that you don't have to leave the input box to scroll - basically for convenience sake.
    3. Handles a double-click. JavaScript only has single clicks, so this uses a boolean flag and a timeout to see if the button was clicked twice within 300 milliseconds. If so, it assumes a double click and loads the page.
    4. Searches for matches in the list as you type
    5. Navigates to the appropriate wiki page
  • Important note
    • The reason navigation goes to the right page is because I added a line in index.php that names the frame, right before if ( "" == $title && "delete" != $action ) {
#MHART - so that the popup index will work
$wgOut->addHTML("<script language='javascript'>self.name='ilabwiki';</script>");
    • Then when I do the window.open('url','ilabwiki') target thing, it won't open a brand new window.
  • Then there's a short bit of scripting to create the list of articles:
$IndexPage .= $toadd;
$wgOut->addHTML($toadd);
$toadd = "<select name='urls' id='urls' size=25 onKeyup='SelectKey(event)'
          onMouseup='DoubleClick()'>" . "\n";
$IndexPage .= $toadd;
$wgOut->addHTML($toadd);

while ($s = wfFetchObject( $res )) {
  $toadd = "<option>" . str_replace( "_", " ", $s->cur_title ) . "</option>" . "\n";
  $IndexPage .= $toadd;
  $wgOut->addHTML($toadd);
}
$toadd = "</select></form></body></html>";
$IndexPage .= $toadd;
$wgOut->addHTML($toadd);

#MHART - you could use script path vars and such here, but I'm lazy
#        and didn't want to find them
$IndexFile = "/var/www/html/images/articleindex.htm";
$IndexFileHandle = fopen($IndexFile, 'w');
fwrite($IndexFileHandle, $IndexPage);
fclose($IndexFileHandle);
  • And you're almost done! Just add a link to the index page in your navigation pane (templates/xhtml_slim.pt)
<li id="n-index"><a href=""
  onClick="window.open('http://yoursite.com/images/articleindex.htm',
  'wikiindex','width=244,height=480,resizable=no,' + 
  'scrollbars=no,toolbar=no,location=no,directories=no,' + 
  'status=no,menubar=no,copyhistory=no'); return false;">Index</a></li>
  • I also create a crontab entry to generate the index once per day - that way a big site won't burden the sql engine with constant loop lookups, rather cache the index page and update it daily.

Enjoy! --MHart 19:57, 11 May 2005 (UTC)[reply]