您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
If your move is a blunder or inaccuracy, a red circle will signal this on the board.
// ==UserScript== // @name Lichess show mistakes on the board // @description If your move is a blunder or inaccuracy, a red circle will signal this on the board. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js // @grant none // @include http://*.lichess.org/* // @include https://lichess.org/* // @version 1.6 // @namespace https://greasyfork.org/users/729712 // ==/UserScript== let $ = jQuery.noConflict(); $(document).ready(() => { setTimeout(() => { init(); }, 500); }); let clickedElement; const COLORS = { '?': '#E69F00', '?!': '#56B4E9', '??': '#ff3d00', }; const MOVE_TYPES = { Blunder: '??', Mistake: '?!', Inaccuracy: '?', }; /** * Highlight the move type on the board (OTB) */ const highlightMoveTypeOTB = () => { clearBoardIndicators(); const activeMove = getActiveMove(); if (activeMove) { let moveType; moveType = getMoveType(activeMove.innerText); const lm = $('.last-move')[0]; if (moveType) { const color = COLORS[moveType]; lm.innerHTML = `<div> <div style="width: 20px;height: 20px;background: ${color};position: absolute;right: 0;border-radius: 10px;"></div> <div style="position: absolute;right: 0px;top: 0px;font-weight: bold;width: 20px;height: 20px;/*! align-content: space-evenly; */text-align: center;line-height: 20px;color: black;">${moveType}</div> </div>`; } else { lm.innerHTML = ''; } } else { console.log('no active move found'); } }; /** * Returns the move type */ const getMoveType = (text) => { if (text.indexOf(MOVE_TYPES.Blunder) !== -1) return MOVE_TYPES.Blunder; if (text.indexOf(MOVE_TYPES.Mistake) !== -1) return MOVE_TYPES.Mistake; if (text.indexOf(MOVE_TYPES.Inaccuracy) !== -1) return MOVE_TYPES.Inaccuracy; // check this last! return null; }; /** * Clears the board indicators. in case we move away from the main line via explorer */ const clearBoardIndicators = () => { $('.last-move')[0].innerHTML = ''; $('.last-move')[1].innerHTML = ''; }; /** * determines if a button is a review navigation button */ const isReviewNavButton = (but) => { const goodActions = ['first', 'prev', 'next', 'last']; return goodActions.indexOf(but.dataset.act) !== -1; }; /** * returns all the navigation buttons << < > >> */ const getNavButtons = () => { const navButtons = []; const allButtons = document.getElementsByTagName('button'); for (let i = 0; i < allButtons.length; i++) { if (isReviewNavButton(allButtons[i])) { navButtons.push(allButtons[i]); } } return navButtons; }; /** * Returns the active move */ const getActiveMove = () => { const activeElements = document.getElementsByClassName('active'); for (let i = 0; i < activeElements.length; i++) { if (activeElements[i].tagName === 'MOVE') { return activeElements[i]; } } return null; }; /** * Highlight the move types in the moves list */ const highlightMoveTypeITML = () => { const moves = document.getElementsByTagName('move'); for (let i = 0; i < moves.length; i++) { const moveType = getMoveType(moves[i].innerText); if (moveType) { moves[i].style.color = COLORS[moveType]; } } }; const init = () => { // initial highlight of the moves highlightMoveTypeITML(); // set the listeners for the action buttons const navButtons = getNavButtons(); navButtons.forEach((button) => { button.onclick = () => { highlightMoveTypeOTB(); highlightMoveTypeITML(); }; }); // $(document).mousedown((ev) => { // clickedElement = ev.target; // }); // tricky one. a user can also click on the bad move and we need to show the move, or on the // engine line and we need to clear the mistakes. this will double trigger the render when // you click on the arrows $(window).mouseup((ev) => { // const isMove = clickedElement.tagName === "MOVE" || clickedElement.parentElement.tagName === "MOVE"; // const isChoiceButton = ev.target.parentElement.classList == "choices"; setTimeout(()=> { clearBoardIndicators(); highlightMoveTypeOTB(); highlightMoveTypeITML(); }, 50); }); // set the listeners for the key down / up document.onkeyup = function (e) { switch (e.which) { case 32: // spacebar case 37: // left case 38: // up case 39: // right case 40: // down clearBoardIndicators(); highlightMoveTypeOTB(); highlightMoveTypeITML(); break; default: // exit this handler for other keys } }; };