User:Hagindaz/autonav.js

From Wikibooks, open books for an open world
Jump to navigation Jump to search
Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
  • Mozilla / Firefox / Safari: hold down Shift while clicking Reload, or press Ctrl-Shift-R (Cmd-Shift-R on Apple Mac);
  • Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5;
  • Konqueror: simply click the Reload button, or press F5;
  • Opera users may need to completely clear their cache in Tools→Preferences.
/**
 * autonav script
 * 
 * Automatically adds previous and next chapter links to the top and bottom of 
 * each chapter in the book, based on the order of the chapters on the 
 * chapter's parent page. Links not prefixed by the parent page and to the 
 * print version are ignored. Also shows a small list of all chapters at the 
 * bottom and at the sidebar of each chapter.
 * 
 * This program is available under CC0 1.0, viewable at
 * http://creativecommons.org/publicdomain/zero/1.0/.
 */
(function(mw, $, d) {
	'use strict';
	mw.loader.using('mediawiki.api', function() {
		$(d).ready(function() {
			var title = mw.config.get('wgTitle'),
				titleparts = title.split('/'),
				bookTitle = titleparts[0],
				parentPagePath = title.substring(0, title.lastIndexOf('/')),
				parentPageEscapedPath = parentPagePath.replace('"', '"'),
				chapterTitle = titleparts[titleparts.length - 1],
				api;
			
			function addNavigation(bookTitle, chapterTitle, $previous, $next, $all) {
				var $content = $('#mw-content-text'),
					$nav = $('<div class="noprint" style="text-align: center" />'),
					$allnav = $('<div class="autonav-all noprint" style="font-size: x-small; text-align: center; line-height: 1.3em" />'),
					$sidenav = $('<ul />').css('list-style-type', 'decimal').css('color', 'rgb(100, 100, 100)'),
					$el,
					i;
				
				// add previous and next links to $nav
				if ($previous.length) {
					$previous.text('← ' + $previous.text());
					$nav.append($previous);
					$nav.append(' · ');
				}
				$nav.append($('<a />').attr('href', mw.util.getUrl(bookTitle)).css('font-weight', 'bold').text(bookTitle));
				if ($next.length) {
					$nav.append(' · ');
					$next.text($next.text() + ' →');
					$nav.append($next);
				}
				
				// add list of all chapters shown at the bottom to $allNav
				for (i = 0; i < $all.length; i++) {
					if ($all[i].title === title) {
						$el = $('<span />').text(chapterTitle);
						$allnav.append($el.clone().css('font-weight', 'bold'));
						$sidenav.append($('<li />').append($el.css('color', 'black')));
					} else {
						$allnav.append($($all[i]).clone());
						$sidenav.append($('<li />').append($all[i]));
					}
					if (i < $all.length - 1) {
						$allnav.append(' · ');
					}
				}
				
				// add the created divs to $content, and hide the redundant #contentSub div
				$content.prepend($nav.clone().addClass('autonav-top').css('font-size', 'smaller'));
				$('#contentSub').hide();
				$content.append($nav.clone().addClass('autonav-bottom').wrapInner('<span style="border-top: solid thin rgb(170, 170, 170); padding: 2px 5px" />'));
				$content.append($allnav);
				$('<div class="portal expanded portlet">')
					.append('<h3 style="text-transform: initial"><a>' + bookTitle + '</a></h3>')
					.append($sidenav.wrap('<div class="body pBody autonav-sidebar" style="display: block" />').parent())
					.appendTo('#mw-panel, #column-one, #mw_portlets');
			}
			
			// start with a bunch of error checks
			if (true !== true) {
				mw.log('API is disabled');
				return;
			}
			if (mw.Api === undefined) {
				mw.log('mw.Api is undefined');
				return;
			}
			if (mw.config.get('wgNamespaceNumber') !== 0) {
				mw.log('Not in the main namespace');
				return;
			}
			if (titleparts.length < 2) {
				mw.log('Not in a subpage');
				return;
			}
			if (chapterTitle === 'Print version') {
				mw.log('Not a chapter');
				return;
			}
			
			// get HTML for the book's main page from the server
			api = new mw.Api();
			api.get( {
				action: 'parse',
				page: parentPagePath
			}).done(function(data) {
				var links, i, previous = null, next = null;
				
				// get <a /> elements for all chapters, in order
				// all chapter links look like <a title="Book Title/Chapter Title" …>Chapter Title</a>
				// red links have " (page does not exist)" at the end of the title attribute
				links = $('a[title^="' + parentPageEscapedPath + '/"]', data.parse.text['*'])
					.not('.autonav-exclude a')
					.not('[title="' + parentPageEscapedPath + '/Print version"]')
					.filter(function isCorrectDepth() {
						return this.title.lastIndexOf('/') == parentPagePath.length;
					});
				
				// loop through list of chapters until you find the current page
				for (i = 0; i < links.length; i++) {
					if (links[i].title === title || links[i].title === title + ' (page does not exist)') {
						if (i > 0 && links[i - 1].title !== bookTitle + '/Print version') {
							previous =  links[i - 1];
						}
						if (i < links.length - 1 && links[i + 1].title !== bookTitle + '/Print version') {
							next = links[i + 1];
						}
						
						addNavigation(bookTitle, chapterTitle, $(previous).clone(), $(next).clone(), links);
						return;
					}
				}
			}).fail(function(error) {
				mw.log("Could not open book's main page: " + error);
			});
		});
	});
}(mediaWiki, jQuery, document));