Home › Forums › JavaScript › jQuery -> Native: Select all tags + addEventHandler, can I do more better?
- This topic is empty.
-
AuthorPosts
-
February 4, 2014 at 3:14 pm #161867
shaneisme
ParticipantSo 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.
February 5, 2014 at 4:46 pm #161986dyr
ParticipantYour 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
February 5, 2014 at 5:00 pm #161987shaneisme
ParticipantReally, 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.
February 5, 2014 at 5:44 pm #161990dyr
ParticipantI 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
February 5, 2014 at 5:51 pm #161991shaneisme
ParticipantThanks, 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.
February 6, 2014 at 10:52 am #162059shaneisme
ParticipantOne 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 returningundefined
trying to findhref
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?
February 6, 2014 at 12:24 pm #162069dyr
ParticipantCan 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.
February 6, 2014 at 2:32 pm #162083shaneisme
ParticipantAfter 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 thehref
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.
February 6, 2014 at 2:57 pm #162086dyr
Participanthttp://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!)
February 6, 2014 at 4:26 pm #162100shaneisme
ParticipantThanks a lot for your guidance, here’s (nearly) the full program: http://codepen.io/anon/pen/nksai
February 6, 2014 at 5:03 pm #162101dyr
ParticipantPrepare 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.
February 6, 2014 at 5:21 pm #162104shaneisme
ParticipantBeautiful… 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.
February 6, 2014 at 5:26 pm #162106dyr
ParticipantThanks! Happy to help. I’ve been updating my PEN over the last 10 minutes so be sure to take another look.
February 6, 2014 at 6:17 pm #162112shaneisme
ParticipantFebruary 6, 2014 at 6:18 pm #162113dyr
ParticipantHaha, thanks Shane. It was a nice break from what I should be doing today. :)
-
AuthorPosts
- The forum ‘JavaScript’ is closed to new topics and replies.