<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://rpg.manath.com/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3ACommon.js</id>
	<title>MediaWiki:Common.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://rpg.manath.com/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3ACommon.js"/>
	<link rel="alternate" type="text/html" href="https://rpg.manath.com/index.php?title=MediaWiki:Common.js&amp;action=history"/>
	<updated>2026-11-14T04:55:59Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://rpg.manath.com/index.php?title=MediaWiki:Common.js&amp;diff=1276&amp;oldid=prev</id>
		<title>Manath: Page turning for the story book</title>
		<link rel="alternate" type="text/html" href="https://rpg.manath.com/index.php?title=MediaWiki:Common.js&amp;diff=1276&amp;oldid=prev"/>
		<updated>2026-11-02T01:00:41Z</updated>

		<summary type="html">&lt;p&gt;Page turning for the story book&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/* The Story So Far: show chapters as facing pages, with tabs and arrows to turn between spreads. */&lt;br /&gt;
mw.hook( &amp;#039;wikipage.content&amp;#039; ).add( function ( $content ) {&lt;br /&gt;
	$content.find( &amp;#039;.story-book&amp;#039; ).each( function () {&lt;br /&gt;
		var book = this;&lt;br /&gt;
		if ( book.getAttribute( &amp;#039;data-ready&amp;#039; ) ) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		book.setAttribute( &amp;#039;data-ready&amp;#039;, &amp;#039;1&amp;#039; );&lt;br /&gt;
&lt;br /&gt;
		var pages = Array.prototype.filter.call( book.children, function ( el ) {&lt;br /&gt;
			return el.classList.contains( &amp;#039;story-box&amp;#039; );&lt;br /&gt;
		} );&lt;br /&gt;
		if ( !pages.length ) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Group the chapters into spreads of two facing pages.&lt;br /&gt;
		var spreads = [];&lt;br /&gt;
		for ( var i = 0; i &amp;lt; pages.length; i += 2 ) {&lt;br /&gt;
			var spread = document.createElement( &amp;#039;div&amp;#039; );&lt;br /&gt;
			spread.className = &amp;#039;story-spread&amp;#039;;&lt;br /&gt;
			book.insertBefore( spread, pages[ i ] );&lt;br /&gt;
			spread.appendChild( pages[ i ] );&lt;br /&gt;
			if ( pages[ i + 1 ] ) {&lt;br /&gt;
				spread.appendChild( pages[ i + 1 ] );&lt;br /&gt;
			}&lt;br /&gt;
			spreads.push( spread );&lt;br /&gt;
		}&lt;br /&gt;
		// Drop stray empty paragraphs the parser left between chapters.&lt;br /&gt;
		Array.prototype.forEach.call( book.querySelectorAll( &amp;#039;:scope &amp;gt; p&amp;#039; ), function ( p ) {&lt;br /&gt;
			if ( /^\s*$/.test( p.textContent ) ) {&lt;br /&gt;
				p.remove();&lt;br /&gt;
			}&lt;br /&gt;
		} );&lt;br /&gt;
		if ( spreads.length &amp;lt; 2 ) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function chapterNumber( page, fallback ) {&lt;br /&gt;
			var title = page.querySelector( &amp;#039;.story-title&amp;#039; );&lt;br /&gt;
			var m = title &amp;amp;&amp;amp; title.textContent.match( /Chapter\s+([0-9IVXLC]+)/i );&lt;br /&gt;
			return m ? m[ 1 ] : String( fallback );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		var labels = spreads.map( function ( spread, n ) {&lt;br /&gt;
			var first = chapterNumber( spread.children[ 0 ], n * 2 + 1 );&lt;br /&gt;
			return spread.children[ 1 ] ?&lt;br /&gt;
				&amp;#039;Chapters &amp;#039; + first + &amp;#039;–&amp;#039; + chapterNumber( spread.children[ 1 ], n * 2 + 2 ) :&lt;br /&gt;
				&amp;#039;Chapter &amp;#039; + first;&lt;br /&gt;
		} );&lt;br /&gt;
&lt;br /&gt;
		var current = 0;&lt;br /&gt;
		var navs = [];&lt;br /&gt;
&lt;br /&gt;
		function makeButton( text, title, onClick ) {&lt;br /&gt;
			var b = document.createElement( &amp;#039;button&amp;#039; );&lt;br /&gt;
			b.type = &amp;#039;button&amp;#039;;&lt;br /&gt;
			b.textContent = text;&lt;br /&gt;
			if ( title ) {&lt;br /&gt;
				b.title = title;&lt;br /&gt;
			}&lt;br /&gt;
			b.addEventListener( &amp;#039;click&amp;#039;, onClick );&lt;br /&gt;
			return b;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function makeNav() {&lt;br /&gt;
			var nav = document.createElement( &amp;#039;div&amp;#039; );&lt;br /&gt;
			nav.className = &amp;#039;story-nav&amp;#039;;&lt;br /&gt;
			var tabs = labels.map( function ( label, n ) {&lt;br /&gt;
				var tab = makeButton( label, null, function () {&lt;br /&gt;
					show( n, nav );&lt;br /&gt;
				} );&lt;br /&gt;
				tab.setAttribute( &amp;#039;role&amp;#039;, &amp;#039;tab&amp;#039; );&lt;br /&gt;
				nav.appendChild( tab );&lt;br /&gt;
				return tab;&lt;br /&gt;
			} );&lt;br /&gt;
			var arrows = document.createElement( &amp;#039;span&amp;#039; );&lt;br /&gt;
			arrows.className = &amp;#039;story-arrows&amp;#039;;&lt;br /&gt;
			var prev = makeButton( &amp;#039;◂ Previous&amp;#039;, null, function () {&lt;br /&gt;
				show( current - 1, nav );&lt;br /&gt;
			} );&lt;br /&gt;
			var next = makeButton( &amp;#039;Next ▸&amp;#039;, null, function () {&lt;br /&gt;
				show( current + 1, nav );&lt;br /&gt;
			} );&lt;br /&gt;
			arrows.appendChild( prev );&lt;br /&gt;
			arrows.appendChild( next );&lt;br /&gt;
			nav.appendChild( arrows );&lt;br /&gt;
			navs.push( { tabs: tabs, prev: prev, next: next } );&lt;br /&gt;
			return nav;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function show( n, fromNav ) {&lt;br /&gt;
			if ( n &amp;lt; 0 || n &amp;gt;= spreads.length ) {&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			current = n;&lt;br /&gt;
			spreads.forEach( function ( spread, k ) {&lt;br /&gt;
				spread.hidden = k !== n;&lt;br /&gt;
			} );&lt;br /&gt;
			navs.forEach( function ( nav ) {&lt;br /&gt;
				nav.tabs.forEach( function ( tab, k ) {&lt;br /&gt;
					tab.setAttribute( &amp;#039;aria-selected&amp;#039;, k === n ? &amp;#039;true&amp;#039; : &amp;#039;false&amp;#039; );&lt;br /&gt;
				} );&lt;br /&gt;
				nav.prev.disabled = n === 0;&lt;br /&gt;
				nav.next.disabled = n === spreads.length - 1;&lt;br /&gt;
			} );&lt;br /&gt;
			// Turning the page from the bottom bar jumps back up to the top of the book.&lt;br /&gt;
			if ( fromNav &amp;amp;&amp;amp; fromNav === bottomNav &amp;amp;&amp;amp; book.getBoundingClientRect().top &amp;lt; 0 ) {&lt;br /&gt;
				book.scrollIntoView( { behavior: &amp;#039;smooth&amp;#039; } );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		var topNav = makeNav();&lt;br /&gt;
		var bottomNav = makeNav();&lt;br /&gt;
		book.insertBefore( topNav, book.firstChild );&lt;br /&gt;
		book.appendChild( bottomNav );&lt;br /&gt;
		show( 0 );&lt;br /&gt;
	} );&lt;br /&gt;
} );&lt;/div&gt;</summary>
		<author><name>Manath</name></author>
	</entry>
</feed>