views:

3287

answers:

3

I'm writing a bit of javascript and need to choose between SVG or VML (or both, or something else, it's a weird world). Whilst I know that for now that only IE supports VML, I'd much rather detect functionality than platform.

SVG appears to have a few properties which you can go for: window.SVGAngle for example.

Is this the best way to check for SVG support?

Is there any equivalent for VML?

Unfortuntaly - in firefox I can quite happily do all the rendering in VML without error - just nothing happens on screen. It's quite hard to detect that situation from script.

+7  A: 

For VML detection, here's what google maps does (search for "function Xd"):

function supportsVml() {
    if (typeof supportsVml.supported == "undefined") {
        var a = document.body.appendChild(document.createElement('div'));
        a.innerHTML = '<v:shape id="vml_flag1" adj="1" />';
        var b = a.firstChild;
        b.style.behavior = "url(#default#VML)";
        supportsVml.supported = b ? typeof b.adj == "object": true;
        a.parentNode.removeChild(a);
    }
    return supportsVml.supported
}

I see what you mean about FF: it allows arbitrary elements to be created, including vml elements (<v:shape>). It looks like it's the test for the adjacency attribute that can determine if the created element is truly interpreted as a vml object.

For SVG detection, this works nicely:

function supportsSvg() {
    return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Shape", "1.0")
}
Crescent Fresh
Ok, this is good. The VML detection is working fine, however the SVG detection fails in firefox. In fact, firefox denies all SVG abilities on http://www.howtocreate.co.uk/tutorials/jsexamples/hasFeature.html.
Jim T
As a compromise to firefox, I'm combining my old window.SVGAngle check with the much nice feature check, if either succeed, then it's supported. If you can fix up, improve on or remove the supportsSvg function, I can accept your answer.
Jim T
Hmm, works for my FF (2) including that link.
Crescent Fresh
Jim T
I found the Shape attribute here: "http://www.din.or.jp/~hagi3/JavaScript/JSTips/Mozilla/Samples/hasFeature.htm"
Jim T
Well that does seem a more specific feature check.
Crescent Fresh
I've updated the answer to use `feature#Shape` instead of `feature#SVG`. #SVG is too "catch all" that obviously FF corrected in v3.
Crescent Fresh
Shame really, I much prefer the idea of detecting #SVG. Oh well, reality strikes.
Jim T
I realize now though that testing for feature "#SVG" is like testing if a browser "supports html". It's so open-ended, it makes sense to test for a specific feature of SVG, like drawing shapes (which is so fundamental) to svg.
Crescent Fresh
Don't forget too that you are testing for svg as a global feature by specifying "http://www.w3.org/TR/SVG11/feature" before the # hash.
Crescent Fresh
+5  A: 

I'd suggest one tweak to crescentfresh's answer - use

document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")

rather than

document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Shape", "1.0")

to detect SVG. WebKit is currently very picky about reporting features, and returns false for feature#Shape despite having relatively solid SVG support. The feature#BasicStructure alternative is suggested in the comments to https://bugs.webkit.org/show_bug.cgi?id=17400 and gives me the answers I expected on Firefox/Opera/Safari/Chrome (true) and IE (false).

Note that the implementation.hasFeature approach will ignore support via plugins, so if you want to check for e.g. the Adobe SVG Viewer plugin for IE you'll need to do that separately. I'd imagine the same is true for the RENESIS plugin, but haven't checked.

Mike C
+2  A: 

You might like to skip this and use a JS library which will allow you to do vector drawing cross-browser, if that's the intention. The library will then handle this, outputting to SVG if supported or fallback to canvas, VML, flash, silverlight, etc if not, depending on what's available. Examples of libraries that will do this are, in no particular order: dojo.gfx (http://docs.dojocampus.org/dojox/gfx/), Raphaël (http://raphaeljs.com/) & SVGWeb (http://code.google.com/p/svgweb/)

dflock
The raphaeljs demos are incredible. +1 for turning me on to that.
Koobz
Raphael is indeed incredible, I love it and recommend it to everyone. But it was just too slow for one particular thing I wanted to do. I also didn't feel that the way that raphael detected svg was very nice (I can't remember what that was now), and wondered if there was a better, more official way to do it, hence the question.
Jim T