]> git.sesse.net Git - remoteglot/blobdiff - www/js/chessboard-0.3.0.js
Yet more transition tweaks.
[remoteglot] / www / js / chessboard-0.3.0.js
index b58c589fb4394d4349c6f844faeb38108c8b853c..412df0225ddbaed8035d0ea768633f9c8c71e5c0 100644 (file)
@@ -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,16 +607,23 @@ 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();
@@ -680,17 +636,50 @@ function doAnimations(a, oldPos, 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