ARTICLE AD BOX
I have a JS script that swaps out an element's inner text with an alternative held in a data-* attribute:
<span data-swapinnertext="new text">old text</span>I have been using this, and it works fine to a point. The point being that there's only one swap on the page:
function swapInnerText0() { if (document.querySelectorAll('span[data-swapinnertext]').length > 0) { var s, spans = document.querySelectorAll('span[data-swapinnertext]'); for (s = 0; s < spans.length; s++) { var swapText = spans[s].dataset.swapinnertext, innerText = spans[s].innerText; spans[s].onmouseover = function() { this.innerText = swapText; } spans[s].onmouseout = function() { this.innerText = innerText; } spans[s].onclick = function() { this.innerText = swapText; this.onmouseover = null; this.onmouseout = null; this.removeAttribute('data-swapinnertext'); } } } }However, if there's more that one, then the onmouseout event replaces the text with the value from the last member of span[s]. I realize why this is the case, so I sought to fix it.
This works, creating temporary data-* cache attributes to hold the text versions for each element:
function swapInnerText1() { if (document.querySelectorAll('span[data-swapinnertext]').length > 0) { var s, spans = document.querySelectorAll('span[data-swapinnertext]'); for (s = 0; s < spans.length; s++) { spans[s].setAttribute('data-swapcache1', spans[s].dataset.swapinnertext); spans[s].setAttribute('data-swapcache2', spans[s].innerText); spans[s].onmouseover = function() { this.innerText = this.dataset.swapcache1; } spans[s].onmouseout = function() { this.innerText = this.dataset.swapcache2; } spans[s].onclick = function() { this.innerText = this.dataset.swapcache1; this.onmouseover = null; this.onmouseout = null; this.removeAttribute('data-swapinnertext'); this.removeAttribute('data-swapcache1'); this.removeAttribute('data-swapcache2'); } } } }But it is inelegant. What I had tried to earlier do was create a 2D array of the elements and use that to ensure that the text versions for each element were separated from the others:
function swapInnerText2() { if (document.querySelectorAll('span[data-swapinnertext]').length > 0) { var sp, sw, spans = document.querySelectorAll('span[data-swapinnertext]'), swaps = Array(); for (sp = 0; sp < spans.length; sp++) { var swapText = spans[sp].dataset.swapinnertext, innerText = spans[sp].innerText; swaps.push(Array(swapText, innerText)); } for (sw = 0; sw < swaps.length; sw++) { var newText = swaps[sw][0], oldText = swaps[sw][1]; swaps[sw].onmouseover = function() { this.innerText = newText; } swaps[sw].onmouseout = function() { this.innerText = oldText; } swaps[sw].onclick = function() { this.innerText = newText; this.onmouseover = null; this.onmouseout = null; this.removeAttribute('data-swapinnertext'); } } } }And this is where things go weird. None of the swaps[sw] objects respond to the mouse events. I placed alert() outside the anonymous functions, and they picked up that swaps[sw] were objects, the index and text values for each one, but within the functions nothing happened.
I've racked what little brain I have, and searched extensively, but simply cannot understand why the mouse events don't work in the third version—which I prefer over the second—but do in the other two.
