Browser compatibility error - javascript

I create one web page (which display details in table) using html & js. Which works on firefox but not in IE.
function frontEnd()
{
try{
th1 = document.getElementById('th1');
th1.firstChild.nodeValue = "Technology";
th2 = document.getElementById('th2');
th2.firstChild.nodeValue = "Level of knowledge";
t1 = document.getElementById('t1');
t1.firstChild.nodeValue = "HTML";
tl1 = document.getElementById('tl1');
tl1.firstChild.nodeValue = "5";
document.getElementById('MyTab').style.visibility="visible";
}
catch(e)
{
alert(e);
}
}
th1 is an id of table heading, t1,tl1 are data id. Actually am trying to display static values in table when user clicks button. It works sucessfully in firefox, not in IE. When click button using IE it reflects an error "[Object Error]"
Please tel me how to made the same code to work in IE.
Thanks,
Naveen

Why don't you use JQuery or Prototype JavaScript library , they are cross browser compatible.
Jquery
http://api.jquery.com/first-child-selector/

Related

Copy rendered html with styles to outlook [duplicate]

Is there a way in javascript to copy an html string (ie <b>xx<b>) into the clipboard as text/html, so that it can then be pasted into for example a gmail message with the formatting (ie, xx in bold)
There exists solutions to copy to the clipboard as text (text/plain) for example https://stackoverflow.com/a/30810322/460084 but not as text/html
I need a non flash, non jquery solution that will work at least on IE11 FF42 and Chrome.
Ideally I would like to store both text and html versions of the string in the clipboard so that the right one can be pasted depending if the target supports html or not.
Since this answer has gotten some attention, I have completely rewritten the messy original to be easier to grasp. If you want to look at the pre-revisioned version, you can find it here.
The boiled down question:
Can I use JavaScript to copy the formatted output of some HTML code to the users clipboard?
Answer:
Yes, with some limitations, you can.
Solution:
Below is a function that will do exactly that. I tested it with your required browsers, it works in all of them. However, IE 11 will ask for confirmation on that action.
Explanation how this works can be found below, you may interactively test the function out in this jsFiddle.
// This function expects an HTML string and copies it as rich text.
function copyFormatted (html) {
// Create container for the HTML
// [1]
var container = document.createElement('div')
container.innerHTML = html
// Hide element
// [2]
container.style.position = 'fixed'
container.style.pointerEvents = 'none'
container.style.opacity = 0
// Detect all style sheets of the page
var activeSheets = Array.prototype.slice.call(document.styleSheets)
.filter(function (sheet) {
return !sheet.disabled
})
// Mount the container to the DOM to make `contentWindow` available
// [3]
document.body.appendChild(container)
// Copy to clipboard
// [4]
window.getSelection().removeAllRanges()
var range = document.createRange()
range.selectNode(container)
window.getSelection().addRange(range)
// [5.1]
document.execCommand('copy')
// [5.2]
for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = true
// [5.3]
document.execCommand('copy')
// [5.4]
for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = false
// Remove the container
// [6]
document.body.removeChild(container)
}
Explanation:
Look into the comments in the code above to see where you currently are in the following process:
We create a container to put our HTML code into.
We style the container to be hidden and detect the page's active stylesheets. The reason will be explained shortly.
We put the container into the page's DOM.
We remove possibly existing selections and select the contents of our container.
We do the copying itself. This is actually a multi-step process:
Chrome will copy text as it sees it, with applied CSS styles, while other browsers will copy it with the browser's default styles.
Therefore we will disable all user styles before copying to get the most consistent result possible.
Before we do this, we prematurely execute the copy command.
This is a hack for IE11: In this browser, the copying must be manually confirmed once. Until the user clicked the "Confirm" button, IE users would see the page without any styles. To avoid this, we copy first, wait for confirmation, then disable the styles and copy again. That time we won't get a confirmation dialog since IE remembers our last choice.
We actually disable the page's styles.
Now we execute the copy command again.
We re-enable the stylesheets.
We remove the container from the page's DOM.
And we're done.
Caveats:
The formatted content will not be perfectly consistent across browsers.
As explained above, Chrome (i.e. the Blink engine) will use a different strategy than Firefox and IE: Chrome will copy the contents with their CSS styling, but omitting any styles that are not defined.
Firefox and IE on the other hand won't apply page-specific CSS, they will apply the browser's default styles. This also means they will have some weird styles applied to them, e.g. the default font (which is usually Times New Roman).
For security reasons, browsers will only allow the function to execute as an effect of a user interaction (e.g. a click, keypress etc.)
There is a much simpler solution. Copy a section of your page (element) than copying HTML.
With this simple function you can copy whatever you want (text, images, tables, etc.) on your page or the whole document to the clipboard.
The function receives the element id or the element itself.
function copyElementToClipboard(element) {
window.getSelection().removeAllRanges();
let range = document.createRange();
range.selectNode(typeof element === 'string' ? document.getElementById(element) : element);
window.getSelection().addRange(range);
document.execCommand('copy');
window.getSelection().removeAllRanges();
}
How to use:
copyElementToClipboard(document.body);
copyElementToClipboard('myImageId');
If you want to use the new Clipboard API, use the write method like below:
var type = "text/html";
var blob = new Blob([text], { type });
var data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(
function () {
/* success */
},
function () {
/* failure */
}
);
Currently(Sep 2021), The problem is that Firefox doesn't support this method.
I have done a few modifications on Loilo's answer above:
setting (and later restoring) the focus to the hidden div prevents FF going into endless recursion when copying from a textarea
setting the range to the inner children of the div prevents chrome inserting an extra <br> in the beginning
removeAllRanges on getSelection() prevents appending to existing selection (possibly not needed)
try/catch around execCommand
hiding the copy div better
On OSX this will not work. Safari does not support execCommand and chrome OSX has a known bug https://bugs.chromium.org/p/chromium/issues/detail?id=552975
code:
clipboardDiv = document.createElement('div');
clipboardDiv.style.fontSize = '12pt'; // Prevent zooming on iOS
// Reset box model
clipboardDiv.style.border = '0';
clipboardDiv.style.padding = '0';
clipboardDiv.style.margin = '0';
// Move element out of screen
clipboardDiv.style.position = 'fixed';
clipboardDiv.style['right'] = '-9999px';
clipboardDiv.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
// more hiding
clipboardDiv.setAttribute('readonly', '');
clipboardDiv.style.opacity = 0;
clipboardDiv.style.pointerEvents = 'none';
clipboardDiv.style.zIndex = -1;
clipboardDiv.setAttribute('tabindex', '0'); // so it can be focused
clipboardDiv.innerHTML = '';
document.body.appendChild(clipboardDiv);
function copyHtmlToClipboard(html) {
clipboardDiv.innerHTML=html;
var focused=document.activeElement;
clipboardDiv.focus();
window.getSelection().removeAllRanges();
var range = document.createRange();
range.setStartBefore(clipboardDiv.firstChild);
range.setEndAfter(clipboardDiv.lastChild);
window.getSelection().addRange(range);
var ok=false;
try {
if (document.execCommand('copy')) ok=true; else utils.log('execCommand returned false !');
} catch (err) {
utils.log('execCommand failed ! exception '+err);
}
focused.focus();
}
see jsfiddle where you can enter html segment into the textarea and copy to the clipboard with ctrl+c.
For those looking for a way to do this using ClipboardItem and cannot get it to work even with dom.events.asyncClipboard.clipboardItem set to true, the answer can be found at nikouusitalo.com.
And here is my working code (tested on Firefox 102).
const clipboardItem = new
ClipboardItem({'text/html': new Blob([html],
{type: 'text/html'}),
'text/plain': new Blob([html],
{type: 'text/plain'})});
navigator.clipboard.write([clipboardItem]).
then(_ => console.log("clipboard.write() Ok"),
error => alert(error));
Make sure you try pasting it into a rich text editor such as gmail and not to a plain text/markdown editor such as stackoverflow.

Javascript - Copy string to clipboard as text/html

Is there a way in javascript to copy an html string (ie <b>xx<b>) into the clipboard as text/html, so that it can then be pasted into for example a gmail message with the formatting (ie, xx in bold)
There exists solutions to copy to the clipboard as text (text/plain) for example https://stackoverflow.com/a/30810322/460084 but not as text/html
I need a non flash, non jquery solution that will work at least on IE11 FF42 and Chrome.
Ideally I would like to store both text and html versions of the string in the clipboard so that the right one can be pasted depending if the target supports html or not.
Since this answer has gotten some attention, I have completely rewritten the messy original to be easier to grasp. If you want to look at the pre-revisioned version, you can find it here.
The boiled down question:
Can I use JavaScript to copy the formatted output of some HTML code to the users clipboard?
Answer:
Yes, with some limitations, you can.
Solution:
Below is a function that will do exactly that. I tested it with your required browsers, it works in all of them. However, IE 11 will ask for confirmation on that action.
Explanation how this works can be found below, you may interactively test the function out in this jsFiddle.
// This function expects an HTML string and copies it as rich text.
function copyFormatted (html) {
// Create container for the HTML
// [1]
var container = document.createElement('div')
container.innerHTML = html
// Hide element
// [2]
container.style.position = 'fixed'
container.style.pointerEvents = 'none'
container.style.opacity = 0
// Detect all style sheets of the page
var activeSheets = Array.prototype.slice.call(document.styleSheets)
.filter(function (sheet) {
return !sheet.disabled
})
// Mount the container to the DOM to make `contentWindow` available
// [3]
document.body.appendChild(container)
// Copy to clipboard
// [4]
window.getSelection().removeAllRanges()
var range = document.createRange()
range.selectNode(container)
window.getSelection().addRange(range)
// [5.1]
document.execCommand('copy')
// [5.2]
for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = true
// [5.3]
document.execCommand('copy')
// [5.4]
for (var i = 0; i < activeSheets.length; i++) activeSheets[i].disabled = false
// Remove the container
// [6]
document.body.removeChild(container)
}
Explanation:
Look into the comments in the code above to see where you currently are in the following process:
We create a container to put our HTML code into.
We style the container to be hidden and detect the page's active stylesheets. The reason will be explained shortly.
We put the container into the page's DOM.
We remove possibly existing selections and select the contents of our container.
We do the copying itself. This is actually a multi-step process:
Chrome will copy text as it sees it, with applied CSS styles, while other browsers will copy it with the browser's default styles.
Therefore we will disable all user styles before copying to get the most consistent result possible.
Before we do this, we prematurely execute the copy command.
This is a hack for IE11: In this browser, the copying must be manually confirmed once. Until the user clicked the "Confirm" button, IE users would see the page without any styles. To avoid this, we copy first, wait for confirmation, then disable the styles and copy again. That time we won't get a confirmation dialog since IE remembers our last choice.
We actually disable the page's styles.
Now we execute the copy command again.
We re-enable the stylesheets.
We remove the container from the page's DOM.
And we're done.
Caveats:
The formatted content will not be perfectly consistent across browsers.
As explained above, Chrome (i.e. the Blink engine) will use a different strategy than Firefox and IE: Chrome will copy the contents with their CSS styling, but omitting any styles that are not defined.
Firefox and IE on the other hand won't apply page-specific CSS, they will apply the browser's default styles. This also means they will have some weird styles applied to them, e.g. the default font (which is usually Times New Roman).
For security reasons, browsers will only allow the function to execute as an effect of a user interaction (e.g. a click, keypress etc.)
There is a much simpler solution. Copy a section of your page (element) than copying HTML.
With this simple function you can copy whatever you want (text, images, tables, etc.) on your page or the whole document to the clipboard.
The function receives the element id or the element itself.
function copyElementToClipboard(element) {
window.getSelection().removeAllRanges();
let range = document.createRange();
range.selectNode(typeof element === 'string' ? document.getElementById(element) : element);
window.getSelection().addRange(range);
document.execCommand('copy');
window.getSelection().removeAllRanges();
}
How to use:
copyElementToClipboard(document.body);
copyElementToClipboard('myImageId');
If you want to use the new Clipboard API, use the write method like below:
var type = "text/html";
var blob = new Blob([text], { type });
var data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(
function () {
/* success */
},
function () {
/* failure */
}
);
Currently(Sep 2021), The problem is that Firefox doesn't support this method.
I have done a few modifications on Loilo's answer above:
setting (and later restoring) the focus to the hidden div prevents FF going into endless recursion when copying from a textarea
setting the range to the inner children of the div prevents chrome inserting an extra <br> in the beginning
removeAllRanges on getSelection() prevents appending to existing selection (possibly not needed)
try/catch around execCommand
hiding the copy div better
On OSX this will not work. Safari does not support execCommand and chrome OSX has a known bug https://bugs.chromium.org/p/chromium/issues/detail?id=552975
code:
clipboardDiv = document.createElement('div');
clipboardDiv.style.fontSize = '12pt'; // Prevent zooming on iOS
// Reset box model
clipboardDiv.style.border = '0';
clipboardDiv.style.padding = '0';
clipboardDiv.style.margin = '0';
// Move element out of screen
clipboardDiv.style.position = 'fixed';
clipboardDiv.style['right'] = '-9999px';
clipboardDiv.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
// more hiding
clipboardDiv.setAttribute('readonly', '');
clipboardDiv.style.opacity = 0;
clipboardDiv.style.pointerEvents = 'none';
clipboardDiv.style.zIndex = -1;
clipboardDiv.setAttribute('tabindex', '0'); // so it can be focused
clipboardDiv.innerHTML = '';
document.body.appendChild(clipboardDiv);
function copyHtmlToClipboard(html) {
clipboardDiv.innerHTML=html;
var focused=document.activeElement;
clipboardDiv.focus();
window.getSelection().removeAllRanges();
var range = document.createRange();
range.setStartBefore(clipboardDiv.firstChild);
range.setEndAfter(clipboardDiv.lastChild);
window.getSelection().addRange(range);
var ok=false;
try {
if (document.execCommand('copy')) ok=true; else utils.log('execCommand returned false !');
} catch (err) {
utils.log('execCommand failed ! exception '+err);
}
focused.focus();
}
see jsfiddle where you can enter html segment into the textarea and copy to the clipboard with ctrl+c.
For those looking for a way to do this using ClipboardItem and cannot get it to work even with dom.events.asyncClipboard.clipboardItem set to true, the answer can be found at nikouusitalo.com.
And here is my working code (tested on Firefox 102).
const clipboardItem = new
ClipboardItem({'text/html': new Blob([html],
{type: 'text/html'}),
'text/plain': new Blob([html],
{type: 'text/plain'})});
navigator.clipboard.write([clipboardItem]).
then(_ => console.log("clipboard.write() Ok"),
error => alert(error));
Make sure you try pasting it into a rich text editor such as gmail and not to a plain text/markdown editor such as stackoverflow.

Change is not displayed on page refresh while using IE8

I have written some JavaScript functions that will do 2 things when a button is clicked:
It will change the label of the button to "Deactivate" from "Activate" and vice versa.
The value of the ActiveStatus property will change to 0 from 1 and vice versa.
The code works alright and the change is displayed perfectly in Mozilla Firefox, but whenever I try display the page in IE 8, change is not displayed, although in database, the value changes perfectly.
Here are the JavaScript codes for the button click:
$(function () {
var stat = document.getElementById("stat").value;
//alert(stat);
if (stat == 1)
document.getElementById("butt").value = "Activate";
else
document.getElementById("butt").value = "Deactivate";
});
function activeStatus(ActiveStatus) {
//alert(ActiveStatus);
if (ActiveStatus == 1) {
return "Activate";
}
else
return "Deactivate";
}
function change() {
var butt = document.getElementById("butt").value;
if (butt == 'Deactivate') {
document.getElementById("butt").value = "Activate";
document.getElementById("stat").value = 1;
}
else {
document.getElementById("butt").value = "Deactivate";
document.getElementById("stat").value = 0;
}
}
Also, an exception message I'm getting whenever I'm trying to view the page in IE 8 is:
Microsoft JScript runtime error: Object doesn't support this property or method
I'm getting this error at the Country.js JavaScript file. The place where I'm getting this exception is:
var url = "/Country/GetAllCountry";
var refresh = function () {
$.getJSON(url, {}, function (data) {
self.Countries(data);
});
};
More specifically, in this line:
self.Countries(data);
None of these happen, when I try to run my application in Firefox. All these happen when I try to run my application in IE 8.
Why am I facing this problem????
EDIT-1: I solved my problem partially. The exception:
Microsoft JScript runtime error: Object doesn't support this property or method
was displayed only because 'Countries' was undefined in Country.js. Countries must be a valid observable, but it has to be declared. I simply had to add this line of code next to it, doing the declaration:
self.Countries = ko.observableArray([]);
Now the exception has disappeared, still the page is not refreshed after the button click.
The answer to this problem is in these 5 simple steps:
Select Tools >> Internet Options.
Click the Settings button in Browsing History.
Select the Every time I visit the webpage radio button.
Click OK to close the Settings dialog.
Click OK to close the Internet Options dialog.
It works perfectly now.
Courtesy: Gonzalo (https://stackoverflow.com/users/203766/gonzalo)

IE 10 + jQuery - Not able to use "append" function

I am running an HTML 5 application using the KendoUI framework. Once of the screens deal with XML data that needs to be parsed and processed.
This screen needs to be shown as a popup and that data is shown in a grid inside this popup. To do this, I am calling a function on clicking the "show-popup" button inside which I have the following piece of code :
var tTranslationXML = XMLFromString(_SelectedCategoryValueRecord.DisplayTextTranslation);
.
.
.
// other stuff but nothing that changes "tTranslationXML"
.
.
if (_SelectedCategoryValueRecord.DisplayTextTranslation) // and there are values in the translation field
{
var $language = $(tTranslationXML).find('Language');
var $oldTranslation = $($language).find("en-US");
if ($oldTranslation.length == 0)
$oldTranslation = $($language).find(GetCorrectedCase("en-US"));
if ($oldTranslation.length == 0) {
var $newTranslation = $.createElementNS("en-US").text(_UpdatedDisplayText);
$language.append($newTranslation);
}
}
And if you are wondering what "XMLFromString" is, its nothing but a simple helper to parse the XML data from a string variable
function XMLFromString(pXMLString)
{
if (!pXMLString)
pXMLString = "<Language></Language>";
if (window.ActiveXObject) {
var oXML = new ActiveXObject("Microsoft.XMLDOM");
oXML.loadXML(pXMLString);
return oXML;
} else {
return (new DOMParser()).parseFromString(pXMLString, "text/xml");
}
}
My issue is that this works fine on Chrome and Firefox but I get an error in IE10 when this particular line executes -
"$language.append($newTranslation);"
I am basically trying to append a new translation value to the contents of my variable here.
The error is as follows :
SCRIPT13: Type mismatch
jquery-1.8.3.min.js, line 2 character 71981
Any ideas on how to solve this?
Sorry for the delayed response.
I figured out that the issue was to avoid using the method "createElementNS" and instead use the "createElement" method when creating the parent node. Subsequent appendages to this node do not throw up any issues. However there will issues when you append to a node that was originally created using "createElementNS".
This seems specific to IE10 because the NS method worked fine on chrome, FF and Safari.
Thank you all for the tips and ideas.

How do I get HTML Markup for createRange() in Firefox

I am currently using code similar to this:
try {
// IE ONLY
var theElement = "myElementName";
window.frames[theElement].focus();
var selection = window.frames[theElement].document.selection.createRange();
alert ( selection.htmlText );
} catch(e) {
var selection = window.frames[theElement].document.getSelection();
alert ( selection );
}
As you can see, I am accessing a node from an iframe (no fun already). I am definitely in new territory here, so am sure there are more issues to arise, but right now, I am trying to get Firefox to give me the same result as IE.
In IE, I can access the HTML code of the selection by using the (apparently IE-only) htmlText property of the object returned by createRange(). What I am looking for is the Firefox equivalent to that (or a function that I can use to give me the same result).
Anyone know how to do this?
This works in Firefox 2 and later (untested in earlier versions):
var selection = window.frames[theElement].getSelection();
var range = selection.getRangeAt(0);
var div = document.createElement("div");
div.appendChild(range.cloneContents());
alert(div.innerHTML);

Categories

Resources