Search code examples
javascriptcross-browserconditional-compilationgoogle-closure-compiler

How to detect Internet Explorer in JavaScript with Google Closure Compiler?


I have a JavaScript function that handles mouse button events. It must be able to distinguish between left and right mouse buttons. Sadly, Internet Explorer uses different values for event.button than all other browsers do. I know how to interpret them, but I need to know which path to go.

I did that with a JavaScript hack that relies on conditional compilation. It's like this:

if (/*@cc_on!@*/false) { IE fixup... }

I consider this quite a safe method because it is based on the JavaScript parser capabilities that cannot be faked and are unlikely to be imitated by other browsers.

Now I'm using the Google Closure Compiler to pack my JavaScript files. I found that it removes conditional compilation comments just like any other comment, too. So I tried different hacks. One of them it this:

if ("\v" == "v") { IE fixup... }

Unfortunately, the closure compiler quite clever and finds out that the condition can never be true and removes that code. Also, I don't like it because Microsoft may eventually fix that \v bug and then the detection fails.

I could just read something like navigator.appName or what it's called, but this is way too easy to fake. And if somebody modifies their browser identification, they're unlikely to implement the other event.button behaviour...

Closure compiler allows to preserve certain comments. I tried this:

if (/**@preserve/*@cc_on!@*/false) { IE fixup... }

While this produces the desired result after compression, it is not a functional conditional comment in its source form. But for debugging reasons, I need my JavaScript file to work both compressed and uncompressed.

Is there any hope for me to get this working without modifying the compressed JS file by hand?

For the reference, here's my complete function in its original form:

function findEvent(e)
{
    e = e || event;   // IE
    if (!e.target && e.srcElement)   // IE
        e.target = e.srcElement;
    if (isSet(e.button))
    {
        // Every browser uses different values for the mouse buttons. Correct them here.
        // DOM says: 0 = left, 1 = middle, 2 = right (multiple buttons not supported)
        // Opera 7 and older and Konqueror are not specifically handled here.
        // See http://de.selfhtml.org/javascript/objekte/event.htm#button
        if (/*@cc_on!@*/false)   // IE - http://dean.edwards.name/weblog/2007/03/sniff/ - comment removed by Google Closure Compiler
        {
            if (e.button & 1)
                e.mouseButton = 0;
            else if (e.button & 2)
                e.mouseButton = 2;
            else if (e.button & 4)
                e.mouseButton = 1;
        }
        else
            e.mouseButton = e.button;
    }
    return e;
}

Solution

  • Okay, after some more searching, for now I'm happy with this solution:

    function ieVersion()
    {
        var style = document.documentElement.style;
        if (style.scrollbar3dLightColor != undefined)
        {
            if (style.opacity != undefined)
                return 9;
            else if (style.msBlockProgression != undefined)
                return 8;
            else if (style.msInterpolationMode != undefined)
                return 7;
            else if (style.textOverflow != undefined)
                return 6;
            else
                return 5.5;
        }
        return 0;
    }
    

    Found on http://msdn.microsoft.com/en-us/library/ms537509%28v=vs.85%29.aspx#4

    Here's a list of other methods I found on the way:
    http://dean.edwards.name/weblog/2007/03/sniff/ – Doesn't work with Closure Compiler
    http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html – That's the one with "\v"
    http://www.thespanner.co.uk/2009/01/29/detecting-browsers-javascript-hacks/ – Similar to above, also for other browsers
    How to detect Internet Explorer in JavaScript with Google Closure Compiler? – Answer by John on this page