JavaScript Coding Standards – Why is JavaScript in HREF Attributes Discouraged?

coding-standardscoding-stylehtmljavascript

Disclaimer: I came to Programmers.SE to ask this question because I understand this is the place to ask this type of question, and not necessarily stackoverflow. If I am wrong, please close the question and direct me to a place where I may be able to discuss it.

I have noticed that people have been saying (in the year 2014) that we aren't supposed to use JavaScript in the href attribute of an HTML anchor tag. So then this function call:

<a id="expand-rail" href="javascript:callMyFunc()">Expand</a>

is discouraged, and over this it is preferred instead to attach an event handler to the onclick event of this anchor tag.

Why?

I'll take that this style of JavaScript function calls is very '90's, but what specific style guideline discusses this and weighs the pros and cons of doing it this was and recommends against it? I mean, there must be a pros and cons list, because I can think of some pros, like quick access to a function for a small HTML file, or easy readability on a small project. Yes, you have the cons, like not separating the view from the controller. I want to know who said this, why it is "generally understood", and where I can verify that.

Take something like this:

<span>
    Please <a id="page-reload" href="javascript:window.location.reload()">click here</a> to refresh
</span>

It is abundantly obvious what I am trying to do. Is it really necessary to separate the logic from the view in this case? If you agree with me that we can let this one slide, then where do we draw the line?

Best Answer

It revolves around the principle of Unobtrusive JavaScript. The modern approach dictates that there should be a separation of functionality from presentation.

I hate to cite Wikipedia, but give Wikipedia's article on Unobtrusive JavaScript a read.

On a personal note there are three things about Unobtrusive JavaScript I quite like:

  1. Separation of concerns – My JavaScript is completely separate from my HTML code. It's in separate files and it encourages me to write clean JavaScript code. With inline tags I tend to dump piles of garbage into script tags. Here I'm writing very tight, modular, reusable, and maintainable JavaScript.

  2. Graceful degradation – When you use inline JavaScript like that, you're assuming that the client has JavaScript enabled. What happens if the client doesn't have JavaScript enabled? Does your site fail entirely? If you write unobtrusive JavaScript you're typically building a functional site with HTML then enhancing the experience with JavaScript. Without JavaScript your site's user experience is degraded, but still functional.

  3. Ask instead of assume – This ties in to what I was talking about with point number two. What you're encouraged to do is build a core experience using HTML + CSS then enhance it with JavaScript. In many of my sites (I'm a .NET MVC developer) I use jQuery UI to load partial pages for input forms. With unobtrusive JavaScript my site works perfectly with full page loads, and then is enhanced with AJAX requests that allow me to create modal dialogs. In my server code I actually dictate whether to return a View() (full layout) or PartialView() (plain HTML) based on whether or not the request is an AJAX request.

Let's look at your first example. Based on context I can assume that you have a section of your page that is hidden, and the link calls a function to expand that section of the page. You could be achieving that in one of two ways. You could be hiding the section with the content and then displaying it when the link is clicked (toggling CSS) or you could be making a call to the server to load the data and display it on the page (AJAX request). In its current form the content that the methods call displays is now inaccessible to your client. You could refactor your page to display all content on the page at load time if JavaScript is unavailable and then hide it when the DOM is ready, or you could have the link direct to a full page with the content then change that behaviour to an AJAX request.

Related Topic