Search code examples
jquerytwitter-bootstrap-3jquery-cookie

Saving multiple panel's collapsed state using cookies with $.cookie()


I'm trying to determine how I might save a collapsible panel's collapsed state using $.cookie.

This question has been helpful so far, but still missing the end solution.

Any solutions I have found so far have only saved the last rolled down panel so when the page is reloaded the only panel saved is the last one.

What I need is to save all panels that are rolled down rather than just one.

Link to jCookie plugin on Github.

Link to demo on JSFiddle


UPDATE

It has been suggested that LocalStorage is a more appropriate solution to what I am trying to achieve. If you can comment on why and what local storage is that would be much appreciated.


UPDATE 2

because of the suggestion that local storage would be an improvement over using cookies for this problem. The selected answer was based off this. However as mentioned by Robin, there are downsides to using this technique on HTTPS sites.


HTML

<div class="panel panel-default">
    <div data-toggle="collapse" data-target="#panel1" class="panel-heading collapsed">
        <h4 class="panel-title">
            <a> Panel 1 </a>
        </h4>
    </div>
    <div id="panel1" class="panel-collapse collapse">
        <div class="panel-body">
        </div>
    </div>
</div>


<div class="panel panel-default">
    <div data-toggle="collapse" data-target="#panel2" class="panel-heading collapsed">
        <h4 class="panel-title">
            <a> Panel 2 </a>
        </h4>
    </div>
    <div id="panel2" class="panel-collapse collapse">
        <div class="panel-body">
        </div>
    </div>
</div>


<div class="panel panel-default">
    <div data-toggle="collapse" data-target="#panel3" class="panel-heading collapsed">
        <h4 class="panel-title">
            <a> Panel 3 </a>
        </h4>
    </div>
    <div id="panel3" class="panel-collapse collapse">
        <div class="panel-body">
        </div>
    </div>
</div>

jQUERY

$(".panel .panel-collapse").on('shown.bs.collapse', function ()
{
    var active = $(this).attr('id');
    $.cookie('activePanelGroup', active);
});

$(".panel .panel-collapse").on('hidden.bs.collapse', function ()
{
    $.removeCookie('activePanelGroup');
});

var last = $.cookie('activePanelGroup');
if (last != null)
{
    //remove default collapse settings
    $(".panel .panel-collapse").removeClass('in');
    //show the account_last visible group
    $("#" + last).addClass("in");
}

Solution

  • This will create a cookie for every panel when it's shown and remove the cookie when the panel is hidden.

    $(".panel .panel-collapse").on('shown.bs.collapse', function ()
    {
        var active = $(this).attr('id');
        $.cookie(active, "1");
    });
    
    $(".panel .panel-collapse").on('hidden.bs.collapse', function ()
    {
        var active = $(this).attr('id');
        $.removeCookie(active);
    });
    

    So, when loading the document, we check every cookie and expand the panel.

    $(document).ready(function(){
        var panels=$.cookie(); //get all cookies
        for (var panel in panels){ //<-- panel is the name of the cookie
            if ($("#"+panel).hasClass('panel-collapse')) // check if this is a panel
            {
                $("#"+panel).collapse("show");
            }
        }    
    });
    

    USING LOCALSTORAGE

    However, as someone suggested, using localStorage may be a better option. localStorage is great for this.

    $(".panel .panel-collapse").on('shown.bs.collapse', function ()
    {
        var active = $(this).attr('id');
        var panels= localStorage.panels === undefined ? new Array() : JSON.parse(localStorage.panels);
        if ($.inArray(active,panels)==-1) //check that the element is not in the array
            panels.push(active);
        localStorage.panels=JSON.stringify(panels);
    });
    
    $(".panel .panel-collapse").on('hidden.bs.collapse', function ()
    {
        var active = $(this).attr('id');
        var panels= localStorage.panels === undefined ? new Array() : JSON.parse(localStorage.panels);
        var elementIndex=$.inArray(active,panels);
        if (elementIndex!==-1) //check the array
        {
            panels.splice(elementIndex,1); //remove item from array        
        }
        localStorage.panels=JSON.stringify(panels); //save array on localStorage
    });
    

    When you load the page, get the values of localStorage and show the panels.

    $(document).ready(function(){
        var panels=localStorage.panels === undefined ? new Array() : JSON.parse(localStorage.panels); //get all panels
        for (var i in panels){ //<-- panel is the name of the cookie
            if ($("#"+panels[i]).hasClass('panel-collapse')) // check if this is a panel
            {
                $("#"+panels[i]).collapse("show");
            }
        }  
    });
    

    EDIT: See it working: FIDDLE