Assigning events to elements with same class name

Hello all,

I am trying to apply events to elements that share the same class but can’t get it to work properly.
This is what I have:

function RUNATPAGELOAD(){
	var ttt = document.getElementsByClassName('M');
	for (i=0;i<ttt.length;i++){
		ttt[i].setAttribute('draggable', true);
		ttt[i].addEventListener('ondragstart', dragStarted(event), false);
		ttt[i].addEventListener('ondragover', draggingOver(event), false);
		ttt[i].addEventListener('ondragleave', draggingLeave(event), false);
		ttt[i].addEventListener('ondrop', dropped(event), false);
		ttt[i].addEventListener('onclick', editUldDetails(this), false);
         }
}

Any ideas?

This needs to be:

ttt[i].addEventListener(‘ondragstart’, dragStarted, false);

As it’s written now, you’re invoking your callback function at the moment that you’re adding the listener. But what you really want to do is give a reference to the function itself (without the calling parentheses) so it can be invoked later.

And so on for the other lines.

Do you think that it might be better to just have just the one event handler on the document element instead?

But if you take away the parameter (event) the function does not work?

I got a lot of them…
I thought it would be better to assign them to the element upon loading the page rather and also for learning purposes. (I am still new to JS)

The event is ‘click’ - there is no event ‘onclick’

similarly for the others.

You only need to add ‘on’ for event handlers and with JScript’s attachEvent.

Hello felgall,

I removed the “on” but it still isn’t working.

function RUNATPAGELOAD(){
	var ttt = document.getElementsByClassName('M');
	for (i=0;i<ttt.length;i++){
		ttt[i].setAttribute('draggable', true);
		ttt[i].addEventListener('dragstart', dragStarted, false);
		ttt[i].addEventListener('dragover', draggingOver, false);
		ttt[i].addEventListener('dragleave', draggingLeave, false);
		ttt[i].addEventListener('drop', dropped, false);
		ttt[i].addEventListener('click', editUldDetails(this), false);
	}
}

The ‘click’ listener will try to run whatever running editUldDetails(this) returns.

The rest should be running the specified functions when the events are triggered.

We would need to see the actual code for the functions to figure out why they don’t appear to be working when the code tries to run them.

[quote=“Ethannn, post:5, topic:203983, full:true”]
I got a lot of them…[/quote]

Even better then. When you have a lot of elements to deal with, having one event listener is much more efficient than using thousands of event listeners.

You are right it worked except for the click listener.
I have to find a solution for that.
Thanks for your help and sharing your knowledge!

I guess I have misunderstood you.
How can I use one listener for all of them?

Change that to

ttt[i].addEventListener('click', function() {editUldDetails(this)}, false);

to get it working (assuming that ‘this’ points to what you expect it to point to).

You need one listener per type of event.

Instead of attaching them all to each element you could instead attach them to the body tag and then test if the element that triggered the event has the class and process that element if it does from within the listener. That way you only have one dragstart event listener for the page instead of one per element having the class. Similarly for the other events.

Your code works.
I am now trying to follow your advice, but the following does not work:

document.getElementsByClassName('M').addEventListener('click',function (){
	alert("IT WORKS");
},false);

If you are using jQuery, then attaching an event to the body of the document is as simple as:

$('document.body').on('.M', 'click', function (){
	alert("IT WORKS");
});

With vanilla JavaScript, it’s a bit more long winded, and ends up being:

document.body.addEventListener('click', function (evt) {
    if (evt.target.className === 'M') {
	alert("IT WORKS");
    }
}, false);

With all of those other events that you want to add, they can get a bit long-winded so you can reduce the amount of repetition by using a separate function to connect things together.

Here’s an example using the “It works” part.

function itWorks() {
    alert("IT WORKS");
}
function addClassEventHandler(className, eventType, eventFunc) {
    document.body.addEventListener(eventType, function (evt) {
       	if (evt.target.className === className) {
            eventFunc(evt);
        }
    });
}
addClassEventHandler('M', 'click', itWorks);

With that addClassEventHandler function, your code will be as easy as this:

addClassEventHandler('M', 'dragstart', dragStarted);
addClassEventHandler('M', 'dragover', draggingOver);
addClassEventHandler('M', 'dragleave', draggingLeave);
addClassEventHandler('M', 'drop', dropped);
addClassEventHandler('M', 'click', function (evt) {
    editUldDetails(evt.target);
});

Here’s a quick demo of this in action: http://jsfiddle.net/xftx0phk/1/

The main benefit here is that instead of the page having to juggle thousands of event handlers on the page, it instead has an easier time handling just a few handlers attached to the body.

1 Like

You’ve learned me a lot with this. many many thanks!
this is very useful.

Man, it’ll be great to have vanilla event delegation (or just better built-in sugar a la jQuery)

You mean like vanilla JavaScript has provided ever since event listeners were added (and attachEvent for JScript provided the same thing for IE5 through IE8).

I mean instead of
if (evt.target.className === ‘M’) {
//blah
}
directly setting the target in the call as a param. So maybe just sugar, but I like some sugar

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