views:

335

answers:

4

I have a page with two frames, and I need to (via javascript) copy an element and all of its nested elements (it's a ul/li tree) and most importantly it's style from one frame to the other.

I get all the content via assigning innerhtml, and I am able to position the new element in the second frame with dest.style.left and dest.style.top and it works. But I'm trying to get all the style information and nothing's happening.

I'm using getComputedStyle to get the final style for each source element as I loop through each node then and assigning them to the same position in the destination nodelist and nothing happens to visually change the style.

What am I missing?

+6  A: 

With getComputedStyle, you can get the cssText property which will fetch the entire computed style in a CSS string:

var completeStyle = window.getComputedStyle(element1, null).cssText;
element2.style.cssText = completeStyle;

Unfortunately, getComputedStyle isn't supported by Internet Explorer, which uses currentStyle instead. Doubly unfortunate is the fact that currentStyle returns null for cssText, so the same method cannot be applied to IE. I'll try and figure something out for you, if nobody beats me to it :-)


I thought about it and you could emulate the above in IE using a for...in statement:

var completeStyle = "";
if ("getComputedStyle" in window)
    completeStyle = window.getComputedStyle(element1, null).cssText;
else
{
    var elStyle = element1.currentStyle;
    for (var k in elStyle) { completeStyle += k + ":" + elStyle[k] + ";"; }
}

element2.style.cssText = completeStyle;
Andy E
trying this now since clone doesn't work for me. getcomputedstyle() requires two params for anybody who's following my travails... will update soon.
stu
I must be going insane. I've spent the whole day banging my head against this and have gotten nowhere. I'm stepping through with firebug and I have a recursive function that follows every nodechild and calls getcomputedstyle and firebug returns a computedCSSStyleDeclaration with 162 keys in it, but no value settings so when I call .cssText I get nothing.But when I look at the elements with firebug, IT can get all the computedstyle information.GAAAAAAAAAHHHHHHH!!!!!!!!!!
stu
Maybe I'm missing something obvious. Does getcomputedstyle() disregard things defined in CSS style tags? That's where all the style that I'm trying to copy from is defined. I'm going to try putting the style in the tags themselves...
stu
Plot update for all of you following along at home. If you put the style="..." information in each tag, and copy innerHTML it copies the style information too. Unfortunately, I don't think my designer will tolerate the requirement that all the style information be in each tag.My next test will be to manually copy the <style> tag. No idea if that will work at all.
stu
@stu: Sorry for not replying sooner, I had a broadband engineer out to my house yesterday. Have you tried any browsers other than Firefox? It could be an isolated issue and for Firefox you may have to loop through the style properties just like in IE. Also, `getComputedStyle` requires only one parameter, the second is entirely optional and should be `null` for regular elements.
Andy E
Inneresting. Firebug choked on it when I only put one param, and I got a notenoughparams exception or something like that.Anyway, I went the other route (see my answer below) and that works in IE and FF (and hopefully others as well) and it's a lot simpler than me iterating through the node tree. Less cool, but at this point, I just need it to work.
stu
@stu: I was revisiting some of my old answers and when I saw this I remembered that Firefox *requires* a second parameter for *getComputedStyle()*. I [reported a bug for this](https://bugzilla.mozilla.org/show_bug.cgi?id=567350) on Bugzilla a while back but they're not going to fix it until CSSOM is finalized. I've edited my answer to include this fix, sorry I didn't think of it earlier :-)
Andy E
+7  A: 

Have you tried cloneNode? It can copy the element and all of its children in one fell swoop. http://www.w3schools.com/dom/met_element_clonenode.asp

Eric Mickelsen
If you need to transfer it as a string, you should be able to use JSON. This actually may end up being smaller than trying to transfer the computed style, and it should work properly if the appriopriate css is available in both contexts.
Eric Mickelsen
+1 - `cloneNode` might not copy the entire style if styles were applied by ID selectors (`#myFrame { }`) or other selectors that would not apply to the new node, but this should be perfect if that's not the case here.
Andy E
Must have missed that part of the doc I was so expecting to have to do it myself, but alas it's not working either which leads me to believe something else is wrong. I have a feeling there's some nuance about it going from one frame to another. Would clone necessarily pick up styles inherited from nodes parent to the one I'm cloning?
stu
@stu, `cloneNode` will only copy the attributes and properties that are set (that is, any inline or DOM-applied styles, and any attributes that trigger CSS styles to be applied). If some styles are determined by inheritance from the parent elements, those will only be applied in your other frame if the cloned child is appended to the same structure and the same CSS is available. Also worth noting when moving DOM nodes between frames, you should look into `document.importNode`, as some browsers will restrict the operation unless you do it explicitly.
eyelidlessness
Thanks for the tip. I'll check that out. I got the bright idea to copy the node to the same frame to isolate the problem and it's still not picking up the style, so I'm missing something else. So if clone doesn't pick up parent style traits, I'll have to go back to getcomputedstyle.
stu
@stu, as already mentioned, `cloneNode` won't copy styles inherited from parents. It will only copy the attributes that are set in the DOM. Either use the computed style (probably your best bet) or duplicate the parent structure (obviously only has limited application). Be aware, also, that even using the computed style will not necessarily cascade all styles correctly down to the clone'd node's children.
eyelidlessness
A: 

This will work if the styles are applied via the "style" attribute on an element.

http://stackoverflow.com/questions/2087778/javascript-copy-style

RussellUresti
A: 

Well I gave up the original tack of trying to get the [computed] style information out of the source tag, I just never got it to work.

So instead I tried this, and it did work...

First I grabbed the -style- tag from the source frame, then I appendChilded it to the end of the -head- tag of the second frame. For which this proved useful... http://stackoverflow.com/questions/875610/how-do-you-copy-an-inline-style-element-in-ie

Then I made a few nested div elements, each having an id or style class I needed to inherit so that the hierarchy matched the first frame. Then I shoved the innerhtml of the source frame's tag that I wanted to copy and then finally appendChilded it to the body of the second frame, and magically, it all worked.

var topd = doc.createElement('div'); // make a div that we can attach all our styles to so they'll be inherited
topd.id = 'menuanchorelement';
// shove our desired tag in the middle of a few nested elements that have all the classes we need to inherit...
topd.innerHTML = "<div id='multi-level'><ul class='menu'>" + dh.innerHTML + "</ul></div>";

doc.body.appendChild(topd); // voila

stu