MediaWiki:Gadget-chessDemo.js

From mediawiki.org

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
( function( DOM_w, DOM_d ) {
	if ( ~mw.config.get( 'wgCategories' ).indexOf( 'Pages using Template chessDemo' ) ) {
		var init = function( demo ) {
				var printable = DOM_w.location.search && DOM_w.location.search.indexOf( '&printable=yes' ),
					data = JSON.parse( demo.getAttribute( 'data-data' ) ),
					notes = demo.querySelector( '.cd-notation' ),
					ui = demo.querySelector( '.cd-controls' ),
					board = demo.querySelector( '.cd-board' ),
					speed = data.speed * 1000,
					controls = data.controls,
					BF = data.blackfirst,
					setup = data.setup,
					moves = data.moves,
					numberofmoves = data.moves.length,
					parsed = [],
					frame = 0,
					glue = function( a ) {
						return 'cd-file-' + a.join( ' cd-rank-' );
					},
					pick = function( s ) {
						return board.querySelector( '[class*="' + s + '"]:not([class*="cd-captured"])' );
					},
					note = function( r ) {
						if ( notes ) {
							var ln = notes.querySelector( '.cd-movenote' ),
								mn = notes.querySelectorAll( 'b span' )[ frame ];
							if ( ln ) {
								ln.removeAttribute( 'class' );
							}
							if ( !r ) {
								mn.classList.add( 'cd-movenote' );
							}
						}
					},
					move = function( dir ) {
						var pf = parsed[ frame ],
							i = 0, m, m0, m00, m1, m10, lm,
							alm = board.querySelectorAll( 'div[class*="cd-moving"]' );
						while ( lm = alm[ i++ ] ) {
							lm.classList.remove( 'cd-moving' );
						}
						i = 0;
						while ( m = pf[ i++ ] ) {
							m0 = m[ 0 ];
							m00 = m0[ 0 ];
							m00.setAttribute( 'class', m0[ dir ] );
							m00.classList.add( 'cd-moving' );
							if ( m1 = m[ 1 ] ) {
								m10 = m1[ 0 ];
								m10.setAttribute( 'class', m1[ dir ] );
								m10.classList.add( 'cd-moving' );
							}
						}
						note();
					},
					next = function( a ) {
						if ( a ) {
							data.timeout = DOM_w.setTimeout( function() {
								actions.play( a );
							}, speed );
						}
					},
					actions = {
						reset: function() {
							var i = 0, p;
							actions.pause();
							note( true );
							frame = 0;
							while ( p = board.querySelectorAll( 'div:not(.cd-fallback)' )[ i ] ) {
								p.setAttribute( 'class', setup[ i++ ] );
							}
						},
						auto: function() {
							actions.pause();
							actions.play( true );
						},
						pause: function() {
							DOM_w.clearTimeout( data.timeout );
						},
						back: function() {
							var lf = frame - 1;
							actions.pause();
							if ( lf >= 0 && parsed[ lf ] ) {
								--frame;
								move( 1 );
							} else {
								skipTo( numberofmoves );
							}
						},
						play: function( a ) {
							actions.pause();
							if ( frame < data.moves.length ) {
								move( 2 );
								++frame;
								next( a );
							} else {
								if ( a ) {
									data.timeout = DOM_w.setTimeout( function() {
										actions.reset();
										next( a );
									}, speed );
								} else {
									actions.reset();
								}
							}
						}
					},
					skipTo = function( pos ) {
						actions.reset();
						while ( pos-- ) {
							actions.play();
						}
					},
					calculate = function( initial ) {
						while ( frame < numberofmoves ) {
							var m = data.moves[ frame ],
								from = m[ 0 ].split( '' ),
								bits = ( /(^(0\-0(?:\-0)?)|([KQBNR]{1})?(?:[a-h]{0,1}[1-8]{0,1})?(x{1})?([a-h]{1}[1-8]{1})(e\.p\.)?(?:(?:\=)?([KQBNR]{1}))?(?:\+|#)?(?:[.]*)?$)/ ).exec( m[ 1 ] ),
								castle = bits[ 2 ],
								piece = bits[ 3 ] ? 'cd-piece-' + bits[ 3 ] + ' ' : '',
								to = bits[ 5 ] ? bits[ 5 ].split( '' ) : '',
								promote = bits[ 7 ] ? 'cd-piece-' + bits[ 7 ] + ' ' : '',
								turn = frame % 2,
								color = 'cd-piece-' + [ 'white', 'black' ][ +( BF ? !turn : turn ) ],
								pass = [], arr = [];
								
							if ( castle ) {
								var rank = ' cd-rank-' + from[ 1 ],
									kingside = castle === '0-0',
									ck = color + ' cd-piece-K cd-file-e' + rank,
									cr = color + ' cd-piece-R cd-file-' + ( kingside ? 'h' : 'a' ) + rank;
								pass.push( [
									[ pick( ck ), ck, color + ' cd-piece-K cd-file-' + ( kingside ? 'g' : 'c' ) + rank ],
									[ pick( cr ), cr, color + ' cd-piece-R cd-file-' + ( kingside ? 'f' : 'd' ) + rank ]
								] );
							} else {
								var f = color + ' ' + piece + glue( from );
								if ( bits[ 4 ] ) {
									var captured = pick( glue( bits[ 6 ] ? [ to[ 0 ], from[ 1 ] ] : to ) ),
										cc = captured.getAttribute( 'class' );
									arr.push( [ captured, cc, cc + ' cd-captured' ] );
								}
								arr.push( [ pick( f ), f, color + ' ' + ( promote || piece ) + glue( to ) ] );
								pass.push( arr );
							}
							parsed.push( pass );
							move( 2 );
							++frame;
						}
						if ( initial !== undefined ) {
							skipTo( initial );
						}
					},
					controlSpeed = function( evt ) {
						speed = 5000 - evt.target.value;
					},
					controlDemo = function( evt ) {
						var trg = evt.target;
						if ( trg.tagName.toLowerCase() === "button" ) {
							actions[ trg.getAttribute( 'data-action' ) ]();
						}
					};
				if ( controls || printable ) {
					var min = '<button title="Step back one move" data-action="back">&#9664;</button><button title="Step forward one move" data-action="play">&#9654;</button>',
						med = '<span><button title="Reset the board" data-action="reset">Reset</button>' + min +
							'<button title="Play automatic animation" data-action="auto">Auto &#9654;</button></span>';
					if ( printable || controls === 'min' ) {
						ui.classList.add( 'cd-mini' );
						ui.innerHTML = '<span>' + min + '</span>';
					} else if ( controls === 'med' ) {
						ui.innerHTML = med;
					} else {
						ui.innerHTML = med + '<br><span><label>Speed:<input type="range" value="' + ( 5000 - speed ) + '" min="0" max="4500" step="500"></label>' +
							'<button title="Pause automatic animation" data-action="pause">&#8214;</button><button title="Stop automatic animation" data-action="reset">&#9632;</button></span>';
						ui.querySelector( 'input' ).addEventListener( 'input', controlSpeed, false );
					}
					ui.addEventListener( 'click', controlDemo, false );
				}
				calculate( data.initial );
				if ( printable ) {
					if ( notes ) {
						var cc = notes.querySelector( '.mw-collapsible-content' );
						if ( cc ) {
							cc.style.display = 'block';
						}
					}
				} else if ( data.autostart ) {
					actions.play( true );
				}
			};
		$( DOM_d ).ready( function() {
			var demos = DOM_d.querySelectorAll( '.chessDemo' ),
				link = DOM_d.createElement( 'link' ),
				i = 0, demo;
			link.href = '/w/index.php?title=User:Fred_Gandt/chessDemo.css&action=raw&ctype=text/css';
			link.setAttribute( 'rel', 'stylesheet' );
			link.addEventListener( 'load', function() {
				while ( demo = demos[ i++ ] ) {
					init( demo );
				}
			}, false );
			DOM_d.querySelector( 'head' ).appendChild( link );
		} );
	}
} ( window, document ) );