Changing CSS class in jQuery - javascript

I'm trying to change the CSS class of a couple DIVs, Linked below is my jFiddle
The only change is that the -selected class actually has a background image which seems to have the background color of the -non-selected class.
The other problem is after selecting another div, you can't select the first one again. What exactly is jQuery doing with the classes? When I add the -non-selected class to it, it should become select-able again, right?
http://jsfiddle.net/9FZcz/
jQuery
$(".selector-box").click(function () {
$(".selector-box-selected").removeClass("selector-box-selected").addClass("selector-box");
$(this).removeClass("selector-box").addClass("selector-box-selected");
});
HTML
<div class="selector-box-selected"></div>
<div class="selector-box"></div>
<div class="selector-box"></div>
<div class="selector-box"></div>
CSS
.selector-box{
margin-bottom:2px;
width:328px;
height:46px;
background-color:rgba(255,255,255,.25);
}
.selector-box-selected{
margin-bottom:2px;
width:351px;
height:46px;
background-image:url(../images/layout/SelectedArrow.png);
}

You should try another way to adding and removing classes, try this one :
$(".selector-box").click(function () {
$('.selector-box').removeClass("selected");
$(this).addClass("selected");
});
Updated JsFiddle

The problem with not being able to select the first one again is that the click event is not being linked to it, since you only apply it to the <div> elements with the class .selector-box. Apart from that, CSS seems fine, check the fiddle: http://jsfiddle.net/9FZcz/2/

I change your code abit
<div name="ss" class="selector-box-selected"></div>
<div name="ss" class="selector-box"></div>
<div name="ss" class="selector-box"></div>
<div name="ss" class="selector-box"></div>
$("div[name=ss]").click(function () {
$("div[name=ss]").removeClass("selector-box-selected").addClass("selector-box");
$(this).removeClass("selector-box").addClass("selector-box-selected");
});
don't mind a name SS, change it to what you want :D

There are already answers posted that suggests solutions that requires some refactoring, like adding a selected class to selected elements rather than having seperate selector-box-selected and selector-box classes.
While I think you should perform the refactoring since it makes the overall design better and leads to less CSS code duplication, here's a solution without refactoring the code.
I kept track of the last selected element to avoid looping over all of boxes to remove the selected class.
DEMO
var selectedBox = $('.selector-box-selected').get();
$('.selector-box').add(selectedBox).click(function () {
if (selectedBox === this) return;
selectedBox = $([this, selectedBox])
.toggleClass('selector-box-selected')
.toggleClass('selector-box')
.get(0);
});

Related

jQuery.toggle() not working on a div

On a web page we have a list of profiles. On the right hand side of the profile is some text, followed by an arrow img#arrow.
When img#arrow is clicked, we have the following jQuery we hope to run:
However, the corresponding .bottom-sec is not toggling.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent +' .bottom-sec').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec" style="display: none;">
<p>Initially hidden text.</p>
</div>
<img id="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
Problem
The problem with your code is exactly what the comment on your question is saying, but he didn't explain anything:
You're combining two different ways of selecting elements. One is with selectors, the other is traversing. You're using them in a way which isn't possible (the $parent + ' .bottom-sec' part). The comment linked to a jQuery page about traversing which you should definitely read! It tells you a lot about how to use traversing functions, which you could use!
Solution
There are multiple solutions to this, but I'll write down the one I think is the best:
First of all, change the HTML a bit. I've removed the element style of .bottom-sec and changed the id of the image to a class, because you have multiple images with the same id on the page, which is not a recommended thing to do. Classes can occur more than once, id's cannot.
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec">
<p>Initially hidden text.</p>
</div>
<img class="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
I've reduced the JavaScript to the following. Note that is just reduced to one line, where a click on the .arrow element goes searching for the closest .profile-right parent. If, for whatever reason, you decide to change the HTML and the .arrow element is no longer a child of the .profile-right, this code still works. The only thing it does is toggle an active class on the .profile-right.
jQuery(document).on('ready', function() {
jQuery('.arrow').on('click', function(){
jQuery(this).closest('.profile-right').toggleClass('active');
});
});
The document ready listener was added because of OP's comment.
With CSS, we can use the new .active class to show or hide the element.
.profile-right .bottom-sec {
display: none
}
.profile-right.active .bottom-sec {
display: block
}
Original Code Fix
If for some reason you wanted to use your original code, this is how it should be:
// Nothing wrong about this part.
// Your only worry should be that there could be
// multiple elements with the same ID, which is something really bad.
jQuery('#arrow').click(function(){
// This part is correct, no worries
var $parent = $(this).parent();
// Removed the $(...), because $parent is already a jQuery object
$parent.addClass('active');
// Changed the selector to a find function
$parent.find('.bottom-sec').toggle();
});
You could also combine all of the code inside the listener function to just one line:
jQuery('#arrow').click(function(){
$(this).parent().addClass('active').find('.bottom-sec').toggle();
});
Change your js code like below.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent).find('.bottom-sec').toggle();
});
In your event listener you can catch the element (the down arrow) that triggered the event. It will be referred as this.
Then you can go through the DOM tree using .next() and .parent() to access the <div> to toggle.
Note: you may need more functions than the one I explained above.
Note 2: without code or more detailed information, we can't help you further, I will edit this answer if you add details.

jQuery refactoring, how to avoid repetitive code?

I know this is awfully simple, but I'm new to this and I just need to be shown it once. So when I'm using jQuery/javascript I find myself writing repetitive code again and again to target different elements with the same function, for example:
$(function() {
$('.icon1').click(function() {
$('.info1').toggle().addClass('animated fadeInDown');
$('.info2, .info3, .info4').hide();
});
});
$(function() {
$('.icon2').click(function() {
$('.info2').toggle().addClass('animated fadeInLeft');
$('.info1, .info3, .info4').hide();
});
});
and this repeats again for icon3 and icon4. I'm selecting a different element, showing another, hiding another three, and adding different classes in each function, and I don't know what would be the best way not to repeat the whole thing for each element. I would be very glad to be shown any ideas to refactor this, and wouldn't mind seeing how that is done in vanilla js also.
(For illustration the code here is a snippet from the code on the experience section of my portfolio where clicking on an icon reveals an info panel about it, and hides any previously shown info panels.)
Use a common class, use this, and not to remove it from the collection
$(function() {
$('.commonClass').click(function() {
$(this).toggle().addClass('animated fadeInDown');
$('.commonClass').not(this).hide();
});
});
You should be able to separate those selectors with commas.
$('.icon1,.icon2').click(function()
Or assign each a single class they share that behavior? ".icon-btn" where you use ".icon-btn" as the selector for any you wish to have that behavior.
It would be better if you can plan your html better with data attribute
for eg:
<div class="icon" data-info = "1"> <div>
<div class="icon" data-info = "2"> <div>
<div class="info-1 info"> <div>
<div class="info-2 info"> <div>
$('.icon').click(function() {
var className = '.info-' + $(this).data('info');
$('.info').hide();
$(className).toggle().addClass('animated fadeInDown');
});
you can also remove .info1,.info2 from js code by adding some common class in html as info to them.
for eg
I'm making some assumptions about your actual HTML, but you could probably leverage the siblings() method in this case.
$(document).on('click', '.icon', function() {
$(this).toggle().addClass('animated fadeIn')
.siblings().hide();
});

jQuery set class not working after its already been set

trying to make a simple expanding heading script.
I don't wish to use accordions and just looking for a light weight home made solution. As i enjoy writing and learning things myself.
In my eyes, what i have should work. But it doesnt.
The aim is:
When a heading is clicked, all of the content is hidden and then the next content element after the heading is shown. This prevents more than one content being shown at any time.
After this, the div class gets changed to be a 'selected' state.
This works okay.
However, the next part runs if the heading class is the selected state, and if so it SHOULD change its class back to the normal and also hide the next element content.
The aim is to allow the hide / show options.
The latter part of changing back the class doesnt work however. I also know there is a much for efficient way of writing this, but not sure how.
JS:
$(function() {
$('.headingHelp').click(function(){
$('.infoHelp').fadeOut();
$(this).next('.infoHelp').fadeIn();
$(this).attr('class', 'headingHelp_sel');
});
$('.headingHelp_sel').click(function(){
$(this).next('.infoHelp').fadeOut();
$(this).attr('class', 'headingHelp');
});
});
Example HTML:
<p class="headingHelp">Content Heading</p>
<div class="infoHelp">
Content
</div>
<p class="headingHelp">Content Heading 2</p>
<div class="infoHelp">
Content 2
</div>
JSFiddle: http://jsfiddle.net/C7bHn/1/
Thanks in advance!
Since your "selected" class is added after the DOM is loaded, jQuery is not aware of it.
I suggest using jQuery's on() for delegated events. This will allow you to select dynamically generated classes:
$(document).on('click','.headingHelp',function(){
$('.infoHelp').fadeOut();
$(this).next('.infoHelp').fadeIn();
$(this).attr('class', 'headingHelp_sel');
});
$(document).on('click','.headingHelp_sel',function(){
$(this).next('.infoHelp').fadeOut();
$(this).attr('class', 'headingHelp');
});
Working Example (jsfiddle)
Edit:
Here's another method without using delegation. It just adds/removes a "sel" class rather than changing the class completely.
$('.headingHelp').click(function(){
// save clicked element in a variable for use below
$this=$(this);
// remove / add "selected" class
$('.headingHelp').removeClass('sel');
$this.addClass('sel');
// fade in / out content
$('.infoHelp').fadeOut();
$this.next('.infoHelp').stop().fadeIn();
});
.infoHelp {
display: none;
}
.headingHelp {
background-color:#999;
padding: 1%;
cursor: pointer;
color: white;
}
.headingHelp:hover,
.headingHelp.sel {
background-color:#666;
}
Working Example (jsfiddle)
jQuery selector working "AT CURRENT MOMENT" . Your selector $('.headingHelp_sel') empty when running this code.
Best code:
$(function() {
$('.headingHelp').click(function(){
var open = $(this).next('.infoHelp').is(':visible');
$('.infoHelp').fadeOut();
if(!open)
{
$(this).next('.infoHelp').fadeIn();
}
});
});

jQuery click function using same classes

I have a dropdown function that I need to work only on the div clicked, not all (I have 14+ of the same classes on the page that need to be displayed when a certain one is clicked)
At the moment my jQuery is as follows.
$('.qacollapsed').hide();
$('.qa').click(function () {
$('.qacollapsed').slideToggle();
$(this).toggleClass('active');
});
Of course, that is toggling all qacollapsed classes when there is 14 on the page (Q&A)
Is there a way for it to only drop down the one that is clicked?
the HTML
<div class="qa">
<h4 class="question"> </h4>
</div>
<div class="qacollapsed">
<p> </p>
</div>
It would be helpful to provide a snippet of HTML here, but I'll take a guess at the structure of your markup for now..
Instead of referencing all .qacollapsed elements, you need find elements that are close to the .qa that was clicked, e.g.:
$('.qa').click(function () {
$(this) // start with the clicked element
.find('.qacollapsed') // find child .qacollapsed elements only
.slideToggle();
$(this).toggleClass('active');
});
This will work if .qacollapsed is inside .qa - if not, you might need to use next (for siblings), or one of the other jQuery tree traversal methods.
Yo could find() it or use this as a context in the selector to choose only a descendent of the clicked object
$('.qa').click(function () {
$('.qacollapsed', this).slideToggle();
//You could do $(this).find('.qacollapsed').slideToggle();
$(this).toggleClass('active');
});
Check out the jQuery selectors and why not just use $(this)?
$('.qacollapsed').hide();
$('.qa').click(function () {
$(this).toggleClass('active').next().slideToggle();
});
Personally, I'd give all the divs IDs, the clickable bit being the ID of the question in the database for example, and the answer just being id='ID_answer' or something, then use jquery to slide in the div with the id corresponding to the link clicked, ie
Var showIt = $(this).attr('id') + '_answer'
$('.qacollapsed').not('#'+showIt).hide();
$('#'+showIt).slideToggle;
That will hide all the divs without that ID and show the required one.
Dexter's use of .next above looks simpler though, I've not tried that as being relatively new to jquery too.

jQuery toggle - Close all except this

I have found this code (jQuery):
$('.toggle').click(function() {
$('.container').eq($(this).index()).toggle('fast');
});
This is my HTML:
<h4 class="toggle">Title1</h4>
<h4 class="toggle">Title2</h4>
<h4 class="toggle">Title3</h4>
<div class="container">Content1</div>
<div class="container">Content2</div>
<div class="container">Content3</div>
CSS
.container {
display: none;
}
I can toggle what I want with it.
The problem
When I click the toggle-class I want to close all open container-classes BUT NOT the current container-class (because it should be toggled).
The current container-class should toggle. That means that all elements could be closed BUT ONLY ONE could be opened at the same time.
I tried to just put jQuery hide before the script but that makes the container-class impossible to close (because when toggle hide is equal to show).
Code guess hide all .container except this
Using David's answer as a starting point, we can use .siblings to accomplish what you want:
$('.toggle').click(function() {
var index = $(this).index();
$('.container').eq(index).toggle().siblings('.container').hide();
});
See: http://www.jsfiddle.net/85zCp/
As an aside, you might want to use JavaScript to hide all elements initially instead of CSS because users with JavaScript disabled won't be able to see any content if you use CSS to hide them. Also, you would probably want to have each h4 heading in front of the contents instead of it put together like you're doing right now.
$('.toggle').click(function () {
$('.container').hide('fast');
$('.container').eq($(this).index()).show('fast');
});
I don't know exactly but I think this is what you're looking for...
Cheers...
This is a little verbose, but its use should be fairly obvious:
$('.toggle').click(
function(){
var index = $(this).index();
$('.container').hide().eq(index).show();
});
JS Fiddle demo.

Categories

Resources