I'm making a project that includes a lot of elements creation and appending, after a little research i came up with that
$(newElement) and $(selector)
are slower than
.createElement(newElement) and .getElementBy
Since i'm doing a todo-list app which will include a lot of creation/appending/selection of this :
<div class="mainTaskWrapper clearfix">
<div class="mainMarker"></div>
<label for="task1">This is task1</label>
<div class="holder"></div>
<div class="subTrigger"></div>
<div class="checkButton"></div>
<div class="optTrigger"></div>
<div class="mainOptions">
<ul>
<li id="mainInfo">Details</li>
<li id="mainDivide">Divide</li>
<li id="mainEdit">Edit</li>
<li id="mainDelete">Delete</li>
</ul>
</div>
</div>
What would you advise me to use ? jQuery selection and creation way, or JavaScript one ?
When you say "a lot of creation/appending/selection", what exactly do you mean?
Is it in the order of several per second, or just "a lot"? Since the code will run client-side, one per second won't be that much of an issue.
jQuery would then be the 'best' choice, as maintainability is a large plus, and any code you write with jQuery will probably be a lot clearer.
Depends a bit on what else you're doing. In some cases, setting innerHTML is the fastest (esp. with big bulky blocks getting inserted).
That said from a dev standpoint the jquery method is really the most maintainable. I'd probably go w/ the jquery version until performance becomes a problem, and wrap the calls to jquery in other functions that I can swap out when it does.
It's really a developer preference issue.
Personally, I find strictly using jQuery selectors to be easier to write and understand, and more consistent when the selectors get more complex. Using native JavaScript is faster to compile and render, but you might not actually see any difference depending on the complexity of your page.
I would advise you NOT to create that many identical elements all at once. Instead, place them once in your HTML and hide it (use display:none) and then use jQuery to .clone() the whole block as needed.
HOWEVER: First, get rid of those id= attributes. You can't have more than one element on a page with the same ID.
Related
This question relates to the article http://davidwalsh.name/css-do .
What are the differences and advantages these approaches?
<div class="do-launch-login">...</div>
<a class="do-close-modal">...</a>
<input class="do-autocomplete" />
and
<div id ="login" class="launch-login">...</div>
<a id="close" class="close-modal">...</a>
<input id="autocomplete" class="clautocomplete" />
The author calls them do- prefixes, i call them (and use them as) js- or jQ- prefixes.
Javascript has a whole scale of possible applications in DOM manipulation... than just a do-
Those prefixes are to indicate classes used exclusively by JS, means you cannot find them in i.e: style.css but rather as part of some Javascript logic in script.js.
Also you cannot use ID multiple times cause ID should be unique-per-page, so, classes in any case, spiced with a prefix to distinguish it's application.
(hm...do-... still seems pretty funny.)
Personally for me, I generate a lot of dynamic HTML on the fly for my web applications. Because of this, I try to never use IDs as I make multiple instances of the same HTML objects.
It is considered terrible practice to ever have a duplicate of an ID, so I always use class names as selectors.
But that's just me.
Id should only be used for a single thing. However a class can be given to many different things.
You could easily google this for more in depth answer
Some consider use of id in css a bad practice, because of:
The element is not re-usable on that page.
This is the beginning downward sprial into specificity.
Usually, IDs refer to something specific, and abstracting would be tough.
Any performance gains picked up by using id, is negated by adding any other selector to the left for that id
quoted from http://screwlewse.com/
I've got a web app that has loads of DOM elements, and it's causing the browser to slow down.
I would like to know what the culprit is. It's trivial to write a bit of javascript to loop through all DOM elements and report on which tags are used the most, but I'm looking for something a little more sophisticated. Let's say for example that the following structure appears a thousand times:
<div class="container">
<div class="somestuff">
<ul>
<li>Only one item</li>
</ul>
</div>
</div>
Doing a "report" on how many times a tag is used might show the div tag as being used a lot, which in a large app doesn't tell me much if it is used often outside that structure, which is pretty likely for most apps.
What I'd like is something that detects and reports that the above structure occurs 1000 times. Again, it might be easy enough to report on tag+class, but I'm guessing that there are instances where such a simplistic approach would have trouble detecting what I'm trying to find, just for example when there is no class. Are there any tools / scripts already out there? Or approaches others have used to find the culprit in a situation similar to this?
I am wondering if it is better to put your html in javascript or in your html files.
For example having my js file have this
$('<div>').addClass('test').append(
$('<p>').text('test1'),
$('<span>').text('test2'),
$('<span>').text('test3')
).insertAfter( $('#test1') );
VS
My html file looking like this
<div id="#test1"></div>
<div class="test">
<p>test1</p>
<span>test2</span>
<span>test3</span>
</div>
and the js file have:
$('.test').show();
Highly subjective and depends on contexts of course.
In a web page, most of the content is already known. No reason not to just put the content in the HTML and use CSS (and maybe Javascript when really needed) to style in.
In a web application, however, things are not so well known. The document is much more dynamic and using Javascript to add/remove elements is required.
BTW, your two pieces of code do two different things. In the first example you give it a class of test and in the second you are giving it an ID of #test1. This is an invalid ID and should be test1. The selector for that ID would be #test1 which may be causing some of the confusion.
This is probably okay for just straight-up webpages, but for web applications you should really look into a templating system such as mustache.js(https://github.com/janl/mustache.js) or Handlebars.js(http://handlebarsjs.com/).
That way, you can keep your HTML in external template files and use Javascript objects and arrays to fill them with data. For example, a mustache template might look like:
<div id="{{id}}"></div>
<div class="{{class}}">
<p>{{name}}</p>
<span>{{prop1}}</span>
<span>{{prop2}}</span>
</div>
And you would have an object that looks like this to fill it:
var obj = {
id: "myID",
class: "some classes",
name: "Martin Brennan",
prop1: "whatever",
prop2: 22
}
And you would use the template with the object like this (after loading the template into a variable):
Mustache.render(template, obj)
Like Jeremy J Starcher said though, this is highly subjective, and I would suggested that you give templating systems a try to see if you can see the value in using them in your project(s).
Of course the second option is much better and faster.
If you use
$('<div>').addClass('test').append(
$('<p>').text('test1'),
$('<span>').text('test2'),
$('<span>').text('test3')
).insertAfter( $('#test1') );
browser must parse JavaScript. And each time you use $() you are creating an object which has a lot of properties and methods which you don't use (useless!). And of course the browser must parse the HTML too.
But if you use
<div id="#test1"></div>
<div class="test">
<p>test1</p>
<span>test2</span>
<span>test3</span>
</div>
browser only has to parse HTML and it's much faster.
One of the largest benefits of using the 2nd, hard-coded HTML method is that it'll still show up for people with JavaScript disabled. It's hard to verify exactly how many users don't have JS enabled (because most trackers use JS..) but last guesstimate I heard was somewhere around 5% of internet users.
Moral of the story - make your site work without JavaScript. Then and only then add JavaScript to make it look prettier/ add additional (non essential) features.
The simple answer is that static content should be created using normal markup, while Javascript should be used for dynamic content.
Also, in many cases you can use both. You can have static HTML markup with style="display:none", and then use Javascript to change the style to make it appear and disappear as needed.
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.
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.