web-dev-qa-db-ja.com

JavaScriptを使用して要素(およびそのスタイル)を複製​​する

私が実装しているJavaScriptライブラリの場合、元のスタイルとまったく同じ適用スタイルを持つ要素を複製するために 1つ必要です。私は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>

そして、次のようなスタイル:

body > p {
  font-size: 1.4em;
  font-family: Georgia;
  padding: 2em;
  background: rgb(165, 177, 33);
  color: rgb(66, 52, 49);
}

次のようなものを使用して、要素のクローンを作成する場合。

var element = document.getElementById('Origin');
var copy = element.cloneNode(true);
var destination = document.getElementById('destination');
destination.appendChild(copy);

スタイルは複製されません。

24
acebal

クローンを作成する必要があるだけでなく、おそらくdeepクローンも作成する必要があります。

_node.cloneNode(true);
_

ドキュメントは ここ です。

deepがfalseに設定されている場合、子ノードは複製されません。ノードに含まれるテキストは、1つ以上の子テキストノードに含まれているため、複製されません。

deepが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)); 
_

結果はここに表示されます: http://jsbin.com/egice3/

編集2

前に言っておけばよかったです;)計算されたスタイルは完全に異なります。 CSSセレクターを変更するか、そのスタイルをクラスとして適用すると、解決策が得られます。

編集3

この問題は私が良い解決策を見つけられなかった正当な問題であるため、次のことを思い付くのに十分気になりました。それは特に優雅ではありませんが、それは仕事を成し遂げます(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);
_

詳細といくつかの注意事項については、PPKの記事 Get Styles を参照してください。

31
Justin Johnson

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;
        }
    }
}
7
Luigi D'Amico