我正在尝试确定如何使用 $.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");
}
这将为每个面板在显示时创建一个 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
您应该将活动面板保存在数组中并将其存储在 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);
});
}
<!-- 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");
}
}
}
您可以在单个 cookie 中设置设置(即逗号分隔)并在打开-关闭时更新它。
openPanels = $.cookie('activePanelGroup').split(",");
编辑
我同意克里斯的观点。我发现将所有值存储在单个 cookie 中是一个更优雅的解决方案,但是,我们应该记住单个cookie 大小限制。 (这因浏览器而异)。
您只需在本地存储上为与其 ID 关联的每个面板创建一个变量,用于存储面板的状态。
加载页面时,只需循环所有面板类对象,检查其在本地存储中的关联变量,并根据值应用适当的类。