在这里,我使用 iframe 来显示页中页面,其中包含基于 Gridstack 网格的编辑器来重新定位其元素。内页应该由纯 HTML 和 CSS 组成。所有与 gridstack 相关的 CSS 和任何与 ko 相关的 JS 调用都应该从外部页面进行。我在一个页面上工作。
现在的问题是,只要我将Gridstack网格放入iframe并将其绑定到视图模型。它的大小不合适。小部件存在于 HTML中,但不可见(由于零高度)
在这种情况下,Knockout 绑定被执行,但CSS 高度属性和垂直 Y 位置无法动态计算。
注意:宽度和水平 X 位置得到正确分配,因为它们是从静态 CSS 类加载的。
更新:可能要解决这个问题,需要覆盖 Gridstack 中的这个函数。它在外部页面而不是内部页面中动态创建 CSS。这可能是问题的原因:
createStylesheet: function(id) {
var style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.setAttribute('data-gs-style-id', id);
if (style.styleSheet) {
style.styleSheet.cssText = '';
} else {
style.appendChild(document.createTextNode(''));
}
document.getElementsByTagName('head')[0].appendChild(style);//POSSIBLE CAUSE OF THE PROBLEM
return style.sheet;
},
//WORKAROUND TO SKIP THE SAME-ORIGIN POLICY
$('#editor-iframe').load(function() {
$(function() {
$('#editor-iframe').contents().find('html').html('<head><title></title><style type="text/css">.grid-stack { background: lightgoldenrodyellow; } .grid-stack-item-content { color: #2c3e50; text-align: center; background-color: #18bc9c; } </style><link rel="stylesheet" href="https://rawgit.com/troolee/gridstack.js/master/dist/gridstack.css" /></head><body><div class="grid-stack" data-bind="gridstack: widgets"><div class="grid-stack-item" data-bind="attr: {\'data-gs-x\': $data.x, \'data-gs-y\': $data.y, \'data-gs-width\': $data.width, \'data-gs-height\': $data.height, \'data-gs-auto-position\': $data.auto_position}"><div class="grid-stack-item-content"><button data-bind="click: $parent.deleteWidget">Delete me</button></div></div></div></body>');
//THE ACTUAL CODE
ko.bindingHandlers.gridstack = {
init: function(element, valueAccessor, allBindingsAccessor, data, context) {
ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, data, context);
return {
controlsDescendantBindings: true
};
},
update: function(element, valueAccessor, allBindingsAccessor, data, context) {
var widgets = valueAccessor(),
grid = $(element).gridstack().data('gridstack'),
afterAddWidget = function(items) {
var item = _.find(items, function(i) {
return i.nodeType === 1;
});
grid.addWidget(item);
ko.utils.domNodeDisposal.addDisposeCallback(item, function() {
grid.removeWidget(item);
});
//RESIZE IFRAME TO FIT NEW CONTENT
var iframeWin = document.getElementById('editor-iframe').contentWindow;
$('#editor-iframe')
.height(Math
.max(
iframeWin.document.body.scrollHeight, iframeWin.document.body.offsetHeight,
iframeWin.document.documentElement.clientHeight,
iframeWin.document.documentElement.scrollHeight,
iframeWin.document.documentElement.offsetHeight) + 'px');
},
newVA = function() {
return {
data: widgets,
afterRender: afterAddWidget
};
};
ko.bindingHandlers.foreach.update(element, newVA, allBindingsAccessor, data, context);
}
};
var Controller = function(widgets) {
var self = this;
this.widgets = ko.observableArray(widgets);
this.addNewWidget = function() {
this.widgets.push({
x: 0,
y: 0,
width: Math.floor(1 + 3 * Math.random()),
height: Math.floor(1 + 3 * Math.random()),
auto_position: true
});
return false;
};
this.deleteWidget = function(item) {
self.widgets.remove(item);
return false;
};
};
var widgets = [{
x: 0,
y: 0,
width: 2,
height: 2
}, {
x: 2,
y: 0,
width: 4,
height: 2
}, {
x: 6,
y: 0,
width: 2,
height: 4
}, {
x: 1,
y: 2,
width: 4,
height: 2
}];
var controller = new Controller(widgets);
ko
.applyBindings(
controller,
document
.getElementById('editor-iframe').contentWindow.document.body);
});
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui.js" type="text/javascript"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-debug.js" type="text/javascript"></script>
<script type="text/javascript" src="https://rawgit.com/troolee/gridstack.js/master/dist/gridstack.js"></script>
<iframe id="editor-iframe" src="http://stacksnippets.net" sandbox="allow-same-origin" style="width:100%"></iframe>