Viewing File: /usr/local/cpanel/base/cjt/browser.js

/* ----------------------------------------------------------------------

NOTE: The following code is ONLY meant for displaying NOTICES, to the effect
of: "Your browser is too old; it looks like you might have better luck using
one of these browsers: X, Y, Z".

Do NOT use this code in place of feature detection. To determine if the
browser supports a feature (e.g., <canvas>), do:

var i_can_canvas = false;
try {
    i_can_canvas = document.createElement("canvas").getContext("2d");
} catch(e) {}

... rather than using any of this logic here.

In fact, as the comments below describe, you shouldn't get here until
you've actually done feature detection.

NOTE: Putting feature detection into this file was considered but rejected
because it would usually mean instantiating "throw-away" objects. We could
revisit that decision in the future.

 ---------------------------------------------------------------------- */

(function(window) {
    var YAHOO = window.YAHOO,
        CPANEL = window.CPANEL;

    // NOTE: This structure only needs to record when each platform FIRST
    // gained a browser that supports a given API.
    //
    // So, for example, Windows 8 doesn't need a "file_api" entry because
    // every shipping browser already supported the File API when Microsoft
    // released Windows 8.
    //
    // The first item in each array is the "ID test", which currently is always
    // a regular expression but can also be a function.
    var BROWSER_SUPPORT = {
        file_api: {
            android: [
                [/^2\.3/, "Firefox", "Opera"]
            ],
            macintosh: [
                [/^10\.6/, "Chrome", "Firefox", "Opera"],
                [/^10\.7/, "Chrome", "Firefox", "Opera", "Safari"]
            ],
            windows: [

                // WinXP and Vista didn't get IE10.
                [/^(?:6\.0|5\.[1-9])/, "Chrome", "Firefox", "Opera"],

                // Win7 shipped with IE9.
                [/^6\.1/, "Chrome", "Firefox", "Internet Explorer", "Opera"]
            ]
        }
    };

    function _parse_ua_data() {
        var YAHOO_ENV_UA = YAHOO.env.ua;

        var client_os = YAHOO_ENV_UA.os;
        var client_os_version;

        if (client_os) {
            var client_appstring = YAHOO_ENV_UA.gecko ? navigator.oscpu : navigator.appVersion;

            switch (client_os) {
                case "windows":
                    client_os_version = client_appstring.match(/Windows\s+NT\s+([^;]+)/);
                    break;
                case "macintosh":
                    client_os_version = client_appstring.match(/Mac\s+OS\s+(?:X\s+)?([\d._]+)/);
                    break;
            }

            if (client_os_version) {
                client_os_version = client_os_version[1].replace(/_/g, "."); // replace() is for MacOS
            }
        } else {
            if (YAHOO_ENV_UA.android) {
                client_os = "android";
                client_os_version = YAHOO_ENV_UA.android;
            } else if (YAHOO_ENV_UA.ios) {
                client_os = "ios";
                client_os_version = YAHOO_ENV_UA.ios;
            }
        }

        return {
            os: client_os,
            os_version: client_os_version
        };
    }

    /**
     * http://stackoverflow.com/questions/2450954/how-to-randomize-a-javascript-array
     */

    function _shuffle_array(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }

    // This is factored out for testing purposes.

    function _get_browser_support_options(features) {

        var feature_browsers;

        var os_info = _parse_ua_data();
        var client_os = os_info.os;
        var client_os_version = os_info.os_version;

        if (client_os) {
            if (typeof features === "string") {
                features = [features];
            }

            features.forEach(function(feature) {
                var possibilities = BROWSER_SUPPORT[feature] && BROWSER_SUPPORT[feature][client_os];
                if (possibilities) {
                    possibilities.forEach(function(poss) {
                        var ptest = poss[0];
                        if (ptest instanceof RegExp) {
                            if (!ptest.test(client_os_version)) {
                                return;
                            }
                        } else if (ptest instanceof Function) {
                            if (!ptest(client_os_version)) {
                                return;
                            }
                        }

                        // >=2nd time through: delete keys that aren't in
                        // the current array.
                        if (feature_browsers) {
                            for (var browser in feature_browsers) {
                                if (poss.indexOf(browser) === -1) {
                                    delete feature_browsers[browser];
                                }
                            }
                        } else { // First time through: create keys for each browser.
                            feature_browsers = {};
                            poss.slice(1).forEach(function(browser) {
                                feature_browsers[browser] = true;
                            });
                        }
                    });
                }
            });

        }

        return feature_browsers && Object.keys(feature_browsers);
    }

    /**
     * Return a message with the best "knowable" advice to a user for
     * loading a page that needs the given feature/features.
     *
     * This *assumes* that we've already determined that the current
     * OS does not support the given feature. So if you ask for a message
     * about the File API, and you're running Windows 8, the response message
     * won't be very helpful because it'll think you're running something
     * "weird", when in fact you're just running something that doesn't need
     * this check (because every Windows 8 browser supports File API).
     *
     * We rely here on OS version detection, which is imprecise at best.
     *
     * Examples:
     *
     *   get_browser_support_message("file_api")
     *   -> Returns the browsers that support File API on the current OS.
     *
     *   get_browser_support_message( ["file_api", "cool_new_thing"] )
     *   -> Returns the browsers that support File API *and* "cool_new_thing"
     *      on the current OS.
     *
     * @method get_browser_support_message
     * @param features {String|Array} Which feature(s) to check for a message.
     * @return {String} The requested message.
     */

    function get_browser_support_message(features) {
        var feature_browsers = _get_browser_support_options(features);

        var os_notice;

        if (feature_browsers) {

            // Shuffle these so that we're not "preferring" one browser over another.
            feature_browsers = _shuffle_array(feature_browsers);

            if (feature_browsers.length === 1) {
                os_notice = LOCALE.maketext("Try this page with the latest available version for your platform of “[_1]”", feature_browsers[0]);
            } else {
                os_notice = LOCALE.maketext("Load this page with the latest available version for your platform of one of these web [numerate,_1,browser,browsers]: [join,~, ,_2]", feature_browsers.length, feature_browsers);
            }
        }

        return os_notice || LOCALE.maketext("Load this page with a newer web browser. (You may need to use another device.)");
    }

    CPANEL.browser = {
        NO_SUPPORT_MESSAGE: LOCALE.maketext("Your web browser lacks support for a feature that this page requires."),
        get_browser_support_message: get_browser_support_message,

        // exposed only for testing
        _get_browser_support_options: _get_browser_support_options
    };
}(window));
Back to Directory File Manager