Forums

The forums ran from 2008-2020 and are now closed and viewable here as an archive.

Home Forums JavaScript jQuery -> Native: Select all tags + addEventHandler, can I do more better?

  • This topic is empty.
Viewing 15 posts - 1 through 15 (of 15 total)
  • Author
    Posts
  • #161867
    shaneisme
    Participant

    So the goal was to remove jQuery dependency from a very small function to pass clicks through to Google Analytics in a more robust nature. This had been working with jQuery without issues, I just hated adding the library in for one function.

    Basically I wanted to change this into native:

    $('a').on('click', function() {
      doSomething();
    });
    

    I have a working example here: http://codepen.io/anon/pen/fLyHG

    I’m one of those guys learning native via jQuery, so I’m still adding all the bells and whistles to my bat-belt. Does anyone have suggestions or articles I can read? I’ve been having difficulty finding examples for this type of thing specifically.

    #161986
    dyr
    Participant

    Your example works, what sort of advice are you looking for? Some things to keep in mind:

    addEventListener vs attachEvent (the latter used for IE5-8 compatibility)

    In your sendClick function you’ve named the event parameter ‘a’ which might be confusing; typically ‘e’, ‘evt’, or ‘event’ is used.

    Abstracting your javascript so it is more generalized and less tightly coupled with the specifics of this use case. Seems trivial for this simple example but the more complex a project becomes, the more value there is in keeping things DRY.

    Some nice-ification:

    Instead of

    function sendClick(a) {
      var el = a.target, label = el.getAttribute('href');
      sendGAEvent(label);
    }
    

    Why not just do…

    function sendClick(event) {
       sendGAEvent(event.target.getAttribute('href'))
    }
    

    Also I’ve not seen anyone write a for loop that way but it’s kind of cool!

    Cheers

    #161987
    shaneisme
    Participant

    Really, I was wondering if this was the best way to do what I wanted (it seems wasteful somehow):

    var a = document.getElementsByTagName('a');
    for (var i=a.length; i--;) {
      a[i].addEventListener('click', sendClick);
    } 
    

    I like your feedback, I’ll definitely update my code to be happier.

    #161990
    dyr
    Participant

    I don’t see anything wrong with that at all. Just keep in mind that addEventListener isn’t truly cross-browser compatible.

    http://stackoverflow.com/questions/2657182/correct-usage-of-addeventlistener-attachevent

    #161991
    shaneisme
    Participant

    Thanks, I’m lucky enough to not have to worry about <IE8… unless I’m not reading that correctly.

    That, and this is just icing on top to get more data out of a user’s visit.

    #162059
    shaneisme
    Participant

    One other question if anyone has insight.

    I’ve been reading up on event order (capturing, bubbling) and I’m not 100% sure I get it.

    When an <a> tag has a child element, say an image, my code is returning undefined trying to find href because it wants to push back the <img> as the click event first.

    To get around this, I’ve hacked this:

    var el = event.target;
    if (el.nodeName == 'IMG') {
      el = el.parentNode;
    }
    

    Of course, this will only work if an <img> tag is the child.

    I tried setting both true and false to the event handler on addEventListener and also stopped the propagation, but it seemed like no matter what I did it would return the children first.

    My desired behavior would be to only return the click event on the <a> ignoring all children elements.

    What am I missing / doing wrong?

    #162069
    dyr
    Participant

    Can you post a PEN with a reduced case?

    http://codepen.io/shawkdsn/pen/pIdDk
    (click a link to alert the href)

    Not able to reproduce what you’re saying.

    #162083
    shaneisme
    Participant

    After viewing yours, I’m clearly doing something wrong, but here’s a pen:

    http://codepen.io/anon/pen/xbqID

    I’m not sending the href directly, because I need the event.target for information to build a label in case the href fails some parameters.

    Edit – I’ve done some tweaking and now can get the href, but now I get it all the time. I still need access to the target information to be able to get things like the ID, innerText, etc.

    http://codepen.io/anon/pen/dAyIw

    #162086
    dyr
    Participant

    http://codepen.io/shawkdsn/pen/oELmG

    This should help you out. Instead of using “event” just use the “this” reference which refers to the function context (the object that invoked the function) which in our case is the Anchor element that fired the ‘click’ event.

    OPTIONAL: I just built up a little data object and filled it with the properties you want. Then you could access those properties individually using data.id, data.href, or together by referencing the object itself : ‘data’ (remember this will be typeof === object, so treat it as such!)

    #162100
    shaneisme
    Participant

    Thanks a lot for your guidance, here’s (nearly) the full program: http://codepen.io/anon/pen/nksai

    #162101
    dyr
    Participant

    Prepare to have your mind blown: http://codepen.io/shawkdsn/pen/Ahpsf

    Everything you wrote to determine the correct label can be summarized in a one-liner!

    As you can see in my example, the label is getting set properly on each of the links.

    Here’s the one-liner:

    function getLabel(context) {
      return isInArray( skipHREF, context.href.toLowerCase() ) ? context.id || context.title || context.innerText : context.href.toLowerCase()
    }
    

    It’s very similar to what you wrote in so far as we’re passing in the context (“this” from the click handler function) but in this case we’re using a ternary operator which I know you’re familiar with because you used it in your code. However we’re also taking advantage of “lazy evaluation” to return the correct value by chaining a bunch of OR ( || ) operators together. http://addyosmani.com/blog/exploring-javascripts-logical-or-operator/

    From the link:

    “What’s happening here isn’t quite magic—the expression is simply being lazily evaluated. The interpreter checks the value of the first part of the statement, null, establishes that it’s falsy and continues moving forward until a falsy value isn’t found (or if no truthy value is found, returning the last value)”

    So:

    return isInArray( skipHREF, context.href.toLowerCase() ) ? context.id || context.title || context.innerText : context.href.toLowerCase() 
    

    What this is really saying is:

    First check if the context.href is one we should skip.
    If it isn't, then we use context.href.toLowerCase() [ this is the final bit of the line... after the colon ]
    If it's one we should skip, then we'll use context.id
    If context.id is falsey (undefined, '', null) then we'll use context.title
    If context.title is falsey then we'll use context.innerText
    

    This is such a nice trick and I learned it somewhat recently so I’m glad to be able to pass it along.

    Cheers~ good luck picking up the pieces of your brain off the floor… ewww.

    #162104
    shaneisme
    Participant

    Beautiful… my bat-belt just got an anti-Joker spray.

    I always thought those lazy or operators were pseudo code.

    You get the Official Medal of Shane. Wear it proudly son.

    #162106
    dyr
    Participant

    Thanks! Happy to help. I’ve been updating my PEN over the last 10 minutes so be sure to take another look.

    #162112
    shaneisme
    Participant
    #162113
    dyr
    Participant

    Haha, thanks Shane. It was a nice break from what I should be doing today. :)

Viewing 15 posts - 1 through 15 (of 15 total)
  • The forum ‘JavaScript’ is closed to new topics and replies.