jQuery to flip arrow icon based on collapse position - javascript

I am looking for some jQuery that will flip my arrow icon from down to up based on the position of the collapsed state.
<div class="panel panel-default">
<div class="panel-heading customize">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#personnel-menu" href="#personnel">
Personnel
<span class="pull-right"><i class="fa fa-angle-down"></i></span>
</a>
</h4>
</div>
<div id="personnel" class="panel-collapse collapse">
<div class="panel-body">
<ul class="list-unstyled stripped">
<li>Users</li>
</ul>
</div>
</div>
</div>
When in "open" position, this line <div id="personnel" class="panel-collapse collapse"> will change to <div id="personnel" class="panel-collapse collapse in">. Adds "in".
While in this position, with "in" <div id="personnel" class="panel-collapse collapse in"> I would like to take the line <span class="pull-right"><i class="fa fa-angle-down"></i></span> (a few lines above the former) and change the class fa-angle-down to fa-angle-up.
How can I achieve this?
Thanks.

From your example, I assume you're using Bootstrap's Collapse plugin with Font Awesome.
If it's the case, perhaps you could try hooking into the Collapse's shown.bs.collapse and hidden.bs.collapse events and do your manipulation (flipping the arrow icon) there.
For example:
$('#personnel-menu').on('hidden.bs.collapse', function (event) {
var arrow = $('#' + event.target.id).parent().find('i');
arrow.removeClass('fa-angle-down');
arrow.addClass('fa-angle-up');
}).on('shown.bs.collapse', function (event) {
var arrow = $('#' + event.target.id).parent().find('i');
arrow.removeClass('fa-angle-up');
arrow.addClass('fa-angle-down');
});
Live Demo: http://jsfiddle.net/pUam7/show/ (source)

The code to do this is fairly straight forward:
var elem = $("#personnel");
if (elem.hasClass("in")) {
elem.parents(".panel").first().find(".fa-angle-down")
.removeClass("fa-angle-down")
.addClass("fa-angle-up");
}
else {
elem.parents(".panel").first().find(".fa-angle-up")
.removeClass("fa-angle-up")
.addClass("fa-angle-down");
}
You would trigger this code whenever you want to add the "in" class to the $("#personel") object.
However, if you're going to be adding the class anyway, IMO a better way to do it would be to add the class to the $(".panel") div - then CSS will take care of the changes for you, eg:
.panel .panel-heading .panel-title a i.fa {
background-color: red;
}
.panel.in .panel-heading .panel-title a i.fa {
background-color: blue;
}
Even if you do want to use javascript, then, IMO it's best to add the code to change the class (from fa-angle-down to fa-angle-up and vice-versa) on whatever event/in whatever function call you are using to add the "in" class to the $("#personnel") object.

Related

Select all but this element

I have a few accordions setup and I'd like only one to be open throughout the whole page. I thought that the .not() method would achieve what I wanted however it is just immediately closing the current div.
Here is what I have if anyone can spot where I've gone wrong:
JS
$( document ).ajaxComplete(function() {
$('.accordion-toggle').click(function(){
//Expand or collapse this panel
$(this).next().stop().slideToggle('1000');
$(this).toggleClass('active').siblings().removeClass('active');
//Hide the other panels
$('.accordion-content').not(this).slideUp('1000');
});
});
HTML
<div id="location1">
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
</div>
<div id="location2">
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
<h3 class="accordion-toggle">Opening times <i class="fa fa-angle-down"></i></h3>
<div class="accordion-content">
<p>List of products available here!</p>
</div>
</div>
CSS
.accordion-content {
display: none;
padding:20px 0;
border-bottom: 1px solid #d4d5d7;
}
.accordion-content.default {display: block;}
.accordion-toggle {
cursor: pointer;
font-size:18px;
padding:10px 0;
margin:0;
border-bottom:1px solid #d4d5d7;
position:relative;
}
You were pretty close. You should change this line
$('.accordion-content').not(this).slideUp('1000');
To This:
$('.accordion-toggle').not(this).next().slideUp('1000');
Since your click function is applied to the accordion-toggle class, you have to target that class since this is an accordion-toggle class element, and you want to filter out all elements that are not this object. This will also force you to have to use the .next() method since you're looking to slide the next element in the DOM.
Edit 1:
In order to remove the active class across all of the #locationX divs, you should separate this line
$(this).toggleClass('active').siblings().removeClass('active');
Into this:
$('.active').not(this).removeClass('active');
$(this).toggleClass('active');
The way it was written previously, after the active class is toggled on the current element, it will only remove that class from all sibling elements, which won't properly affect elements in the other divs. It makes the script a bit longer, but it will remove all of the active classes before toggling the class on the current element.
Edit 2:
The simplest solution for the whole function is probably the following:
$('.accordion-toggle').click(function(){
//Expand or collapse this panel
$(this).next().stop().slideToggle('1000');
//Hide the other panels
$('.accordion-toggle').not(this).removeClass('active').next().slideUp('1000');
$(this).toggleClass('active');
});
In your case this is the toggle not the content (it would also have to be $(this) not just this, so:
$('.accordion-content').not(this).slideUp('1000');
Will match all accordion content.
You could try:
var $content = $(this).next('.accordion-content');
$('.accordion-content').not($content).slideUp('1000');
As a note, I would set var $this = $(this); at the beginning of your handler so that you are not repeatedly creating jQuery objects which is relatively expensive.

Jquery toggle and add/remove

I have two buttons.
Both buttons have a rollover css color change.
One of the buttons just links to another page.. however, the other button when clicked needs to
A.) Show a hidden div
B.) toggle to the roll-over color and stay that color. (but not change the other buttons class)
I only want the button with the id of "edit" to toggle the class m-button-regular to m-button-active and not the other button. The JQuery I am using changes both buttons classes to m-button-active.
What is going wrong in this script?
<a href="#tab1" id="edit" >
<span class="m-button-small m-button-regular text-center floatleft clearfix mtm mls" id="sm-tab1">
<i class="fa fa-gear"></i>
<p>EDIT</p>
</span>
</a>
<a href="#tab1">
<span class="m-button-small m-button-regular text-center floatleft clearfix mtm mls" id="sm-tab1">
<i class="fa fa-plus"></i>
<p>ADD</p>
</span>
</a>
<div class="row editcontainer">
</div>
$('.editcontainer').hide();
$(document).ready(function(){
$('#edit').click(function(){
$(".editcontainer").toggle();
$('.m-button-regular').toggleClass("m-button-active");
});
});
You need to use .find() to refer its child span, then you can use toggle.
Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
Use
$(this).find('.m-button-regular').toggleClass("m-button-active");
instead of
$('.m-button-regular').toggleClass("m-button-active");
This seems to do what you want :
$('.editcontainer').hide();
$(document).ready(function() {
$('#edit').click(function() {
$(".editcontainer").toggle();
$('#edit').toggleClass("m-button-active");
});
});
.m-button-active {
color : green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<a href="#tab1" id="edit">
<span class="m-button-small m-button-regular text-center floatleft clearfix mtm mls" id="sm-tab1">
<i class="fa fa-gear"></i>
<p>EDIT</p>
</span>
</a>
<a href="#tab1">
<span class="m-button-small m-button-regular text-center floatleft clearfix mtm mls" id="sm-tab1">
<i class="fa fa-plus"></i>
<p>ADD</p>
</span>
</a>
<div class="row editcontainer" style="display: none">Edit container</div>
By the way your selector was originally selecting both buttons.
This is refering to all classes:
$('.m-button-regular').toggleClass("m-button-active");
You must refer the button
$("#edit").toggleClass("m-button-active");
You are almost right but slight change to your code and bingo
$('.editcontainer').hide();
$(document).ready(function(){
$('#edit').click(function(){
$(".editcontainer").toggle();
$('.m-button-regular',this).toggleClass("m-button-active"); //<--- add a scope, same as $(this).find
});
});

Bootstrap 3 Collapse - changing the glyphicon in the panel heading depending on collapse state

I know that this has been asked several times but I cannot get any of the answers to work in my code.
I am using Bootstrap 3 panels and collapse to show adverts. In the basic view, only the advert heading is shown together with a chevron down glyph to indicate that there is more information.
When the user clicks on the chevron-down, the main panel body containing the advert text is shown. At this point, I would like the chevron-down glyph to change to a chevron-up glyp.
I am using the following code:
<script language="JavaScript" type="text/javascript">
$('#Advert').on('show.bs.collapse', function(){
$('#Glyp-Advert').removeclass('glyphicon glyphicon-chevron-down').addclass('glyphicon glyphicon-chevron-up');
});
$('#Advert').on('hide.bs.collapse', function() {
$('#Glyp-Advert').removeclass('glyphicon glyphicon-chevron-up').addclass('glyphicon glyphicon-chevron-down');
});
</script>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a id="Heading-Advert" data-toggle="collapse" data-parent="#accordion" href="#Advert">
Heading
<span class="pull-right"><span id="Glyp-Advert" class="glyphicon glyphicon-chevron-down"></span></span>
</a>
</h4>
</div>
<div id="Advert" class="panel-collapse collapse">
<div class="panel-body">
Advert text<br />
</div>
</div>
</div>
This succeeds in displaying the main advert panel but will not change the glyph.
Any help would be appreciated. Note that the page will contain several adverts; so I intend to repeat the above code several times on the page but change the id's to contain the word 'Advert1' or 'Advert2' etc instead of just 'Advert'.
JavaScript is case-sensitive.
As such, your calls to removeclass and addclass are invalid because removeClass and addClass are the actual method names (notice the capital 'C' in each name).
Your code works otherwise. See http://jsfiddle.net/wilsonjonash/SXYZ2/
The answer from Jonathan Wilson was spot on BUT it failed to mention that the script needs to be AFTER the html and not before in my sample code.
Therefore, the correct code should be
<div class="panel panel-default"><div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a id="Heading-Advert" data-toggle="collapse" data-parent="#accordion" href="#Advert">
<span class="pull-right"><span id="Glyp-Advert" class="glyphicon glyphicon-chevron-down"></span></span>
Heading
</a>
</h4>
</div>
<div id="Advert" class="panel-collapse collapse">
<div class="panel-body">
Advert text<br />
</div>
</div>
</div>
<script language="JavaScript" type="text/javascript">
$('#Advert').on('show.bs.collapse', function(){
$('#Glyp-Advert').removeClass('glyphicon glyphicon-chevron-down').addClass('glyphicon glyphicon-chevron-up');
});
$('#Advert').on('hide.bs.collapse', function() {
$('#Glyp-Advert').removeClass('glyphicon glyphicon-chevron-up').addClass('glyphicon glyphicon-chevron-down');
});
</script>
You don't necessarily need Javascript. You can do this with a few CSS styles. Here's how I've done it.
Make sure all your panel-title a links have this class: accordion-toggle
Add this CSS to your style sheet:
.
/* symbol for open panels */
.panel-heading .accordion-toggle:after {
font-family: 'FontAwesome';
content: "\f068";
float: right;
color: #474747;
}
/* symbol for closed panels */
.panel-heading .accordion-toggle.collapsed:after {
content: "\f067";
}
Note, I've used FontAwesome here, but you can change the font and characters to whatever you need, such as up and down chevrons.

JQuery add class dynamically to first element with a particular class

I have dynamically created bootstrap accordions containing dynamically created groups in each. I want to add the in class to the first group in each accordion, which opens it as you can see in the linked bootstrap example.
<div class="panel panel-default">
<div class="panel-heading">
<h6 class="panel-title">
<a class="accordionToggle" data-toggle="collapse" data-parent="#dynamicId" href="#dynamicId">
Title
</a>
</h6>
</div>
<div class="panel-collapse collapse" id="dynamicId">
...
</div>
</div>
...
There can be any number of .panel.panel-default which can contain any number of .panel-collapse.collapse
Here is what I have tried, as well as some other variations, to add the in class to the first .panel-collapse.collapse of each .panel.panel-default but I keep ending up with it adding the class to each one and not just the first.
$(".panel.panel-default").each(function (index) {
$(this).children(".panel-collapse.collapse:first").addClass("in");
});
$(".panel.panel-default").each(function (index) {
$(this).find(".panel-collapse.collapse:first").addClass("in");
});
$(".panel.panel-default").each(function (index) {
$(this).children(".panel-collapse.collapse").first().addClass("in");
});
Any help will be appreciated!
You need to iterate the panel-group, because I think what you are trying to do is to expand the first item in each accordion
$(".panel-group").each(function (index) {
$(this).children(".panel-collapse.collapse:first").addClass("in");
});
Demo: Fiddle
Simply add this:
$(document).ready(function(){
$(".panel-collapse.collapse:first").addClass("in");
});
It works for me.

Bootstrap Toggle text change on multiple elements

Hello i have the following issue while using a bootstrap toggle.
Code as follow
(I copied the wrong section of HTML code so i edited the question this is the actual code wich is being applied to toggle)
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title active">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">Electronics <span class="more">+</span></a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Item 1 (2)</li>
<li>Item 2 (1)</li>
<li>Item 3 (3)</li>
</ul>
</div>
</div>
</div><!-- panel 1-->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">Cartridges <span class="more">+</span></a>
</h4>
</div>
<div id="collapseTwo" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Item 1 (2)</li>
<li>Item 2 (1)</li>
<li>Item 3 (3)</li>
</ul>
</div>
</div>
</div><!-- panel 2-->
</div><!-- panel group -->
And this is what i'm using to replace the text
$('.more').click(function(){
$(this).text(function(i,old){
return old=='+' ? '-' : '+';
});
});
So i wanted to change the text of div class=more to minus(-) when the element it's clicked
on this thread i found the answer Twitter bootstrap collapse: change display of toggle button
However as i have multiple items, when i click on one of them, the sign changes to (-) that works flawlessly, but if i click on another "item" the first one collapses but the sign remains (-) instead of changing to (+)
How can i do it? i know it's a simple question and maybe a simple answer but i'm kinda stuck in here.
Thanks for your help
In my opinion you should be hooking in to the native Bootstrap events :
$('.dropdown').on({
'show.bs.dropdown': function () {
var l = $('.more', this).html('-')
$('.more').not(l).html('+')
},
'hidden.bs.dropdown': function () {
$('.more', this).html('+')
}
});
FIDDLE
Along with updating current more element, you need to update all other more elements to +
var $mores = $('.more').click(function () {
$(this).text(function (i, old) {
return old == '+' ? '-' : '+';
});
//update all other more text to -
$mores.not(this).text('+');
});
Demo: Fiddle
Try:
$('.more').click(function(){
var txt = $(this).text();
if(txt == "+"){
$('.more').text("+");
$(this).text("-");
}
else{
$(this).text("+");
}
});
DEMO here.

Categories

Resources