user7341673
user7341673

Reputation:

Javascript onclick event on getElementsByClassName

I have a svg map and I am putting that into object and I am trying to create all path with id clickable.

For that I am doing this to get svg object :

 let a = document.getElementById("biharsvg")

And I am putting that into svg doc like this:

   var svgDoc = a.contentDocument;

And now I am getting all the values of certain class using this:

  let de = svgDoc.getElementsByClassName("fil0");

I can also get the attribute id value using this:

var i;
for (i = 0; i < de.length; i++) {
  var j = de[i].getAttribute("id");
   console.log(j);

}

I want to add a click event on each attribute id and get the value when I am doing this:

var i;
for (i = 0; i < de.length; i++) {
  var j = de[i].getAttribute("id");
   console.log(j);
  svgDoc.getElementById(j).onclick = function() {
      modal.style.display = "block";  
        console.log(this.getAttribute("id"));
    }
}

This is working fine and I am getting all the values but in jquery I can use this:

 $(de).click(function(){
   alert(this.getAttribute("id"));
});

Is there any way I can use something like this in javascript without loop. My question is what is the best possible way to make this work in javascript.

Upvotes: 0

Views: 1032

Answers (3)

connexo
connexo

Reputation: 56740

I find for..of to be the most convenient and readable syntax:

for (const element of svgDoc.getElementsByClassName("fil0")) {
  console.log(element.id);
}

Upvotes: 0

user5734311
user5734311

Reputation:

I just want to show an alternative way, pointed out by CBroe, where a click on the document is checked for its event target:

let de = Array.from(mylist.getElementsByClassName("fil0"));
document.addEventListener('click', function(e) {
  const el = e.target;
  if (de.indexOf(el) < 0) return false;
  alert(el.innerHTML);
});
<ul id="mylist">
  <li>one</li>
  <li class="fil0">two*</li>
  <li class="fil0">three*</li>
</ul>

<p>* has click event assigned indirectly</p>

This has the additional benefit that it only uses a single handler function, and if the indexOf() condition is changed to something like classList.contains(), it will even work for elements that don't exist yet.

Upvotes: 0

Asons
Asons

Reputation: 87191

The javascript version for jQuery's

$(de).click(function(){
   alert(this.getAttribute("id"));
});

would be something like

Array.from(de).forEach( function(el){
    el.addEventListener('click', function() {
        alert(this.getAttribute("id"));
        // or "this.id" should work too
    });
});

To be noted, when doing $(de).click(function(){...} with jQuery, it also loops, internally.


And as commented, with arrow functions you could shorten the code even more

Array.from(de).forEach(el => el.addEventListener('click', function () {...}))

var de = document.querySelectorAll('span');

Array.from(de).forEach(el => el.addEventListener('click', function () {
  alert(this.id);
}))
span {
  display: inline-block;
  padding: 20px;
  margin: 0 5px;
  border: 1px dotted black;
}
span::after {
  content: attr(id)
}
<span id="nr1">click </span>
<span id="nr2">click </span>
<span id="nr3">click </span>


Updated based on a comment.

The main difference between your existing loop and the above is, the above is more efficient, with a cleaner/shorter code.

In your original loop

var i;
for (i = 0; i < de.length; i++) {
  var j = de[i].getAttribute("id");
   svgDoc.getElementById(j).onclick = function() {
      modal.style.display = "block";  
        console.log(this.getAttribute("id"));
    }
}

you iterate through the element array de, get its id and then make a new call using getElementById to get the element you already have.

With the kept syntax/logic, your existing code could been simplified to something like this

for (var i = 0; i < de.length; i++) {
    de.onclick = function() {
        modal.style.display = "block";  
        console.log(this.getAttribute("id"));
    }
}

Upvotes: 1

Related Questions