Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
342 views
in Technique[技术] by (71.8m points)

css - Duplicating an element (and its style) with JavaScript

For a JavaScript library I'm implementing, I need to clone an element which has exactly the same applied style than the original one. Although I've gained a rather decent knowledge of JavaScript, as a programming language, while developing it, I'm still a DOM scripting newbie, so any advice about how this can be achieved would be extremely helpful (and it has to be done without using any other JavaScript library).

Thank you very much in advance.

Edit: cloneNode(true) does not clone the computed style of the element. Let's say you have the following HTML:

<body>
  <p id="origin">This is the first paragraph.</p>
  <div id="destination">
    <p>The cloned paragraph is below:</p>
  </div>
</body>

And some style like:

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

If you just clone the element, using something like:

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

Styles are not cloned.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Not only will you need to clone, but you'll probably want to do deep cloning as well.

node.cloneNode(true);

Documentation is here.

If deep is set to false, none of the child nodes are cloned. Any text that the node contains is not cloned either, as it is contained in one or more child Text nodes.

If deep evaluates to true, the whole subtree (including text that may be in child Text nodes) is copied too. For empty nodes (e.g. IMG and INPUT elements) it doesn't matter whether deep is set to true or false but you still have to provide a value.

Edit: OP states that node.cloneNode(true) wasn't copying styles. Here is a simple test that shows the contrary (and the desired effect) using both jQuery and the standard 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)); 

Results are visible here: http://jsbin.com/egice3/

Edit 2

Wish you would have mentioned that before ;) Computed style is completely different. Change your CSS selector or apply that style as a class and you'll have a solution.

Edit 3

Because this problem is a legitimate one that I didn't find any good solutions for, it bothered me enough to come up with the following. It's not particularily graceful, but it gets the job done (tested in FF 3.5 only).

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 s[i] == "string" && s[i] && 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);

See PPK's article entitled Get Styles for more information and some caveats.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...