From a4f98005bc8fd0f1e9362d824de4d1948a03a756 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 21 Dec 2022 00:27:55 +0100 Subject: [PATCH] Remove all jQuery from chessboard.js that does not involve animations. --- www/js/chessboard-0.3.0.js | 269 +++++++++++++++++++------------------ 1 file changed, 137 insertions(+), 132 deletions(-) diff --git a/www/js/chessboard-0.3.0.js b/www/js/chessboard-0.3.0.js index 4b24ec0..c45feeb 100644 --- a/www/js/chessboard-0.3.0.js +++ b/www/js/chessboard-0.3.0.js @@ -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(); -- 2.39.2