views:

105

answers:

7

Because windows xp renders certain fonts so poorly, i would like to detect whether the user is using that OS and add a class to the body accordingly.

I'm looking ideally for an html conditional statement or php $_SERVER var to do this

However failing that a piece of javscript along the lines of below would do

if(users_os === 'xp'){
    $('body').addClass('xp');
}

What avenues should i be persuing?!!!

thanks!


EDIT: TO CLARIFY!

This is further development on a project which renders the webapp in nicer fonts if the user has it natively installed - see part of my solution here: for extending font stacks abilities.

Fonts render differently on combinations of OS and Browser, not Browser alone - i want to be able to know whether a user is on xp or not becuase it's rendering of Calibri is so very poor

+1  A: 

Try this

if(navigator.oscpu == 'Windows NT 5.1')
{
    ...
}
Adam
I think thats the best way to go.
@Tom: Not in all browsers. In IE and Chrome, you would need to parse this information out of `navigator.userAgent`.
Andy E
Ahh right thats true. My mistake.
+7  A: 

It actually makes no sense to determine which operating system is used for a Web Application. The only thing which should be of interest, is the Browser. Even in the Browser you just have to care about what it supports and what not.

In JQuery you may use the .support(), .browser() and .boxModel() methods for that purpose.

jAndy
Also, given Cleartype 8can8 be enabled on Windows XP, the original check fails (also differing browsers can implement differing rendering routines)
Rowland Shaw
@Evan: And only allow what to view the page?
icktoofay
i disagree, the operating system makes a big difference to font rendering, have you tried it?
Haroldo
@Haroldo I just tried a `span` with Calibri in both Windows 7 and its built-in Windows XP virtual machine (on which I haven't changed any settings). They look identical to me in Firefox: http://pekkagaiser.com/blog/user/files/Calibri.PNG I had to install Calibri as it doesn't ship with XP by default - but that's a different issue, and you're going to have that on Macs, Linux-based machines etc. as well. Can you show an example of how fonts are rendered differently?
Pekka
@Haroldo: I'm not saying there is no difference I'm just saying it makes no sense to check for that. Looking at Windows alone has how many, 4,5, 6 different `OS` versions? In that different OS versions you have to care about 3-5 different browser behaviors on that platform? It should not within your scope to care about the OS. You still can do, but its senseless as before
jAndy
@pekka, thanks pekka i rechecked on my XP machine. I've been a massive bellend and realised that the browser was zoomed out 1 notch. Zoomed to 100% it looks ok and not awful! definately worse than xp and vista, but certainly fine and not worth making special exceptions for. thanks for your help(s)!
Haroldo
@jAndy, I would say that if the display was as bad as i thought it was (and didnt have it on wrong zoom) it would have definitely been worth making a special case for XP. I'm not concerned about aesthetics pre-xp and post xp microsoft seem to have sorting things out!
Haroldo
A: 

You should perform a check on navigator.appVersion, which contains OS version (my Win 7 become "Windows NT 6.1"):

Try this on your browser address bar to see which values are returned.

javascript:alert(navigator.appVersion);
mamoo
+2  A: 

Well, with PHP you could use $_SERVER['HTTP_USER_AGENT']. This string contains the browser, but also the OS. Example

Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729)

With the "substr" function (which is faster) or an preg_match you can extract the OS from the string.

faileN
i never like to *depend* on string matching (strpos/preg_match) for a futureproof solution, can you see any problems with Andy E's head's solution?
Haroldo
@Haroldo: the difference is that PHP handles the matching for you, it still uses the HTTP_USER_AGENT string, but it does the heavy lifting so you don't have to.
Andy E
@Andy E's head: That's what I wanted to write :)
faileN
+3  A: 

I fully agree with jAndy's answer, you shouldn't ever need OS detection for a web application and you should rarely need browser detection (the exception being stats/analytics, of course).

That being said, if you're insistent you need this, you can get what you need to know using the PHP function get_browser():

$browser = get_browser();
echo $browser["platform"];
// -> "WinXP"
Andy E
this looks great Andy, the only reason i'm doing this is to beautify my app without sacrificing performance. (text replacement services like cufon and remotely hosted fonts like typekit/webfonts have slight performance problems)
Haroldo
this might come in useful one day, cheers!
Haroldo
@Haroldo: I understand and fully encourage you to do as you please. When people talk about how it's a bad idea to use browser detection, they do so in the knowledge that it is unreliable vs feature detection. For instance, checking for IE6 to use ActiveX instead of native `XMLHttpRequest` is a bad idea because it can be disabled in IE7/8. What your doing doesn't seem like it could do any harm, so I don't think anyone can present a *real* argument against it
Andy E
A: 

You could try this

function OS()
{
    var n = navigator.oscpu;
    var Name = "empty";

    var osName = new Array("Windows XP", "Windows Vista", "Windows 7");

    var osNameAlt = new Array("Windows NT 5.1", "Windows NT 6.0", "Windows NT 6.1");

    for(a=0;a < osNameAlt.length; a++)
    {
        if (n == osNameAlt[a])
        {
            this.Name = osName[a];

            break;
        }


    }   

}



var os = new OS();


alert(os.Name);

Just add the OS names to the array

As I mentioned in a comment reply to [Adam's answer](http://stackoverflow.com/questions/3067916/conditional-or-js-to-detect-whether-user-is-on-windows-xp/3067931#3067931), *this will **only** work in Firefox!*
Andy E
Didn't see the comment until now. And posted this before i knew.
A: 

You can use navigator.platform also:

var isXP = /NT 5.1/.test(navigator.platform)

quirksmode.org has a great class you can use to detect the browser platform here (pasted below).

I have used similar methods to conditonally include CSS on Mac platforms, as fonts can be quite different on the Mac and even break layouts with their size and spacing difference. I did it because it was very late in the project and we need a band-aid. I'm a fan of just letting different sites look different in different browsers, as long as they remain functional and attractive. For example, I implement rounded corners using CSS only, and therefore they don't show in IE. I think this is acceptable, but some may not (have a look at quoterobot.com for an example - not my work by the way!)

var BrowserDetect = {
    init: function () {
        this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
        this.version = this.searchVersion(navigator.userAgent)
            || this.searchVersion(navigator.appVersion)
            || "an unknown version";
        this.OS = this.searchString(this.dataOS) || "an unknown OS";
    },
    searchString: function (data) {
        for (var i=0;i<data.length;i++) {
            var dataString = data[i].string;
            var dataProp = data[i].prop;
            this.versionSearchString = data[i].versionSearch || data[i].identity;
            if (dataString) {
                if (dataString.indexOf(data[i].subString) != -1)
                    return data[i].identity;
            }
            else if (dataProp)
                return data[i].identity;
        }
    },
    searchVersion: function (dataString) {
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) return;
        return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
    },
    dataBrowser: [
        {
            string: navigator.userAgent,
            subString: "Chrome",
            identity: "Chrome"
        },
        {   string: navigator.userAgent,
            subString: "OmniWeb",
            versionSearch: "OmniWeb/",
            identity: "OmniWeb"
        },
        {
            string: navigator.vendor,
            subString: "Apple",
            identity: "Safari",
            versionSearch: "Version"
        },
        {
            prop: window.opera,
            identity: "Opera"
        },
        {
            string: navigator.vendor,
            subString: "iCab",
            identity: "iCab"
        },
        {
            string: navigator.vendor,
            subString: "KDE",
            identity: "Konqueror"
        },
        {
            string: navigator.userAgent,
            subString: "Firefox",
            identity: "Firefox"
        },
        {
            string: navigator.vendor,
            subString: "Camino",
            identity: "Camino"
        },
        {       // for newer Netscapes (6+)
            string: navigator.userAgent,
            subString: "Netscape",
            identity: "Netscape"
        },
        {
            string: navigator.userAgent,
            subString: "MSIE",
            identity: "Explorer",
            versionSearch: "MSIE"
        },
        {
            string: navigator.userAgent,
            subString: "Gecko",
            identity: "Mozilla",
            versionSearch: "rv"
        },
        {       // for older Netscapes (4-)
            string: navigator.userAgent,
            subString: "Mozilla",
            identity: "Netscape",
            versionSearch: "Mozilla"
        }
    ],
    dataOS : [
        {
            string: navigator.platform,
            subString: "Win",
            identity: "Windows"
        },
        {
            string: navigator.platform,
            subString: "Mac",
            identity: "Mac"
        },
        {
               string: navigator.userAgent,
               subString: "iPhone",
               identity: "iPhone/iPod"
        },
        {
            string: navigator.platform,
            subString: "Linux",
            identity: "Linux"
        }
    ]

};
BrowserDetect.init();
cam8001