ace*_*bal 23 javascript css dom
对于我正在实现的JavaScript库,我需要克隆一个与原始元素具有完全相同的应用样式的元素.虽然我已经获得了相当不错的JavaScript知识,作为一种编程语言,在开发它时,我仍然是一个DOM脚本新手,所以任何有关如何实现这一点的建议都会非常有用(并且必须要做到这一点)不使用任何其他JavaScript库).
非常感谢你提前.
编辑:cloneNode(true)
不克隆元素的计算样式.假设您有以下HTML:
<body>
<p id="origin">This is the first paragraph.</p>
<div id="destination">
<p>The cloned paragraph is below:</p>
</div>
</body>
Run Code Online (Sandbox Code Playgroud)
有些风格如:
body > p {
font-size: 1.4em;
font-family: Georgia;
padding: 2em;
background: rgb(165, 177, 33);
color: rgb(66, 52, 49);
}
Run Code Online (Sandbox Code Playgroud)
如果您只是使用以下内容克隆元素:
var element = document.getElementById('origin');
var copy = element.cloneNode(true);
var destination = document.getElementById('destination');
destination.appendChild(copy);
Run Code Online (Sandbox Code Playgroud)
样式未克隆.
Jus*_*son 31
您不仅需要克隆,而且您可能也想要进行深度克隆.
node.cloneNode(true);
Run Code Online (Sandbox Code Playgroud)
文档在这里.
如果deep设置为false,则不会克隆任何子节点.节点包含的任何文本也不会被克隆,因为它包含在一个或多个子Text节点中.
如果深度计算结果为true,则也会复制整个子树(包括可能位于子文本节点中的文本).对于空节点(例如IMG和INPUT元素),无论deep是设置为true还是false都无关紧要,但您仍需提供值.
编辑:OP表示node.cloneNode(true)
不是复制样式.这是一个简单的测试,使用jQuery和标准DOM API显示相反的(和期望的效果):
var node = $("#d1");
// Add some arbitrary styles
node.css("height", "100px");
node.css("border", "1px solid red");
// jQuery clone
$("body").append(node.clone(true));
// Standard DOM clone (use node[0] to get to actual DOM node)
$("body").append(node[0].cloneNode(true));
Run Code Online (Sandbox Code Playgroud)
结果显示在这里:http://jsbin.com/egice3/
希望你之前提到过;)计算风格完全不同.更改CSS选择器或将该样式应用为类,您将获得一个解决方案.
因为这个问题是合法的,我没有找到任何好的解决方案,所以让我感到困扰,想出以下内容.它不是特别优雅,但它完成了工作(仅在FF 3.5中测试).
var realStyle = function(_elem, _style) {
var computedStyle;
if ( typeof _elem.currentStyle != 'undefined' ) {
computedStyle = _elem.currentStyle;
} else {
computedStyle = document.defaultView.getComputedStyle(_elem, null);
}
return _style ? computedStyle[_style] : computedStyle;
};
var copyComputedStyle = function(src, dest) {
var s = realStyle(src);
for ( var i in s ) {
// Do not use `hasOwnProperty`, nothing will get copied
if ( typeof i == "string" && i != "cssText" && !/\d/.test(i) ) {
// The try is for setter only properties
try {
dest.style[i] = s[i];
// `fontSize` comes before `font` If `font` is empty, `fontSize` gets
// overwritten. So make sure to reset this property. (hackyhackhack)
// Other properties may need similar treatment
if ( i == "font" ) {
dest.style.fontSize = s.fontSize;
}
} catch (e) {}
}
}
};
var element = document.getElementById('origin');
var copy = element.cloneNode(true);
var destination = document.getElementById('destination');
destination.appendChild(copy);
copyComputedStyle(element, copy);
Run Code Online (Sandbox Code Playgroud)
有关更多信息和一些注意事项,请参阅PPK的文章" 获取样式".
在研究了整个Web上的几个好的解决方案之后,我决定结合每个方面的所有最佳方面,并提出解决方案。
我将解决方案保留在简单的超快速Javascript中,以便每个人都可以转换为他们本月最新的出色JS风格。
代表来自马尼拉的香草.....
* @problem: Sometimes .cloneNode(true) doesn't copy the styles and your are left
* with everything copied but no styling applied to the clonedNode (it looks plain / ugly). Solution:
*
* @solution: call synchronizeCssStyles to copy styles from source (src) element to
* destination (dest) element.
*
* @author: Luigi D'Amico (www.8bitplatoon.com)
*
*/
function synchronizeCssStyles(src, destination, recursively) {
// if recursively = true, then we assume the src dom structure and destination dom structure are identical (ie: cloneNode was used)
// window.getComputedStyle vs document.defaultView.getComputedStyle
// @TBD: also check for compatibility on IE/Edge
destination.style.cssText = document.defaultView.getComputedStyle(src, "").cssText;
if (recursively) {
var vSrcElements = src.getElementsByTagName("*");
var vDstElements = destination.getElementsByTagName("*");
for (var i = vSrcElements.length; i--;) {
var vSrcElement = vSrcElements[i];
var vDstElement = vDstElements[i];
// console.log(i + " >> " + vSrcElement + " :: " + vDstElement);
vDstElement.style.cssText = document.defaultView.getComputedStyle(vSrcElement, "").cssText;
}
}
}
Run Code Online (Sandbox Code Playgroud)