GWT - How to get the client browser name

Do you need to implement specific code for a given browser, due to different causes, bugs or workarounds? Here are some helper static native functions to figure out what browser the client uses. Obviously these functions must be called only on the GWT client-side, due to the native JavaScript scriptlet.

/**
* Gets the name of the used browser.
*/
public static native String getBrowserName() /*-{
    return navigator.userAgent.toLowerCase();
}-*/;

/**
* Returns true if the current browser is Chrome.
*/
public static boolean isChromeBrowser() {
    return getBrowserName().toLowerCase().contains("chrome");
}

/**
* Returns true if the current browser is Firefox.
*/
public static boolean isFirefoxBrowser() {
    return getBrowserName().toLowerCase().contains("firefox");
}


/**
* Returns true if the current browser is IE (Internet Explorer).
*/
public static boolean isIEBrowser() {
    return getBrowserName().toLowerCase().contains("msie");
}

For the other browsers (opera, safari, seamonkey etc) you can have your own function made after the previous 3 models.

Cheers!

6 comments:

  1. Shouldn't the programmer use in the {module}.gwt.xml file instead? I looked at the GWT (1.7.1, sadly) code to see how to do it.

    I did this because I wanted to mark certain form labels as 'required', and take advantage of the CSS 2.1 :before pseudo-element selector on browsers that respected it and the content CSS attribute set to an asterisk, while manually adding an asterisk on browsers that didn't.

    So, I created a class extending HorizontalPanel. It has a static inner class that tells whether the panel needs an explicit InlineLabel to contain the asterisk and can provide it if necessary.

    The inner class has a subclass that handles the IE6 and Hosted mode case. The outer class uses GWT.create() to get an inner class, and the .gwt.xml file checks whether IE6 or hosted mode are in use and orders the substitution.

    ReplyDelete
  2. I don't get it; how do you get the name of the user's browser from the {module}.gwt.xml file ?

    Can you provide a simple sample code, please?

    Cheers!

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. My gwt.xml file is RequiredText.gwt.xml.

    <module>
    <inherits name="com.google.gwt.core.Core" />
    <inherits name="com.google.gwt.user.UserAgent" />
    <replace-with class="com.erjablow.RequiredText.RequiredTextImplNonCss">
    <when-type-is class="com.erjablow.RequiredText.RequiredTextImpl" />
    <any>
    <when-property-is name="user.agent" value="ie6" />
    <when-property-is name="user.agent" value="hosted" />
    </any>
    </replace-with>
    <module>

    The GWT compiler generates mn Javascript files, where m is the number of browser types you support, and n is the number of locales you support. You can cut down on m and n by other module declarations. By default, GWT creates IE6, IE8, FF, Opera, Safari, and HostedMode versions, though the list may have changed in GWT 2.x.

    Now, my RequiredText class (and I don't have it on this machine, so I won't fill everything out) looks like

    public class RequiredText extends Composite {
    public static class RequiredTextImpl {
    public boolean requiresExplicitAsterisk(){
    return false;
    }
    public InlineLabel explictAsteriskLabel() {
    return null;
    }
    }
    public static class RequiredTextImplNonCss extends RequiredTextImpl {
    public boolean requiresExplicitAsterisk(){
    return true;
    }
    public InlineLabel explictAsteriskLabel() {
    InlineLabel label = new InlineLabel("*");
    label.setStyleName("requiredTextAsterisk");
    return label;
    }
    }
    private final RequiredTextImpl impl = GWT.create(RequiredTextImpl.class);
    // ...
    }

    It's more complicated, but none of the tests occur at runtime. GWT does the same thing in much of its code; look at its gwt.xml files for uses of <replace-with>, and then look at its source code.

    Sorry--I deleted my earlier post because I forgot that angle brackets needed to be escaped.

    ReplyDelete
  5. Now, I understand what you want to do. But this is more complex and something else than what I meant.

    *** First of all, what you do by fixing the {module}.gwt.xml file, with the "user.agent" property, is to limit the permutations at compilation time, which implicitly will increase the speed of it.

    *** Secondly, you described a very complex way of adding a silly "*" to a label.

    What I meant in my article is that in the client-side code you may need to know what browser is used (not to limit it) and do something specifically, like below:

    Example
    ---------

    if (isChromeBrowser()) {
    panel.add (new TextLabel ("Chrome browser isn't supported yet!"));
    }

    I hope with this that I clarified what is the meaning of the "getBrowserName()" function :-)

    Cheers!

    ReplyDelete
  6. You don't need to call toLowerCase() after calling getBrowserName() each time, since you call it in the method itself already. It's useless overhead.

    ReplyDelete