How can I replace newline characters using javascript in IE8? - javascript

I've searched Stackoverflow for hours and hours, and nobody's solution works in Internet Explorer 8.
I am provided with a plaintext document like this:
This is a legal agreement ("Agreement") between you and ...
License
Subject to you continued and ongoing compliance with the terms and conditions set ...
Restrictions
Except as otherwise explicitly provided in this Agreement, ...
Ownership
Except for this license granted to you, as between you and ...
Disclaimer of Warranties
Use at your own risk. ...
And I need to replace the newline characters (linebreaks, carriage returns, whatever you want to call them) with double linebreaks (<br/><br/>) to make the text look more normal.
The nl2br function from jQuery convert line breaks to br (nl2br equivalent) works fine in most browsers. However, a client of mine uses IE8.
Go ahead and try the nl2br function using IE8 (or a modern Internet Explorer set to IE8 mode); it doesn't work.
Does anyone know why it doesn't work in IE8? And how to accomplish the goal?
P.S. I put some code here http://jsfiddle.net/L2Ufj/2/ and oddly enough it works in IE8 via jsfiddle, but if you copy it to somewhere else and run it for real, it won't work in IE8.

One way to get round this in IE8 is to convert the line-breaks into a 'token' that IE8 will recognise before it is rendered on the page. Then once it's rendered, in a success handler for example you can search for that token and replace with <br> or whatever you wish:
e.g.
Pre render (I've used < br > as my token but you can use anything)
textToEdit = textToEdit.replace(/\n/g, '<br>');
Post render (Search for your token and replace with <br> or whatever you wish)
renderedTextWrapper.innerHTML = renderedTextWrapper.innerHTML.replace(/<br>/g, '<br>');

When you retrieve element's innerHTML, IE will convert the innerHTML to a "standard-format" (by collapsing multi-spaces into one, removing linebreak, etc...) before giving you the result.
Thus, you can not find any linebreak character in the innerHTML you get with IE. What a bad news.
I think the most feasible & easy approach is to store your text inside <textarea> tag instead of normal <div>. IE will leave <textarea> alone when you get it's value instead of innerHTML:
originalText=document.getElementById('EULA_content').value
Of course, when you get the newText, you should append it to another div element.

Related

Can't get word on click

I have a script that get the word by getselection method when click, not by user selection, and then show an alert box with the word it's working well with some words, for example:
Si potrebbe comumente
It works with "potrebbe", but not with "Si".... It means, it works when the word is in the middle of the line, but not with the first or last word of the line...
This only happen when after apply the CheckKnowWords function, without apply this function, it works 100%.
The code is to big to post here, so, to prevent visual polution, I create this jsfiddle link: https://jsfiddle.net/fabiobraglin/ww7uLvd1/
ON FIREFOX
InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
ON CHROME:
Uncaught InvalidStateError: Failed to execute 'surroundContents' on 'Range': The Range has partially selected a non-Text node.
When use:
range.surroundContents(newNode);
Firefox seems to have a number of issues with this code.
1) An error is thrown in some cases
According to the documentation on MDN for Range.surroundContents:
An exception will be thrown, however, if the Range splits a non-Text
node with only one of its boundary points.
It also suggests another method that will work regardless. Instead of
range.surroundContents(newNode);
you can use
newNode.appendChild(range.extractContents());
range.insertNode(newNode);
This will make it so that you will not get errors on beginning and ending words, like Si, or mondo.
2) The popup and title show the entire html
They should show the text instead (e.g. senza instead of <span style="border-radius: 4px;border: 1px solid #ffcccc; background: #ffcccc;">senza</span>). To fix this, you can replace innerHTML with innerText.
More issues
There are a few more issues I found, but this is where it gets tricky. MDN has a warning that Selection.modify is non-standard and doesn't have plans to become standard, so you will get weird behavior between browsers, such as:
In Firefox, punctuation is being included at the end of the word (e.g. forti, or IATA).). In Chrome, this doesn't happen. Also, words with punctuation in them seem to work fine in Chrome but not in Firefox (e.g. the word L'indice looks fine in Chrome but comes up as indice in Firefox).
In Firefox, clicking on a word that follows a recognized word will instead select the recognized word. For example, if you clikc on ognuno where it says viaggo che ognuno di, it will catch the word che, but this doesn't happen in Chrome.
The word Henley is unique in that it is in bold tags. In the phrase britannica Henley & Partners, if you click on either Henley or & in Chrome you will get britannica. In Firefox you will get Henley.
You might want to consider changing the technique for finding the word. For example, you're already going through and highlighting all words you're interested in by wrapping them in a span. Instead of using Range and Selection, you could use the click event to figure out which span you're in, then get the text within that. If your initial checking also excludes punctuation and "words" like &, then you could just select the entire inner text.
Another minor issue I noticed is the HTML uses an unescaped & instead of &. It probably isn't affecting this example, but in general you'll run into less problems if you properly escape HTML (I think it's mainly just <, > and &, but there's plenty of tools and documentation on that elsewhere).
Here's an updated fiddle solving the first two issues, but they may be obsolete if you end up doing some refactoring to solve the other issues.
updated the fiddle. https://jsfiddle.net/ww7uLvd1/8/ Always use split(/\s+/) while trying to split with space

How to prevent & conversion to & when using JavaScript? (browser specifc)

I have a problem concerning string output on HTML page when using Javascript and ASP. Logic of page generation goes like this:
We use asp page to generate HTML code using Response.Write(). If string contains numeric character reference (for example С) it would show on the user's side just fine as a character.
After that we add OnLoad event, which calls for a Javascript function. All this happens inside <body><\body> tags. Source for JavaScript added inside <script></script> tags. The function only adds document.href, which contains reference to the same asp page.
The asp logic loads again and adds some text to the page using Response.BinaryWrite() (Response.Write can be used all the same) All character references are shown as codes:С. Obviously all '&' symbols become &(asp automatic conversion), browser decodes it as & and we can only see a code С and not the symbol 'С'.
As far as I know such behaviour can be caused by <script> tags, as a precaution against xss attacks. In the end I want to stop encoding '&' as &.
However here is the most important part:
If I add header with "Content-Type" "text\html", IE (any version) starts encoding NCR symbols in a correct way. But Firefox, Chrome and Safari do not change behavior and keep encoding & as &. I can see several questions on Stack Overflow which looks like mine, yet the situation is not exactly the same (My strings are not inserted directly by JavaScript, so I cannot manipulate output string and change & to &, also my strings have correct symbols in the first place, they get changed by asp or by browser). Is there any elegant way to force Firefox or Chrome to decode page as IE? Maybe some settings or attributes in HTML tags? This problem looks like it depends on a browser to me, am I right?

textarea attribute wrap=hard does not work on pasted text, any workarounds?

I have a textarea
<textarea id="id-textarea-readme" wrap="hard"></textarea>
which works realy fine, until someone writes his text in "notepad" and puts it in there via c&p , the words are wrapped correctly but no "extra" linebreaks are made (which is kind of the purpose of "hard")
Is there any workaround to make this work? any JS or a trick to trigger the linebreaks?
The wrap=hard attribute is nonstandard and does not work consistently across browsers. Modify the design so that you do not need to rely on such client-side operations. Textarea elements should be expected to yield actual user input, containing line breaks when user actually hit Enter. If you need to split long lines for further processing, do it server-side.
In my tests, IE wraps even in copy and paste. Firefox, on the other hand, introduces hard line breaks only when it wraps at whitespace but not when it wraps inside a “word”, so that for cols=5, the input 0123456789 (whether direct or copypaste) gets displayed as two lines but sent as one line, whereas 01234 56789 gets sent as two lines. I would expect to find other browsers incompatibilities as well.
the copy & paste issue probably comes from native OS linebreak/return/newline issues.
you could just listen for change or paste on the textarea DOM element and parse with javascript? that'd be my conceptual guess, here's a generic example in jquery:
$("textarea").on("change", function(event){
$this.replace(/\n\r?/g, '\n');
});

Regex behaving differently in IE6/IE7

My HTML is something like this :
<select>
<option>ABC (123)</option>
<option>XYZ (789)</option>
</select>
What I'm trying to do is: using JQuery and a regex, I replace the "(" with <span>( here's my JQuery line:
$(this).html($(this).html().replace(/\(/g,"<span>("));
It's working as intended in Firefox, chrome and safari, but (as usual) not behaving correctly on IE6/IE7 (the text after "(" just get removed)
Any thoughts ?
PS: I'm doing it this way because I need "(number") to be in a different color, and <span> in a <option> is not valid.
I don't think it's the regex breaking. The below works fine in IE7:
alert("(test".replace(/\(/g,"<span>("));
What's probably happening is that IE6/7 have no clue how to render a span inside an option and just fails to display anything.
You're saying that span in an option is not valid, and yet that's exactly what you're trying to add. Invalid code isn't prettier just because it happens to be valid at load-time, if you know you're going to mess it upp later. So really, if that's your only concern, do add this span declaratively in your HTML, rather than injecting it later.
But if you want to fix this, I think it might help if you rewrite the regex to cover the entire tag. In a lot of cases, IE doesn't let you just change the HTML to whatever, but will use its own internal representation to fix up the code, according to its own preferences. When you write a table, for instance, IE will always internally infer a tbody, even if there isn't any in the code. In the same manner, if you inject a <span> and there's no </span>, IE might insert one by itself. To get around this, make sure you inject the code in its entirety in one go:
$(this).html($(this).html().replace(/\((.*?)\)/g,"<span>($1)</span>"));
I don't have IE7 but in IE6 the following
javascript:"<select><option>ABC (123)</option><option>XYZ (789)</option></select>".replace(/\(/g,"<strong>(")
yields
<select><option>ABC <strong>(123)</option><option>XYZ <strong>(789)</option></select>
And gets correctly displayed (aside that <strong> has no effect). Also works fine when using <span> instead of <strong>

innerHTML alternative for retrieving contents of page?

I'm currently using innerHTML to retrieve the contents of an HTML element and I've discovered that in some browsers it doesn't return exactly what is in the source.
For example, using innerHTML in Firefox on the following line:
<div id="test"><strong>Bold text</strong></strong></div>
Will return:
<strong>Bold text</strong>
In IE, it returns the original string, with two closing strong tags. I'm assuming in most cases it's not a problem (and may be a benefit) that Firefox cleans up the incorrect code. However, for what I'm trying to accomplish, I need the exact code as it appears in the original HTML source.
Is this at all possible? Is there another Javascript function I can us?
I don't think you can receive incorrect HTML code in modern browsers. And it's right behaviour, because you don't have source of dynamicly generated HTML. For example Firefox' innerHTML returns part of DOM tree represented in string. Not an HTML source. And this is not a problem because second </strong> tag is ignored by the browser anyway.
innerHTML is generated not from the actual source of the document ie. the HTML file but is derived from the DOM object that is rendered by the browser. So if IE somehow shows you incorrect HTML code then it's probably some kind of bug. There is no such method to retrieve the invalid HTML code in every browser.
You can't in general get the original invalid HTML for the reasons Ivan and Andris said.
IE is also “fixing” your code just like Firefox does, albeit in a way you don't notice on serialisation, by creating an Element node with the tagName /strong to correspond to the bogus end-tag. There is no guarantee at all that IE will happen to preserve other invalid markup structures through a parse/serialise cycle.
In fact even for valid code the output of innerHTML won't be exactly the same as the input. Attribute order isn't maintained, tagName case isn't maintained (IE gives you <STRONG>), whitespace is various places is lost, entity references aren't maintained, and so on. If you “need the exact code”, you will have to keep a copy of the exact code, for example in a JavaScript variable in a <script> block written after the content in question.
If you don't need the HTML to render (e.g., you're going to use it as a JS template or something) you can put it in a textarea and retrieve the contents with innerHTML.
<textarea id="myTemplate"><div id="test"><strong>Bold text</strong></strong></div></textarea>
And then:
$('#myTemplate').html() === '<div id="test"><strong>Bold text</strong></strong></div>'
Other than that, the browser gets to decide how to interpret the HTML and it will only return you it's interpretation, not the original.
innerTEXT ? or does that have the same eeffect?
You must use innerXML property. It does exactly what you want to achieve.

Categories