children vs selector - jQuery - javascript

For the sake of simplicity I'll narrow down the question as below. I have a large code running in the click js functions. To represent that All I have added an alert()
HTML
<ul>
<li>Test li 1</li>
<li>Test li 2</li>
<li>Test li 3</li>
<li>Test li 4</li>
<li>Test li 5</li>
</ul>
JS
Method 1
$('ul li').click(function(){alert('hi');});
Method 2
$('ul').children().click(function(){alert('hi');});
Method 1 and method 2 both works fine.
Which one is better ? Is it better to use the selector or use the children method ? What's the purpose of having a children method when we can use selector?
Test Fiddle
I'm just grabbing the basics and hope not knowing something is not a crime. Thanks

While both of those pieces of code work correctly on the sample HTML they are not identical.
.children returns all child elements (whether they are an "li" or not).
"ul li" as a selector returns all "li" descendants of the "ul" whether they are children or not.
These two are equivalent and select only "li" children of the "ul" parent:
$('ul > li').click(function(){alert('hi');});
$('ul').children("li").click(function(){alert('hi');});
As for which is better (the original question), there is no real answer for this I suspect and will depend on your actual requirements and html (when you ask for which is 'better' what do you mean? Performance? Maintainability?).
Usually the former will use the CSS selector engine of the browser where the selector you are using is supported, and the later will always use jquery built code (I think) so I would go for the former in most cases.

as to
Which one is better ?..
updated
actually, it depends on the HTML structure... if incase, you have small number of <li>'s in ul (first level) going with children selector is better
you can check this in js.perf...link here
but if you have large number of <li> (in first level) the children selector gets slower ..

Related

Working with previousSibling and nextSibling to set attributes

so since I started studying JavaScript I've been reading this book called Learning JavaScript by Tim Wright.
In this book I found a chapter about how we can move and target elements in the DOM tree and one of them is making use of properties which target siblings, while doing the exercises in the book I simply could not make the following statement work:
<ul id="nav">
<li>Home</li>
<li>About Us</li>
<li>Contact Us</li>
</ul>
<script>
//Should add "next" class attribute to the "Contact Us" li tag.
document.getElementById("about").parentNode.nextSibling.setAttribute("class", "next");
</script>
After having a quick look at this code I was wondering if any of you more experienced developers could help me and explain me why this doesn't work properly. I feel confused because I can't know whether I'm doing something wrong or the article about these properties is misspelled.
Anyway thanks for your time and help in advance!
Cheers!
cs.almeida
nextSibling selects the very next sibling of the element. The very next sibling node can also be a textNode that doesn't have setAttribute method, i.e. what your code tries to do is adding a class to the next sibling textNode. If you remove the line break and other hidden characters between the 2 li elements then you code will work as expected.
Another option is using the nextElementSibling property instead of the nextSibling, which will select the next sibling node that has nodeType of 1, i.e. the next HTMLElement sibling of the element.
document.getElementById("about")
.parentNode
.nextElementSibling
.classList // https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
.add("next");

jQuery: Is using children() more efficient than using child selector

I often need to setup jQuery events on li tags that don't have a class or ID associated with them like in this example:
<div id="menu">
<ul id="nav">
<li>Nav Item 1</li>
<li>Nav Item 2</li>
<li>Nav Item 3</li>
<li>Nav Item 4</li>
<li>Nav Item 5</li>
</ul>
</div>
My understanding is that jQuery selecting reads from right to left so if I were to use a $('#nav > li) jquery selector it would have to search through all of the li tags and then evaluate whether the li tag had a parent with the id of nav.
Assuming this page has 30 li tags but I only want to select the 5 in the example, would it be more efficient to use $('#nav').children('li') ? My logic is that it will quickly find the #nav ID and then will only have 5 elements inside of it to search through.
An additional question I have is If there were more than 30 child elements to #nav would it then be more efficient to use the child selector $('#nav > li')?
Thanks in advance
After having to try and create a custom selector, I was surprised to find that selectors are indeed evaluated right to left.
That means $('#nav > li') will first find all LIs in the page, then filter those to retain any having id="nav" in their immediate parent.
$('#nav').children('li') will be faster for the reasons above and what you assumed (which was correct).
The other side of the coin is "do you care?". If, for instance, you are only interested in mouse events, then the speed is driven by human interaction (at most a few times per second), whereas the speed difference in your selector methods would only be noticeable if you could do it 50,000 times per second. basically you will not normally care, but you should err on the side of efficiency when you can :)
if you were just after this to add mouse events, say click, using a single delegated event handler, attached to an ancestor element, will be very efficient:
e.g.
$("#nav").on('click', 'li', function() {
// DO SOMETHING HERE - "this" IS THE LI CLICKED
});
This is efficient because it works as follows:
Listen for click events bubbling up the DOM to the single id="nav" element we listen to.
Then apply the jQuery selector against the elements in the bubble chain.
Then apply the function to the matching element that caused the event.
This technique also means it will work for dynamically added objects as they only need to match the selector at event time (not event-registration time).
Notes:
If no convenient ancestor is available to target, use document as the default for bubbled events.
Do not use 'body' for delegated event handlers as styling can stop body receiving bubbled mouse events (if it has a calculated height of zero). Use document as your fallback.

jquery nth selector in IE7

I have a list of elements and need to make some amends to the first element in the list using jquery. I have tried a few methods to target the first item but none of them seem to work in IE7. These are the following methods I've tried...
$(this).eq(1)
$(this).first()
$(this:nth-child(1))
All of these methods worked in all browsers except IE7, does anyone know of a fix to use for IE7 or a different method that will work in IE7?
Thanks in advance for any help?
Try this.
<ul id="list">
<li>list item 1</li>
<li>list item 2</li>
</ul>​
$('#list li').first().css('background-color', 'red');
It's working in IE7 http://jsfiddle.net/jur4x/JKBH4/
Try like this
$(this:first-child)
Will get more info from here
EDIT
Sorry for the confusion.
What I was trying to say is to use first-child instead of first()
You can use like this $('ul li:first-child').css('background-color', 'red');
.first() is a valid function and will work.
For example:
$("li").first(); // will match the first li in the tree

jQuery: Is there a way to automatically add attributes to dynamically generated HTML, in the same way that live() works with events?

I have a list like the following:
<ul id="links">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>
I'm adding a target attribute to each link using jQuery, because I don't want to alter the server-side HTML output; it's used in many other places and this is the only instance where the links should have this attribute.
$('#links a').attr('target', '_top');
The problem is that new links are dynamically appended to this list client-side, also using jQuery; when they are, they obviously lack the target attribute, so I end up with this sort of thing:
<ul id="links">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
</ul>
I cannot alter the jQuery script which is appending the links in order to include the attribute, so my question is this: I know I can use live() to automatically set up event handlers for dynamically generated elements, but is there a way of automatically adding attributes to any new elements added?
I don't think there's any way to do what you're asking. But you can use live to accomplish the same thing:
$('#links a').live("click", function(e) {
$(this).attr('target', '_top');
});
If you're not averse to plugins, you might take a look at livequery, which will accomplish what you want.
Here's an example:
$("#links a").livequery(function () {
$(this).prop("target", "_top");
});
http://jsfiddle.net/vRF3G/
You might want to look into jQuery's special event system. It allows you to create custom special events that get triggered when certain conditions are met.
Here's another SO thread with a "onContentChange" event:
Create a jQuery special event for content changed
And here's another article on jQuery Custom Special Events:
http://benalman.com/news/2010/03/jquery-special-events/
This is a terrible solution:
$("#links a").live("mouseover", function() { $(this).attr("target","_top"); });
Can't click on it without mousing over it, the target attribute is set before it is needed.

Toggle multi-level ul with mootools

Greetings,
I would like to toggle a huge multi-level ul with mootools 1.1 or plain javascript.
The list looks like:
HTML:
<ul>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
<li>
<ul>
<li>ddd
<ul>
<li>fff</li>
<li>ggg</li>
</ul>
</li>
<li>eee</li>
</ul>
</li>
</ul>
What I would like to do initially is to show the first level expanded, and the other levels collapsed and when each of the list items is clicked, to expand the ul below it.
Is it possible to do it without (greatly) modifying the html above?
From the documentation, I see that Fx.Slide is the most appropriate, however it accepts the id of the element as a parameter, which means I have to assign id's to each list item.
Is there a way by using selectors of collections of elements starting from the top?
I'm not sure whay I'll say apply with the very old 1.1 version. However, at least since 1.2, the element you need to pass is either the ID (like you said), either the actual element.
If you can use another version than 1.1, try the 1.3 which makes it easier to select the elements you want.
Here, I believe you need every <ul> element which has a direct <li> as parent. MooTools 1.3 features this new selector engine Slick, which would accomplish it fairly easilly: ul !> li.
However, I'm not sure (I didn't success) that the direct child selectors works properly with 1.1.
Here is what I came up with: http://jsfiddle.net/rCfwq/

Categories

Resources