S
Scott Sauyet
Usinging such a static API can keep code from blowing up but it can
also obscure API misuse and cause other problems.
It can, and it's also more flexible. But it is less convenient, and
that really is a consideration.
For instance, this is certainly fine for me:
API.roundCorners(myDiv);
And this is overkill:
if (API.roundCorners) {
API.roundCorners(myDiv);
}
Because rounded corners are merely a nice touch, and not something I
care to make a big deal about in my code.
And while there are times I might appreciate this flexibility:
if (API.myCoolFade) {
API.myCoolFade(myDiv);
} else {
myDiv.style.display = 'none';
}
It's also pretty nice to be able to do this:
API.myCoolFade(myDiv)
and know that the library is internally checking API.canSetOpacity and
whatever other flags it needs, then defaulting to its own
"style.display = 'none'" branch if the effects are not available.
I know that such a technique is less flexible. For instance, I
couldn't choose to do this:
if (API.myCoolFade) {
API.myCoolFade(myDiv);
} else {
var warning = document.createElement("H3");
myDiv.insertBefore(warning, myDiv.firstChild);
for (var i = 0; i < 5; i++) {
setTimeout((function(seconds) {
return function() {
warning.innerHTML = "This div will " +
"self-destruct in " + seconds +
" seconds!";
};
})(5 - i), 1000 * i);
}
setTimeout(function() {
myDiv.style.display = 'none';
}, 5000);
}
but I'm often willing to sacrifice such flexibility for the simplicity
of the static API.
[ ... ]
A library could provide a static API and provide a separate mechanism
for determining browser support of each function, but I don't know
that that would be advantageous in any way aside from allowing lazily-
written, terser code.
Of course that last phrase can also be written "simpler, clearer
code".
One technique I've used on several occasions in my own mini-library
code is to add "supported" properties to API functions, which return
values "complete", "degrade", "empty", or false, depending upon
whether the function is completely supported, degrades acceptably,
returns empty objects or arrays, or is totally unsupported, with code
something like this:
API.myCoolFade = API._support((function() {
if (API.opacitySupported) return "complete";
return "degrade";
)(), function(elt) {
if (API.opacitySupported) {
// cool opacity animation here.
} else {
if (elt) elt.style.display = 'none';
}
});
The _support function simply adds the 'supported' property to the
function supplied as the second parameter, with the value supplied in
the first parameter, and returns this enhanced function.
It can then be used simply, if I don't care:
API.roundCorner(myDiv);
Or I can test if I like:
if (API.myCoolFade.supported) {
API.myCoolFade(myDiv);
} else {
myDiv.style.display = 'none'
}
Or if I really want my own alternate degrading technique, I can check
the value of supported:
if (API.myCoolFade.supported == "complete") {
API.myCoolFade(myDiv);
} else if (API.myCoolFade.supported == "degrade") {
// My hand-rolled alternate hide technique here.
} else {
myDiv.style.display = 'none'
}
It has worked for me, but I haven't had to use it much, because it's
never been for large public APIs. It was exactly this sort of pseudo-
fade that motivated it, though, and it worked well enough there. For
API methods that returned arrays of nodes, usually there is complete
support across browsers, but when there isn't, the "supported"
property tells me that the function will at least return me an array I
could continue to process, even if it's empty, which often simplified
further coding.
In any case, I've never tried to code in the dynamic API style for
library code. Are there good examples of libraries that do it? I
understand My Library does; are there other publicly available
examples?
-- Scott