I'm trying to create a user script for the Chess.com website. I need to detect changes in the class attribute on certain elements on the page.
There is a small problem: certain mutations of the class attribute are missed by the observer.
My question in short: does anyone have any idea, from the general, conceptual point of the MutationObserver
(at least), what might be the reason of this?
A more detailed question:
I'll post the script below, in case anyone wants to try, but the behavior is this:
- I attached an observer to a black knight (I play for black), whichever appears first in the DOM, when I
pointerdown
on it, it is added a 'dragging' class. One change is observed, which is OK.
Then I release the pointer, no changes seem to occur to the class attribute, no observer call.
Then I pointerdown
again on the knight tile, to remove 'selection' fro it (not to make a move) and this is what I see (this step is marked with red):
An array of 3 MutationRecords is passed to the observer callback:
- in the first record we see the the old value is the same as the current value from step 1 (not marked with red) (which is normal and expected);
- in the second record (change 2) we see that the old value was
piece bn dragging
while the current value from the previous record (change 1 in the marked block) was piece bn square-28
. This means that somewhere in between the 'square-28' class had been removed and the 'dragging' one added and no mutation record for this has been reported. The same problem is with step 3.
Some additional thoughts:
I tried to reproduce such a situation on another dummy page, but I failed, the changes are always reported (even if they don't occur actually, like when removing a class which wasn't present elem.classList.remove('unexisting-class')
).
Firefox and Chrome both have the same behavior, so it looks like not a bug
It can't be a call to observer.takeRecords()
elsewhere, since in that case the queue would be completely empty, and change 1 wouldn't be present. So apparently the queue of changes is not empty, yet some changes, which must be there, are abscent.
It can't be an overridden MutationObserver
, since one seem to contain [native Code], no definition of it was present in the scripts.
The script is:
// ==UserScript==
// @name so-question-chess.com
// @version 0.0.0-0
// @include https://www.chess.com/play/*
// @run-at document-end
// @grant none
// ==/UserScript==
(function() {
'use strict';
const chessBoard = document.querySelector('chess-board');
const observerBoard = new MutationObserver((changes) => {
// attach the observer to the first black knight, when one appears
for (const change of changes) {
if (change.type === 'childList') {
const addedNode = change.addedNodes.item(0);
if (!addedNode) {
continue;
}
const classList = addedNode.classList;
//detect a black knight
if (classList && classList.contains('bn') && classList.contains('piece')) {
//The relevant part, the observer which observes changes on the class
//attribute on the black knight piece
const observerPiece = new MutationObserver((changes) => {
console.group('single change array');
for (const change of changes) {
console.group('single change item');
console.count('change');
console.log('current value: ' + change.target.attributes.class.value);
console.log('old value: ' + change.oldValue);
console.groupEnd();
}
console.countReset('change');
console.groupEnd();
});
observerPiece.observe(addedNode, {
attributeFilter: ['class'],
attributeOldValue: true,
subtree: false,
});
//End of the relevant part
observedBoard.disconnect();
break;
}
}
}
});
observerBoard.observe(chessBoard, {subtree: false, childList: true});
})();
I have no idea of why this is happening, and would be very grateful, if someone pointed to the reason of this.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…