I am tempted to make some custom attributes for some page elements to make selection easier, via the .attr(); function in jQuery.
I figure that this is probably discouraged, as there is a lot of flexibility in jQuery and javaScript that, as a novice, I have not learned to employ yet to its full potential.
Other than making cryptic IDs or adding lots of classes, what are some ways to add more information to my divs and other page elements for easy selecting via the selector $()?
I'm mostly curious as to pros/cons, and what memory issues or speed issues result based on different approaches.
There isn't a problem at all creating custom attributes on your elements. Anyway, you should follow the html5 data- spec.
<div id="foo" data-info="hello" data-more="{'iam': 'anobject'}" />
The cool thing about using this is, jQuery (latest version) will automatically parse the data-x attributes and adds those into the .data() expando.
$('#foo').data('info') === 'hello'
$('#foo').data('more').iam === 'anobject'
You are still able to run a selector like
$('div[data-info=hello]')
on your elements.
ref.: .data(), html5 data attributes
HTML5 introduces data-* attributes. So if you are going to introduce custom attributes, I would at least stick to this specification.
There is also the .data() method in jQuery for associating arbitrary data with elements. As long as you don't need to use the data in a selector, this is the preferred way.
jQuery plug ins usually use some already existing attributes like "rel" or "title" but jQuery also has the .data() method which stores information on an specific object in javascript. It acts like a log.
http://api.jquery.com/jQuery.data/
Both of this techniques are acceptable and work well.
The first thing to be aware of is that the jQuery selectors are extremely powerful. You don't always need to select by an ID or a class - you can select by tag, by type, by relation to another selection (children/parents/siblings/etc). So, there may not be a need to add IDs or classes to your various elements in order to select them.
With that said, don't avoid classes and IDs just for avoiding classes and IDs. They exist for a reason, and that reason is to make selection of them straightforward and easy (whether it is with jQuery or CSS or whatever else). If you remove classes and IDs, you may make your HTML look nicer, but your jQuery code may become convoluted and/or very inefficient. (For example, it is always faster to select an ID directly than select a parent component and find its children.)
I don't think you should be discouraged to use attr(). It is a powerfull tool and really helps to add more information to your elements. I have some projects using it to suport internal javascript frameworks and it turns my code clean and legible. And it has the advantage to be is a ease to work with selectors!
You should really be using only classes and IDs for the initial selection but here are some handy selectors you can use on top of this:
http://api.jquery.com/category/selectors/
A unique ID is the quickest way to find an element through jQuery, so if the purpose of your temptation is to make your elements easier for jQuery to retrieve, it seems pointless.
I've used such techniques for adding attributes such as title or alt for better accessibility.
Use .data('key', 'val') to set your data and.data('key') to read it.
I would definitely use the Data api (http://api.jquery.com/jQuery.data/)
Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
One of my colleagues doesn't like to use HTML classes and ids for javascript/jQuery purpose. Therefore I've seen that he had created custom html attribute such as
<div id="myid" class="cssClasses ..." [some-purpose-id]="mycustomId">...</div>
I asked him if it was really a good idea and he replied that he considers that classes and Ids should be reserved for styling.
Personally, I would have used classes. Some classes would have been used for styling, and some other classes would have been used for programming (jQuery selectors). The idea is to keep things appart also. And of course jQuery could set styling classes but if possible not use them for selection. Of course I also use id when appropriate but since an id is unique on a page, I like to do generic stuff using classes.
I would like to know you opinions on the better approach (if there is one). Thank you.
I would recommend against that, but rather use the HTML5 data attribute. Read about it here.
You should use classes and IDs for both javascript and CSS. Your colleague is wrong.
It helps to remember that you want to keep separation between data (html), presentation (css styling), and behavior (javascript). Classes and IDs are there for a reason, and it's not for styling (and not for javascript, either!). They are there to allow you to semantically mark up your document.
When writing proper HTML, your classes and IDs should reflect the actual content and purpose of the data those nodes contain. Then, when you need to style them, you can specify the proper styling for, say the .zip_code class. And when you need special behavior, you can use javascript to apply the required behavior to your .deletable list items.
Of course, sometimes in the real world, there are people who feel very strongly against things, and you end up having to go along with what they want. In this case, you may have to compromise with your colleague and use HTML5's data-* attributes, as someone else suggested. However, while this is a solution that will result in valid HTML, it is not what data-* attributes were designed for, so it isn't technically the correct solution.
No, for the most part, you shouldn't use made-up attributes. These are not valid HTML, and will show up as errors if you try to validate your code.
However in HTML5 you can use custom attributes that begin with data-. You can read more about them on the html5doctor website. data- attributes, however, are more often advocated for storing information, not labels. e.g. for a product you might say data-brand="gucci". Or something.
Using attributes for styling or javascript is misleading, because it's not a dichotomy. Often, you will need to add an id or class to style your markup. If possible, you can reuse these attributes to select elements in javascript without adding attributes. It keeps your code clean, but this is obviously just a preference.
If you need to select an element that doesn't already have a unique id or class that could be used for selection, you could use the data attribute. However using ids and classes is still standard practice.
It may be useful if you want to supply another data inside attributes for multiple purposes, look at the following example:
<script>
function getIt(){
ob = document.getElementById('myid')
alert(ob.getAttributeNode('anotherTitle').value)
}
</script>
<div id="myid" class="cssClasses" anotherTitle="new Title">The div</div>
Test
I used the anotherTitle attribute to save or store another set of data in-which it may be used in another usage.
This is a working example http://jsfiddle.net/vxknh/
The refrence: http://www.w3schools.com/jsref/prop_attr_value.asp
Maybe your colleague was inspired by examples of the declarative style used in the dojo toolkit.
data- is a good way to "stamp" your attributes for a specific purpose (for example all dojo specific attributes are of the form data-dojo-whatever). This reduces the risk of conflict with other scripts or css.
So yes it can be a good idea, but no classes and ids are not reserved for styling.
Classes and ID have their advantages and disadvantages (it is also very dependant on how you use them).
Classes - they were designed to convey styling info, but with advent of jQuery now they have dual purpose, sometimes signifying action (or data) and sometimes styling. This is quite confusing especially on large scale projects. Imagine a designer trying to "re-factor" the CSS and changing these class names on elements that have javascript/jQuery hooked up to it - bad things ensue. You could mitigate against that prefixing your non-styling class names with a "namespace" like ".donttouchthis-jqueryclass", which differentiates the logic from presentation is a very primitive manner. The advantage of using a class is that it can be "stacked" thus it can convey more complex "logic" than an ID for example. From a pure javascript (no jQuery) point of view reliance on classes in your code introduces some backward compatibility issues (getElementsByClassName).
IDs - as the name implies were designed to uniquely identify elements. From a programming point of view IDs offer the fastest way to access elements in the DOM (getElementById). They can also be styled, however the potential to remove an ID when re-factoring is lower (as you can always remove ID styling and give it a class). IDs are unique thus making extensive use of them to store any complex data is very, very limited. But they are great to bind click handlers or uniquely identify chunks of the DOM as long as you only need one of elements identified by them.
Both Classes and IDs have one important rule which limits their usefulness as means for conveying any business logic - they cannot start with a number (and often you just need that database id conveniently assigned to an element)
Custom attributes (not data-) - they can be anything which is kinda cool, however if you care about "validity" of your HTML you will be restricted to certain DTD types and you will need to specify them in your DTD. In reality they do not harm your HTML as browsers are specifically obliged (under the W3C convention) to ignore unknown attributes. The only problem being a clash with potential future developments. If you are using pure javascript they will also be a bit of a pain to use (but this is a subjective option - as suggested in one of the answers above this is a good supplementary option to use them as data storage). The potential for a mixup when re-factoring CSS is small.
Custom data- attributes - these are great if you are using jQuery because you can store really complex data against it (objects etc), when used correctly they really kick ass and give you a nice vocabulary to describe function of your DOM elements. "data-" namespace nicely protects it from any future conflicts with non name-spaced attributes.
Having said all that the best solution is not to overtly rely on any of these, but implement javascript patterns which allow you to pass a parent DOM element and later apply functionality to it based on markup (like a standard jQuery plugin pattern). This way you remove a lot of dependencies on specific attributes/classes/ids that are a part of static HTML source.
I want to clarify the good practices in terms of Designer/Developer workflow.
Here is my observation, let me know if I am wrong : there is no fundamental reason why CSS and JS should use the same attributes. Events associated to an html tag are not related to the styles that are applied to it and separating them would help the maintenance for both the developers and the designers.
And my question : why isn't there a strict separation between the two? I understand that we are free to use custom attributes for JavaScript and keep IDs, classes and HTML tag names for CSS however everything in jQuery seems to be made to use them. For example :
$("#myid").html("Test");
$("#myid").addClass("clickable");
$("#myid").removeClass("clickable");
if($("#myid").hasClass("clickable")) var clickable = true;
etc. Why is so?
Side-question : is there some performance issues about using only custom attributes for JavaScript?
$('[event="clickable"]').html("Test");
This article from Roy Tomeij http://roytomeij.com/2012/dont-use-class-names-to-find-HTML-elements-with-JS.html mentionned in stackoverflow : Separate ID and Class for JS and CSS seems to advice not to use classes in Javascript but that's all I have found so far and I want to expand the discussion.
It is valuable for both CSS and JavaScript to have the two items : unique IDs and multiple classes but when I think about it we could have div such as
<div css_id="mydiv" css_class="green" js_id="unique_element" js_class="other_event">
and hypothetical CSS properties and jQuery functions such as
div#mydiv{margin_top:20px;} //reads from css_id attributes
div.green{color:green;} //reads from css_class attributes
$("#unique_element").click(function(){alert("Clicked!")}) //reads from js_id attributes
$(".other_event").click(function(){alert("Congratulations!")}) //reads from js_class attributes
and in the same way
$("#unique_element").addClass("clickable2"); //add a value to the js_class attribute
Thank you all! I do not intend to reinvent everything just to explore ways to improve teams' workflows.
I think you can answer your own question. What possible benefit does having markup that looks like this provide?
<div css_id="mydiv" css_class="green" js_id="unique_element" js_class="other_event">
To me it looks messy and harder to deal with. In theory, content is king, and in the beginning you have a beautifully marked-up semantic HTML document. Thoughtfully, you add semantic class names and IDs based on the content within them. Using these IDs and classes, you are able to staple design and functionality onto your document using CSS and JavaScript respectively.
To answer your other question, IDs are faster for JavaScript. If you're using JQuery, the performance is negligible if you cache the DOM references as variables (which you should always do if you reference an element more than onec). For example, var $myclass = $('.myclass'); You can read more about selector performance here.
For CSS, many people recommend avoiding IDs for styling as much as possible. You can read the spec on specificity, but basically using lots of ids will lead to some of the same (though less extreme) problems as using !important.
The best I've seen is:
<div class="button button-primary js-modal-popup">
Essentially - add a class with js- prepended to it so you can distinguish from your stylistic classes and your jQuery hooks. It allows you to to create as many ID's or classes as you'd like without inhibiting your styles to be tied to actions as well.
there is no fundamental reason why CSS and JS should use the same attributes.
This is true. They're two separate languages...so, yes. There is no 'fundamental reason' why they should use the same attributes.
however everything in jQuery seems to be made to use them.
I don't think this is true, though. JQuery has specific functions for class and so on because, well, they're existing CSS attributes. But it also has the same exact functions for custom attributes, so there's no asymmetry here. I don't think this could be used as evidence that Jquery was made to use CSS attributes anymore than custom attributes.
As to your questions of performance or which to use, I think that bookcasey adequately answered them.
I often use CSS ids or classes to select elements in Javascript. Many of those classes do just exist for that use case and do not have any styles attached at all.
I ponder now if it would be any good to mark those classes explicitly. Maybe something like a leading underscore (e.g. class="_field").
The thing is that I never heard of such a practice. Is this recommended? Maybe already used in a bigger project? What kind of marking would make sense? I read somewhere that a leading underscore could be problematic. What else could I use to easily identify those "Javascript only" classes?
You can do that as a personal coding convention. The spec doesn't state that the class attribute must be used in styling only, or in scripting only. You can use it to classify your elements in any way you want, so there's no restriction in how you name and organize your classes.
The majority of the time I find that the class names used in JS matches the styling I want to do in CSS. As long as you name them properly it's not a big deal that a class name is used by only CSS or JS.
You may want to use the data-* attributes suggested by HTML5. They even work in HTML4, though the resulting code is not valid.
As a sidenote, ExtJS has used "namespaced" custom attributes for their tree nodes for quite some time:
<div class="x-tree-node-el x-tree-node-leaf x-unselectable cls"
ext:tree-node-id="Foobar">
(They should change that to data-ext-tree-node-id btw)
It is better to use ids for working with JavaScript since an element has only one id that is unique to it, while classes can be applied to multiple HTML elements.
Are selectors or functions faster in jQuery? Example:
$('#something div.else'); // find multiple divs with class .else
or
$('#something').children('div.else');
I'm trying my best to optimize a page with hundreds of returned elements that seems to hang on a certain crappy computer here in the office (that must use Internet Explorer ::shudder::).
Well in this case, the second's faster, but, they're not equivalent. The first finds any descendant div.else, the other finds only direct children that are div.else.
It depends on your DOM as to which is faster, the equivalent of the second would be this:
$('#something > div.else');
This uses the child selector. They should be very, very close, and in any case, I doubt a selector descending from an ID is your problem area, I think you'll find the vast majority of your time in JS is spent elsewhere.
For diagnosing speed issues, get a profiler, for IE specifically there's a fantastic free one called dynaTrace AJAX Edition. Grab it, follow the short tutorials on their site...you'll find where your pain areas in IE are pretty quickly.
Although I haven't checked with the jQuery code, I think the difference should be negligable between your two examples - although the first one should run a little faster.
The problem with old IE versions is that they do not support a native way to fetch items based on class names. In this case, jQuery has to execute a regulra expression on each class attribute of each element contained.
If it is possible in your case, you might gain quite a lot performance when being able to select on an unusual tagname:
$("#container blockquote.else")
and ideally,leave away the class name.
EDIT: just saw the answer from Nick and he's right, the scond one only has to check the direct children. The equivalent first one would be:
$("#container > div.else")
In your specific example, your first example of
$('#something div.else');
gets optimized through Sizzle (which is delivered within the jQuery lib) into
$('#something').find('div.else');
without that optimization, it would be slower, since the selector engine sizzle does work from right to left. So, it would match all divs with the class else and would then check which of those has #something as parent.
edit
The Sizzle optimazation is slower
anyway, since it took a while until
that task is completed and some
functions are called on the way
In general, using jQuery functions is a lot faster. For instance jQuerys .eq() function will use an array slice to reduce a wrappet set of jQuery objects, whereas :eq() selector will invoke sizzle.
If in your example, div.else elements are direct children of #something, .children() will beat .find() since .find() will also lookup all descendants (and their childs).
If I understand correctly you need the fastest way to get #something div.else in IE6. Since jQuery uses Sizzle, the way it will find that is first find all div's, then filter by the ones with the else class, and has an ancestor with the #something id.
Your second example will be faster if it contains few children, slower if it contains many.
A suggestion you could try would be to use another tag type instead of div, one that isn't used in your page, say blockquote. Just reset it's styles with css so it looks like a normal div, then change your selector to #something blockquote.else which should be tons faster.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I'm looking for any way that I can improve the selector performance of a jQuery call. Specifically things like this:
Is $("div.myclass") faster than $(".myclass")
I would think it might be, but I don't know if jQuery is smart enough to limit the search by tag name first, etc. Anyone have any ideas for how to formulate a jQuery selector string for best performance?
There is no doubt that filtering by tag name first is much faster than filtering by classname.
This will be the case until all browsers implement getElementsByClassName natively, as is the case with getElementsByTagName.
In some cases, you can speed up a query by limiting its context. If you have an element reference, you can pass it as the second argument to limit the scope of the query:
$(".myclass", a_DOM_element);
should be faster than
$(".myclass");
if you already have a_DOM_element and it's significantly smaller than the whole document.
As Reid stated above jQuery is working from the bottom up. Although
that means $('#foo bar div') is a
lot slower than $('bar div #foo')
That's not the point. If you had #foo you wouldn't put anything before it in the selector anyway since IDs have to be unique.
The point is:
if you are subselecting anything from an element with an ID then select the later first and then use .find, .children etc.: $('#foo').find('div')
your leftmost (first) part of the selector can be less efficient scaling to the rightmost (last) part which should be the most efficient - meaning if you don't have an ID make sure you are looking for $('div.common[slow*=Search] input.rare') rather than $('div.rare input.common[name*=slowSearch]') - since this isn't always applicable make sure to force the selector-order by splitting accordingly.
In order to fully comprehend what is faster, you have to understand how the CSS parser works.
The selector you pass in gets split into recognizable parts using RegExp and then processed piece by piece.
Some selectors like ID and TagName, use browser's native implementation which is faster. While others like class and attributes are programmed in separately and therefore are much slower, requiring looping through selected elements and checking each and every class name.
So yes to answer your question:
$('tag.class') is faster than just $('.class'). Why?
With the first case, jQuery uses the native browser implementation to filter the selection down to just the elements you need. Only then it launches the slower .class implementation filtering down to what you asked for.
In the second case, jQuery uses it's method to filter each and every element by grabbing class.
This spreads further than jQuery as all javascript libraries are based on this. The only other option is using xPath but it is currently not very well supported among all browsers.
Here is how to icrease performance of your jQuery selectors:
Select by #id whenever possible (performance test results ~250 faster)
Specify scope of your selections ($('.select', this))
I'll add a note that in 99% of web apps, even ajax heavy apps, the connection speed and response of the web server is going to drive the performance of your app rather than the javascript. I'm not saying the you should write intentionally slow code or that generally being aware of what things are likely to be faster than others isn't good.
But I am wondering if you're trying to solve a problem that doesn't really exist yet, or even if you're optimizing for something that might change in the near future (say, if more people start using a browser that supports getElementsByClassName() function referred to earlier), making your optimized code actually run slower.
Another place to look for performance information is Hugo Vidal Teixeira's Performance analysis of selectors page.
http://www.componenthouse.com/article-19
This gives a good run down of speeds for selector by id, selector by class, and selector prefixing tag name.
The fastest selectors by id was: $("#id")
The fastest selector by class was: $('tag.class')
So prefixing by tag only helped when selecting by class!
I've been on some of the jQuery mailing lists and from what I've read there, they most likely filter by tag name then class name (or vice versa if it was faster). They are obsessive about speed and would use anything to gain a smidgen of performance.
I really wouldn't worry about it too much anyway unless you are running that selector thousands of times/sec.
If you are really concerned, try doing some benchmarking and see which is faster.
Consider using Oliver Steele's Sequentially library to call methods over time instead of all at once.
http://osteele.com/sources/javascript/sequentially/
The "eventually" method helps you call a method after a certain period of time from its initial call. The "sequentially" method lets you queue several tasks over a period of time.
Very helpful!
A great tip from a question I asked: Use standard CSS selectors wherever possible. This allows jQuery to use the Selectors API. According to tests performed by John Resig, this results in near-native performance for selectors. Functions such as :has() and :contains() should be avoided.
From my research support for the Selectors API was introduced with jQuery 1.2.7, Firefox 3.1, IE 8, Opera 10, Safari 3.1.
If I am not mistaken, jQuery also is a bottom up engine. That means $('#foo bar div') is a lot slower than $('bar div #foo'). For example, $('#foo a') will go through all of the a elements on the page and see if they have an ancestor of #foo, which makes this selector immensely inefficient.
Resig may have already optimized for this scenario (it wouldn't surprise me if he did - I believe he did in his Sizzle engine, but I am not 100% certain.)
I believe that selecting by ID first is always faster:
$("#myform th").css("color","red");
should be faster than
$("th").css("color","red");
However, I wonder how much chaining helps when starting with the ID? Is this
$("#myform").find("th").css("color","red")
.end().find("td").css("color","blue");
any faster than this?
$("#myform th").css("color","red");
$("#myform td").css("color","blue");