2

Let's say we have a unordered list with a class:

    <ul class="list-class">
        <li><a href="#">All</a></li>
        <li><a href="#">Breakfast</a></li>
        <li><a href="#">Lunch</a></li>
        <li><a href="#">Dinner</a></li>
        <li><a href="#">Snack</a></li>
   </ul>

Let's say now I wanted to create some function that does different things based on which item has been clicked on:

function whichElement() {
    alert("The -- Link has been clicked");
}

How can this be done without creating a separate function for each item and writing an inline onclick="" event? I'm open to using jQuery as well.

5
  • Why not to use jquery Commented Jun 25, 2013 at 5:12
  • The easiest way is to give the list items or links classes of their own. Anything in particular that would make that a bad idea? Commented Jun 25, 2013 at 5:14
  • stackoverflow.com/questions/1207939/… Commented Jun 25, 2013 at 5:14
  • No not at all, but is there a way to simply determine this? Potentially using "this"? I'm just learning JS for the first time. Commented Jun 25, 2013 at 5:15
  • @Arun have you check my answer?is it helpful? Commented Jun 25, 2013 at 7:57

8 Answers 8

1

How about this if I understand correctly:

var items = document.querySelectorAll('.list-class li');

[].forEach.call(items, function(item){

  var text = item.textContent.trim().toLowerCase();

  item.addEventListener('click', function(){
    if (text == 'all') {
      //...
    }
    //...
  });
});
Sign up to request clarification or add additional context in comments.

2 Comments

Would be worth mentioning that some of these methods require a modern browser, or the methods require shimming. i.e. querySelectorAll, forEach, textContent, trim and addEventListener, current codes requires IE9+ but +1 for POJS solution.
[].forEach.call will create an empty Array in the memory while Array.prototype.foreach.call doesn't.
1

You may try this

function addEvent(elem, event, fn)
{
    if (elem.addEventListener)
    {
        elem.addEventListener(event, fn, false);
    }
    else
    {
        elem.attachEvent("on" + event, function() {
            return(fn.call(elem, window.event));   
        });
    }
}

addEvent(window, 'load', function(e){
    var list = document.querySelector('.list-class');
    addEvent(list, 'click',  function(e){
         e = e || window.event;
         var el = e.target || e.srcElement;
         alert(el.innerHTML);
    });
});

DEMO.

2 Comments

I'm not sure why you only went half way with your cross-browser POJS solution? You created a cross-browser addEvent but then you use ´querySelector´ which requires IE8+. Still, +1 for a POJS solution.
Yes, I mentioned that it is IE8+
0

Add a click handler to the ul, something like:

$('.list-class').on(
  'click',
   function(e){
     e = e || event;
     var from = e.target || e.srcElement;
     if (/^a$/i.test(from.tagName)){
        alert('you clicked '+from.innerHTML);
     }
   });

See this jsFiddle

3 Comments

Would it not have been better to use jquery's event delegation instead of testing for the tag and why not a simple from.tagName === "a" instead of regex test?
Maybe, but what do you know - this is event delegation. JQuery will use the same mechanics internally. test: some browsers report 'A', others 'a' for the tagname, so test is a bit shorter compared to from.tagName === "a" || from.tagName === "A".
Perhaps I didn't explain myself so well, yes you have a form of "direct delegation", see jquery on event delegation. jquery should also take care of the e || event and target || srcElement for you by "normalisation" and hence are unnecessary. Then regarding tagName by John Resig himself. Gives you final code in jquery as per this jsfiddle. This is what I was trying to convey.
0

Do a Jquery Trick as

$("#list-class li").click(function() {
    alert($(this).prevAll().length+1);
});

Here is the FIDDLE

Comments

0

EDIT: event.target returns DOM element that initiated the event.

$('.list-class').click(function(e){  
   alert(e.target.nodeName);
});

Check this in JSFiddle

1 Comment

With this, I could of course click on an li element and not specifically the contained a element and it would fire the alert.
0

Not to jump on the bandwagon as this is similar to others (but not quite)...

$('.list-class>li').on('click',
   function(){
      alert('clicked ' + $('a',this)[0].innerHTML); //eg "clicked Lunch" etc
   }
);

http://jsfiddle.net/znySy/

This simply alerts the text of the link clicked, but equally within the function you could switch on the text eg...

function(){
    switch ($('a',this)[0].innerHTML) {
        case 'Lunch'     : // do something for Lunch
        case 'Breakfast' : // do something for Breakfast
        default          : // do something for not Lunch or Breakfast
    }
}

Comments

0

You can do it in POJS like so, this should be cross-browser compatible and doesn't use any 3rd party libraries. Other advantage is that there is only one event listener per element of the named class, uses event propagation.

Javacsript

/*jslint maxerr: 50, indent: 4, browser: true */
/*global alert */

(function () {
    "use strict";

    function addEvent(elem, event, fn) {
        if (typeof elem === "string") {
            elem = document.getElementById(elem);
        }

        function listenHandler(e) {
            var ret = fn.apply(null, arguments);

            if (ret === false) {
                e.stopPropagation();
                e.preventDefault();
            }

            return ret;
        }

        function attachHandler() {
            window.event.target = window.event.srcElement;

            var ret = fn.call(elem, window.event);

            if (ret === false) {
                window.event.returnValue = false;
                window.event.cancelBubble = true;
            }

            return ret;
        }

        if (elem.addEventListener) {
            elem.addEventListener(event, listenHandler, false);
        } else {
            elem.attachEvent("on" + event, attachHandler);
        }
    }

    function whichElement(e) {
        var target = e.target;

        if (target.tagName === "A" && target.parentElement.tagName === "LI" && target.parentElement.parentElement.className === "list-class") {
            alert("The " + target.firstChild.nodeValue + " Link has been clicked");
        }
    }

    addEvent(document.body, "click", whichElement);
}());

On jsfiddle

If you were using some newer/custom HTML tags or XML then you may need to consider tagName case sensitivity, and write the following to be certain.

if (target.tagName.toUpperCase() === "A" && target.parentElement.tagName.toUpperCase() === "LI" && target.parentElement.parentElement.className === "list-class") {

In jquery terms the above could be written as

Javascript

$(document).on('click', '.list-class>li>a', function (e) {
    alert("The " + e.target.firstChild.nodeValue + " Link has been clicked");
});

On jsfiddle

In jquery they call this event delegation.

3 Comments

Understood, of course if you keep your own library of functions then jquery becomes pretty redundant, and you demystify the hidden magic. :)
Oh yeah I'm not one of those people that doesn't understand that jQuery is just a JS library. It just makes some stuff really easy to write! Good answer though btw! Nice to see some POJS
Probably not. My pet hate (one of)
0
<ul class="list-class">
        <li><a href="#" id="hrefID1">All</a></li>
        <li><a href="#" id="hrefID2">Breakfast</a></li>
        <li><a href="#" id="hrefID3">Lunch</a></li>        
   </ul>
 <script>
$(".list-class li").find('a').each(function(){
    $(this).click(function(){
        switch($(this).attr('id'))
        {
            case "hrefID1";
                    //do what ever 
                    break;
            case "hrefID2";
                    //do what ever 
                    break;
            case "hrefID3";
                    //do what ever 
                    break;
        }
    });
});
</script>

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.