/******************************************************************************
    Browser.js
    Copyright (c) 2006-2008 Motorola, Inc.
    All rights reserved
******************************************************************************/
$package("netopia/browser.html");

//--------------------

function $body (doc)
{
    doc = $doc(doc);
    return doc.body || doc.getElementsByTagName("body")[0];
}

function $head (doc)
{
    doc = $doc(doc);
    return doc.head || doc.getElementsByTagName("head")[0];
}

function $doc (doc)
{
    return doc || document;
}

window.kClassName = "window";

//-------------------------------------------------

netopia.create("dhtml").add({

Browser : $extends (netopia.core.Object,
{
    // see http://www.quirksmode.org/js/detect.html for details...
    ctor : function ()
    {
        var versionSearchString;

        function searchString (data)
        {
            for (var i=0; i < data.length; ++i)
            {
                versionSearchString = data[i].ver || data[i].name;
                if (data[i].prop)
                    return data[i].name;
                if (data[i].string && data[i].string.indexOf(data[i].text) != -1)
                    return data[i].name;
            }
            return null;
        }

        function getVer (str)
        {
            var index = str.indexOf(versionSearchString);
            if (index != -1)
                return parseFloat(str.substring(index + versionSearchString.length+1));
            return null;
        }

        // NOTE: Order is important...
        var browsers = [
            { string: navigator.userAgent, text: "OmniWeb", ver: "OmniWeb/", name: "OmniWeb" },
            { string: navigator.vendor, text: "Apple", name: "Safari" },
            { prop: window.opera, name: "Opera" },
            { string: navigator.vendor, text: "iCab", name: "iCab" },
            { string: navigator.vendor, text: "KDE", name: "Konqueror" },
            { string: navigator.userAgent, text: "Firefox", name: "Firefox" },
            { string: navigator.vendor, text: "Camino", name: "Camino" },
            // for newer Netscapes (6+)
            { string: navigator.userAgent, text: "Netscape", name: "Netscape" },
            { string: navigator.userAgent, text: "MSIE", name: "IE", ver: "MSIE" },
            { string: navigator.userAgent, text: "Gecko", name: "Mozilla", ver: "rv" },
            // for older Netscapes (4-)
            { string: navigator.userAgent, text: "Mozilla", name: "Netscape", ver: "Mozilla" }
        ];
        var platforms = [
            { string: navigator.platform, text: "Win", name: "Windows" },
            { string: navigator.platform, text: "Mac", name: "Mac" },
            { string: navigator.platform, text: "Linux", name: "Linux" }
        ];

        this.name = (searchString(browsers) || "?").toLowerCase();
        this.version = getVer(navigator.userAgent) || getVer(navigator.appVersion) || "?";
        this.os = (searchString(platforms) || "?").toLowerCase();
        this.vendor = navigator.vendor || "?";

        this.ie      = this.is("ie");
        this.khtml   = /konqueror|safari|khtml/i.test(navigator.userAgent);
        this.firefox = this.is("firefox");
        this.gecko   = (/Gecko/i.test(navigator.userAgent) && !this.khtml);
        this.safari  = this.is("safari");

        this.linux   = (this.os == "linux");
        this.mac     = (this.os == "mac");
        this.windows = (this.os == "windows");
    },

    fixClassNames : function (el)
    {
        // NOTE: these class must agree with those generated by the <ntpa:body>
        // custom tag...
        var add = [], remove = [];

        function append (b, pos, neg, name)
        {
            remove.push(pos + name);
            remove.push(neg + name);
            add.push((b ? pos : neg) + name);
        }

        function atLeast (b, name) { append(b, "atleast", "lessthan", name); }
        function hasNo   (b, name) { append(b, "has", "no", name); }
        function isNot   (b, name) { append(b, "is", "not", name); }

        isNot(this.firefox, "Firefox");
        isNot(this.gecko,   "Gecko");
        isNot(this.ie,      "IE");
        isNot(this.khtml,   "KHTML");
        isNot(this.safari,  "Safari");

        hasNo(!this.ie || this.version >= 7, "AlphaPng");

        if (this.ie)
        {
            isNot(this.version == 6, "IE6");
            isNot(this.version == 7, "IE7");

            atLeast(this.version >= 6, "IE6");
            atLeast(this.version >= 7, "IE7");
        }

        isNot(this.linux,   "Linux");
        isNot(this.mac,     "Mac");
        isNot(this.windows, "Windows");

        netopia.dhtml.replaceClassNames(el, remove, add);
    },

    is : function ()
    {
        for (var i = 0; i < arguments.length; ++i)
            if (this.name == arguments[i])
                return true;
        return false;
    },

    olderThan : function (name, ver)
    {
        return this.name == name.toLowerCase() && this.version < ver;
    }
})

}); // netopia.dhtml

netopia.dhtml.browser = new netopia.dhtml.Browser();

function $ (id, doc)
{
    if (typeof(id) != "string")
        return id;

    doc = $doc(doc);
    var el = doc.getElementById(id);

    // http://www.sixteensmallstones.org/ie-javascript-bugs-overriding-
    //          internet-explorers-documentgetelementbyid-to-be-w3c-compliant-
    //          exposes-an-additional-bug-in-getattributes
    //
    // (yes, it's one very long URL w/o line breaks) Apparently, IE7 has a bug
    // when you have a form in which there is an input with the name attribute
    // set to "id". It causes the "el.id" to return the wrong thing. The work
    // around is to use "el.attributes['id'].value" instead. The reason for the
    // extra work in the first place is because IE's getElementById returns
    // elements matching on "name" as well as "id" attributes.
    //
    /*if (el && netopia.dhtml.browser.ie)
        if (el.attributes["id"].value != id) // if (not a valid match on id)
        {
            var all = doc.all[id]; // then find the correct element
            for (var i = 1, n = all.length; i < n; ++i)
            {
                el = all[i];
                if (el.attributes["id"].value == id)
                    return el;
            }

            return null;
        }*/

    // dgriffin(5/Feb/08) - all the above is sad to be sure, *but*, there's an
    // issue with assigning an element's ID (e.g., elem.id = 'foo'). Doing so
    // does *not* set elem.attributes["id"] to match! So, the above logic does
    // its thing and rejects the element found by getElementById. Since all of
    // the code in NetopiaCommons is standards-based, the "id" tag is used and
    // "name" is not. This renders the above code not very helpful, but it is
    // often the case when using cloneNode to replicate DOM trees that the new
    // tree gets reassigned ID's before being added to the DOM. Rather than go
    // to more complex methods to set an ID, I'm commenting out the above for
    // now. Maybe we'll find a need for it and/or a way to do it reliably.

    return el;
}

