Identify Touch/Gesture Capable Devices using GWT - gwt

I would like to know if it is possible to identify whether a device is capable of Touch/Gesture Events or not in GWT?
Devices like iPhone supports Multi-Touch Events to a huge extent. Similarly Google Chrome in Desktop also supports TouchEvents. And at present, Windows 8 has been designed with an IE that is responding to TouchEvents.
I am working on an Application where i want to restrict certain features to only Touch/Gesture Capable Devices! Any Solution, please help?

I don't think there's any other way than UA sniffing.

GWT currently does not provide such utility.
Also, till gwt provides us a direct utlity api, it would make sense to write jsni over existing javascript techniques like these stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript .
For windows 8 the msdn document to refer is http://blogs.msdn.com/b/ie/archive/2011/09/20/touch-input-for-ie10-and-metro-style-apps.aspx

I did this with User Agent Check in Deferred Binding. I created a white list so that more devices can be added later.
Here is the Code,
<!-- Definitions for mobile -->
<define-property name="mobile.user.agent" values="android, ios, not_mobile" />
<property-provider name="mobile.user.agent"><![CDATA[
{
var ua = window.navigator.userAgent.toLowerCase();
if (ua.indexOf("android") != -1) { return "android"; }
if (ua.indexOf("iphone") != -1) { return "ios"; }
if (ua.indexOf("ipad") != -1) { return "ios"; }
return 'not_mobile';
}
]]></property-provider>
<!-- Constrain the value for non-webkit browsers -->
<set-property name="mobile.user.agent" value="not_mobile" >
<none> <!-- Actually means NOR, in this case "not safari" -->
<when-property-is name="user.agent" value="safari" />
</none>
</set-property>
Then i defined my classes using the replace-with property in my Module file. Here for example, i have replaced flash player with HTML5 videos for devices like iPad.
<replace-with class="com.example.HTML5Player">
<when-type-is class="com.example.FlashPlayer" />
<any>
<when-property-is name="mobile.user.agent" value="android" />
<when-property-is name="mobile.user.agent" value="ios" />
</any>
</replace-with>

Related

GWT: Load different css in host page

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%

Prevent application from running on a particular browser

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.

GWT deferred binding

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.

Mapping ui:field in GWT to generated code

I'm trying to get some automated UI testing going on a GWT application and I'm having trouble finding a way to track UI elements.
For example, I have the following:
<g:Button text="Submit" ui:field="submitButton" enabled="true" />
which generates:
<button class="gwt-Button" type="button">Submit</button>
Its a compiler error to set both ui:field and id (id is considered deprecated anyway) so the problem is that I have no easy way to select my submit button using something like selenium.
Is anyone aware of a way I can map the
ui:field="sumbitButton"
to the generated HTML?
After further investigation I've discovered that you can enable debugIds which are ment for testing purposes. If you add:
<inherits name="com.google.gwt.user.Debug"/>
to your *.gwt.xml file you can then set debugId on your ui elements as such:
<g:Button text="Submit" ui:field="submitButton" enabled="true" debugId="submitButton"/>
and also in the codebehind by using the ensure debug id method
submitButton.ensureDebugId("submitButton");

Web site exhibits JavaScript error on iPad / iPhone under 3G but not under WiFi

Connecting to http://www.manage-us.com on an iPad under 3G [used to] result in a JavaScript error which can be seen if the developer console has been enabled. If the same page is accessed using the same iPad under a WiFi connection no error is displayed. [The error has now gone because I applied the fix below!].
Why is this?
I've tried simulating low bandwidth (using dummynet) on Safari on Mac and on the iPad simulator on Mac. This does not reproduce the problem.
I am currently suspecting this is a problem being introduced by my mobile operator in the UK (O2) which is known to modify some content through a proxy cache such as downgrading image files. If you can confirm that you don't experience this problem when connecting by 3G on iPad or iPhone through another mobile operator that would be helpful.
I've investigated this further and discovered that the problem is that the UK mobile operator O2 (the original exclusive iPhone operator for Apple), modifies web content before sending it to iPhones and iPads. Probably before sending it to any device running a mobile browser.
They non-deterministically inline some of the CSS and JavaScript into the main source files of the web pages. This can create errors either because of mistakes in their algorithm or the consequence of stripping white space from source files with syntactic mistakes in the source files which were otherwise benign.
These modifications also strip copyright messages from copyrighted javascript libraries and css libraries and play havoc with delivery optimisations.
For example, imagine if a user is visiting a sequence of pages on your site which all link to jQuery libraries. Instead of letting your mobile browser locally cache the library, O2 inline the library on every page, forcing your phone to load the entire library over and over again for every page.
I've written a blog about the issue here in the hope if drawing a bit more attention to this: http://stuartroebuck.blogspot.com/2010/07/mobile-proxy-cache-content-modification.html
My workaround is to use document.write() to insert the JavaScript library dependencies at load time and prevent O2 from inlining them. This seems to work quite well. e.g.:
<script type="text/javascript">
// <![CDATA[
// Using document.write to load JavaScript dependencies to bypass O2 network inlining of JavaScript.
function loadJS(file){document.write("<" + "script type='text/javascript' src='" + file + "'></" + "script>")}
loadJS("/js/jquery-1.4.2.min.js");
loadJS("/js/myJSLibrary.js");
// ]]>
</script>
Note that, as ever, document.write will not work if the page is served as XHTML.
For anyone needing a solution to this in ASP.NET, this sets the Cache-Control header as per http://stuartroebuck.blogspot.com/2010/08/official-way-to-bypassing-data.html for javascript files using URL Rewrite Module 2.0 http://learn.iis.net/page.aspx/665/url-rewrite-module-20-configuration-reference.
<system.webServer>
<rewrite>
<outboundRules>
<rule name="Compression header" preCondition="Match JS Files">
<match serverVariable="RESPONSE_Cache-Control" pattern="(.*)" />
<action type="Rewrite" value="no-transform" />
</rule>
<preConditions>
<preCondition name="Match JS Files">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="(javascript)$" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
Alternatively can be done using a HttpModule
public class AddHeaderModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.EndRequest += OnEndRequest;
}
void OnEndRequest(object sender, System.EventArgs e)
{
if(HttpContext.Current.Response.ContentType.Contains("javascript"))
HttpContext.Current.Response.Headers.AddHeader("Cache-Control", "no-transform");
}
}
and
<configuration>
<system.web>
<httpModules>
<add name="AddHeaderModule" type="your.namespace.AddHeaderModule" />
</httpModules>
</system.web>
</configuration>