Swapping text inside class (not ID)

Hi,

I have this script with works well to swap the text inside the id on clicking.

function changeText(idElement) {
    var element = document.getElementById('change');
    if (idElement) {
        if (element.innerHTML === 'Read more...') element.innerHTML = 'Close';
        else {
            element.innerHTML = 'Read more...';
        }
    }
}

 <a id="change" onClick="javascript:changeText(1)">Read more...</a>

The problem is that there are up to 4 “change” elements in the page.

Is it possible to replace the ids for a classes?

Thanks.

document.getElementsByClassName("example");

Update your HTML to be class=“” and not ID=“”

You need to loop over them.

var elements = document.getElementByClassName('change');
var elmLen = elements.length;

for(var i=0; i < elmLen; i++) {
    alert(elements[i].innerHTML);
}

This will loop over all your .change classes.

The rest of the logic is up to you. Inside the for loop just access the current element by elements[i] just like you are with element above.

Alternatively, you could use jQuery and let it do the work for you. Instead of the loop above, you could just call the class name then the $.each() method.

$('.change').each(function() {
    var classText = $(this).text();
    var readMore = 'Read More...';
    
    if(classText === readMore) {
       $(this).text('Close');
    } else {
        $(this).text(readMore);
    }
});

A much shorter way to write that in plain JavaScript is to use the forEach method:

[].forEach.call(document.querySelectorAll('.change'), function(el) {
alert(el.innerHTML);
});

in this case instead of using element[i] to reference the current element the code has already copied the current element to el for you (or whatever you decide to call the function parameter).

1 Like

That’s a nice idea Felgall.

I’ve been uneasy though about using .forEach.call on a regular basis by itself for it tends to raise more questions from other seeing it. Putting it in a suitably named function has helped to alleviate such concerns.

function forEachElement(nodeList, callback) {
    [].forEach.call(nodeList, callback);
}

var elements = document.querySelectorAll('.change');
forEachElement(elements, function(el) {
    alert(el.innerHTML);
});

Someday we’ll be able to eventually use for (... of ...) to iterate over each of the elements, but only going to be when ES6 has wide enough support.

Oh dear, it’s not shorter now though. :grin:

1 Like

The difference being that getElementsByClassName is dynamically updated if the classes in the page change during the loop processing whereas the .forEach.call mapping of it extracts a static array of the elements that have the class at the time that statement executes to convert to an array whereas querySelectorAll is static in the first place and so should be both faster and not have any unexpected side effects.

Of course antiquated browsers don’t support querySelectorAll but then getElementsByClassName hasn’t been around that much longer. So which you choose might depend on which antiquated browsers you need to support (of course then you’d need a polyfill or es5shiv for forEach as well). Fortunately the antiquated browsers that don’t support the 2011 version of JavaScript are not used by so many people now.

The other thing with using querySelectorAll is that it makes it possible to do the same code for ANY selector - id, class, tag or more complex combinations.

1 Like

Yes, my bad. Towards the end of things I blindly copy/pasted that part from the previous post. Things have been edited to correct.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.