Bootstrap + AngularJS + jQuery - Nested panels "collapse" behaviour failing - javascript

I am trying to nest accordion panels which works. However, I want the chevron icon to point down (fa-chevron-down) when the panel-body is collapsed and point right when the panel-body is not collapsed. I wrote a directive to get this effect and it too works.However, when I apply this directive to the nested panel, its working the effect on both the nested and parent panel-heading. What am I doing wrong? Is there a cleaner way to do this?
(function () {
'use strict';
angular
.module('myApp', [])
.directive('bsCollapse', bsCollapse);
function bsCollapse() {
var $ = window.$;
var directive = {
restrict: 'EA',
link: linkFunc,
};
return directive;
function linkFunc(scope, el, attr, ctrl) {
$(el[0])
.on('hide.bs.collapse', function (evt) {
$(evt.currentTarget)
.prev()
.children()
.children()
.removeClass('fa-chevron-down')
.addClass('fa-chevron-right');
})
.on('show.bs.collapse', function (evt) {
$(evt.currentTarget)
.prev()
.children()
.children()
.removeClass('fa-chevron-right')
.addClass('fa-chevron-down');
});
}
}
})();
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
</head>
<body>
<div class="container">
<!-- PARENT PANEL GROUP -->
<div class="panel-group col-sm-6 col-sm-offset-3" id="accordion">
<!-- PARENT PANEL -->
<div class="panel panel-default">
<!-- PARENT PANEL HEADING -->
<div class="panel-heading" data-parent="#accordion" data-target="#collapseOne" data-toggle="collapse" role="button">
<h4 class="panel-title">
PARENT PANEL HEADING
<i class="fa fa-chevron-down fa pull-right"></i>
</h4>
</div>
<!-- PARENT PANEL COLLAPSE BODY -->
<div bs-collapse class="panel-collapse collapse in" id="collapseOne" role="tabpanel">
<div class="panel-body">
<!-- NESTED PANEL GROUP -->
<div class="panel-group" id="accordion2">
<!-- NESTED PANEL -->
<div class="panel panel-default">
<!-- NESTED PANEL HEADING -->
<div class="panel-heading" data-parent="#accordion2" data-target="#nestedCollapseOne" data-toggle="collapse" role="button">
<h4 class="panel-title">
NESTED PANEL HEADING
<i class="fa fa-chevron-down fa pull-right"></i>
</h4>
</div>
<!-- NESTED PANEL COLLAPSE BoDY -->
<div bs-collapse class="panel-collapse collapse in" id="nestedCollapseOne" role="tabpanel">
<div class="panel-body">
NESTED PANEL BODY....
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- JS Assets -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</body>
</html>
I've tried the method mentioned in the answer below. scope, flag and have faced the problem that when quickly opening and closing the panel/accordion, it fails. Please see the sreenshots - they are from the plnkr you've provided. Thanks though.

The icons in both the panels are affected is because the $on event is triggered at the same time in both the elements. I have edited your code and added few lines of code in script and used angularjs' ng-class which is lot easier. Here is a plunker demo . Hope it helps.
scipt.js:
scope.flag1 = true;
scope.flag2=true;
scope.parentDiv = function() {
scope.flag1 = !scope.flag1;
};
scope.nestedDiv = function() {
scope.flag2= !scope.flag2;
};
HTML:
<h4 class="panel-title">
PARENT PANEL HEADING
<i ng-class="{'fa fa-chevron-down': flag1, 'fa fa-chevron-right': !flag1}" class="pull-right"></i>
</h4>
<h4 class="panel-title">
NESTED PANEL HEADING
<i ng-class="{'fa fa-chevron-down': flag2, 'fa fa-chevron-right': !flag2}" class="pull-right"></i>
</h4>

I've found a CSS solution to this. Thankfully, Bootstrap throws in a collapsed class to the panel-heading. From there I can add this style which adds the chevron-right to :before pseudo class.
Also, this doesn't require directive or AngularJS code.
Thank you stackoverflow for reference to this :
Use Font Awesome Icons in CSS
div.panel-heading i {
position: relative;
}
div.panel-heading.collapsed i:before {
content: "\f054";
font-family: FontAwesome;
}
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
</head>
<body>
<div class="container">
<!-- PARENT PANEL GROUP -->
<div class="panel-group col-sm-6 col-sm-offset-3" id="accordion">
<!-- PARENT PANEL -->
<div class="panel panel-default">
<!-- PARENT PANEL HEADING -->
<div class="panel-heading" data-parent="#accordion" data-target="#collapseOne" data-toggle="collapse" role="button">
<h4 class="panel-title">
PARENT PANEL HEADING
<i class="fa fa-chevron-down fa pull-right"></i>
</h4>
</div>
<!-- PARENT PANEL COLLAPSE BODY -->
<div bs-collapse class="panel-collapse collapse in" id="collapseOne" role="tabpanel">
<div class="panel-body">
<!-- NESTED PANEL GROUP -->
<div class="panel-group" id="accordion2">
<!-- NESTED PANEL -->
<div class="panel panel-default">
<!-- NESTED PANEL HEADING -->
<div class="panel-heading" data-parent="#accordion2" data-target="#nestedCollapseOne" data-toggle="collapse" role="button">
<h4 class="panel-title">
NESTED PANEL HEADING
<i class="fa fa-chevron-down fa pull-right"></i>
</h4>
</div>
<!-- NESTED PANEL COLLAPSE BoDY -->
<div bs-collapse class="panel-collapse collapse in" id="nestedCollapseOne" role="tabpanel">
<div class="panel-body">
NESTED PANEL BODY....
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- JS Assets -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
</body>
</html>

Related

jQuery AddClass/RemoveClass/Attr Isn't Working

There is a nearby location on the property listing page. I want to show is collapsed on the page load.
I tried add/removeclass and attr but didn't work.
Theme dynamically removes "in" to collapseFive class + "collapsed" to panel-title class
Original code, not collapsed
<div class="panel-wrapper yelp_wrapper">
<a class="panel-title" id="yelp_details" data-toggle="collapse" data-parent="#yelp_details" href="#collapseFive"><span class="panel-title-arrow"></span>Yakınlarda Neler Var</a>
<div id="collapseFive" class="panel-collapse collapse in">
Original code, collapsed
<div class="panel-wrapper yelp_wrapper">
<a class="panel-title collapsed" id="yelp_details" data-toggle="collapse" data-parent="#yelp_details" href="#collapseFive" aria-expanded="false"><span class="panel-title-arrow"></span>Yakınlarda Neler Var</a>
<div id="collapseFive" class="panel-collapse collapse" aria-expanded="false" style="height: 0px;">
Add class
$(document).ready(function(){
$("#yelp_details").addClass("collapsed");
});
Remove class
$(document).ready(function(){
$("#collapseFive").removeClass("in");
});
Attr
$(document).ready(function(){
$("#collapseFive").attr("class", "panel-collapse collapse");
});
I assume this is a boostrap collapse. If that's right, you need to use:
.collapse('show'): hows a collapsible element.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<div class="panel-wrapper yelp_wrapper">
<a class="panel-title" id="yelp_details" data-toggle="collapse" data-parent="#yelp_details"
href="#collapseFive"><span class="panel-title-arrow"></span>Yakınlarda Neler Var</a>
<script>
$(function () {
$('#collapseFive').collapse('show');
});
</script>
<div id="collapseFive" class="panel-collapse collapse in">
<div class="well">
1
2
3
4
</div>
</div>
</div>

Change panel width when collapse in Bootstrap

I'm trying to change the collapse behavior in bootstrap, but without success.
I want to create a page with small panels (maybe col-md-4 that I named tabs) that changes the width after click, when the panel collapse.
Here is a example first page:
Here is the same page after click in the "tabs":
My current code, can't hide the <div>something here</div> and change the panel's width.
Below is the code for one panel with simple collapse effect.
<section class="col-md-4">
<h3 class="page-header title">Forms</h3>
<div class="panel-group">
<div id="panel-form-1" class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<span class="glyphicon glyphicon-chevron-right"></span><a data-toggle="collapse" href="#panel1"> Panel #1</a>
</h4>
</div>
<div id="panel1" class="panel-collapse collapse">
<div class="panel-body">
<form role="form" id="form1">
<div class="row">
<div class="col-md-6">
<div>Stuff</div>
</div>
</div>
</form>
</div>
<div class="panel-footer">
<span class="glyphicon glyphicon-question-sign"></span>
</div>
</div>
</div>
<!-- Other panels-->
</div>
</section>
<div class="col-md-8 something">Something here</div>
JS (not working. No console errors):
<script type="text/javascript" src="../bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript">
$('.collapse').on('show.bs.collapse', function (e) {
$(this).parent("section").removeClass("col-md-4").addClass("col-md-12");
$(document).find("div.something").hide();
});
</script>
My result page with opened panels is something like (please ignore the glyphicon problems):
I tried to follow the example in this another question here in SO, but I didn't understand it very well.
Is it possible achieve it using bootstrap?
Misc:
Bootstrap 3.3.7
JQuery 3.1.1
Chrome and Firefox

collapse in hide or show do it from js

I write some control unit that switch couple of containers by using "collapse" class from bootstrap like list with anchors that has special for my hidden containers "href" attribute, here is example of two list elements that can describe behaviour:
<div id="my_list">
<ul>
<li class="active">
<a onclick="return false" data-parent="#switch_tables" href="#collapse1">One</a>
</li>
<li>
<a onclick="return false" data-parent="#switch_tables" href="#collapse2">Two</a>
</li>
</div>
Then in html code i use some container:
<div id="switch_tables" class="panel">
<div id="collapse1" class="collapse in"> SOME IN HERE </div>
<div id="collapse2" class="collapse"> SOMETHING ELSE</div>
</div>
So when i use this stuff and first elemet of list is active the first container is shown too because i add "in" class after "collapse" class. When I switch to the other list element, then first container should dissappear and the second one should be shown. Of course I has more list links and more hidden containers than just 2 but it's just an example. The thing that I want to do is to prevent default behaviour and to forbid active elemet to hide by clicking on it.
So I switch the "active" list element by clicking on list items and also show or hide exact container that has same id that the list has, so the containers is linked with list items, this thing is done by js code:
$(function(){
$('ul li a').on('click', function(){
$(this).parent().addClass('active').siblings().removeClass('active');
var to_toggle = $(this).attr('href');
$('.collapse.in').collapse('hide');
$(to_toggle+':not(".in")').collapse('show');
});
});
And now I see when I switch between list items, the containers appear and hide correctly.
When I click on second link, I see how first container is hiding and the second one is appear, and vice versa.
Idea is that if there is open containers, the ones that has "collapse in" class should be closed by js, but how to forbid closing an active container?
For example I click on second link in list, my first container is hiding, second one is appear, I click on second link again and second container dissappear so I dont see anything on screen. but the list item is active.
So the question is how to modify js so only one container can have "collapse in" class at a time, and nothing can remove it until the user will switch it to other container so class "in" will move to other container that is coming from anchor attribute "href" and can't be removed in this place?
If you are using bootstrap , so you can use bootstrap collapse feature for example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Collapse</title>
<link rel="stylesheet" href="../../../dist/css/bootstrap.min.css">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="page-header">
<h1>Collapse <small>Bootstrap Visual Test</small></h1>
</div>
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
Collapsible Group Item #1
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">
Collapse one content
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">
Collapsible Group Item #2
</a>
</h4>
</div>
<div id="collapseTwo" class="panel-collapse collapse">
<div class="panel-body">
Collapse two content
</div>
</div>
</div>
</div>
</div>
<!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script>
<script src="../../collapse.js"></script>
</body>
</html>
So I solve my problem by point from #Zigri2612 but use little different approach:
$(function(){
$('ul li a').on('click', function(){
$(this).parent().addClass('active').siblings().removeClass('active');
var to_toggle = $(this).attr('href');
$("#switch_tables").find('div').each(function(){
if ( ('#'+$(this).attr("id")) != to_toggle )
$(this).filter('.collapse.in').collapse('hide');
});
$(to_toggle+':not(".in")').collapse('show');
});
});
Here is a working example for collapse hide and show. here the plus and minus icons are changing. you can alter it for your need.
$(document).ready(function(){
// Add minus icon for collapse element which is open by default
$(".collapse.show").each(function(){
$(this).prev(".card-header").find(".fa").addClass("fa-minus").removeClass("fa-plus");
});
// Toggle plus minus icon on show hide of collapse element
$(".collapse").on('show.bs.collapse', function(){
$(this).prev(".card-header").find(".fa").removeClass("fa-plus").addClass("fa-minus");
}).on('hide.bs.collapse', function(){
$(this).prev(".card-header").find(".fa").removeClass("fa-minus").addClass("fa-plus");
});
});
.bs-example{
margin: 20px;
}
.accordion .fa{
margin-right: 0.5rem;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<style>
</style>
<div class="bs-example">
<div class="accordion" id="accordionExample">
<div class="card">
<div class="card-header" id="headingOne">
<h2 class="mb-0">
<button type="button" class="btn btn-link" data-toggle="collapse" data-target="#collapseOne"><i class="fa fa-plus"></i> What is HTML?</button>
</h2>
</div>
<div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body">
<p>HTML stands for HyperText Markup Language. HTML is the standard markup language for describing the structure of web pages. Learn more.</p>
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="headingTwo">
<h2 class="mb-0">
<button type="button" class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseTwo"><i class="fa fa-plus"></i> What is Bootstrap?</button>
</h2>
</div>
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo" data-parent="#accordionExample">
<div class="card-body">
<p>Bootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development. It is a collection of CSS and HTML conventions. Learn more.</p>
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="headingThree">
<h2 class="mb-0">
<button type="button" class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseThree"><i class="fa fa-plus"></i> What is CSS?</button>
</h2>
</div>
<div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionExample">
<div class="card-body">
<p>CSS stands for Cascading Style Sheet. CSS allows you to specify various style properties for a given HTML element such as colors, backgrounds, fonts etc. Learn more.</p>
</div>
</div>
</div>
</div>
</div>

how to check if "true or false = expanded area?"

I have the following list in bootstrap
<i class="fa fa-plus rgh-i" data-toggle="collapse" data-target="#field-1"></i>
<i class="fa fa-plus rgh-i" data-toggle="collapse" data-target="#field-2"></i>
<i class="fa fa-plus rgh-i" data-toggle="collapse" data-target="#field-3"></i>
I use bootstrap to toggle a div.
Each element html i has a aria-expanded="true" when I want to show my div and aria-expanded="false" when I want to hide my div.
I want to check if there are already elements that aria-expanded="true"..and whether there next to hide the previous open.
$( "i" ).on( "click", function() {
if(There are elements of that property aria-expanded="true")
{
hide previous item before you open the current one
}else{
//something
}
});
I tried to make an example jsdfiddle but unfortunately we did ... I hope that you have understood what I want to do.
Basically ... I briefly before hiding the previous item to display the next and not be allowed to be open more than one element.
Thanks in advance!
if(this.attr('aria-expanded') === "true"){
// hide previous item before you open the current one
}
You need to use attribute equals selector:
Selects elements that have the specified attribute with a value exactly equal to a certain value
var areaexpandedtrue = $('[aria-expanded=true]');
if(areaexpandedtrue.length){
areaexpandedtrue.hide();
}
you can also get the value first, and then compare.
var value = $('#aria-expanded').val(); // jQuery func.
if (value =='true'){
//do some stuff
}
else{
//do some stuff
}
If you are trying to make accordion in bootstrap then try this.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example of Bootstrap 3 Accordion</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example{
margin: 20px;
}
</style>
</head>
<body>
<div class="bs-example">
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">1. What is HTML?</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">
<p>HTML stands for HyperText Markup Language. HTML is the main markup language for describing the structure of Web pages. Learn more.</p>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo">2. What is Bootstrap?</a>
</h4>
</div>
<div id="collapseTwo" class="panel-collapse collapse">
<div class="panel-body">
<p>Bootstrap is a powerful front-end framework for faster and easier web development. It is a collection of CSS and HTML conventions. Learn more.</p>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseThree">3. What is CSS?</a>
</h4>
</div>
<div id="collapseThree" class="panel-collapse collapse">
<div class="panel-body">
<p>CSS stands for Cascading Style Sheet. CSS allows you to specify various style properties for a given HTML element such as colors, backgrounds, fonts etc. Learn more.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
you can write your code by referencing this.
<i class="test fa fa-plus rgh-i" data-toggle="collapse" aria-expanded="false" data-target="#field-1"></i>
This jquery call returns boolean if aria-expanded is true or false, if you use a jquery onclick you can pass the first parameter as this.
$('.test').attr('aria-expanded');
$( ".test" ).click(function() {
if ($(this).attr('aria-expanded')) {
//your code here
} else {
//your code here
}
});

how to change collapse direction of a panel in bootstrap

I have a well-known basic collapsible panel which its codes mentioned belowed. I changed some properties via css sets like collapse-in and collapse height&width but could not achieve to change collapsing direction. I want to change it towards top opposite to default position. How can I do that? I assure you that I tried several ways but could not solve the issue.
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href="#collapse1">Collapsible panel</a>
</h4>
</div>
<div id="collapse1" class="panel-collapse collapse">
<div class="panel-body">Panel Body</div>
<div class="panel-footer">Panel Footer</div>
</div>
</div>
</div>
Just interchange the positions of .panel-heading and #collapse1.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body>
<div class="panel-group">
<div class="panel panel-default">
<div id="collapse1" class="panel-collapse collapse">
<div class="panel-body">Panel Body</div>
<div class="panel-footer">Panel Footer</div>
</div>
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href="#collapse1">Collapsible panel</a>
</h4>
</div>
</div>
</div>
</body>
</html>

Categories

Resources