- We design and build extraordinary applications for companies looking to make the next great idea a reality.
- learn more
GWT: DOM and Opacity

One thing missing from the DOM class in GWT is the ability to set element opacity in a browser independent way. You do have DOM.setStyleAttribute, but in IE you set the opacity by squeezing a alpha(opacity=val) into the filter, where in most other browsers you set the opacity style attribute directly.
If you take a peek into the prototype library, you'll see all sorts of cruft around setting opacity, such as supporting Konquerer, etc., but in the world of GWT, we just have to support a few browsers (IE6+, Mozilla, Safari, Opera). I had a need for a kinder, gentler opacity when I started developing GWTaculous, my pure GWT port of the Scriptaculous effects library. I implemented my own DOMX class to support those extended DOM operations I needed.
The module def file looks like this:
<module>
<inherits name='com.google.gwt.user.User'/>
<replace-with class="org.puregwt.gwtaculous.client.dom.impl.DOMXImplStandard">
<when-type-is class="org.puregwt.gwtaculous.client.dom.impl.DOMXImpl"/>
</replace-with>
<replace-with class="org.puregwt.gwtaculous.client.dom.impl.DOMXImplOpera">
<when-type-is class="org.puregwt.gwtaculous.client.dom.impl.DOMXImpl"/>
<when-property-is name="user.agent" value="opera"/>
</replace-with>
<replace-with class="org.puregwt.gwtaculous.client.dom.impl.DOMXImplSafari">
<when-type-is class="org.puregwt.gwtaculous.client.dom.impl.DOMXImpl"/>
<when-property-is name="user.agent" value="safari"/>
</replace-with>
<replace-with class="org.puregwt.gwtaculous.client.dom.impl.DOMXImplIE6">
<when-type-is class="org.puregwt.gwtaculous.client.dom.impl.DOMXImpl"/>
<when-property-is name="user.agent" value="ie6"/>
</replace-with>
<replace-with class="org.puregwt.gwtaculous.client.dom.impl.DOMXImplMozilla">
<when-type-is class="org.puregwt.gwtaculous.client.dom.impl.DOMXImpl"/>
<when-property-is name="user.agent" value="gecko1_8"/>
</replace-with>
<replace-with class="org.puregwt.gwtaculous.client.dom.impl.DOMXImplMozillaOld">
<when-type-is class="org.puregwt.gwtaculous.client.dom.impl.DOMXImpl"/>
<when-property-is name="user.agent" value="gecko"/>
</replace-with>
<entry-point class='org.puregwt.gwtaculous.client.GWTaculous'/>
</module>
So, GWT identifies the user agent and subs in the appropriate subclass to handle calls to DOMX. The code for DOMX looks like this:
public class DOMX {
private static DOMXImpl impl;
static {
impl = (DOMXImpl) GWT.create(DOMXImpl.class);
}
public static void setOpacity(Element e, double opacity) {
if (opacity < 0.00001) {
opacity = 0.0;
}
if (opacity > 1.0) {
opacity = 1.0;
}
impl.setOpacity(e, opacity);
}
public static double getOpacity(Element e) {
return impl.getOpacity(e);
}
public static void clearOpacity(Element e) {
impl.clearOpacity(e);
}
}
The
bounds checking for opacity is so that we don't get any non-sense
value, plus we don't want scientific notation, so we zero out values
that are too small.
The DOMXImpl class looks something like this:
public abstract class DOMXImpl {
public void setOpacity(Element e, double opacity) {
DOM.setStyleAttribute(e, "opacity", Double.toString(opacity));
}
public double getOpacity(Element e) {
// get the current opacity
String opacity = DOM.getStyleAttribute(e, "opacity");
if ((opacity == null) || (opacity.trim().equals(""))) {
return 1;
} else {
try {
return Double.parseDouble(opacity);
} catch (NumberFormatException ex) {
return 0;
}
}
}
public void clearOpacity(Element e) {
DOM.setStyleAttribute(e, "opacity", "");
}
}
Really
pretty self explanatory. We set the opacity attribute in the usual way.
The one place we really have to override this is in the IE6 class, DOMXImplIE6:
public class DOMXImplIE6 extends DOMXImpl {
public native void setOpacity(Element e, double opacity) /*-{
if (opacity == 1) {
e.style.filter = (e.style.filter || '').replace(/alpha\([^\)]*\)/gi,'');
} else {
e.style.filter = (e.style.filter || '').replace(/alpha\([^\)]*\)/gi,'') +
'alpha(opacity='+opacity*100+')';
}
}-*/;
public native double getOpacity(Element e) /*-{
var value;
if(value = (e.style.filter || '').match(/alpha\(opacity=(.*)\)/))
if(value[1]) return parseFloat(value[1]) / 100;
return 1.0;
}-*/;
public native void clearOpacity(Element e) /*-{
e.style.filter = (e.style.filter ||
'').replace(/alpha\([^\)]*\)/gi,'');
}-*/;
}
This overrides the
behavior for IE. The code is lifted almost straight out of Prototype.
At some point I'll bundles this up as a patch for GWT's DOM class. My
actual DOMX implementation has a bunch more utility methods, but this
is it as far as opacity is concerned (sorry, Opera needs something
special to enable opacity in certain elements). In the meantime, if
anyone has suggestions, I'm open to hearing them.
Technorati Tags: ajax, gwt, scriptaculous, styles, css, opacity, DOM, gwtaculous
Topics: Ajax Frameworks, CSS, GWT
Leave a comment
About Pathfinder
Recent
- Walk-Through Test Coverage
- Where minimalism fails: The problem with Apple’s less-is-more approach
- jQuery goodness with ASP .NET
- Design Thinking
- Bullseye Diagram
- Roles Testing For Security
- Blackbird takes the pain out of JavaScript logging
- Making GWT JSON not Quite so Painful
- IDEA - preconference workshop 06 Oct 08
- HTML5, Ajax history management, and The Ajax Experience 2008 Boston
Archives
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006

