jQuery Cookies: Remember Sate of Bootstrap Panel Heading - javascript

I would like to use jQuery Cookies to retain the state of my Bootstrap accordion. So far, this code is working well, but it only retains the state of the .panel .panel-collapse element.
jQuery(document).ready(function () {
//when a group is shown, save it as the active accordion group
jQuery("#checkout-accordion").on('shown.bs.collapse', function () {
var active = jQuery("#checkout-accordion .in").attr('id');
jQuery.cookie('activeAccordionGroup2', active);
// alert(active);
});
jQuery("#checkout-accordion").on('hidden.bs.collapse', function () {
jQuery.removeCookie('activeAccordionGroup2');
});
var last = jQuery.cookie('activeAccordionGroup2');
if (last != null) {
//remove default collapse settings
jQuery("#checkout-accordion .panel-collapse").removeClass('in');
//show the account_last visible group
jQuery("#" + last).addClass("in");
}
});
I would need another piece of code that sets the cookie for the .panel-heading element. It should remember class collapsed when the accordion panel is collapsed, and remove class collapsed when it's toggled/active.
There's also this code, which works well too, but only for the .panel .panel-collapse element, and not for .panel-heading also.
jQuery(document).ready(function() {
var lastState = localStorage.getItem('lastState');
if (!lastState) {
lastState = [];
localStorage.setItem('lastState', JSON.stringify(lastState));
} else {
lastStateArray = JSON.parse(lastState);
var arrayLength = lastStateArray.length;
for (var i = 0; i < arrayLength; i++) {
var panel = '#'+lastStateArray[i];
$(panel).addClass('in');
}
}
jQuery('#checkout-accordion').on('shown.bs.collapse', '.panel-collapse', function() {
lastState = JSON.parse(localStorage.getItem('lastState'));
if ($.inArray($(this).attr('id'), lastState) == -1) {
lastState.push($(this).attr('id'));
};
localStorage.setItem('lastState', JSON.stringify(lastState));
});
jQuery('#checkout-accordion').on('hidden.bs.collapse', '.panel-collapse', function() {
lastState = JSON.parse(localStorage.getItem('lastState'));
lastState.splice( $.inArray($(this).attr('id'), lastState), 1 );
localStorage.setItem('lastState', JSON.stringify(lastState));
});
});
Any ideas?

Related

Multiple accordions simultaneously open. How to open only 1 JQuery accordion at a time

Currently open accordion is not closing when another opens.
This is the code I used, not sure where I got it wrong.
<script>
$(document).ready(function () {
//each accordion has a text entry and a corresponding image
var accordionEntries = document.querySelectorAll('.accordion-entry');
var accordionImages = document.querySelectorAll('.accordion-image');
for ( var i = 0; i < accordionEntries.length; i++ ) {
accordionEntries[i].dataset.target = 'accordion-image-' + i;
accordionImages[i].classList.add('accordion-image-' + i);
}
//toggles accordion open state
$(document).on('click', '.accordion-header', function () {
if ($(this).is(".accordion-open")) return $(this).removeClass("accordion-open");
var parent = $(this).closest('.accordion-entry, .accordion-image');
if(!parent.hasClass('.accordion-open')){
parent.toggleClass('accordion-open');
} else {
$('.accordion-open').removeClass('accordion-open')
}
$('.' + parent.data('target')).toggleClass('accordion-open')
})
})
</script>
Thanks for everyone's help in trying to answer the question, a colleague eventually helped me solve this. Here is the solution with comments for anyone else's benefit.
<script>
$(document).ready(function () {
var accordionEntries = document.querySelectorAll('.accordion-entry');
var accordionImages = document.querySelectorAll('.accordion-image');
for ( var i = 0; i < accordionEntries.length; i++ ) {
accordionEntries[i].dataset.target = 'accordion-image-' + i;
accordionImages[i].classList.add('accordion-image-' + i);
}
$(document).on('click', '.accordion-header', function () {
// close currently opened accordion
// add class to open clicked accordion
var accordionEntry = $(this).closest('.accordion-entry');
var open = 'accordion-open';
/* If the accordion that was clicked is in open state,
* remove all occurrences of the 'accordion-open' class and DO NOTHING
* AFTER.
*/
if (accordionEntry.hasClass('accordion-open')) {
accordionEntry.removeClass(open);
$('.' + open).removeClass(open);
} else {
/* If the accordion that was clicked is NOT in open state,
* remove all occurrences of the 'accordion-open' class and add 'accordion-open' class
*. to the accordion that was clicked.
*/
accordionEntry.removeClass(open);
$('.'+ open).removeClass(open);
accordionEntry.addClass('accordion-open');
$('.'+ accordionEntry.data['target']).addClass(open)
$('.'+ accordionEntry[0].dataset.target).addClass(open)
}
});
});
</script>

Adding code to existing .js to collapse navbar when click outside menu

Currently I use .js for my sticky navbar in Bootstrap 4.1.3 which works as desired. I have tried to insert a function in the script, which makes the navbar bar collapse on mobile phones if you click outside the menu. However, without luck. https://biogenity.com/RC19/index.html
The code I am currently using is:
$(document).ready(function () {
var stickyToggle = function (sticky, stickyWrapper, scrollElement) {
var stickyHeight = sticky.outerHeight();
var stickyTop = stickyWrapper.offset().top;
if (scrollElement.scrollTop() >= stickyTop) {
stickyWrapper.height(stickyHeight);
sticky.addClass("is-sticky");
}
else {
sticky.removeClass("is-sticky");
stickyWrapper.height('auto');
}
};
$('[data-toggle="sticky-onscroll"]').each(function () {
var sticky = $(this);
var stickyWrapper = $('<div>').addClass('sticky-wrapper');
sticky.before(stickyWrapper);
sticky.addClass('sticky');
$(window).on('scroll.sticky-onscroll resize.sticky-onscroll', function () {
stickyToggle(sticky, stickyWrapper, $(this));
});
stickyToggle(sticky, stickyWrapper, $(window));
});
});
I want to be able to implement a similar function as the following. It is not certain that this is the best solution for "collapse when you click outside the menu".
$(document).on('click', function(event){
var $clickedOn = $(event.target),
$collapsableItems = $('.collapse'),
isToggleButton = ($clickedOn.closest('.navbar-toggle').length == 1),
isLink = ($clickedOn.closest('a').length == 1),
isOutsideNavbar = ($clickedOn.parents('.navbar').length == 0);
if( (!isToggleButton && isLink) || isOutsideNavbar ) {
$collapsableItems.each(function(){
$(this).collapse('hide');
});
}
});
Thanks in advance.
Based on your code, try this:
$(document).click(function (event) {
var clickedOn = $(event.target),
isNavbar = clickedOn.hasClass('navbar'),
// Target only nav links not all links
isNavbarLink = clickedOn.closest('.nav-link').length == 1,
navbarCollapse = $('.navbar-collapse'),
isNavbarOpen = navbarCollapse.hasClass('show');
// if its not navbar and navbar is opened
if (!isNavbar && isNavbarOpen) {
// if the user is not cliking on the nav links
if (!isNavbarLink) {
// thes close the navbar
navbarCollapse.collapse('hide');
}
}
});

slideToggle is creating a wobble at the end of an accordion

Creating an accordion - on the slide - the elements underneath the element that is sliding seem to move down a px and then back up, creating a juddering effect.
$(document).ready(function() {
//Promos banners rotation and accordion
$(function(){
var $accordionList = $('.accordion').find('li');
var numberOfItems = $accordionList.length;
var currentItem = 0;
// Set first item to active
$accordionList.eq(currentItem).addClass('active').find('.content').slideToggle(800, function() {});
// Loops through promos
var infiniateLoop = setInterval(function() {
if(currentItem == numberOfItems - 1){
currentItem = 0;
}
else {
currentItem++;
}
// Remove active class, if is has it, and close content
$accordionList.parent().find('li.active').removeClass('active')
.find('.content').slideToggle(800, function() {
});
// Add active class and open content
$accordionList.eq(currentItem).addClass('active').find('.content').slideToggle(800, function() {
});
}, 4000 );
// Click to show promo
$accordionList.on('click', function () {
// Stop rotation
clearInterval(infiniateLoop);
var $accordionHead = $(this);
// Remove active class, if is has it, and close content
if($accordionHead.hasClass('active')) {
// Do nothing
}
else {
$accordionHead.parent().find('li.active').removeClass('active')
.find('.content').slideToggle(800, function() {
});
// Add active class and open content
$accordionHead.addClass('active').find('.content').slideToggle(800, function() {
});
};
});
});
});
Fiddle here demonstrating the problem
I've seen some suggestions that you fix the height of the content div - but the site is responsive so that won't work.
Ya, I've had this problem before to. My favorite fix is to just make my own .slideToggle()
div = $('div');
height = div.height();
width = div.width();
$('div').click( function() {
if ($(this).hasClass('hidden')) {
$(this).animate({height: "0", width: "0"}, 200).hide().addClass('hidden');
} else {
$(this).animate({height: height, width: width}, 200).show().removeClass('hidden');
}
});
You could even wrap it in a prototype function if you wanted to.

jquery - sorting li position when other li expand

wonder if anyone could help me on this:
when my animation expands the <li> to reveal the content, there are jumps and sometimes some places remain empty due to the floating of the <li> elements, it makes sense and it is correct but i was just wondering if i could somehow tell the <li>s to re-order in order to occupy all the available space if any.
(function ($) {
// Get all menu items with IDs starting with "filter-" and loop over them
$(".menu li[id|=filter]").each(function () {
// Get the ID add extract the page class name from it (remove "filter-" from it)
var type = $(this).attr("id").replace("filter-", "");
// Get the items in the "webbies" list with that class name
var items = $(".webbies li[class~=" + type + "]");
// Don't do anything if there aren't any
if (items.length == 0) return;
// Get a list of the other items in the list
var others = $(".webbies li:not([class~=" + type + "])");
// Add a click event to the menu item
$("a", this).click(function (e) {
// Stop the link
e.preventDefault();
// Close open item
if (openItem) {
close(openItem);
}
items.removeClass("inactive").animate({
opacity: 1
});
others.addClass("inactive").animate({
opacity: 0.2
});
});
});
var openItem;
// Opens an item
var open = function (item) {
// Close open item
if (openItem) close(openItem);
$("img", item).first().hide("slow");
item.animate({
width: 350,
height: 370
});
$("div.info", item).show("slow", function () {
$("div.fader", item).animate({
opacity: 1
});
});
// Set open item
openItem = item;
};
// Closes an item
var close = function (item) {
$("div.fader", item).animate({
opacity: 0
}, function () {
$("div.info", item).hide("slow");
item.animate({
width: 150,
height: 90
});
$("img", item).first().show("slow");
});
// Reset open item
openItem = null;
};
$(".webbies li").each(function () {
var item = $(this);
$("div.fader", item).css("opacity", 0);
$("a.showMe", item).click(function (e) {
e.preventDefault();
if (item.hasClass("inactive")) return;
open(item);
});
});
})(jQuery);
Thanks
The first thing I thought of was to use jQuery Masonry and recalculate after resizing with .masonry( 'reloadItems' )
the solution was to use masonry as linked by the previous comments, my final code is this:
jQuery(function(){
jQuery('#container').masonry({
itemSelector: '.box',
columnWidth: 190,
animate: true
});
});
(function ($) {
// Get all menu items with IDs starting with "filter-" and loop over them
$(".menu li[id|=filter]").each(function () {
// Get the ID add extract the page class name from it (remove "filter-" from it)
var type = $(this).attr("id").replace("filter-", "");
// Get the items in the "webbies" list with that class name
var items = $("#container div[class~=" + type + "]");
// Don't do anything if there aren't any
if (items.length == 0) return;
// Get a list of the other items in the list
var others = $("#container div:not([class~=" + type + "])");
// Add a click event to the menu item
$("a", this).click(function (e) {
// Stop the link
e.preventDefault();
// Close open item
if (openItem) {
close(openItem);
}
items.removeClass("inactive").animate({opacity: 1});
others.addClass("inactive").animate({opacity: 0.2});
});
});
var openItem;
// Opens an item
var open = function (item) {
// Close open item
if (openItem) close(openItem);
$("img", item).first().hide("slow");
item.width(340)
item.height(360);
$("div.fader", item).animate({opacity: 1}, function () {
$("#container").masonry('reloadItems', function () {
$("div.info", item).show("slow");
});
});
// Set open item
openItem = item;
};
// Closes an item
var close = function (item) {
$("div.fader", item).animate({opacity: 0});
$("div.info", item).hide("slow");
item.animate({width: 150, height: 100}, function () {
$("img", item).first().show("slow");
$("#container").masonry('reloadItems');
});
// Reset open item
openItem = null;
};
$("#container div.box").each(function () {
var item = $(this);
$("div.fader", item).css("opacity", 0);
$("a.showMe", item).click(function (e) {
e.preventDefault();
if (item.hasClass("inactive")) return;
open(item);
});
});
})(jQuery);

Is there a way to convert this jquery code to javascript?

I'm trying to create a tab menu. And I need this coded in regular javascript, not jquery.
$(document).ready(function() {
//When page loads...
$(".general_info_content").hide(); //Hide all content
$("ul.general_info_tabs li:first").addClass("active").show(); //Activate first tab
$(".general_info_content:first").show(); //Show first tab content
//On Click Event
$("ul.general_info_tabs li").click(function() {
$("ul.general_info_tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".general_info_content").hide(); //Hide all tab content
var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content
$(activeTab).fadeIn(); //Fade in the active ID content
return false;
});
});
The core of what you want to do is below - I'm sure there are a thousand different ways to do each task:
Remove a CSS class from an element:
var classes = document.getElementById([id]).className.split(" ");
for(var i = 0; i < classes.length; i++)
if(classes[i] == removeClass)
classes[i] = "";
document.getElementById([id]).className = classes.join(" ");
Add a CSS class to an element:
document.getElementById([i]).className += " " + addClassName;
Hide an element:
document.getElementById([i]).style.display = "none";
Fade an element:
// not tested, but based on tested/used code
function fade(el, opacity, fadeInTime) {
if (opacity < 100) {
el.style.opacity = opacity / 100;
el.style.filter = "alpha(opacity=" + opacity + ")";
opacity += 5;
setTimeout(function () { fade(el, opacity, fadeInTime); }, fadeInTime / 5);
}
}
To find all elements by CSS and tag name:
var matches = new Array();
var all = document.getElementByTagName(searchTagName);
for(var i = 0; i < all.length; i++){
if(all[i].className.replace(searchClassName, "") != all[i].className) {
matches.push(all[i].className);
}
}
// do something with (i.e., return or process) matches
And for the record, I find it encouraging, not unreasonable, that a person using the jQuery library wants to know how to do get things done with native JS/DOM.
More functions to complement Brian's post. Good luck.
EDIT: As I mentioned I would change the class=general_info_content to id=general_info_content1.
function attach(el, event, fnc) {
//attach event to the element
if (el.addEventListener) {
el.addEventListener(event, fnc, false);
}
else if (document.attachEvent) {
el["on" + event] = fnc; // Don not use attachEvent as it breaks 'this'
}
}
function ready() {
// put all your code within $(function(){}); here.
}
function init() {
attach(document, "readystatechange", function () {
if (document.readyState == "complete") {
ready();
}
});
}

Categories

Resources