Cross browser support for document.write() - html

I have an HTML Document object assigned to variable var doc. Using this document object i am rendering string values to a text file where values are getting rendered and written but in an improper format in IE11 browser but working fine in IE8,IE10,ff n chrome.Please find my below code:
function savecontent(str){
var filename = "data.txt";
var str=replaceAll(str,'<doublequote>','"');
var w = window.frames.w;
if( !w )
{
w = document.createElement( 'iframe' );
w.id = 'w';
w.style.display = 'none';
document.body.insertBefore( w,null );
w = window.frames.w;
if( !w )
{
w = window.open( '', '_temp', 'width=100,height=100' );
if( !w )
{
window.alert( 'Sorry, could not create file.' ); return false;
}
}
}
var doc = w.document;
doc.open('text/plain');
doc.charset="iso-8859-1";
doc.write(str);
doc.close(doc.write(str));
w.close();
if( doc.execCommand( 'SaveAs', false, filename ) )
{
window.alert("Please save the file.");
}
}
Where my str could be something like
employee_firstname,employee_lastname,employee_id,employee_salary,employee accountno,employee_dob etc..
which is rendered in IE11 as,
employee_firstname,employee_lastname,
employee_id,employee_salary,employee accountno,employee_dob
but where as expected is and data is rendered in IE8,ff n chrome in the below format:
employee_firstname,employee_lastname,employee_id,
employee_salary,employee accountno,employee_dob
The different i notice in other browser like IE8,FF n chrome is line break
happening differently in IE11 compared to other browsers.
Can anyone please tell me how to format rendering of data properly in text file in IE11 browser or any alternative to document.write()?

The problem cannot quite be reconstructed from the code supplied, but the heart of the problem seems to be that you are generating a new document to be displayed in an inline frame, using the open() method for a Document object. This is relatively well supported, but only when the created document is an HTML document, not a plain text document.
When you try to use text/plain format, browsers handle things differently. They actually create an HTML document, placed in the DOM tree of the creating document. It contains a body part that either has just the text you have written or a pre element wrapper around it, causing it to be displayed as-is. For example, old versions of IE generate the pre element, IE 11 does not. It might be argued that IE 11 does the right thing: being plain text does not mean that text should be rendered as-is with respect to division into lines.
Anyway, the way to avoid this is to generate an HTML document and insert the pre wrapper with your code, provided that you wish to display the text as-is:
doc.open('text/html');
doc.write('<pre>' + str + '</pre>');

Related

Copying text with a new line to <input type="text"/> not working in IE

My problem is the following:
I have an input, simple as that:
<input type="text"/>
And when I try to paste some text that contains a new line in it, all the text after the new line does not appear.
Now I know this type of input shouldn't support such behavior, and the best scenario is to use a textarea but that would be hardly achievable in the current project I am working on.
However, other browsers convert the new line to a space character and append the text after the new line so you eventually get the whole text in a single line. IE doesn't do that.
I have found the following solution to intercept paste event and I thought maybe I can use it to transform the string into a single-lined but it doesn't work in firefox. I can try a browser detection but I am afraid it can fail in many other scenarios as well.
Is there something else that I can do to make IE behave like other browsers and what are my best options?
I found this answer that might be the solution to your problem:
JavaScript get clipboard data on paste event (Cross browser)
It should work in IE6+, FF 22+, Chrome & Safari.
HTML
<input id='editableDiv' contenteditable='true' type="text"/>
JavaScript
function handlePaste (e) {
var clipboardData, pastedData;
// Stop data actually being pasted into input field
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Remove new line characters
alert(pastedData);
var res = pastedData.replace(/\r?\n|\r/g, );
}
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
Hope this helps mate.
Thanks for your answer George K - yours was the base for my solution. I had a few remaining problems to get past:
addEventListener was giving me 'element not found'
concatenated value wasn't populating the field
So I ended up with these slight modifications to your javascript:
function handlePaste(e) {
var clipboardData, pastedData;
// Stop data actually being pasted into input field
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Remove new line characters
var res = pastedData.replace(/\r?\n|\r/g, ' ');
document.getElementById(e.target.id).value = res; // <- added this to populate value
}
// added this also - this fixed my 'element not found' error
window.addEventListener('load', function () {
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
})
BTW, I am using an <asp:textbox> instead of an <input> element.
This works for me in both IE (11) and Chrome (83.x).

Preserve highlight when copy from Ace Editor

I am using Ace Editor in my web app. Wonder if it's possible to copy the text inside Ace Editor to clipboard with highlight. With default configurations, if I copy the selected text in Ace Editor to clipboard, it seems that only text content is copied with no html styles.
Thanks a lot for your help!
Unfortunately there is no api for this. you'll need to modify https://github.com/ajaxorg/ace/blob/v1.2.5/lib/ace/keyboard/textinput.js#L290 to also set text/html mime type to some html, rendered similar to https://github.com/ajaxorg/ace/blob/v1.2.5/lib/ace/layer/text.js#L442.
Also you'll need to include the css for the theme in the copied html
I know this is late, but this might be helpful for someone like me who stumbled upon this problem this late.
The basic idea is to get the text that is being copied and use Ace's tokenizer to generate HTML from it:
Add an event listener on the copy/cut event on the editor's container.
You can use clipboard object in event to get the data currently being copied: event.clipboardData?.getData('text/plain')
Rest steps are in code below
// get current tokenizer
const tokenizer = aceSession.getMode().getTokenizer();
// get `Text` object from ace , this will help in generating HTML
const Text = ace.require('ace/layer/text').Text;
// create a wrapper div, all your resultant HTML will come inside this
// also this will contain the basic HTML required to initialize the editor
const root = document.createElement('div');
// this is the main magic object
const rootText = new Text(root);
lines.forEach(line => {
// this converts your text to tokens
const tokens = tokenizer.getLineTokens(line, 'start') as any;
const leadingSpacesCount = (line.match(/^\s*/) || [])[0].length;
const lineGroupEl = document.createElement('div');
lineGroupEl.className = 'ace_line_group';
const lineEl = document.createElement('div');
lineEl.className = 'ace_line';
const spaceSpan = document.createElement('span');
if (tokens && tokens.tokens.length) {
//////////////////////////////////////////////////////
// Magic Happens here, this line is responsible for converting our tokens to HTML elements
rootText.$renderSimpleLine(lineEl, tokens.tokens);
//////////////////////////////////////////////////////
// Leading spaces do not get translated to HTML, add them separately
spaceSpan.innerHTML = ' '.repeat(leadingSpacesCount);
lineEl.insertBefore(spaceSpan, lineEl.children[0]);
} else {
spaceSpan.innerHTML = ' ';
lineEl.appendChild(spaceSpan);
}
lineGroupEl.appendChild(lineEl);
// `root` has a wrapper div, inside which our main div (with class "ace_layer ace_text-layer") lies
root.children[0].appendChild(lineGroupEl);
});
return root.innerHTML;
Now finally, in your eventlistener you can wrap this with any div to give your own custom color to it, and put it to clipboardData with text\html mime type:
event.clipboardData?.setData('text/html', htmlContent);

html5 template tag: fallback for content access

I am using a template tag in a webkit browser (JavaFX WebView 2.2) to store elements that I may clone and append on the main part of the document.
However, I can't access its content using templateElement.content (the HTML5 standard). Instead, I use jQuery to get the elements inside the template TAG with the selector "#templateElement div".
Seems the template tag is not yet fully supported (inner scripts also run), although its contents are not rendered.
My fear is that, when the template tag becomes supported, the way to get its contents will break and my page will stop working.
What is the recommended way of getting template contents regardless future implementation changes?
HTML:
<template id="templateElement">
<div>Clone Me!</div>
</template>
JavaScript:
function getContentsCurrent() {
var toBeCloned = $("#templateElement div")[0];
//append where needed...
}
function getContentsFuture() {
var toBeCloned = templateElement.content.getElementsByTagName("div")[0];
//append where needed...
}
EDIT
I think jQuery won't be able to handle this automatically, even in the future, because the template "innerHTML" is purposely routed to content so that it becomes inaccessible to the DOM (so no selector touches it accidentally).
You could test if the content feature exists before:
function getContents() {
var toBeCloned;
if ( templateElement.content )
toBeCloned = templateElement.content.getElementsByTagName("div")[0];
else
toBeCloned = templateElement.querySelector("div");
//append where needed...
}
Another way:
var content = templateElement.content || templateElement
var toBeCloned = content.querySelector( "div" )
//...

Base64 image tag in safari did not showed up

I made a tsp which decode Image to base64 byte array String.
It works in Chrome and Firefox. However in safari 8.0, it does not work.
My jsp looks like below :
String sFileInfo = "";
String name = request.getHeader("file-name");
String ext = name.substring(name.lastIndexOf(".")+1);
InputStream is = request.getInputStream();
byte b[] = IOUtils.toByteArray(is);
String base64DataString = Base64.encodeBase64String(b);
base64DataString = "data:image/" + ext + ";base64," + base64DataString;
if(is != null) {
is.close();
}
And as result code below will be attached to browser.
<p><span style="font-size:48px"><img alt="" src="data:image/jpeg;base64,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" style="height:90px; width:169px" />1<span style="background-color:#00FFFF">zxczxczc</span></span></p>
I copy this code(part of after base64;) and put link below in safari.
http://base64online.org/decode/
and I got an image, so I assume that Safari also support base64 image.
However, when I put this on web with image tags, it does not work.
Thanks for answer :D
PS browser error message is
Failed to load resource: (kCFErrorDomainCFNetwork error -10.)
I know this question is pretty old but I've recently faced a similar problem on iOS' safari, and the problem seems to be that Safari will not render base64 images that does not have a number of character divisible by 4.
The solution to this problem is to pad your encoded string at the end using '=' characters. Here is a basic algorithm:
// b64str = 's/3eea4sp...' (or any base 64 encoded string)
while (b64str.length % 4 > 0) {
b64str += '=';
}
Hope this helps someone !
I was in a similar situation but the posted solution did not work for me. But I did come up with an alternative solution after some trial and error. Hope this helps out.
// Add an actual base64 string
var encodedImgString = 'data:image/png;base64,iVBORw0KGgoAAA...';
// Create an image, set img source and cross origin attribute
var iosImg = new Image;
iosImg.src = encodedImgString;
iosImg.crossOrigin = 'Anonymous';
// Change this to target your element and add it wherever you need it to appear
document.body.appendChild(iosImg);
#SylvainB - I think it needs to be divisible by 3 or 4 to render in Safari
#IHan - make sure to exlude 'data:image/png;base64,' part while doing the divisibility test
Not a fix but I think a more deeper look into this is that safari won't render the base64 at all with the dom loading but will work if you apply it using JS. You can go to inspect and remove your base64 and repost it in the image will load fine.

Can't get same origin iframe body on IE10?

I've created a page with an empty iframe on it. I can then select the iframe document and navigate to it's body:
var iframe = document.getElementsByTagName('iframe')[0];
var doc = iframe.contentDocument || iframe.contentWindow.document;
var body = doc.body;
console.log("Body is", body);
In firefox and chrome this gives me the body object. In IE10 it gives me null.
Here is a Jsbin demonstrating the issue. Open up the JS, Console, Output panels and click "Run With JS".
Two questions:
How do I get access to the iframe's body in a cross-browser manner?
Which is the correct "to-spec" behavior?
I had a similar problem earlier today. It seems IE, at least 9 and 10, doesn't create the iframe body correctly (when I used the developer tools I was able to see a body tag inside the iframe, but like you wasn't able to call it), when there's no specified src. It gives you null cause it doesn't exist.
The answer, to whether there is a cross browser manner to access the iframe's body, is no. BUT, you could use a workaround. First, check if the iframe body exist, if not, then create it.
Your code would look like this:
var iframe = document.getElementsByTagName('iframe')[0];
var doc = iframe.contentDocument || iframe.contentWindow.document;
// The workaround
if (doc.body == null) { // null in IE
doc.write("<body></body>");
}
var body = doc.body;
console.log("Body is", body);
Source: http://forums.asp.net/t/1686774.aspx/1
This code is working for me cross-browser:
var doc=ifr.contentWindow||ifr.contentDocument;
if (doc.document) doc=doc.document;
var body=doc.getElementByTagName("body")[0];
Over a year later but I believe the solution was to call
doc.open()
//make any modifications
doc.close()
//at this point doc.body will not be null
This made things work in a fairly consistent manner cross browser