var numFinished = 0;
function onFinish(e, opt_force) {
- if (e && e.target) {
- e.target.transitionProperty = null;
- e.target.transitionDuration = null;
- }
-
- 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();
- }
+ if (++numFinished === a.length) {
+ for (let piece of removed_pieces) {
+ piece.remove();
+ }
- // run their onMoveEnd function
- if (cfg.hasOwnProperty('onMoveEnd') &&
- typeof cfg.onMoveEnd === 'function') {
- cfg.onMoveEnd(deepCopy(oldPos), deepCopy(newPos));
+ // run their onMoveEnd function
+ if (cfg.hasOwnProperty('onMoveEnd') &&
+ typeof cfg.onMoveEnd === 'function') {
+ cfg.onMoveEnd(deepCopy(oldPos), deepCopy(newPos));
+ }
}
}
- 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;
- }
- });
- });
+ fadein_pieces.forEach((piece) => {
+ piece.style.display = null;
+ piece.style.opacity = 1;
+ piece.animate(
+ [ { opacity: 0 }, { opacity: 1 } ],
+ { duration: cfg.appearSpeed }
+ ).addEventListener('finish', onFinish);
+ });
+ fadeout_pieces.forEach((piece) => {
+ piece.style.display = null;
+ piece.style.opacity = 0;
+ piece.animate(
+ [ { opacity: 1 }, { opacity: 0 } ],
+ { duration: cfg.trashSpeed }
+ ).addEventListener('finish', onFinish);
+ });
+ 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);
+
+ let destSquarePosition = findSquarePosition(destination);
+ piece.animate(
+ [
+ { top: piece.style.top, left: piece.style.left },
+ { top: destSquarePosition.top, left: destSquarePosition.left }
+ ],
+ { duration: cfg.moveSpeed }
+ ).addEventListener('finish', onFinish);
+ piece.style.top = destSquarePosition.top;
+ piece.style.left = destSquarePosition.left;
}
}
var sourceSquarePosition = findSquarePosition(DRAGGED_PIECE_SOURCE);
// animate the piece to the target square
- DRAGGED_PIECE.addEventListener('transitionend', complete, {once: true});
- requestAnimationFrame(() => {
- DRAGGED_PIECE.style.transitionProperty = 'top, left';
- DRAGGED_PIECE.style.transitionDuration = cfg.snapbackSpeed + 'ms';
- DRAGGED_PIECE.style.top = sourceSquarePosition.top;
- DRAGGED_PIECE.style.left = sourceSquarePosition.left;
- });
+ DRAGGED_PIECE.animate(
+ [
+ { top: DRAGGED_PIECE.style.top, left: DRAGGED_PIECE.style.left },
+ { top: sourceSquarePosition.top, left: sourceSquarePosition.left }
+ ],
+ { duration: cfg.snapbackSpeed }
+ ).addEventListener('finish', complete);
+ DRAGGED_PIECE.style.top = sourceSquarePosition.top;
+ DRAGGED_PIECE.style.left = sourceSquarePosition.left;
// set state
DRAGGING_A_PIECE = false;
};
// snap the piece to the target square
- DRAGGED_PIECE.addEventListener('transitionend', complete, {once: true});
- requestAnimationFrame(() => {
- DRAGGED_PIECE.style.transitionProperty = 'top, left';
- DRAGGED_PIECE.style.transitionDuration = cfg.snapSpeed + 'ms';
- DRAGGED_PIECE.style.top = targetSquarePosition.top;
- DRAGGED_PIECE.style.left = targetSquarePosition.left;
- });
+ DRAGGED_PIECE.animate(
+ [
+ { top: DRAGGED_PIECE.style.top, left: DRAGGED_PIECE.style.left },
+ { top: targetSquarePosition.top, left: targetSquarePosition.left }
+ ],
+ { duration: cfg.snapSpeed }
+ ).addEventListener('finish', complete);
+ DRAGGED_PIECE.style.top = targetSquarePosition.top;
+ DRAGGED_PIECE.style.left = targetSquarePosition.left;
}
function beginDraggingPiece(source, piece, x, y) {
DRAGGED_PIECE = PIECE_ON_SQUARE[source];
DRAGGED_PIECE_SOURCE = source;
DRAGGED_PIECE_LOCATION = source;
- DRAGGED_PIECE.style.transitionProperty = null;
- DRAGGED_PIECE.style.transitionDuration = null;
// 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.