IE doesn't recognise Javascript Class and breaks - javascript

I wrote some Javascript code that works perfectly in all major browsers. Of course I made sure that none of this would be executed by Internet Explorer by creating a function that figures out what browser the user is using.
Here's the problem however: Even if I told IE not to execute the code, the browser still reads all of my Javascript and since it finds something it doesn't recognise it stops running any other Javascript.
The only thing I could think of doing was creating a function that would return if the user is using IE, but that doesn't seem to work since I think the problem comes from IE initially parsing my script and not being able to understand modern JS syntax.
Here's a simplified version of my code:
class Section {
constructor(dom, startPosition, endPosition, backgroundPosition) {
this.dom = dom;
this.startPosition = startPosition;
this.endPosition = endPosition;
this.backgroundPosition = backgroundPosition;
}
}
function isIE() {
ua = navigator.userAgent;
/* MSIE used to detect old browsers and Trident used to newer ones*/
var is_ie = ua.indexOf("MSIE ") > -1 || ua.indexOf("Trident/") > -1;
return is_ie;
}
let sections = [];
function sectionParallax() {
if (!isIE()) {
sections.push( new Section("test", 123, 123, 123))
}
}
IE's console reports:
SCRIPT1002: Syntax error
On class Section.
I'm completely out of ideas on what to do here. How do I make sure IE doesn't load this part of the code?

JavaScript classes and constructor not support IE browser, so, in the IE browser, it will show the "SCRIPT1002: Syntax error" error.
You could modify your code as below:
var Section = /** #class */ (function () {
function Section(dom, startPosition, endPosition, backgroundPosition) {
this.dom = dom;
this.startPosition = startPosition;
this.endPosition = endPosition;
this.backgroundPosition = backgroundPosition;
}
return Section;
}());
function isIE() {
ua = navigator.userAgent;
/* MSIE used to detect old browsers and Trident used to newer ones*/
var is_ie = ua.indexOf("MSIE ") > -1 || ua.indexOf("Trident/") > -1;
return is_ie;
}
var sections = [];
function sectionParallax() {
if (!isIE()) {
/*If not using IE browser. */
var newsection = new Section("test", 123, 123, 123);
sections.push(newsection);
}
}

The JS parser has to parse the JavaScript you tell it to load, even if it is a function that never executes.
If you want to stop IE from loading it, then don't load the <script> which contains it. This means you need to dynamically add the <script> if the browser does support the feature.
If you need to support IE, then don't deliver JS to the browser that uses syntax IE doesn't recognise. Consider using a tool like Babel to transpile it to an older version of JavaScript which IE does support.

You could check for IE before loading the script with a Conditional Comment :
<!--[if !IE]>-->
<script src="script.js"></script>
<!--<![endif]-->

Related

JS Bookmarklets: Increase/decrease site's font size

I was using the code from here to enlargen sites:
var p=document.getElementsByTagName('*');
for(i=0;i<p.length;i++) {
if(p[i].style.fontSize){
var s=parseInt(p[i].style.fontSize.replace("px",""));
}
else {
var s=12;
}
s+=2;
p[i].style.fontSize=s+"px"
But this has recently stopped working on my Chrome (Version 81.0.4044.138 (Official Build) (64-bit)). I am curious as to why, and any working alternatives.
ٍٍExplaining "stopped working": After using it, the page goes blank, and sometimes shows "14px":
This article from 2ality says
Finish with undefined: If you don’t return (or finish with!) undefined, the result replaces the current web page. [Note: Webkit browsers such as Chrome and Safari never replace a page, only non-Webkit browsers such as Firefox do.]
but Chrome has changed this behavior.
Chrome now runs a code like
if (typeof bookmark_reslt === "string") {
document.body.innerHTML = bookmark_reslt
}
A minimal reproducible example of the bookmarklet is javascript: "14px"
The easiest solution is to add undefined in the end of the script.
Firefox executes a code like document.body.innerHTML = String(bookmark_reslt)
// examples to see how `toString` affects Bookmarklets in Firefox
javascript: a = {}; a; // <body>[object Object]</body>
javascript: a = {}; a.toString = ()=> 2; a; // <body>2</body>

Check for "-ms-expand" support

i'm trying to make a little script to style "select" tags in my html testing for the support of the "appearance" style property:
if ("webkitAppearance" in select.style ||
"MozAppearance" in select.style ||
"oAppearance" in select.style ||
"appearance" in select.style ||
"-ms-expand" in select.style) {
return;
}
// else apply wrapper and style it.
The problem is that i don't know how to check for -ms-expand property, because it's not working and i don't want to user browser version sniffing in this case.
You can't check -ms-expand in javascript, because it is pseudo-element, and it do not affect to content. You can't detect it like ::before/::after in Modernizr, but -ms-expand is enabled in IE 10+, so better will be to detect is IE 10 or higher by javascript:
Detection IE 11:
!window.ActiveXObject && "ActiveXObject" in window
Detection IE 10:
var isIE10 = false;
/*#cc_on
if (/^10/.test(#_jscript_version)) {
isIE10 = true;
}
#*/
Not the most optimal solution in terms of performance, but you could try this:
var expandSupport = (function(){
try{
var style = document.createElement("style");
style.textContent = "#ie10-test::-ms-expand{ }";
document.body.appendChild(style);
var supported = !!style.sheet.rules.length;
document.body.removeChild(style);
return supported;
} catch(e){ return false; }
}());
document.body.appendChild(document.createTextNode(expandSupport ? "Your browser appears to support the -ms-expand pseudo-element" : "Your browser doesn't appear to support the -ms-expand pseudo-element"));
Fiddle here.
The reason this works is because browsers will discard any selectors they don't support or can't interpret, which means any browser that doesn't understand what the "::-ms-expand" pseudo-element is probably isn't IE10 or up.
Essentially, all that this code is doing is creating a dummy <style> tag, adding a ruleset that only IE10+ is expected to support, and reporting back the number of rules found in it.

Class Name not getting changed in IE 7, 8 and chrome

I am trying to change class name of two elements during onload.
Here is my code for the same :
var browserName=navigator.appName;
var tfElem = document.getElementById("TTlExpct");
var blTfElem = document.getElementById("BTLExpct");
if (browserName=="Microsoft Internet Explorer")
{
tfElem.className ="pn-tf";
blTfElem.className ="pn-tf active";
}
else
{
tfElem.setAttribute('class', 'pn-tf');
blTfElem.setAttribute('class', 'pn-tf active');
}
The else block takes care of the code if its not IE, in mozilla, this is working fine, class name is getting set.
Its not working in IE7 and IE8
and
in chrome, it works only if i reload the page again.
Any help will be appreciated .
There is a bug in the implementation of setAttribute in old versions of IE. In newer versions of IE that bug may be emulated if you do not use a Doctype that triggers standards mode.
Replace:
foo.setAttribute('class', value);
With:
foo.className = value;
Do this everywhere. Don't try to do browser detection. All browsers that support setAttribute('class', value) also support foo.className = value.
The code in your question should be rewritten as:
var tfElem = document.getElementById("TTlExpct");
var blTfElem = document.getElementById("BTLExpct");
tfElem.className ="pn-tf";
blTfElem.className ="pn-tf active";

JavaScript: The best way to detect IE

Reading this article I've found a following piece of code:
if ('v'=='\v') { // Note: IE listens on document
document.attachEvent('onstorage', onStorage, false);
}
Is this method 'v'=='\v' a great idea? Is this the shortest way to detect IE ever?
You can check for Trident, IE's engine, by the following:
var trident = !!window.ActiveXObject;
As stated on MSDN it is only supported in IE.
Edit:
Note: above code returns false in IE-11, If you want to detect also IE-11 use this:
var isIE = "ActiveXObject" in window; //window.ActiveXObject !== undefined;
If you can avoid it, don't test for browsers. Do feature detection. This will mean that your code is (more likely to be) future-proof. In this case, for instance, if you discovered that the browser was IE and decided to use attachEvent because of it, you would miss out on the fact that addEventListener (superior) is available in IE9.
In this case, test to see if document.addEventListener exists. If it does, you have the answer.
if (document.addEventListener) {
document.addEventListener(...);
} else {
document.attachEvent(...);
}
Edit: duri's comment above shows that this test fails in IE9 (as per standards), which actually means it is a perfect test for addEventListener, since that is available from IE9. However it is still far, far better to program for specific functionality, rather than specific browsers.
To check if the browser is Internet Explorer, use feature detection to check for documentMode:
http://msdn.microsoft.com/en-us/library/ie/cc196988%28v=vs.85%29.aspx
This code checks to see if the browser is Internet Explorer 8, 9, 10, or 11:
var docMode = document.documentMode,
hasDocumentMode = (docMode !== undefined),
isIE8 = (docMode === 8),
isIE9 = (docMode === 9),
isIE10 = (docMode === 10),
isIE11 = (docMode === 11),
isMsEdge = window.navigator.userAgent.indexOf("Edge/") > -1;
// browser is IE
if(hasDocumentMode) {
if(isIE11){
// browser is IE11
} else if(isIE10){
// browser is IE10
} else if(isIE9){
// browser is IE9
} else if(isIE8){
// browser is IE8
}
} else {
// document.documentMode is deprecated in MS Edge
if(isMsEdge){
// browser is MS Edge
}
}
Checking document.documentMode will only work in IE8 through IE11, since documentMode was added in IE8 and has been deprecated / removed in MS Edge.
http://msdn.microsoft.com/en-us/library/ff406036%28v=vs.85%29.aspx
I hope this helps!
UPDATE
If you really need to detect IE7, check for document.attachEvent:
var isIE7 = (document.attachEvent !== undefined);
if(isIE7) {
// browser is IE7
}
IE7 returns a object, but if the browser is IE11 (for example), then this would come back as undefined, since IE11 does not have attachEvent.
UPDATE:
Added check for MS Edge. document.documentMode was deprecated in MS Edge. Due to the nature of MS Edge, you can check for Edge/ in the User Agent. Microsoft is making it difficult to use feature detection in MS Edge.
The JavaScript includes() method is not supported in IE11 and earlier. So you can use code to check whether if the includes() method is supported. This can work for all versions of IE. But the includes method isn't for early versions of Chrome, Firefox, Safari, and Opera. This may not be the most efficient way to detect IE.
var aString = "something";
if(!aString.includes){
alert("You are using IE");
} else {
alert("You are not using IE");
}

Why would this code work in IE and fail in Firefox and Chrome?

So loading up our new web application in Firefox and Chrome I had an alert subtly tell me that a tabStrip couldn't be found. Following through the code I found this function:
function initializeTabStrip() {
var tblList = document.getElementsByTagName("table");
var tabStrip = null;
for (var i = 0; i < tblList.length; ++i) {
if (typeof (tblList[i].tabStripRoot) != "undefined") {
tabStrip = tblList[i];
break;
}
}
if (tabStrip) {
window.tabStrip = new TabStrip(tabStrip);
}
else {
alert("couldn't find tabstrip");
}
}
In both Firefox and Chrome, typeof (tblList[i].tabStripRoot) comes up to be undefined, whereas in Internet Explorer the same section of code will find an item, and follow through correctly.
I've tried using Firebug and IE's developer toolbar script debugging tool to follow through and attempt to discover what 'tabStripRoot' is, but I haven't had any luck.
Would any of you JavaScript guru's be able to give me some direction into why one out of three browsers works?
Thanks for your help.
You're relying on IE's non-standard ability to access arbitrary attributes as properties of DOM elements.
In standards-compliant browsers, you cannot write someElement.tabStripRoot to access the tabStripRoot attribute.
Change it to tblList[i].getAttribute('tabStripRoot').

Categories