Extension:Accordion
|
|
This extension stores its code inside a wiki page. Please be aware that MediaWiki developers do not review or keep track of extensions that put their code on the wiki.
|
|
|
WARNING: the code or configuration described here poses a major security risk.
Problem: Vulnerable to Cross-site scripting attacks, because it passes user input directly to the browser. This may lead to user accounts being hijacked, among other things. |
|
Accordion Release status: beta |
|||
|---|---|---|---|
| Implementation | Tag | ||
| Description | enable "accordion pagination" of sections of a page | ||
| Author(s) | Robert Hänel (RoberthaenelTalk) | ||
| Last version | 0.1 (12/22/2010) | ||
| MediaWiki | 1.16 | ||
| License | No license specified | ||
| Download | #Source | ||
| Example | Simple Demo and the corresponding Wikitext | ||
|
|||
|
|||
|
Check usage (experimental) |
|||
Contents |
[edit] Abstract
This extension might be useful for navigating large pages by hiding all but the current section using Java Script. It was inspired by this article.
[edit] Installation
Copy the Sources into two files named extensions/Accordion/Accordion.php and extensions/Accordion/Accordion.js and add the following line to your LocalSettings.php:
require_once( "$IP/extensions/Accordion/Accordion.php" );
[edit] Usage
Put the following tag around the content you want to enable for accordion pagination:
<accordion> content </accordion>
This will put any text between two consecutive headers (default: <h2> or == Header ==) into a hideable div. The different sections can be navigated by clicking on the respective headers or by using the previous and next links.
The following optional parameter can be provided in the <accordion> tag:
| Parameter | Default | Explanation |
|---|---|---|
| level | 2 | Level of the headers marking the different section of the content. Must be a number between 1 and 6. |
[edit] Source
[edit] Accordion.php
<?php /** * Accordion extension -- accordion pagination with the <accordion> tag * * @file * @version 0.1 * @author Robert Hänel * @link http://www.mediawiki.org/wiki/Extension:Accordion Documentation */ if ( !defined( 'MEDIAWIKI' ) ) { die( 'This is not a valid entry point.' ); } // Extension credits that will show up on Special:Version $wgExtensionCredits['parserhook'][] = array( 'name' => 'Accordion', 'version' => 0.1, 'author' => 'Robert Hänel', 'url' => 'http://www.mediawiki.org/wiki/Extension:Accordion', 'description' => 'Accordion pagination with the <code><accordion></code> tag' ); // Register hooks $wgHooks['BeforePageDisplay'][] = 'wfAccordionOnBeforePageDisplay'; $wgHooks['ParserFirstCallInit'][] = 'wfAccordionRegisterHook'; /** * Register the <accordion> hook with the parser. * * @param $parser Object: instance of Parser * @return Boolean: true */ function wfAccordionRegisterHook( &$parser ) { $parser->setHook( 'accordion', 'wfAccordionCallback' ); return true; } /** * Add Accordion.js to the page output. * * @param $out Object: instance of OutputPage * @return Boolean: true */ function wfAccordionOnBeforePageDisplay( &$out ) { global $wgScriptPath; $out->addScriptFile( $wgScriptPath . '/extensions/Accordion/Accordion.js' ); return true; } /** * Actually does all the parsing for us; called by wfAccordionRegisterHook. */ function wfAccordionCallback( $input, $args, &$parser ) { $level = $args['level']; if ( !isset( $level ) ) { $level = 2; } $result = '<script type="text/javascript">var acc_hlevel = ' . $level . ';</script>'; $result .= '<div id="acc_container">'; $result .= $parser->recursiveTagParse( $input ); $result .= '</div>'; return $result; }
[edit] Accordion.js
// addHandler function is defined in wikibits.js addHandler( 'load', onloadListener ); function onloadListener() { if ( typeof( acc_hlevel ) !== 'undefined' ) { accordion_init( acc_hlevel ); } } // @todo FIXME: this needs a different name in order not to conflict with // jQuery's $ alias function $( id ) { return document.getElementById( id ); } function in_array( arr, val ) { for ( i = 0; i < arr.length; i++ ) { if ( arr[i] == val ) { return 1; } } return 0; } function scrollToElem( elem ) { var pos = 0; while( elem != null ) { pos += elem.offsetTop; elem = elem.offsetParent; } window.scrollTo( 0, pos ); } function accordion_init( hlevel ) { var i = 0; /* skip adding elements to the current content-div until we get to the next h<hlevel> */ var ignore = true; var headerNum = 0; var hname = 'H' + hlevel; var ignoreElem = []; for ( i = 1; i < hlevel; i++ ) { ignoreElem.push( ( 'H' + i ) ); } i = 0; while ( $( 'acc_container' ).childNodes.length > i ) { var node = $( 'acc_container' ).childNodes[i]; if ( node.nodeName == hname ) { if ( headerNum != 0 ) { var nextdiv = document.createElement( 'div' ); nextdiv.className = 'acc_next'; var next = document.createElement( 'a' ); next.className = 'acc_link'; next.innerHTML = 'next>>'; next.onclick = nextClicked; nextdiv.appendChild( next ); $( 'content-' + headerNum ).appendChild( nextdiv ); } headerNum++; node.id = 'header-' + headerNum; if ( ignore == true ) { node.className = 'acc_header acc_header_first'; } else { node.className = 'acc_header'; } node.onclick = headerClicked; div = document.createElement( 'div' ); div.id = 'content-' + headerNum; div.className = 'acc_content'; div.style.display = ( headerNum == 1 ) ? 'block' : 'none'; $( 'acc_container' ).insertBefore( div, $( 'acc_container' ).childNodes[i + 1] ); if ( headerNum != 1 ) { var prevdiv = document.createElement( 'div' ); prevdiv.className = 'acc_prev'; var prev = document.createElement( 'a' ); prev.className = 'acc_link'; prev.innerHTML = '<<previous'; prev.onclick = prevClicked; prevdiv.appendChild( prev ); div.appendChild( prevdiv ); } ignore = false; } else if ( in_array( ignoreElem, node.nodeName ) ) { ignore = true; } else { if ( headerNum != 0 && ignore == false ) { var id = 'content-' + headerNum; if ( id != node.id ) { $( id ).appendChild( node ); i--; } } } i++; } } function headerClicked() { var contentId = this.id.replace( /header-/, 'content-' ); var divs = $( 'acc_container' ).getElementsByTagName( 'div' ); for ( i = 0; i<divs.length; i++ ) { if ( divs[i].id.match( /^content-/ ) ) { divs[i].style.display = ( divs[i].id == contentId ) ? 'block' : 'none'; } } scrollToElem( $( this.id ) ); } function nextClicked() { var thisId = this.parentNode.parentNode.id; var nextId = 'content-' + ( parseInt( thisId.replace( /content-/, '' ) ) + 1 ); $( thisId ).style.display = 'none'; $( nextId ).style.display = 'block'; scrollToElem( $( nextId.replace( /content-/, 'header-' ) ) ); } function prevClicked() { var thisId = this.parentNode.parentNode.id; var prevId = 'content-' + ( parseInt( thisId.replace( /content-/, '' ) ) - 1 ); $( thisId ).style.display = 'none'; $( prevId ).style.display = 'block'; scrollToElem( $( prevId.replace( /content-/, 'header-' ) ) ); }
