]> source.dussan.org Git - gwtquery.git/commitdiff
Adding more testing and fixes
authorManolo Carrasco <manolo@apache.org>
Wed, 7 Jan 2015 11:58:29 +0000 (12:58 +0100)
committerManolo Carrasco <manolo@apache.org>
Wed, 7 Jan 2015 19:28:41 +0000 (20:28 +0100)
gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transform.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/TransitionsAnimation.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/SpecialEvent.java
gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java

index 14908568e9a664fb5bf29933e2c3c96d4a5e8a87..e1c0842b2ad2f657426833c7967df548ff5a19cf 100644 (file)
@@ -488,6 +488,35 @@ public class JsUtils {
     return a
   }-*/;
 
+  /**
+   * Call any arbitrary function present in a Javascript object.
+   * It checks the existence of the function and object hierarchy before executing it.
+   * It's very useful in order to avoid writing jsni blocks for very simple snippets.
+   *
+   * Note that GWT 3.0 jsinterop will come with a method similar, so we might deprecate
+   * this in the future.
+   *
+   * Example
+   * <pre>
+   *  // Create a svg node in our document.
+   *  Element svg = jsni(document, "createElementNS", "http://www.w3.org/2000/svg", "svg");
+   *  // Append it to the dom
+   *  $(svg).appendTo(document);
+   *  // show the svg element in the debug console
+   *  jsni("console.log", svg);
+   * </pre>
+   *
+   * @param jso the object containing the method to execute
+   * @param meth the literal name of the function to call, dot separators are allowed.
+   * @param args an array with the arguments to pass to the function.
+   * @return the java ready boxed object returned by the jsni method or null, if the
+   * call return a number we will get a Double, if it returns a boolean we get a java
+   * Boolean, strings comes as java String, otherwise we get the javascript object.
+   */
+  public static <T> T jsni(JavaScriptObject jso, String meth, Object... args) {
+    return runJavascriptFunction(jso, meth, args);
+  }
+
   /**
    * Run any arbitrary function in javascript scope using the window as the base object.
    * It checks the existence of the function and object hierarchy before executing it.
@@ -536,6 +565,8 @@ public class JsUtils {
    * @return the java ready boxed object returned by the jsni method or null, if the
    * call return a number we will get a Double, if it returns a boolean we get a java
    * Boolean, strings comes as java String, otherwise we get the javascript object.
+   *
+   * @deprecated use jsni instead.
    */
   public static <T> T runJavascriptFunction(JavaScriptObject o, String meth, Object... args) {
     return runJavascriptFunctionImpl(o, meth, JsObjectArray.create().add(args).<JsArrayMixed>cast());
index 762f4444687f218a91a3c8d14965945a67aa7b7e..36bee0df6eec0f5e8c195dccaf431786d5a37a95 100755 (executable)
@@ -21,6 +21,7 @@ import com.google.gwt.dom.client.Element;
 import com.google.gwt.query.client.Function;
 import com.google.gwt.query.client.GQuery;
 import com.google.gwt.query.client.Properties;
+import com.google.gwt.query.client.js.JsMap;
 import com.google.gwt.query.client.plugins.effects.Fx;
 import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
 import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.EasingCurve;
@@ -142,6 +143,30 @@ public class Effects extends QueuePlugin<Effects> {
     return Fx.off;
   }
 
+  /**
+   * Maintain a cache table with vendor properties so as plugins can use it.
+   */
+  public static JsMap<String, String>vendorPropNames;
+
+  /**
+   * Browser prefix for vendor spedific properties.
+   */
+  public static String prefix;
+
+  static {
+    if (GWT.isClient()) {
+      vendorPropNames = JsMap.create();
+      prefix  = browser.msie ? "ms" : browser.opera ? "o" : browser.mozilla ? "moz" : browser.webkit ? "webkit" : "";
+    }
+  }
+
+  /**
+   * Get the cached vendor property name.
+   */
+  public static String vendorProperty(String prop) {
+    return vendorPropNames.get(prop) != null ? vendorPropNames.get(prop) : prop;
+  }
+
   /**
    * The animate() method allows you to create animation effects on any numeric
    * Attribute, CSS property, or color CSS property.
index 3983791ac008cf5b1bf629f4ecf968a254dcc5df..56679a993e7a86ea558509de23d7826bf68d1c9b 100644 (file)
@@ -394,7 +394,7 @@ public class Events extends GQuery {
     dispatchEvent(evt, null, funcs);
   }
 
-  private void dispatchEvent(NativeEvent evt, Object[] datas, Function... funcs) {
+  public void dispatchEvent(NativeEvent evt, Object[] datas, Function... funcs) {
     for (Element e : elements()) {
       if (isEventCapable(e)) {
         $(e).data(EventsListener.EVENT_DATA, datas);
index 883fdf205ca125a622490b6d8990058dba8a14ce..9331124b8042177d4f7ec02adfbc57017466ad5e 100644 (file)
@@ -149,13 +149,17 @@ public class PropertiesAnimation extends GQAnimation {
 
   protected static final String[] ATTRS_TO_SAVE = new String[] {"overflow"};
 
-  private static final RegExp REGEX_NUMBER_UNIT = RegExp.compile("^([0-9+-.]+)(.*)?$");
+  protected static final String NUMBER = "[\\d+-.]+";
+  protected static final String UNIT = "[a-z%]+";
 
-  protected static final RegExp REGEX_SYMBOL_NUMBER_UNIT = RegExp
-      .compile("^([+-]=)?([0-9+-.]+)(.*)?$");
+  private static final RegExp REGEX_NUMBER_UNIT = RegExp.compile("^(" + NUMBER + ")(.*)?$");
 
-  protected static final RegExp REGEX_NON_PIXEL_ATTRS =
-      RegExp.compile("z-?index|font-?weight|opacity|zoom|line-?height|scale|rotat|skew|perspect|^\\$", "i");
+  protected static final RegExp REGEX_SYMBOL_NUMBER_UNIT = RegExp.compile("^([+-]=)?(" + NUMBER + ")(" + UNIT + ")?$");
+
+  protected static final RegExp REGEX_SCALE_ATTRS = RegExp.compile("scale|opacity");
+
+  protected static final RegExp REGEX_NON_PIXEL_ATTRS = RegExp.compile("scale|opacity"
+      + "|z-?index|font-?weight|zoom|line-?height|rotat|skew|perspect|^\\$", "i");
 
   private static final RegExp REGEX_COLOR_ATTR = RegExp.compile(".*color$", "i");
 
@@ -246,9 +250,6 @@ public class PropertiesAnimation extends GQAnimation {
       start = 0;
       unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px";
     } else if ("hide".equals(val)) {
-      if (hidden) {
-        return null;
-      }
       g.saveCssAttrs(key);
       end = 0;
       unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px";
index 000161473f76f381fbd081119b667708c7265e58..da0bb509de4005cea9014f6c941823b46e0fe131 100644 (file)
@@ -15,7 +15,9 @@
  */
 package com.google.gwt.query.client.plugins.effects;
 
-import static com.google.gwt.query.client.GQuery.browser;
+import static com.google.gwt.query.client.plugins.Effects.prefix;
+import static com.google.gwt.query.client.plugins.Effects.vendorPropNames;
+import static com.google.gwt.query.client.plugins.Effects.vendorProperty;
 
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
@@ -43,9 +45,20 @@ public class Transform  {
   protected static final Style divStyle = Document.get().createDivElement().getStyle();
 
   // Compute browser specific constants, public so as they are usable in plugins
-  public static final String prefix = browser.msie ? "ms" : browser.opera ? "o" : browser.mozilla ? "moz" : browser.webkit ? "webkit" : "";
-  public static final String transform = getVendorPropertyName("transform");
-  public static final String transformOrigin = getVendorPropertyName("transformOrigin");
+
+  static {
+    for (String s: new String[]{"transition", "transitionDelay", "transform", "transformOrigin"}) {
+      vendorPropNames.put(s, getVendorPropertyName(s));
+    }
+    // x,y,z are aliases
+    for (String s: new String[]{"x", "y", "z"}) {
+      vendorPropNames.put(s, "translate" + s.toUpperCase());
+    }
+  }
+
+  public static final String transform = vendorProperty("transform");
+  public static final String transformOrigin = vendorProperty("transformOrigin");
+
   // Non final for testing purposes.
   public static boolean has3d = supportsTransform3d();
 
@@ -88,6 +101,7 @@ public class Transform  {
     return null;
   }
 
+
   /**
    * Return the Transform dictionary object of a element.
    */
@@ -108,7 +122,10 @@ public class Transform  {
    */
   public static Transform getInstance(Element e, String initial) {
     Transform t = GQuery.data(e, TRANSFORM);
-    if (t == null || initial != null && !initial.isEmpty()) {
+    if (t == null || initial != null) {
+      if (initial == null) {
+        initial = GQuery.getSelectorEngine().getDocumentStyleImpl().curCSS(e, transform, false);
+      }
       t = new Transform(initial);
       GQuery.data(e, TRANSFORM, t);
     }
@@ -146,7 +163,7 @@ public class Transform  {
   private void parse(String s) {
     if (s != null) {
       for (MatchResult r = transformParseRegex.exec(s); r != null; r = transformParseRegex.exec(s)) {
-        setFromString(r.getGroup(1), r.getGroup(2));
+        setFromString(vendorProperty(r.getGroup(1)), r.getGroup(2));
       }
     }
   }
@@ -180,12 +197,6 @@ public class Transform  {
       map.put(prop, Arrays.asList(x, y));
     } else if ("perspective".equals(prop)) {
       map.put(prop, unit(val[0], "px"));
-    } else if ("x".equals(prop)) {
-      setter("translate", val[0], null);
-    } else if ("y".equals(prop)) {
-      setter("translate", null, val[0]);
-    } else if ("z".equals(prop)) {
-      setter("translate", null, null, val[0]);
     } else if (translatePropRegex.test(prop)) {
       map.put(prop, unit(val[0], "px"));
     } else if ("translate".equals(prop)) {
index bff2033441104824b7f185b47a3e5144630e0ec0..1bf8ad7d655c785e1e8d9949b1cf85c607248256 100644 (file)
 package com.google.gwt.query.client.plugins.effects;
 
 import static com.google.gwt.query.client.plugins.effects.Transform.getInstance;
-import static com.google.gwt.query.client.plugins.effects.Transform.getVendorPropertyName;
 import static com.google.gwt.query.client.plugins.effects.Transform.isTransform;
-import static com.google.gwt.query.client.plugins.effects.Transform.prefix;
 import static com.google.gwt.query.client.plugins.effects.Transform.transform;
-import static com.google.gwt.query.client.plugins.effects.Transform.transformOrigin;
 
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.query.client.Function;
@@ -48,6 +45,7 @@ import com.google.gwt.query.client.plugins.effects.TransitionsAnimation.Transiti
 import com.google.gwt.regexp.shared.RegExp;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -72,14 +70,13 @@ import java.util.List;
  */
 public class Transitions extends Effects {
 
-  protected static final String transition = getVendorPropertyName("transition");
-
   // passing an invalid transition property in chrome, makes disable all transitions in the element
   public static final RegExp invalidTransitionNamesRegex = RegExp.compile("^(.*transform.*|duration|function|easing|delay|clip-.*)$");
 
-  protected static final String transitionDelay = getVendorPropertyName("transitionDelay");
   protected static final String transitionEnd = browser.mozilla || browser.msie ? "transitionend" : (prefix + "TransitionEnd");
 
+  protected static final String transition = vendorProperty("transition");
+
   public static final Class<Transitions> Transitions = GQuery.registerPlugin(
       Transitions.class, new Plugin<Transitions>() {
         public Transitions init(GQuery gq) {
@@ -100,12 +97,9 @@ public class Transitions extends Effects {
 
   @Override
   public String css(String prop, boolean force) {
-    if ("transform".equals(prop)) {
+    prop = vendorProperty(prop);
+    if (transform.equals(prop)) {
       return isEmpty() ? "" : getInstance(get(0), null).toString();
-    } else if ("transformOrigin".equals(prop)) {
-      return super.css(transformOrigin, force);
-    } else if ("transition".equals(prop)) {
-      return super.css(transition, force);
     } else if (isTransform(prop)) {
       return isEmpty() ? "" : getInstance(get(0), null).get(prop);
     } else {
@@ -115,22 +109,19 @@ public class Transitions extends Effects {
 
   @Override
   public Transitions css(String prop, String value) {
-    if ("transform".equals(prop)) {
+    prop = vendorProperty(prop);
+    if (transform.equals(prop)) {
       for (Element e : elements()) {
-        Transform t = getInstance(e, value);
+        Transform t = getInstance(e, value != null ? value : "");
         getStyleImpl().setStyleProperty(e, transform, t.toString());
       }
-    } else if ("transformOrigin".equals(prop)) {
-      super.css(transformOrigin, value);
-    } else if ("transition".equals(prop)) {
-      super.css(transition, value);
     } else if (isTransform(prop)) {
       for (Element e : elements()) {
         Transform t = getInstance(e, null);
         t.setFromString(prop, value);
         getStyleImpl().setStyleProperty(e, transform, t.toString());
       }
-    } else if (!invalidTransitionNamesRegex.test(prop)) {
+    } else {
       super.css(prop, value);
     }
     return this;
@@ -206,4 +197,17 @@ public class Transitions extends Effects {
   protected GQAnimation createAnimation() {
     return new TransitionsAnimation();
   }
+
+  @Override
+  public boolean isVisible() {
+    for (String s : Arrays.asList("opacity", "scale", "scaleX", "scaleY", "scale3d", "width", "height")) {
+      String[] parts = css(s).split("\\s*,\\s*");
+      for (String p : parts) {
+        if (p.matches("^0[a-z%]*")) {
+          return false;
+        }
+      }
+    }
+    return super.isVisible();
+  }
 }
index 5a79e31179542b1884ddde67aa6920a413b80b39..5dcc56df38198136653070e13e0195b725a7af03 100644 (file)
@@ -67,7 +67,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
     }
 
     public void onStart() {
-      boolean hidden = !g.isVisible();
+      boolean hidden = !t.isVisible();
 
       super.onStart();
       if (action == null) {
@@ -96,7 +96,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
         originY = "bottom";
       }
 
-      g.show().css("transformOrigin", originX + " " + originY);
+      t.show().css("transformOrigin", originX + " " + originY);
 
       effects.add(new TransitFx("scale", "", scaleXini + " " + scaleYini, scaleXend + " " + scaleYend, ""));
     }
@@ -108,16 +108,16 @@ public class TransitionsAnimation extends PropertiesAnimation {
         return;
       }
       if (currentAction == Action.HIDE) {
-        g.hide();
+        t.hide();
       }
-      g.css("transformOrigin", "");
-      g.css("transform", "");
+      t.css("transformOrigin", "");
+      t.css("transform", "");
     }
   }
 
-  public static Fx computeFxProp(Element e, String key, String val, boolean hidden) {
+  public static TransitFx computeFxProp(Element e, String key, String val, boolean hidden) {
     Transitions g = $(e).as(Transitions.Transitions);
-    String unit = "";
+    String unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px";
     if ("toggle".equals(val)) {
       val = hidden ? "show" : "hide";
     }
@@ -135,9 +135,17 @@ public class TransitionsAnimation extends PropertiesAnimation {
 
     if ("show".equals(val)) {
       g.saveCssAttrs(key);
-      trsStart = "0";
+      if (trsStart.isEmpty()) {
+        trsStart = "0";
+      }
+      if (REGEX_SCALE_ATTRS.test(key)) {
+        trsEnd = "1";
+      }
     } else if ("hide".equals(val)) {
       g.saveCssAttrs(key);
+      if (trsStart.isEmpty() && REGEX_SCALE_ATTRS.test(key)) {
+        trsStart = "1";
+      }
       trsEnd = "0";
     } else {
       MatchResult parts = REGEX_SYMBOL_NUMBER_UNIT.exec(val);
@@ -148,15 +156,16 @@ public class TransitionsAnimation extends PropertiesAnimation {
         String part3 = parts.getGroup(3);
         trsEnd = "" + Double.parseDouble(part2);
 
-        unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" :  part3 == null || part3.isEmpty() ? "px" : part3;
+        if (part3 != null && !part3.isEmpty()) {
+          unit = part3;
+        }
 
         if (trsStart.isEmpty()) {
-          trsStart = key.matches("scale") ? "1" : "0";
+          trsStart = REGEX_SCALE_ATTRS.test(key) ? "1" : "0";
         }
 
         if (part1 != null && !part1.isEmpty()) {
           double n = "-=".equals(part1) ? -1 : 1;
-
           double st = 0;
           MatchResult sparts = REGEX_SYMBOL_NUMBER_UNIT.exec(trsStart);
           if (sparts != null) {
@@ -164,29 +173,39 @@ public class TransitionsAnimation extends PropertiesAnimation {
             unit = sparts.getGroup(3) == null || sparts.getGroup(3).isEmpty() ? unit : sparts.getGroup(3);
           }
           trsStart = "" + st;
-
           double en = Double.parseDouble(trsEnd);
           trsEnd = "" + (st + n * en);
         }
 
         // Deal with non px units like "%"
-        if (!unit.isEmpty() && !"px".equals(unit) && trsStart.matches("[-+]?[\\d.]+")) {
+        if (!unit.isEmpty() && !"px".equals(unit) && trsStart.matches(NUMBER)) {
           double start = Double.parseDouble(trsStart);
-          double to = Double.parseDouble(trsEnd);
-          g.css(key, to + unit);
-          start = to * start / g.cur(key, true);
-          trsStart = "" + start;
-          g.css(key, start + unit);
+          if (start != 0) {
+            double to = Double.parseDouble(trsEnd);
+            g.css(key, to + unit);
+            start = to * start / g.cur(key, true);
+            trsStart = "" + start;
+            g.css(key, start + unit);
+          }
         }
       } else {
         trsStart = "";
         trsEnd = val;
+        if (trsStart.isEmpty()) {
+          trsStart = REGEX_SCALE_ATTRS.test(key) ? "1" : "0";
+        }
       }
     }
+    if (trsStart.matches(NUMBER)) {
+      trsStart += unit;
+    }
+    if (trsEnd.matches(NUMBER)) {
+      trsEnd += unit;
+    }
     return new TransitFx(key, val, trsStart, trsEnd, unit);
   }
 
-  protected Transitions g;
+  protected Transitions t;
   protected int delay = 0;
   private String oldTransitionValue;
 
@@ -198,8 +217,9 @@ public class TransitionsAnimation extends PropertiesAnimation {
 
   @Override
   public GQAnimation setElement(Element elem) {
-    g = $(elem).as(Transitions.Transitions);
-    return super.setElement(elem);
+    e = elem;
+    g = t = $(elem).as(Transitions.Transitions);
+    return this;
   }
 
   public TransitionsAnimation setDelay(int delay) {
@@ -213,7 +233,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
       TransitFx fx = (TransitFx) effects.get(i);
       String val = isStart ? fx.transitStart : fx.transitEnd;
       if (!val.isEmpty()) {
-        p.set(fx.cssprop, val + fx.unit);
+        p.set(fx.cssprop, val);
       }
     }
     return p;
@@ -230,7 +250,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
 
   @Override
   public void onComplete() {
-    g.css(Transitions.transition, oldTransitionValue);
+    t.css(Transitions.transition, oldTransitionValue);
     super.onComplete();
   }
 
@@ -239,15 +259,15 @@ public class TransitionsAnimation extends PropertiesAnimation {
     onStart();
     // Compute initial properties
     Properties p = getFxProperties(true);
-    g.css(p);
+    t.css(p);
     // Some browsers need re-flow after setting initial properties (FF 24.4.0).
-    g.offset();
+    t.offset();
 
     // Compute final properties
     p = getFxProperties(false);
 
     // Save old transition value
-    oldTransitionValue = g.css(Transitions.transition);
+    oldTransitionValue = t.css(Transitions.transition);
 
     // Set new transition value
     String newTransitionValue  = "";
@@ -256,10 +276,10 @@ public class TransitionsAnimation extends PropertiesAnimation {
     for (String s : transProps) {
       newTransitionValue += (newTransitionValue.isEmpty() ? "" : ", ") + s + " " + attribs;
     }
-    g.css(Transitions.transition, newTransitionValue);
+    t.css(Transitions.transition, newTransitionValue);
 
     // Set new css properties so as the element is animated
-    g.css(p);
+    t.css(p);
 
     // Wait until transition has finished to run finish animation and dequeue
     new Timer() {
index 7d88ac7c3ea612d603b52771b7162f376c10483d..94dcc501d4d157073d60e9668e7cb2ccc5dc8727 100644 (file)
@@ -14,6 +14,7 @@
 package com.google.gwt.query.client.plugins.events;
 
 import static com.google.gwt.query.client.GQuery.$;
+import static com.google.gwt.query.client.GQuery.console;
 
 import com.google.gwt.core.client.Duration;
 import com.google.gwt.dom.client.Element;
@@ -641,6 +642,11 @@ public class EventsListener implements EventListener {
   }
 
   public void onBrowserEvent(Event event) {
+//    console.log("onBrowser", event.getType(), event, element);
+    if (JsUtils.isDefaultPrevented(event)) {
+      console.log("RETTT");
+      return;
+    }
     double now = Duration.currentTimeMillis();
     // Workaround for Issue_20
     if (lastType.equals(event.getType()) && now - lastEvnt < 10
@@ -688,9 +694,18 @@ public class EventsListener implements EventListener {
    * given eventBit or eventName.
    */
   public boolean hasHandlers(int eventBits, String eventName) {
+    return hasHandlers(eventBits, eventName, null);
+  }
+
+  /**
+   * Return true if the element is listening for the
+   * given eventBit or eventName and the handler matches.
+   */
+  public boolean hasHandlers(int eventBits, String eventName, Function handler) {
     for (int i = 0, j = elementEvents.length(); i < j; i++) {
       BindFunction function = elementEvents.get(i);
-      if (function.hasEventType(eventBits) || function.isTypeOf(eventName)) {
+      if ((function.hasEventType(eventBits) || function.isTypeOf(eventName))
+         && (handler == null || function.isEquals(handler))) {
         return true;
       }
     }
index 8083b098cbbe964b1de4cf0533ccca236db11b8a..f45b32a9d585cae017477a9eb74ee3aaff926c1a 100644 (file)
@@ -57,7 +57,7 @@ public interface SpecialEvent {
 
     @Override
     public boolean hasHandlers(Element e) {
-      return listener(e).hasHandlers(Event.getTypeInt(type), type);
+      return listener(e).hasHandlers(Event.getTypeInt(type), type, handler);
     }
 
     @Override
index 0b21080265f27c38f7d7bc48d32acb82b3453002..eba3fe6dcba0d74c135231a5596d5fe93da66767 100644 (file)
@@ -32,6 +32,7 @@ import com.google.gwt.query.client.plugins.effects.Fx.TransitFx;
 import com.google.gwt.query.client.plugins.effects.PropertiesAnimation;
 import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.EasingCurve;
 import com.google.gwt.query.client.plugins.effects.Transform;
+import com.google.gwt.query.client.plugins.effects.Transitions;
 import com.google.gwt.query.client.plugins.effects.TransitionsAnimation;
 import com.google.gwt.query.client.plugins.effects.TransitionsAnimation.TransitionsClipAnimation;
 import com.google.gwt.user.client.Timer;
@@ -263,6 +264,12 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
     assertEquals("cssprop=padding value=20px start=5 end=20 unit=px",
         PropertiesAnimation.computeFxProp(g.get(0), "padding", "20px", false)
             .toString());
+    assertEquals("cssprop=opacity value=show start=0 end=1 unit=",
+        PropertiesAnimation.computeFxProp(g.get(0), "opacity", "toggle", true)
+            .toString());
+    assertEquals("cssprop=opacity value=hide start=1 end=0 unit=",
+        PropertiesAnimation.computeFxProp(g.get(0), "opacity", "toggle", false)
+            .toString());
 
     prop1 = GQuery.$$("marginTop: '-110px', marginLeft: '-110px', top: '50%', left: '50%', width: '174px', height: '174px', padding: '20px'");
     GQAnimation an = new PropertiesAnimation().setEasing(EasingCurve.swing).setElement(g.get(0)).setProperties(prop1);
@@ -316,6 +323,67 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
             .toString());
   }
 
+  private void assertTransitFx(TransitFx fx, String prop, String val, String unit, String start, String end) {
+    assertEquals(prop, fx.cssprop);
+    assertEquals(val, fx.value);
+    assertEquals(unit, fx.unit);
+    if (!start.contains(".")) {
+      // discard decimals
+      assertEquals(start, fx.transitStart.replaceAll("\\.\\d+([a-z%]*)$", "$1"));
+    } else {
+      assertEquals(start, fx.transitStart);
+    }
+    if (!end.contains(".")) {
+      // discard decimals
+      assertEquals(end, fx.transitEnd.replaceAll("\\.\\d+([a-z%]*)$", "$1"));
+    } else {
+      assertEquals(end, fx.transitEnd);
+    }
+  }
+
+  public void testTransitionsCss() {
+    $(e).html("<div>");
+    Transitions t = $("div", e).as(Transitions.Transitions);
+
+    t.css("transform", "scale(1,2) rotateX(5deg) x(7) y(8)");
+    assertEquals("1,2", t.css("scale"));
+    assertEquals("7px", t.css("x"));
+    assertEquals("7px", t.css("translateX"));
+    t.css("y", "8");
+    assertEquals("8px", t.css("y"));
+    assertEquals("8px", t.css("translateY"));
+  }
+
+  public void testTransitionsAnimationComputeEffects() {
+    $(e)
+        .html(
+            "<div id='parent' style='background-color: yellow; width: 100px; height: 200px; top:130px; position: absolute; left: 130px'>"
+            + "<p id='child' style='opacity: 0.7; background-color: pink; width: 100px; height: 100px; position: absolute; padding: 5px; margin: 0px'>Content 1</p></div>");
+    GQuery g = $("#child");
+    TransitFx f;
+
+    f = TransitionsAnimation.computeFxProp(g.get(0), "rotateY", "90deg", false);
+    assertTransitFx(f, "rotateY", "90deg", "deg", "0deg", "90deg");
+
+    f = TransitionsAnimation.computeFxProp(g.get(0), "marginTop", "-110px", false);
+    assertTransitFx(f, "marginTop", "-110px", "px", "0px", "-110px");
+
+    f = TransitionsAnimation.computeFxProp(g.get(0), "opacity", "toggle", false);
+    assertTransitFx(f, "opacity", "hide", "", "0.7", "0");
+
+    f = TransitionsAnimation.computeFxProp(g.get(0), "scaleX", "show", true);
+    assertTransitFx(f, "scaleX", "show", "", "0", "1");
+
+    f = TransitionsAnimation.computeFxProp(g.get(0), "width", "toggle", false);
+    assertTransitFx(f, "width", "hide", "px", "100px", "0px");
+
+    f = TransitionsAnimation.computeFxProp(g.get(0), "width", "+=45", false);
+    assertTransitFx(f, "width", "+=45", "px", "100px", "145px");
+
+    f = TransitionsAnimation.computeFxProp(g.get(0), "width", "100%", false);
+    assertTransitFx(f, "width", "100%", "%", "100px", "100%");
+  }
+
   public void testTransformParser() {
     Transform.has3d = true;
     Transform t = new Transform("scaleZ(0.5) rotateZ(90deg) skewX(4) rotateY(45) scale(1, 1) x(10) y(12) z(14) matrix(1, 2,3 ,4)");
@@ -363,8 +431,8 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
     assertEquals("60px", to.getStr("top").replace(".0", ""));
     assertEquals("0", from.getStr("rotateZ").replace(".0", ""));
     assertEquals("90", to.getStr("rotateZ").replace(".0", ""));
-    assertEquals("0", from.getStr("rotateY").replace(".0", ""));
-    assertEquals("45", to.getStr("rotateY").replace(".0", ""));
+    assertEquals("0deg", from.getStr("rotateY").replace(".0", ""));
+    assertEquals("45deg", to.getStr("rotateY").replace(".0", ""));
     assertEquals("0 0", from.getStr("scale").replace(".0", ""));
     assertEquals("1 1", to.getStr("scale"));
     assertNull(to.get("delay"));
@@ -452,16 +520,6 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
     timer.schedule(duration * 2);
   }
 
-  public void testComputeFxPropTransitions() {
-    $(e).html("<div id='idtest' style='width: 200px; height 200px; border: solid 1px; position: absolute' ></div>");
-    final GQuery g = $("#idtest", e);
-
-    TransitFx fx = (TransitFx)TransitionsAnimation.computeFxProp(g.get(0), "width", "+=100", false);
-    assertEquals("200", fx.transitStart.replace(".0",""));
-    assertEquals("300", fx.transitEnd.replace(".0",""));
-    assertEquals("px", fx.unit);
-  }
-
   public void testStop() {
     $(e)
     .html(