I am a Javascript newbie. I'm trying to write a userscript for Chrome with Tampermonkey. I have managed to create some code to change some words in a <p>
to a shortened version, but unfortunately this makes the rest of the text, which includes some other code, not work.
To reach this stage, I have tried all day. But with my limited knowledge, I am stuck on how to proceed despite googling how to solve this.
function run () {
var target = document.querySelector('#dipContainer dip-info-top div.new-dip-info div.col-md-4 div:nth-child(2) div:nth-child(1) p')
if (target) {
var str = target.innerHTML;
str = str.replace(" String to find", "Shortened");
target.innerHTML = str;
} else {
setTimeout(run, 500);
}
}
//The below detect any time the <p> changes and run the code to shorten the term. It works.
waitForKeyElements (
"#dipContainer dip-info-top div.new-dip-info div.col-md-4 div:nth-child(2) div:nth-child(1) p",
run
);
})();
Unfortunately, the <p>
also contains some other code after the string I wanted shortened, which allows you to click on some to get some stats come up.
<span class="player-info-stat">
<a class="badge ng-binding disabled" ng-class="{'disabled': history.itemModerationCount === 0}" ng-click="history.itemModerationCount > 0 ? openHistoryModal('itemHistory') : null" data-ol-has-click-handler="">0</a>
</span>
If I run my code to change to the shortened text, you can't click on these anymore for the stats to show up, even though it still does detect if there are stats available.
Does anyone know why? From what I've search, the replace
command should only change the text you want and leave the rest intact?
It sounds like the child elements have event listeners on them, in which case reassigning the innerHTML
of the parent will corrupt the listeners.
Rather than replacing the innerHTML
, search for text nodes, and set their node value to the replaced text:
// https://stackoverflow.com/questions/2579666/
function nativeTreeWalker(parent) {
var walker = document.createTreeWalker(
parent,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while (node = walker.nextNode()) {
textNodes.push(node);
}
return textNodes;
}
document.querySelector('p').addEventListener('click', () => console.log('p clicked'));
const textNodes = nativeTreeWalker(document.querySelector('#div'));
textNodes.forEach((textNode) => {
textNode.nodeValue = textNode.nodeValue.replace(/text/g, 'replaced');
});
<div id="div">
text
<p>clickable</p>
text
</div>