Solved

jQuery Toggle - How to keep/retain the current class after toggle.

Posted on 2016-09-12
9
46 Views
Last Modified: 2016-09-13
I'm using a unordered list as a drop down menu. When the user selects their color choice the toggle occurs as intended but it removes the current class of the selected item. I would like to retain the current class but also add the new class. Hopefully I'm explaining this correctly. Let me know if you need me to clarify anything.

The List:
<ul class="singleSelect">
    <li class="init">CHOOSE COLOR</li>
    <li class="red-sq" data-value="Red">RED</li>
    <li class="black-sq" data-value="Black">BLACK</li>
    <li class="green-sq" data-value="Green">GREEN</li>
    <li class="blue-sq" data-value="Blue">BLUE</li>
</ul>

After they select a color (i.e. Black) it looks like this:
<ul class="singleSelect">
    <li class="init">BLACK</li>
    <li class="red-sq" data-value="Red">RED</li>
    <li class="black-sq" data-value="Black">BLACK</li>
    <li class="green-sq" data-value="Green">GREEN</li>
    <li class="blue-sq" data-value="Blue">BLUE</li>
</ul>

I want it to look like this:
<ul class="singleSelect">
    <li class="init black-sq">BLACK</li>
    <li class="red-sq" data-value="Red">RED</li>
    <li class="black-sq" data-value="Black">BLACK</li>
    <li class="green-sq" data-value="Green">GREEN</li>
    <li class="blue-sq" data-value="Blue">BLUE</li>
</ul>

<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$("ul.singleSelect").on("click", ".init", function() {
    $(this).closest("ul.singleSelect").children('li:not(.init)').toggle();
});

var allOptions = $("ul.singleSelect").children('li:not(.init)');
$("ul.singleSelect").on("click", "li:not(.init)", function() {
    allOptions.removeClass('selected');
    $(this).addClass('selected');
    $("ul.singleSelect").children('.init').html($(this).html());
    allOptions.toggle();
});


$("#submit").click(function() {
    alert("The selected Value is "+ $("ul").find(".selected").data("value"));
});

});//]]> 

</script>

Open in new window

0
Comment
Question by:swaggerking
  • 4
  • 3
  • 2
9 Comments
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41795577
What you are wanting to do is to give the .init <li> the same class as the clicked one - but then you would need to know what the class was to add it and to remove it when another item is checked.
Much easier to simply clone the clicked element, give it the .init class and then remove the existing init

$("ul.singleSelect").on("click", "li:not(.init)", function() {
  allOptions.removeClass('selected');
  $(this).addClass('selected');
  // CLONE
  var newinit = $(this).clone().addClass('init');
  // REMOVE EXISTING
  $('.init').remove();
  // PUT IT BACK
  $("ul.singleSelect").prepend(newinit);
  allOptions.toggle();
});

Open in new window

0
 
LVL 21

Expert Comment

by:Kim Walker
ID: 41796144
I'm not sure I understand your question. In your before and after example above, the only difference is that the content of the first <li> element has changed from "CHOOSE COLOR" to "BLACK". Yet you say
it removes the current class of the selected item
The selected item would be the third <li> element which still has its original class of black-sq.

In the jQuery code you have provided, the only class modification is to remove or add the class selected. But in the before and after samples you've provided, none of the classes have changed. And the desired result doesn't show any elements with the selected class.

In my testing, though, the third <li> element does, indeed, have both the black-sq and selected classes. In further testing, it appears that the code does exactly what it is programmed to do.

Please elaborate on what is happening for you that is not what you expected. Based on your desired result, Julian Hansen has provided code above to produce exactly that. But your sample code suggests there are other considerations to deal with.
0
 

Author Comment

by:swaggerking
ID: 41796382
Thanks Julian & Kim for your responses.
I couldn't get Julian's example to work due to not being as clear as I should have been with what I'm trying to accomplish. Let me try this again.

I have a drop down menu for selecting a color. The default first <li> is:
<li class="init">CHOOSE COLOR</li>

When the user clicks on the drops down list and chooses a color (i.e. Black) I would like the <li> class to change to:
<li class="init black-sq">BLACK</li> instead of <li class="init">BLACK</li>

I want the selected <li> to keep its current class but append/add ".inet" which is not currently happening. It's removing the class and replacing it with just ".inet". I want it to be the color class and the inet class. Make sense?
I'm attaching basic html example.
colorlist.html
0
 
LVL 51

Accepted Solution

by:
Julian Hansen earned 450 total points
ID: 41796496
I think I understood your requirement - I implemented your code locally to see what it does and then modified it to do what you wanted.

Here is the sample I put together - without your styles which I had to guess.
I took the code I posted above and added it to the source you posted. The problem was that you are adding and removing a selected class that is interferring - I removed those two lines and got this sample
JQuery
$(window).load(function(){
	$("ul.singleSelect").on("click", ".init", function() {
		$(this).closest("ul.singleSelect").children('li:not(.init)').toggle();
	});

	var allOptions = $("ul.singleSelect").children('li:not(.init)');
	$("ul.singleSelect").on("click", "li:not(.init)", function() {
	// REMOVED THESE
	//  allOptions.removeClass('selected');
	//  $(this).addClass('selected');
	  // CLONE
	  var newinit = $(this).clone().addClass('init');
	  // REMOVE EXISTING
	  $('.init').remove();
	  // PUT IT BACK
	  $("ul.singleSelect").prepend(newinit);
	  allOptions.toggle();
	});

	$("#submit").click(function() {
		alert("The selected Value is "+ $("ul").find(".selected").data("value"));
	});

});

Open in new window

1
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 21

Assisted Solution

by:Kim Walker
Kim Walker earned 50 total points
ID: 41796511
I tested Julian's code also and it works for me. The only thing I would add to Julian's last comment is that the submit click event will not work without the selected class. I have moved the line to add the selected class near the bottom.
$(window).load(function(){
	$("ul.singleSelect").on("click", ".init", function() {
	    $(this).closest("ul.singleSelect").children('li:not(.init)').toggle();
	});
	
	var allOptions = $("ul.singleSelect").children('li:not(.init)');
	$("ul.singleSelect").on("click", "li:not(.init)", function() {
		allOptions.removeClass('selected');
		// CLONE
		var newinit = $(this).clone().addClass('init');
		// REMOVE EXISTING
		$('.init').remove();
		// PUT IT BACK
		$("ul.singleSelect").prepend(newinit);
		$(this).addClass('selected');
		allOptions.toggle();
	});
	
	$("#submit").click(function() {
	    alert("The selected Value is "+ $("ul").find(".selected").data("value"));
	});

});

Open in new window

1
 

Author Comment

by:swaggerking
ID: 41796523
Julian and Kim,
Thank you. Your solution(s) was exactly what I was looking for. Your included explanation of the solution was beneficial to me as well. Have a great day.
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41796533
NB posted code did not include a submit button - not clear as to the requirement so a lot of guessing going on.

The selected item is always the first item so you can can get it by

$('li:first-child').data('value');

Open in new window

So this works
	$("#submit").click(function() {
		alert("The selected Value is "+ $("li:first-child").data("value"));
	});

Open in new window


No need for the selected class - I have updated the sample
1
 

Author Closing Comment

by:swaggerking
ID: 41796583
Thanks again!
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41796719
You are welcome.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now