我有两组元素:
<div class='container container1'>
<div class='colors'>
<div class='blue'></div>
<div class='red'></div>
</div>
<div class='drinks'>
<div class='soda'>coke</div>
<div class='juice'></div>
</div>
</div>
<div class='container container2'>
<div class='cars'>
<div class='sedans'></div>
<div class='vans'></div>
</div>
<div class='drinks'>
<div class='soda'>mountain dew</div>
<div class='coffee'></div>
</div>
</div>
我想将container1粘贴到container2上,以便覆盖任何替换,并且将每个容器的任何唯一内容单独放在一起并放在一起。
结果应为:
<div class='container container-result'>
<div class='colors'>
<div class='blue'></div>
<div class='red'></div>
</div>
<div class='cars'>
<div class='sedans'></div>
<div class='vans'></div>
</div>
<div class='drinks'>
<div class='soda'>coke</div>
<div class='juice'></div>
<div class='coffee'></div>
</div>
</div>
元素可以具有任意层次/深度。最好的方法是什么?
提前致谢。
答案 0 :(得分:1)
由于您的问题被标记为jQuery,因此使用该库的答案稍微短一些:
function copy(from, to) {
from.children().each(function() {
var match = to.children("." + this.className.split(' ').join('.'));
if(match.length) {
if(match.children().length == 0) {
match.replaceWith(this);
} else {
copy($(this), match);
}
} else {
to.append(this);
}
}).end().remove();
from.remove();
}
然后你就这样称呼它:
copy($(".container1"), $(".container2"));
You can give it a try here,结果是:
<div class="container container2">
<div class="cars">
<div class="sedans"></div>
<div class="vans"></div>
</div>
<div class="drinks">
<div class="soda">coke</div>
<div class="coffee"></div>
<div class="juice"></div></div>
<div class="colors">
<div class="blue"></div>
<div class="red"></div>
</div>
</div>
请注意,如果您想要替换,那么类名仍为container2
,只需添加此名称即可在copy()
调用后切换该类:
$(".container2").toggleClass("container2 container-result");
匹配基于元素包含的所有类,因此如果元素具有class="car blue"
并且存在相应的class="blue car"
,则会选择要覆盖的那个。
这不是最有效的路线,因为你在每次迭代时都会在子项上启动选择器引擎,但除非你正在做很多元素,否则它应该非常快。 / p>
答案 1 :(得分:0)
关于独特的合并,我无法帮助你,但如果你的应用程序碰巧是在PHP中,那么你可以使用php的array_merge函数在输出HTML之前合并它们。
ReplaceWith是一个很好的jquery函数来代替“粘贴”,它可能会帮助你解决一半的问题。
答案 2 :(得分:0)
这看起来像你想要的那样:
<div class='container container1'>
<div class='colors'>
<div class='blue'></div>
<div class='red'></div>
</div>
<div class='drinks'>
<div class='soda'>coke</div>
<div class='juice'></div>
</div>
</div>
<div class='container container2'>
<div class='cars'>
<div class='sedans'></div>
<div class='vans'></div>
</div>
<div class='drinks'>
<div class='soda'>mountain dew</div>
<div class='coffee'></div>
</div>
</div>
<div class='container container-result'>
</div>
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
function getContainerArray(containers, level) {
level = level || 0;
var result = [];
for (var i=0; i<containers.length; ++i) {
var el = containers.eq(i);
var obj = { "class": el.attr("class") };
if (level == 0) {
obj.items = getContainerArray(el.children("div"), 1);
} else {
obj.text = el.text();
}
result.push(obj);
}
return result;
}
function mergeContainers(containerArray) {
var result = [];
function indexOfClass(name) {
for (var i = 0; i < result.length; ++i) {
if (result[i]["class"] == name) {
return i;
}
}
return -1;
}
for (var i = 0; i < containerArray.length; ++i) {
var obj = containerArray[i];
var name = obj["class"];
var index = indexOfClass(name);
if (index < 0) {
result.push(obj);
} else if (obj.items != null) {
result[index].items = mergeContainers(new Array().concat(result[index].items, obj.items));
}
}
return result;
}
function getHtml(objArray) {
var result = [];
for (var i = 0; i < objArray.length; ++i) {
var obj = objArray[i];
result.push("<div class=\"", obj["class"], "\">");
if (obj.text != null && obj.text != "") {
result.push(obj.text);
}
if (obj.items != null) {
result.push(getHtml(obj.items));
}
result.push("</div>");
}
return result.join("");
}
var html = getHtml(mergeContainers(getContainerArray($("div.container1>div,div.container2>div"))));
$("div.container-result").append(html);
</script>
答案 3 :(得分:0)
这个答案:
container-result
已经存在,则处理重复的合并。See it in action at jsfiddle.net.
/*--- Get all "container" divs but exclude any "container-result" divs.
*/
var zContainers = $("div.container").not ("div.container-result");
if (zContainers && zContainers.length)
{
//--- Get or create the results div.
var zResultDiv = $("div.container-result");
if (!zResultDiv || !zResultDiv.length)
{
zResultDiv = zContainers.parent ().append ("<div class='container container-result'></div>");
zResultDiv = $("div.container-result");
}
//--- Move the container's contents to the master container, preserving order.
zContainers.each (function () {$(this).children ().appendTo (zResultDiv);} )
//--- Kill the old container(s).
zContainers.remove ();
RecursivelyMergeDivsByClass (zResultDiv);
}
function RecursivelyMergeDivsByClass (jNode)
{
/*--- Get a list of the direct-child div's class names.
Sort and winny out a list of duplicates.
*/
var zDirectChildDivs = jNode.find ("> div");
var aClassList = zDirectChildDivs.map (function () {return this.className;} ).get ();
aClassList.sort ().unshift (0);
for (var J = aClassList.length-1; J > 0; J--)
if (aClassList[J] != aClassList[J-1]) aClassList.splice (J, 1); // Delete items without duplicates.
aClassList.splice (0, 1);
/*--- For any duplicates, copy the contents into the first instance, preserving order.
For exact duplicate nodes, the first (oldest) version is kept and the remaining are discarded.
*/
for (var J = aClassList.length-1; J >= 0; J--)
{
var zDupClasses = zDirectChildDivs.filter ("." + aClassList[J]);
var zFirstDiv = zDupClasses.first ();
zDupClasses = zDupClasses.not (zFirstDiv);
zDupClasses.each (function () {$(this).children ().appendTo (zFirstDiv);} )
zDupClasses.remove ();
RecursivelyMergeDivsByClass (zFirstDiv)
}
}