]> source.dussan.org Git - gwtquery.git/commitdiff
Allow to use customized animations. And Fixes.
authorManolo Carrasco <manolo@apache.org>
Sat, 3 Jan 2015 19:03:49 +0000 (20:03 +0100)
committerManolo Carrasco <manolo@apache.org>
Sat, 3 Jan 2015 19:48:21 +0000 (20:48 +0100)
In this patch there are many fixes found when playing with plugins.
Also I have refactored Effects and Transitions plugins so as it is
easier to extend and implement customized animations.
Now we use properties instead of the Fx.css3 hack to disable modern
animations.

14 files changed:
gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml
gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml
gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java
gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java
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/effects/ClipAnimation.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.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 [new file with mode: 0644]
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/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java
gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java

index 08a6ff116c6453d9b94410e529fdca7cbc70b5bd..9bbc7431b0ea713c0a3512df8a1d6b1ba0fe710b 100644 (file)
      -->
     <define-linker name="stddoctype" class="com.google.gwt.query.linker.IFrameWithDocTypeLinker"/>
 
+    <!-- Let the user select type of animations to use -->
+    <define-property name="animation" values="js,transition" />
+    <set-property name="animation" value="transition" />
+    <set-property name="animation" value="js">
+        <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>
+    </set-property>
+    <!-- Animations based on JS loops -->
+    <replace-with class="com.google.gwt.query.client.plugins.effects.ClipAnimation">
+        <when-type-assignable
+            class="com.google.gwt.query.client.plugins.Effects.GQAnimation" />
+        <when-property-is name="animation" value="js" />
+    </replace-with>
+    <!-- Animations based on CSS3 transitions -->
+    <replace-with class="com.google.gwt.query.client.plugins.effects.TransitionsAnimation.TransitionsClipAnimation">
+        <when-type-assignable
+            class="com.google.gwt.query.client.plugins.Effects.GQAnimation" />
+        <when-property-is name="animation" value="transition" />
+    </replace-with>
 </module>
index 28cfea6cc471f115c0b3db879c1525707f5de8db..f21b6ba51bfcbe7dce1e4a622e35b22512736468 100644 (file)
 
     <!-- Inherit GQuery module -->
     <inherits name='com.google.gwt.query.Query'/>
-    
+
     <source path="client"/>
-    <super-source path="super"/>    
-    
+    <super-source path="super"/>
+
     <!-- Detect whether querySelectorAll is available -->
     <define-property name="selectorCapability" values="native,js"/>
     <property-provider name="selectorCapability">
         <when-property-is name="user.agent" value="ie6" />
     </set-property>
     <set-property name="selectorCapability" value="native" >
-        <any>
-            <when-property-is name="user.agent" value="safari" />
-        </any>
+        <when-property-is name="user.agent" value="safari" />
     </set-property>
-    
+
     <!-- Selector Engines -->
     <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeMin">
         <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
index 063aaf389ded7725751220bf0c18bc0591287246..bd5e9be14bd95b76c7d0377b13dc239dd85ddbcb 100644 (file)
@@ -35,11 +35,11 @@ public abstract class Function {
    * Utility method to get a string representation with the content
    * of the arguments array. It recursively visits arrays and inspect
    * object to print an appropriate representation of them.
-   * 
+   *
    * It is very useful to debug arguments passed in nested promises.
-   * 
+   *
    * It is protected so as it can be used in Inner functions.
-   * 
+   *
    * Output example:
    * <pre>
    * [0](com.google.gwt.query.client.plugins.QueuePlugin) <div>a1</div><div>a2</div>
@@ -124,7 +124,7 @@ public abstract class Function {
 
   /**
    * Return the first element of the arguments list.
-   * 
+   *
    * @deprecated use getArgument(idx) instead.
    */
   @Deprecated
@@ -143,7 +143,7 @@ public abstract class Function {
   /**
    * Utility method for safety getting a JavaScriptObject present at a certain
    * position in the list of arguments composed by arrays.
-   * 
+   *
    */
   @SuppressWarnings("unchecked")
   public <T extends JavaScriptObject> T getArgumentJSO(int argIdx, int pos) {
@@ -161,10 +161,10 @@ public abstract class Function {
   /**
    * Utility method for safety getting an array present at a certain
    * position in the list of arguments.
-   * 
+   *
    * Useful for Deferred chains where result of each resolved
    * promise is set as an array in the arguments list.
-   * 
+   *
    * Always returns an array.
    */
   public Object[] getArgumentArray(int idx) {
@@ -179,7 +179,7 @@ public abstract class Function {
 
   /**
    * Return the argument in the position idx or null if it doesn't exist.
-   * 
+   *
    * Note: if the return type doesn't match the object, you
    * will get a casting exception.
    */
@@ -204,7 +204,7 @@ public abstract class Function {
 
   /**
    * Safety return the argument in the position idx.
-   * 
+   *
    * If the element class is not of the requested type it returns null and
    * you don't get casting exeption.
    */
@@ -214,7 +214,7 @@ public abstract class Function {
 
   /**
    * Safety return the argument in the position idx.
-   * 
+   *
    * If the element class is not of the requested type it returns null and
    * you don't get casting exeption.
    */
@@ -225,15 +225,15 @@ public abstract class Function {
   /**
    * Utility method for safety getting an object present at a certain
    * position in the list of arguments composed by arrays.
-   * 
+   *
    * Useful for Deferred chains where result of each resolved
    * promise is set as an array in the arguments list.
-   * 
+   *
    * When the object found in the array doesn't match the type required it returns a null.
-   * 
+   *
    * Note: If type is null, we don't check the class of the object found andd you could
    * eventually get a casting exception.
-   * 
+   *
    */
   @SuppressWarnings("unchecked")
   public <T> T getArgument(int argIdx, int pos, Class<? extends T> type) {
@@ -302,7 +302,7 @@ public abstract class Function {
 
   /**
    * Return the index in a loop execution.
-   * 
+   *
    * Used in GQuery.each()
    */
   public int getIndex() {
@@ -427,6 +427,8 @@ public abstract class Function {
   /**
    * Override this method for bound event handlers if you wish to deal with
    * per-handler user data.
+   *
+   * @return boolean false means stop propagation and prevent default
    */
   public boolean f(Event e, Object... arg) {
     setArguments(arg);
@@ -437,7 +439,7 @@ public abstract class Function {
   /**
    * Override this method for bound event handlers.
    *
-   * @return boolean: false means stop propagation and prevent default
+   * @return boolean false means stop propagation and prevent default
    */
   public boolean f(Event e) {
     setEvent(e);
index 13f6c4a3f56b3ae225466865a68d5829db6c1545..2862ee0f0bc09e7da17145610817d5a0d7ffe78e 100644 (file)
@@ -135,7 +135,7 @@ public class JsCache extends JavaScriptObject {
   }
 
   public final native boolean isEmpty() /*-{
-    for (k in this) return false;
+    for (k in this) if (this.hasOwnProperty(k)) return false;
     return true;
   }-*/;
 
@@ -240,7 +240,7 @@ public class JsCache extends JavaScriptObject {
     var key, keys=[];
     // Chrome in DevMode sets '__gwt_ObjectId' to JS objects
     // GWT sets '$H' when calling getHashCode (see com/google/gwt/core/client/impl/Impl.java)
-    for(key in this) if (key != '__gwt_ObjectId' && key != '$H') keys.push(String(key));
+    for(key in this) if (this.hasOwnProperty(key) && key != '__gwt_ObjectId' && key != '$H') keys.push(String(key));
     return keys;
   }-*/;
 
index 13520fe400e4d2655cb6225e8f0236809c4b6643..ecd7c6a8296302ac76b070f6f1f9d786c9032581 100644 (file)
  */
 package com.google.gwt.query.client.js;
 
+import static com.google.gwt.query.client.GQuery.browser;
+
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.core.client.JsArray;
 import com.google.gwt.core.client.JsArrayMixed;
+import com.google.gwt.core.client.JsonUtils;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.Node;
@@ -90,9 +93,9 @@ public class JsUtils {
    * Default JsUtils implementation.
    */
   public static class JsUtilsImpl {
-    public native Properties parseJSON(String json) /*-{
-      return $wnd.JSON.parse(json);
-    }-*/;
+    public Properties parseJSON(String json) {
+      return JsonUtils.safeEval(json);
+    }
 
     public native String JSON2String(JavaScriptObject o) /*-{
       return $wnd.JSON.stringify(o);
@@ -129,15 +132,9 @@ public class JsUtils {
    * IE JsUtils implemetation.
    */
   public static class JsUtilsImplIE6 extends JsUtilsImpl {
-    public static final native Properties evalImpl(String properties) /*-{
-      return eval(properties);
-    }-*/;
-
     @Override
     public Properties parseJSON(String json) {
-      // No checks to the passed string so json should be
-      // a well-formed json string.
-      return evalImpl("(" + json + ")");
+      return JsonUtils.unsafeEval(json);
     }
 
     @Override
@@ -190,7 +187,7 @@ public class JsUtils {
     @Override
     public JsArray<Element> unique(JsArray<Element> a) {
       // in IE6 XML elements does not support adding hashId to the object
-      if (a.length() > 0 && isXML(a.get(0))) {
+      if (browser.ie6 && isXML(a.get(0))) {
         return a;
       }
       return super.unique(a);
@@ -299,11 +296,23 @@ public class JsUtils {
   }
 
   /**
-   * Check if an object has already a property with name <code>name</code>
-   * defined.
+   * Check if an object has a property with <code>name</code> defined.
+   * It supports dots in the name meaning checking nested properties.
+   *
+   * Example:
+   * <pre>
+   *  // Check whether a browser supports touch events
+   *  hasProperty(window, "ontouchstart");
+   * </pre>
    */
-  public static native boolean hasProperty(JavaScriptObject o, String name) /*-{
+  public static native boolean hasProperty(JavaScriptObject o, String name)/*-{
     return o && name in o;
+    var p = name.split('.');
+    for (var i in p) {
+      if (!(o && p[i] in o)) return false;
+      o = o[p[i]];
+    }
+    return true;
   }-*/;
 
   /**
@@ -348,7 +357,7 @@ public class JsUtils {
 
   /**
    * Return whether a node is detached to the DOM.
-   * 
+   *
    * Be careful : This method works only on node that should be inserted within the body node.
    */
   public static boolean isDetached(Node n) {
@@ -480,6 +489,34 @@ public class JsUtils {
     return a
   }-*/;
 
+  /**
+   * 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.
+   * 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 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(String meth, Object... args) {
+    return runJavascriptFunction(null, meth, args);
+  }
+
   /**
    * Call via jsni any arbitrary function present in a Javascript object.
    *
@@ -494,20 +531,25 @@ public class JsUtils {
    *  $(svg).appendTo(document);
    * </pre>
    *
-   * @param o  the javascript object where the function is.
-   * @param meth the literal name of the function to call.
+   * @param o  the javascript object where the function is, it it is null we use window.
+   * @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 javascript object returned by the jsni method or null.
+   * @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 runJavascriptFunction(JavaScriptObject o, String meth, Object... args) {
-    return runJavascriptFunctionImpl(o, meth, JsObjectArray.create().add(args)
-        .<JsArrayMixed> cast());
+    return runJavascriptFunctionImpl(o, meth, JsObjectArray.create().add(args).<JsArrayMixed>cast());
   }
 
-  private static native <T> T runJavascriptFunctionImpl(JavaScriptObject o, String meth,
-      JsArrayMixed args) /*-{
-    return (f = o && o[meth])
-        && @com.google.gwt.query.client.js.JsUtils::isFunction(*)(f)
+  private static native <T> T runJavascriptFunctionImpl(JavaScriptObject o, String meth, JsArrayMixed args) /*-{
+    var f = o || window, p = meth.split('.');
+    for (var i in p) {
+      o = f;
+      f = f[p[i]];
+      if (!f) return null;
+    }
+    return @com.google.gwt.query.client.js.JsUtils::isFunction(*)(f)
         && @com.google.gwt.query.client.js.JsCache::gwtBox(*)([f.apply(o, args)]);
   }-*/;
 
@@ -542,7 +584,7 @@ public class JsUtils {
 
   /**
    * Returns a QueryString representation of a JavascriptObject.
-   * 
+   *
    * TODO: jquery implementation accepts a second parameter (traditional)
    */
   public static String param(JavaScriptObject js) {
index acb7fc17345ac375a153d18d07f0c7472b01b24d..762f4444687f218a91a3c8d14965945a67aa7b7e 100755 (executable)
 package com.google.gwt.query.client.plugins;
 
 import com.google.gwt.animation.client.Animation;
+import com.google.gwt.core.client.GWT;
 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.plugins.effects.ClipAnimation;
-import com.google.gwt.query.client.plugins.effects.ClipAnimation.Direction;
 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;
-import com.google.gwt.query.client.plugins.effects.TransitionsAnimation.TransitionsClipAnimation;
 
 /**
  * Effects plugin for Gwt Query.
@@ -42,14 +40,34 @@ public class Effects extends QueuePlugin<Effects> {
     // Each Animation is associated to one element
     protected Element e;
     protected Properties prps;
+    protected Easing easing;
+    protected Function[] funcs;
+    protected Effects g;
 
-    protected GQAnimation setElement(Element element) {
+    public GQAnimation setElement(Element element) {
       e = element;
+      g = $(e).as(Effects);
       return this;
     }
 
-    protected GQAnimation setProperties(Properties properties) {
+    public GQAnimation setProperties(Properties properties) {
       prps = properties == null ? Properties.create() : properties;
+      if (prps.defined("easing")) {
+        try {
+          easing = EasingCurve.valueOf(prps.getStr("easing"));
+        } catch (Exception ignore) {
+        }
+      }
+      return this;
+    }
+
+    public GQAnimation setEasing(Easing ease) {
+      easing = ease != null ? ease : EasingCurve.swing;
+      return this;
+    }
+
+    public GQAnimation setCallback(Function... f) {
+      funcs = f;
       return this;
     }
 
@@ -92,12 +110,20 @@ public class Effects extends QueuePlugin<Effects> {
     super(gq);
   }
 
-  private void queueAnimation(final Element e, final GQAnimation anim, final int duration) {
+  /**
+   * Queue an animation for an element.
+   *
+   * The goal of this method is to reuse animations.
+   * @param e
+   * @param anim
+   * @param duration
+   */
+  public void queueAnimation(final GQAnimation anim, final int duration) {
     if (isOff()) {
       anim.onStart();
       anim.onComplete();
     } else {
-      queue(e, DEFAULT_NAME, new Function() {
+      queue(anim.e, DEFAULT_NAME, new Function() {
         public void cancel(Element e) {
           Animation anim = (Animation) data(e, GQAnimation.ACTUAL_ANIMATION, null);
           if (anim != null) {
@@ -169,7 +195,6 @@ public class Effects extends QueuePlugin<Effects> {
    * @param easing the easing function to use for the transition
    */
   public Effects animate(Object stringOrProperties, int duration, Easing easing, Function... funcs) {
-
     final Properties p = (stringOrProperties instanceof String)
         ? (Properties) $$((String) stringOrProperties)
         : (Properties) stringOrProperties;
@@ -177,19 +202,25 @@ public class Effects extends QueuePlugin<Effects> {
     if (p.getStr("duration") != null) {
       duration = p.getInt("duration");
     }
-
     duration = Math.abs(duration);
 
     for (Element e : elements()) {
-      if (Fx.css3) {
-        new TransitionsClipAnimation(easing, e, p, funcs).run(duration);
-      } else {
-        queueAnimation(e, new ClipAnimation(easing, e, p, funcs), duration);
-      }
+      GQAnimation a = createAnimation();
+      a.setEasing(easing).setProperties(p).setElement(e).setCallback(funcs);
+      queueAnimation(a, duration);
     }
     return this;
   }
 
+  /**
+   * Override this to create plugins with customized animation implementation.
+   *
+   * By default it uses deferred binding.
+   */
+  protected GQAnimation createAnimation() {
+    return GWT.create(GQAnimation.class);
+  }
+
   /**
    *
    * The animate() method allows you to create animation effects on any numeric
@@ -308,53 +339,6 @@ public class Effects extends QueuePlugin<Effects> {
     return animate(stringOrProperties, duration, EasingCurve.linear, funcs);
   }
 
-  /**
-   * Animate the set of matched elements using the clip or scale property. It is possible to show or
-   * hide a set of elements, specify the direction of the animation and the start corner of the
-   * effect. Finally it executes the set of functions passed as arguments.
-   *
-   * @deprecated use animate() instead
-   */
-  @Deprecated
-  public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c,
-      ClipAnimation.Direction d, Function... f) {
-    return clip(a, c, d, Speed.DEFAULT, f);
-  }
-
-  /**
-   * Animate the set of matched elements using the clip or scale property. It is possible to show or
-   * hide a set of elements, specify the direction of the animation and the start corner of the
-   * effect. Finally it executes the set of functions passed as arguments.
-   *
-   * @deprecated use animate() instead
-   */
-  @Deprecated
-  public Effects clip(final ClipAnimation.Action a,
-      final ClipAnimation.Corner c, final ClipAnimation.Direction d,
-      final int duration, final Function... f) {
-    for (Element e : elements()) {
-      if (Fx.css3) {
-        new TransitionsClipAnimation(e, a, c, d, null, null, f).run(duration);
-      } else {
-        queueAnimation(e, new ClipAnimation(e, a, c, d, f), duration);
-      }
-    }
-    return this;
-  }
-
-  /**
-   * Animate the set of matched elements using the clip or scale property. It is possible to show or
-   * hide a set of elements, specify the direction of the animation and the start corner of the
-   * effect. Finally it executes the set of functions passed as arguments.
-   *
-   * @deprecated use animate() instead
-   */
-  @Deprecated
-  public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c,
-      Function... f) {
-    return clip(a, c, Direction.BIDIRECTIONAL, Speed.DEFAULT, f);
-  }
-
   /**
    * Reveal all matched elements by adjusting the clip or scale property firing an optional callback
    * after completion. The effect goes from the center to the perimeter.
index 627c0b4732ab5b6aa0b40a081a493597483b2218..6794d1c16b9017762480baa958e8f5e63d6244e3 100755 (executable)
  */
 package com.google.gwt.query.client.plugins.effects;
 
-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.JsUtils;
 import com.google.gwt.query.client.plugins.Effects;
+import com.google.gwt.query.client.plugins.Effects.GQAnimation;
 
 /**
  * Animation which uses the css clip property to show/hide an element.
@@ -55,15 +54,10 @@ public class ClipAnimation extends PropertiesAnimation {
   private Corner corner;
   private Direction direction;
   private GQuery back = Effects.$();
-  private Effects g;
   private Action currentAction;
 
-  public ClipAnimation(Element elem, Properties p, Function... funcs) {
-    this(null, elem, p, funcs);
-  }
-
-  public ClipAnimation(Easing easing, Element elem, Properties p, Function... funcs) {
-    super(easing, elem, p, funcs);
+  @Override
+  public GQAnimation setProperties(Properties p) {
     corner = Corner.CENTER;
     try {
       corner = Corner.valueOf(getNormalizedValue("clip-origin", p));
@@ -78,26 +72,13 @@ public class ClipAnimation extends PropertiesAnimation {
       action = Action.valueOf(getNormalizedValue("clip-action", p));
     } catch (Exception e) {
     }
-    g = GQuery.$(e).as(Effects.Effects);
+    return super.setProperties(p);
   }
 
   public static String getNormalizedValue(String value, Properties p) {
     return JsUtils.hyphenize(p.getStr(value)).replace("-", "_").toUpperCase();
   }
 
-  public ClipAnimation(Element elem, Action a, Corner c, Direction d, Easing easing,
-      Properties p, final Function... funcs) {
-    super(easing, elem, p, funcs);
-    this.action = a;
-    this.corner = c;
-    this.direction = d;
-    g = GQuery.$(e).as(Effects.Effects);
-  }
-
-  public ClipAnimation(Element elem, Action a, Corner c, Direction d, final Function... funcs) {
-    this(elem, a, c, d, null, Properties.create(), funcs);
-  }
-
   @Override
   public void onComplete() {
     super.onComplete();
index b81a9de9c63d1585575472a20ac4463721845ea4..1e202e33f031e8b77bacc6e773770c7b9d66941a 100644 (file)
@@ -33,8 +33,6 @@ public class Fx {
    */
   public static boolean off = false;
 
-  public static boolean css3 = Transitions.transition != null;
-
   /**
    * A pojo to store css3 transition values.
    */
index e5a4c8f6abfc4ed963646df90ae53edbd77a4cda..ceb6b556418691f4c6c167acb4b51c9d77d01f22 100644 (file)
  */
 package com.google.gwt.query.client.plugins.effects;
 
-import static com.google.gwt.query.client.GQuery.$;
-
 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.JsObjectArray;
 import com.google.gwt.query.client.plugins.Effects;
 import com.google.gwt.query.client.plugins.Effects.GQAnimation;
@@ -159,7 +155,7 @@ public class PropertiesAnimation extends GQAnimation {
       .compile("^([+-]=)?([0-9+-.]+)(.*)?$");
 
   protected static final RegExp REGEX_NON_PIXEL_ATTRS =
-      RegExp.compile("z-?index|font-?weight|opacity|zoom|line-?height|scale|rotation|^\\$", "i");
+      RegExp.compile("z-?index|font-?weight|opacity|zoom|line-?height|scale|rotat|^\\$", "i");
 
   private static final RegExp REGEX_COLOR_ATTR = RegExp.compile(".*color$", "i");
 
@@ -173,7 +169,6 @@ public class PropertiesAnimation extends GQAnimation {
     if (REGEX_COLOR_ATTR.test(key)) {
       return computeFxColorProp(e, key, val);
     }
-
     return computeFxNumericProp(e, key, val, hidden);
   }
 
@@ -288,32 +283,7 @@ public class PropertiesAnimation extends GQAnimation {
     return new Fx(key, val, start, end, unit, rkey);
   }
 
-  protected Easing easing;
   protected JsObjectArray<Fx> effects;
-  private Function[] funcs;
-  private Effects g;
-
-  public PropertiesAnimation(Element elem, Properties p, Function... funcs) {
-    this(null, elem, p, funcs);
-  }
-
-  public PropertiesAnimation(Easing ease, Element elem, Properties p, Function... funcs) {
-    try {
-      easing = EasingCurve.valueOf(p.getStr("easing"));
-    } catch (Exception e) {
-    }
-    if (easing == null) {
-      easing = ease;
-    }
-    if (easing == null) {
-      easing = EasingCurve.swing;
-    }
-    this.funcs = funcs;
-    setProperties(p);
-    setElement(elem);
-
-    g = $(e).as(Effects.Effects);
-  }
 
   @Override
   public void onCancel() {
@@ -329,7 +299,7 @@ public class PropertiesAnimation extends GQAnimation {
   @Override
   public void onComplete() {
     super.onComplete();
-    for (int i = 0; i < effects.length(); i++) {
+    for (int i = 0; effects != null && i < effects.length(); i++) {
       Fx fx = effects.get(i);
       if ("hide".equals(fx.value)) {
         g.hide();
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transform.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transform.java
new file mode 100644 (file)
index 0000000..641a02c
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2014, The gwtquery team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.plugins.effects;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.query.client.GQuery;
+import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+/**
+ * A dictionary class with all the properties of an element transform
+ * which is able to return the correct syntax for setting the css transform
+ * property.
+ */
+public class Transform  {
+
+  private static final String TRANSFORM = "_t_";
+
+  protected static final RegExp transformRegex = RegExp.compile("^(scale([XYZ]|)|translate([XYZ]|3d)|rotate([XYZ]|3d)?|perspective|skew[XYZ]|x|y)$");
+  private static final RegExp transform3dRegex = RegExp.compile("^(rotate([XYZ]|3d)|perspective)$");
+
+  private HashMap<String, List<String>> map = new HashMap<String, List<String>>();
+
+  /**
+   * Return the Transform dictionary object of a element.
+   */
+  public static Transform getInstance(Element e) {
+    return getInstance(e, null);
+  }
+
+  public static boolean isTransform(String propName) {
+    return transformRegex.test(propName);
+  }
+
+  /**
+   * Return the Transform dictionary object of an element, but reseting
+   * historical values and setting them to the initial value passed.
+   */
+  public static Transform getInstance(Element e, String initial) {
+    Transform t = GQuery.data(e, TRANSFORM);
+    if (t == null || initial != null && !initial.isEmpty()) {
+      t = new Transform(initial);
+      GQuery.data(e, TRANSFORM, t);
+    }
+    return t;
+  }
+
+  public Transform(String s) {
+    parse(s);
+  }
+
+  public String get(String prop) {
+    return listToStr(map.get(prop), ",");
+  }
+
+  private String listToStr(List<String> l, String sep) {
+    String v = "";
+    if (l != null) {
+      for (String s : l) {
+        v += (v.isEmpty() ? "" : sep) + s;
+      }
+    }
+    return v;
+  }
+
+  private void parse(String s) {
+    if (s != null) {
+      RegExp re = RegExp.compile("([a-zA-Z0-9]+)\\((.*?)\\)", "g");
+      for (MatchResult r = re.exec(s); r != null; r = re.exec(s)) {
+        setFromString(r.getGroup(1), r.getGroup(2));
+      }
+    }
+  }
+
+  public void set(String prop, String ...val) {
+    setter(prop, val);
+  }
+
+  public void setFromString(String prop, String ...val) {
+    if (val.length == 1) {
+      String[] vals = val[0].split("[\\s*,\\s*]");
+      set(prop, vals);
+    } else {
+      set(prop, val);
+    }
+  }
+
+  private void setter(String prop, String ...val) {
+    if (prop.matches("(rotate[XYZ]?|skew[XYZ])")) {
+      map.put(prop, unit(val[0], "deg"));
+    } else if ("scale".equals(prop)) {
+      String x = val.length < 1 ? "1" : val[0];
+      String y = val.length < 2 ? x : val[1];
+      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 (prop.matches("(translate[XYZ])")) {
+      map.put(prop, unit(val[0], "px"));
+    } else if ("translate".equals(prop)) {
+      if (map.get("translateX") == null) {
+        map.put("translateX", unit("0", "px"));
+      }
+      if (val[0] != null) {
+        map.put("translateX", unit(val[0], "px"));
+      }
+      if (map.get("translateY") == null) {
+        map.put("translateY", unit("0", "px"));
+      }
+      if (val.length > 1 && val[1] != null) {
+        map.put("translateY", unit(val[1], "px"));
+      }
+      if (map.get("translateZ") == null) {
+        map.put("translateZ", unit("0", "px"));
+      }
+      if (val.length > 2 && val[2] != null) {
+        map.put("translateZ", unit(val[0], "px"));
+      }
+      map.put("translate", Arrays.asList(map.get("translateX").get(0), map.get("translateY").get(0), map.get("translateY").get(0)));
+    } else {
+      map.put(prop, unit(val[0], ""));
+    }
+  }
+
+  /**
+   * Converts the dictionary to a transition css string.
+   */
+  public String toString() {
+    // purposely using string addition, since my last tests demonstrate
+    // that string addition performs better than string builders in gwt-prod.
+    String ret = "";
+    for (Entry<String, List<String>> e: map.entrySet()) {
+      if (Transitions.has3d || !transform3dRegex.test(e.getKey())) {
+        String v = listToStr(e.getValue(), ",");
+        ret += (ret.isEmpty() ? "" : " ") + e.getKey() + "(" + v + ")";
+      }
+    }
+    return ret;
+  }
+
+  private List<String> unit(String val, String unit) {
+    return Arrays.asList(val + (val.endsWith(unit) ? "" : unit));
+  }
+}
\ No newline at end of file
index cefedcebb10982b05c2625c615fed5cea95ba83d..b939a9b1bed3eb35e27305e1f832cd028b4fd791 100644 (file)
  */
 package com.google.gwt.query.client.plugins.effects;
 
-import com.google.gwt.core.client.Duration;
+import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.Style;
 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.JsUtils;
+import com.google.gwt.query.client.plugins.Effects;
 import com.google.gwt.query.client.plugins.Plugin;
 import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
 import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.EasingCurve;
-import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.query.client.plugins.effects.TransitionsAnimation.TransitionsClipAnimation;
 import com.google.gwt.regexp.shared.RegExp;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Timer;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map.Entry;
 
 /**
  * Transitions and transformation plugin for gQuery.
@@ -69,127 +65,24 @@ import java.util.Map.Entry;
 
  * </pre>
  */
-public class Transitions extends GQuery {
-
-  /**
-   * A dictionary class with all the properties of an element transform
-   * which is able to return the correct syntax for setting css properties.
-   */
-  public static class Transform  {
-
-    private static final RegExp transform3dRegex = RegExp.compile("^(rotate([XY]|3d)|perspective)$");
-
-    private HashMap<String, List<String>> map = new HashMap<String, List<String>>();
-
-    public Transform(String s) {
-      parse(s);
-    }
-
-    public String get(String prop) {
-      return listToStr(map.get(prop), ",");
-    }
-
-    private String listToStr(List<String> l, String sep) {
-      String v = "";
-      if (l != null) {
-        for (String s : l) {
-          v += (v.isEmpty() ? "" : sep) + s;
-        }
-      }
-      return v;
-    }
-
-    private void parse(String s) {
-      if (s != null) {
-        RegExp re = RegExp.compile("([a-zA-Z0-9]+)\\((.*?)\\)", "g");
-        for (MatchResult r = re.exec(s); r != null; r = re.exec(s)) {
-          setFromString(r.getGroup(1), r.getGroup(2));
-        }
-      }
-    }
-
-    public void set(String prop, String ...val) {
-      setter(prop, val);
-    }
-
-    public void setFromString(String prop, String ...val) {
-      if (val.length == 1) {
-        String[] vals = val[0].split("[\\s*,\\s*]");
-        set(prop, vals);
-      } else {
-        set(prop, val);
-      }
-    }
-
-    private void setter(String prop, String ...val) {
-      if (prop.matches("(rotate[XY]?|skew[XY])")) {
-        map.put(prop, unit(val[0], "deg"));
-      } else if ("scale".equals(prop)) {
-        String x = val.length < 1 ? "1" : val[0];
-        String y = val.length < 2 ? x : val[1];
-        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 ("translate".equals(prop)) {
-        if (map.get("translateX") == null) {
-          map.put("translateX", unit("0", "px"));
-        }
-        if (val[0] != null) {
-          map.put("translateX", unit(val[0], "px"));
-        }
-        if (map.get("translateY") == null) {
-          map.put("translateY", unit("0", "px"));
-        }
-        if (val[1] != null) {
-          map.put("translateY", unit(val[1], "px"));
-        }
-        map.put("translate", Arrays.asList(map.get("translateX").get(0), map.get("translateY").get(0)));
-      }
-    }
-
-    /**
-     * Converts the dictionary to a transition css string.
-     */
-    public String toString() {
-      // purposely using string addition, since my last tests demonstrate
-      // that string addition performs better than string builders in gwt-prod.
-      String ret = "";
-      for (Entry<String, List<String>> e: map.entrySet()) {
-        if (has3d || !transform3dRegex.test(e.getKey())) {
-          String v = listToStr(e.getValue(), ",");
-          ret += (ret.isEmpty() ? "" : " ") + e.getKey() + "(" + v + ")";
-        }
-      }
-      return ret;
-    }
-
-    private List<String> unit(String val, String unit) {
-      return Arrays.asList(val + (val.endsWith(unit) ? "" : unit));
-    }
-  }
+public class Transitions extends Effects {
 
   // Used to check supported properties in the browser
-  private static Style divStyle = DOM.createDiv().getStyle();
+  protected static final Style divStyle = Document.get().createDivElement().getStyle();
 
-  private static final String prefix = browser.msie ? "ms" : browser.opera ? "o" : browser.mozilla ? "moz" : browser.webkit ? "webkit" : "";
+  public static final String prefix = browser.msie ? "ms" : browser.opera ? "o" : browser.mozilla ? "moz" : browser.webkit ? "webkit" : "";
   private static final String transform = getVendorPropertyName("transform");
-  private static final String TRANSFORM = "_t_";
   private static final String transformOrigin = getVendorPropertyName("transformOrigin");
 
-  protected static final RegExp transformRegex = RegExp.compile("^(scale|translate|rotate([XY]|3d)?|perspective|skew[XY]|x|y)$");
   protected static final String transition = getVendorPropertyName("transition");
 
   // passing an invalid transition property in chrome, makes disable all transitions in the element
-  private static final RegExp invalidTransitionNamesRegex = RegExp.compile("^(.*transform.*|duration|easing|delay|clip-.*)$");
+  public static final RegExp invalidTransitionNamesRegex = RegExp.compile("^(.*transform.*|duration|function|easing|delay|clip-.*)$");
 
-  private static final String transitionDelay = getVendorPropertyName("transitionDelay");
-  private static final String transitionEnd = browser.mozilla || browser.msie ? "transitionend" : (prefix + "transitionEnd");
+  protected static final String transitionDelay = getVendorPropertyName("transitionDelay");
+  protected static final String transitionEnd = browser.mozilla || browser.msie ? "transitionend" : (prefix + "TransitionEnd");
 
-  public static boolean has3d = supportsTransform3d();
+  public static final boolean has3d = supportsTransform3d();
 
   public static final Class<Transitions> Transitions = GQuery.registerPlugin(
       Transitions.class, new Plugin<Transitions>() {
@@ -198,7 +91,8 @@ public class Transitions extends GQuery {
         }
       });
 
-  private static String getVendorPropertyName(String prop) {
+  public static String getVendorPropertyName(String prop) {
+    assert divStyle != null;
     // we prefer vendor specific names by default
     String vendorProp =  JsUtils.camelize("-" + prefix + "-" + prop);
     if (JsUtils.hasProperty(divStyle, vendorProp)) {
@@ -215,7 +109,7 @@ public class Transitions extends GQuery {
   }
 
   private static String property(String prop) {
-    if (transformRegex.test(prop)) {
+    if (Transform.isTransform(prop)) {
       return transform;
     }
     return prop.replaceFirst("^(margin|padding).+$", "$1");
@@ -238,16 +132,15 @@ public class Transitions extends GQuery {
   @Override
   public String css(String prop, boolean force) {
     if ("transform".equals(prop)) {
-      return isEmpty() ? "" : getTransform(get(0), null).toString();
+      return isEmpty() ? "" : Transform.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 (transformRegex.test(prop)) {
-      return isEmpty() ? "" : getTransform(get(0), null).get(prop);
+    } else if (Transform.isTransform(prop)) {
+      return isEmpty() ? "" : Transform.getInstance(get(0), null).get(prop);
     } else {
-      String ret =  super.css(prop, force);
-      return ret;
+      return super.css(prop, force);
     }
   }
 
@@ -255,16 +148,16 @@ public class Transitions extends GQuery {
   public Transitions css(String prop, String value) {
     if ("transform".equals(prop)) {
       for (Element e : elements()) {
-        Transform t = getTransform(e, value);
+        Transform t = Transform.getInstance(e, 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 (transformRegex.test(prop)) {
+    } else if (Transform.isTransform(prop)) {
       for (Element e : elements()) {
-        Transform t = getTransform(e, null);
+        Transform t = Transform.getInstance(e, null);
         t.setFromString(prop, value);
         getStyleImpl().setStyleProperty(e, transform, t.toString());
       }
@@ -274,7 +167,7 @@ public class Transitions extends GQuery {
     return this;
   }
 
-  private List<String> filterTransitionPropertyNames(Properties p) {
+  public static List<String> filterTransitionPropertyNames(Properties p) {
     List<String> ret = new ArrayList<String>();
     for (String s : p.keys()) {
       if (invalidTransitionNamesRegex.test(s)) {
@@ -295,15 +188,6 @@ public class Transitions extends GQuery {
     return ret;
   }
 
-  private Transform getTransform(Element e, String initial) {
-    Transform t = data(e, TRANSFORM);
-    if (t == null || initial != null && !initial.isEmpty()) {
-      t = new Transform(initial);
-      data(e, TRANSFORM, t);
-    }
-    return t;
-  }
-
   /**
    * The transition() method allows you to create animation effects on any numeric HTML Attribute,
    * CSS property, or color using CSS3 transformations and transitions.
@@ -320,49 +204,17 @@ public class Transitions extends GQuery {
        .transition("{x: +100, width: +40px}", 2000, EasingCurve.easeOut);
    * </pre>
    */
-  public Transitions transition(Object stringOrProperties, final int duration, final Easing easing, final int delay, final Function... funcs) {
-    if (isEmpty()) {
-      return this;
-    }
-
-    final Properties cssProps = (stringOrProperties instanceof String)
-      ? (Properties) $$((String) stringOrProperties)
-      : (Properties) stringOrProperties;
-
-    final String ease = easing == null ? "ease" : easing.toString();
-    final List<String> transProps = filterTransitionPropertyNames(cssProps);
-    final double queuedAt = delay > 0 ? Duration.currentTimeMillis() : 0;
-
-    // Use gQuery queue, so as we can chain transitions, animations etc.
-    queue(new Function() {
-      public void f() {
-        // This is called once per element
-        final String oldTransitionValue = $(this).css(transition);
-        // Recompute delay based on the time spent in the queue
-        int d = Math.max(0, delay - (int) (Duration.currentTimeMillis() - queuedAt));
-        // Generate transition value
-        String attribs = duration + "ms" + " "  + ease + " " + d + "ms";
-        String newTransitionValue  = "";
-        for (String s : transProps) {
-          newTransitionValue += (newTransitionValue.isEmpty() ? "" : ", ") + s + " " + attribs;
-        }
-
-        final Transitions thisTrans = $(this).as(Transitions);
-        // Configure animation using transition property
-        thisTrans.css(transition, newTransitionValue);
-        // Set all css properties for this transition using the css method in this class
-        thisTrans.css(cssProps);
-
-        // TODO: Use transitionEnd events once GQuery supports non-bit events
-        // last time I tried, setting  'transitionEnd' made custom events fail (slideEnter)
-        new Timer() {
-          public void run() {
-            thisTrans.css(transition, oldTransitionValue).each(funcs).dequeue();
-          }
-        }.schedule(d + duration);
+  public Transitions transition(Object stringOrProperties, final int duration, final Easing easing,
+      final int delay, final Function... funcs) {
+    if (!isEmpty()) {
+      Properties p = (stringOrProperties instanceof String)
+          ? $$((String) stringOrProperties)
+          : (Properties) stringOrProperties;
+      for (Element e : elements()) {
+        queueAnimation(new TransitionsClipAnimation().setEasing(easing).setProperties(p)
+            .setElement(e).setCallback(funcs), duration);
       }
-    });
-
+    }
     return this;
   }
 
@@ -380,4 +232,9 @@ public class Transitions extends GQuery {
   public Transitions transition(Object stringOrProperties, int duration, String easing, int delay) {
     return transition(stringOrProperties, duration, EasingCurve.valueOf(easing), delay);
   }
+
+  @Override
+  protected GQAnimation createAnimation() {
+    return new TransitionsAnimation();
+  }
 }
index 4636b12eed6d551a3d84d5eecb151c2e35a90122..5a79e31179542b1884ddde67aa6920a413b80b39 100644 (file)
@@ -20,13 +20,16 @@ import static com.google.gwt.query.client.GQuery.$$;
 import static com.google.gwt.query.client.plugins.effects.ClipAnimation.getNormalizedValue;
 
 import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.Function;
 import com.google.gwt.query.client.Properties;
+import com.google.gwt.query.client.plugins.Effects.GQAnimation;
 import com.google.gwt.query.client.plugins.effects.ClipAnimation.Action;
 import com.google.gwt.query.client.plugins.effects.ClipAnimation.Corner;
 import com.google.gwt.query.client.plugins.effects.ClipAnimation.Direction;
 import com.google.gwt.query.client.plugins.effects.Fx.TransitFx;
 import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.user.client.Timer;
+
+import java.util.List;
 
 /**
  * Animation effects on any numeric CSS3 property or transformation
@@ -44,12 +47,8 @@ public class TransitionsAnimation extends PropertiesAnimation {
     private Direction direction;
     private Action currentAction;
 
-    public TransitionsClipAnimation(Element elem, Properties p, Function... funcs) {
-      this(null, elem, p, funcs);
-    }
-
-    public TransitionsClipAnimation(Easing easing, Element elem, Properties p, Function... funcs) {
-      super(easing, elem, p, funcs);
+    @Override
+    public GQAnimation setProperties(Properties p) {
       corner = Corner.CENTER;
       try {
         corner = Corner.valueOf(getNormalizedValue("clip-origin", p));
@@ -64,14 +63,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
         action = Action.valueOf(getNormalizedValue("clip-action", p));
       } catch (Exception e) {
       }
-    }
-
-    public TransitionsClipAnimation(Element elem, Action a, Corner c, Direction d, Easing easing,
-        Properties p, final Function... funcs) {
-      super(easing, elem, p, funcs);
-      this.action = a;
-      this.corner = c;
-      this.direction = d;
+      return super.setProperties(p);
     }
 
     public void onStart() {
@@ -119,7 +111,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
         g.hide();
       }
       g.css("transformOrigin", "");
-      g.css("transform", "scale(1 1)");
+      g.css("transform", "");
     }
   }
 
@@ -139,7 +131,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
     }
 
     String cur = g.css(key, true);
-    String trsStart = cur, trsEnd = trsStart;
+    String trsStart = cur.matches("auto|initial") ? "" : cur, trsEnd = trsStart;
 
     if ("show".equals(val)) {
       g.saveCssAttrs(key);
@@ -196,18 +188,26 @@ public class TransitionsAnimation extends PropertiesAnimation {
 
   protected Transitions g;
   protected int delay = 0;
+  private String oldTransitionValue;
 
-  public TransitionsAnimation(Element elem, Properties p, Function... funcs) {
-    this(null, elem, p, funcs);
+  @Override
+  public GQAnimation setProperties(Properties p) {
+    delay = p.getInt("delay");
+    return super.setProperties(p);
   }
 
-  public TransitionsAnimation(Easing easing, Element elem, Properties p, Function... funcs) {
-    super(easing, elem, p, funcs);
-    delay = p.getInt("delay");
-    g = $(e).as(Transitions.Transitions);
+  @Override
+  public GQAnimation setElement(Element elem) {
+    g = $(elem).as(Transitions.Transitions);
+    return super.setElement(elem);
   }
 
-  private Properties getFxProperties(boolean isStart) {
+  public TransitionsAnimation setDelay(int delay) {
+    this.delay = delay;
+    return this;
+  }
+
+  public Properties getFxProperties(boolean isStart) {
     Properties p = $$();
     for (int i = 0; i < effects.length(); i++) {
       TransitFx fx = (TransitFx) effects.get(i);
@@ -221,7 +221,7 @@ public class TransitionsAnimation extends PropertiesAnimation {
 
   @Override
   protected Fx getFx(Element e, String key, String val, boolean hidden) {
-    return computeFxProp(e, key, val, hidden);
+    return Transitions.invalidTransitionNamesRegex.test(key) ? null : computeFxProp(e, key, val, hidden);
   }
 
   @Override
@@ -229,21 +229,43 @@ public class TransitionsAnimation extends PropertiesAnimation {
   }
 
   @Override
+  public void onComplete() {
+    g.css(Transitions.transition, oldTransitionValue);
+    super.onComplete();
+  }
+
   public void run(int duration) {
+    // Calculate all Fx values for this animation
     onStart();
-
     // Compute initial properties
     Properties p = getFxProperties(true);
-    g.css(p)
-      // Some browsers need after setting initial properties re-flow (FF 24.4.0).
-      .offset();
+    g.css(p);
+    // Some browsers need re-flow after setting initial properties (FF 24.4.0).
+    g.offset();
 
     // Compute final properties
     p = getFxProperties(false);
-    g.transition(p, duration, easing, delay, new Function() {
-      public void f() {
+
+    // Save old transition value
+    oldTransitionValue = g.css(Transitions.transition);
+
+    // Set new transition value
+    String newTransitionValue  = "";
+    List<String> transProps = Transitions.filterTransitionPropertyNames(p);
+    String attribs = duration + "ms" + " "  + easing + " " + delay + "ms";
+    for (String s : transProps) {
+      newTransitionValue += (newTransitionValue.isEmpty() ? "" : ", ") + s + " " + attribs;
+    }
+    g.css(Transitions.transition, newTransitionValue);
+
+    // Set new css properties so as the element is animated
+    g.css(p);
+
+    // Wait until transition has finished to run finish animation and dequeue
+    new Timer() {
+      public void run() {
         onComplete();
       }
-    });
+    }.schedule(delay + duration);
   }
 }
index a5a502ea61661e276248626f9a0c8bbad49923ab..1ab2ca240f53c3f9db942caf4cc0d6ca9f11fbb0 100644 (file)
@@ -263,7 +263,6 @@ public class GQueryDeferredTestGwt extends GWTTestCase {
 
     $("button", e)
       .click(new Function(){public void f()  {
-        Fx.css3 = false;
         $("p", e).append(" Started... ");
         GQuery.when( effect ).done(new Function(){public void f()  {
           $("p", e).append(" Finished! ");
@@ -291,7 +290,6 @@ public class GQueryDeferredTestGwt extends GWTTestCase {
 
     $("button", e)
       .bind("click", new Function(){public void f()  {
-        Fx.css3 = false;
         $("p", e).append(" Started... ");
 
         $("div",e).each(new Function(){public Object f(Element e, int i) {
index da19afb138b72c7c35edab795a05f018223f0b8f..9658e98b5d1de3e969e3ce3fb99e294740a3b8cc 100644 (file)
@@ -15,7 +15,9 @@
  */
 package com.google.gwt.query.client;
 
-import static com.google.gwt.query.client.GQuery.*;
+import static com.google.gwt.query.client.GQuery.$;
+import static com.google.gwt.query.client.GQuery.$$;
+import static com.google.gwt.query.client.GQuery.Effects;
 
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.RepeatingCommand;
@@ -24,12 +26,13 @@ import com.google.gwt.junit.DoNotRunWith;
 import com.google.gwt.junit.Platform;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.query.client.GQuery.Offset;
-import com.google.gwt.query.client.plugins.effects.Fx;
+import com.google.gwt.query.client.plugins.Effects.GQAnimation;
 import com.google.gwt.query.client.plugins.effects.Fx.ColorFx;
 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.TransitionsAnimation;
+import com.google.gwt.query.client.plugins.effects.TransitionsAnimation.TransitionsClipAnimation;
 import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Label;
@@ -55,7 +58,6 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
   }
 
   public void gwtSetUp() {
-    Fx.css3 = false;
     if (e == null) {
       testPanel = new HTML();
       RootPanel.get().add(testPanel);
@@ -259,9 +261,8 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
             .toString());
 
     prop1 = GQuery.$$("marginTop: '-110px', marginLeft: '-110px', top: '50%', left: '50%', width: '174px', height: '174px', padding: '20px'");
-    PropertiesAnimation an = new PropertiesAnimation(EasingCurve.swing, g.get(0), prop1);
-    an.onStart();
-    an.onComplete();
+    GQAnimation an = new PropertiesAnimation().setEasing(EasingCurve.swing).setElement(g.get(0)).setProperties(prop1);
+    an.run(0);
 
     assertEquals("cssprop=marginTop value=0 start=-110 end=0 unit=px",
         PropertiesAnimation.computeFxProp(g.get(0), "marginTop", "0", false)
@@ -285,9 +286,8 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
             .toString());
 
     prop1 = GQuery.$$("marginTop: '0', marginLeft: '0', top: '0%', left: '0%', width: '100px', height: '100px', padding: '5px'");
-    an = new PropertiesAnimation(EasingCurve.swing, g.get(0), prop1);
-    an.onStart();
-    an.onComplete();
+    an = new PropertiesAnimation().setEasing(EasingCurve.swing).setElement(g.get(0)).setProperties(prop1);
+    an.run(0);
 
     assertEquals("cssprop=marginTop value=-110px start=0 end=-110 unit=px",
         PropertiesAnimation.computeFxProp(g.get(0), "marginTop", "-110px",
@@ -312,6 +312,40 @@ public class GQueryEffectsTestGwt extends GWTTestCase {
             .toString());
   }
 
+  public void testTransitionsAnimation() {
+    final GQuery m = $("<div style='top: 10px; width:50px'>foo</div>").appendTo(e);
+
+    TransitionsClipAnimation a = new TransitionsClipAnimation();
+    a.setElement(m.get(0));
+    a.setProperties($$("clip-action: show, clip-origin: top-right, scaleZ: 0.5, delay: 30, left: 100, top: +=50, rotateZ: 90, rotateY: 45deg, easing: custom, duration: 400"));
+    a.onStart();
+
+    Properties from = a.getFxProperties(true);
+    Properties to = a.getFxProperties(false);
+
+    // HTMLUnit and chrome return different decimal part
+    assertEquals("0px", from.getStr("left").replace(".0", ""));
+    assertEquals("100px", to.getStr("left").replace(".0", ""));
+    assertEquals("10px", from.getStr("top").replace(".0", ""));
+    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("0 0", from.getStr("scale").replace(".0", ""));
+    assertEquals("1 1", to.getStr("scale"));
+    assertNull(to.get("delay"));
+    assertNull(to.get("easing"));
+
+    // HTMLUnit and chrome return different values
+    assertTrue(m.attr("style").contains("rigin: 100% 0%") || m.attr("style").contains("rigin: right top"));
+    assertTrue(m.attr("style").contains("top: 10px"));
+
+    a.run(1);
+    assertTrue(m.attr("style").contains("rigin: 100% 0%") || m.attr("style").contains("rigin: right top"));
+    assertTrue(m.attr("style").contains("top: 60px"));
+  }
+
   public void testColorEffectParsing(){
     String html = "<div id='test' style='color: #112233'>Test</div>";
     $(e).html(html);