Why is String.toLowerCase undefined in Chrome but not Firefox? - javascript

In the Chrome console, String.toLowerCase returns undefined. However in Firefox, it does not.
What's the reason for the difference?
var body = $("body");
body.append(new String(String.toLowerCase).toString());
body.append("<br>");
body.append(String.prototype.toLowerCase.toString());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

String.toLowerCase is one of the Generics that Firefox has allowed for String, Array (and possibly other). They are not defined in any ECMAScript standard and are considered deprecated by Firefox and will be removed.
Extracted from the MDN docs:
String generics are non-standard, deprecated and will get removed near future. Note that you can not rely on them cross-browser without using the shim that is provided below.
See also:
Introduction of Generics in Firefox's JS 1.6
Deprecation announcement (Not sure how much support the site has from Mozilla, so take this one with a grain of salt.)
Deprecation warning implementation ticket

Is this what you are trying to do? Either of these work fine in chrome for me.
let body = $("body");
let str = 'STRING TO LOWER';
body.append(str.toLowerCase());
body.append("<br>");
body.append("ALL CAPS".toLowerCase());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Why can I not name a JavaScript function `all`?

all is not a built-in function or keyword, but why can I not call a function if it is named all?
There is no error message in the debug console, and the function works if I rename it to all2.
Here is the code: tested in chrome and IE10
<!DOCTYPE html>
<head>
</head>
<body>
<script>
function all()
{
alert(1);
}
function all2()
{
alert(2);
}
</script>
<input type="button" value="all1" onclick="all()">
<input type="button" value="all2" onclick="all2()">
</body>
</html>
This should have worked in chrome. However all has been a method in IE until IE11.
[all is no longer supported. Starting with Internet Explorer 11, use getElementById. For info, see Compatibility changes.]
Returns a reference to the collection of elements contained by the object.
via http://msdn.microsoft.com/en-us/library/ie/ms537434(v=vs.85).aspx
I remember using it long ago, early javascript days something like this..
for(i = 0; i < document.all.length; i++){
document.all(i) ...
}
It is deprecated in IE now and not implemented in most other browsers, although may still be considered a reserved name because of how wide reaching legacy code may be.
Update: I was able to track down another SO question, they answered it nicely.
document.all is available only on Internet Explorer, webkit and Opera.
On every other browser all is an undefined property of document object
(and undefined is considered as a false value)
As historical note: many (really many) years ago document.all was used
to tell Internet Explorer from Netscape Navigator so if you meet a
script that is checking if (document.all) ... I strongly suggest to
find a better script :)
-Fabrizio Calderan

IE7 converting bracket notation to . notation in javascript

I have this line of code (where 'e' is a click event):
var type = $(e.currentTarget.parentNode)[0].classList[0];
which is producing this error in IE7 (using Companion.JS to report errors):
'0.classList.0' is null or not an object
I tried the following variations on my code, but get the same result:
var type = $(e.currentTarget).parent()[0].classList[0];
var type = $(e.currentTarget).parent()['0'].classList['0'];
This code works in the latest Chrome and Firefox browsers. Any idea what's going on here?
First check the .length of $(e.currentTarget.parentNode), you might have to add a condition for IE because the currentTarget is inconsistent with other browsers.
Also, classList is not supported in IE.
Code with classList does not work in IE?
parse the .attr('class') or [0].className

Jquery issues on older versions of IE

I have the following statement in document.ready function:
if($("sidebar ").html().trim().length == 0)
{
$("sidebar").append("<p> The sides..</p>");
};
It works fine in IE 9 but as soon as I select IE 8 (browser and document standard), the script stops working and gives the following error:
SCRIPT5007: Unable to get value of the property 'trim': object is null or undefined
application-e51c9eee7d22e9644481115dc1fedd5f.js, line 7 character 17578
I looked at the .js in debug mode and see that my statement above is transformed to:
$("sidebar ").html().trim().length==0&&$("sidebar").append("<p> The sides..</p>")
How do I prevent this error? Please note that I do see that the node is present in the rendered page.
I thought that maybe just having reference to shiv5.html may not be sufficient to take care of the IE idiosyncrasies. So, I have added modernizr.js via sprockets and I have added class="no-js" in my layout. Still no luck in IE <9.
What am I missing? What else can I do to get the favor of Microsoft overlords?
According to MDN, trim isn't available in IE < 9.
You could use $.trim instead:
if($.trim($("sidebar ").html()).length == 0)
{
$("sidebar").append("<p> The sides..</p>");
} // <-- Don't want a semicolon here.
The MDN article lists an alternative if you don't want to find all the instances of trim and correct them. You could use the following to create .trim if it's not natively available:
if(!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g,'');
};
}
Check out this thread. After a quick search it seems that many people are experiencing issues with trim.

Dynamic CSS3 prefix user agent detection

Is there a better way then using jQuery.browser, or equivalents, for determining css 3 prefixes (-moz, -webkit, etc), as it is disencouraged? Since the css is dynamic (the user can do anything with it on runtime), css hacks and style tag hacks can't be considered.
I don't see the issue with using the navigator.userAgent to determine if you need to cater for Webkit / Gecko CSS3 prefixes. Or better yet, just stick with CSS2 until CSS3 becomes a W3C Recommendation.
The reason use of the navigator object is discouraged is because it was used over Object detection when (java)scripting for different browsers, your situation is one where it is fine to use user agent detection, because your'e specifically targeting certain quirks with different rendering engines.
Edit:
Picking up from where cy left off, you can use javascript object detection to detect whether a prefix is used, I made some quick code to do so:
window.onload = function ()
{
CSS3 = {
supported: false,
prefix: ""
};
if (typeof(document.body.style.borderRadius) != 'undefined') {
CSS3.supported = true;
CSS3.prefix = "";
} else if (typeof(document.body.style.MozBorderRadius) != 'undefined') {
CSS3.supported = true;
CSS3.prefix = "-moz-";
} else if (typeof(document.body.style.webkitBorderRadius) != 'undefined') {
CSS3.supported = true;
CSS3.prefix = "-webkit-";
}
if (CSS3.supported)
if (CSS3.prefix == "")
alert("CSS3 is supported in this browser with no prefix required.");
else
alert("CSS3 is supported in this browser with the prefix: '"+CSS3.prefix+"'.");
else
alert("CSS3 is NOT supported in this browser.");
};
Remember to watch out for strange quirks such as -moz-opacity which is only supported in older versions of Firefox but has now been deprecated in favour of opacity, while it still uses the -moz- prefix for other new CSS3 styles.
Array.prototype.slice.call(
document.defaultView.getComputedStyle(document.body, "")
)
.join("")
.match(/(?:-(moz|webkit|ms|khtml)-)/);
Will return an array with two elements. One with dashes and one without dashes, both lowercase, for your convenience.
Array.prototype.slice.call(
document.defaultView.getComputedStyle(document.body, "")
);
Without the browser check will return an array of nearly all the css properties the browser understands. Since it's computed style it won't display shorthand versions, but otherwise I think it gets all of them. It's a quick hop skip and a jump to auto detect whatever you need as only vendor prefixed stuff starts with a dash.
IE9, Chrome, Safari, FF. Opera won't let you slice CSSStyleDeclaration for you can still use the same getComputedStyle code and loop through the properties or test for a specific one. Opera also wanted to be the odd man out and not report the vendor prefix dasherized. Thanks Opera.
Object.keys(CSSStyleDeclaration.prototype)
Works in IE9 and FF and reports the TitleCased (JavaScript) version of the vendor property names. Doesn't work in WebKit as the prototype only reports the methods.
Here's an interesting and very dangerous function I just wrote along these lines:
(function(vp,np){
Object.keys(this).filter(function(p){return vp=vp||p.match(/^(Moz|ms)/)}).forEach(function(op){
this.__defineGetter__(np=op.replace(vp[0], ""), function() { return this[op] });
this.__defineSetter__(np, function(val) { this[op] = val.toString() });
}, this);
}).call(CSSStyleDeclaration.prototype);
I didn't test anything Konquerer.
It's adding in another library, but would Modernizr work for you? It adds CSS classes to the <html> tag that can tell you what the browser supports.
It does muddy up the code a bit, but can certainly be helpful in appropriate situations.
Speculatively: Yes. You can try adding a vendor prefix css rule (that's what they're called), and then test to see if that rule exists. Those vendor-specific rules won't be added to the DOM in browsers in which they're not supported in some cases.
For example, if you try adding a -moz rule in webkit, it won't add to the DOM, and thus jQuery won't be able to detect it.
so,
$('#blah').css('-moz-border-radius','1px');
$('#blah').css('-moz-border-radius') //null in Chrome
Conversely,
$('#blah').css('-webkit-border-radius','1px');
$('#blah').css('-webkit-border-radius'); //returns "" in Chrome
This method works in WebKit browsers; I'm testing to see if it works in others. Pending.
Edit: Sadly, this isn't working in Firefox or Opera, which just returns "" no matter compatibility. Thinking of ways to do this cross-browser...
Final Edit: Andrew Dunn's answer does this in a way that works (at least in FF and Webkit, which is better than my method).
I use ternary operator to have it only in 1 line. If it's not webkit nor gecko, I'll just use the standard property. If it has no support, who really cares then?
var prefix = ('webkitAnimation' in document.body.style) ? '-webkit-' : ('MozAnimation' in document.body.style? '-moz-' : '');
Basically I found Animation is one of the properties never changed. As soon as the browser starts supporting the Draft / Candidate Recommendation of a CSS3 property, it drops the prefix on JS side. So you will need to be careful and take in mind that, before copy-pasting.

A weird regex problem

The following code results in "undefined" for lastIndex:
var a = /cat/g;
var l = "A test sentence containing cat and dog.";
var r = a.exec(l);
document.write(r.lastIndex);
However, it works perfectly for r.index (and r.input).
I am using Firefox. Does anybody have a clue?
EDIT: OK, the above code works perfectly in IE! Further, in Firefox, it works perfectly if instead of calling r.lastIndex on line 5, a.lastIndex is called. It appears that Firefox does not return lastIndex property in the result - rather sets the property for the pattern invoking the exec() only. Interesting that IE sets both.
This is one of those places where Microsoft decided to add some stuff to the language and act as if it was supposed to be there. Thankfully, they are now cleaning up their act and documenting such nonsense.
To be clear: Firefox is correct according to the ECMAScript Language Specification 3rd Edition (PDF, 705KB).
IE is not correct; its behaviour is a proprietary extension. There is no reason to believe that this IE-specific behaviour will ever be supported by any other browser. It certainly isn't at the moment. See JScript Deviations from ES3 (PDF, 580KB, by Pratap Lakshman of Microsoft Corporation) Section 4.6 for more on this particular deviation from the spec, including tests showing no support on other browsers.
Note also that this may not even be supported in the future by IE: a number of proprietary IE CSS-related mechanisms are disabled by default on IE8-in-IE8-mode, and future implementations of JScript may find a reason to similarly disable this extension to the language.
lastIndex is a property of a RegExp object. So try this:
a.lastIndex
To avoid all the weird, try this
var a = /cat/g;
var l = "A test sentence containing cat and dog.";
var r = a.exec(l);
var lastIndex = (r!=null) ? l.indexOf(r[0])+r[0].length : 0;
It is used here: http://www.pagecolumn.com/tool/regtest.htm

Categories