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
Related
I am trying to link navigation menu items and jQuery tabs together. That means I have two submenu items just think those are category and item and also I have 2 tabs in my page, those are My category and My Items.
What I am trying to do using this is I want to open My category tab when I click on the link category from submenu and vice versa. And also I want to open My Item tab when I click on the link item from the submenu and vice versa.
I tried it doing with jQuery but can't get to work correctly.
My HTML -
<ul id="new-menu">
<li class="dropdown-holder" id="">
<a>My Menu</a>
<div class="dropdown">
<div class="menu-container">
<div class="menu-link">
my sub menu 1
</div>
<div class="menu-link">
my sub menu 2
</div>
</div>
</div>
</li>
<li class="dropdown-holder" id="">
<a>Category & Item</a>
<div class="dropdown">
<div class="menu-container">
<div class="menu-link">
Category
</div>
<div class="menu-link">
Item
</div>
</div>
</div>
</li>
</ul>
<div id="main">
<ul>
<li>Category</li>
<li>Item</li>
</ul>
<div id="tabs-1">
<p>On the Insert tab, the galleries include items that are designed to coordinate with the overall look of your document. You can use these galleries to insert tables, headers, footers, lists, cover pages, and other document building blocks. When you create pictures, charts, or diagrams, they also coordinate with your.</p>
</div>
<div id="tabs-2">
<p>On the Insert tab, the galleries include other document building blocks. When you create pictures, charts, or diagrams, they also coordinate with your.</p>
</div>
</div>
This is my jQuery:
function setCurrent(element) {
$('div').removeClass('current');
$(element).parent().addClass('current');
}
$('#cat_link').click(function() {
$('#tabs-1').hide();
$('#tabs-2').show();
setCurrent(this);
$('#ui-id-2').parent().removeClass('ui-tabs-active ui-state-active');
$('#ui-id-2').parent().addClass('ui-state-default ui-corner-top');
$('#ui-id-1').parent().removeClass('ui-state-default ui-corner-top');
$('#ui-id-1').parent().addClass('ui-tabs-active ui-state-active');
return false;
});
$('#item_link').click(function() {
$('#tabs-2').hide();
$('#tabs-1').show();
setCurrent(this);
$('#ui-id-1').parent().removeClass('ui-tabs-active ui-state-active');
$('#ui-id-1').parent().addClass('ui-state-default ui-corner-top');
$('#ui-id-2').parent().removeClass('ui-state-default ui-corner-top');
$('#ui-id-2').parent().addClass('ui-tabs-active ui-state-active');
return false;
});
This is JS Fiddle
You can see it is working in some manner but not perfectly. Reverse order also not working. Reverse order mean I need to select submenu item according to clicks on tabs.
UPDATE -
According to above JSFiddle
If I click on category link from submenu category tab is opening but its content display from item tab.
If I click on item link from submenu item tab is opening but its content from category tab.
Hope someone will help me.
Thank you.
You can make it simpler: Use right methods to do the job. You are not utilizing jquery ui tabs events /methods.
$("#main").tabs({
activate: function (event, ui) { // subscribe to tab activate
var target = '.menu-link [data-target=#' + ui.newTab.attr('aria-controls') + ']'; // Get the ID of the tab activated. aria-controls on the rendered tab div will give the id of the tab anchor. so get the target as the menu link which has the data-target as that of the id of the current tab.
addCurrent(target); // set up corresponding menu link
}
});
$('.menu-link a').click(function (e) {
e.preventDefault(); // This is required to prevent the default action on click of an anchor tab.
var target = $(this).data('target'); // Get the target repsective to the clicked menu. This is jquery data() to retreive data attribute value.
$("#main").tabs("option", { //Use right method to do the job. set which tab to be opened by using the jquery ui tabs option overload.
'active': $(target).index() - 1 // set the index of the tab to be opened. Get the index using .index() on the target which is the tab anchor and set that as active.
});
addCurrent(this); // set up style for the current menu link
});
function addCurrent(elem) {
$('.current'). // select the currently activated elements
not($(elem) // but not this one if clicked on itself
.closest('.menu-link') // get the closest(Use this instead of parent(), closest is recommended to parent)
.addClass('current') // add the class to the new menu
).removeClass('current'); // remove from existing ones.
}
Minor addition to your markup adding a data-target on your menu link to point to the tab:
Category
Demo
References:
tabs.activate
closest()
index()
tab options
.not()
This is all you need:
$("#main").tabs();
$('.menu-container .menu-link a').on("click", function() {
// get the position of the menu we clicked inside
var menu_ind = $(this).parents('.dropdown-holder').index();
// if not in the submenu we care about, go about default behavior
if( menu_ind != 1 ) return;
// get the position of the link
var ind = $(this).parents('.menu-link').index();
// activate the corresponding tab
$("#main").tabs('select', ind);
return false;
});
it's just tweaks based on the link I posted.
Fiddle: http://jsfiddle.net/925at/1/
You should include at least a snippet of the HTML that would put your jquery code in context so future visitors don't have to rely on jsfiddle.
It looks like you are calling hide/show on the wrong divs.
If #tabs-1 holds your category content, and #tabs-2 holds your item content, shouldn't clicking on #cat-link show #tabs-1 and not hide it?
I have a drop down menu that returns results after a selection. The user can then click a link, cloning the dropdown menu, and choose another selection that will return more results. The structure of the results div is as follows:
<ul>
<li class="red">
<span> some html content</span>
</li>
<li class="red">
<span> some html content</span>
</li>
</ul>
I would like the user to click an li and change the background color. The user should only be able to change the color of one li at a time. I am able to accomplish this first part using:
$("li.red, li.blue").live("click",function() {
var $this, c;
$this = $(this);
c = $this.hasClass("red")
? {us: "blue", them: "red" }
: {us: "red", them: "blue" };
$("li." + c.us).removeClass(c.us).addClass(c.them);
$this.removeClass(c.them).addClass(c.us);
});
The problem is that when the user adds another selection (and the previous dropdown is cloned using jquery), and clicks an li in that results div, the previous selection is unselected. I want the user to be able to change the background of the li for the first set of results, as well as change the background for the second set of results. So each set of results would be able to toggle background colors between only that particular ul.
Any help is much appreciated!
Try this...
$("ul").on("click", "li", function() {
$(this).parent().find("li").removeClass("red").addClass("blue");
$(this).toggleClass("red").toggleClass("blue");
});
jsFiddle example... http://jsfiddle.net/L34pT/3/
Giving the ul a class name or ID would make sure it only affects the list in question. It looks a little pointless, but I used parent and find so that you only have to change the ul selector if you do give it a class or ID, and it will still work.
Try to use on() instead of live():
$(document).on("click","li.red, li.blue",function() {
...
});
I made a table out of a simple list structure:
<html>
<body>
<ul id="Column:0">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:1">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:2">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
</body>
</html>
Now I want to add a simple .mouseover() to every row, for e.g. changing the color of a row, when hovered. And this is what I figured out, so far:
for (var i = 2; i <= _totalRows; i++) {
var row = $('#TimeTable ul li:nth-child(' + i + ')')
row.each(function() {
$(this).click(function(evt) {
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
}); //end $(this).click(fn)
}); // end each(fn)
}
I get a set of all <li> objects matching to :nth-child(i) where i is the rows number.
var row = $('#TimeTable ul li:nth-child(' + i + ')')
Now I just iter this set through to add a .click(fn) to every <li>.
This works fine. Every cell has it's .click(fn) attached to it.
But the following, what to do on a click, is where I'm stuck for several hours now:
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
I simply don't get it to run.
You can actually ignore this gibberish, as it's just the last of several things I already tried here.
What I'm trying to do is simply select every <li> with an id='Row:X' and manipulate its CSS. The best I yet had was, that I can click a cell, but no matter in what row this cell is, the last one gets colored. I remember having used i as the row-index, when that happened, so I might miss some understanding of event-handling here, too.
Use a class name for duplicate groups of elements not an ID. If you give row one a class of "Row1" the selector is simply:
$('.Row1')
Then:
$('#TimeTable li').removeClass('highlight');
$('.Row1').addClass('highlight');
If you just wish to change the color on mouseover:
$('#TimeTable ul li').mouseover(function(){
$(this).css('background','red');
});
$('#TimeTable ul li').mouseout(function(){
$(this).css('background','green');
});
Make your ID's like so: C1R1 (Column1Row1) and so on
JQuery read/google up "jquery each"
JQuery read/google up "jquery bind click"
JQuery read/google up "jquery attr" and "JQuery val()"
This will give you the knowledge to write your own and most importantly understand it better. You will want to achieve the following (your close but no for loop required):
A list which JQuery attaches a click event handler to each LI, and then when the click happens the ID can be retrieved.
PS. There's a time and place for tables, they 9/10 times nearly always better for displaying data than CSS is. If you have a complex multi column row and want fiexed hights and no JS to fix things or do anything smart you can have a table and css :Hover on TR for stying mouse over and out etc. Heights are also constant.
PS. PS. If your data is dynamic and coming from a database and the whole row is an ID from the database I tend to avoid using the html ID attribute for this and make my own. You can retrieve this via attr("myattribute");
NOTE ON CSS and IDS:
Standard practice for ID's are to be used once on a page.
Class for repeatable content
Good luck.
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();
I have a list in which I am dynamically adding the classname, now when I click on that item again the class stays there. I dont want that I want that classname to be assigned to the currently clicked list item.
<ul id="menubar">
<li>one</li>
<li>two</li>
</ul>
Now when I click on one I dynamically add classname, and when I click on two the classname stays the same on one and it gets affected on two as well. but I want it to be removed from one and to be applied to currently clicked item.
How can I achieve it?
$$('#menubar li').invoke('observe', 'click', (function(e) {
//removes classname from all the li elements
$$('#menubar li').invoke('removeClassName', 'myClass');
//Gets the li you clicked on
var list_item = Event.element(e);
//adds the classname
list_item.addClassName('myClass');
}).bindAsEventListener(this));
You need to be including .removeClass() in the same event as when you addClass() to the other one.
$('.one').click(function(){
$(this).addClass('myClass');
$('.two').removeClass('myClass');
});
This could be written more efficiently, but im writing this in between meetings.
Hope it's a start!