Explanation of two arguments for jQuery .each() method - javascript

In the following jQuery, the .each() method takes two arguments: 'ul li a' and menu. What do these two arguments mean?
var menu = $('.menu');
$('ul li a', menu).each(function() {
$(this).append('<span />');
});
HTML:
<div class="menu">
<ul>
<li>Edit Profile</li>
<li>Account Settings</li>
<li>Appear Offline</li>
<li>Logout</li>
</ul>
</div>

The second parameter to the jQuery function is the context. This tells jQuery to only search for elements that are in that context
So for your example:
$('ul li a', menu).each(function() {
$(this).append('<span />');
});
This will only search for anchors within li's within a ul, that are also located inside of menu.
This can be a very useful optimization since it can significantly cut down the amount of space jQuery has to search.
EDIT
To possibly make this a bit clearer (as jfriend00 points out), your particular example, $('ul li a', menu), is equivalent to $('.menu ul li a')
The context parameter is explained here in the docs

Hello Brother Assalamu Alaikkum,
The explanation is as follows,
The first parameter is 'ul li a' It means that it searches for the anchor tag within the list item tag which in turn present inside the unordered list tag. This first argument is the sub context.
The second parameter menu which is the main context. That is jquery searches for the elements with the class name as "menu".
Finally jquery searches the sub context within the main context. So the jquery searches for the main context "menu" first and then it searches the sub context within the main context. The keyword "each" denotes all the sub elements to be searched within the main element.
hope this helps you.

Related

How do I read this function?

function showTweet(username) {
$( "<ul/>", {
"class": "my-user-list",
html: usertweets[username].join( "<li/>" )
}).appendTo( $("#tweets") );
}
So I see that the selector is targeting an unordered list, but what comes after the comma and why is it in curly brackets?
I understand the .append portion. I do not understand what "class": "my-user-list" and html: usertweets[username].join( "<li/>") do. Note that usertweets is an array.
Any insight would be greatly appreciated!
The selector is not targeting a ul - it is creating one. The second parameter is an object that contains the properties to set on the new ul element. It is then added to the DOM by appending it to the #tweets element.
To show the difference:
// to create a ul element in memory
$('<ul></ul>'); // or...
$('<ul />');
// select all ul elements currently in the DOM
$('ul');
The curly brackets are for PlainObject which is plain JavaScript object. From that I would read
Please create me a <ul> with class my-user-list with html of lists of usertweets joined with <li/> and append that to <ul> and append the ul to an element with id tweets
Here's the example
http://jsfiddle.net/xz6a0yqy/
It's not targeting ul, it first creates a <ul> element, and set the <ul>'s class to "my-user-list", then set its the html inside it to usertweets[username].join("<li/>"), which should creates some <li>, and finally append the newly created <ul> and the <li>s inside it to $("#tweets").
You can see more from jQuery#.jQuery().

Using jQuery .remove() to take <li> elements out of an <ol> but the DOM still thinks that the <li> elements are there?

I have a function that removes li elements from an ol when you click on an icon. When the ol is totally emptied, I would like to replace the li with a bit off filler material so that the user can still drag and drop new li elements into the list. (It's kind of a shopping cart setup.)
The problem that I'm running into is that when I use jQuery .remove() the li is removed from the DOM BUT jQuery doesn't it as being gone. So, for example, calling .has(".li") returns true even when all the li's are gone, and calling childNodes.length returns the total number of li that have ever existed in the ol. Code follows:
function onClick(element)
var parent = $(element).parent().attr('id');
$(element).remove();
var container = document.getElementById(parent);
console.log(container.childNodes.length); //always logs the total number that have ever existed
if(container.childNodes.length < 1){
parent.append("<li class='placeholder'>Drag and Drop Components Here</li>");
I'm pretty sure that this isn't the problem because I've been careful to grab the parent container only after the element was removed from the DOM.
Any ideas?
EDIT: The requested ul and li structure:
<h4>Components</h4>
<ol id="components" class="droppable">
<li class="placeholder">Drag and Drop Components Here</li>
</ol>
Users drag and drop the following code into the list, which is retrieved via $.get from some php scripts.
<li id="$id"><table style="color:white"><tr><td>$this->longname</td>
<td>Delete image</div></td></tr></table></li>
The click handler is the code above.
Assuming you have misplaced the function name onClick instead of destrComp, there are multiple problems.
To the click handler you are passing the clicked anchor element not the li element as you as assuming, so when you say $(element).parent() or $(element).remove() it is not dealing with the elements you think it is dealing.
Try
function destrComp(element) {
var $parent = $(element).closest('ul');
$(element).closest('li').remove();
if ($parent.children().length < 1) {
$parent.append("<li class='placeholder'>Drag and Drop Components Here</li>");
}
}
According to your code you seem to be removing the "a" tag, but not the parent.
$(element).remove(); //This removes the a tag
$(element).parents('li').remove(); //This removes the parent li element

Add return false to parent link only with jQuery

I have a list inside a toggled div...
<li>
Link
<ul stlye="display:none;">
<li>Child Link</li>
</ul>
</li>
Ive written a piece of jQuery to toggle the display of the child UL only when a child link is clicked it no longer works (It doesnt go through to google), can anybody see where im going wrong?
// Dropdown
$('.archives ul li a').click(function(){
$(this).parent().find('ul').slideToggle();
return false;
});
STYLE is spelled wrong.
stlye=
From your post's title it appears you want something like this...
$('.archives ul li a').click(function(){
var $children = $(this).parent().find('ul');
$children.slideToggle();
return $children.length > 0 ? false : true;
});
Return will be false only when child ULs are found.
Assuming what you've shown is inside a ul which is in turn inside an element with class archives, then the selector .archives ul li a matches both the parent and child anchors, because you've used a descendant selector, and so your handler gets called for the child, and the return false; prevents it from doing its default action (following the link).
If your goal is to have the handler triggered only for the earlier link and not for the child link, then you may need to be more specific. You haven't shown enough of your markup for us to help you be more specific, though. If I assume your markup looks something like this:
<div class="archives">
<ul>
<li>
Link
<ul style="display:none;">
<li>Child Link</li>
</ul>
</li>
</ul>
</div>
...then the selector to match only the "Link" anchor and not the "Child Link" anchor would be .archives > ul > li > a (e.g., using direct child selectors).
Also note that you had stlye rather than style, but I assume that's just a typo in the question. (Why don't people use copy and paste?! ;-) )
The ChildLink is also matched by your selector, and in the click handler you're preventing the default action (which would be "navigate to Google").
So you should adapt your selector to only get the toggle Link, or you use this:
$('.archives ul li a').click(function(e){
if ($(this).siblings('ul').slideToggle().length) // if we found a list to toggle
e.preventDefault(); // or return false
});
Since your return false statement is cancelling the default link action, you need to be more specific so that you don't target the links that want to allow to continue to function.
Try this:
$('.archives > li > a').click(function () {
$(this).parent().find('ul').slideToggle();
return false;
});
jsFiddle example
By using the > child selector and changing the target to only the immediate child links of the outermost list, the sublinks won't be selected and will continue to work. In your code your $('.archives ul li a') will apply to any child links, not just the top level.

Hide all LI`s except the selected

I want to hide all other LI's in a certain UL except the LI that I select.
<ul>
<li><div></div></li>
<li><div></div></li>
</ul>
<ul>
<li><div></div></li> -- HIDE
<li><div></div></li> -- SELECT
<li><div></div></li> -- HIDE
</ul>
<ul>
<li><div></div></li>
<li><div></div></li>
</ul>
How can I solve this the best way?
I've tried using indexes, but having some problems getting it to work, and selecting the correct UL. As you may see, I've got no class on the UL's or LI's so I think the only option is LI's.
What I really do, is selecting a div inside the LI so, I get the selected LI's index by:
var li_index = $(this).parent().index();
You traverse the DOM up from the div that was clicked then hide the other elements with .not($(this).parent()).toggle() -> Not the li that surrounds this div
$('div').click(function () {
$(this).closest('ul').find('li').not($(this).parent()).toggle();
});
.toggle() can be replaced with .hide() if you don't want the User to be able to reverse their decision.
JS Fiddle: http://jsfiddle.net/tDmy3/2/
Tried something like this?
$(this).closest('ul').find('li').not(this).hide();
Or
$('li', $(this).closest('ul')).not(this).hide();
Get a jQuery element set with all relevant <li> elements, then remove the selected element. For example:
$('ul#mylist li').not(selector).hide();
From the JQuery documentation:
Given a jQuery object that represents a set of DOM elements, the .not() method constructs a new jQuery object from a subset of the matching elements. The supplied selector is tested against each element; the elements that don't match the selector will be included in the result.
Instead of a selector, you can also give the element object itself if you have a reference to it.
This should work:
$( 'ul li' ).click( function( e ) {
// by default, hide all li's
$( 'ul li' ).hide();
// show only the selected li
$( this ).show();
});
http://jsfiddle.net/BqKun/
Hope this helps.

Jquery select all children within children

I'm sure this will be a simple question but I still struggle with DOM selectors in Jquery so here is a model of my html code:
<fieldset class="product-options" id="product-options-wrapper">
<ul class="options-list">
<li><a href>Item1.1</a></li>
<li><a href>Item1.2</a></li>
<li><a href>Item1.3</a></li>
</ul>
...other html items here
<ul class="options-list">
<li><a href>Item2.1</a></li>
<li><a href>Item2.2</a></li>
<li><a href>Item2.3</a></li>
</ul>
</fieldset>
Now how do I select all of the 'li a' items in both lists (or X number of lists) with class name .options-list and bind them with a click function.
Currently I have:
$('fieldset#product-options-wrapper ul.options-list > li a').bind('click', function(e) {
//code here
});
And it only gets the first options-list.
Thanks, greatly appreciated!
EDIT: If i click on a Item2.X list item first, then it will grab that options list. But as soon as I click on the Item1.x list items it disregards the second .options-list
If you are going to bind to each li element, you should bind it to the ul element instead (helps greatly with performance when there are a lot of events).
$('.options-list', '#product-options-wrapper').bind('click', function(e)
{
e.preventDefault();//In case you don't want to go to a different page
var clicked = e.target;//The href that was clicked
/* If you only want this to happen if the a tag was clicked, add the following line
if(clicked.tagName == 'A')*/
//Rest here
});
How about $('.options-list a').bind('click', function(e) { });?
You can use delegate in this case to make it even simpler. Try this
$('#product-options-wrapper ul.options-list').delegate('li > a', 'click', function(e) {
//code here
});
Your method seems sound to me. I created a test fiddle using your HTML (and an extra anchor to prove that it won't get the click added) and your JS (with minor modifications).
http://jsfiddle.net/chrisvenus/esZxH/1/
The selector you had did work but since you said you wanted the a to be a direct child of the li (or at least I read it that way) I slightly tweaked it in my version above. ARe you sure its not just your function is not doing quite what you want while executing or can you confirm that your click function isn't being run at all?

Categories