innerHTML and style attributes

T

Tom de Neef

I copy data to a second window, where it is prepared for proper printing and
copying, via:
function copyTable(source,destin){
secondWindow.document.getElementById(destin).innerHTML =
document.getElementById(source).innerHTML
}

When the source has all style attributes in the elements itself, such as <td
align="right" style="padding-right:4pt">, everything works out fine.
But when attributes are passed via a class reference, such as
<style type ="text/css"> td.rght {text-align:right; padding-right:4pt}
</style>
<td class="rght">
IE seems to pass the style information for each element but FF(6 or 7) does
not copy the style attributes accross. Same problem when I use css pseudo
classes.
I do not understand this and it makes FF unworkable for me.

Do I miss something or is this to be expected?
TIA
Tom
 
E

Evertjan.

Tom de Neef wrote on 30 sep 2011 in comp.lang.javascript:
I copy data to a second window, where it is prepared for proper
printing and copying, via:
function copyTable(source,destin){
secondWindow.document.getElementById(destin).innerHTML =
document.getElementById(source).innerHTML
}

When the source has all style attributes in the elements itself, such
as <td align="right" style="padding-right:4pt">, everything works out
fine. But when attributes are passed via a class reference, such as
<style type ="text/css"> td.rght {text-align:right; padding-right:4pt}
</style>
<td class="rght">
IE seems to pass the style information for each element but FF(6 or 7)
does not copy the style attributes accross. Same problem when I use
css pseudo classes.
I do not understand this and it makes FF unworkable for me.

Do I miss something or is this to be expected?

FF does not "work" for you as programmer, but for your users.

myTable.innerHTML is not a very usable duplication agent FOR TABLES, as
has been said time and again in this NG. Browsers might use the source-
code, the DOM-tree or other methods for duplication.

Perhaps a complete table using at least a <tbody></tbody> and propper
</tr> and </td>'s might still do the trick, but I doubt that.

I think, that your trial shows your approach is unworkable cross-browser-
wize, so try a different approach:

Best build the new page table up from
1 DOM-scratch or
2 database-scratch,
3 insert the table source by serverside file-inclusion in both pages,
or
4 use the original page for printing using @media css directives,
for instance.
 
T

Tom de Neef

Without any idea of what you are actually doing it is not practical to
determine which expectations would be reasonable from it.

Ok, the basics. Forget tables, forget differences between browsers,
concentrate on style attributes.
In the code below, the style information for the first two <p> elements is
in a <style> element. The third <p> has no style attributes and the last one
has an explicit style="color:green".
The body.onclick will open a second window where these <p> elements are
copied via innerHTML of their parent <div>. In the process the 3rd p's
innerHTML will be modified.

In the new window the first three <p>'s seem to be copied without their
style information; the 3rd has its contents modified and the fourth one
comes through with style info intact.
This confuses me.
The 3rd p is modified, so innerHTML does not copy source html. It must copy
the DOM tree for the element.
But if it does, why does it not copy the attributes as well?
Thank you,
Tom

--- test code ---
<!DOCTYPE HTML SYSTEM>
<html>
<head>
<title>xxx</title>
<script type="text/javascript">
var secondWindow;

function makeHTML(txt){
var s = "<html><head><title>xxx</title></head>";
s +="<body>"+txt+"</body></html>";
return s
}

function extraWindow(txt){
secondWindow = window.open("","Support","");
secondWindow.document.write(makeHTML(txt));
secondWindow.document.close();
secondWindow.focus();
}

function copyElement(source,destin){
secondWindow.document.getElementById(destin).innerHTML =
document.getElementById(source).innerHTML
}

function testCopy(source){
extraWindow("<div id='trgt'> </div>");
copyElement('src','trgt');
}
</script>

<style type="text/css">
p.blue {color:blue}
p:first-child {color:red; padding-left:20pt}
</style>
</head>

<body onclick="testCopy('src')">
<div id='src'>
<p>first para should be red and indented</p>
<p class="blue">para with class=blue</p>
<p>para without class</p>
</div>
</body>

</html>
 
J

Jukka K. Korpela

30.9.2011 21:04 said:
Ok, the basics. Forget tables, forget differences between browsers,
concentrate on style attributes.

In fact, your sample code contains no style attributes.
--- test code ---

Well this is at least a somewhat complete test case, though for several
reasons, a URL would have been better.
function makeHTML(txt){
var s = "<html><head><title>xxx</title></head>";
s +="<body>"+txt+"</body></html>";
return s
}

So you're generating an HTML document with no <style> element, or style
attribute for that matter.

Why does it come as a surprise that no styles are applied when rendering it?
 
S

Stuart McCall

Tom de Neef said:
Ok, the basics. Forget tables, forget differences between browsers,
concentrate on style attributes.
In the code below, the style information for the first two <p> elements is
in a <style> element. The third <p> has no style attributes and the last
one has an explicit style="color:green".
The body.onclick will open a second window where these <p> elements are
copied via innerHTML of their parent <div>. In the process the 3rd p's
innerHTML will be modified.

In the new window the first three <p>'s seem to be copied without their
style information; the 3rd has its contents modified and the fourth one
comes through with style info intact.
This confuses me.
The 3rd p is modified, so innerHTML does not copy source html. It must
copy the DOM tree for the element.
But if it does, why does it not copy the attributes as well?
Thank you,
Tom

--- test code ---
<!DOCTYPE HTML SYSTEM>
<html>
<head>
<title>xxx</title>
<script type="text/javascript">
var secondWindow;

function makeHTML(txt){
var s = "<html><head><title>xxx</title></head>";
s +="<body>"+txt+"</body></html>";
return s
}

function extraWindow(txt){
secondWindow = window.open("","Support","");
secondWindow.document.write(makeHTML(txt));
secondWindow.document.close();
secondWindow.focus();
}

function copyElement(source,destin){
secondWindow.document.getElementById(destin).innerHTML =
document.getElementById(source).innerHTML
}

function testCopy(source){
extraWindow("<div id='trgt'> </div>");
copyElement('src','trgt');
}
</script>

<style type="text/css">
p.blue {color:blue}
p:first-child {color:red; padding-left:20pt}
</style>
</head>

<body onclick="testCopy('src')">
<div id='src'>
<p>first para should be red and indented</p>
<p class="blue">para with class=blue</p>
<p>para without class</p>
</div>
</body>

</html>

In the function testCopy, as you have it now, 'src' is undefined. Should be
'source', yes?
 
T

Tom de Neef

Jukka K. Korpela said:
In fact, your sample code contains no style attributes.


Well this is at least a somewhat complete test case, though for several
reasons, a URL would have been better.


So you're generating an HTML document with no <style> element, or style
attribute for that matter.

Why does it come as a surprise that no styles are applied when rendering
it?

Thank you. That is quick ;-)
Hard to answer your question. I was so convinced that the information of a
class definition must have been passed to all the elements that the obvious
never occured.
I checked: the copied element contains the same class attribute as the
original.

I need the attributes explicitly in the elements - like in the last <p> -
otherwise Word will not see them after a copy/paste.
From the classlist of each element I can copy the relevant attributes.
But where can I obtain the attributes applied to an element through the
pseudo-class definition p:first-child ? I.e. given an element, is there an
attribute or method that tells me if such a pseudo-class style is involved
(sorry for the sloppy language)?
Tom
 
S

Scott Sauyet

Tom said:
Jukka K. Korpela wrote
Tom de Neef wrote:
In fact, your sample code contains no style attributes.
[ ... ]
So you're generating an HTML document with no <style> element, or style
attribute for that matter.

I checked: the copied element contains the same class attribute as the
original.

I think you're missing the point. Look at the generated document as a
whole. It has no <STYLE> element in it. When you put this in the
parent document:

| <style type="text/css">
| p.blue {color:blue}
| p:first-child {color:red; padding-left:20pt}
| </style>

you got the expected styles in that document. When you create the new
document, you don't copy the stylesheet, so you don't get the expected
styles. If you copied the style text or added a link to a shared
stylesheet to the new document it should just work.

-- Scott
 
T

Tom de Neef

Scott Sauyet said:
Tom said:
Jukka K. Korpela wrote
Tom de Neef wrote:
Ok, the basics. Forget tables, forget differences between browsers,
concentrate on style attributes.
In fact, your sample code contains no style attributes.
[ ... ]
So you're generating an HTML document with no <style> element, or style
attribute for that matter.

I checked: the copied element contains the same class attribute as the
original.

I think you're missing the point. Look at the generated document as a
whole. It has no <STYLE> element in it. When you put this in the
parent document:

| <style type="text/css">
| p.blue {color:blue}
| p:first-child {color:red; padding-left:20pt}
| </style>

you got the expected styles in that document. When you create the new
document, you don't copy the stylesheet, so you don't get the expected
styles. If you copied the style text or added a link to a shared
stylesheet to the new document it should just work.
I appreciate that but it is of no use to me. I need the styles as attributes
to each element. The reason is that the copied part of the page will then be
copy/pasted into Word by the user. Word will render the inline style
settings but not the embedded ones when it gets data via a paste.

So, what I'll have to do is:
- copy the DOM of selected part of the page (typically a table)
- for each element in that tree, obtain the actual styles (I am researching
CSSStyleDeclaration and currentStyle objects)
- copy properties of these objects to attributes of the element (unless
already set)

The alternative is to inline the styles from the start. But with alignment,
padding and various rules and borders the source document, produced by the
server, gets rather big, whereas with style pseudo-classes it is of minimal
size.
Tom
 
T

Tim Streater

Tom de Neef said:
Scott Sauyet said:
Tom said:
Jukka K. Korpela wrote
Tom de Neef wrote:

Ok, the basics. Forget tables, forget differences between browsers,
concentrate on style attributes.

In fact, your sample code contains no style attributes.
[ ... ]
So you're generating an HTML document with no <style> element, or style
attribute for that matter.

I checked: the copied element contains the same class attribute as the
original.

I think you're missing the point. Look at the generated document as a
whole. It has no <STYLE> element in it. When you put this in the
parent document:

| <style type="text/css">
| p.blue {color:blue}
| p:first-child {color:red; padding-left:20pt}
| </style>

you got the expected styles in that document. When you create the new
document, you don't copy the stylesheet, so you don't get the expected
styles. If you copied the style text or added a link to a shared
stylesheet to the new document it should just work.
I appreciate that but it is of no use to me. I need the styles as attributes
to each element. The reason is that the copied part of the page will then be
copy/pasted into Word by the user. Word will render the inline style
settings but not the embedded ones when it gets data via a paste.

So, what I'll have to do is:
- copy the DOM of selected part of the page (typically a table)
- for each element in that tree, obtain the actual styles (I am researching
CSSStyleDeclaration and currentStyle objects)
- copy properties of these objects to attributes of the element (unless
already set)

Then you'll get a new version of Word and it won't work any more. Or an
old version. Or a version on another platform. This is too fragile an
approach, IMO.
 
J

Jukka K. Korpela

You quoted that but did not get the hint, did you?
Thank you. That is quick ;-)
Hard to answer your question.

Please let me help you: You have no idea of how document objects work.
I was so convinced that the information of a
class definition must have been passed to all the elements that the obvious
never occured.

You are not passing any "class definition", just some class attributes.
Is this the "obvious" thing you are talking about?
I checked: the copied element contains the same class attribute as the
original.

So? You can have class="do what I want". Do you expect it to work?
I need the attributes explicitly in the elements - like in the last <p> -
otherwise Word will not see them after a copy/paste.

So? Has this anything to do with JavaScript?
From the classlist of each element I can copy the relevant attributes.
But where can I obtain the attributes applied to an element through the
pseudo-class definition p:first-child ? I.e. given an element, is there an
attribute or method that tells me if such a pseudo-class style is involved
(sorry for the sloppy language)?

It's not sloppy, just absurd. The code snippet that you posted generates
a document with _no_ style sheet.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
I copy data to a second window, where it is prepared for proper printing and
copying, via:
function copyTable(source,destin){
secondWindow.document.getElementById(destin).innerHTML =
document.getElementById(source).innerHTML
}

That should copy the HTML which is within the element source - no more,
no less.
When the source has all style attributes in the elements itself, such as <td
align="right" style="padding-right:4pt">, everything works out fine.

One would expect those styles to be included.
But when attributes are passed via a class reference, such as
<style type ="text/css"> td.rght {text-align:right; padding-right:4pt}
</style>
<td class="rght">
IE seems to pass the style information for each element but FF(6 or 7) does
not copy the style attributes accross. Same problem when I use css pseudo
classes.
I do not understand this and it makes FF unworkable for me.

You should have more browsers; I'd expect that others would agree with
FF. To a first approximation, one expects IE to do what Microsoft think
might be wanted, whereas others just try to do what is right.
Do I miss something or is this to be expected?

You need to copy the stylesheets from the DOM structure of the source to
that of the destination. It ought to work. My page
<http://www.merlyn.demon.co.uk/js-props.htm> should be able to show its
own stylesheet elements.
 
T

Tom de Neef

Richard Cornford said:
OK, but differences between IE and Firefox seemed important in your
original post.


Others have already covered the main problem with your test case code, but
do observe how quickly that test case elicited informative responses.


Reading the - innerHTML - property serialises the pertinent DOM branch at
the point of reading it, and applies some algorithm to that serialisation
(where that algorithm had not traditionally been specified or consistent
across browsers).


I want to make one observation about this code in addition to what has
already been said by others.


That DOCTYPE is the minimum necessary to put a browser into 'standards'
mode, so this source document is in standards mode.


I don't recall whether it is even possible to switch a document from
'quirks' mode to 'standards' mode by including a DOCTYPE in text written
using - document.write -, but even if it is that is not being attempted
here.


With an empty string as the first argument to the - window.open - method
the usual response is for the browser to open the new window with
about:blank page (or opera:blank, or whatever else the particular
browser/version uses as a blank page). Although the loading of this page
is likely to be very quick I would be reluctant to treat the process as
guaranteed to be synchronous (either in practice now, or if now for the
foreseeable future (because multi-core CPUs are becoming the norm and
opening a new window should represent an opportunity to start a new thread
on the processor, offload the work to another core, and increase the
browsers performance along the way).

<snip>

The - document.write - method inserts mark-up into a document that is
being parsed if the document has not finished loading, and only replaces
the document if the document on which the method is called has finished
being parsed. As you are writing a complete HTML document it is the
latter of these two behaviours that you appear to want; that is, you are
relying on the loading of about:blank being synchronous when there nothing
beyond a set of observations of behaviour to say that it will be.

However, the point I really wanted to make is that your source document is
in 'standards' mode, but I know that IE's about:blank is a 'quirks' mode
page. I have no idea what mode these pages will be in on other browsers
(but I expect they follow IE, and if not then that would not be a good
thing in this context). These modes are primarily concerned with the
interpretation of CSS within the document, so where that interpretation is
significant to the mode in your document you will see differences in the
presentation of the content between the source and destination.

When I do this (and I do) I load a content-less 'blank' page from the
server into the new window, specifying an appropriate DOCTYPE to get the
desired mode, and include in that page an onload listener that alerts the
opener page to the arrival of that document, and so triggers the actual
writing of content to that newly loaded document (which deals with the
asynchronous loading of that page from the server). Obviously that
requires more, and more complex, code, but gains an explicit control over
these aspects of page loading that could not be certain otherwise.

Thank you. Many things to think about.
Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,266
Messages
2,571,078
Members
48,772
Latest member
Backspace Studios

Latest Threads

Top