]> git.sesse.net Git - remoteglot/commitdiff
Remove all jQuery from chessboard.js that does not involve animations.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 20 Dec 2022 23:27:55 +0000 (00:27 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 22 Dec 2022 00:00:56 +0000 (01:00 +0100)
www/js/chessboard-0.3.0.js

index 4b24ec04d5fe3a29845da396f9a1e8c10bb79d57..c45feeb74b5dc9b593271dd9e8cd1143d6569ce8 100644 (file)
@@ -359,21 +359,12 @@ function checkDeps() {
     }
 
     // set the containerEl
-    containerEl = $(el);
+    containerEl = el;
   }
 
-  // else it must be something that becomes a jQuery collection
-  // with size 1
-  // ie: a single DOM node or jQuery object
+  // else it must be a DOM node
   else {
-    containerEl = $(containerElOrId);
-
-    if (containerEl.length !== 1) {
-      window.alert('ChessBoard Error 1003: The first argument to ' +
-        'ChessBoard() must be an ID or a single DOM node.' +
-        '\n\nExiting...');
-      return false;
-    }
+    containerEl = containerElOrId;
   }
 
   // JSON must exist
@@ -509,7 +500,7 @@ function expandConfig() {
 // fudge factor, and then keep reducing until we find an exact mod 8 for
 // our square size
 function calculateSquareSize() {
-  var containerWidth = parseInt(containerEl.css('width'), 10);
+  var containerWidth = parseInt(getComputedStyle(containerEl).width, 10);
 
   // defensive, prevent infinite loop
   if (! containerWidth || containerWidth <= 0) {
@@ -681,7 +672,9 @@ function buildPiece(piece, hidden, id) {
   }
   html += '" />';
 
-  return html;
+  let elem = document.createElement('template');
+  elem.innerHTML = html;
+  return elem.content;
 }
 
 function buildSparePieces(color) {
@@ -702,27 +695,34 @@ function buildSparePieces(color) {
 // Animations
 //------------------------------------------------------------------------------
 
+function offset(el) {  // From https://youmightnotneedjquery.com/.
+  let box = el.getBoundingClientRect();
+  let docElem = document.documentElement;
+  return {
+    top: box.top + window.pageYOffset - docElem.clientTop,
+    left: box.left + window.pageXOffset - docElem.clientLeft
+  };
+}
+
 function animateSquareToSquare(src, dest, piece, completeFn) {
   // get information about the source and destination squares
-  var srcSquareEl = $('#' + SQUARE_ELS_IDS[src]);
-  var srcSquarePosition = srcSquareEl.offset();
-  var destSquareEl = $('#' + SQUARE_ELS_IDS[dest]);
-  var destSquarePosition = destSquareEl.offset();
+  var srcSquareEl = document.getElementById(SQUARE_ELS_IDS[src]);
+  var srcSquarePosition = offset(srcSquareEl);
+  var destSquareEl = document.getElementById(SQUARE_ELS_IDS[dest]);
+  var destSquarePosition = offset(destSquareEl);
 
   // create the animated piece and absolutely position it
   // over the source square
   var animatedPieceId = createId();
-  $('body').append(buildPiece(piece, true, animatedPieceId));
-  var animatedPieceEl = $('#' + animatedPieceId);
-  animatedPieceEl.css({
-    display: '',
-    position: 'absolute',
-    top: srcSquarePosition.top,
-    left: srcSquarePosition.left
-  });
+  document.body.append(buildPiece(piece, true, animatedPieceId));
+  var animatedPieceEl = document.getElementById(animatedPieceId);
+  animatedPieceEl.style.display = '';
+  animatedPieceEl.style.position = 'absolute';
+  animatedPieceEl.style.top = srcSquarePosition.top;
+  animatedPieceEl.style.left = srcSquarePosition.left;
 
   // remove original piece from source square
-  srcSquareEl.find('.' + CSS.piece).remove();
+  srcSquareEl.querySelector('.' + CSS.piece).remove();
 
   // on complete
   var complete = function() {
@@ -743,29 +743,27 @@ function animateSquareToSquare(src, dest, piece, completeFn) {
     duration: cfg.moveSpeed,
     complete: complete
   };
-  animatedPieceEl.animate(destSquarePosition, opts);
+  $(animatedPieceEl).animate(destSquarePosition, opts);
 }
 
 function animateSparePieceToSquare(piece, dest, completeFn) {
-  var srcOffset = $('#' + SPARE_PIECE_ELS_IDS[piece]).offset();
-  var destSquareEl = $('#' + SQUARE_ELS_IDS[dest]);
-  var destOffset = destSquareEl.offset();
+  var srcOffset = offset(document.getelementById(SPARE_PIECE_ELS_IDS[piece]));
+  var destSquareEl = document.getElementById(SQUARE_ELS_IDS[dest]);
+  var destOffset = offset(destSquareEl);
 
   // create the animate piece
   var pieceId = createId();
-  $('body').append(buildPiece(piece, true, pieceId));
-  var animatedPieceEl = $('#' + pieceId);
-  animatedPieceEl.css({
-    display: '',
-    position: 'absolute',
-    left: srcOffset.left,
-    top: srcOffset.top
-  });
+  document.body.append(buildPiece(piece, true, pieceId));
+  var animatedPieceEl = document.getElementById(pieceId);
+  animatedPieceEl.style.display = '';
+  animatedPieceEl.style.position = 'absolute';
+  animatedPieceEl.style.left = srcOffset.left;
+  animatedPieceEl.style.top = srcOffset.top;
 
   // on complete
   var complete = function() {
     // add the "real" piece to the destination square
-    destSquareEl.find('.' + CSS.piece).remove();
+    destSquareEl.querySelector('.' + CSS.piece).remove();
     destSquareEl.append(buildPiece(piece));
 
     // remove the animated piece
@@ -782,7 +780,7 @@ function animateSparePieceToSquare(piece, dest, completeFn) {
     duration: cfg.moveSpeed,
     complete: complete
   };
-  animatedPieceEl.animate(destOffset, opts);
+  $(animatedPieceEl).animate(destOffset, opts);
 }
 
 // execute an array of animations
@@ -980,28 +978,28 @@ function calculateAnimations(pos1, pos2) {
 
 function drawPositionInstant() {
   // clear the board
-  boardEl.find('.' + CSS.piece).remove();
+  boardEl.querySelectorAll('.' + CSS.piece).forEach((piece) => piece.remove());
 
   // add the pieces
   for (var i in CURRENT_POSITION) {
     if (CURRENT_POSITION.hasOwnProperty(i) !== true) continue;
 
-    $('#' + SQUARE_ELS_IDS[i]).append(buildPiece(CURRENT_POSITION[i]));
+    document.getElementById(SQUARE_ELS_IDS[i]).append(buildPiece(CURRENT_POSITION[i]));
   }
 }
 
 function drawBoard() {
-  boardEl.html(buildBoard(CURRENT_ORIENTATION));
+  boardEl.innerHTML = buildBoard(CURRENT_ORIENTATION);
   drawPositionInstant();
 
   if (cfg.sparePieces === true) {
     if (CURRENT_ORIENTATION === 'white') {
-      sparePiecesTopEl.html(buildSparePieces('black'));
-      sparePiecesBottomEl.html(buildSparePieces('white'));
+      sparePiecesTopEl.innerHTML = buildSparePieces('black');
+      sparePiecesBottomEl.innerHTML = buildSparePieces('white');
     }
     else {
-      sparePiecesTopEl.html(buildSparePieces('white'));
-      sparePiecesBottomEl.html(buildSparePieces('black'));
+      sparePiecesTopEl.innerHTML = buildSparePieces('white');
+      sparePiecesBottomEl.innerHTML = buildSparePieces('black');
     }
   }
 }
@@ -1065,13 +1063,15 @@ function captureSquareOffsets() {
   for (var i in SQUARE_ELS_IDS) {
     if (SQUARE_ELS_IDS.hasOwnProperty(i) !== true) continue;
 
-    SQUARE_ELS_OFFSETS[i] = $('#' + SQUARE_ELS_IDS[i]).offset();
+    SQUARE_ELS_OFFSETS[i] = offset(document.getElementById(SQUARE_ELS_IDS[i]));
   }
 }
 
 function removeSquareHighlights() {
-  boardEl.find('.' + CSS.square)
-    .removeClass(CSS.highlight1 + ' ' + CSS.highlight2);
+  boardEl.querySelectorAll('.' + CSS.square).forEach((piece) => {
+    piece.classList.remove(CSS.highlight1);
+    piece.classList.remove(CSS.highlight2);
+  });
 }
 
 function snapbackDraggedPiece() {
@@ -1086,7 +1086,7 @@ function snapbackDraggedPiece() {
   // animation complete
   function complete() {
     drawPositionInstant();
-    draggedPieceEl.css('display', 'none');
+    draggedPieceEl.style.display = 'none';
 
     // run their onSnapbackEnd function
     if (cfg.hasOwnProperty('onSnapbackEnd') === true &&
@@ -1098,14 +1098,14 @@ function snapbackDraggedPiece() {
 
   // get source square position
   var sourceSquarePosition =
-    $('#' + SQUARE_ELS_IDS[DRAGGED_PIECE_SOURCE]).offset();
+    offset(document.getElementById(SQUARE_ELS_IDS[DRAGGED_PIECE_SOURCE]));
 
   // animate the piece to the target square
   var opts = {
     duration: cfg.snapbackSpeed,
     complete: complete
   };
-  draggedPieceEl.animate(sourceSquarePosition, opts);
+  $(draggedPieceEl).animate(sourceSquarePosition, opts);
 
   // set state
   DRAGGING_A_PIECE = false;
@@ -1123,7 +1123,7 @@ function trashDraggedPiece() {
   drawPositionInstant();
 
   // hide the dragged piece
-  draggedPieceEl.fadeOut(cfg.trashSpeed);
+  $(draggedPieceEl).fadeOut(cfg.trashSpeed);
 
   // set state
   DRAGGING_A_PIECE = false;
@@ -1139,12 +1139,12 @@ function dropDraggedPieceOnSquare(square) {
   setCurrentPosition(newPosition);
 
   // get target square information
-  var targetSquarePosition = $('#' + SQUARE_ELS_IDS[square]).offset();
+  var targetSquarePosition = offset(document.getElementById(SQUARE_ELS_IDS[square]));
 
   // animation complete
   var complete = function() {
     drawPositionInstant();
-    draggedPieceEl.css('display', 'none');
+    draggedPieceEl.style.display = 'none';
 
     // execute their onSnapEnd function
     if (cfg.hasOwnProperty('onSnapEnd') === true &&
@@ -1158,7 +1158,7 @@ function dropDraggedPieceOnSquare(square) {
     duration: cfg.snapSpeed,
     complete: complete
   };
-  draggedPieceEl.animate(targetSquarePosition, opts);
+  $(draggedPieceEl).animate(targetSquarePosition, opts);
 
   // set state
   DRAGGING_A_PIECE = false;
@@ -1190,27 +1190,24 @@ function beginDraggingPiece(source, piece, x, y) {
   captureSquareOffsets();
 
   // create the dragged piece
-  draggedPieceEl.attr('src', buildPieceImgSrc(piece))
-    .css({
-      display: '',
-      position: 'absolute',
-      left: x - (SQUARE_SIZE / 2),
-      top: y - (SQUARE_SIZE / 2)
-    });
+  draggedPieceEl.setAttribute('src', buildPieceImgSrc(piece));
+  draggedPieceEl.style.display = null;
+  draggedPieceEl.style.position = 'absolute';
+  draggedPieceEl.style.left = (x - (SQUARE_SIZE / 2)) + 'px';
+  draggedPieceEl.style.top = (y - (SQUARE_SIZE / 2)) + 'px';
 
   if (source !== 'spare') {
     // highlight the source square and hide the piece
-    $('#' + SQUARE_ELS_IDS[source]).addClass(CSS.highlight1)
-      .find('.' + CSS.piece).css('display', 'none');
+    let square = document.getElementById(SQUARE_ELS_IDS[source]);
+    square.classList.add(CSS.highlight1);
+    square.querySelector('.' + CSS.piece).style.display = 'none';
   }
 }
 
 function updateDraggedPiece(x, y) {
   // put the dragged piece over the mouse cursor
-  draggedPieceEl.css({
-    left: x - (SQUARE_SIZE / 2),
-    top: y - (SQUARE_SIZE / 2)
-  });
+  draggedPieceEl.style.left = (x - (SQUARE_SIZE / 2)) + 'px';
+  draggedPieceEl.style.top = (y - (SQUARE_SIZE / 2)) + 'px';
 
   // get location
   var location = isXYOnSquare(x, y);
@@ -1220,13 +1217,13 @@ function updateDraggedPiece(x, y) {
 
   // remove highlight from previous square
   if (validSquare(DRAGGED_PIECE_LOCATION) === true) {
-    $('#' + SQUARE_ELS_IDS[DRAGGED_PIECE_LOCATION])
-      .removeClass(CSS.highlight2);
+    document.getElementById(SQUARE_ELS_IDS[DRAGGED_PIECE_LOCATION])
+      .classList.remove(CSS.highlight2);
   }
 
   // add highlight to new square
   if (validSquare(location) === true) {
-    $('#' + SQUARE_ELS_IDS[location]).addClass(CSS.highlight2);
+    document.getElementById(SQUARE_ELS_IDS[location]).classList.add(CSS.highlight2);
   }
 
   // run onDragMove
@@ -1323,11 +1320,8 @@ widget.config = function(arg1, arg2) {
 // remove the widget from the page
 widget.destroy = function() {
   // remove markup
-  containerEl.html('');
+  containerEl.innerHTML = '';
   draggedPieceEl.remove();
-
-  // remove event handlers
-  containerEl.unbind();
 };
 
 // shorthand method to get the current FEN
@@ -1462,18 +1456,18 @@ widget.resize = function() {
   SQUARE_SIZE = calculateSquareSize();
 
   // set board width
-  boardEl.css('width', (SQUARE_SIZE * 8) + 'px');
+  boardEl.style.width = (SQUARE_SIZE * 8) + 'px';
 
   // set drag piece size
-  draggedPieceEl.css({
-    height: SQUARE_SIZE,
-    width: SQUARE_SIZE
-  });
+  if (draggedPieceEl !== null) {
+    draggedPieceEl.style.height = SQUARE_SIZE + 'px';
+    draggedPieceEl.style.width = SQUARE_SIZE + 'px';
+  }
 
   // spare pieces
   if (cfg.sparePieces === true) {
-    containerEl.find('.' + CSS.sparePieces)
-      .css('paddingLeft', (SQUARE_SIZE + BOARD_BORDER_SIZE) + 'px');
+    containerEl.querySelector('.' + CSS.sparePieces)
+      .style.paddingLeft = (SQUARE_SIZE + BOARD_BORDER_SIZE) + 'px';
   }
 
   // redraw the board
@@ -1493,21 +1487,16 @@ function isTouchDevice() {
   return ('ontouchstart' in document.documentElement);
 }
 
-// reference: http://www.quirksmode.org/js/detect.html
-function isMSIE() {
-  return (navigator && navigator.userAgent &&
-      navigator.userAgent.search(/MSIE/) !== -1);
-}
-
-function stopDefault(e) {
-  e.preventDefault();
-}
-
 function mousedownSquare(e) {
+  let target = e.target.closest('.' + CSS.square);
+  if (!target) {
+    return;
+  }
+
   // do nothing if we're not draggable
   if (cfg.draggable !== true) return;
 
-  var square = $(this).attr('data-square');
+  var square = target.getAttribute('data-square');
 
   // no piece on this square
   if (validSquare(square) !== true ||
@@ -1519,10 +1508,15 @@ function mousedownSquare(e) {
 }
 
 function touchstartSquare(e) {
+  let target = e.target.closest('.' + CSS.square);
+  if (!target) {
+    return;
+  }
+
   // do nothing if we're not draggable
   if (cfg.draggable !== true) return;
 
-  var square = $(this).attr('data-square');
+  var square = target.getAttribute('data-square');
 
   // no piece on this square
   if (validSquare(square) !== true ||
@@ -1536,19 +1530,27 @@ function touchstartSquare(e) {
 }
 
 function mousedownSparePiece(e) {
+  if (!e.target.matches('.' + CSS.sparePieces + ' .' + CSS.piece)) {
+    return;
+  }
+
   // do nothing if sparePieces is not enabled
   if (cfg.sparePieces !== true) return;
 
-  var piece = $(this).attr('data-piece');
+  var piece = e.target.getAttribute('data-piece');
 
   beginDraggingPiece('spare', piece, e.pageX, e.pageY);
 }
 
 function touchstartSparePiece(e) {
+  if (!e.target.matches('.' + CSS.sparePieces + ' .' + CSS.piece)) {
+    return;
+  }
+
   // do nothing if sparePieces is not enabled
   if (cfg.sparePieces !== true) return;
 
-  var piece = $(this).attr('data-piece');
+  var piece = e.target.getAttribute('data-piece');
 
   e = e.originalEvent;
   beginDraggingPiece('spare', piece,
@@ -1595,6 +1597,11 @@ function touchendWindow(e) {
 }
 
 function mouseenterSquare(e) {
+  let target = e.target.closest('.' + CSS.square);
+  if (!target) {
+    return;
+  }
+
   // do not fire this event if we are dragging a piece
   // NOTE: this should never happen, but it's a safeguard
   if (DRAGGING_A_PIECE !== false) return;
@@ -1603,7 +1610,7 @@ function mouseenterSquare(e) {
     typeof cfg.onMouseoverSquare !== 'function') return;
 
   // get the square
-  var square = $(e.currentTarget).attr('data-square');
+  var square = target.getAttribute('data-square');
 
   // NOTE: this should never happen; defensive
   if (validSquare(square) !== true) return;
@@ -1620,6 +1627,11 @@ function mouseenterSquare(e) {
 }
 
 function mouseleaveSquare(e) {
+  let target = e.target.closest('.' + CSS.square);
+  if (!target) {
+    return;
+  }
+
   // do not fire this event if we are dragging a piece
   // NOTE: this should never happen, but it's a safeguard
   if (DRAGGING_A_PIECE !== false) return;
@@ -1628,7 +1640,7 @@ function mouseleaveSquare(e) {
     typeof cfg.onMouseoutSquare !== 'function') return;
 
   // get the square
-  var square = $(e.currentTarget).attr('data-square');
+  var square = target.getAttribute('data-square');
 
   // NOTE: this should never happen; defensive
   if (validSquare(square) !== true) return;
@@ -1650,58 +1662,51 @@ function mouseleaveSquare(e) {
 
 function addEvents() {
   // prevent browser "image drag"
-  $('body').on('mousedown mousemove', '.' + CSS.piece, stopDefault);
+  let stopDefault = (e) => {
+    if (e.target.matches('.' + CSS.piece)) {
+      e.preventDefault();
+    }
+  };
+  document.body.addEventListener('mousedown', stopDefault);
+  document.body.addEventListener('mousemove', stopDefault);
 
   // mouse drag pieces
-  boardEl.on('mousedown', '.' + CSS.square, mousedownSquare);
-  containerEl.on('mousedown', '.' + CSS.sparePieces + ' .' + CSS.piece,
-    mousedownSparePiece);
+  boardEl.addEventListener('mousedown', mousedownSquare);
+  containerEl.addEventListener('mousedown', mousedownSparePiece);
 
   // mouse enter / leave square
-  boardEl.on('mouseenter', '.' + CSS.square, mouseenterSquare);
-  boardEl.on('mouseleave', '.' + CSS.square, mouseleaveSquare);
-
-  // IE doesn't like the events on the window object, but other browsers
-  // perform better that way
-  if (isMSIE() === true) {
-    // IE-specific prevent browser "image drag"
-    document.ondragstart = function() { return false; };
+  boardEl.addEventListener('mouseenter', mouseenterSquare);
+  boardEl.addEventListener('mouseleave', mouseleaveSquare);
 
-    $('body').on('mousemove', mousemoveWindow);
-    $('body').on('mouseup', mouseupWindow);
-  }
-  else {
-    $(window).on('mousemove', mousemoveWindow);
-    $(window).on('mouseup', mouseupWindow);
-  }
+  window.addEventListener('mousemove', mousemoveWindow);
+  window.addEventListener('mouseup', mouseupWindow);
 
   // touch drag pieces
   if (isTouchDevice() === true) {
-    boardEl.on('touchstart', '.' + CSS.square, touchstartSquare);
-    containerEl.on('touchstart', '.' + CSS.sparePieces + ' .' + CSS.piece,
-      touchstartSparePiece);
-    $(window).on('touchmove', touchmoveWindow);
-    $(window).on('touchend', touchendWindow);
+    boardEl.addEventListener('touchstart', touchstartSquare);
+    containerEl.addEventListener('touchstart', touchstartSparePiece);
+    window.addEventListener('touchmove', touchmoveWindow);
+    window.addEventListener('touchend', touchendWindow);
   }
 }
 
 function initDom() {
   // build board and save it in memory
-  containerEl.html(buildBoardContainer());
-  boardEl = containerEl.find('.' + CSS.board);
+  containerEl.innerHTML = buildBoardContainer();
+  boardEl = containerEl.querySelector('.' + CSS.board);
 
   if (cfg.sparePieces === true) {
-    sparePiecesTopEl = containerEl.find('.' + CSS.sparePiecesTop);
-    sparePiecesBottomEl = containerEl.find('.' + CSS.sparePiecesBottom);
+    sparePiecesTopEl = containerEl.querySelector('.' + CSS.sparePiecesTop);
+    sparePiecesBottomEl = containerEl.querySelector('.' + CSS.sparePiecesBottom);
   }
 
   // create the drag piece
   var draggedPieceId = createId();
-  $('body').append(buildPiece('wP', true, draggedPieceId));
-  draggedPieceEl = $('#' + draggedPieceId);
+  document.body.append(buildPiece('wP', true, draggedPieceId));
+  draggedPieceEl = document.getElementById(draggedPieceId);
 
   // get the border size
-  BOARD_BORDER_SIZE = parseInt(boardEl.css('borderLeftWidth'), 10);
+  BOARD_BORDER_SIZE = parseInt(boardEl.style.borderLeftWidth, 10);
 
   // set the size and draw the board
   widget.resize();