Wiring element events - javascript

I recently read a blog post. In it, the author told readers to wire up all their onclick events not inline, but when the DOM's ready, like this (jQuery example):
<script type="text/javascript">
$(document).ready(function() {
$("myElement").click(...
});
</script>
This, for all the elements on the page with events attached to them. And that script block, with all its wirings, should go at the end of the page.
He said that setting it in-line was more difficult to maintain:
<span id="myElement" onclick="...">moo</span>
But he didn't say why.
Is this true in others' experiences? Is it a better practice to do this? What are its advantages?

Well, it's generally regarded as good style to separate code and content from each other as much as possible. If you use that method, you have wonderfully clean HTML:
<span id="myElement">moo</span>
and a separate, central code repository that you can keep in one place, and could even put into an external Javascript file.
Editing your HTML layout becomes really fun then, and it looks great as well.
I don't always follow this rule myself to the letter, and I'm not as zealous about it as others. But I allow myself a maximum of a function call onclick='do_stuff()' when doing stuff inline. Anything more complex turns to code soup really fast.

Having all of your event handlers in one place makes the code much easier to maintain, because you don't need to hunt through the HTML looking for event handlers. It also allows you to have both single and double quotes in the handlers, and will fail on syntax errors when the script block is parsed instead of when the event is first fired.
Also, every inline event handler requires the browser to parse a separate expression (equivalent to an eval call), hurting performance.

It's just messy. It's best to keep your logic separate from your markup, just as you ought to keep your markup separate from your styling. If you keep clean separation, managing code is easier since you don't need to hunt through your markup to modify what happens when you hover over images, for instance.
# index.html
<img class="thumbnail" src="puppies.jpg" />
# index.js
$("img.thumbnail").fadeTo(0, 0.5).hover(
function () { $(this).fadeTo("fast", 1.0); },
function () { $(this).fadeTo("slow", 0.5); }
);
# index.css
img.thumbnail { border:1px dotted red; }

Advantages are you won't have to search for events generated by html controls in different controls(ASCX) or Page in case your page has many controls(ASCX) embeded.
You can even debug if the event is registered using Firebug or some other debugger.

Read this article on behavioral separation which explains the graceful degradation when JavaScript is disabled. You can also find articles on unobtrusive JavaScript to understand the spirit of jQuery.

Also, if you use event bubbling you can avoid having multitudes of event handlers.

An advantage for me of an inline event is you can see directly what will happen when you perform the action, just by inspecting the element.
This is particularly quick if you maintain an old code or done by someone else.
Another advantage is about speed, attaching events later use the DOM and it is probably not as fast as inline generation.
And by using an unobtrusive templating engine like PURE you can keep you HTML clean of any JS logic

Related

What's the difference between .click(function () { and javascript:myfunction()?

Consider the simple link below:
Link
I understand there are two ways to run a function when a user clicks this element:
$(".mylink").click(function () {
and
Link
Is there a performance difference between the two, or any other practical reason I should use one over the other?
Using $('.mylink').click(function(){ is better as it follows standard event registration model. (jQuery internally uses addEventListener and attachEvent).
Basically registering an event in modern way is the unobtrusive way of handling events. Also to register more than one event listener for the target you can call addEventListener() for the same target.
Read jQuery.click() vs onClick
and How does inline Javascript (in HTML) work?
https://softwareengineering.stackexchange.com/questions/86589/why-should-i-avoid-inline-scripting
They have the same functional behavior, there is no difference whatsoever.
The difference is in code modularity and maintainability.
Using the first method is preferred and more appropriate because it doesn't mix between HTML and JavaScript, a concept called Unobtrusive JavaScript.
If you have worked in the early days of HTML, then you should remember when there were all those attributes like background, color, font ... etc.
Then CSS came in, and everybody told us not to use those old attributes anymore because they mix presentation with document structure, instead we should use CSS to control layout and look of the document.
This is similar to that idea but it is now used for code, separate functionality from document structure.
Edit: Quoting from #mplungjan comment in order to be more accurate:
That there is no difference is not true. href="javascript:myFunction()" does not have the ability to cancel the actual click with a preventDefault or return false. Hence animated gifs will stop running in some browsers and older browsers would even partially unload the page. Also if the function returned a value, the page would be replaced with that value, seen when beginners try href="javascript:window.open..." and get [object object] on the page
Jquery like any other good JavaScript frameworks supplies you with functionality independent of browser platform wrapping all the intricacies, which you may not care about or don't want to care about.
I think using a framework is better instead of using pure JavaScript and doing all the stuff from scratch, unless you usage is very limited.
I definitely recommend JQuery!
The first one is JQuery convention of an event listener. You need to include jquery library in order to use it. The second one is a Javascript convention. You don't need to include any library or extra code to run. There are no differences in terms of performance, but as I told if you do not want to include any kind of library you should use the second example.

onclick attribute vs eventListeners

I'm re-writing the code of a website I created a few years ago, and I was wondering what was the most efficient way to handle the click event on an element?
I have a list of items with links to edit them, and they're all written with the onclick="..." HTML attribute. Is it better that way or I should use $.bind() or addEventListener to handle it? What's the best practice?
It is considered best practice to utilize what is called unobtrusive javascript. What this means is you separate the layout of your HTML from the behavior of the elements. So instead of using the onclick attribute, which mixes up element structure and behaviour, you layout your DOM structure in markup and then attached event handlers via javascript.
What this means is that is considered best practice to use javascript to attached event handlers, as follows:
<html>
<script>
... bind event handlers to your DOM and set behaviours here
</script>
<body>
.... layout your DOM here
</body>
<html>
This has advantages for long-term code maintainability and extensibility. This approach works very nicely with javascript libraries such as jQuery.
In terms of performance, you may be able to achieve performance gains via an unobtrusive javascript approach by using an intelligent caching strategy.
For more information on unobtrusive javascript, see here
addEventListener or it's jQuery version on \ bind is the best practice as it separates the visual part-HTML from the functional part- javascript.
Separates of concerns.
If the code is written already, I wouldn't change it, it's not that important.
Many people will discourage the use of onclick because "what if you want to add another onclick event?" - personally I have never had this issue, but I can sort of understand.
If you're not using the links for anything other than a single click event, then onclick is perfectly fine. However, if you want it to be bulletproof, you probably want addEventListener. I actually have my own addEvent/fireEvent/removeEvent trio of functions that keep track of events and handle browser inconsistencies for me (bringing in window.event, for instance) and this works quite well.

Why are more people nowadays using script to assign events handlers vs assigning the event from within the html element?

As a learner I like to look at lots of source code. Since I started learning JavaScript about a year ago, I notice a trend of people not using traditional event handlers as in onclick="doSomething()", but are more and more using methods like document.getElementById("someId").onclick = function(){..some code..};
What's the reason behind this trend?
Assigning the handlers in Javascript puts all of the code in one place instead of scattering it throughout the HTML.
This helps separate content from script, just like CSS helps separate content from style.
It's also faster, since the browser won't need to fire up a Javascript parser for each handler attribute.
This is an example of Unobtrusive Javascript.
The other answers haven't touched on this, so:
Your example uses the (reflected) onclick attribute even in the JavaScript code:
document.getElemenbyId("someId").onclick = function(){..some code..};
...which for me misses out one of the primary reasons for doing this without using attributes: Playing nicely with others. The DOM2 way of attaching handlers (addEventListener, or attachEvent on IE [IE9 has the standard addEventListener finally]):
document.getElementById("someId").addEventListener("click", function() { ... }, false);
// or
document.getElementById("someId").attachEvent("onclick", function() { ... });
... is non-exclusive — more than one handler can be attached at the same time. Whereas if you assign to onclick, you're kicking any previous handler off and taking over.
To me, this "playing nicely" thing is a big sell. Well, that and keeping code and markup separate, but that's been well-covered in other answers.
HTML should be only markup, pure content.
Design should be in CSS style sheet.
Dynamic scripting should be in JavaScript code, separate file is good.
Just feels better and looks better - as far as I can tell it's not more efficient just more elegant and easier to maintain when all the script is in one place instead of being spread all across the HTML. :)
As mentioned by other answers, the main reason is separation of concerns (in this case, keeping behaviour separate from content), which is entirely sensible. However, that isn't always the only consideration. I've previously written a lengthy answer to a related question.
I think most people are using jQuery. $("#someId").click(function(){}) and when you want to attach an event to many elements jQuery makes it easy and puts your function in one place.

What is more efficient: listeners or functions in jquery

I have been using Jquery alot lately an was wondering if I should use listeners or functions for my clicks.
Normally I do the following:
<head>
<script type="text/javascipt">
function buttonclicked() {
alert("You Clicked it");
}
</script>
</head>
<button onclick="buttonclicked()">Click Me</button>
Benefits of using listeners also allow you to separate your markup and JavaScript.
Reasons that it's better to use the jQuery event mechanism and not the "intrusive" onfoo element attributes:
You can take advantage of the "live" mechanism. If your interest is efficiency, then this is something you definitely should be thinking about.
Disjoint pieces of code can bind handlers to the same elements for different reasons without even having to know about eachother. You don't have to update a single handler to deal with everything.
You keep your markup much cleaner, and save a lot of trouble when event handling needs to change. If you bind handlers based on (for example) element class ("button.showHelpText" for example) then radical changes to your "help text" code can be made without having to touch the HTML markup at all.
You avoid the unsightly mess of polluting the global Javascript namespace with all those global handler functions.
You have solid, dependable access to the "event" data, courtesy of the jQuery framework.
Overall, if you're going to use jQuery, dive in and really use it.
i think its more efficient to do what you did in your example.
Also, i wouldnt do that since it is not that much more efficient that it would matter, and it makes for ugly code. Also its better to separate your js from your html.
So please dont do what you did in your example unless you have a very good reason

Best Practices for onload Javascript

What is the best way to handle several different onload scripts spread across many pages?
For example, I have 50 different pages, and on each page I want to set a different button click handler when the dom is ready.
Is it best to set onclicks like this on each individual page,
<a id="link1" href="#" onclick="myFunc()" />
Or a very long document ready function in an external js file,
Element.observe(window, 'load', function() {
if ($('link1')) {
// set click handler
}
if ($('link2')) {
// set click hanlder
}
...
}
Or split each if ($('link')) {} section into script tags and place them on appropriate pages,
Or lastly, split each if ($('link')) {} section into its own separate js file and load appropriately per page?
Solution 1 seems like the least elegant and is relatively obtrusive, solution 2 will lead to a very lengthy load function, solution 3 is less obtrusive then 1 but still not great, and solution 4 will load require the user to download a separate js file per page he visits.
Are any of these best (or worst) or is there a solution 5 I'm not thinking of?
Edit: I am asking about the design pattern, not which onload function is the proper one to use.
Have you thought about making a class for each type of behavior you'd like to attach to an element? That way you could reuse functionality between pages, just in case there was overlap.
For example, let's say that on some of the pages you want to a have button that pops up some extra information on the page. Your html could look like this:
More info
And your JavaScript could look like this:
jQuery(".more-info").click(function() { ... });
If you stuck to some kind of convention, you could also add multiple classes to a link and have it do a few different things if you needed (since jQuery will let you stack event handlers on an element).
Basically, you're focusing on the behaviors for each type of element you're attaching JavaScript to, rather than picking out specific ids of elements to attach functionality to.
I'd also suggest putting all of the JavaScript into one common file or a limited number of common files. The main reason being that, after the first page load, the JavaScript would be cached and won't need to load on each page. Another reason is that it would encourage you do develop common behaviors for buttons that are available throughout the site.
In any case, I would discourage attaching the onlick directly in the html (option #1). It's obtrusive and limits the flexibility you have with your JavaScript.
Edit: I didn't realize Diodeus had posted a very similar answer (which I agree with).
First of all I dont understand why you think setting event listeners is obtrusive?
but ...
Solution one is a bad idea
<a id="link1" href="#" onclick="myFunc()" />
because you should keep your make-up and your scripts seperate.
Solution two is a bad idea
Element.observe(window, 'load', function() {
if ($('link1')) {
// set click handler
}
if ($('link2')) {
// set click hanlder
}
...
}
because you are using a lot of unneeded javascript for every page.
Solution three is a bad idea for the same reason I said solution one is a bad idea.
Solution 4 is the best idea, yeah its one extra load per page, but if for each page you just split each if ($('link')) {} section, the file size can not be that large? Plus, if you take this code out of the global javascript, then its load time will be reduced.
You could hack the class name and use it in a creative manner:
<a class="loadevent functionA" id="link1" href="#" onclick="myFunc()" />
... on another page...
<a class="loadevent functionB" id="link1" href="#" onclick="myFunc()" />
You could select by class name "loadevent" and grab the other class names for that tag, the other class name being the actual function name you want to hook into. This way one handler would be able to do every page and all you have to do is provide the corresponding class names.
I would use JQuery's document ready if possible
$(document).ready(function() {
// jQuery goodness here.
});
While Chris is somewhat correct in that you can do this:
$(document.ready(function() {
// A
});
$(document.ready(function() {
// B
});
$(document.ready(function() {
// C
});
and all functions will be called (in the order they are encountered), it's worth mentioning that the ready() event isn't quite the same to onload(). From the jQuery API docs:
Binds a function to be executed
whenever the DOM is ready to be
traversed and manipulated.
You may want the load() event instead:
$(document).load(function() {
// do stuff
});
which will wait for images and the like to be loaded.
Without resorting to the kneejerk jQuery, if the page varying JS is relatively light I would include it in an inline header script (binding to the onload event trigger, yes) similar to #4, but I wouldn't do this as a separate JS script and download, I'd be looking to handle this with a server side include - however you want to handle that (me? I'd go with XSLT includes).
That gives you both a high degree of modular separation and keeps the download as light as possible.
Having a lot of different pages, I would allow different handling of events for those pages ...
If, however, differencies were slight, I would try to find a pattern I could hang on to, and probably make a real simple algorithm to tell the pages apart ...
The last thing I would resort to, was to use a (big) library (jquery, mootools or whatever !-) if I wasn't going to use it in any other way ...
Now you're talking of best practices, best practice would always be what your users will experience as the lightest solution, and in that, users should be understood in the widest possible way, including developers and so on who are to maintain that site !o]

Categories

Resources