在当前项目中,我需要能够使用jQuery动态添加多级可排序嵌套列表。我有嵌套的可排序列表按预期工作但我遇到的问题是,父母的下一个兄弟姐妹在视觉上重叠了以前父母兄弟姐妹的后代,如this fiddle所示
视觉上我需要每个列表项不与其兄弟姐妹的任何后代重叠,所以我的想法是我需要根据后代元素的累积高度设置高度/边距 - 底部。
我唯一可以尝试分类的工作是:
function resizeHeight(){
var setToChildrenHeights = function(){
var height = $(this).height();
$(this).children().each(function(){
height += $(this).outerHeight();
});
$(this).css('margin-bottom',height);
}
$("li").each(setToChildrenHeights);
}
问题在于,当我有3个级别的嵌套列表时,它不起作用(即父母被推出直接孩子的方式,但不会挡住孩子们的孩子。
作为参考,我使用的谷歌搜索子集是:
除了搜索jQuery api文档之外,到目前为止我还没有找到解决方案,我希望另一组眼睛能够指出我的错误。任何帮助表示赞赏。
更新: 我有幸用这个代码(updated fiddle)采取递归方法,但不幸的是现在它设置了太多的利润底部:
function recursiveResize($parentElement){
var numChild = $parentElement.children().length
console.log('number of children = '+numChild);
var parentHeight = $parentElement.height();
if (numChild<1)
return parentHeight;
var height = 0;
$parentElement.children().each(function(){
height += recursiveResize($(this));
});
return parentHeight + height;
}
//try2
function newResizeRecursive(){
var $parentElements = $('li');
$parentElements.each(function(){
var height = $(this).height();
var childrenHeights = recursiveResize($(this));
var newmargin = childrenHeights - height +3
console.log('new margin = '+newmargin);
console.log('before '+$(this).css('margin-bottom'))
$(this).css('margin-bottom', (newmargin>3 ? newmargin: 3))
console.log('after '+$(this).css('margin-bottom'))
});
}
答案 0 :(得分:0)
从我提出的this question开始,我相信我们可以为您重新编写代码。不幸的是,你的小提琴只能让我感到困惑,所以我不会更新它。
每次附加元素时,都应使用此函数返回的maxHeight
调整父元素和父元素的大小:
var heightArray=$('#builder *').map(function(){
return $(this).outerHeight();
}).get();
var maxHeight = Math.max.apply(Math, heightArray);
我认为您应该只需要为父元素的ID转出#builder
。
将来,使用JSfiddle,您应该避免包含无关的信息并保持代码简单。有些原因你可能想用javascript附加按钮,但是在jsfiddle中你会更容易看到你是否只使用了HTML区域。
答案 1 :(得分:0)
好的我有工作fiddle here。 @James G。的建议是一个很好的起点,但事实证明重新调整大小有两个问题:
为了让重新调整大小正常工作,我最终需要找到所有叶子节点然后遍历树,根据其后代的大小重新调整每个祖先的大小,如下所示:
function resize(childId){
//will find all the leafnodes
var $leafnodes = findLeafNodes();
//resize all ancestors of each leafnode
$leafnodes.each(function(){
resizebyID($(this).attr('id'));
});
}
function resizebyID(childId){
console.log('resize id='+childId);
var $child = $('#'+childId);
var $parent = $child.parent();
var $grandparent = $parent.parent();
//traverse each ansestor height in order
$child.parentsUntil('#builder').each(function(){
if ($(this).is('form')){}
else{
var heightsA = $(this).children().map(function(){
return $(this).outerHeight();
}).get();
var heightsum =0;
for(var i=0; i<heightsA.length; i++)
heightsum += heightsA[i];
$(this).css('margin-bottom',heightsum);
console.log('ancestor:'+ $(this).attr('class')
+' height='+heightsum);
}
});
}
function findLeafNodes(){
//try this, from #builder find the deepest child nodes
//and then resize each up the node from there:
function innerMost( root ) {
var $children = $( root ).children();
while ( true ) {
//set uniqueIDs so resize can work
$children.each(function(){
$(this).uniqueId();
})
var $temp = $children.children();
if($temp.length > 0) $children = $temp;
else return $children;
}
}
var $inner = innerMost($('#builder'));
return $inner;
}
我不仅需要在添加元素时重新调整大小,还需要在触发可排序事件时重新调整大小。所以我设置了可排序的对象,以便在触发事件时调用resize():
function getSortableContainer(containerClass) {
var $sortableContainer = $('<ul class="' + containerClass + '"></ul>');
var sortOptions = {
placeholder: "ui-state-highlight",
opacity: 0.5,
connectWith: '.' + containerClass,
change: function (event, ui) {},
stop: function (event, ui) {
console.log("New " + containerClass + " position: " + ui.item.index());
resize(childID);
}
};
$sortableContainer.sortable(sortOptions);
$sortableContainer.disableSelection();
console.log("new " + containerClass + " added");
return $sortableContainer;
}