GWT offers javascript files mainly for Fifefox, chrome....., but what happens if another browser is being used such as K Melon or another browser which GWT does not specifically generates the javascript for that browser!!
I have tested for K Melon, it works correctly but i just want to know, how GWT knows which Javascript files to load
This is probably way more information than you wanted.
As far as mechanics go, GWT grabs the user agent from the browser, then uses a mechanism called a "property provider" to classify the browser. So, a property provider sets a property named "user.agent" to one of several predefined classes of browsers.
Here is an XML file which defines constants for all classes of browsers GWT currently knows about:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/UserAgent.gwt.xml?
At compile time, your app is compiled separately for each class of browser you want to support, and a different batch of JS gets loaded for each type of browser. The beauty of this is that the end user downloads the minimum amount of code needed to run the app, and won't be bloated by having conditional code for IE when you are running Chrome or Firefox.
Its a bit complex, but you can peek at the code that writes out some JavaScript to examine the User Agent string here to determine which class of browser is currently running:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/rebind/UserAgentPropertyGenerator.java
Once it picks a value for the user.agent property, the various parts of GWT conditionally substitute in code where browser specific logic is needed. Most browsers return a long list of "compatible" user agents. GWT tries to pick the best match from those. You can see that there is a default case - if the user agent string isn't recognized at all it sets the user.agent value to 'unknown' and fires up a warning to alert that the developer needs to manually pick one.
To dive a little deeper, here's the mechanism the compiler uses to pull in browser specific code based on the user.agent property:
(from Window.gwt.xml)
<module>
<inherits name="com.google.gwt.core.Core"/>
<inherits name="com.google.gwt.user.UserAgent"/>
<replace-with class="com.google.gwt.user.client.impl.WindowImplIE">
<when-type-is class="com.google.gwt.user.client.impl.WindowImpl"/>
<any>
<when-property-is name="user.agent" value="ie6"/>
<when-property-is name="user.agent" value="ie8"/>
<when-property-is name="user.agent" value="ie9"/>
</any>
</replace-with>
</module>
You'll notice that if 'webkit' is seen in the user agent, GWT returns the string 'safari' to identify the class of browser. There is no separate class of browser for Chrome. Chrome and Safari are very similar, and pretty closely written to specs, so there's not a lot of special casing for them. But that's not to say that there isn't Chrome specific code in some places. Sometimes a difference in browser will be detected at runtime. Its only done this way when there are just small browser differences. Here's an example of the way a minor difference between Chrome and Safari is handled:
public class HyperlinkImplSafari extends HyperlinkImpl {
private static boolean shiftIsModifier = onChrome();
private static native boolean onChrome() /*-{
return navigator.userAgent.indexOf("Chrome") != -1;
}-*/;
#Override
public boolean handleAsClick(Event event) {
//...
boolean modifiers = alt || ctrl || meta;
if (shiftIsModifier) {
modifiers |= shift;
}
return !modifiers && !middle && !right;
}
}
Check this post out - Google GWT cross-browser support: is it BS?
Even with the big names in browser industry, my experience with GWT apps hasn't been 100% compatibility, but really comes close.
For other browsers, it will look for the engine (most of them are offshoots of webkit or variants of mozilla's offering), if that is recognized, GWT generates the code for it more or less.
Anyways, the user base for such browsers itself is too tiny. In practice, it mostly suffices to test compatibility between IE6 (sigh), IE7, IE8 (yes they behave differently!), Firefox, and nowadays, chrome, safari and IE9.
Related
In using Eclipse to edit a web application. When I edit a Java class, put the cursor into a method name and use “search for references” from the mouse menu, Eclipse shows me all other places in the Java code, where the method is used. When I rename the method in one Java class, the rename is executed all across the code in any other Java classes where the method is used.
However, in our web application, there are also HTML files in JSF-XML format (EL), and they can also use the Java code. Example:
// BaseForm.java
#Named("BaseForm")
#SessionScoped
public class BaseForm
public String getMessage() {
return "Lorem ipsum dolor sit amet";
}
}
<!-- baseForm.xhtml -->
<ui:composition ...>
<ui:define name="contentHeader">
<h3>#{BaseForm.message}</h3>
^^^^^^^ this will invoke getMessage()!
Eclipse does detects the connection between the Java and the HTML: If there is no BaseForm, or if BaseForm doesn’t have a getMessage(), it will show an error in the HTML editor.
I am not editing the HTML files normally, I am only working on the Java code. But, if I rename something, it maybe that the rename must be aligned with a change somewhere in the HTML. I often miss this, and it doesn’t get noticed until a user clicks on the page where the error is, and the application crashes. (So to say, there is no compile-time error.) My question is, is there any support for me in Eclipse when renaming, and if yes, how can I enable it?
My observed behaviour is, when I “search for references”, Eclipes gives me only the matches in Java, not in HTML (even though it knows something about the relationship of the two, as I wrote before.) If I rename getMessage(), for example to getFallbackMessage(), it will change all function calls in all Java classes, taking into account many kinds of dependencies such as inheritance, and not accidentally renaming an unrelated getMessage() function that belongs to another class. So this is more powerful than a text editor’s Edit/Replace in all files. However, Eclipse doesn’t change the HTML where the function is called.
I could imagine that, if the one part of this function is so elaborated, that there is also some support to port such renames to HTML, but it doesn’t yet. I wonder if that exists and if yes, how can I enable it.
My desired behaviour is, when I “search for references”, Eclipse shows me references in Java files and references in XHTML files. When I rename getMessage() to getFallbackMessage(), the HTML will be edited, and #{FormClass.message} will be changed to #{FormClass.fallbackMessage}.
So my question is composed in two parts:
does such function exist in Eclipse?
if yes, what may cause that it is disabled, and how maybe I can change it to be enabled?
GWT is used and the application is deployed on WebLogic using HTTPS.
The performance is poor and with F12 Developer Tools, we could see that blank.html is downloaded multiple times. This is clearly related to GWT but we have not been able to figure out why.
The following is from javascript:
defineSeed(2613, 2614, makeCastMap([Q$BaseModelData, Q$ModelData, Q$Theme, Q$Serializable]), Slate_0);
var SLATE;
function $clinit_GXT(){
$clinit_GXT = nullMethod;
IMAGES = new XImages_generatedBundle_0;
MESSAGES = new XMessages__0;
SSL_SECURE_URL = getModuleBaseURL() + 'blank.html';
}
This is from GWT.java:
/**
* URL to a blank file used by GXT when in secure mode for iframe src to
* prevent the IE insecure content. Default value is 'blank.html'.
*/
public static String SSL_SECURE_URL = GWT.getModuleBaseURL() + "blank.html";
Does anyone know under what circumstances blank.html is called?
Thanks!
This is from GWT.java:
This is actually from GXT.java.
This is used in a few cases when creating an <iframe> element, so that IE won't give errors if your site is hosted from SSL. I can actually only find one case (as of GXT 3.1.1) which uses this, in Layer.java. Only IE pages loaded from https urls will make use of this.
The Layer class uses this as a "shim", a way to prop up some DOM elements above overs, and work around some browser bugs (typically plugin or iframe related). Menus and popup dialogs use this to ensure that they don't appear "underneath" content that they should be "above".
This file is very small - just enough HTML to convince IE than the iframe has correctly loaded, and no more. It never changes, and should load nearly instantly.
As far as performance goes, this should only happen when a Menu or Window/Dialog/Tooltip is shown - these shouldn't be happening on app startup usually, at least not more than a window or two. Additionally, the browser should recognize that it is loading the same element and cache it correctly, and not load it multiple times (though it might be listed several times as hitting the cache). If the server has instructed the browser to never cache the file, that is something you should look at changing.
In short, this is very unlikely to be the cause of any performance issues, at least in GXT itself. If somehow you have the shim enabled on every single widget in your project, this should not be required. If the file is loading slowly, something may be very wrong with your server configuration.
For reference, here is the entire file:
<html></html>
I recently upgraded my application to GWT 2.7 from GWT 2.5. This has caused me to drop support for IE6 and IE7.
I would like to provide users with IE6 or IE7 with a warning that their browser is outdated and will not work. At the moment if you go to the app with one of those browsers, you get a blank screen.
I know there are a couple ways that I could hack something together but I would rather use the GWT way, rather than some hack. Is there a GWT hook for unsupported browsers?
Option (hack) One
Drop this into my main.html:
if(document.documentMode === 6 || document.documentMode === 7){
myUnsupportedBrowserWarningFunction();
}
Potential problem with this is that if someone is using a browser that GWT doesn't recognise and I don't recognise (mobile opera? Some other browser), they will still get a blank page.
Option (hack) Two
GWT looks for the compiled JS here:
gwt/myApp/ASDFKLSDJFLSFDJSLDFJLSJDFSDES.cache.js
When someone is using an unsupported browser the following is requested (and is not found):
gwt/myApp/undefined.cache.js
It would be possible to create undefined.cache.js and put your unsupported browser code there. This is obviously a brittle solution and will break with future GWT updates.
Option Three
A recent patch (available in GWT 2.7) allows you to provide a default
permutation (e.g. safari) if GWT can not detect the browser and with
deferred binding you can display a warning that the provided app might not
work correctly as the browser is generally unsupported by GWT.
-- J.
Source
I don't want to set a default permutation for unsupported browsers. I want the site to not work and to display a warning. So this solution doesn't really provide what I am looking for.
Similar Questions & Posts
The same question was asked for an eariler version of GWT in 2009. I hope that GWT has added some kind of hook or best practice in the last 6 years.
More info on setting a default (fallback) permutation
You should be able to use onLoadErrorFn for that: https://code.google.com/p/google-web-toolkit/issues/detail?id=8135
<script>
function gwtLoadError(errMsg) {
// GWT app couldn't load, reason in errorMsg
}
</script>
<meta name="gwt:onLoadErrorFn" content="gwtLoadError">
or possibly onPropertyErrorFn:
<script>
function gwtPropError(propName, allowedValues, actualValue) {
if (propName == 'user.agent') {
// unsupported browser
}
}
</script>
<meta name="gwt:onPropertyErrorFn" content="gwtPropError">
(I don't think user.agent.runtimeWarning would help in this case, but maybe have a look)
There is an easy way:
Conditional Comments
<!--[if lt IE 8]>
<p>You are using an unsupportet browser. Please perform an update</p>
<![endif]-->
I think Option 3 may be the best one, but there is a problem: This will start the actual application (which still may be incompatible).
If this is an issue and you want a clear warning, you can rewrite the permutation selection script (You would need to update the script with the upcoming GWT releases)
You will need to copy this source:
https://gwt.googlesource.com/gwt/+/2.7.0/user/src/com/google/gwt/useragent/rebind/UserAgentPropertyGenerator.java
You could add something like:
$wnd.Location.replace('nosupported.html');
between line 90 and 91
I have gwt application based on GWTP. App supports two versions (tablet & desktop) and uses different widget libraries (sencha gxt and sencha touch). These libraries require different css files in host page. Moreother css are in conflict each to other. How I can load different css files in my host page?
I already read about gwt mobilewebapp sample, but they use single html-page and different implementations of components.
You can check the Useragent and decide which CSS File to deliver.
I recommend to use ClientBundles. This deliver only the css styles need, and speed up your page.
In your Entrypoint you just decide which css file you want to deliver:
if(useragent == "desktop") {
YourStyle.getTheme().getMGWTClientBundle().getDesktopCss().ensureInjected();
} else {
YourStyle.getTheme().getMGWTClientBundle().getAppCss().ensureInjected();
}
or you can make a switch inside your css files. But you have to use ClientBundles anyway.
There you can have something like this:
#external gwt-button;
#if user.agent safari {
.gwt-Button {
...
}
}
#external gwt-button is to avoid obfuscation errors. you can also use #external *;
You could also do this on the server side, by using a JSP file as the css source.
Then, in the JSP file, decide which set of properties to send based on the requesting user agent or other.
Another option is to write the host page as a JSP file, and it can include the proper CSS file based on the request.
This is a pretty easy way to go, but you must enable the JSP processor in your web.xml. It also requires your deployed system to have a java compiler on it, which is not the case if you only install the JRE on the webserver.
You have to create two classes which load the css file :
You can do some thing related to type in gwt.xml file
<replace-with
class="com.test.classMobile">
<when-type-is
class="com.Test.classBrowser" />
<when-property-is name="tablet.user.agent" value="ipad" />
</replace-with>
Just try this..I am not sure 100%
When I build a GWT application, it runs on all browsers like IE,chrome,firefox etc. provided GWT plugin is installed for that browser.
I want to know how can I prevent a GWT application from running on a particular browser i.e. if I don't want my GWT apps to run on say Firefox, how can I achieve that? What changes I need to do in my code?
Add <set-property name="user.agent" value="ie6,ie8,ie9,safari,opera" /> to your *.gwt.xml file and it will fail to load in Firefox (FYI, Firefox's user.agent token is gecko1_8).
If you don't want to support IE6 and IE7 for instance, you don't need to compile for them, and you can decrease your compilation time by removing the ie6 token from the user.agent value list.