Closed axelferdinand closed 1 year ago
I now managed to make it work on a clean site, but I can't make it work with my site using AngularJS – do you know of any conflict? :)
Never mind, friend – made it work by putting your wonderful code of JS inside an Angular controller! Thanks for this script, it's really wonderful!
That's so cool that you found a use for it! Hope the comments in the match.js script were helpful, good luck with your project!
Yeah, it's really, really great! Just what I was looking for, and luckily I managed to google the problem in a way leading to this repo... Thanks!!
PS: Using ChatGPT, I did a few improvements to the code (or at least, ChatGPT claims it's improvements). Here's the final result:
/*######################--Start of Main--######################*/
// Define constants for class names and keys
const TEXT_CLASS_NAME = 'text';
const HIGHLIGHT_CLASS_NAME = 'highlight';
const TITLE_KEY = 'title'; // Key for title in dictionary entries
const DESCRIPTION_KEY = 'description'; // Key for description in dictionary entries
function main(dictionaryEntries) {
console.log(dictionaryEntries);
// Get all elements with class 'text'
let textElements = document.querySelectorAll(`.${TEXT_CLASS_NAME}`);
// Loop through all child nodes of the text elements
for (let element of textElements) {
for (let searchNode of element.childNodes) {
listIteration(dictionaryEntries, searchNode, false);
}
}
// Add event listeners for mouseover and mouseout events
document.body.addEventListener("mouseover", (e) => listIteration(dictionaryEntries, e.target, true), true);
document.body.addEventListener("mouseout", (e) => tooltip(null, e.target, false));
}
/*######################--End of Main--######################*/
// Function to iterate through dictionary entries and apply highlighting or tooltips
function listIteration(dictionaryEntries, currentNode, isEventTriggered) {
for (let item of dictionaryEntries) {
if (currentNode.hasChildNodes() && !isEventTriggered) {
makeTargetable(currentNode, item[TITLE_KEY]);
}
if (isEventTriggered) {
if (currentNode.classList.contains(item[TITLE_KEY].toLowerCase())) {
tooltip(item[DESCRIPTION_KEY], currentNode, true);
}
}
}
}
// Function to apply highlighting to a node
function makeTargetable(currentNode, title) {
const REGEX = new RegExp(`\\b${title}\\b`, 'i');
if (currentNode.nodeName === 'P' && currentNode.parentNode.nodeName !== 'A' && currentNode.innerText.match(REGEX) !== null) {
let textNodes = Array.from(currentNode.childNodes).filter(node => node.nodeType === 3);
textNodes.forEach(textNode => {
let text = textNode.nodeValue;
let match = REGEX.exec(text);
if (match) {
let before = document.createTextNode(text.substring(0, match.index));
let highlighted = document.createElement('span');
highlighted.className = `${HIGHLIGHT_CLASS_NAME} ${title.toLowerCase()}`;
highlighted.textContent = match[0];
let after = document.createTextNode(text.substring(match.index + match[0].length));
currentNode.insertBefore(before, textNode);
currentNode.insertBefore(highlighted, textNode);
currentNode.insertBefore(after, textNode);
currentNode.removeChild(textNode);
}
});
}
}
// Function to show or hide tooltips
function tooltip(tip, target, isHovering) {
const tooltipElement = document.getElementById('tooltip');
if (isHovering) {
if (!tooltipElement) {
const tooltipSpan = document.createElement('span');
tooltipSpan.id = 'tooltip';
tooltipSpan.textContent = tip;
target.parentNode.insertBefore(tooltipSpan, target.nextSibling);
}
} else {
if (tooltipElement) {
tooltipElement.parentNode.removeChild(tooltipElement);
}
}
}
// AJAX request to get dictionary entries
(function () {
fetch('/api/dictionary.json')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
main(data);
})
.catch(error => {
console.error('There has been a problem with your fetch operation: ', error);
});
})();
It's supposed to be faster, and user more "modern" approaches. Also, CSS is moved out of the JS.
Have a great day!
Hey there!
This is EXACTLY what I'm looking for... However, I can't make it work on it's own. Are there any dependencies?