X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=www%2Fjs%2Fchessboard-0.3.0.js;h=f69d0ed3802968a07c2ee533464565c82cb7a88e;hb=dc7fb3ce880439ad1c024681a437b1d2c599af86;hp=5d257a0dc3b222b9facbbc31bb74bffdaeb43d7c;hpb=249993293db3218abf9cfa7a88fd9fd2dd5e1101;p=remoteglot diff --git a/www/js/chessboard-0.3.0.js b/www/js/chessboard-0.3.0.js index 5d257a0..f69d0ed 100644 --- a/www/js/chessboard-0.3.0.js +++ b/www/js/chessboard-0.3.0.js @@ -26,7 +26,7 @@ function validMove(move) { var tmp = move.split('-'); if (tmp.length !== 2) return false; - return (validSquare(tmp[0]) === true && validSquare(tmp[1]) === true); + return validSquare(tmp[0]) && validSquare(tmp[1]); } function validSquare(square) { @@ -67,9 +67,9 @@ function validPositionObject(pos) { if (typeof pos !== 'object') return false; for (var i in pos) { - if (pos.hasOwnProperty(i) !== true) continue; + if (!pos.hasOwnProperty(i)) continue; - if (validSquare(i) !== true || validPieceCode(pos[i]) !== true) { + if (!validSquare(i) || !validPieceCode(pos[i])) { return false; } } @@ -104,7 +104,7 @@ function pieceCodeToFen(piece) { // convert FEN string to position object // returns false if the FEN string is invalid function fenToObj(fen) { - if (validFen(fen) !== true) { + if (!validFen(fen)) { return false; } @@ -144,7 +144,7 @@ function fenToObj(fen) { // position object to FEN string // returns false if the obj is not a valid position object function objToFen(obj) { - if (validPositionObject(obj) !== true) { + if (!validPositionObject(obj)) { return false; } @@ -157,7 +157,7 @@ function objToFen(obj) { var square = COLUMNS[j] + currentRow; // piece exists - if (obj.hasOwnProperty(square) === true) { + if (obj.hasOwnProperty(square)) { if (num_empty > 0) { fen += num_empty; num_empty = 0; @@ -266,7 +266,7 @@ function deepCopy(thing) { */ function error(code, msg, obj) { // do nothing if showErrors is not set - if (cfg.hasOwnProperty('showErrors') !== true || + if (!cfg.hasOwnProperty('showErrors') || cfg.showErrors === false) { return; } @@ -346,7 +346,7 @@ function validAnimationSpeed(speed) { // validate config / set default options function expandConfig() { - if (typeof cfg === 'string' || validPositionObject(cfg) === true) { + if (typeof cfg === 'string' || validPositionObject(cfg)) { cfg = { position: cfg }; @@ -369,45 +369,45 @@ function expandConfig() { } // default piece theme is wikipedia - if (cfg.hasOwnProperty('pieceTheme') !== true || + if (!cfg.hasOwnProperty('pieceTheme') || (typeof cfg.pieceTheme !== 'string' && typeof cfg.pieceTheme !== 'function')) { cfg.pieceTheme = 'img/chesspieces/wikipedia/{piece}.png'; } // animation speeds - if (cfg.hasOwnProperty('appearSpeed') !== true || - validAnimationSpeed(cfg.appearSpeed) !== true) { + if (!cfg.hasOwnProperty('appearSpeed') || + !validAnimationSpeed(cfg.appearSpeed)) { cfg.appearSpeed = 200; } - if (cfg.hasOwnProperty('moveSpeed') !== true || - validAnimationSpeed(cfg.moveSpeed) !== true) { + if (!cfg.hasOwnProperty('moveSpeed') || + !validAnimationSpeed(cfg.moveSpeed)) { cfg.moveSpeed = 200; } - if (cfg.hasOwnProperty('snapbackSpeed') !== true || - validAnimationSpeed(cfg.snapbackSpeed) !== true) { + if (!cfg.hasOwnProperty('snapbackSpeed') || + !validAnimationSpeed(cfg.snapbackSpeed)) { cfg.snapbackSpeed = 50; } - if (cfg.hasOwnProperty('snapSpeed') !== true || - validAnimationSpeed(cfg.snapSpeed) !== true) { + if (!cfg.hasOwnProperty('snapSpeed') || + !validAnimationSpeed(cfg.snapSpeed)) { cfg.snapSpeed = 25; } - if (cfg.hasOwnProperty('trashSpeed') !== true || - validAnimationSpeed(cfg.trashSpeed) !== true) { + if (!cfg.hasOwnProperty('trashSpeed') || + !validAnimationSpeed(cfg.trashSpeed)) { cfg.trashSpeed = 100; } // make sure position is valid - if (cfg.hasOwnProperty('position') === true) { + if (cfg.hasOwnProperty('position')) { if (cfg.position === 'start') { CURRENT_POSITION = deepCopy(START_POSITION); } - else if (validFen(cfg.position) === true) { + else if (validFen(cfg.position)) { CURRENT_POSITION = fenToObj(cfg.position); } - else if (validPositionObject(cfg.position) === true) { + else if (validPositionObject(cfg.position)) { CURRENT_POSITION = deepCopy(cfg.position); } @@ -458,7 +458,7 @@ function buildBoard(orientation) { 'style="grid-row: ' + (i+1) + '; grid-column: ' + (j+1) + ';" ' + 'data-square="' + square + '">'; - if (cfg.showNotation === true) { + if (cfg.showNotation) { // alpha notation if ((orientation === 'white' && row === 1) || (orientation === 'black' && row === 8)) { @@ -550,57 +550,6 @@ function findSquarePosition(square) { }; } -function animateSquareToSquare(move_pieces, complete) { - for (const [piece, destination] of move_pieces) { - // Move it to the end of the stack, which changes the implicit z-index - // so that it will go on top of any pieces it's replacing. - piece.remove(); - boardEl.appendChild(piece); - - // animate the piece to the destination square - piece.addEventListener('transitionend', complete, {once: true}); - } - requestAnimationFrame(() => { - for (const [piece, destination] of move_pieces) { - let destSquarePosition = findSquarePosition(destination); - piece.style.transitionProperty = 'top, left'; - piece.style.transitionDuration = cfg.moveSpeed + 'ms'; - piece.style.top = destSquarePosition.top; - piece.style.left = destSquarePosition.left; - } - }); -} - -function fadeIn(pieces, onFinish) { - pieces.forEach((piece) => { - piece.style.opacity = 0; - piece.style.display = null; - piece.addEventListener('transitionend', onFinish, {once: true}); - }); - requestAnimationFrame(() => { - pieces.forEach((piece) => { - piece.style.transitionProperty = 'opacity'; - piece.style.transitionDuration = cfg.appearSpeed + 'ms'; - piece.style.opacity = 1; - }); - }); -} - -function fadeOut(pieces, onFinish) { - pieces.forEach((piece) => { - piece.style.opacity = 1; - piece.style.display = null; - piece.addEventListener('transitionend', onFinish, {once: true}); - }); - requestAnimationFrame(() => { - pieces.forEach((piece) => { - piece.style.transitionProperty = 'opacity'; - piece.style.transitionDuration = cfg.trashSpeed + 'ms'; - piece.style.opacity = 0; - }); - }); -} - // execute an array of animations function doAnimations(a, oldPos, newPos) { let fadeout_pieces = []; @@ -658,39 +607,79 @@ function doAnimations(a, oldPos, newPos) { } var numFinished = 0; - function onFinish(e) { + function onFinish(e, opt_force) { if (e && e.target) { e.target.transitionProperty = null; e.target.transitionDuration = null; } - numFinished++; - - // exit if all the animations aren't finished - if (numFinished !== a.length) return; + if (opt_force) { + // For whatever reason, the transition didn't seem to actually run + // (and thus, we didn't get an end event). Finish off now. + // (In particular, this seems to happen in Chrome if the tab is + // hidden and left alone for a while.) + if (numFinished == a.length) return; + numFinished = a.length; // Make sure a very delayed later event will be ignored. + } else { + numFinished++; + if (numFinished !== a.length) return; + } for (let piece of removed_pieces) { piece.remove(); } // run their onMoveEnd function - if (cfg.hasOwnProperty('onMoveEnd') === true && + if (cfg.hasOwnProperty('onMoveEnd') && typeof cfg.onMoveEnd === 'function') { cfg.onMoveEnd(deepCopy(oldPos), deepCopy(newPos)); } } - requestAnimationFrame(() => { // Firefox workaround. - if (fadeout_pieces.length > 0) { - fadeOut(fadeout_pieces, onFinish); - } - if (fadein_pieces.length > 0) { - fadeIn(fadein_pieces, onFinish); - } - if (move_pieces.length > 0) { - animateSquareToSquare(move_pieces, onFinish); - } - }); + if (fadeout_pieces.length == 0 || fadein_pieces.length > 0 || move_pieces.length > 0) { + requestAnimationFrame(() => { // Firefox workaround. + // Backup in case the transition never runs. + setTimeout(() => onFinish(null, true), + cfg.appearSpeed + cfg.trashSpeed + cfg.moveSpeed + 100); + + fadein_pieces.forEach((piece) => { + piece.style.opacity = 0; + piece.style.display = null; + piece.addEventListener('transitionend', onFinish, {once: true}); + }); + fadeout_pieces.forEach((piece) => { + piece.style.opacity = 1; + piece.style.display = null; + piece.addEventListener('transitionend', onFinish, {once: true}); + }); + for (const [piece, destination] of move_pieces) { + // Move it to the end of the stack, which changes the implicit z-index + // so that it will go on top of any pieces it's replacing. + piece.remove(); + boardEl.appendChild(piece); + piece.addEventListener('transitionend', onFinish, {once: true}); + } + requestAnimationFrame(() => { + fadein_pieces.forEach((piece) => { + piece.style.transitionProperty = 'opacity'; + piece.style.transitionDuration = cfg.appearSpeed + 'ms'; + piece.style.opacity = 1; + }); + fadeout_pieces.forEach((piece) => { + piece.style.transitionProperty = 'opacity'; + piece.style.transitionDuration = cfg.trashSpeed + 'ms'; + piece.style.opacity = 0; + }); + for (const [piece, destination] of move_pieces) { + let destSquarePosition = findSquarePosition(destination); + piece.style.transitionProperty = 'top, left'; + piece.style.transitionDuration = cfg.moveSpeed + 'ms'; + piece.style.top = destSquarePosition.top; + piece.style.left = destSquarePosition.left; + } + }); + }); + } } // returns the distance between two squares @@ -744,9 +733,9 @@ function calculateAnimations(pos1, pos2) { // remove pieces that are the same in both positions for (var i in pos2) { - if (pos2.hasOwnProperty(i) !== true) continue; + if (!pos2.hasOwnProperty(i)) continue; - if (pos1.hasOwnProperty(i) === true && pos1[i] === pos2[i]) { + if (pos1.hasOwnProperty(i) && pos1[i] === pos2[i]) { delete pos1[i]; delete pos2[i]; } @@ -754,7 +743,7 @@ function calculateAnimations(pos1, pos2) { // find all the "move" animations for (var i in pos2) { - if (pos2.hasOwnProperty(i) !== true) continue; + if (!pos2.hasOwnProperty(i)) continue; var closestPiece = findClosestPiece(pos1, pos2[i], i); if (closestPiece !== false) { @@ -773,7 +762,7 @@ function calculateAnimations(pos1, pos2) { // add pieces to pos2 for (var i in pos2) { - if (pos2.hasOwnProperty(i) !== true) continue; + if (!pos2.hasOwnProperty(i)) continue; animations.push({ type: 'add', @@ -786,11 +775,11 @@ function calculateAnimations(pos1, pos2) { // clear pieces from pos1 for (var i in pos1) { - if (pos1.hasOwnProperty(i) !== true) continue; + if (!pos1.hasOwnProperty(i)) continue; // do not clear a piece if it is on a square that is the result // of a "move", ie: a piece capture - if (squaresMovedTo.hasOwnProperty(i) === true) continue; + if (squaresMovedTo.hasOwnProperty(i)) continue; animations.push({ type: 'clear', @@ -835,10 +824,10 @@ function calculatePositionFromMoves(position, moves) { position = deepCopy(position); for (var i in moves) { - if (moves.hasOwnProperty(i) !== true) continue; + if (!moves.hasOwnProperty(i)) continue; // skip the move if the position doesn't have a piece on the source square - if (position.hasOwnProperty(i) !== true) continue; + if (!position.hasOwnProperty(i)) continue; var piece = position[i]; delete position[i]; @@ -858,7 +847,7 @@ function setCurrentPosition(position) { if (oldFen === newFen) return; // run their onChange function - if (cfg.hasOwnProperty('onChange') === true && + if (cfg.hasOwnProperty('onChange') && typeof cfg.onChange === 'function') { cfg.onChange(oldPos, newPos); } @@ -882,7 +871,7 @@ function snapbackDraggedPiece() { drawPositionInstant(); // run their onSnapbackEnd function - if (cfg.hasOwnProperty('onSnapbackEnd') === true && + if (cfg.hasOwnProperty('onSnapbackEnd') && typeof cfg.onSnapbackEnd === 'function') { cfg.onSnapbackEnd(DRAGGED_PIECE, DRAGGED_PIECE_SOURCE, deepCopy(CURRENT_POSITION), CURRENT_ORIENTATION); @@ -911,7 +900,7 @@ function dropDraggedPieceOnSquare(square) { if (DRAGGED_PIECE_SOURCE === square) { // Nothing to do, but call onSnapEnd anyway - if (cfg.hasOwnProperty('onSnapEnd') === true && typeof cfg.onSnapEnd === 'function') { + if (cfg.hasOwnProperty('onSnapEnd') && typeof cfg.onSnapEnd === 'function') { cfg.onSnapEnd(DRAGGED_PIECE_SOURCE, square, DRAGGED_PIECE); } return; @@ -935,7 +924,7 @@ function dropDraggedPieceOnSquare(square) { drawPositionInstant(); // execute their onSnapEnd function - if (cfg.hasOwnProperty('onSnapEnd') === true && + if (cfg.hasOwnProperty('onSnapEnd') && typeof cfg.onSnapEnd === 'function') { requestAnimationFrame(() => { // HACK: so that we don't add event handlers from the callback... cfg.onSnapEnd(DRAGGED_PIECE_SOURCE, square, DRAGGED_PIECE); @@ -1041,13 +1030,13 @@ function stopDraggedPiece(location) { } // run their onDrop function, which can potentially change the drop action - if (cfg.hasOwnProperty('onDrop') === true && + if (cfg.hasOwnProperty('onDrop') && typeof cfg.onDrop === 'function') { var newPosition = deepCopy(CURRENT_POSITION); // source piece was on the board and position is on the board - if (validSquare(DRAGGED_PIECE_SOURCE) === true && - validSquare(location.square) === true) { + if (validSquare(DRAGGED_PIECE_SOURCE) && + validSquare(location.square)) { // move the piece delete newPosition[DRAGGED_PIECE_SOURCE]; newPosition[location.square] = DRAGGED_PIECE; @@ -1137,7 +1126,7 @@ widget.move = function() { } // skip invalid arguments - if (validMove(arguments[i]) !== true) { + if (!validMove(arguments[i])) { error(2826, 'Invalid move passed to the move method.', arguments[i]); continue; } @@ -1205,17 +1194,17 @@ widget.position = function(position, useAnimation) { } // convert FEN to position object - if (validFen(position) === true) { + if (validFen(position)) { position = fenToObj(position); } // validate position object - if (validPositionObject(position) !== true) { + if (!validPositionObject(position)) { error(6482, 'Invalid value passed to the position method.', position); return; } - if (useAnimation === true) { + if (useAnimation) { // start the animations doAnimations(calculateAnimations(CURRENT_POSITION, position), CURRENT_POSITION, position); @@ -1253,12 +1242,12 @@ function mousedownSquare(e) { // no piece on this square if (!validSquare(square) || - CURRENT_POSITION.hasOwnProperty(square) !== true) { + !CURRENT_POSITION.hasOwnProperty(square)) { return; } // do nothing if we're not draggable - if (cfg.draggable !== true) return; + if (!cfg.draggable) return; beginDraggingPiece(square, CURRENT_POSITION[square], e.pageX, e.pageY); } @@ -1270,13 +1259,13 @@ function touchstartSquare(e) { } // do nothing if we're not draggable - if (cfg.draggable !== true) return; + if (!cfg.draggable) return; var square = target.getAttribute('data-square'); // no piece on this square - if (validSquare(square) !== true || - CURRENT_POSITION.hasOwnProperty(square) !== true) { + if (!validSquare(square) || + !CURRENT_POSITION.hasOwnProperty(square)) { return; } @@ -1286,14 +1275,14 @@ function touchstartSquare(e) { function mousemoveWindow(e) { // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; + if (!DRAGGING_A_PIECE) return; updateDraggedPiece(findSquareFromEvent(e.pageX, e.pageY)); } function touchmoveWindow(e) { // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; + if (!DRAGGING_A_PIECE) return; // prevent screen from scrolling e.preventDefault(); @@ -1304,18 +1293,14 @@ function touchmoveWindow(e) { function mouseupWindow(e) { // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; + if (!DRAGGING_A_PIECE) return; stopDraggedPiece(findSquareFromEvent(e.pageX, e.pageY)); } function touchendWindow(e) { // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; - - // get the location - var location = isXYOnSquare(e.changedTouches[0].pageX, - e.changedTouches[0].pageY); + if (!DRAGGING_A_PIECE) return; stopDraggedPiece(findSquareFromEvent(e.changedTouches[0].pageX, e.changedTouches[0].pageY)); @@ -1331,18 +1316,18 @@ function mouseenterSquare(e) { // NOTE: this should never happen, but it's a safeguard if (DRAGGING_A_PIECE !== false) return; - if (cfg.hasOwnProperty('onMouseoverSquare') !== true || + if (!cfg.hasOwnProperty('onMouseoverSquare') || typeof cfg.onMouseoverSquare !== 'function') return; // get the square var square = target.getAttribute('data-square'); // NOTE: this should never happen; defensive - if (validSquare(square) !== true) return; + if (!validSquare(square)) return; // get the piece on this square var piece = false; - if (CURRENT_POSITION.hasOwnProperty(square) === true) { + if (CURRENT_POSITION.hasOwnProperty(square)) { piece = CURRENT_POSITION[square]; } @@ -1361,18 +1346,18 @@ function mouseleaveSquare(e) { // NOTE: this should never happen, but it's a safeguard if (DRAGGING_A_PIECE !== false) return; - if (cfg.hasOwnProperty('onMouseoutSquare') !== true || + if (!cfg.hasOwnProperty('onMouseoutSquare') || typeof cfg.onMouseoutSquare !== 'function') return; // get the square var square = target.getAttribute('data-square'); // NOTE: this should never happen; defensive - if (validSquare(square) !== true) return; + if (!validSquare(square)) return; // get the piece on this square var piece = false; - if (CURRENT_POSITION.hasOwnProperty(square) === true) { + if (CURRENT_POSITION.hasOwnProperty(square)) { piece = CURRENT_POSITION[square]; } @@ -1406,7 +1391,7 @@ function addEvents() { window.addEventListener('mouseup', mouseupWindow); // touch drag pieces - if (isTouchDevice() === true) { + if (isTouchDevice()) { boardEl.addEventListener('touchstart', touchstartSquare); window.addEventListener('touchmove', touchmoveWindow); window.addEventListener('touchend', touchendWindow); @@ -1423,8 +1408,7 @@ function initDom() { } function init() { - if (checkDeps() !== true || - expandConfig() !== true) return; + if (!checkDeps() || !expandConfig()) return; initDom(); addEvents();