I tried tackling my first project, an accordion menu. I have set to each item that needs to show/hide a class of .menu and an id.
While trying to retrieve the id's of each element i've used this statement:
var $currentId = $('ul.menu').attr('id');
Only problem is that it seems this only retrieves the id of the first element. Can anyone tell how can I retrieve all the It's to store them in a variable. I am planing to use if statements in order to check for each particular id when it's clicked.Thank You!
EDIT:It seems I was misunderstood what I have to do is this I'll start from the beginning:
Here is my HTML :
<ul id="container">
<li class="select">Downloads</li>
<li >
<ul class = "menu" id="first" >
<li>
iTunes
</li>
<li>
iTunes
</li>
</ul>
</li>
<li class="select">
Products List
</li>
<li>
<ul class = "menu" id="second" >
<li>
iTunes
</li>
<li>
iTunes
</li>
</ul>
</li>
What I have to do is when I click on the li with class of select I have to make the ul with the class of menu appear. How I wanted to do this to retrieve all the id's of the ul.menu and store them in a variable and when I click on any of the li.select the underlying ul should show.
Use each loop to get the ids of each element. Inside the loop use just just use this.id to get the id of the element where `this represents the dom element.
$('ul.menu').each(function(){
alert(this.id);
});
If you want the ids of all elements into an array you can use jQuery map method.
var Ids = $.map($('ul.menu'), function(){
return this.id;
});
map() translates all items in an array or object to new array of items. Ids will contain the ids of all the elements.
Then you can use $.inArray to search for a specific id within it. It will return its index or -1 if not found in the array.
if($.inArray("someId", Ids) != -1){
//Id found in the array
}
You may need to iterate over all the items and check the current status.
You can do this using the each method.
You can even dynamically add a listener for the click event for each element that matches your selector (in this case 'ul.menu'):
$('ul.menu').each(function(){
$(this).click(function()
{
alert('click');
});
});
EDIT: You can do this to hide/show the secondary items when the li.select items are clicked:
$('li.select').click(function(){
$(this).next().toggle();
});
This will give you an array that contains the ids:
var listOfIds = [];
$('ul.menu').each(function(){ listOfIds.push(this.id); });
The better thing to do would be to use
$('ul.menu li').click(function(event){
$(this).attr('id');
});
That will setup an event listener for each menu item and then allow you to do some thing when that menu item is clicked. The line with $(this).attr('id') can be replaced with any code you wish. Maybe even $(this).find('ul').show();
Related
I am looking for a way to compare elements using jQuery. Basically for every element with a certain data attribute, I want to "appendChild" another element that has a matching ID.
So in the following example, 'a' has a data attribute of data-dropdown="drop-delivery-options". The second element has an ID="drop-delivery-options", so they match. I can select elements with this ID but how do I select elements that match data-attributes/IDs?
So a function that would be like:
If elementA[data-attribute] = elementB[ID] {
(elementA).appendChild(elementB)
}
Add Option
<div id="drop-delivery-options" data-dropdown-content class="f-dropdown content table-options drop-delivery-options">
<ul>
<li>Add Deposit Account</li>
<li>Add Cash Pickup</li>
<li>Send to Card</li>
<li>Add Home Delivery</li>
</ul>
</div>
You can use the data-dropdown attribute to select the select element, then use appendTo() to append it to the a. Note though that given your example you will end up with nested a elements, which is invalid. You should look to change the parent a element to something else.
$('.button').click(function() {
$('#' + $(this).data('dropdown')).appendTo(this);
});
Working example
I am currently developing a remote file browser that allows the user to multi-select files and to delete the selected files together. The list is essentially a styled unordered list:
<ul class="nav">
<li><a>File one</a></li>
<li><a>File two</a></li>
<li><a>File three</a></li>
<li><a>File four</a></li>
</ul>
I've added a jQuery script that changes adds a style class to an li (i.e. highlights the item) when it is clicked:
var lis = $('.nav li a').click(function(e){
if(!e.ctrlKey) {
lis.removeClass("selected");
}
$(this).toggleClass("selected");
});
Now I want to implement a delete function that has to decide which files are selected, but I am unsure what is the best way to do this.
The easiest way will be to loop through the li entries and to check which entries are styled the class "selected".
Is this method advisable? That is, it is a good idea to use classes as flags?
You can simply use class selector to build required selector. there is no need to iterate over all li element and check for class selected existance:
$('.selected');
to remove li having anchor as selected:
$('.selected').parent().remove()
or
$('li:has(.selected)').remove()
I would like some help to optimize my code.
I have a product list.
<ul>
<li> Item 1 </li>
<li> Item 2 </li>
</ul>
For every item I have a section with the item's details.
<div id="item1-details"> Item Details 1 </div>
<div id="item2-details"> Item Details 2 </div>
These sections are hidden.
They only appear when the user clicks on the item listed above.
$("#item1").click(function() { $("#item1-details").show(); });
$("#item2").click(function() { $("#item2-details").show(); });
Up to this point I have no problems. The logic is very basic.
The problem comes when the information is retrieved from the database.
When the user clicks on an item, how do I pass the ID of the related detail's section to the jQuery function?
I have two foreach blocks. One to populate the - ul - list and another to create the detail's sections. I can use the item ID to make unique the link and use the same ID adding a character to make unique the details section. But how can I create this automatism with jQuery.
I hope I was clear, even with my English.
Thank you all.
you can use data attributes like this
<li> Item 1 </li>
and then
$("#item1").click(function() {
$attr = $(this).attr('data-id');
$("#item"+$attr+"-details").show();
});
Based on the fact that the ids are related, you can just use simple click, grab the id, and show it.
$("li").on("click", "a", function(evt) { //detect click on anchors in the li
var id = this.id; //get id of what is clicked
$("#" + id + "-details").show(); //show the element
evt.preventDefault();
});
You could do, get the id and with cointains (*=) show the the div:
$('div').hide();
$('ul a').click(function(){
$('div[id*=' + this.id +']').toggle();
})
DEMO
I was using the jquery next() method on the following html:
<div id="NavBar">
<div class="dropDownList">
<ul>
<li><span>Home</span></li>
<li><span>Products</span>
<ul>
<li><span>test</span>
<li><span>test</span>
</ul>
</li>
<li><span>Company</span>
</li>
<li><span>Contact</span></li>
</ul>
</div>
<div class="dropDownList">
<ul>
<li><span>Home</span></li>
<li><span>Products</span>
</li>
<li><span>Company</span>
</li>
<li><span>Contact</span></li>
</ul>
</div>
</div>
I added the following click handler to anchors in the list and wrote the current and next() element to the console like so:
$('.dropDownList > ul > li > a').click(function() {
console.dir($(this));
var checkElement = $(this).next();
console.dir(checkElement);
}
When I click the "Products" list item of the first ul I see this in the console:
So I can see the first element is the anchor and the next is the ul- this makes sense to me. Now my confusion comes in when I click the "Products" list item in the second ul. I get back two objects like before, but this time they are both anchors. I thought that the first anchor element would be "Products" and the second would be "Company" because that is the next element in the list- or maybe even the <li> element containing the next anchor. Instead when I drill down into the objects in the console they appear to be the same element. The text and textContent field is the same for both:
Why is this?
In your second example, the next element in the list is not a sibling to the a anchor; it's a sibling to its parent li.
That Products anchor has no .next() element, and you should see in your console that $(this).next() is an empty jQuery object with zero .length. http://jsfiddle.net/mblase75/6LFPG/
So the problem is that in your a anchor has no next() it will return null. So in that case you will have to go up to the parent and get the next sibling. Here is a really quick rough example on how it can be done.
var CheckElement;
if($(this).next().length != 0){
checkElement = $(this).next();
}
else{
checkElement = $(this).parent().next();
}
the JQuery next() method brings you to the next sibling of the selected element.
Siblings are those that elements that have the same parents.
From your given html
<li><span>Products</span> //child of 'li'
<ul> <----------------------------------//child of 'li'
<li><span>test</span>
<li><span>test</span>
</ul>
</li>
What you selected was the first child.
So when you called next in the first example it selected the next child.
In your second example there is no second child to traverse therefore it defaults to an empty jquery element.
I am trying to convert a nested li into one single li using recursive method using jquery
html as follows
<ul>
<li>item-1
<ul>
<li>item-1.1</li>
</ul>
</li>
<li>item-2
<ul>
<li>item-2.1</li>
<li>item-2.2
<ul>
<li>item-2.2.1</li>
<li>item-2.2.2</li>
</ul>
</li>
</ul>
</li>
<li>item-3
<ul>
<li>item-3.1</li>
</ul>
</li>
<li>item-4</li>
<li>item-5</li>
</ul>
Final single li as below
<ul>
<li>item-1</li>
<li>item-2</li>
<li>item-3</li>
<li>item-4</li>
<li>item-5</li>
<li>item-1.1</li>
<li>item-2.1</li>
<li>item-2.2</li>
<li>item-3.1</li>
<li>item-2.2.1</li>
<li>item-2.2.2</li>
</ul>
basically loop through each level then append to the end of the list.
Any ideas how I can achieve this? so it can handle any level of the list item.
Here is a recursive approach that will give the output you're looking for:
function recurseFetchListItems($ul)
{
var $li = $ul.remove().children("li").remove();
if ($li.length) {
$li = $li.add(recurseFetchListItems($li.children("ul")));
}
return $li;
}
It uses add() to accumulate the different levels of list items, while removing each level from the document. It also uses children() instead of find() in order to process a single depth level per call.
From there, you only have to start from the first <ul> element, add the cumulated set of list items back to the document, and wrap them in a new <ul> element:
$(document).ready(function() {
recurseFetchListItems($("ul:first")).appendTo("body").wrapAll("<ul>");
});
You can see the results in this fiddle.
Original (misguided) answer follows:
You don't really need a recursive function to do that, because whole DOM element trees can be matched with a single selector. For instance, $("li") matches all the list items, whatever their depth is.
So, to achieve what you want, we only need to match all the <li> elements, remove their parent <ul> elements from the document, then wrap the list items into a new <ul> element using wrapAll() and add that element back:
$(document).ready(function() {
$("li").parent().remove().end().appendTo("body").wrapAll("<ul>");
});
You can see the results in this fiddle.