]> source.dussan.org Git - gwtquery.git/commitdiff
Effects/Animation work
authorRay Cromwell <cromwellian@gmail.com>
Wed, 6 May 2009 01:04:40 +0000 (01:04 +0000)
committerRay Cromwell <cromwellian@gmail.com>
Wed, 6 May 2009 01:04:40 +0000 (01:04 +0000)
gwtquery-core/src/main/java/com/google/gwt/query/client/Effects.java
gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java
gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java

index 38c904eabcce1235b8faef8c7f962668773a4459..a15948c7016b53213ab1c01a6386b7825a7360e8 100644 (file)
@@ -18,6 +18,8 @@ package com.google.gwt.query.client;
 import com.google.gwt.animation.client.Animation;\r
 import com.google.gwt.dom.client.Element;\r
 import com.google.gwt.dom.client.NodeList;\r
+import com.google.gwt.core.client.Duration;\r
+import com.google.gwt.user.client.Timer;\r
 \r
 /**\r
  * Effects plugin for Gwt Query.\r
@@ -40,6 +42,237 @@ public class Effects extends GQuery {
     GQuery.registerPlugin(Effects.class, new EffectsPlugin());\r
   }\r
 \r
+  public enum Easing {\r
+\r
+    LINEAR {\r
+      public double ease(double p, double n, double firstNum, double diff) {\r
+        return firstNum + diff * p;\r
+      }\r
+    }, SWING {\r
+      public double ease(double p, double n, double firstNum, double diff) {\r
+        return ((-Math.cos(p * Math.PI) / 2) + 0.5) * diff + firstNum;\r
+      }\r
+    };\r
+\r
+    public abstract double ease(double p, double n, double firstNum,\r
+        double diff);\r
+  }\r
+\r
+  public enum Speed {\r
+\r
+    SLOW(600), FAST(200), DEFAULT(400);\r
+\r
+    public int getDuration() {\r
+      return duration;\r
+    }\r
+\r
+    private final int duration;\r
+\r
+    Speed(int dur) {\r
+      this.duration = dur;\r
+    }\r
+  }\r
+\r
+  protected class PropFx {\r
+\r
+    public SpeedOpts opt;\r
+\r
+    public Element elem;\r
+\r
+    public String prop;\r
+\r
+    private double startTime;\r
+\r
+    private double start;\r
+\r
+    private double end;\r
+\r
+    private String unit;\r
+\r
+    private double now;\r
+\r
+    private double pos;\r
+\r
+    private double state;\r
+\r
+    public double cur(boolean force) {\r
+      if (elem.getPropertyString(prop) != null && (elem.getStyle() == null\r
+          || elem.getStyle().getProperty(prop) == null)) {\r
+        return elem.getPropertyDouble(prop);\r
+      }\r
+      double r = Double.parseDouble(GQuery.curCSS(elem, prop, force));\r
+      return !Double.isNaN(r) && r > -10000 ? r\r
+          : Double.parseDouble(GQuery.curCSS(elem, prop, false));\r
+    }\r
+\r
+    public void show() {\r
+      opt.cache.put(prop, elem.getStyle().getProperty(prop));\r
+      opt.show = true;\r
+      custom("width".equals("width") || "height".equals(prop) ? 1 : 0,\r
+          cur(false));\r
+    }\r
+\r
+    private boolean step(boolean gotoEnd) {\r
+      double t = Duration.currentTimeMillis();\r
+\r
+      if (gotoEnd || t >= opt.duration + startTime) {\r
+        now = end;\r
+        pos = start = 1;\r
+        update();\r
+        opt.curAnim.set(prop, "true");\r
+        boolean done = true;\r
+        for (String key : opt.curAnim.keys()) {\r
+          if (!"true".equals(opt.curAnim.get(key))) {\r
+            done = false;\r
+          }\r
+        }\r
+        if (done) {\r
+          if (opt.display != null) {\r
+            elem.getStyle().setProperty("overflow", opt.overflow);\r
+            elem.getStyle().setProperty("display", opt.display);\r
+            if ("none".equals(GQuery.curCSS(elem, "display", false))) {\r
+              elem.getStyle().setProperty("display", "block");\r
+            }\r
+          }\r
+          if (opt.hide) {\r
+            $(elem).hide();\r
+          }\r
+          if (opt.hide || opt.show) {\r
+            for (String key : opt.curAnim.keys()) {\r
+              elem.getStyle().setProperty(key, opt.cache.getString(key));\r
+            }\r
+          }\r
+          opt.complete(elem);\r
+        }\r
+        return false;\r
+      } else {\r
+        double n = t - startTime;\r
+        state = n / opt.duration;\r
+        pos = opt.easing.ease(this.state, n, 0, 1);\r
+        update();\r
+        return true;\r
+      }\r
+    }\r
+\r
+    public void update() {\r
+               (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );\r
+\r
+               // Set display property to block for height/width animations\r
+               if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )\r
+                       this.elem.style.display = "block";\r
+    }\r
+\r
+    public void hide() {\r
+      opt.cache.put(prop, elem.getStyle().getProperty(prop));\r
+      opt.hide = true;\r
+      custom(cur(false), 0);\r
+    }\r
+\r
+    private void custom(double from, double to) {\r
+      custom(from, to, "px");\r
+    }\r
+\r
+    private void custom(double from, double to, String unit) {\r
+      startTime = Duration.currentTimeMillis();\r
+      start = from;\r
+      end = to;\r
+      now = start;\r
+\r
+      Timer t = new Timer() {\r
+        @Override\r
+        public void run() {\r
+          step(false);\r
+        }\r
+      };\r
+    }\r
+  }\r
+\r
+  private class SpeedOpts {\r
+\r
+    private Properties properties;\r
+\r
+    private int duration;\r
+\r
+    private Effects.Easing easing;\r
+\r
+    private Function complete;\r
+\r
+    private boolean queue = true;\r
+\r
+    public String display;\r
+\r
+    public String overflow;\r
+\r
+    public Properties curAnim;\r
+\r
+    public boolean hide;\r
+\r
+    private GQuery.DataCache cache = DataCache.createObject().cast();\r
+\r
+    public boolean show;\r
+\r
+    public boolean isQueue() {\r
+      return queue;\r
+    }\r
+\r
+    public void setQueue(boolean queue) {\r
+      this.queue = queue;\r
+    }\r
+\r
+    protected SpeedOpts(int speed, Easing easing, Function complete) {\r
+      this.complete = complete;\r
+      this.easing = easing;\r
+      this.duration = speed;\r
+    }\r
+\r
+    public Function getComplete() {\r
+      return complete;\r
+    }\r
+\r
+    public void setComplete(Function complete) {\r
+      this.complete = complete;\r
+    }\r
+\r
+    public int getDuration() {\r
+      return duration;\r
+    }\r
+\r
+    public void setDuration(int duration) {\r
+      this.duration = duration;\r
+    }\r
+\r
+    public Easing getEasing() {\r
+      return easing;\r
+    }\r
+\r
+    public void setEasing(Easing easing) {\r
+      this.easing = easing;\r
+    }\r
+\r
+    public Properties getProperties() {\r
+      return properties;\r
+    }\r
+\r
+    public void setProperties(Properties properties) {\r
+      this.properties = properties;\r
+    }\r
+\r
+    protected SpeedOpts(Speed speed, Easing easing, Function complete) {\r
+      this.complete = complete;\r
+      this.easing = easing;\r
+      this.duration = speed.getDuration();\r
+    }\r
+\r
+    public void complete(Element elem) {\r
+      if (queue) {\r
+        $(elem).dequeue();\r
+      }\r
+      if (complete != null) {\r
+        complete.f(elem);\r
+      }\r
+    }\r
+  }\r
+\r
   public Effects(Element element) {\r
     super(element);\r
   }\r
@@ -52,6 +285,115 @@ public class Effects extends GQuery {
     super(list);\r
   }\r
 \r
+  public Effects animate(final Properties properties, final Speed speed,\r
+      final Easing easing, final Function complete) {\r
+    if (properties.get("queue") != null) {\r
+      queue(new Function() {\r
+        final SpeedOpts optall = new SpeedOpts(speed, easing, complete);\r
+\r
+        @Override\r
+        public void f(Element e) {\r
+          boolean hidden = !$(e).visible();\r
+          for (String key : properties.keys()) {\r
+            String prop = properties.get(key);\r
+            if ("hide".equals(prop) && hidden\r
+                || "show".equals(prop) && !hidden) {\r
+              optall.complete(e);\r
+              return;\r
+            }\r
+            if ("height".equals(key)\r
+                || "width".equals(key) && e.getStyle() != null) {\r
+              optall.display = $(e).css("display");\r
+              optall.overflow = e.getStyle().getProperty("overflow");\r
+            }\r
+          }\r
+          if (optall.overflow != null) {\r
+            e.getStyle().setProperty("overflow", "hidden");\r
+          }\r
+          optall.curAnim = properties.cloneProps();\r
+          for (String key : properties.keys()) {\r
+            PropFx fx = new PropFx();\r
+            String val = properties.get(key);\r
+            fx.elem = e;\r
+            fx.opt = optall;\r
+            fx.prop = key;\r
+            if ("toggle".equals(val)) {\r
+              if (hidden) {\r
+                fx.show();\r
+              } else {\r
+                fx.hide();\r
+              }\r
+            } else if ("show".equals(val)) {\r
+              fx.show();\r
+            } else if ("hide".equals(val)) {\r
+              fx.hide();\r
+            } else {\r
+              JSArray parts = new Regexp("^([+-]=)?([0-9+-.]+)(.*)$")\r
+                  .match(val);\r
+              double start = fx.cur(true);\r
+\r
+              if (parts != null) {\r
+                double end = Double.parseDouble(parts.getStr(2));\r
+                String unit = parts.getStr(3);\r
+                if (unit == null) {\r
+                  unit = "px";\r
+                }\r
+                if (!"px".equals(unit)) {\r
+                  e.getStyle().setProperty(key, (end != 0 ? end : 1) + unit);\r
+                  start = (end != 0 ? end : 1) / fx.cur(true) * start;\r
+                  e.getStyle().setProperty(key, start + unit);\r
+                }\r
+                if (parts.getStr(1) != null) {\r
+                  end = (("-=".equals(parts.getStr(1)) ? -1 : 1) * end) + start;\r
+                }\r
+                fx.custom(start, end, unit);\r
+              } else {\r
+                fx.custom(start, Double.parseDouble(val), "");\r
+              }\r
+            }\r
+          }\r
+        }\r
+      });\r
+    }\r
+    return this;\r
+  }\r
+\r
+//                     jQuery.each( prop, function(name, val){\r
+//                             var e = new jQuery.fx( self, opt, name );\r
+//\r
+//                             if ( /toggle|show|hide/.test(val) )\r
+//                                     e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );\r
+//                             else {\r
+//                                     var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),\r
+//                                             start = e.cur(true) || 0;\r
+//\r
+//                                     if ( parts ) {\r
+//                                             var end = parseFloat(parts[2]),\r
+//                                                     unit = parts[3] || "px";\r
+//\r
+//                                             // We need to compute starting value\r
+//                                             if ( unit != "px" ) {\r
+//                                                     self.style[ name ] = (end || 1) + unit;\r
+//                                                     start = ((end || 1) / e.cur(true)) * start;\r
+//                                                     self.style[ name ] = start + unit;\r
+//                                             }\r
+//\r
+//                                             // If a +=/-= token was provided, we're doing a relative animation\r
+//                                             if ( parts[1] )\r
+//                                                     end = ((parts[1] == "-=" ? -1 : 1) * end) + start;\r
+//\r
+//                                             e.custom( start, end, unit );\r
+//                                     } else\r
+//                                             e.custom( start, val, "" );\r
+//                             }\r
+//                     });\r
+//\r
+//                     // For JS strict compliance\r
+//                     return true;\r
+//             });\r
+//     },  \r
+//  }\r
+\r
   public Effects fadeIn() {\r
     Animation a = new Animation() {\r
 \r
@@ -103,12 +445,40 @@ public class Effects extends GQuery {
   }\r
 \r
   public Effects hide() {\r
-    this.css("display", "none");\r
+    for (Element e : elements()) {\r
+      GQuery q = $(e);\r
+      String old = (String) q.data("olddisplay");\r
+      if (old != null && !"none".equals(old)) {\r
+        q.data("olddisplay", GQuery.curCSS(e, "display", false));\r
+        e.getStyle().setProperty("display", "none");\r
+      }\r
+    }\r
     return this;\r
   }\r
 \r
+  private DataCache elemDisplay = DataCache.createObject().cast();\r
+\r
   public Effects show() {\r
-    this.css("display", "");\r
+    for (Element e : elements()) {\r
+      GQuery q = $(e);\r
+      String old = (String) q.data("olddisplay");\r
+      e.getStyle().setProperty("display", SelectorEngine.or(old, ""));\r
+      if ("none".equals(GQuery.curCSS(e, "display", false))) {\r
+        String tagName = e.getTagName();\r
+        String display = "";\r
+        if (elemDisplay.getString(tagName) != null) {\r
+          display = elemDisplay.getString(tagName);\r
+        } else {\r
+          Element elem = $("<" + tagName + ">").appendTo($("body")).get(0);\r
+          display = GQuery.curCSS(elem, "display", false);\r
+          if ("none".equals(display)) {\r
+            display = "block";\r
+          }\r
+        }\r
+        e.getStyle().setProperty("display", display);\r
+        q.data("olddisplay", display);\r
+      }\r
+    }\r
     return this;\r
   }\r
 \r
index 574ab8c79ef6c4eb5dd13fa5e7a6caf6d174be92..2c9c354ef35206a7d41f756a0a7db8e851183535 100644 (file)
@@ -62,7 +62,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
     }\r
   }\r
 \r
-  private static final class DataCache extends JavaScriptObject {\r
+  static final class DataCache extends JavaScriptObject {\r
 \r
     protected DataCache() {\r
     }\r
@@ -375,12 +375,18 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
   }\r
 \r
   private static String curCSS(Element elem, String name) {\r
+    return curCSS(elem, name, false);\r
+  }\r
+\r
+  public static String curCSS(Element elem, String name, boolean force) {\r
     Style s = elem.getStyle();\r
     ensureStyleImpl();\r
-    name = styleImpl.getPropertyName(name);\r
+    if (!force) {\r
+      name = styleImpl.getPropertyName(name);\r
 \r
-    if (SelectorEngine.truth(s.getProperty(name))) {\r
-      return s.getProperty(name);\r
+      if (SelectorEngine.truth(s.getProperty(name))) {\r
+        return s.getProperty(name);\r
+      }\r
     }\r
     return styleImpl.getCurrentStyle(elem, name);\r
   }\r
@@ -760,6 +766,7 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
 //    return this;\r
 \r
   //  }\r
+\r
   /**\r
    * Return a style property on the first matched element.\r
    */\r
index ab14f61049ac2fed3e04990852e76499e5897612..56e24a7be94be0ea60ef32baaaf6f7f9b2e8589c 100644 (file)
@@ -63,4 +63,15 @@ public class Properties extends JavaScriptObject {
     }\r
     return keys;\r
   }-*/;\r
+\r
+  public native Properties cloneProps() /*-{\r
+    var props = {};\r
+    for(p in this) {\r
+      props[p] =  this[p];\r
+    }\r
+  }-*/;\r
+\r
+  public native void set(String key, String val) /*-{\r
+    this[key]=val;\r
+  }-*/;\r
 }\r