Pure feature detection library, a la carte style.
This document is not complete.
Browser sniffing and feature inference are flawed techniques for detecting browser support in client side JavaScript. The goal of has.js is to provide a collection of self-contained tests and unified framework around using pure feature detection for whatever library consumes it.
You likely won't see has.js as a public API in any library. The idea is that %yourfavoritelibrary% will import some or all the available tests, based on their own needs for providing you a normalized future proof API against common tasks.
not stable, so keep that in mind. This is a young project, and the decided naming conventions may be a moving target. The tests are nothing that haven't been done over and over in various places, so the intention is to come to some agreement on a basic naming convention and API based on real world use cases.
Currently, the testing convention is has('somefeature')
returns Boolean, e.g.:
if(has("function-bind")){
// your enviroment has a native Function.prototype.bind
}else{
// you should get a new browser.
}
In the real world, this may translate into something like:
mylibrary.trim = has("string-trim") ? function(str){
return (str || "").trim();
} : function(str){
/* do the regexp based string trimming you feel like using */
}
By doing this, we can easily defer to browser-native versions of common functions, augment prototypes (which has.js will not do) to supplement the natives, or whatever we choose.
Running has()
is a one-time cost, deferred until needed. After first run, subsequent has()
checks are cached and return immediately.
Each test is self-contained. Register a test with has.add()
:
has.add("some-test-name", function(global, document, anElement){
// global is a reference to global scope, document is the same
// anElement only exists in browser enviroments, and can be used
// as a common element from which to do DOM working.
// ALWAYS CLEAN UP AFTER YOURSELF in a test. No leaks, thanks.
// return a Boolean from here.
return true;
});
You can register and run a test immediately by passing a truthy value after the test function:
has.add("some-other-test", function(){
return false; // Boolean
}, true)
This is preferred over what would seem a much more effective version:
// this is not wrapped in a function, and should be:
has.add("some-other-test", ("foo" in bar)); // or whatever
By forcing a function wrapper around the test logic we are able to defer execution until needed, as well as provide a normalized way for each test to have its own execution context. This way, we can remove some or all the tests we do not need in whatever upstream library should adopt has.
Something resembling a "builder" is coming. A basic dependency matcher and test lister is provided in build/
.
has.js contributions are covered under a common license by way of Dojo Foundation CLA, and brought to you by the following awesome folks:
There is an IRC room setup for discussion or questions: #hasjs@irc.freenode.net
Internally, we follow these conventions:
"
g
, d
, and n
. Use these aliases always.STR == "string"
FN == "function"
!!(someExpression)
as necessary!!("x" in y)
or anything else that would otherwise return a boolean, e.g.
x !== y
, x > y
, typeof y
return ("x" in y)
Tentatively, has.js is available under the Academic Free License, New BSD License, and the MIT License. Providing this common code under multiple licenses requires us to have all contributors agree to a CLA.
has.js is open source, and open to contribution. Please fork and send pull requests as you see fit. This is a rough list of things that are needed or coming:
has("native-xhr") // tests if the environment has a native XmlHttpRequest implementation
.var CONTS = ""
style helpers in a single wrapping function.