使用 $.cookie() 的 cookies 保存多个面板的折叠状态

问题描述 投票:0回答:5

我正在尝试确定如何使用 $.cookie 保存可折叠面板的折叠状态。

这个问题到目前为止很有帮助,但仍然缺少最终的解决方案。

到目前为止我发现的任何解决方案都只保存了最后一个滚动的面板,因此当重新加载页面时,唯一保存的面板是最后一个面板。

我需要的是保存所有向下滚动的面板,而不仅仅是一个。

链接到 Github 上的 jCookie 插件。

链接到 JSFiddle 上的演示


更新

有人建议 LocalStorage 是更适合我想要实现的目标的解决方案。如果您能评论为什么以及本地存储是什么,我们将不胜感激。


更新2

因为有人建议本地存储将比使用 cookie 更好地解决这个问题。所选答案就是基于此。然而,正如 Robin 所提到的,在 HTTPS 站点上使用此技术有一些缺点。


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");
}
jquery twitter-bootstrap-3 jquery-cookie
5个回答
27
投票

这将为每个面板在显示时创建一个 cookie,并在面板隐藏时删除 cookie。

$(".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);
});

因此,在加载文档时,我们检查每个 cookie 并展开面板。

$(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");
        }
    }    
});

使用本地存储

但是,正如有人建议的那样,使用

localStorage
可能是更好的选择。
localStorage
非常适合这个。

$(".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
});

加载页面时,获取 localStorage 的值并显示面板。

$(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");
        }
    }  
});

编辑:查看它的工作原理:FIDDLE


3
投票

您应该将活动面板保存在数组中并将其存储在 cookie 中,而不是一次只保存 1 个

id

你的JS应该是这样的:

var activePanels = []; // array for the active panels
$(".panel .panel-collapse").on('shown.bs.collapse', function ()
{   
    var active = $(this).attr('id');
    activePanels.push(active); // store the active panel id into the array
    $.cookie('activePanelGroup', activePanels); // add array to the cookie
    console.log($.cookie('activePanelGroup')); // display current active panels stored in the cookie
});

$(".panel .panel-collapse").on('hidden.bs.collapse', function ()
{
    var selectedPanel = $(this).attr('id');
    var index = activePanels.indexOf(selectedPanel);
    if (index > -1) // if id exists on the active panels array
      activePanels.splice(index, 1); // remove it on the active panels array
    $.cookie('activePanelGroup', activePanels); // add the updated active panels array to remove the old one
    console.log($.cookie('activePanelGroup')); // display current active panels stored in the cookie
});

var aPanels = $.cookie('activePanelGroup');  // retrieve all active panels 

if (aPanels != null)
{   
    //remove default collapse settings
    $(".panel .panel-collapse").removeClass('in');
    // put all active ids to array
    var arr = aPanels.split(",");
    // loop on each active panels
    $.each( arr, function( key, value ) {
      //show the account_last visible group
      $("#" + value).addClass("in");

      // store again the selected panels so it won't get reset on reload
      activePanels.push(value);
      $.cookie('activePanelGroup', activePanels);
    });
}

小提琴


1
投票

<!-- when you have multiple levels of child-sections like this below - to hide/collapse or show and restore again -->
<!--here's how I kept track of their id's - ps. I have since removed the multiple -->
<!--tables but, it looked like this when I put this answer in -->

    <div class="panel-group" id="accordion">
        <div class="panel panel-default">
            <div class="panel-heading">
            </div>
            <div class="panel-body">
<!--TABLE 1-->
                <table class="table table-condensed" style="border-collapse: collapse;">
                    <tbody class="component-grp">
                        <tr data-toggle="collapse" data-parent="#accordion" data-target="#compogrp@x" class="accordion-toggle">
                            <td colspan="10">
                                <div class="">
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <td class="hiddenRow">
                                <div class="accordian-body panel-collapse collapse" id="compogrp@x">
<!--TABLE 2-->
                                    <table class="table table-striped">
                                        <thead>
                                            <tr class="header">
                                                <th></th>
                                                <th>Position</th>
                                                <th>shape</th>

                                            </tr>
                                        </thead>
                                        <tbody class="component-row">
                                            <tr data-toggle="collapse" data-target="#comp-@x" class="accordion-toggle collapsed">
                                                <td>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td colspan="10" class="hiddenRow">                                                
                                                </td>
                                            </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>

        </div>

    </div>

让我提出一个额外的替代方案:如果您像我一样自定义了引导面板示例,并最终为您的手风琴进行了多次嵌套,那么假设您的折叠和展开元素(展开或折叠的面板)有唯一的 id,您可以捕获(依赖)单击事件来获取折叠/展开面板的 id,无论它位于嵌套中有多深。

我定制了 stackoverflow 中的示例来实现此目的;基本上,它在单击事件时获取展开面板的 id,创建一个以 id 作为名称(var temp)的 cookie,如果面板折叠,稍后将使用该 cookie 将其删除。然后在页面刷新(或等)时循环通过cookie来恢复手风琴状态。我必须提到,不建议将 cookie 用于此类规范。因此,您可以更改代码以使用 localStorage 或 Javascript 数组。希望这对某人有帮助。

    $(document).on('shown.bs.collapse', function (e) {
           //whenever and wherever a panel is shown on any level of the  nesting, save the id in a cookie
            var active = $(e.target).attr('id')
           var temp = active;
            $.cookie(temp, active);
            console.log("panel expanded: ");
        });

        $(document).on('hidden.bs.collapse', function (e) {
            var temp = $(e.target).attr('id')
           //whenever and wherever a panel is collapsed on any level of the  nesting, remove the corresponding cookie
            $.removeCookie(temp);
            console.log("panel collapsed: ");

        });

        function restoreActiveAccordionGroup() {
             var last = [];
             last = $.cookie();
            if (last) {

                //remove default collapse settings from all panels
                $("#accordion").removeClass('in');
                for (var i in last) {
                //restore the last visible panel group in all nested levels
                $("#" + i).addClass("in");
                }

            }
        }

1
投票

您可以在单个 cookie 中设置设置(即逗号分隔)并在打开-关闭时更新它。

openPanels = $.cookie('activePanelGroup').split(",");

在此处查看您编辑的 JsFiddle 示例的工作情况。

编辑

我同意克里斯的观点。我发现将所有值存储在单个 cookie 中是一个更优雅的解决方案,但是,我们应该记住单个

cookie 大小限制。 (这因浏览器而异)。


0
投票
我宁愿使用 localStorage 而不是 cookie。

您只需在本地存储上为与其 ID 关联的每个面板创建一个变量,用于存储面板的状态。

加载页面时,只需循环所有面板类对象,检查其在本地存储中的关联变量,并根据值应用适当的类。

© www.soinside.com 2019 - 2024. All rights reserved.