Applying bootstrap accordion functionality on the fly - javascript

The non-technical staff at our organisation need to be able to create bootstrap accordions but dont have the skills to create them from scratch. My solution is to allow them to build divs with a class of "accordion-panel" applied and then build the accordion from those divs.
The code I have so far is below but it doesnt apply the actual expand/collapse mechanism. How do I make it work?
<div class="accordion-panel open" id="accordion-panel_open">
<h4>Why did you do that?</h4><p>fasdfqw fasdf asdf asdf</p>
</div>
<div class="accordion-panel" desc="title of this panel" id="accordion-panel">
strong text<h4>No really...Why did you do that?</h4><p><br>dfasd fasdf asdf asdf asdf sadf sdf</p>
</div>
<script>
$(document).ready( function() {
var $code = false;
var $panels = $(".accordion-panel");
if ($panels.length > 0) {
var $panelloc = $panels.last().after('<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">');
var i=1;
$panels.each(function() {
var $this = $(this);
var $heading = $this.find("h4");
var headingtext = $heading.text();
$heading.remove();
var panelcode = '<div class="panel panel-default"><div class="panel-heading" role="tab" id="panel'+i+'"><h4 class="panel-title"><a role="button" data-toggle="collapse" data-parent="#accordion" href="#info'+i+'" aria-expanded="true" aria-controls="info'+i+'">'+headingtext+'</a></h4></div><div id="info'+i+'" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="panel'+i+'"><div class="panel-body">'+$this.text()+'</div></div></div>';
$("#accordion").append(panelcode);
i++;
$this.remove();
});
}
});
</script>

I'd have them structure their code a little differently like this:
<div id="accordian">
<div class="panel open">
<h4 class="title">Why did you do that?</h4>
<div class="content">
<p>fasdfqw fasdf asdf asdf</p>
</div>
</div>
<div class="panel">
<h4 class="title">title of this panel</h4>
<div class="content">
strong text<h4>No really...Why did you do that?</h4>
<p>dfasd fasdf asdf asdf asdf sadf sdf</p>
</div>
</div>
</div>
This is more definitive with what they want to do, and you're not requiring them to put any functional ids in there, other than "accordian".
Here's the script I'd use:
$('#accordian')
.addClass('panel-group');
$('#accordian .panel')
.addClass('panel-default');
$('#accordian h4.title')
.removeClass('title')
.addClass('panel-title')
.each( function(id){
$(this).wrapInner('<a data-toggle="collapse" data-parent="#accordion" href="#ac' + id + '"></a>');
})
.wrap( '<div class="panel-heading"></div>' );
$('#accordian .content')
.removeClass('content')
.addClass('panel-collapse collapse')
.addClass( function(){
return $(this).parent().hasClass('open') ? 'in':'';
})
.each( function(id){
$(this).attr('id', 'ac' + id);
})
.wrapInner('<div class="panel-body"></div>');
Here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/hshqgvk8/

Related

How do I make my accordion collapse when another is open?

I want other accordions to close when one is open. I tried using data-toggles with bootstrap but it didnt help. Here is my complete source code on Github.
<button class="accordion">Bedroom & Living Room</button>
<div class="panel">
<p>Wipe down tables and chairs.<br>
Removing dirt from carpets using high-powered vacuums.<br>
Removing garbage and debris.</p>
</div> <br>
<button class="accordion">Bathroom & Kitchen</button>
<div class="panel">
<p>Wash Dishes<br>
Clean counters<br>
Stove</p>
</div> <br>
<button class="accordion">Extra Services</button>
<div class="panel">
<p>Polished furniture.<br>
Dusting window sills and desk.<br>
Proper removal of dust and careful treatment to blinds and mini blinds.</p>
</div>
<script>
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function(){
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
</script>
As i said Data-toggles didnt work. Please tell me if I am doing anthing wrong. You can try to edit it in my git hub and tell me if it works.
<div id="accordion">
<a data-toggle="collapse" data-parent="#accordion" href="#collapse1"><button class="accordion">Bedroom & Living Room</button></a>
<div id="collapse1" class="panel-collapse collapse in">
<div class="panel">
<p>Wipe down tables and chairs.<br>
Removing dirt from carpets using high-powered vacuums.<br>
Removing garbage and debris.</p>
</div>
</div>
<a data-toggle="collapse" data-parent="#accordion" href="#collapse2"><button class="accordion">Bathroom & Kitchen</button></a>
<div id="collapse2" class="panel-collapse collapse in">
<div class="panel">
<p>Wash Dishes<br>
Clean counters<br>
Stove</p>
</div>
</div>
<a data-toggle="collapse" data-parent="#accordion" href="#collapse3"><button class="accordion">Extra Services</button></a>
<div id="collapse3" class="panel-collapse collapse in">
<div class="panel">
<p>Polished furniture.<br>
Dusting window sills and desk.<br>
Proper removal of dust and careful treatment to blinds and mini blinds.</p>
</div>
</div>
</div>
Since you're using bootstrap you may want to look at using their accordion:
https://www.w3schools.com/bootstrap/tryit.asp?filename=trybs_collapsible_accordion&stacked=h
It does exactly what you want to do.

How to close other panels when another one is opened

I'm newbie in bootstrap and jquery, using the code below to create many bootstrap panels, my problem is that I would like to close the others panels when i click in full size icon of one panel
someone know how can do it?
thank you
<div class="panel panel-primary">
<div class="panel-heading">
<h4 class="panel-title"> Panel Widget Title
<div class="pull-right"> <i class="fa fa-times"></i> <i class="fa fa-minus"></i> </div>
</h4>
</div>
<div class="panel-wrapper collapse in">
<div class="panel-body"> Panel Widget Body </div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h4 class="panel-title"> Panel Widget Title
<div class="pull-right"> <i class="fa fa-times"></i> <i class="fa fa-minus"></i> </div>
</h4>
</div>
<div class="panel-wrapper collapse in">
<div class="panel-body"> Panel Widget Body </div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h4 class="panel-title"> Panel Widget Title
<div class="pull-right"> <i class="fa fa-times"></i> <i class="fa fa-minus"></i> </div>
</h4>
</div>
<div class="panel-wrapper collapse in">
<div class="panel-body"> Panel Widget Body </div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
(function($, window, document){
var panelSelector = '[data-perform="panel-collapse"]';
$(panelSelector).each(function() {
var $this = $(this),
parent = $this.closest('.panel'),
wrapper = parent.find('.panel-wrapper'),
collapseOpts = {toggle: false};
if( ! wrapper.length) {
wrapper =
parent.children('.panel-heading').nextAll()
.wrapAll('<div/>')
.parent()
.addClass('panel-wrapper');
collapseOpts = {};
}
wrapper
.collapse(collapseOpts)
.on('hide.bs.collapse', function() {
$this.children('i').removeClass('fa-minus').addClass('fa-plus');
})
.on('show.bs.collapse', function() {
$this.children('i').removeClass('fa-plus').addClass('fa-minus');
});
});
$(document).on('click', panelSelector, function (e) {
e.preventDefault();
var parent = $(this).closest('.panel');
var wrapper = parent.find('.panel-wrapper');
wrapper.collapse('toggle');
});
}(jQuery, window, document));
(function($, window, document){
var panelSelector = '[data-perform="panel-dismiss"]';
$(document).on('click', panelSelector, function (e) {
e.preventDefault();
var parent = $(this).closest('.panel');
removeElement();
function removeElement() {
var col = parent.parent();
parent.remove();
col.filter(function() {
var el = $(this);
return (el.is('[class*="col-"]') && el.children('*').length === 0);
}).remove();
}
});
}(jQuery, window, document));
});
</script>
JSFIDDLE link
Bootstrap provides collapse.js to do the same.
here is the reference: Bootstrap.
or go to fiddle
you just need to do this:
$('.panel-title a').collapse();
since your question is little vague, I am not clear about your requirement.
please have a look on to this code. I think this might be you a re asking
fiddled here
HTML
//Same as in you code, java script part is not needed
JQUERY
$(document).ready(function () {
$(".panel-heading").click(function () {
$(this).closest(".panel").find(".panel-body").toggleClass("hide");
});
$(".fa.fa-times").click(function(){
$(".panel-body").addClass("hide");
$(this).parent(".panel").find(".panel-body").removeClass("hide");
});
});
EDIT
check updated fiddle

How to set class active to div?

I have this menu in this fiddle and I want to set active div on click:
<div class="account-item">
<div class="account-heading active">
<h4 class="account-title">
2. TRANSACTION_HISTORY
</h4>
</div>
</div>
I have this script but i get selected all divs
function SetActiveDiv()
{
var element = $("a").parent().parent();
if (element.hasClass("active")) {
element.removeClass("active");
} else {
element.addClass("active");
}
}
You need to pass the clicked element reference
1.MY_TICKETS
then
function SetActiveDiv(el) {
var element = $(el).closest('.account-heading');
element.toggleClass("active");
}
Demo: Fiddle
Note: Since you are using jQuery, try to use jQuery event handlers instead of inline handlers
So
1.MY_TICKETS
then
jQuery(function ($) {
$('.account-group .account-title a').click(function () {
var $heading = $(this).closest('.account-heading').toggleClass("active");
$('.account-group .account-heading.active').not($heading).removeClass('active');
})
})
Demo: Fiddle
just make the selector to look like (double class selector):
var element = $(".account-heading.active");
You need to take a look at your code and understand what it is doing. Take the following line:
$("a").parent().parent();
What does this do? It selects every anchor, then selects the parent, then selects the parent of that parent.
Considering you're using jQuery, you can use it to bind the event handler instead of using onClick in your html (which is considering bad practice).
$('a').on('click', function() {
$('.account-heading').removeClass('active');
$(this).parent().parent().addClass('active');
});
jsFiddle: http://fiddle.jshell.net/jxmbj36s/5/
Remove all the functions in html onclick="SetActiveLink('#/*')" and then use this jQuery function so you will not be repetitive:
$(".account-group a").on("click", function(){
$(".account-group a").removeClass("active");
$(this).addClass("active");
});
See the result here:
$(".account-group a").on("click", function(){
$(".account-group a").removeClass("active");
$(this).addClass("active");
});
.active {
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-lg-2 col-md-3 left-sidebar-container">
<div class="left-sidebar">
<div class="account">
<h1>MY_ACCOUNT</h1>
<div class="account-group" id="accordion">
<div class="account-item">
<div class="account-heading">
<h4 class="account-title">
1.MY_TICKETS
</h4>
</div>
</div>
<div class="account-item">
<div class="account-heading">
<h4 class="account-title">
2. TRANSACTION_HISTORY
</h4>
</div>
</div>
<div class="account-item">
<div class="account-heading">
<h4 class="account-title">
3. PAYIN
</h4>
</div>
</div>
<div class="account-item">
<div class="account-heading">
<h4 class="account-title">
4.PAYOUT
</h4>
</div>
</div>
<div class="account-item">
<div class="account-heading active">
<h4 class="account-title has-sub">
<a data-toggle="collapse" data-parent="#accordion" href="#settings">5.SETTINGS</a>
</h4>
</div>
<div id="settings" class="account-collapse collapse in">
<div class="account-body">
PERSONAL_INFORMATION
NOTIFICATIONS
CHANGE_PASSWORD
GAME_SETTINGS
</div>
</div>
</div>
<div class="account-item">
<div class="account-heading">
<h4 class="account-title has-sub">
<a data-toggle="collapse" data-parent="#accordion" href="#promotions">6.PROMOTIONS</a>
</h4>
</div>
<div id="promotions" class="account-collapse collapse">
<div class="account-body">
BONUSES
COMPETITIONS
VOUCHER_REDEEM
</div>
</div>
</div>
<div class="account-item">
<div class="account-heading">
<h4 class="account-title">
7. SYSTEM_MESSAGES
</h4>
</div>
</div>
</div>
</div>
</div>
</div>
I think that the following code will help you to solve this problem
function SetActiveDiv() {
var el = $("a").closest("div.account-heading")[0];
var el = $("a").parent().parent();
if ($(el).hasClass('active')) {
$(el).removeClass('active')
} else {
$(el).addClass('active')
}
}

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.

Collapse in the first if the latest closed

I am taking bootstrap3's collapse tools. http://getbootstrap.com/javascript/#collapse
but I want that if all closed, the first div should open again, so that no spare space will be there if all are closed.
this is what i tried, but this is working only once and for the second time, it is not opening the first. any ideas why?
$(function(){
$('#four').on('click', function () {
var four_class = $('#collapseFour').attr("class");
if(four_class=="panel-collapse in"){
$('#collapseOne').collapse();
}
});
});
my fourth content
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a class="accordion-toggle lead" data-toggle="collapse" data-parent="#accordion" href="#collapseFour" id="four">
Locations eintragen
</a>
</h4>
</div>
<div id="collapseFour" class="panel-collapse collapse">
<div class="panel-body">
fourth content
</div>
</div>
</div>
You need to watch the hidden.bs.collapse event which is broadcast when a panel has closed.
In there you check if the number of panels is equal to the number of closed panels and if so open the first one..
$('#accordion').on('hidden.bs.collapse', function (item) {
// after closing check if any is still open
var self = $(this),
collapsed = self.find('.collapsed'),
all = self.find('.panel-title'),
allClosed = collapsed.length === all.length;
if (allClosed){
setTimeout(function(){
self.find('.panel-collapse').first().collapse('show');
}, 10);
}
})

Categories

Resources