StartBootstrap / startbootstrap-sb-admin-2

A free, open source, Bootstrap admin theme created by Start Bootstrap
https://startbootstrap.com/themes/sb-admin-2/
MIT License
9.78k stars 5.72k forks source link

sidebar returns after closing when the screen is small #296

Open stccorp opened 5 years ago

stccorp commented 5 years ago

I just noticed that if I use a phone or simply resize chrome to look like a phone, the size bar resizes. This is what I expected. The problem is that if I click on the 3 bars to CLOSE the side-bar and then go to the another page, the side bar appears again instead of keeping it close. In PHP I will keep the state of the sidebar on a session but I will think that the template should do that.

Could anyone point me in the right direction of how to fix this?

Thank you

tiesont commented 5 years ago

The key word here is "template" - this project is just meant to be a set of components for building out an application. I'm not sure where demoing "state" management (remembering if the sidebar is collapsed) would fit.

Assuming you really wanted to add something, I'd say that the Storage API makes the most sense, since that's client-side storage (and therefore agnostic of the server technology being used). You'd probably want to write it in TypeScript, since that would make it integrate better with frameworks like React or Angular.

Just my two cents, obviously.

mariodeckers commented 5 years ago

If anybody has played around with this and found a fix that remembers the toggled state, I would very much appreciate if they could share here. (Not much of a developer myself, just using the template to put something simple together.) Thanks!

MostlyChrisJ commented 5 years ago

As we have jQuery available let's use it to get the current class state of the sidebar (toggled or not) and then set a cookie to store its new state.

So...

  1. If the sidebar is maximised (not toggled) then we'll set the cookie to 'off'.
  2. If the sidebar is minimised (toggled) then we'll set the cookie to 'on'.
$(document).ready(function () {

    $('#sidebarToggle').on('click', function () {
        let state = ($('#sidebar').hasClass('toggled')) ? 'off' : 'on';
        document.cookie = 'sidebar=' + state + '; path=/';
    });

});

Then to set the state of the sidebar on every page refresh, we need to get the cookie value and then set the #sidebar class.

Here is an example using PHP:

<ul id="sidebar" class="sidebar navbar-nav <?= setSidebarState() ?>">

setSidebarState() will return a 'toggled' or empty string based on the cookie value that was set above.

function setSidebarState() {

    // Set the initial state to nothing so the sidebar will be shown.
    $setState = '';

    // If the sidebar cookie is present, get its value and set
    // the sidebar state based on the cookie value.
    if (isset($_COOKIE['sidebar'])) {

        $getState = $_COOKIE['sidebar'];

        if ($getState === 'off') {
            $setState = 'toggled';
        }

    }

    return $setState;

}
stccorp commented 5 years ago

Thank you so much for taking the time. Decided to go the js route since I think this is a template functionality and not an application functionality.

Step 1: I changed sb-admin-2.js // Toggle the side navigation $("#sidebarToggle, #sidebarToggleTop").on('click', function(e) { $("body").toggleClass("sidebar-toggled"); $(".sidebar").toggleClass("toggled"); if ($(".sidebar").hasClass("toggled")) { setCookie('sidebar','off',1); $('.sidebar .collapse').collapse('hide'); }else{ setCookie('sidebar','on',1);

};

});

Step2. Added this line

if (getCookie('sidebar') == 'off') $(".sidebar").toggleClass("toggled");

Seems to work. Sometime I see a flicker of the menu moving in and out.

PS: I got set and get coockie from here https://www.w3schools.com/js/js_cookies.asp

tiesont commented 5 years ago

The flicker you're seeing is probably caused by the slight delay which occurs between when the page is rendered and when the JavaScript is run - you'll want this to run as soon as possible, so probably want to move the Step2 code to the <head> of your page, if possible.

Generally speaking, referencing the MDN or similar official API docs tends to offer better results (Mozilla is an actual member of the W3C. Refsnes Data is most certainly not). For instance: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie

That being said, you might have better luck with localStorage, which would work like so:

localStorage.setItem('sidebar', 'on');

and

let sidebarState = localStorage.getItem('sidebar');

If you only want to persist the setting while the browser / tab is open, use sessionStorage:

sessionStorage.setItem('sidebar', 'on');

and

let sidebarState = sessionStorage.getItem('sidebar');

It's not a coincidence that the APIs look similar - the only difference (for you) in how they work is how long they're persisted - see https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API.

mariodeckers commented 5 years ago

Great help guys! So this works now:

  1. Change sb-admin-2.js

    let sidebarState = sessionStorage.getItem('sidebar');
    $(".sidebar").toggleClass(sidebarState);
    
    $("#sidebarToggle, #sidebarToggleTop").on('click', function(e) {
    $("body").toggleClass("sidebar-toggled");
    $(".sidebar").toggleClass("toggled");
    if ($(".sidebar").hasClass("toggled")) {
      sessionStorage.setItem('sidebar', 'toggled');
      $('.sidebar .collapse').collapse('hide');
    } else {
      sessionStorage.setItem('sidebar', '');
    };
    });

    Or as tiesont commented use localStorage instead of sessionStorage if you so wish.

  2. Tell my pages (e.g. index.html) to use sb-admin-2.js and not the minified sb-admin-2.min.js

Thanks a lot!