4

This is the jQuery code I have

$('p').click(function(){
    alert("click successful!");
});

This is the JS code I could come up with

window.onload = function() {
    var para = document.getElementsByTagName('p');
    for(var i = 0; i < para.length; i++) {
        para[i].addEventListener('click',function(){
            alert("click successful!");
        });
    }
}

The Javascript code is too bulky, is there a way where I can select a tag by its name and write the code as -

"If any 'p' tag is clicked, alert('click successful')"

instead of looping through all the <p></p> tags? Any alternative way using tag name?

Siddharth Thevaril
  • 3,722
  • 3
  • 35
  • 71

4 Answers4

7

You can use event delegation - add a click handler to a higher level element and check event.target

document.body.addEventListener("click", function(e) {
    if (e.target.tagName.toLowerCase() == "p") alert("click succeeded");
});

Demo: http://jsfiddle.net/jdkr3sch/

Dennis
  • 32,200
  • 11
  • 64
  • 79
  • 2
    This doesn't work. Or rather, it only works if there is nothing but text in the paragraph. As soon as you add any element, even an innocent ``, clicking on that child element won't trigger the alert. – Niet the Dark Absol Oct 25 '15 at 14:17
  • As a side note, `nodeName` is usually a better choice http://stackoverflow.com/questions/4878484/difference-between-tagname-and-nodename And ya, you should check for any ascendant node or node itself being a P element – A. Wolff Oct 25 '15 at 14:17
  • @NiettheDarkAbsol It's wrong to say "this doesn't work" but that is a noteworthy caveat. Once you add in the check for descendants you're back to the bulk that OP wanted to avoid though. – Dennis Oct 26 '15 at 03:57
3

jQuery is "less code" because you're calling a pre-written function. Don't want to use jQuery? Then write your own functions.

function addEventToElements(tagname,handler) {
    var elems = document.getElementsByTagName(tagname);
    for(var i = 0, l = elems.length; i<l; i++) {
        elems[i].addEventListener('click',handler);
    }
}

Now in your actual code, you can just write:

addEventToElements('p',function() {alert("click succeeded");});

Congratulations, you have re-invented jQuery.

... Or not, because the reason jQuery is so popular is that it does a lot more. Things like normalising browser support (for those that use attachEvent or the old onEventName handlers) are half the reason jQuery exists, and you'd have to account for all of them in your own re-invention ;)

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
3

Here's a shorter way.

document.addEventListener('DOMContentLoaded', function() {
    document.body.addEventListener('click', function(evt) {
        if (evt.target.matches('p, p *')) alert('Paragraph clicked!');
    }, false);
}, false);

Notes:

1) This has the advantage of event delegation, which is something I'd suggest looking into. In a nutshell, means you bind the event once, not N times, and then interrogate which element fired it when it fires, i.e. in the callback, not at the point of declaring the event as you are currently.

2) For waiting to use elements, use the DOMContentLoaded event rather than window.onload - the former is (loosely) analogous to jQuery's DOM ready handler.

3) matches() is a relatively modern method and won't work in ancient browsers, or may need a vendor-prefixed version - http://caniuse.com/#feat=matchesselector

Mitya
  • 33,629
  • 9
  • 60
  • 107
1

for selecting:

document.querySelectorAll('p')

(also for more than one element p ).

AFAIK this is the closest thing to $('p')


addEventListener('click',function(){alert("click successful!")}

to add click handler to single element.


to simulate an array you can use the [].slice.call on the dom element collection (in this way you use .forEach() method) .


all together:

[].slice.call(document.querySelectorAll('p')).
forEach(function(x){x.addEventListener('click',
    function(){alert("click successful!")
})})

https://jsfiddle.net/maio/m861hbmh/

maioman
  • 18,154
  • 4
  • 36
  • 42