User:קיפודנחש/chess-animator.js

$(function {

var allPositionClasses = '01234567' .split('') .map(function(r) { return 'pgn-prow-' + r + ' pgn-pfile-' + r; } ) .join(' ');

function processOneDiv { var $div = $(this), data = $div.data('chess'), boards, pieces = [], timer, delay = 800, boardDiv = $div.find('.pgn-board-img'), movedOnce, currentBoard;

function createPiece(letter) { var ll = letter.toLowerCase, color = letter == ll ? 'd' : 'l'; var piece = $(' ') .data('piece', letter) .addClass('pgn-chessPiece pgn-ptype-color-' + ll + color) .appendTo(boardDiv); pieces.push(piece); return piece; }

function processFen(fen) { var fenAr = fen.split('/'), board = []; for (var i in fenAr) { var j = 0; letters = fenAr[i].split(''); for (var li in letters) { var l = letters[li]; if (/[prnbqk]/i.test(l)) { board[(7 - i) * 8 + j] = createPiece(l); j++; }				else j += parseInt(l); }		}		return board; }

function processPly(board, ply) { newBoard = board.slice; var source = ply[0], destination = ply[1], special = ply[2]; if (typeof(source) == typeof(ply)) { // castling. 2 source/dest pairs newBoard = processPly(newBoard, source); newBoard = processPly(newBoard, destination); } else { newBoard[destination] = newBoard[source]; delete newBoard[source]; if (special) { if (typeof(special) == "string") newBoard[destination] = createPiece(special); // promotion else delete newBoard[special]; // en passant }		}		return newBoard; }

function gotoBoard(boardNum) { var previous = currentBoard, board = boards[boardNum], hidden = pieces.filter(function(piece) { return $.inArray(piece, pieces) + 1; }), appearNow = board.filter(function(piece) { return typeof(previous) == 'number' && ! ~$.inArray(piece, boards[previous]); } ); currentBoard = boardNum; for (var i in hidden) hidden[i].addClass('pgn-piece-hidden'); for (var j in board) { board[j] .removeClass(allPositionClasses + ' pgn-piece-hidden') .toggleClass('pgn-transition-immediate', ~$.inArray(board[j], appearNow)) .addClass('pgn-prow-' + parseInt(j / 8) + ' pgn-pfile-' + j % 8 ); }		if (boardNum == boards.length - 1) stopAutoplay; $('.pgn-movelink', $div).removeClass('pgn-current-move'); var notation = $('.pgn-movelink[data-ply=' + boardNum + ']', $div); if (notation.length) { notation.addClass('pgn-current-move'); if (movedOnce && typeof(notation[0].scrollIntoView) === "function") { // todo: replace with gentler scroll, that does not force the container into view. notation[0].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' }); }		}		movedOnce = true; }

function advance { if (currentBoard < boards.length - 1) gotoBoard(currentBoard + 1); }

function retreat { if (currentBoard > 0) gotoBoard(currentBoard - 1); }

function gotoStart { gotoBoard(0); stopAutoplay; }

function gotoEnd { gotoBoard(boards.length - 1); }

function clickPlay { if (currentBoard == boards.length - 1) gotoBoard(0);

if (timer) stopAutoplay; else startAutoplay; }

function changeDelay { if (delay < 400) delay = 400; if (timer) { stopAutoplay; startAutoplay; }	}

function slower { delay += Math.min(delay, 1600); changeDelay; }

function faster { delay = delay > 3200 ? delay - 1600 : delay / 2; changeDelay; }

function stopAutoplay { clearTimeout(timer); $('.pgn-button-play').removeClass('pgn-image-button-on'); timer = null; }

function startAutoplay { timer = setInterval(advance, delay); $('.pgn-button-play').addClass('pgn-image-button-on'); }

function flipBoard { $div.toggleClass('pgn-flip'); $('.pgn-button-flip', $div).toggleClass('pgn-image-button-on'); }	function clickNotation { stopAutoplay; gotoBoard($(this).data('ply')); }

function connectButtons { $('.pgn-button-advance', $div).click(advance); $('.pgn-button-retreat', $div).click(retreat); $('.pgn-button-tostart', $div).click(gotoStart); $('.pgn-button-toend', $div).click(gotoEnd); $('.pgn-button-play', $div).click(clickPlay); $('.pgn-button-faster', $div).click(faster); $('.pgn-button-slower', $div).click(slower); $('.pgn-button-flip', $div).click(flipBoard); $('.pgn-movelink', $div).click(clickNotation); }

if (data) { $div.find('.pgn-chessPiece').remove; // the parser put them there for "noscript" viewers, we need to clear them var board = processFen(data.fen); var display = data.display || data.plys.length; boards = [board]; for (var ind in data.plys) { var ply = data.plys[ind]; board = processPly(board, ply); boards.push(board); }		// onsole.log(JSON.stringify(boards, 4)); connectButtons; gotoBoard(display); }

}

$('.pgnviewer').each(processOneDiv); });