when get a element's style, we always use
if(document.defaultView && document.defaultView.getComputedStyle) to check whether the browser support the method or not.
why not use if(window.getComputedStyle)?
So in short, the reason why we use document.defaultView && document.defaultView.getComputedStyle is that we want a cross-browser working-on-every-element method of checking whenever it supports fetching computed styles.
Simple if(window.getComputedStyle) would fail for iframes in Firefox 3.6 (according to article linked in comment by Alex K.).
According to the MDN defaultView is no longer required
In many code samples, getComputedStyle is used from the document.defaultView object. In nearly all cases, this is needless, as getComputedStyle exists on the window object as well. It's likely the defaultView pattern was a combination of folks not wanting to write a testing spec for window and making an API that was also usable in Java.
There was a bug in Firefox 3.6 (2010/2011) that needed defaultView fix
Related
Case: e is of type HtmlElement and not css selector
I am talking about any attribute, not just standard allowed ones, like atom-type or data-atom-type, whatever may be the name, will it work without jQuery?
I suspect $(e).attr(name,value) is too slow, first of all it is creating an entire jQuery object ($(e) !== $(e) // two objects are not same) (jsPerf: http://jsperf.com/jquery-attr-vs-native-setattribute/28) and then it invokes certain checks and then sets value, which most browsers easily support e.setAttribute.
Is there any problem replacing $(e).attr(name,value) to e.setAttribute(name,value)?
IE8 supports setAttribute as per MSDN documentation. Is there any mobile browser or any browser which will not support it?
Eventually I want to improve performance of my JavaScript framework, initially we used jQuery extensively for its cross browser DOM features.
We have now understood that unless you are using css selector, most functions such as attr,val,text are better called with their direct DOM counter part when you have instance of HtmlElement.
I suspect $(e).attr(name,value) is too slow, first of all it is creating an entire jQuery object and then it invokes certain checks and then sets value, which most browsers easily support e.setAttribute.
If you measure it, you'll find that the difference in performance is large-ish in relative terms, but miniscule in absolute terms, and it's absolute terms we normally care about. It just doesn't matter in 99.999999% of cases. If you run into a specific performance problem, and trace it to using jQuery, then consider optimizing at that point.
what is benefit of $(e).attr(name,value) vs e.setAttribute(name,value)?
In the specific case you mention, where e is an HTMLElement, there are only a couple of benefits:
There are a couple of IE-specific bugs in setAttribute that jQuery works around for you
There are some "attributes" people set when they really should be setting a property, for instance checked or disabled; jQuery maps those (this is mostly a legacy feature these days, as people should be using prop)
It does some pre-processing on boolean values for you, letting you use $(e).attr("checked", true) when true really should be "checked"
IE8 supports setAttribute as per MSDN documentation. Is there any mobile browser or any browser which will not support it?
All browsers support setAttribute. As I mention earlier, various versions of IE have had various bugs in it, but it's there and mostly works.
I'm in the process of refactoring some code that someone else wrote. There is function that uses:
!!('ontouchstart' in window)
I've seen this used in other projects: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js#L40
And in a Stackoverflow answer: https://stackoverflow.com/a/4819886/1127635
But it seems like it could be slower than alternatives: http://jsperf.com/hasownproperty-vs-in-vs-undefined/12
So why use this possibly slower alternative? What browsers don't support other solutions?
Both of your alternative tests are flawed in some way:
window.ontouchstart !== null tests for a non-null listener. Testing the value of ontouchstart is a risky approach because libraries or other code might change the value of ontouchstart. Testing the value is a bad approach; it would be much better to test for the existence of the property itself, which brings us to your next proposed test...
window.hasOwnProperty('ontouchstart') tests if the window object has its own ontouchstart property. In some browsers (I've just confirmed this on Chrome 37 and IE9), window doesn't have its own on-event properties; instead, they are properties of window.__proto__.
We shouldn't test for a value (because previous code may have changed the value before we run our code) and we can't test for window's own property, because browser differ in their implementation of where event listener properties exist in window's prototype chain. So, our most consistent option is to test whether the property exists (regardless of value) anywhere in window's prototype chain. This is exactly what we do with the in operator.
Of course, if someone else's code runs before our test, they could add an ontouchstart property where there originally wasn't one. Testing support for events with absolute rigor simply isn't possible and it's an awful business.
I recently faced a problem with determining browsers' support for certain DOM features. One of them was Element.children feature, which is still causing me headache. I have the following line in my code:
var NATIVE_CHILDREN = Element.prototype.hasOwnProperty('children');
It is supposed to check if the browser supports Element.children -feature [https://developer.mozilla.org/en/DOM/Element.children].
According to MDN and quick testing, all the major browsers support this feature.
On Firebug on Firefox, value of NATIVE_CHILDREN is expectedly true. Surprisingly, on Chrome, Safari and Opera the value is false (unfortunately I don't have accees to machine with Windows to check what IE thinks about it).
According to DOM4 - Free Editor's Draft 5 April 2012 [http://dom.spec.whatwg.org/#element], children should be part of Element object's prototype. Apperantly Chrome's, Safari's and Opera's Element object doesn't contain such a method!
I have tried checking the prototypes of HTMLCollection and Node (I also tested HTMLParagraphElement and HTMLBodyElement), but none of them seem to contain method called 'children' (except on Firefox). How can I make my test to work cross-browser? I don't want to use any external libraries for this, because this is for my own little library.
I think the reason why this test might return false on Chrome is that you're checking on the prototype. This is not the best way, for several reasons:
Different browsers can (and do) use different implementations of the prototype, some prototypes are not accessible in IE for instance. In this case, I'd say your issue is the result of chrome relying on the (non standard) __proto__ property rather then prototype. I can't remember when, but I had a similar issue with chrome, and this was the source if the problem.
AFAIK all browsers have a children property for their elements, though they behave differently in some cases, so I have some doubt as to the use of checking the existence of such a property.
If you still want to check this, why not use document.body.hasOwnProperty('children')? Returns true on FF, Chrome, Safari and IE.
That's because some engines only slap on the children attribute on element creation. A quick test in the Chrome console shows that:
Element.prototype.hasOwnProperty( 'children' ); //false
//however,
document.createElement( 'foo' ).hasOwnProperty( 'children' ); //true
//or even
!!document.createElement( 'foo' ).children; //true
Non-function properties often don't appear on the prototype, for a simple reason - they aren't set yet, and it doesn't make sense if they will be. Element.prototype doesn't have any children, because it's not an element, it's a prototype for elements.
It is safer to check if( 'children' in document.body) than to mess around with prototypes. Important to note the quotes, if not a variable children might be used/created...
According to QuirksMode, all browsers support children except Firefox 3 (which is a surprise to me, since it worked when I tested in that browser...), so there should be no need to test for this property.
There are lots of DOM/CSS inconsistencies between browsers. But how many core JS differences are there between browsers? One that recently tripped me up is that in Firefox, setTimeout callback functions get passed an extra parameter (https://developer.mozilla.org/en/window.setTimeout).
Also, now that browsers are implementing new functions (e.g. Array.map), it can get confusing to know what you can/can't use if you are trying to write code that must work on all browsers (even back to IE6).
Is there a website that cleanly organizes these types of differences?
I find QuirksMode and WebDevout to have the best tables regarding CSS and DOM quirks. You can bridge those incompatibilities with jQuery. There is also this great list started by Paul Irish which includes pretty much any polyfill you could ever need, including ones for ES5 methods such as Array.map.
There doesn't appear to be anything out there that clearly outlines all these issues (very surprising actually). If you use jQuery there is a nice browser compatibility doc section that outlines supported browsers and known issues. I just deal with issues as they come up (as you should be browser testing in all cases anyways) and you can document them if you want to make sure you are coding correctly or if you run into issues and need to know fixes. It's easy to find issues when you do a quick search on a particular topic.
Well, I'm going to open up a CW:
Prior to Firefox 4 Function.apply only accept an Array, not an array-like object. Ref MDC: Function.apply
Some engines (which ones?) promote the result of String.prototype methods from string to String. Ref a String.prototype's "this" doesn't return a string?
Firefox 4 may insert "event loops" into seemingly synchronous code. Ref Asynchronous timer event running synchronously ("buggy") in Firefox 4?
Earlier Firefox versions would accept a trailing , in object literals. Ref trailing comma problem, javascript (Seems "fixed" in FF6).
Firefox and IE both treat function-expression productions incorrectly (but differently).
Math.round/Math.toFixed. Ref Math.round(num) vs num.toFixed(0) and browser inconsistencies
The IE vs. W3C Event Model -- both are missing events/features of the other.
MDN explains how to use the window.screen object, but also says "DOM Level 0. Not part of specification."
W3Schools says that window.screen.* properties are supported in all major browsers.
If I understand this correctly... window.screen is completely non-standard, but is nonetheless universally supported. Is that right?
If this is the case, are there any cross-browser differences I need to be aware of, or can I just use it? I'm mostly interested in screen.availWidth, by the way.
Quirksmode compatibility tables to the rescue!
http://www.quirksmode.org/dom/w3c_cssom.html#screenview
Most, but not all values are supported by the major browsers.
You should be fine with it.
The reason that it is not part of a standard is because DOM Level 0 was introduced before standards were around. DOM Level 0 is also called the Legacy DOM, and it was created at the same time NetScape 2.0 made JavaScript in the browser a reality; in effect, DOM Level 0 was the very first DOM spec.
The Legacy DOM will be around for a long time, if not then it would break backward compatibility with a TON of very popular scripts already in existence.
EDIT: In other words, your understanding is completely correct. It is not "standardized" but it is completely universal and will remain so for a long time.