BAPS (browser and plugin sniffer)
BAPS, apart from being an acronym chosen purely for its its puerile humour, stands for browser and plugin sniffer - and I've just posted it in the scripts section.
As promised earlier this week, this is a utility to accurately detect information about the user's environment, such as browser name, version, language and installed plugins.
This is an area that is famously annoying, since different browsers expose different information to the Javascript's native navigator object, which exists to tell developers about the user's environment. Thus, it's never been standardised.
BAPS clears this up, as it caters for browsers' inconsistencies. It caters, for example, with the fact that Opera 11.52 declares itself as Opera 9.8. And for the fact that Chrome declares itself as, er, Netscape.
It sets a global variable, baps, which is an object containing various information about the user's environment, such as browser, version, language and plugins.
In terms of plugins, it detects Flash, WMP and QuickTime, but you can easily extend it to look for more.
Head over here to download, get usage info or view a demo.
post a commentRoundup: animated table sort / browser sniffing
With the exception of Blockster, the most popular script I've ever posted is my animated table sorter.
Which is rather odd, since as far as I'm aware it's buggy. Somehow, though, if the comments and e-mails are anything to go by, loads of people have been able to use it just fine.
Given this unexpected popularity I'm going to attempt to rebuild it in the coming months.
This script is among the top five hardest scripts I've written, so I'll, er, look forward to that.
In other news, stay tuned for my next script, later this week - a browser and plugin sniffer.
Browser sniffing is one of those things that you can't believe there still isn't a standard way of doing. Even jQuery's $.browser utility comes with a load of caveats warning that results might not be as expected.
And it's little wonder. Different browsers declare different, non-standard data in the various properties of the navigator object. Over the years these have led to some amusing revelations; if you ask Chrome what its navigator.appName is you'll get... Netscape. Naturally.
So I've been labouring away on a script that will provide you with something representing a reliable utility for this sort of thing. Not only with regards to detecting browser name but also other info such as language (more on that later...) and plugin support (and on that...).
post a commentAnnoyances with client-side XSL transformation
A current project of mine heavily involves XSL.
XSL is that rare thing: a technology that can run both on the client and on the server.This might be exciting if it wasn't so dubious; the likelihood of browsers and servers implementing a recommendation in equivalent fashion, just seems so unlikely.
That said, XSL does, I must admit, enjoy a pretty decent implementation in the browser, and with few cross-browser issues, too.
Naturally you won't want to be trying it in the likes of IE6 (which runs a very, very stripped-down version of XSL) but if you don't care about IE6, you should be fine.
Today, though, I did hit a snag: where XSL imports are concerned. Specifically, they don't work in Webkit browsers (Safari, Chrome).
This is only a problem when transforming your XSL through Javascript, i.e. within a webpage context - not if you're opening up the XML manually. In the latter case, your imports will work fine.
This is annoying, and it's not at all clear why Google/Apple don't add support for this.
Weirdness in Opera
As anyone close to me will tell you (or, rather, sigh and then tell you), my browser of choice is Opera. Now Opera does support XSL includes in the context of JS transformation... in a way.
If you load the XSL from a file, any XSL include statements within it will work.
1//utility function to load XML file and return as XML object
2function loadXMLDoc(dname) {
3 if (window.XMLHttpRequest)
4 xhttp=new XMLHttpRequest();
5 else
6 xhttp=new ActiveXObject("Microsoft.XMLHTTP");
7 xhttp.open("GET",dname,false);
8 xhttp.send("");
9 return xhttp.responseXML;
10}
11
12//load and parse XML & XSL files
13var xml = loadXMLDoc('some_xml_file.xml');
14var xsl = loadXMLDoc('some_xsl_file.xsl');
15
16//non-IE
17if (document.implementation && document.implementation.createDocument) {
18 xsltProcessor=new XSLTProcessor();
19 xsltProcessor.importStylesheet(xsl);
20 var output = xsltProcessor.transformToFragment(xml, document);
21//IE
22} else if (window.ActiveXObject)
23 var output = xml.transformNode(xsl);
24return output;
If, however, you specify and convert your XSL from a string, not from a file, you can forget about XSL includes.
1//prepare XML & XSL strings then parse into XML objects
2var xml = "1.0" encoding="ISO-8859-1"?>
3var xsl = "1.0" encoding="ISO-8859-1"?>
4xml = $.parseXML(xml);
5xsl = $.parseXML(xsl);
This would appear to be a bug. In both cases, the resultant xml and xsl vars are both typeof == 'XML Document Object'. In other words, they should be equivalent - but only the former approach allows XSL includes.
Looks like I'll be doing my XSL on the server after all.
post a commentBizarre webkit bug with 'typeof'
That'll teach me to post scripts and assume, without checking, that the normally-reliable Chrome and Safari will play ball. The other day I posted my JS simulation of REGEXP lookbehinds, but Marcus Tucker found it didn't work in these browsers.
After some digging, it seems there's a bizarre bug in Webkit browsers (i.e. Chrome and Safari) whereby regular expression objects are considered functions, not objects. So:
alert(typeof /\w+/);
Opera, IE and FF all say 'object', as you'd expect, but Chrome and Safari say 'function'. Very odd. I fixed the issue by using instanceof rather than typeof:
1alert(/\w+/ instanceof RegExp)
2//all browsers say true - happy days!
post a comment