在 JQueryUI 和 Knockout 的帮助下,我提出了一个 JavaScript 解决方案。
我意识到我希望所做的任何调整都能在页面刷新时保持不变。一旦状态进入它,像 Knockout 支持的 MVVM 方法似乎是一个不错的选择。这也意味着我可以为相关值订阅 JQueryUI Resizable 事件,并相应地重新计算“编辑器”div 的高度。
导航宽度可以更改,细节高度也可以更改。编辑器 div 高度会相应调整。它也适用于首页加载和窗口大小调整。最后,这些调整在页面刷新后仍然存在(我将它们存储在 cookie 中)。
HTML 和 CSS 已被大大简化。
结果在这个jsFiddle中,也在这里:
HTML
<div id="header">
Header
</div>
<div id="container">
<div id="nav" data-bind="jqResizableWidth: navWidth, jqOptions: { handles: 'e', minWidth: 5 } ">
Navigation
</div>
<div id="main">
<div id="details" data-bind="jqResizableHeight: detailsHeight, jqOptions: { handles: 's', minHeight: 10 }">
Details
</div>
<div id="toolbar">
Button1 Button2 Button3 Button4 Button5 Button6 Button7
</div>
<div id="editor">
<div class="paragraph">
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Etiam quam sapien, volutpat ac iaculis ut, malesuada quis massa. Quisque quis risus eu tellus mattis sagittis vulputate at nisl. Donec at nibh non neque facilisis adipiscing. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec at condimentum est. Fusce gravida diam vel odio venenatis vitae cursus lorem cursus. Ut tristique, libero quis scelerisque semper, arcu velit faucibus dui, eu imperdiet nisl arcu id enim. Nullam eget placerat risus.
</div>
<div class="paragraph">
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Etiam quam sapien, volutpat ac iaculis ut, malesuada quis massa. Quisque quis risus eu tellus mattis sagittis vulputate at nisl. Donec at nibh non neque facilisis adipiscing. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec at condimentum est. Fusce gravida diam vel odio venenatis vitae cursus lorem cursus. Ut tristique, libero quis scelerisque semper, arcu velit faucibus dui, eu imperdiet nisl arcu id enim. Nullam eget placerat risus.
</div>
<div class="paragraph">
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Etiam quam sapien, volutpat ac iaculis ut, malesuada quis massa. Quisque quis risus eu tellus mattis sagittis vulputate at nisl. Donec at nibh non neque facilisis adipiscing. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec at condimentum est. Fusce gravida diam vel odio venenatis vitae cursus lorem cursus. Ut tristique, libero quis scelerisque semper, arcu velit faucibus dui, eu imperdiet nisl arcu id enim. Nullam eget placerat risus.
</div>
<div class="paragraph">
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Etiam quam sapien, volutpat ac iaculis ut, malesuada quis massa. Quisque quis risus eu tellus mattis sagittis vulputate at nisl. Donec at nibh non neque facilisis adipiscing. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec at condimentum est. Fusce gravida diam vel odio venenatis vitae cursus lorem cursus. Ut tristique, libero quis scelerisque semper, arcu velit faucibus dui, eu imperdiet nisl arcu id enim. Nullam eget placerat risus.
</div>
<div class="paragraph">
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Etiam quam sapien, volutpat ac iaculis ut, malesuada quis massa. Quisque quis risus eu tellus mattis sagittis vulputate at nisl. Donec at nibh non neque facilisis adipiscing. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec at condimentum est. Fusce gravida diam vel odio venenatis vitae cursus lorem cursus. Ut tristique, libero quis scelerisque semper, arcu velit faucibus dui, eu imperdiet nisl arcu id enim. Nullam eget placerat risus.
</div>
</div>
</div>
</div>
<div id="footer">
Footer
</div>
CSS
#header{
position: fixed;
top: 0px;
height: 30px;
}
#footer{
position: fixed;
bottom: 0px;
height: 30px;
}
#container{
position:fixed;
top:30px;
bottom:30px;
left:0;
right:0;
overflow:hidden;
z-index:-1;
background-color: #dddddd;
}
#nav
{
display: table-cell;
background-color: #ccffff;
}
#nav .ui-resizable-e {
background: #cccccc;
width:5px;
height: 100%;
}
#main
{
display: table-cell;
background-color: #ffffcc;
}
#details
{
padding-left: 5px;
background-color: #faccfa;
width: 100%;
}
#details .ui-resizable-s {
background: #cccccc;
width:100%;
height: 5px;
}
#toolbar
{
padding-top: 5px;
padding-left: 5px;
}
#editor
{
padding-left: 5px;
background-color: #fddfaf;
overflow-y: scroll;
}
.paragraph
{
min-height: 150px;
}
JavaScript
ko.bindingHandlers.jqResizableWidth = {
init: function(element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).width(value);
var options = allBindingsAccessor().jqOptions || {};
$(element).resizable(options);
ko.utils.registerEventHandler(element, "resize", function(event, ui) {
var observable = valueAccessor();
var value = ui.size.width;
observable(value);
// Have to include the next line because otherwise JQueryUI Resizable
// fixes the height to the currently resolved height.
$(element).height('100%');
});
}
};
function adjustEditor() {
// Extra 5px added because of 5px
var height = $(window).height() - $('#header').height() - $('#details').height() - $('#toolbar').height() - $('#details .ui-resizable-s').height() - $('#footer').height();
$('#editor').height(height);
}
ko.bindingHandlers.jqResizableHeight = {
init: function(element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).height(value);
var options = allBindingsAccessor().jqOptions || {};
$(element).resizable(options);
ko.utils.registerEventHandler(element, "resize", function(event, ui) {
var observable = valueAccessor();
var value = ui.size.height;
observable(value);
// Have to include the next line because otherwise JQueryUI Resizable
// fixes the width to the currently resolved width.
$(element).width('100%');
});
}
};
var viewModel = function(navWidth, detailsHeight) {
var self = this;
self.navWidth = ko.observable(navWidth);
self.detailsHeight = ko.observable(detailsHeight);
self.navWidth.subscribe(function(newValue) {
$.cookie('navWidth', newValue, {
expires: 7,
path: '/'
});
adjustEditor();
});
self.detailsHeight.subscribe(function(newValue) {
$.cookie('detailsHeight', newValue, {
expires: 7,
path: '/'
});
adjustEditor();
});
};
var navWidth = $.cookie('navWidth') || 80;
var detailsHeight = $.cookie('detailsHeight') || 50;
ko.applyBindings(new viewModel(navWidth, detailsHeight));
$(window).resize(function() {adjustEditor();});
$(window).resize();