IE - Insert newline into <pre>?

D

dhtmlkitchen

How can I insert \n into a pre and have it look right in IE?

I can insert \r\n, but then I'd have to try and use some sort of
detection for... a browser that doesn't support \n in PRE... And I
don't wanna go down that road.

Test case:
<script>
function insertText() {
document.getElementById('test').innerHTML =
"Hey Chuck Norris!\n\nHave some cheeze.\n\nKiss a monkey!!!";
}
</script>


<pre id=test>

</pre>

<input type="button" onclick="insertText()" value="insert text"/>
 
P

Peter Michaux

Hi,


How can I insert \n into a pre and have it look right in IE?

I can insert \r\n, but then I'd have to try and use some sort of
detection for... a browser that doesn't support \n in PRE... And I
don't wanna go down that road.

Test case:
<script>
function insertText() {
document.getElementById('test').innerHTML =
"Hey Chuck Norris!\n\nHave some cheeze.\n\nKiss a monkey!!!";}

</script>

<pre id=test>

</pre>

<input type="button" onclick="insertText()" value="insert text"/>


I just tried a couple things related to your problem.

It seems as though outerHTML respects the \n characters but outerHTML
is not widely supported.


function insertText() {
document.getElementById('test').outerHTML =
"<pre id=\"test\">Hey Chuck Norris!\n\nHave some
cheeze.\n\nKiss a monkey!!!</pre>";
}


Then I tried just replacing the whole pre element by adding a wrapper.


<script>

function insertText() {
document.getElementById('wrapper').innerHTML =
"<pre id=\"test\">Hey Chuck Norris!\n\nHave some
cheeze.\n\nKiss a monkey!!!</pre>";
}

</script>

<div id="wrapper">
<pre id="test">
</pre>
</div>

<input type="button" onclick="insertText()" value="insert text"/>


Maybe you could work one of these into a solution.

Peter
 
J

Julian Turner

On 26 Sep, 04:35, "(e-mail address removed)" <[email protected]>
wrote:
[snip]
How can I insert \n into a pre and have it look right in IE?
[/snip]

I use Peter Michaux's solution of replacing the whole "pre" element
myself.

I hadn't though of Evertjan's solution of "<br>", which seems a good
one.

Another solution (IE only) I came up with was this:-

1. In your html have a useless "<pre id="cr">CR_CHARACTER</pre>".

2. Use the the IE TextRange object and "moveToElementText" for this
pre.

var el = document.getElementById("cr");
var range = document.body.createTextRange();
range.moveToElementText(el);

3. Use execCommand("Copy").

range.execCommand("Copy");

4. Get a second TextRange for the cursor point where you want to
insert the CR, and execCommand("Paste") on that second TextRange.

If your cursor is in some contentEditable place, you might event get
it thus:-

var secondRange = document.selection.createRange();
sectionRange.execCommand("Paste");

Julian Turner
 
D

dhtmlkitchen

On 26 Sep, 04:35, "(e-mail address removed)" <[email protected]>
wrote:
[snip]> How can I insert \n into a pre and have it look right in IE?

[/snip]

I use Peter Michaux's solution of replacing the whole "pre" element
myself.

I hadn't though of Evertjan's solution of "<br>", which seems a good
one.
I don't think it will work in my case; It's complicated to explain.
I've had success in some cases using \r\n:

String.nl = "clipboardData" in window ? "\r\n" : "\n";

But if I don't build the string myself, I don't have control over the
newline/cr characters.

I tried using Peter's approach which worked on PRE elements. I tried
getting it to work on TD but it didn't; so I sucked it up and used an
extra pre in those cases. anyone else reading this thread might be
interested.

/** This method will work with PRE but not TD elements
*/
function setInnerHTML( el, s ) {
if(! "innerHTML" in el ) {
throw new TypeError("setInnerHTML: first argument does not
support innerHTML. Is it an element?");
}

// Webkit and Futhark both support outerHTML.
// Only IE supports clipboardData
var outerHTML = el.outerHTML;
if( outerHTML && "clipboardData" in window ) {
var innerHTML = new RegExp(">([^<]*)<");
var oldContent = outerHTML.match(innerHTML)[1];
el.outerHTML = outerHTML.replace( oldContent, s );
}
else {
el.innerHTML = s;
}
}

Which works. Nasty code but it works.

The page will probably have other scripts that I don't control. The
solution doesn't address the possibility of an anomalous foreign
script that defines a clipboardData variable.

javascript:alert(Object.prototype.propertyIsEnumerable.call(window,
"clipboardData")); // JScript chokes on COM obj.

Attempting to find DontDelete by the return of delete
window.clipboardData was funny. Error: alert(error.name), TypeError:
Bad variable name.

Garrett
 
E

Evertjan.

I don't think it will work in my case; It's complicated to explain.

Which is nonsense, methinks. Either it works or it does not,
your case dos not use another type of <pre>, I am certain.

Why "think" it doesnot work? You can test it:

<pre>
First line<br>Second line
</pre>

QED!

========================

So when you use a line insertion from a javascript string,
first do a replace:

t = t.replace(/\n/g,'<br>')
 
D

David Mark

wrote:
[snip]> How can I insert \n into a pre and have it look right in IE?

I use Peter Michaux's solution of replacing the whole "pre" element
myself.
I hadn't though of Evertjan's solution of "<br>", which seems a good
one.

I don't think it will work in my case; It's complicated to explain.
I've had success in some cases using \r\n:

String.nl = "clipboardData" in window ? "\r\n" : "\n";

But if I don't build the string myself, I don't have control over the
newline/cr characters.

I tried using Peter's approach which worked on PRE elements. I tried
getting it to work on TD but it didn't; so I sucked it up and used an
extra pre in those cases. anyone else reading this thread might be
interested.

/** This method will work with PRE but not TD elements
*/
function setInnerHTML( el, s ) {
if(! "innerHTML" in el ) {
throw new TypeError("setInnerHTML: first argument does not
support innerHTML. Is it an element?");
}

I would test typeof(el.innerHTML) != 'string'.
// Webkit and Futhark both support outerHTML.
// Only IE supports clipboardData

Object inferences are a bad idea.
var outerHTML = el.outerHTML;
if( outerHTML && "clipboardData" in window ) {

This clause is apparently meant for IE only.
var innerHTML = new RegExp(">([^<]*)<");
var oldContent = outerHTML.match(innerHTML)[1];
el.outerHTML = outerHTML.replace( oldContent, s );

Why not do an initial feature test that sets outerHTML for an element
and then tests innerHTML for the \n character? That would seem a
better test than checking clipboardData, then assuming IE, then
assuming all versions of IE have this problem (and all others don't.)
Furthermore, don't bother doing this if there are no \n characters in
the passed string. Considering what this clause does, you want it to
be invoked as little as possible.
}
else {
el.innerHTML = s;
}
}

Which works. Nasty code but it works.

The page will probably have other scripts that I don't control. The
solution doesn't address the possibility of an anomalous foreign
script that defines a clipboardData variable.

Or one that augments elements with an innerHTML property or simply
assigns a value to that property of the passed element.
javascript:alert(Object.prototype.propertyIsEnumerable.call(window,
"clipboardData")); // JScript chokes on COM obj.

Oddly enough, this host object doesn't behave like a COM object (at
least not in IE7.)

This test on a method of a known COM object alerts "unknown."

alert(typeof(window.external.addFavorite));

This test alerts "object."

alert(typeof(window.clipboardData.getData));

So a good test would be:

alert(window.clipboardData && (typeof(window.clipboardData.getData) ==
'object' || typeof(window.clipboardData.getData) == 'unknown'));

The "unknown" test is included in case IE changes clipboardData in the
future to behave like other COM objects (or if they behaved like them
in the past.)

Regardless, I wouldn't infer anything from the results of this test.
Attempting to find DontDelete by the return of delete
window.clipboardData was funny. Error: alert(error.name), TypeError:
Bad variable name.

This is typical of many IE host objects. I think it indicates a COM
object, but then I thought all COM objects had methods of type
"unknown." Oddly enough, this returns true:

alert(Object.prototype.hasOwnProperty.call(window, "clipboardData"));

I would have expected the opposite.
 
D

dhtmlkitchen

(e-mail address removed) wrote on 30 sep 2007 in comp.lang.javascript:


Which is nonsense, methinks. Either it works or it does not,
your case dos not use another type of <pre>, I am certain.

Why "think" it doesnot work? You can test it:
Because I need the characters. I'm setting innerHTML of A then I
compare A and B for equality.

It's a sort of test thing.

<pre id="source">(function(){
return "Borf" + "\n!";
})();</pre>

<pre id="result"></pre>

<pre id="expected">Borf
!</pre>

The test has to look right, and if A == B, it should return true. I
have to care

It might work with BR. I didn't actually try it. In some other cases,
I have to work with the innerHTML for supplanted evals.

<pre id='expected'>
BorfDate: $
{BorfMonster.prototype.getBorfExpurgationDate.call( expected );}
</pre>

I have some scope resolver to resolve expected.

It probably wouldn't get in the way, now that I think of it; it just
seemed easier to avoid tags inside the eval'd element source/expected.

I wouldn't have to deal with the outerHTML hack. It would be simpler.

Garrett
 
E

Evertjan.

Because I need the characters. I'm setting innerHTML of A then I
compare A and B for equality.

What characters? "<br>" is a string of characters.

If you mean javascript strings by A and B, try:

A.replace(/\n/g,'<br>') == B.replace(/\n/g,'<br>')

[so it would not matter if A exor B had been replaced() before or not]
It's a sort of test thing.

<pre id="source">(function(){
return "Borf" + "\n!";
})();</pre>

Impossible, javascript does not run inside a html element,
except for <script type='text/javascript'></script>,
but that shouldn't be called an html element perhaps.

<pre id="result"></pre>

<pre id="expected">Borf
!</pre>
???

The test has to look right, and if A == B, it should return true. I
have to care

What test?

if a == b is true, it always returns true, whether it looks right or
wrong does not matter.
It might work with BR. I didn't actually try it. In some other cases,
I have to work with the innerHTML for supplanted evals.

"supplanted evals" are those [extinct?] life forms?

<pre id='expected'>
BorfDate: $
{BorfMonster.prototype.getBorfExpurgationDate.call( expected );}

Again impossible in clientside javascript,
are you sure you are posting in the right NG?
</pre>

I have some scope resolver to resolve expected.

Eh? Is that English? My bio-parser errors out over this sentence.

It probably wouldn't get in the way, now that I think of it; it just
seemed easier to avoid tags inside the eval'd element source/expected.

What is an evalled element? what is "source/expected"?

Remember eval is evil, if not used where there is really no other
option.
I wouldn't have to deal with the outerHTML hack. It would be simpler.

What would be simpler?

outerHTML is IE only, but no hack.

[quoted signature removed, please do not quote signatures on usenet]

In short, Garret, you are not making much sense.
 
D

dhtmlkitchen

(e-mail address removed) wrote on 01 okt 2007 in comp.lang.javascript:
Because I need the characters. I'm setting innerHTML of A then I
compare A and B for equality.

What characters? "<br>" is a string of characters.

If you mean javascript strings by A and B, try:

A.replace(/\n/g,'<br>') == B.replace(/\n/g,'<br>')

[so it would not matter if A exor B had been replaced() before or not]
It's a sort of test thing.
<pre id="source">(function(){
return "Borf" + "\n!";
})();</pre>

Impossible, javascript does not run inside a html element,
<pre id="result"></pre>
<pre id="expected">Borf
!</pre>
???

The test has to look right, and if A == B, it should return true. I
have to care

What test?

if a == b is true, it always returns true, whether it looks right or
wrong does not matter.
Well, it does matter because I want to test equality and I want to
show the reader the result of the test, e.g.

Result:
<pre>
Beethoven, Orange Juice, Symphony X, Pantera
</pre>

Expected:
<pre>
Beethoven,
Orange Juice
Symphony X,
Pantera,
</pre>

The reader will see it looks wrong in IE. It's distracting at the
least. At worst, the line runs off the screen and causes a horz
scrollbar. Very weak presentation, IMO.
It might work with BR. I didn't actually try it. In some other cases,
I have to work with the innerHTML for supplanted evals.

"supplanted evals" are those [extinct?] life forms?
<pre id='expected'>
BorfDate: $
{BorfMonster.prototype.getBorfExpurgationDate.call( expected );}

Again impossible in clientside javascript,
are you sure you are posting in the right NG?

Alright.

We'll see when I post my article up next week.

Eh? Is that English? My bio-parser errors out over this sentence.

'expected' = the should-be result, e.g. assert(actual, expected, msg);

What is an evalled element? what is "source/expected"?
Eval'd (element source)
Remember eval is evil, if not used where there is really no other
option.
Yeah, well, it's really useful for this test thing. You can't see it
so I can understand why it wouldn't make sense.

Basically, I've got some javascript running in a pre tag. The result
gets output to another pre tag. The user should see the result
formatted correctly. The result should be logically comparable to the
expected result for equality.

What would be simpler?

outerHTML is IE only, but no hack.
Actually, outerHTML is IE, Safari, Opera. Preliminary ad-hoc tests
tell me that whitespace is handled differently in all 3.

I did run into some problems using BR. I can't remember off the top of
my head.

Anyway, BR will work for some things. but not here. thanks.

garrett
 
D

dhtmlkitchen

I would test typeof(el.innerHTML) != 'string'.
Makes sense. If someone ever tries to subvert my function with
something like the following, it will fail silently.

{ innerHTML : "foo" }

I think I can live w/that.
Why not do an initial feature test that sets outerHTML for an element
and then tests innerHTML for the \n character?

I think you meant to say: Do an initial feature test by setting the
element's innerHTML and then checking the outerHTML for "\n" ?

If that's what you meant, that seems like the right way to do it.

The idea you're proposing sounds to be the most correct one:
if set innerHTML with \n results in the browser not displaying \n as a
line break, use the outerHTML regexp hack. Is that Right?

Would require a good bit of testing. Safari 2 has some whitespace
issues on textContent (Problem: to preseve whitespace, use a PRE tag
that is visible). I haven't found any problems with innerHTML yet. So
far, it's just IE.
better test than checking clipboardData, then assuming IE, then
assuming all versions of IE have this problem (and all others don't.)

You're absolutely right. I'm not going down the clipboardData road
anymore.
Furthermore, don't bother doing this if there are no \n characters in
the passed string.
Good point, so:

if( isIE && /\n/.test(s) )

Considering what this clause does, you want it to
be invoked as little as possible.
Why should this be invoked as little as possible?

alert(window.clipboardData && (typeof(window.clipboardData.getData) ==
'object' || typeof(window.clipboardData.getData) == 'unknown'));

The "unknown" test is included in case IE changes clipboardData in the
future to behave like other COM objects (or if they behaved like them
in the past.)
javascript:alert(typeof(window.clipboardData.getData))

"object" in ie7.

For now, I'm just using a conditional comment browser check. I may
revisit this with a more correct approach.

String.nl = /*@cc_on!@*/false ? "\r\n" : "\n";

I put a similar check in the setOuterHTML function, too.

It's in closed scope, so no need to worry about the isIE variable;
it's hidden:
======================================================================
/** This method will work with PRE but not TD elements
*/
var isIE = /*@cc_on!@*/false;

function setInnerHTML( el, s ) {
if(typeof el["innerHTML"] != "string" ) {
throw new TypeError("setInnerHTML: first argument does not
support innerHTML. Is it an element?");
}

var outerHTML = el.outerHTML;
if( isIE && /\n/.test(s) ) {
var innerHTML = new RegExp(">([^<]*)<");
var oldContent = outerHTML.match(innerHTML)[1];
el.outerHTML = outerHTML.replace( oldContent, s );
}
else {
el.innerHTML = s;
}
}
======================================================================


Thanks,

Garrett
 
D

David Mark

Makes sense. If someone ever tries to subvert my function with
something like the following, it will fail silently.

{ innerHTML : "foo" }

I think I can live w/that.




I think you meant to say: Do an initial feature test by setting the
element's innerHTML and then checking the outerHTML for "\n" ?

If that's what you meant, that seems like the right way to do it.

As I recall, the problem was with setting innerHTML failed and in some
cases outerHTML could be used to work around this. The test I
proposed would identify these cases. If you do it the other way
around, you will identify cases where it a workaround is needed, but
you still won't know if outerHTML will actually help. So the full
solution would be to test if there is a problem with innerHTML and
then test if outerHTML is an actual solution to the problem. If it is
not a solution then your app can't function as you need it to.
The idea you're proposing sounds to be the most correct one:
if set innerHTML with \n results in the browser not displaying \n as a
line break, use the outerHTML regexp hack. Is that Right?
Yes.


Would require a good bit of testing. Safari 2 has some whitespace
issues on textContent (Problem: to preseve whitespace, use a PRE tag
that is visible). I haven't found any problems with innerHTML yet. So
far, it's just IE.


You're absolutely right. I'm not going down the clipboardData road
anymore.


Good point, so:

if( isIE && /\n/.test(s) )

Considering what this clause does, you want it to> be invoked as little as possible.


Why should this be invoked as little as possible?

Not that clause, the outerHTML hack.
javascript:alert(typeof(window.clipboardData.getData))

"object" in ie7.

That was my point. Before I tested it, I would have guessed
"unknown."
For now, I'm just using a conditional comment browser check. I may
revisit this with a more correct approach.

String.nl = /*@cc_on!@*/false ? "\r\n" : "\n";

Conditional compilation is preferable to an object inference, but a
feature test would be a better as it would cover non-IE browsers that
may have this same issue. BTW, have you tested this in Mac IE?
 

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
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top