2

I am trying to console.log the value of data-number attribute of <span> on click event using JavaScript. Multiple spans are dynamically created during the execution of the code on the client side and each of them have a class "dynamic-span".

Sample:

<span class="dynamic-span" data-number="1">This is a dynamic span</span>

So when the above span is clicked, number "1" will be console logged.

I am able to log the number using jQuery.

$("body").on("click", ".dynamic-span", function (e) {
    e.preventDefault();
    var number = $(this).data("number");
    console.log(number);
});

I want to achieve the same result using plain JavaScript.

I am targeting the span using the "dynamic-span" class.

var elems = document.getElementsByClassName("dynamic-span");

So, I am able to get the spans using the ClassName. But I am getting HTMLCollection and not an Array and the for loop is not working.

Code:

var
    elems = document.getElementsByClassName("dynamic-span"),
    i;

for (i = 0; i < elems.length; i++) {
    elems[i].addEventListener("click", function (e) {
        console.log(this.getAttribute("data-number"));
    });
}

I have also checked the following StackOverflow question JavaScript click event listener on class but no success.

The following reference https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByClassName suggests the Element.getElementsByClassName() method returns a live HTMLCollection.

Kindly suggest a way to accomplish the above task.

Community
  • 1
  • 1
yusufshakeel
  • 439
  • 3
  • 11
  • 22

1 Answers1

2

hopefully this should do it for you:

document.body.onclick = function (e) {
    //get event object (window.event for IE compatibility)
    e = window.event || e;
    //get target dom object reference
    var targetDomObject = e.target || e.srcElement;

    //extra checks to make sure object exists and contains the class of interest
    if ((targetDomObject) && (targetDomObject.classList) && (targetDomObject.classList.contains("dynamic-span"))) {
        var number = targetDomObject.getAttribute("data-number");
        console.log(number);
    }
}

This makes use of bubbling. Whenever an event fires it will move up through all the objects parents until it is marked as handled or there are no more parents. So by attaching to the body's click event it will catch all unhandled click events on the page. The top of the method gets a reference to the event information then it pulls the initial target object from the event. Then all you need to do is see if the object is the object you want to handle and handle it.

Here is a jsfiddle of the code: https://jsfiddle.net/t4jqtLas/

David
  • 3,653
  • 2
  • 24
  • 26
  • yes it worked!. one question though, what if i want to loop through the HTMLCollection that i got earlier. is there a proper way to do it because the for-loop was not working? – yusufshakeel Sep 09 '16 at 15:29
  • 1
    @yusufshakeel — You said the elements were created dynamically. If you loop over the collection, then you only loop over the elements that exist at the time. – Quentin Sep 09 '16 at 15:31
  • @Quentin how to loop over the ones that are created dynamically. i am able to do it using jquery. what is the proper way to do it using plain javascript for the dynamic spans. the one pointed above by David works. but is there any alternative? – yusufshakeel Sep 09 '16 at 15:45
  • 1
    @yusufshakeel — The jQuery code you put in the question uses event delegation … just like this answer. – Quentin Sep 09 '16 at 15:51