Bootstrap collapse can't handle too many elements - javascript

I have a bootstrap collapse panel which is loaded with a lot of data from an ajax call.
When the data is loaded in the collapse panel is populated with ~ 2000 dom elements, mainly checkboxes and spans.
I've measured the time for the call and the creation of the dom elements, and it doesn't seem to be a problem. It takes less than a second to load and create the elements using jQuery.
However, when I click to expand collpased panel it causes the site to lag, and it takes a good while for the panel to expand.
Is there any solution to this, or an alternative to the bootstrap collapse panels? Could you expand it and show the elements incrementally as you scroll?
I don't seem to have any problem at all with collapse panels that contain less elements.
<div id="collapse_function" class="panel-collapse collapse">
<div class="panel-body">
<div class="panel-group" id="inner_accordion">
<!-- Checkboxes and spans are loaded here dynamically -->
</div>
</div>
Edit: It seems to be the case that even with disabled animations, the site lags.

you should use the :
$('#collapse_function').on('show.bs.collapse', function() { alert('we Go SHOW'); });
$('#collapse_function').on('hide.bs.collapse', function() { alert('we Go Hide'); });
$('#collapse_function').on('shown.bs.collapse', function() { alert('we ARE SHOWN'); });
$('#collapse_function').on('hidden.bs.collapse', function() { alert('we ARE HIDDEN'); });

Well, it seems like I was appending too many dom elements to the collapse panel.
I solved it by lazily loading the elements when scrolling down in the panel.

Related

Simple jQuery accordion toggle

I am working on a simple accordion with toggle states using jQuery. So far so good, but when I click on a different toggle than the initial one that I've clicked on at the start it toggles itself, leaving the previous one with the opened state.
How can one do some kind of a check-up to see if there is another one opened and toggle its state as well?
Here is a Fiddle. Just mess around with it for a few seconds and you will understand what I mean.
// Accordion init
// Hide accordion content on load
$('.accordion-content').hide();
$('.widget-accordion').find('.accordion-toggle').click(function() {
// State change visuals
$(this).toggleClass('opened');
//Expand or collapse this panel
$(this).next().slideToggle('fast');
//Hide the other panels
$(".accordion-content").not($(this).next()).slideUp('fast');
});
As stated in my comment above, here a working fiddle.
The problem is that when you open one accordion item there is no other opened allowed which means that you have to clear every class which stands for the status open...
Working Fiddle
// Accordion init
// Hide accordion content on load
$('.accordion-content').hide();
$('.widget-accordion').find('.accordion-toggle').click(function() {
$('.accordion-toggle').not(this).each(function(){
$(this).removeClass("opened");
});
// State change visuals
$(this).toggleClass('opened');
//Expand or collapse this panel
$(this).next().slideToggle('fast');
//Hide the other panels
$(".accordion-content").not($(this).next()).slideUp('fast');
});
Use This instead of toggleClass:
// State change visuals
$('.accordion-toggle').removeClass('opened');
$(this).addClass('opened');
Fiddle: https://jsfiddle.net/cndnnww5/5/

Can't toggle class to element

I got problem with my accordion: I want when the panel opens jQuery adds a class expanded to the target(element) which I clicked and when the other panel opens, it removes that class and add it to the other one which opens.
The default bootstrap functionality when I open the accordion panel it removes collapsed class of the a tag and when I close it, it adds it(collapsed class) again, I used this to solve my problem(which I explained it in paragraph above) but I couldn't.
here is the HTML code.
<div class="panel-group" id="accordion">
<div class="panel" >
<div class="panel-heading">
<a data-toggle="collapse" data-parent="#accordion" href="#html">HTML</a>
</div>
<ul id="html" class="panel-collapse collapse">
<li><a class="a_nav" href="#">Tags</a></li>
</ul>
</div>
<div class="panel">
<div class="panel-heading">
<a data-toggle="collapse" data-parent="#accordion" href="#css">CSS</a>
</div>
<ul id="css" class="panel-collapse collapse">
<li><a class="a_nav" href="#">Bootstrap</a></li>
</ul>
</div>
</div>
and here is the jQuery code
$(document).ready(function(){
//add class to panel heading of sidebar for expanding
$("div.panel-heading").click(function (event) {
$target = $(event.target);
$target.addClass("expanded");
if($("div.panel-heading a").hasClass("collapsed")) {
$(this).removeClass("expanded");
//this line is for testing if the if condition even works
$(this).text("ok");
}
});
});
You are trying to get the event target and apply or remove the class to the event target every time.
As some users have said before me, maybe you should let bootstrap handle the accordion functionality.
But I will give a quick try to answer your problem.
You are using:
$("div.panel-heading").click(function (event) { ... });
so you want to execute a function when an div with class panel-heading is clicked.
Inside the function you do:
$target = $(event.target);
To get the target element where the click event was fired.
Now looking at your HTML I can see that .panel-heading divs contain a link as a child.
So event.target, will be the link itself if you click on the link or the .panel-heading div if you click on the div, so depending on where you happen to click, the class is going to be added to/removed from different elements.
This is something to watch. Maybe instead of event.target, you can use $(this) in your event handling function.
Below that, your logic is wrong because let's assume that you addClass("expanded") to the correct element, then this:
$("div.panel-heading a").hasClass("collapsed");
Will look at a collection of elements so even if the first link doesn't have the class, the second link may have it, in which case the if statement will evaluate to true and the class you added before, will be removed from the element on which the event handler is called on.
To fix the issue, I would propose something like (if you don't want to let bootstrap do the work):
$(".panel-heading").click(function () {
var $target = $(this);
//close all panels
$(".panel-heading").removeClass("expanded");
$(".panel-heading a").addClass("collapsed");
//open clicked one
$target.addClass("expanded");
$("a", $target).removeClass("collapsed");
});
For better performance, I would cache the collections of elements used in the event handler in variables so that they don't get recalculated every time a click happens.
I think this should solve your issue:
$('.panel-heading').click(function (event) {
$(this).toggleClass('expanded');
$('.panel-heading a').toggleClass('collapsed');
});
See the docs for toggleClass().

Bootstrap: Using panel heading to collapse panel body

I have a Bootstrap v3 Panel with a panel-heading and panel-body. I want a user to be able to click on the panel-heading and it will collapse/expand the panel-body. I am using Bootstrap's Collapse javascript to do this. Here is my markup:
<div class="panel panel-default group-panel">
<div class="panel-heading" role="button" data-toggle="collapse" data-target="#panel-body-foobar">
Action Button
</div>
<div class="panel-body collapse in" id="panel-body-foobar">
Some content here.
</div>
</div>
This code works fine, clicking on the panel heading will collapse/expand the body. However, notice that I also have a button inside the panel heading. When I click that button, it is collapsing/expanding the panel body. See this jsfiddle if you don't know what I mean.
How can I configure this so that only clicking directly on the panel heading, not any child elements, will trigger the collapsing/expanding?
I believe the solution is to define my own click handler (rather than using the one Bootstrap sets up automaitcally) which ignores clicks on children:
$('.panel-heading[data-toggle^="collapse"]').click(function(){
var target = $(this).attr('data-target');
$(target).collapse('toggle');
}).children().click(function(e) {
e.stopPropagation();
});
Thanks to this answer for helping me figure out how to have a jQuery click handler ignore the clicks on children. Note that due to use of e.stopPropagation();, this does not disable any click handlers on the children themselves.

jQuery Isotope doesn't rearrange properly after items have been dynamically adjusted

I have an isotope layout and everything - sorting and filtering and general display - works great. But I have to make the isotope items expandable on click. I did this via a span class which is hidden via JavaScript on initial page load but can be toggled via click on a different span class <span class='Point'>.
This works to a certain degree: the text is toggable - but the layout doesn't resize on click, despite me including .isotope('layout'). The specific jQuery code looks as follows:
$(".risknotes").hide(); $grid.on( 'click', '.Point', function() {
$(this).parent().find(".risknotes").toggle(2000);
$(this).parent().toggleClass('bigger');
$grid.isotope('layout')
});
Funny thing is: if I click a filter, or a sort button, everything resizes perfectly. Just not on initial load or click. I made a jsfiddle reproducing the problem: http://jsfiddle.net/3t2fk5aq/
Your problem is jquery take a time to finish toggle .ricknotes but isotope relayout instantly.
You can use complete option of .toggle() to handle it like this:
$grid.on('click', '.Point', function() {
$(this)
.parent()
.find(".risknotes")
.toggle({ duration: 200,complete: function(){ $grid.isotope('layout') } });
$(this)
.parent()
.toggleClass('bigger');
});

Remove item in Masonry “Remove Method” by clicking on a button

Overview:
I am using Masonry Cascading grid layout library and adding Masonry Remove Method.
This method allows to click on any part of the item --> remove it--> and rests nicely the layout.
Issue:
I would like to remove an item (<div class="item 1"></div> “pink-box”) only by clicking on a specific area (i.e. button) within the item.
I tried to manipulate the function within the JavaScript file, but was unsuccessful to find a solution to my problem. (I started for the first time to build some website 2month ago, so have very little experience in jS or jQ)
Question:
Do you have any rough idea how I could fix this issue?
Here is a link to jsfiddle to show a brief overview of what I would like to achieve: http://jsfiddle.net/intimur/SfU5T/22/
HTML
<div class="masonry">
<div class="item 1"></div>
<div class="item 2">
<div class="remove-btn"> Click here to remove item </div>
</div>
</div>
JavaScript
// http://masonry.desandro.com/masonry.pkgd.js added as external resource
// added http://rawgithub.com/desandro/classie/master/classie.js
docReady( function() {
var container = document.querySelector('.masonry');
var msnry = new Masonry( container, {
columnWidth: 200
});
eventie.bind( container, 'click', function( event ) {
// don't proceed if item was not clicked on
if ( !classie.has( event.target, 'item' ) ) {
return;
}
// remove clicked element
msnry.remove( event.target );
// layout remaining item elements
msnry.layout();
});
});
I haven't checked yet the classie.js as I don't know if it's really needed to remove the item by clicking the button. Just adjusted your Fiddle with:
$(document).on('click', ".remove-btn", function () {
msnry.remove($(this).parent(".item"));
msnry.layout();
});
If you already have the .remove-btn in the actual DOM, it's not necessary to delegate the click-event to the .remove-button from the $(document), so if this is the case this can be simplified to
$(".remove-btn").click(function () {
msnry.remove($(this).parent(".item"));
msnry.layout();
});
Adjusted Fiddle for this version.

Categories

Resources