Remove class from element and add to next element - javascript

I have a list of links, one has the class active.
On my next button click id like to remove the class from the current element and add it to the next only I cant seem to get it to add?
Ive made a fiddle to hopefully explain my problem, any help would be great, thanks
http://jsfiddle.net/h6D4k/
$('.next').click(function(){
$('ul.pagination').find('a.active').removeClass('active');
$('ul.pagination').find('a.active').next('a').addClass('active');
return false;
});

One of the jQuery most usable conveniencies is that its methods are (usually) chainable - in other words, they return the very object they are called from. So you can simply write this:
$('ul.pagination').find('a.active').removeClass('active').closest('li')
.next('li').find('a').addClass('active');
... as it's <li> elements that should be 'nexted', not <a> ones. But in fact, you shouldn't probably discard 'active' altogether if it's the last element in question:
var $a = $('ul.pagination').find('a.active'),
$li = $a.closest('li'),
$nextLi = $li.next('li');
if ($nextLi.length) {
$a.removeClass('active');
$nextLi.find('a').addClass('active');
}

This is actually what you want based on your html structure in you fiddle. http://jsfiddle.net/h6D4k/1/
$('ul.pagination').find('a.active').removeClass('active').parent()
.next().find('a').addClass('active');

Because once you've done this...
$('ul.pagination').find('a.active').removeClass('active');
There is no more a.active - the active classname has been removed from that element. So repeating the same selector...
$('ul.pagination').find('a.active')//...
... will select nothing.
Chain it all together instead.
$('ul.pagination').find('a.active').removeClass('active').next('a').addClass('active');
You have a second problem. According to the jQuery API for next(), it will:
Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector.
You're not trying to get the following sibling:
<ul class="pagination">
<li><a class="one active" href="#">X</a></li>
<li><a class="two" href="#">X</a></li>
<li><a class="three" href="#">X</a></li>
</ul>
Next
Prev
You're trying to get the next <a> in the whole document. That's more challenging - and I'm not sure how to do it.

I would write it this way, preventing the action from doing anything on the last li as well.
http://jsfiddle.net/h6D4k/6/
$('.next').click(function(e){
e.preventDefault();
if ($("ul.pagination a.active").parent().is(":last-child")) return;
$('ul.pagination a.active').removeClass('active').parent().next().find("a").addClass('active');
});

You have two errors in your code:
Once removed, the active class can't be found anymore
your a tags are nested in li tags so next() doesn't work as you expect
To simplify things, you could attach the active class to the li tags.
Live demo: http://jsfiddle.net/h6D4k/7/
Code:
$('.next').click(function(){
$('ul.pagination').find('li.active').removeClass('active')
.next().addClass('active');
return false;
});

Related

Need help using the .not() selector with nested elements

I am trying to clone an li element but without the tags.
I am have tried many different ways but I can make it seem to work.
When I take a look at the html of the li element it still selects the span tags.
Below is the code I am using. Any help would be really appreciated. Thanks!
<ul class="todo_list_items" data-category_id="44">
<li class="tasks" data-task_id="30">
<!-- Don't want to select this span class -->
<span class="modify_tasks">
<a href='#' class='delete_task_name'>Delete</a>
<a href='#' class='edit_task_name'>Edit Task</a>
</span>
Test
</li>
</ul>
<script>
$(document).on("click", ".edit_task_name", function () {
var task_id = $(this).data("task_id");
var previous = $(".tasks[data-task_id=30]").not(".tasks[data-task_id=30] > span").clone();
console.log(previous.html());
});
</script>
Just clone it and then empty it:
var previous = $(".tasks[data-task_id=30]").clone().empty();
EDIT: If you only want to remove the span and not other content, then just remove the span from the clone:
var previous = $(".tasks[data-task_id=30]").clone();
previous.children("span").remove();
not() will check against elements in the set, in your case the set consists of only $(".tasks[data-task_id=30]"). not() is testing the span inside it to see if it matches its own parent, so not wont be adjusting your jQuery object for cloning there. An alternative way to achieve what you want might be code similar to this:
var $tasks = $(".tasks[data-task_id=30]"),
$modifyTasks = $tasks.children('span').detach(),
$cloneOfTasks = $tasks.clone();
$modifyTasks.prependTo($tasks);
$cloneOfTasks.appendTo($tasks.parent());
.detach() removes the span without losing events and data so you can put it back in when your done making your clone.
Alternatively this code might be easier to interpret and use:
var $tasks = $(".tasks[data-task_id=30]");
$('ul.todo_list_items').append($tasks.contents().not('span').clone().wrap('<li class="tasks" data-task_id="30">').closest('li'));
This uses .contents() to grab whats inside the task so you can run not against it. The closest('li') part is needed to ensure the li wrapped around the new element is returned for appending to the ul.

Find element above another using jQuery

I'm trying to find the element using jQuery from the following html.
<ul class="gdl-toggle-box">
<li class="">
<h2 class="toggle-box-title"><span class="toggle-box-icon"></span>Volunteer Form</h2>
<div class="toggle-box-content" style="">
</div>
</li>
</ul>
What I'm looking to do is when the h2 is clicked find the li above the h2 add a class active to it. Tried a few different calls but no luck.
EDIT
The biggest issue is that there are multiple toggle boxes on a page so something like this works on pages with a single toggle but pages with multiple the result is they all open together.
var gdl_toggle_box = jQuery('ul.gdl-toggle-box');
gdl_toggle_box.find('li').each(function(){
jQuery(this).addClass('item');
});
gdl_toggle_box.find('li').not('.active').each(function(){
jQuery(this).children('.toggle-box-content').css('display', 'none');
});
gdl_toggle_box.find('h2').click(function(){
if( jQuery('.item').hasClass('active') ){
jQuery('.item').removeClass('active').children('.toggle-box-content').slideUp();
}else{
jQuery('.item').addClass('active').children('.toggle-box-content').slideDown();
}
});
You can use closest.
closest will match the first parent element that matches the selector traversing up the DOM tree.
Demo
$('h2.toggle-box-title').click(function(){
$(this).closest('li').addClass('active');
});
Try this.
$('h2.toggle-box-title').click(function(){
$(this).parent().addClass('newclass');
});
try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
On you click in the button you can use the event:
$("something").parent().find("h2.myClass");
// And if you want you can add class after you find you object
http://api.jquery.com/find/
Selecting an element's parent
In order to select an element parent, you can use the parent() function.
Try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
*to be more specific, you target the parent you would like to choose by specifying its selector
Check the jQuery API Documentation here
parent() - Get the parent of each element in the current set of matched elements,
optionally filtered by a selector.

select a parent with jQuery

Hello I have some HTML that looks like this,
<div id="music_interests">
<ul class="interests">
<li >
<div class="interest inline">
<img src=""/>
<div class="interest_popup">
1 users have this interest.
Remove interest </div>
</div>
</li>
</ul>
When users clicks the remove button I need to select the parent div (in this case music_interests). How would I go about that?
I have tried doing the following,
$(this).parent().parent().parent().parent() but is there a more elegant way?
To complicate things futher I will not actually no the parents ID when in the app as the remove button occurs in 4 or 5 different areas on the page.
you should use closest()
$(this).closest('div#music_interests');
//find the nearest div with id "music_interests"
//if i omitted the id, it retrieves the div with class "interest_popup"
or parents()
$(this).parents('div:eq(1)');
//get ALL the ancestor divs (until it reaches root tag)
//since music_interests is just 2 levels up, use :eq(1)
If the ID of the DIV you want to remove is static you should only use the ID selector (not something like $("div#music_interests")) as the ID selector is directly mapped to the DOM function document.getElementsById which is pretty fast:
$("#music_interests").remove();
If the ID isn't static you could get the UL just like that:
$(function(){ //execute when page has been loaded
$(".remove").click(function(){ //attach click handler
var removeDiv = $(this).closest("ul").parent().remove(); //get next UL -> DIV is its parent
return false; //stop further processing of "click" event
});
});
if remove button always exist in ul tag (in all your 4 or 5 different areas) then you can use the following code.
$(this).closest("ul").parent()
in this case u don't even need to give id to DIV tags

jquery .remove performance

I am trying to remove the li's with conditon under Ul in multiple div's.
<div>
<ul>
<li class="sel">.....</li>
<li class="sel">.....</li>
............
<li>.....</li>
<li>.....</li>
...........
<!-- I have some 600 li's -->
</ul>
</div>
I have 200 li's with class='sel'. Now I need to remove the remaining 400 li's.
I am trying to remove in two ways, like,
$("ul", this).each(function(){
$("li", this).each(function(){
$(this).remove();
//Also tried with -- $(this).empty().remove();
});
});
other way like,
$("ul", this).each(function(){
$("li[class!=sel]", this).remove(); // Also tried with 'not'
});
Now the problem is, When I am trying to execute these ways In IE getting Script overloaded error.
Please help me out on other ways to remove unwanted li's.
Note: I don't want to keep the un-wanted li's to hide() state.
Thanks in advance...
If you're using the Attribute Not Equal Selector, you don't need to wrap it with .each() - simply call it like this:
$('li[class!="sel"]').remove();
The selector ('li[class!="sel"]') is grabbing all <li> elements that don't have class sel and then calling the remove() method on that entire set of elements.
Demo
Edit
If you only want to target the <ul> which contains the <li class="sel"></li> elements, you can set the context like this:
// Find the first <li> with class="sel" and get it's parent <ul>
var $ul = $('li.sel:first').parent('ul');
// Use $ul as the context for the removal of the <li> elements
$('li[class!="sel"]', $ul).remove();
For what it's worth, I ran into a similar problem just a couple of weeks ago, only in IE8, even calling .remove() on a single item selected by id. The problem only occurred when the element contained a great deal of content.
What I did was to call .html('') to clear the element just before calling .remove(). This reduced the time dramatically (sub-second).
Mine was obviously a different situation (one element vs. many, selected by id vs. contextual selectors, not sure what your li content is, etc.), but it might be worth a shot.
$("ul", this).each(function(){
$("li[class!=sel]", this).html('').remove();
});
Try detaching the ul, remove the li's, then reattach the ul.
$("ul", this).detach().find("li").not(".sel").remove().end().end().appendTo(this);
This prevents the browser from redrawing until all li's that need to be removed are removed.

javascript driven navigation menu on footer

My navigation menu on header looks like this:
<ul id="nav">
<li id="home">
<a class="mainmenu" href="#">Link1</a>
</li>
<li>
<a class="mainmenu" href="#">Link2</a>
</li>
</ul>
and the same markup is used for the footer section and it's not working.
I have also a file called jscript.js which contains all the javascript for the website,
and I found this variable:
var navTarget = "ul#nav li a" //menu link to target
Also, if I remove for example the markup in the header sections the footer will work.
I've tried also to use .nav instead of #nav and I have the same problem.
The navigation menu is controlled by javascript, I don't post the code here because it's huge, for better understanding of how the navigation menu works look here
I've found this in the javascript:
//SET MENU ITEM IDs
$(navTarget).each(function(i){
i++
this.id = this.id +"_" +i ;
});
//MENU CLICK FUNCTION
$(navTarget).click(function() {
//ensure link isnt clickable when active
if ($(this).hasClass('active')) return false;
//get id of clicked item
activeNavItem = $(this).attr('id');
//call the page switch function
switchContent();
});
//CONTENT SWTICH FUNCTION
var switchContent = function (){
//set previous and next link & page ids
var PrevLink = $(navTarget+'.active')
$(PrevLink).removeClass('active');
var PrevId = $(PrevLink).attr('id');
//alert(PrevId)
var NextLink = $('#'+activeNavItem).addClass('active');
var NextId = activeNavItem
//alert(NextId);
From the looks of it, the JS code is using some CSS selector (like jquery's $ or dojo's dojo.query) that pulls in the DOM element target based on the value of navTarget, and then does something with it: turns it into a menu.
But its only doing it once.
You need to look at the JS and see where navTarget is used. Then it should be fairly easy to make it do the menu creation on all the results of $(navTarget) instead of just the first hit.
Also, you should only have on instance of an ID in your dom.
You can change this to a class instead:
var navTarget = "ul.nav li a"
And in the markup:
<div class='nav'>
But you will still have to look at the JS and make sure it functions against a set of targets returned by the CSS selector. That code is probably expecting just a single result and using just it: results[0].
You can only have one element of a given id on the page. So based on your description, it sounds like you have 2.
I don't know exactly how this script works, but you can try using classes instead.
<ul class="nav">
var navTarget = "ul.nav li a";
You would have to change your HTML and the JS navTarget selector string.
But there is also a good chance that your script may not support creating multiple menus at all. And if thats the case, you may need to fix that script or find a better one.
If the code for the footer really is identical to the header, that's the problem. An id should only be used for a single element in a page, and jQuery's selectors will only return the first. Meaning code like "ul#nav li a" only works on the header.
Easiest solution is to change the id's to classes, e.g.:
<ul class="nav">
... and change your jQuery to match that, e.g.:
var navTarget = "ul.nav li a";
Update: And (ignoring that this may end up turning into three duplicate posts), that fix is probably not enough at all, since other parts of the script may only work with a single menu.

Categories

Resources