1

First of all, there are alot similar questions outside not only on this website.

But I searched at least 3 hours for a solution but never found something that was fitting and working.

Also some threads where created long time ago, so some solutions are more complicated/not working and dont use todays possibilities.


So here's the Problem:

HTML File could look like this:

<ul>
  <li><a class="content" href="this.com">I should change!</a>
  </li>
  <li><a class="content" href="any.com">I don't change</a>
  </li>
  <li><a class="content" href="this.com">I should change! too</a>
  </li>
  <li><a class="content" href="any.com">I don't change</a>
  </li>
  <li><a class="content" href="this.com">I also should change!</a>
  </li>
</ul>

Now I want to get all elements wich have attribute class="content".

(I tried solutions with document.getElementsByClassName() and document.querySelector().)

And then change only those wich also contain href="this.com".


And here are the "challenges" the solution should pass:

  • no jQuery and co. -> pure javascript

  • you can only use javascript (the whole solution should work by injecting script.js into a website)

  • if it is possible: no loops

I don't want to make it more complicated than it should be, just thougth that there must be a way to change multiple objects easily like this just for classes:

document.getElementById("theID").innerHTML = "text"

So if there is any way to make it without loop it would be great

(saw alot of solutions with some counting funtion "i < variable.length; i++" when it comes to loop-solution. But think it's much cleaner with simple function like .innerHTML = "" than running a loop)

  • And last: if you know how I could easily delete <li></li> of the selected objects and would tell me know, I would be very thankful.

(I know .parentNode but if I try with this it's more an "Error and Retry Adventure")

Also have trouble with deleting parent of parent or could I just use .parentNode.parentNode ?


If anyone has an idea or working solution I would be very happy.

Thank you very much!

3
  • Firstly, what didn't work about getElementsByClassName? Second, if it is possible: no loops - EH? Commented Nov 18, 2014 at 11:48
  • If you want to act on more than one element, you'll need a loop (or a function which internally uses a loop). The example you gave of not needing a loop (by using getElementById and innerHTML) only acts on a single element. Commented Nov 18, 2014 at 11:52
  • One question/observation: If you unwrap the selected elements by removing the <li> it becomes invalid html. a <ul> should have <li> children. Commented Nov 18, 2014 at 12:52

4 Answers 4

1

No, it cant be done without a loop, you want to act on multiple elements, you need a loop

window.onload = function() {
    var elems = document.querySelectorAll('.content[href="this.com"]');
    for(var i=0;i<elems.length;i++){
      elems[i].innerHTML = "Im changed."   
    }
}
<ul>
  <li><a class="content" href="this.com">I should change!</a>
  </li>
  <li><a class="content" href="any.com">I don't change</a>
  </li>
  <li><a class="content" href="this.com">I should change! too</a>
  </li>
  <li><a class="content" href="any.com">I don't change</a>
  </li>
  <li><a class="content" href="this.com">I also should change!</a>
  </li>
</ul>

As noted in the comments, the above could be changed to:

window.onload = function() {
    [].forEach.call(document.querySelectorAll('.content[href="this.com"]'),function(e){
       e.innerHTML = "Im changed by forEach, its still a loop!"; 
    });
}

But its still just a loop, just hidden behind a method which calls a delegate for each item in the supplied array!

As for unwrapping your <li> his might be useful: Removing wrapper div without Jquery (raw javascript) (The procedure for doing this with a <li> would be more or less the same).

Sign up to request clarification or add additional context in comments.

4 Comments

This answer looks good to me. There is a way to not use a loop in the answer (although internally there will presumably be one...) Note I don't recommend this! Just adding it for completeness. [].forEach.call(document.querySelectorAll('.content[href="this.com"]'), function(el) { el.innerHTML = 'Changed'; });
@Shai - forEach is just a loop.
This is Awesome! It still uses a loop as you said, but seems to me more smooth as you dont use a var and then calc +1 over and over again. This is exactly what i searched for.Very elegant (in my eyes). Thank you so much!
Is it also possible to search for different "href"? Like: ('.myClass{[href="one.com"]|[href="two.com"]}') so the selection would include myClass objects with Link to "one.com" and objects with Link to "tow.com".
1

Test it :

<script>
window.onload = function() {
    var contentClass = document.getElementsByClassName("content");
    for (var i = 0; i < contentClass.length; i++) {
        if (contentClass.item(i).getAttribute("href") == "this.com") {
            contentClass.item(i).innerHTML = "Changed !";   
        }
    }
}
</script>

1 Comment

jsfiddle.net/aLn9so91 (If you're going to go to all that effort, may as well provide a working copy)
1

Try this for changing the first one,

document.querySelectorAll('.content[href="this.com"]')[0].innerHTML = "Changed!!!"

To apply to all selected elements,

var elems = document.querySelectorAll('.content[href="this.com"]');
Array.prototype.sort.call(
    Array.prototype.slice.call(elems, 0), 
    function(el1,el2){
        el1.innerHTML="Changed!!!"; 
        el2.innerHTML="Changed!!!"
    }
)

4 Comments

Will it select all elements or just one?
It will only select one. Look for the [0] its the first element in the result array of querySelectorAll
If ther would be a way to select all items in this arry, then this would be perfect. But it seems that i have to use loop for this :S
This is the best you could get using native sort function without a loop IMHO. Check out the fiddle. jsfiddle.net/aLn9so91/1
0
// get all elements which contents className="content"
var contents = document.getElementsByClassName('content');

// In a loop
for (i = 0; i < contents.length; i++) {
    // If current element contains href="this.com"...
    if (contents[i].href.indexOf("this.com") > -1)
        // then change its innerHTML
        contents[i].innerHTML = "text";
}

// second way, little faster that first one
// get all A elements
var as = document.getElementsByTagName('a');

// In a loop
for (i = 0; i < as.length; i++) {
    // If current element contains href="this.com"...
    if (as[i].href.indexOf("this.com") > -1)
        // then change its innerHTML
        as[i].innerHTML = "text";
}

// third way, long. Do not do such a things
var allElements = document.getElementsByTagName("*");

// In a loop
for (i = 0; i < allElements.length; i++) {
    // If current element contains className="content"...
    if (allElements[i].className == "content")
        // And if its href="this.com"
        if (allElements[i].href.indexOf("this.com") > -1)
            // Change its innerHTML
            allElements.innerHTML = "text";
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.