如何在 display:none 时使用 jQuery 对元素进行操作
How to operate on element using jQuery whilst it is display:none
场景
我有一个仪表板,其中一些小部件分组到用户可以单击的选项卡中。小部件有一个默认的起始高度,当它们包含的内容(图表、图形、表格等)呈现时,它们的高度会更新。
我目前仅在页面加载时更新活动选项卡中的小部件高度,然后当用户单击其他选项卡时更新这些小部件。
问题
我必须使用 setTimeout
来确保活动选项卡在更新高度之前可见,这意味着小部件在单击后会立即向下滑动,而不是立即出现在最佳高度。
问题
- 有没有办法在加载时更新所有小部件的高度,甚至是隐藏在其他选项卡上的
display:none
?
我尝试使用 :visible
和 :hidden
选择器,但没有用。
- 我是否应该坚持目前的性能方法,因为最终可能会在许多选项卡中出现许多小部件?如果是这样,是否可以在没有
setTimeout
的情况下完成,因为我只是猜测 200 毫秒的延迟就足够了。
剥离示例
下面的例子加上Codepen.
$(document).foundation();
$(function () {
var options = {
cellHeight: 40,
verticalMargin: 28,
animate: true,
};
widgetsInit = function(options) {
var targetPanel = '.tabs-panel.is-active';
setTimeout(function(){
$(targetPanel + ' .grid-stack').gridstack(options);
$(targetPanel + ' .grid-stack .grid-stack-item').each(function(i){
$(targetPanel + ' .grid-stack').data('gridstack').resize(
$(targetPanel + ' .grid-stack .grid-stack-item')[i],
$($(targetPanel + ' .grid-stack .grid-stack-item')[i]).attr('data-gs-width'),
Math.ceil(($(targetPanel + ' .grid-stack .grid-stack-item .grid-stack-item-content')[i].scrollHeight + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin) / ($(targetPanel + ' .grid-stack').data('gridstack').cellHeight() + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin))
);
});
}, 200);
}
widgetsInit(options);
$('.tabs-title').on('click', function(e) {
widgetsInit(options);
})
});
.grid-stack > .grid-stack-item > .grid-stack-item-content {
background-color: #fff;
cursor: move;
border: 1px solid #e3e3e3;
border-radius: 4px;
padding: 1rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.jQueryUI.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>
<!-- Tabs start -->
<ul class="tabs dashboard-tabs" data-tabs id="example-tabs" data-deep-link="true" data-update-history="true" data-match-height="false">
<li class="tabs-title is-active"><a href="#panel1" aria-selected="true">Panel 1</a></li>
<li class="tabs-title"><a href="#panel2">Panel 2</a></li>
</ul>
<!-- Tabs end -->
<!-- Panels start -->
<div class="tabs-content unstyled" data-tabs-content="example-tabs">
<!-- Panel 1 start -->
<div class="tabs-panel is-active" id="panel1">
<div class="grid-stack">
<div class="grid-stack-item" data-custom-id="0" data-gs-x="0" data-gs-y="0" data-gs-width="4">
<div class="grid-stack-item-content">
#0<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/VUuBJ0ietME" frameborder="0"></iframe>
</div>
</div>
<div class="grid-stack-item" data-custom-id="1" data-gs-x="4" data-gs-y="0" data-gs-width="4">
<div class="grid-stack-item-content">
#1
</div>
</div>
<div class="grid-stack-item" data-custom-id="2" data-gs-x="8" data-gs-y="0" data-gs-width="4">
<div class="grid-stack-item-content">#2</div>
</div>
<div class="grid-stack-item" data-custom-id="3" data-gs-x="0" data-gs-y="1" data-gs-width="8">
<div class="grid-stack-item-content">#3</div>
</div>
</div>
</div>
<!-- Panel 1 end -->
<!-- Panel 2 start -->
<div class="tabs-panel" id="panel2">
<div class="grid-stack">
<div class="grid-stack-item" data-custom-id="4" data-gs-x="0" data-gs-y="0" data-gs-width="6">
<div class="grid-stack-item-content">
#4<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/a4fv-BtzNmY" frameborder="0"></iframe>
</div>
</div>
<div class="grid-stack-item" data-custom-id="5" data-gs-x="6" data-gs-y="0" data-gs-width="6">
<div class="grid-stack-item-content">#5</div>
</div>
</div>
</div>
<!-- Panel 2 end -->
</div>
<!-- Panels end -->
这里有几件事在起作用。我已经创建了一个关于如何处理它的分支。
https://codepen.io/matthewblewitt/pen/KeybxG
我已经使用基础选项卡 API 而不是点击事件触发了 gridstack 插件,因此您可以删除 setTimeout。
$(document).on('change.zf.tabs', function(e) {
widgetsInit(options);
});
基础选项卡使用 display: none
隐藏了不活动的选项卡,而且 gridstack 插件似乎不太适合 属性。因此,我更改了 CSS 以将不活动的选项卡隐藏在屏幕外,并使用 CSS 不透明度和禁用 gridstack 的动画来淡化它们。
.tabs-panel {
position: absolute;
overflow: hidden;
height: 1px;
width: 1px;
opacity: 0;
transition: 0.75s opacity ease;
display: block;
}
.tabs-panel.is-active {
position: static;
overflow: visible;
width: auto;
height: auto;
opacity: 1;
}
希望对您有所帮助。
场景
我有一个仪表板,其中一些小部件分组到用户可以单击的选项卡中。小部件有一个默认的起始高度,当它们包含的内容(图表、图形、表格等)呈现时,它们的高度会更新。
我目前仅在页面加载时更新活动选项卡中的小部件高度,然后当用户单击其他选项卡时更新这些小部件。
问题
我必须使用 setTimeout
来确保活动选项卡在更新高度之前可见,这意味着小部件在单击后会立即向下滑动,而不是立即出现在最佳高度。
问题
- 有没有办法在加载时更新所有小部件的高度,甚至是隐藏在其他选项卡上的
display:none
?
我尝试使用 :visible
和 :hidden
选择器,但没有用。
- 我是否应该坚持目前的性能方法,因为最终可能会在许多选项卡中出现许多小部件?如果是这样,是否可以在没有
setTimeout
的情况下完成,因为我只是猜测 200 毫秒的延迟就足够了。
剥离示例
下面的例子加上Codepen.
$(document).foundation();
$(function () {
var options = {
cellHeight: 40,
verticalMargin: 28,
animate: true,
};
widgetsInit = function(options) {
var targetPanel = '.tabs-panel.is-active';
setTimeout(function(){
$(targetPanel + ' .grid-stack').gridstack(options);
$(targetPanel + ' .grid-stack .grid-stack-item').each(function(i){
$(targetPanel + ' .grid-stack').data('gridstack').resize(
$(targetPanel + ' .grid-stack .grid-stack-item')[i],
$($(targetPanel + ' .grid-stack .grid-stack-item')[i]).attr('data-gs-width'),
Math.ceil(($(targetPanel + ' .grid-stack .grid-stack-item .grid-stack-item-content')[i].scrollHeight + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin) / ($(targetPanel + ' .grid-stack').data('gridstack').cellHeight() + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin))
);
});
}, 200);
}
widgetsInit(options);
$('.tabs-title').on('click', function(e) {
widgetsInit(options);
})
});
.grid-stack > .grid-stack-item > .grid-stack-item-content {
background-color: #fff;
cursor: move;
border: 1px solid #e3e3e3;
border-radius: 4px;
padding: 1rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.jQueryUI.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>
<!-- Tabs start -->
<ul class="tabs dashboard-tabs" data-tabs id="example-tabs" data-deep-link="true" data-update-history="true" data-match-height="false">
<li class="tabs-title is-active"><a href="#panel1" aria-selected="true">Panel 1</a></li>
<li class="tabs-title"><a href="#panel2">Panel 2</a></li>
</ul>
<!-- Tabs end -->
<!-- Panels start -->
<div class="tabs-content unstyled" data-tabs-content="example-tabs">
<!-- Panel 1 start -->
<div class="tabs-panel is-active" id="panel1">
<div class="grid-stack">
<div class="grid-stack-item" data-custom-id="0" data-gs-x="0" data-gs-y="0" data-gs-width="4">
<div class="grid-stack-item-content">
#0<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/VUuBJ0ietME" frameborder="0"></iframe>
</div>
</div>
<div class="grid-stack-item" data-custom-id="1" data-gs-x="4" data-gs-y="0" data-gs-width="4">
<div class="grid-stack-item-content">
#1
</div>
</div>
<div class="grid-stack-item" data-custom-id="2" data-gs-x="8" data-gs-y="0" data-gs-width="4">
<div class="grid-stack-item-content">#2</div>
</div>
<div class="grid-stack-item" data-custom-id="3" data-gs-x="0" data-gs-y="1" data-gs-width="8">
<div class="grid-stack-item-content">#3</div>
</div>
</div>
</div>
<!-- Panel 1 end -->
<!-- Panel 2 start -->
<div class="tabs-panel" id="panel2">
<div class="grid-stack">
<div class="grid-stack-item" data-custom-id="4" data-gs-x="0" data-gs-y="0" data-gs-width="6">
<div class="grid-stack-item-content">
#4<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/a4fv-BtzNmY" frameborder="0"></iframe>
</div>
</div>
<div class="grid-stack-item" data-custom-id="5" data-gs-x="6" data-gs-y="0" data-gs-width="6">
<div class="grid-stack-item-content">#5</div>
</div>
</div>
</div>
<!-- Panel 2 end -->
</div>
<!-- Panels end -->
这里有几件事在起作用。我已经创建了一个关于如何处理它的分支。 https://codepen.io/matthewblewitt/pen/KeybxG
我已经使用基础选项卡 API 而不是点击事件触发了 gridstack 插件,因此您可以删除 setTimeout。
$(document).on('change.zf.tabs', function(e) {
widgetsInit(options);
});
基础选项卡使用 display: none
隐藏了不活动的选项卡,而且 gridstack 插件似乎不太适合 属性。因此,我更改了 CSS 以将不活动的选项卡隐藏在屏幕外,并使用 CSS 不透明度和禁用 gridstack 的动画来淡化它们。
.tabs-panel {
position: absolute;
overflow: hidden;
height: 1px;
width: 1px;
opacity: 0;
transition: 0.75s opacity ease;
display: block;
}
.tabs-panel.is-active {
position: static;
overflow: visible;
width: auto;
height: auto;
opacity: 1;
}
希望对您有所帮助。