Reputation: 746
I made this script that let me change the letter on hover of the specific letter.
I would like to be able to hover a letter, change it to A
and as soon as the mouseleave
event is called, the letter change back to the original letter.
const toLetterize = document.querySelectorAll(
".change p"
);
console.log(toLetterize);
toLetterize.forEach(function (letterized) {
const letters = letterized.innerHTML;
var nHTML = "";
for (var letter of letters) {
nHTML += "<u>" + letter + "</u>";
}
letterized.innerHTML = nHTML;
document.querySelectorAll("u").forEach(function (hoveredLetter) {
hoveredLetter.addEventListener("mouseenter", function (e) {
console.log("hovered")
hoveredLetter.innerHTML = nextLetter(hoveredLetter.innerText);
});
hoveredLetter.addEventListener("mouseleave", function (e) {
console.log("leaving" + nextLetter(hoveredLetter.innerText))
hoveredLetter.innerHTML = nextLetter(hoveredLetter.innerText);
});
});
});
function nextLetter(ch) {
console.log(ch);
if (!ch.match(/[a-z]/i)) {
return "A";
} else if (ch === "A") {
return ch;
}
return String.fromCharCode(ch);
}
div{
font-family: monospace;
}
<div class="change">
<p> The colours of the binding (chosen by me) will be white letters on a blue field – the Greek flag though really of Bavarian origin and imported with the dynasty. Yet in a special way they symbolise the myth well – the white islands scattered over the sea.</p>
</div>
Upvotes: 0
Views: 51
Reputation: 7229
Using CSS
You can do this with simple css and avoid all the JavaScript in the selected answer.
Using the pseudo class ::before we can show different content on hover. The original letter is stored in attribute data-char. And the css attr() function selects it as the content. And on hover we can select some other letter, which could be a constant, a different attribute, or even a css variable.
.change p span::before {
content: attr(data-char);
}
.change p span:hover::before {
content: "A";
}
When the page loads we use a tiny bit of JavaScript to wrap each letter in a span. Yet, after loading we don't need any scripts to make it work.
<span data-char="k"></span>
Snippet
Run the snippet to understand how it works.
let p = document.querySelector('.change p');
p.innerHTML = p.innerText
.split('')
.map(char => `<span data-char="${char}"></span>`)
.join('');
body {
font-family: monospace;
font-size: 20px;
padding: 2rem;
}
.change p span::before {
content: attr(data-char);
}
.change p span:hover::before {
content: "A";
color: red;
}
<div class="change">
<p> The colours of the binding (chosen by me) will be white letters on a blue field – the Greek flag though really of Bavarian origin and imported with the dynasty. Yet in a special way they symbolise the myth well – the white islands scattered over the
sea.</p>
</div>
Upvotes: 2
Reputation: 8161
Your event handlers should take the element triggering the event from the event object in the arguments (e.target
or e.currentTarget
).
Plus you should keep track of the original letter. I put it inside a data attribute (data-original
) when crafting the u
elements holding each letter.
So that the event handler for mouseenter
now just changes the innerText
of the hovered element with A
and the event handler for mouseleave
just changes the innerText
of the element loosing the cursor with the original letter having at the beginning.
const toLetterize = document.querySelectorAll(".change p");
toLetterize.forEach(function(letterized) {
const letters = letterized.innerHTML;
let nHTML = "";
for (let letter of letters) {
nHTML += `<u data-original='${letter}'>${letter}</u>`;
}
letterized.innerHTML = nHTML;
document.querySelectorAll("u").forEach(function(letter) {
letter.addEventListener("mouseenter", function(e) {
const hoveredElement = e.currentTarget;
const currentLetter = hoveredElement.innerText;
hoveredElement.innerText = 'A';
});
letter.addEventListener("mouseleave", function(e) {
const hoveredElement = e.currentTarget;
const originalLetter = hoveredElement.dataset['original'];
hoveredElement.innerText = originalLetter;
});
});
});
div {
font-family: monospace;
}
u{
cursor: pointer;
}
<div class="change">
<p>The colours of the binding (chosen by me) will be white letters on a blue field – the Greek flag though really of Bavarian origin and imported with the dynasty. Yet in a special way they symbolise the myth well – the white islands scattered over the sea.</p>
</div>
Upvotes: 3