Bootstrap 4 Sidebar menu to stay open on page reload - javascript

I integrated a menu based on https://www.codeply.com/go/T2mpwMOt60 into a website I'm building. Having used it during the build process there is one feature which I feel it misses.
Ideally I would like to have a menu item stay open when navigating to another page. So, looking at the sample menu, that would mean that if Item 3 was open, it should stay open when the page is reloaded, but close if another menu heading was clicked.
Given that every menu section starts with
<a href="#menu1"
<a href="#menu2"
etc, and when opened, the class changes from
class="list-group-item collapsed"
to
class="list-group-item"
I figured that the current menu state could be written to local storage and then read back in on page load to restore the previous state.
Does anyone know of examples that would point me in the right direction on coding this type of functionality?
I've just tried using the following script to save to localStorage
$(document).ready(function () {
$('a').click(function() {
//store the id of the collapsible element
localStorage.setItem('collapseItem', $(this).attr('href'));
});
var collapseItem = localStorage.getItem('collapseItem');
if (collapseItem) {
$(collapseItem).collapse('show')
}
})
It doesn't reopen the menu, but I suspect that is due to what is getting put into local.storage
As an example, When I first click to open the 'customers' sub menu, it stores #menu5, which is the sub menu I would want to be reopened on reload, but when clicking any of the children inside that menu, the stored data will change to the url of the last clicked link.
Additional note, if I reload the page whilst #menu1, #menu2 etc is stored, then it loads with the menu displaying correctly. So it is purely a case of figuring out how to NOT store anything other than the initial #menu open.

The problem is with the objects you are referencing in the event handler.
$(document).ready(function () {
$('a').click(function() {
//store the id of the collapsible element
localStorage.setItem('collapseItem', $(this).attr('href'));
});
var collapseItem = localStorage.getItem('collapseItem');
if (collapseItem) {
$(collapseItem).collapse('show')
}
})
On line 2, it shows that the function will trigger if an a tag is clicked. Try using something else such as button and use that as the link that opens the menus, rather than using the same tag as the one for the hyperlinks. If you can't get that to work then maybe try adding something like an OnMouseDown attribute to each menu-opening button.
Or try my current solution, which checks for a different attribute before saving. This is one that should work, as long as you give each menu-opening link the name here:
<script>
$(document).ready(function () {
$('a').click(function() {
if($(this).attr('name') == "menubtn"){
//store the id of the collapsible element
localStorage.setItem('collapseItem', $(this).attr('href'));
};
});
var collapseItem = localStorage.getItem('collapseItem');
if (collapseItem) {
$(collapseItem).collapse('show')
}
})
</script>
Test 1
Test 2
I wrote those modifications assuming that $ was already defined in your full project, if not then I'll leave it to you to work on that. Tell me if this works.

The solution I used for this is below.
$(document).ready(function () {
$('a').click(function() {
var menuNumber = $(this).attr('href').slice(0, -1);
//console.log(menuNumber);
if (menuNumber == '#menu') {
localStorage.setItem('collapseItem', $(this).attr('href'));
}
var menuHome = $(this).attr('href').slice(-9, -4);
//console.log(menuHome);
if (menuHome == 'index') {
localStorage.setItem('collapseItem', '');
}
});
var collapseItem = localStorage.getItem('collapseItem');
if (collapseItem) {
$(collapseItem).collapse('show')
}
// Clear local storage on menu close action
$('#sidebar .list-group > div').on('hide.bs.collapse', function () {
localStorage.setItem('collapseItem', '');
})
})
I needed to be able to also clear localStorage if the Home link was clicked to prevent the menu from reopening on the last used submenu.
Also added is a check to clear the localStorage data if the arrow icon on the menu was used to close it.
Although it's unlikely that someone would close the accordion in this way and then refresh the page, I thought it better to be thorough.

Related

Keep scroll position and save toggle after page refresh

A long content sub-page has multiple "read more" buttons done with jquery toggleClass.
When a user click the "read more" button the content is showing and the page gets refreshed. (I need the page-refresh for various reasons).
When the page gets refreshed, of course the content is not unfold anymore.
What I am trying todo is:
Save all unfold / fold toggle content before the page-refresh.
Go to the same scroll position before the page-refresh.
I am not sure what is the best way to keep the information -> Cookies, sessionStorage or localStorage for my case, because the user will usually open more sub-pages with "read more" buttons.
I made a JSFiddle (page refresh is not working on a fiddle).
I'd advise using sessionStorage for this.
First, remove all onclick=refreshPage() from your HTML. You want to keep all JS code inside your JS, and to set all handlers at one place. As a best practice, do not use onclick at all.
Next, create two functions: loadState() and saveState(). You will need to call call loadState() on every page load (refresh), and saveState() everytime a toggle button is clicked.
In your handler for clicks on button, also perform the page refresh.
The entire JS code:
$(window).on('load', function() {
loadState();
});
$('.read-more-toggle').on('click', function() {
$(this).next('.read-more-content').toggleClass('hide');
saveState();
refreshPage();
});
// Fold or unfold each content based on state before refresh
// And go to same scroll position before refresh
function loadState() {
let hidden_states = sessionStorage.getItem('hidden-states');
if (!hidden_states) {
return;
}
hidden_states = hidden_states.split(',');
$('.read-more-content').each(function(i, elem) {
if (hidden_states[i] === 'hide') {
elem.classList.add('hide');
}
else {
elem.classList.remove('hide');
}
});
document.scrollingElement.scrollLeft = sessionStorage.getItem('scroll-x');
document.scrollingElement.scrollTop = sessionStorage.getItem('scroll-y');
}
// Remember fold & unfold states, and scroll positions
function saveState() {
let hidden_states = [];
$('.read-more-content').each(function(i, elem) {
hidden_states.push(elem.classList.contains('hide') ? 'hide' : 'show');
});
sessionStorage.setItem('hidden-states', hidden_states);
sessionStorage.setItem('scroll-x', document.scrollingElement.scrollLeft);
sessionStorage.setItem('scroll-y', document.scrollingElement.scrollTop);
}
function refreshPage() {
window.location.reload();
}
Note: If at all possible, try to avoid a page refresh. Storing view states then recreating them after a refresh feels sub-optimal. In some browsers, it may also result in occasional scroll jump glitches as it repaints the restored states.
Lastly, consider if you really need jQuery for your project. Most functionality can be implemented in vanilla JS.

Bourbon Refills How-To Link To Tabs

I'm using the minimal accordion tabs from the bourbon refills site, http://refills.bourbon.io/ and would like to know how I can link to a specific tab from another page in my site. When the page with the tabs loads the first tab is always displayed.
I'd like to know how to link to the page with tabs from a different page on my site but instead of having the first default tab active have the second or third tab be active. You can see exactly what I'm referring to by visiting http://codepen.io/andrewjcurrie/details/qbqvxo/ and below is the JavaScript that powers the tabs.
$(document).ready(function () {
$('.accordion-tabs-minimal').each(function(index) {
$(this).children('li').first().children('a')
.addClass('is-active').next().addClass('is-open').show();});
$('.accordion-tabs-minimal').on('click', 'li > a.tab-link', function(event) {
if (!$(this).hasClass('is-active')) { event.preventDefault();
var accordionTabs = $(this).closest('.accordion-tabs-minimal');
accordionTabs.find('.is-open').removeClass('is-open').hide();
$(this).next().toggleClass('is-open').toggle();
accordionTabs.find('.is-active').removeClass('is-active');
$(this).addClass('is-active'); } else {
event.preventDefault();}});});
As you can see on the pen, I'm hoping to have the links work with hash tags. I'd like to be able to add #Second_Tab to the base URL and have the second tab become active when that link is accessed. Any tips or suggestions on how best to accomplish this would be greatly appreciated, Thanks!
Andrew.
Three steps to get this to work:
remove is-active from the first tab-link in your HTML
add the necessary IDs to each of your tabs (following your example, I added id="Second_Tab" etc.
update the first JS function as follows:
$('.accordion-tabs-minimal').each(function(index) {
if (window.location.hash) {
var hash = $.trim(window.location.hash);
$(hash).addClass('is-active').next().addClass('is-open').show();
} else {
$(this).children('li').first().children('a').addClass('is-active').next().addClass('is-open').show();
}
});
This first checks if the URL has a hash and, if so, adds the necessary classes to that tab and content and displays them. If no hash is in the URL, it instead does the default behavior of displaying the first tab. You can see my working CodePen here http://codepen.io/angeliquejw/pen/xVqzKV?editors=1000

Off-canvas panel closes when removing element

I am setting up a small shop using simpleCart.js and Bootstrap 3.
For displaying the cart I was hoping to use an off-canvas panel that I have enabled using the Jasny-bootstrap add-on. Everything works fine but when I eliminate elements from the cart the off-canvas panel closes. This way the user his unable to modify content in the cart without having to reopen the panel after each click. How can I keep the panel open until the user chooses to close it?
Here is an FIDDLE demonstrating the issue
From looking at this snippet from (link straight to code) simpleCart.js - line 337-353, am I right in assuming that once you remove an item it reloads the cart and therefore it causes the panel to close? If this is the case, then how would a version of this code look like to fix my problem?
// empty the cart
empty: function () {
// remove each item individually so we see the remove events
var newItems = {};
simpleCart.each(function (item) {
// send a param of true to make sure it doesn't
// update after every removal
// keep the item if the function returns false,
// because we know it has been prevented
// from being removed
if (item.remove(true) === false) {
newItems[item.id()] = item
}
});
sc_items = newItems;
simpleCart.update();
},
Thank you in advance :)
The option autohide controls if the navbar should be closed when a user clicks outside of it. Setting it to false, means it stays open until the user clicks on the 'CLOSE PANEL HERE' link.
See the fiddle
Note that normally the navmenu doesn't close when clicked on a link inside of it. I'm not sure why this is happening in your case.

How can I achieve "jumps" with jquery?

I am developing a website that loads different pages depending on what menu icon a user clicks. A friend and I wrote this javascript function:
function loadPage(targetURL){
$.get( targetURL, function( data ) {
document.getElementById("placeholder").innerHTML=data;
window.scrollTo(0,0);
});
}
And the menu icons are coded like this:
<img src="images/some_icon.png" title="Some Page" onclick="javascript:loadPage('pages/somePage.php')"/>
It works great except if trying to jump to a particular div id. For example,
<img src="images/some_icon.png" title="Some Page" onclick="javascript:loadPage('pages/somePage#someLocationOnPage.php')"/>
Taking out the .scrollTo(0,0) doesn't solve the issue. I put that line in to ensure that the page is scrolled all the way up when changing pages (Otherwise, if you were in the middle of the page and clicked a menu icon, the new page would display in the middle of the page).
What have I missed? How can I get the link to jump to a div id?
The two URL's are not different. The one with the bookmark just gets the same HTML code. Since you are not telling the browser to go to a specific bookmark, it should display the same information. (Unless your server sends different info for that link, of course)
I guess you'd have to manually move the view to the bookmark you want.
function loadPage(targetURL, targetID){
$.get( targetURL, function( data ) {
document.getElementById("placeholder").innerHTML=data;
if(targetID && $("#"+targetID).length != 0){
$(document).scrollTop($("#"+targetID).offset().top);
}
else {
window.scrollTo(0,0);
}
});
}
And then give the ID for the target as another parameter. If that's not possible, you can also search for # in the url and find the ID/ or anchor.
First of all you should keep the window.scrollTo(0,0) in your code to keep the page go to top on every click of menu item.
Secondly if on click of menu icon which is calling
loadPage('pages/somePage#someLocationOnPage.php')
your intentions are to open 'somePage' and scroll to the position where element id is 'someLocationOnPage.php' then you should update your loadPage method to check for the part after '#'.
function loadPage(targetURL){
$.get( targetURL, function( data ) {
document.getElementById("placeholder").innerHTML=data;
window.scrollTo(0,0);
// Grab url part after '#'
var name = targetURL.substr( href.indexOf('#') + 1 ), target = $('a[name='+ name +']'), target2 = $('#' + name);
// Determine of bookmark is available or not
target = (target.length)? target : target2;
// Scroll to the bookmark
$('html,body').animate({
scrollTop: target.offset().top
},400);
});
}

Displaying a <div> at a particular index

I'm developing a comment system using jquery. Actually i'm stuck at the portion of displaying the portion, which displays the form at particular index. Suppose that i've 5 links. If i click on the 4th link, the form should be displayed at the 4th link position. But whenever i click on any of the link position, the form is getting displayed at the first link position. This should display as we see in a commenting system. I don't know if have to get some row position or something like that. A sample code from the jsfiddle has been posted below. If i have 3 links, whenever i click on any link, the form will be displayed at first link. I would like to fix this issue. Please help. Thank You
Here's the jsfiddle link
"http://jsfiddle.net/5UMe9/1/"
(function($) {
$.fn.commentSystem = function() {
//var settings = $.extend({index:ind});
//if(settings.index)
$(this).show();
}
}(jQuery));
$(document).ready( function() {
hideForm();
createLink();
onLinkClick();
});
One way to accomplish your goal is to append the form to the div element that has the currently clicked link. In that case, you could pass in the clicked element, and append your form inside the commentSystem method.
Here's a jsfiddle: http://jsfiddle.net/ZDgx6/1/
JS:
(function($) {
$.fn.commentSystem = function(link) {
$(this).insertAfter(link).show();
}
}(jQuery));
.
.
.
$(".link").click(function(e){
$(".Form").commentSystem(e.currentTarget);
});

Categories

Resources