A phenomena I'm seeing more and more of is Javascript code that is tied to a particular element on a particular page, rather than being tied to kinds of elements or UI patterns.
For example, say we had a couple of animated menus on a page:
<ul id="top-navigation">
...
</ul>
<!-- ... -->
<ul id="product-list">
...
</ul>
These two menus might exist on the same page or on different pages, and some pages mightn't have any menus.
I'll often see Javascript code like this (for these examples, I'm using jQuery):
$(document).ready(function() {
$('ul#top-navigation').dropdownMenu();
$('ul#product-selector').dropdownMenu();
});
Notice the problem?
The Javascript is tightly coupled to particular instances of a UI pattern rather than the UI pattern itself.
Now wouldn't it be so much simpler (and cleaner) to do this instead? -
$(document).ready(function() {
$('ul.dropdown-menu').dropdownMenu();
});
Then we can put the 'dropdown-menu' class on our lists like so:
<ul id="top-navigation" class="dropdown-menu">
...
</ul>
<!-- ... -->
<ul id="product-list" class="dropdown-menu">
...
</ul>
This way of doing things would have the following benefits:
Simpler Javascript - we only need to attach once to the class.
We avoid looking for specific instances that mightn't exist on a given page.
If we remove an element, we don't need to hunt through the Javascript to find the attach code for that element.
I believe techniques similar to this were pioneered by certain articles on alistapart.com.
I'm amazed these simple techniques still haven't gained widespread adoption, and I still see 'best-practice' code-samples and Javascript frameworks referring directly to UI instances rather than UI patterns.
Is there any reason for this? Is there some big disadvantage to the technique I just described that I'm unaware of?
First of all I agree with you that using the class approach is better, in general.
But I don't think I'd go so far as to say it's less coupling of the code to the UI. If you think about it, if the code assumes ID "foo" vs. class name "foo", you still have to know that when working with the UI. There's still a 'contract' between them -- whether you meet it through ID or class is not really different.
One disadvantage to using the class approach I'd imagine is speed -- it should be faster to find a particular element by ID than find potentially multiple elements by class. The difference is probably completely negligible though.
But, in the case where your code is designed to attach multiple behaviors, as in your two-dropdown example, using class certainly makes more sense. That is less coupling since your code is a bit more generalized, and your UI more likely to be customizable w/o changing the code.
One thing I'd change in both of your examples... why have the UL in the selector? If the code knows it can only possibly work if the target is a UL, well, that's one thing -- but in that case, it'd be better to avoid the UL in the selector and let the code throw a meaningful error if the target is found not to be a UL, lest the page just do nothing without any indication as to why (e.g. because the UI put the ID/class on a OL).
So in other words, just "#foo" or ".foo" not "ul.foo", etc.
I should point out that in case someone thinks the UL somehow makes the selector more efficient, it doesn't, since selectors are evaluated from right to left.
Your approach is preferred.
The reason people do things in different ways is because they can and it still works.
Related
I'm a front-end developer, and I'm worried about the best way to target my DOM.
Let's imagine a tiny form to create a new zombie :
<h1>Add a new zombie</h1>
<form id="create-zombie">
<input id="zombie" type="text" name="zombie" />
<input id="lvl" type="text" name="lvl" />
<button type="submit">Add</button>
</form>
...and if I want to get the values of zombie and lvl, I will code something like this:
class Zombie_Add extends Controller
# Dom References
el:
'form': '#create-zombie'
'zombie': '#zombie'
'lvl': '#lvl'
run: ->
#on 'submit', #el.form, #validate
validate: (e) =>
e.preventDefault()
zombie = $(#el.zombie).val()
lvl = $(#el.lvl).val()
module.exports = Zombie_Add
That's "ok" and it does the job, but I have some problems with that "structure" :
If somebody touches the DOM and removes an ID, I'm just fucked, it breaks my code (Captain Obvious spotted !)
For more complicated selectors, it's just a mess (I'm thinking about some stuff like that [name^="dummy-"] input:first). I guess it's easy to imagine how shitty the names of el are.
Anyway, what I want to learn today is what's the best way to target the DOM from JS. Is it better to use IDs, class values or, data-* attributes? How we can prettify a selector with plain English, etc...
If somebody touches the DOM and removes an ID, I'm just ****ed, it
breaks my code (Captain Obvious spotted !)
The best way to target a single, unique element in the DOM is with an ID like you are doing with zombie and lvl. It is both fast to execute and simple to code.
It is a given that if someone messes with the id values in your HTML, that will break your Javascript. That's just the way it is. Anyone messing with your HTML has to be smart enough to know that an ID value is there for a reason so if they want to change that or remove it, then it is their responsibility to find someone who can make corresponding changes in the Javascript. That's just the way it is.
For more complicated selectors, it's just a mess (I'm thinking about
some stuff like that [name^="dummy-"] input:first). I guess it's easy
to imagine how ****ty the names of el are.
The same goes for more complicated selectors. Like it or not, a modern web page is a melding of server-side stuff, presentation HTML and Javascript. The three have to work together to deliver the final solution. While you strive to avoid unnecessary dependencies with good design techniques and practices, you cannot avoid all dependencies, nor would even trying to avoid all possible dependencies be an efficient way to develop.
Example
There are coding practices that can make your code less sensitive to edits to the HTML and I consider those to be desirable practices. For example, consider this HTML snippet:
<div class="header">
<div class="headerBorder">
<div class="actions>
Hide
</div>
<div class="contentContainer">
<div class="content">
... content here
</div>
</div>
</div>
</div>
<div class="header">
... more of these repeated
</div>
And you want to have code that, when you click on the Hide link, it will hide the content.
If you code that like this:
$(".header .actions .hide").click(function() {
$(this).parent().next().children().first().hide();
});
Then, you have embedded in your Javascript some extremely detailed knowledge of the HTML structure in the area of your button and content and pretty much any structural change to that HTML (even just adding one more level of div to help with some layout) will break the Javascript. This is bad.
Instead, you could write this:
$(".header .actions .hide").click(function() {
$(this).closest(".header").find(".content").hide();
});
This depends only upon one HTML structural concept - that the .content that corresponds to the .hide button is somewhere in the common .header parent element. The entire structure within that .header parent can be changed and this code will not break. This is robust code that tries to be as independent of the details of the HTML structure as possible.
Anyway, what I want to learn today is what's the best way to target
the DOM from JS. Is it better to use IDs, class values or, data-*
attributes? How we can prettify a selector with plain English, etc...
It's best to use IDs to target elements for which there is only one unique element in the page.
It's best to use class names to target elements for which there can be more than one element in the page and you can combine that with other parts of a selector if you want to target only a specific item with a class name.
data attributes can be used in selectors, but that isn't really their primary purpose. I can't think of any reason why it would be better to use a data attribute instead of a class name. I use data attributes for storing actual data on an object that will be used by scripts. This tends to allow the code to be more generic and let the content describe itself.
When you talk about classes getting removed to change the state of the element, that is a legitimate use of a class, but it would just be a bad design decision to use the same class for selecting an element as for add/removing state. Use different class names for those two purposes. For example, you could have a class name called "selected" that indicates a selection state, but you would only use that in a selector if you wanted just the selected objects. If you wanted all line items in a table, you wouldn't use ".selected", you'd create a more descriptive class name for that object such as "lineitem". Remember, you can have multiple class names on an object so you can use different class names on the same object for different purposes.
You seem to be searching for some magic bullet here that prevents changes in the HTML from affecting Javascript in any way. That simply does not exist. Selecting a DOM element or finding a DOM element relative to something that was clicked will rely on some inherent knowledge of how the HTML is structured or tagged. What is important is that you minimize that dependence to only what is required and that anyone messing with the HTML has an understanding of how to best change things and not break the Javascript or discusses changes with someone who knows the Javascript. If you're using different skills/people on different portions of the project, they have to coordinate their efforts in order to not break things or be aware of what dependencies there are with the other parts of the system. That's just the way it is. There is no magic answer here that removes all dependencies between HTML and Javascript. Smart designs have smaller and more obvious dependencies. Poor designs have large and often hidden depedencies.
Your question about "plain English" isn't particularly clear to me. It seems obvious to use descriptive ID names, class names or attribute names that make it as obvious to the reader what that particular name is being used for. I'm not sure what you were looking for beyond that.
I tried to have a title that match the context I want my answer for.
I explain myself.
After writting thousand of javascript lines of code (with or without jquery) I finally asked myself if I'm doing it wrong.
Mainly thanks to jQuery adding event/delegating to an element is very easy, but all the example are quiet "easy"; meaning it doesn't take into account that you have a page full of list, button, dynamic things...
So my questions, is:
Once again for a complexe website, with hundred of dynamic pages, ajax navigation, millions of user...
Is there any advantage (beside simplicity) to place a global listener (body or whatever) and let all events bubble up ?
When I look at angular it seems they listen 'ng-click' globally, but I can missthink.
Contexte
<body>
<div>
<ul>
<li><span click="myFunc"></span></li>
</ul>
</div>
</body>
-
Sidenot: I'm using jQuery for presentation/simplicity, but it's global question about js
// Standard binding example
$('span').on('click', func)
vs
// Standard delegation example
$('ul').on('click', 'span', func)
vs
// Dispatcher for 'block'
$('ul').on('click', localDispatcher)
vs
// One (and only one) Global Listener for all click
$(body).on('click', globalDispatcher)
With this example, the 3 first one need to be placed manually, on a dedicated js for this page.
Vs
The last one is just a simple event listener, that will use click attribute to dispatch and can be set just once and for all.
I find the last one very cool, because it remove all the hassle to manage click/selector/dom management. Also I don't have to .off every listener when I change page (ajax navigation).
But I wonder about performance or maybe another problems I can think about (that's why I ask the question :D).
I really wonder how "big web startup" manage this kind of Javascript.
Thanks :)
I'd say no to a global listener since it will make things incredibly confusing and frustrating to organize once the app grows into a considerable size.
Also the performance should be really bad since you are involving elements that will be ignored otherwise.
So stick with element or block level event delegation if you want to feel good about yourself in the future!
Description
By design most jquery code leads to a lot of tight coupling, e.g. selectors assume a specific structure of html
var mySubnav = $("#navigation a.sub-menu");
If the corresponding html changes, for whatever reasons,
<a class="subMenu" .... </a>
functionality is broken.
Question
What's the best way to handle tight coupling?
What approaches exist to loosen it up?
Answers, Approaches
use the html custom data attribute to separate css from js logic. e.g. add data-submenu="true" on the html and use var mySubnav = $("[data-submenu]"); on the js side.
implement a solid testing environment
couple as loose as possible, by using the least specific selectors, e.g. $("a.sub-menu'). See also
Eliminate the actual string literals that represent CSS selectors from the body of your jQuery code by (1) retrieving references to static DOM elements beforehand, and (2) storing selector strings in one place (at the top of your code).
use javascript frameworks, like Backbone, which decouple javascript from the DOM via views
use delegate and live regarding coupling due to event management
This may not be a popular answer, but... testing, testing, testing. JQuery and Javascript in general are typically tightly coupled, and for good reason; they're code running in the browser, and so you want to keep the performance relatively snappy. So injecting an indirection layer that allows for looser coupling can decrease performance; as well, it can be a bit of overkill, since there's typically a close pairing between the JQuery / Javascript code that's written and the pages they're written for; this is as much an artifact of the historical development of Javascript, but that's the way that it is. As such, the tight coupling is pretty "normal".
The way to deal with this tight coupling, like any tight coupling, is to make sure that you've got good testing in place to cover any coupling failures. Testing can provide assurance that the coupling is proper, and it's really the best way to assure the functionality you expect anyway.
One option is to use a Javascript framework, like Backbone. It gives you the concept of views which help decouple your Javascript from the DOM structure. For example, you can create the Comment view, which you assign to the following div:
<div class="comment">
<span class="title"></span>
<p class="body"></p>
</div>
And then you can access elements in the view relative to the comment div:
var title = this.$(".title");
This makes it easy to change the DOM structure outside of the comment div as long as the internals of the comment div remain the same.
Use Custom prefixed classes for UI hooks ui-specificGuy
Provided HTML
<div class="container grid8">
<ul class="ul1 horizontal">
<li>List Item 1</li>
<li>List Item 2</li>
</ul>
</div>
Bad - using style purposed classes/hooks
$('.container.grid8').stuff();
$('.ul1.horizontal').moreStuff();
Adjusting the HTML
<div class="container grid8 ui-specificContainer">
<ul class="ul1 horizontal ui-specificList">
<li>List Item 1</li>
<li>List Item 2</li>
</ul>
</div>
Good - using your own purposed classes/hooks
$('.ui-specificContainer').stuff();
$('.ui-specificList').moreStuff();
Only be as specific as neccessary
If this will accomplish your goal.
$('.ui-targetedElement')
Then why have a selector that looks like this?
$('ul > li a.ui-targetedElement')
This simply introduces unnecessary DOM structure dependencies into the functionality you are building, and you should be able to be proactive in this regard because you should be providing your own hooks (prefixed classes) at this point right?
Ultimately though I would say that tight coupling between the DOM and the script are sometimes unavoidable because of the nature of how they work together.
Full Article
If you are talking in respect to event management then make as much use of delegates and live which are not tightly coupled to the dom structure. Take a look at the below urls
Live -
http://api.jquery.com/live/
Delegate -
http://api.jquery.com/delegate/
My suggestion would be to:
retrieve the references of static DOM elements on DOM ready and put them in variables or properties of an object or whatever.
store class names inside an object (or several objects or whatever, as long as those names (strings) are in one place)
Then you can do this:
var mySubnav = $('a.' + C.submenu, navigation);
where navigation is a reference to the #navigation element and C is the class-names object which submenu property is the string "sub-menu".
Now, when you change class-names in your HTML code, you only have to update the C object.
The idea is to get rid of the actual string literals that represent CSS selectors from the body of your jQuery code by (1) retrieving references to static DOM elements beforehand, and (2) storing selector strings in one place (at the top of your code).
If your html changes, the all bets are off.
And what you have is not tight coupling. It is essential for your code to function.
E.g., this is what I would consider tight coupling:
<a class="subMenu" onclick="doSomething()"> .... </a>
The loose version would be:
$("#navigation a.sub-menu').click(function(){
//do something
});
What about using html5 data attributes to do javascript selectors?
<a data-submenu="true" .... </a>
var mySubnav = $("[data-submenu]");
Makes it really clear that javascript is operating on the html.
I have noticed while monitoring/attempting to answer common jQuery questions, that there are certain practices using javascript, instead of jQuery, that actually enable you to write less and do ... well the same amount. And may also yield performance benefits.
A specific example
$(this) vs this
Inside a click event referencing the clicked objects id
jQuery
$(this).attr("id");
Javascript
this.id;
Are there any other common practices like this? Where certain Javascript operations could be accomplished easier, without bringing jQuery into the mix. Or is this a rare case? (of a jQuery "shortcut" actually requiring more code)
EDIT : While I appreciate the answers regarding jQuery vs. plain javascript performance, I am actually looking for much more quantitative answers. While using jQuery, instances where one would actually be better off (readability/compactness) to use plain javascript instead of using $(). In addition to the example I gave in my original question.
this.id (as you know)
this.value (on most input types. only issues I know are IE when a <select> doesn't have value properties set on its <option> elements, or radio inputs in Safari.)
this.className to get or set an entire "class" property
this.selectedIndex against a <select> to get the selected index
this.options against a <select> to get a list of <option> elements
this.text against an <option> to get its text content
this.rows against a <table> to get a collection of <tr> elements
this.cells against a <tr> to get its cells (td & th)
this.parentNode to get a direct parent
this.checked to get the checked state of a checkbox Thanks #Tim Down
this.selected to get the selected state of an option Thanks #Tim Down
this.disabled to get the disabled state of an input Thanks #Tim Down
this.readOnly to get the readOnly state of an input Thanks #Tim Down
this.href against an <a> element to get its href
this.hostname against an <a> element to get the domain of its href
this.pathname against an <a> element to get the path of its href
this.search against an <a> element to get the querystring of its href
this.src against an element where it is valid to have a src
...I think you get the idea.
There will be times when performance is crucial. Like if you're performing something in a loop many times over, you may want to ditch jQuery.
In general you can replace:
$(el).attr('someName');
with:
Above was poorly worded. getAttribute is not a replacement, but it does retrieve the value of an attribute sent from the server, and its corresponding setAttribute will set it. Necessary in some cases.
The sentences below sort of covered it. See this answer for a better treatment.
el.getAttribute('someName');
...in order to access an attribute directly. Note that attributes are not the same as properties (though they mirror each other sometimes). Of course there's setAttribute too.
Say you had a situation where received a page where you need to unwrap all tags of a certain type. It is short and easy with jQuery:
$('span').unwrap(); // unwrap all span elements
But if there are many, you may want to do a little native DOM API:
var spans = document.getElementsByTagName('span');
while( spans[0] ) {
var parent = spans[0].parentNode;
while( spans[0].firstChild ) {
parent.insertBefore( spans[0].firstChild, spans[0]);
}
parent.removeChild( spans[0] );
}
This code is pretty short, it performs better than the jQuery version, and can easily be made into a reusable function in your personal library.
It may seem like I have an infinite loop with the outer while because of while(spans[0]), but because we're dealing with a "live list" it gets updated when we do the parent.removeChild(span[0]);. This is a pretty nifty feature that we miss out on when working with an Array (or Array-like object) instead.
The correct answer is that you'll always take a performance penalty when using jQuery instead of 'plain old' native JavaScript. That's because jQuery is a JavaScript Library. It is not some fancy new version of JavaScript.
The reason that jQuery is powerful is that it makes some things which are overly tedious in a cross-browser situation (AJAX is one of the best examples) and smooths over the inconsistencies between the myriad of available browsers and provides a consistent API. It also easily facilitates concepts like chaining, implied iteration, etc, to simplify working on groups of elements together.
Learning jQuery is no substitute for learning JavaScript. You should have a firm basis in the latter so that you fully appreciate what knowing the former is making easier for you.
-- Edited to encompass comments --
As the comments are quick to point out (and I agree with 100%) the statements above refer to benchmarking code. A 'native' JavaScript solution (assuming it is well written) will outperform a jQuery solution that accomplishes the same thing in nearly every case (I'd love to see an example otherwise). jQuery does speed up development time, which is a significant benefit which I do not mean to downplay. It facilitates easy to read, easy to follow code, which is more than some developers are capable of creating on their own.
In my opinion then, the answer depends on what you're attempting to achieve. If, as I presumed based on your reference to performance benefits, you're after the best possible speed out of your application, then using jQuery introduces overhead every time you call $(). If you're going for readability, consistency, cross browser compatibility, etc, then there are certainly reasons to favor jQuery over 'native' JavaScript.
There's a framework called... oh guess what? Vanilla JS. Hope you get the joke... :D It sacrifices code legibility for performance... Comparing it to jQuery bellow you can see that retrieving a DOM element by ID is almost 35X faster. :)
So if you want performance you'd better try Vanilla JS and draw your own conclusions. Maybe you won't experience JavaScript hanging the browser's GUI/locking up the UI thread during intensive code like inside a for loop.
Vanilla JS is a fast, lightweight, cross-platform framework for
building incredible, powerful JavaScript applications.
On their homepage there's some perf comparisons:
There's already an accepted answer but I believe no answer typed directly here can be comprehensive in its list of native javascript methods/attributes that has practically guaranteed cross-browser support. For that may I redirect you to quirksmode:
http://www.quirksmode.org/compatibility.html
It is perhaps the most comprehensive list of what works and what doesn't work on what browser anywhere. Pay particular attention to the DOM section. It is a lot to read but the point is not to read it all but to use it as a reference.
When I started seriously writing web apps I printed out all the DOM tables and hung them on the wall so that I know at a glance what is safe to use and what requires hacks. These days I just google something like quirksmode parentNode compatibility when I have doubts.
Like anything else, judgement is mostly a matter of experience. I wouldn't really recommend you to read the entire site and memorize all the issues to figure out when to use jQuery and when to use plain JS. Just be aware of the list. It's easy enough to search. With time you will develop an instinct of when plain JS is preferable.
PS: PPK (the author of the site) also has a very nice book that I do recommend reading
When:
you know that there is unflinching cross-browser support for what you are doing, and
it is not significantly more code to type, and
it is not significantly less readable, and
you are reasonably confident that jQuery will not choose different implementations based on the browser to achieve better performance, then:
use JavaScript. Otherwise use jQuery (if you can).
Edit: This answer applies both when choosing to use jQuery overall versus leaving it out, as well as choosing whether to to use vanilla JS inside jQuery. Choosing between attr('id') and .id leans in favor of JS, while choosing between removeClass('foo') versus .className = .className.replace( new Regexp("(?:^|\\s+)"+foo+"(?:\\s+|$)",'g'), '' ) leans in favor of jQuery.
Others' answers have focused on the broad question of "jQuery vs. plain JS." Judging from your OP, I think you were simply wondering when it's better to use vanilla JS if you've already chosen to use jQuery. Your example is a perfect example of when you should use vanilla JS:
$(this).attr('id');
Is both slower and (in my opinion) less readable than:
this.id.
It's slower because you have to spin up a new JS object just to retrieve the attribute the jQuery way. Now, if you're going to be using $(this) to perform other operations, then by all means, store that jQuery object in a variable and operate with that. However, I've run into many situations where I just need an attribute from the element (like id or src).
Are there any other common practices
like this? Where certain Javascript
operations could be accomplished
easier, without bringing jQuery into
the mix. Or is this a rare case? (of a
jQuery "shortcut" actually requiring
more code)
I think the most common case is the one you describe in your post; people wrapping $(this) in a jQuery object unnecessarily. I see this most often with id and value (instead using $(this).val()).
Edit: Here's an article that explains why using jQuery in the attr() case is slower. Confession: stole it from the tag wiki, but I think it's worth mentioning for the question.
Edit again: Given the readability/performance implications of just accessing attributes directly, I'd say a good rule of thumb is probably to try to to use this.<attributename> when possible. There are probably some instances where this won't work because of browser inconsistencies, but it's probably better to try this first and fall back on jQuery if it doesn't work.
If you are mostly concerned about performance, your main example hits the nail on the head. Invoking jQuery unnecessarily or redundantly is, IMHO, the second main cause of slow performance (the first being poor DOM traversal).
It's not really an example of what you're looking for, but I see this so often that it bears mentioning: One of the best ways to speed up performance of your jQuery scripts is to cache jQuery objects, and/or use chaining:
// poor
$(this).animate({'opacity':'0'}, function() { $(this).remove(); });
// excellent
var element = $(this);
element.animate({'opacity':'0'}, function() { element.remove(); });
// poor
$('.something').load('url');
$('.something').show();
// excellent
var something = $('#container').children('p.something');
something.load('url').show();
I've found there is certainly overlap between JS and JQ. The code you've shown is a good example of that. Frankly, the best reason to use JQ over JS is simply browser compatibility. I always lean toward JQ, even if I can accomplish something in JS.
This is my personal view, but as jQuery is JavaScript anyway, I think theoretically it cannot perform better than vanilla JS ever.
But practically it may perform better than hand-written JS, as one's hand-written code may be not as efficient as jQuery.
Bottom-line - for smaller stuff I tend to use vanilla JS, for JS intensive projects I like to use jQuery and not reinvent the wheel - it's also more productive.
The first answer's live properties list of this as a DOM element is quite complete.
You may find also interesting to know some others.
When this is the document :
this.forms to get an HTMLCollection of the current document forms,
this.anchors to get an HTMLCollection of all the HTMLAnchorElements with name being set,
this.links to get an HTMLCollection of all the HTMLAnchorElements with href being set,
this.images to get an HTMLCollection of all the HTMLImageElements
and the same with the deprecated applets as this.applets
When you work with document.forms, document.forms[formNameOrId] gets the so named or identified form.
When this is a form :
this[inputNameOrId] to get the so named or identified field
When this is form field:
this.type to get the field type
When learning jQuery selectors, we often skip learning already existing HTML elements properties, which are so fast to access.
As usual I'm coming late to this party.
It wasn't the extra functionality that made me decide to use jQuery, as attractive as that was. After all nothing stops you from writing your own functions.
It was the fact that there were so many tricks to learn when modifying the DOM to avoid memory leaks (I'm talking about you IE). To have one central resource that managed all those sort of issues for me, written by people who were a whole lot better JS coders than I ever will be, that was being continually reviewed, revised and tested was god send.
I guess this sort of falls under the cross browser support/abstraction argument.
And of course jQuery does not preclude the use of straight JS when you needed it. I always felt the two seemed to work seamlessly together.
Of course if your browser is not supported by jQuery or you are supporting a low end environment (older phone?) then a large .js file might be a problem. Remember when jQuery used to be tiny?
But normally the performance difference is not an issue of concern. It only has to be fast enough. With Gigahertz of CPU cycles going to waste every second, I'm more concerned with the performance of my coders, the only development resources that doesn't double in power every 18 months.
That said I'm currently looking into accessibility issues and apparently .innerHTML is a bit of a no no with that. jQuery of course depends on .innerHTML, so now I'm looking for a framework that will depend on the somewhat tedious methods that are allowed. And I can imagine such a framework will run slower than jQuery, but as long as it performs well enough, I'll be happy.
Here's a non-technical answer - many jobs may not allow certain libraries, such as jQuery.
In fact, In fact, Google doesn't allow jQuery in any of their code (nor React, because it's owned by Facebook), which you might not have known until the interviewer says "Sorry, but you cant use jQuery, it's not on the approved list at XYZ Corporation". Vanilla JavaScript works absolutely everywhere, every time, and will never give you this problem. If you rely on a library yes you get speed and ease, but you lose universality.
Also, speaking of interviewing, the other downside is that if you say you need to use a library to solve a JavaScript problem during a code quiz, it comes across like you don't actually understand the problem, which looks kinda bad. Whereas if you solve it in raw vanilla JavaScript it demonstrates that you actually understand and can solve every part of whatever problem they throw in front of you.
$(this) is different to this :
By using $(this) you are ensuring the jQuery prototype is being passed onto the object.
As comment to one of the questions here a commenter wrote (emphasis mine):
... By using an inline "onclick" you are doing a similar thing, but it is harder to maintain and more prone to issues. The JavaScript community as a whole has been moving away from inline JavaScript for a while now.
This was referring to attaching events to HTML elements using:
$("#someID").click(function(){
do something here...;
});
rather than:
<a id="someID" onclick="someFunction();">
Has there really been a shift away from the old school way of declaring events inline, and if so, what are the benefits of one of the other?
EDIT I guess it may be helpful to include a reference to the original question. It asked about attaching a different click event to each tab. Is my answer crap and do I owe FallenRayne an apology =).
The big benefit is the separation of content (html) and action/behavior (javascript). This is known as Unobtrusive javascript. Keeping these separated makes it easier to change either without affecting the other.
Yes, there has, at least in some portion of the community, not sure how you'd measure it overall.
There are definitely advantages, off the top of my head:
Cleaner / Less code
Easier to debug
Easier to change
Easier to package
Performance
From sheer volume, think of this:
<a onclick="someFunction();">
<a onclick="someFunction();">
<a onclick="someFunction();">
<a onclick="someFunction();">
<a onclick="someFunction();">
Or this once:
$("a").click(someFunction);
You can do this with most frameworks via a css selector, etc, handles many elements at once. This means in server code you're just assigning IDs and classes, the client side is easier to handle separately. It's easier to debug as well, for example: in the console I can do $('a').unbind('click').click(...something new...);
Another benefit is performance. If I can split this into a separate .js file, cached by the client, that's thinner webpages and extra data I'm not sending every time. Smaller web page = faster load.
Here's one more example, thinks about how simple it is, granted some framework action via jQuery going on, but how would this look with inline events?
$("li").hover(function() {
$(this).children().slideToggle();
});
Comparatively, that's a tremendous amount of inline code, even if you leave out the animation portion it's messy (think mouseenter/mouseleave, not mouseover/mouseout...the former, which .hover() uses, is more complicated)
Has there really been a shift away from the old school way of declaring events inline
Yes, definitely, especially with the rise of the JS Frameworks like jQuery, Prototype and so on, all of which encourage declaring events the "new school" way.
and if so, what are the benefits of one of the other?
One of the main reasons is the separation between the HTML structure and the JavaScript programming intelligence (which arguably do belong separated). It makes the markup much, much cleaner and easier to maintain, while all the programming logic is kept in separate files, which has loading performance advantages as well as better maintanability - you have proper libraries that contain the code, instead of fragments of JS code all over the place.
With inline declaration you can assign only one event handler while from code you can assign as many as you wish. Also if you need to assign same event handler to multiple elements doing it with javascript is easier and shorter and you comply to DRY principle.