Allow to use customized animations. And some Fixes.tags/gwtquery-project-1.4.3
@@ -172,4 +172,26 @@ | |||
--> | |||
<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> |
@@ -22,10 +22,10 @@ | |||
<!-- 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"> | |||
@@ -39,11 +39,9 @@ | |||
<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"/> |
@@ -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); |
@@ -135,7 +135,10 @@ 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; | |||
}-*/; | |||
@@ -185,7 +188,10 @@ public class JsCache extends JavaScriptObject { | |||
var key, ret = 0; | |||
// Chrome in DevMode injects a property to JS objects | |||
for (key in this) if (key != "__gwt_ObjectId") ret ++; | |||
for (key in this) { | |||
if (key != "__gwt_ObjectId") | |||
ret ++; | |||
} | |||
return ret; | |||
}-*/; | |||
@@ -240,7 +246,10 @@ 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; | |||
}-*/; | |||
@@ -15,10 +15,13 @@ | |||
*/ | |||
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,22 @@ 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) /*-{ | |||
return o && name in o; | |||
public static native boolean hasProperty(JavaScriptObject o, String name)/*-{ | |||
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 +356,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 +488,63 @@ 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. | |||
* 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 +559,27 @@ 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. | |||
* | |||
* @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()); | |||
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 +614,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) { |
@@ -16,16 +16,15 @@ | |||
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.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; | |||
import com.google.gwt.query.client.plugins.effects.TransitionsAnimation.TransitionsClipAnimation; | |||
/** | |||
* Effects plugin for Gwt Query. | |||
@@ -42,14 +41,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 +111,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) { | |||
@@ -116,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. | |||
@@ -169,7 +220,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 +227,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 +364,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. |
@@ -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); |
@@ -15,12 +15,11 @@ | |||
*/ | |||
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(); |
@@ -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. | |||
*/ |
@@ -15,12 +15,8 @@ | |||
*/ | |||
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; | |||
@@ -153,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%]+"; | |||
private static final RegExp REGEX_NUMBER_UNIT = RegExp.compile("^(" + NUMBER + ")(.*)?$"); | |||
protected static final RegExp REGEX_SYMBOL_NUMBER_UNIT = RegExp | |||
.compile("^([+-]=)?([0-9+-.]+)(.*)?$"); | |||
protected static final RegExp REGEX_SYMBOL_NUMBER_UNIT = RegExp.compile("^([+-]=)?(" + NUMBER + ")(" + UNIT + ")?$"); | |||
protected static final RegExp REGEX_NON_PIXEL_ATTRS = | |||
RegExp.compile("z-?index|font-?weight|opacity|zoom|line-?height|scale|rotation|^\\$", "i"); | |||
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"); | |||
@@ -173,7 +173,6 @@ public class PropertiesAnimation extends GQAnimation { | |||
if (REGEX_COLOR_ATTR.test(key)) { | |||
return computeFxColorProp(e, key, val); | |||
} | |||
return computeFxNumericProp(e, key, val, hidden); | |||
} | |||
@@ -251,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"; | |||
@@ -288,32 +284,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 +300,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(); |
@@ -0,0 +1,237 @@ | |||
/* | |||
* 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 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; | |||
import com.google.gwt.dom.client.Style; | |||
import com.google.gwt.query.client.GQuery; | |||
import com.google.gwt.query.client.js.JsUtils; | |||
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_"; | |||
// Used to check supported properties in the browser | |||
protected static final Style divStyle = Document.get().createDivElement().getStyle(); | |||
// Compute browser specific constants, public so as they are usable in plugins | |||
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(); | |||
// Regular expressions based on http://www.w3schools.com/cssref/css3_pr_transform.asp | |||
protected static final RegExp transformRegex = RegExp.compile("^(matrix(3d)?|(translate|scale|rotate)([XYZ]|3d)?|skew([XY])?|perspective|x|y|z)$"); | |||
private static final RegExp transform3dRegex = RegExp.compile("^(rotate[XY]|\\w+(Z|3d)|perspective)$"); | |||
private static final RegExp transformParseRegex = RegExp.compile("(\\w+)\\((.*?)\\)", "g"); | |||
private static final RegExp anglePropRegex = RegExp.compile("(rotate[XYZ]?|skew[XY]?)"); | |||
private static final RegExp translatePropRegex = RegExp.compile("translate[XYZ]"); | |||
private HashMap<String, List<String>> map = new HashMap<String, List<String>>(); | |||
// Some browsers like HTMLUnit only support 2d transformations | |||
private static boolean supportsTransform3d() { | |||
if (transform == null) { | |||
return false; | |||
} | |||
String rotate = "rotateY(1deg)"; | |||
divStyle.setProperty(transform, rotate); | |||
rotate = divStyle.getProperty(transform); | |||
return rotate != null && !rotate.isEmpty(); | |||
} | |||
/** | |||
* Compute the correct CSS property name for a specific browser vendor. | |||
*/ | |||
public static String getVendorPropertyName(String prop) { | |||
// we prefer vendor specific names by default | |||
String vendorProp = JsUtils.camelize("-" + prefix + "-" + prop); | |||
if (JsUtils.hasProperty(divStyle, vendorProp)) { | |||
return vendorProp; | |||
} | |||
if (JsUtils.hasProperty(divStyle, prop)) { | |||
return prop; | |||
} | |||
String camelProp = JsUtils.camelize(prop); | |||
if (JsUtils.hasProperty(divStyle, camelProp)) { | |||
return camelProp; | |||
} | |||
return null; | |||
} | |||
/** | |||
* Return the Transform dictionary object of a element. | |||
*/ | |||
public static Transform getInstance(Element e) { | |||
return getInstance(e, null); | |||
} | |||
/** | |||
* Return true if the propName is a valid value of the css3 transform property. | |||
*/ | |||
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) { | |||
if (initial == null) { | |||
initial = GQuery.getSelectorEngine().getDocumentStyleImpl().curCSS(e, transform, false); | |||
} | |||
t = new Transform(initial); | |||
GQuery.data(e, TRANSFORM, t); | |||
} | |||
return t; | |||
} | |||
/** | |||
* Create a new Transform dictionary setting initial values based on the | |||
* string passed. | |||
*/ | |||
public Transform(String s) { | |||
parse(s); | |||
} | |||
/** | |||
* Return the value of a transform property. | |||
*/ | |||
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; | |||
} | |||
/** | |||
* Parse a transform value as string and fills the dictionary map. | |||
*/ | |||
private void parse(String s) { | |||
if (s != null) { | |||
for (MatchResult r = transformParseRegex.exec(s); r != null; r = transformParseRegex.exec(s)) { | |||
setFromString(vendorProperty(r.getGroup(1)), r.getGroup(2)); | |||
} | |||
} | |||
} | |||
/** | |||
* Set a transform value or multi-value. | |||
*/ | |||
public void set(String prop, String ...val) { | |||
setter(prop, val); | |||
} | |||
/** | |||
* Set a transform multi-value giving either a set of strings or | |||
* just an string of values separated by comma. | |||
*/ | |||
public void setFromString(String prop, String ...val) { | |||
if (val.length == 1) { | |||
String[] vals = val[0].split("[\\s,]+"); | |||
set(prop, vals); | |||
} else { | |||
set(prop, val); | |||
} | |||
} | |||
private void setter(String prop, String ...val) { | |||
if (anglePropRegex.test(prop)) { | |||
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 (translatePropRegex.test(prop)) { | |||
map.put(prop, unit(val[0], "px")); | |||
} else if ("translate".equals(prop)) { | |||
if (val[0] != null) { | |||
map.put("translateX", unit(val[0], "px")); | |||
} | |||
if (val.length > 1 && val[1] != null) { | |||
map.put("translateY", unit(val[1], "px")); | |||
} | |||
if (has3d && val.length > 2 && val[2] != null) { | |||
map.put("translateZ", unit(val[2], "px")); | |||
} | |||
} else { | |||
map.put(prop, Arrays.asList(val)); | |||
} | |||
} | |||
/** | |||
* Converts the dictionary to a transition css string value but | |||
* excluding 3d properties if the browser only supports 2d. | |||
*/ | |||
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)); | |||
} | |||
} |
@@ -28,26 +28,25 @@ | |||
*/ | |||
package com.google.gwt.query.client.plugins.effects; | |||
import com.google.gwt.core.client.Duration; | |||
import static com.google.gwt.query.client.plugins.effects.Transform.getInstance; | |||
import static com.google.gwt.query.client.plugins.effects.Transform.isTransform; | |||
import static com.google.gwt.query.client.plugins.effects.Transform.transform; | |||
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 +68,14 @@ 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)); | |||
} | |||
} | |||
// Used to check supported properties in the browser | |||
private static Style divStyle = DOM.createDiv().getStyle(); | |||
private 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"); | |||
public class Transitions extends Effects { | |||
// 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 transitionEnd = browser.mozilla || browser.msie ? "transitionend" : (prefix + "TransitionEnd"); | |||
public static boolean has3d = supportsTransform3d(); | |||
protected static final String transition = vendorProperty("transition"); | |||
public static final Class<Transitions> Transitions = GQuery.registerPlugin( | |||
Transitions.class, new Plugin<Transitions>() { | |||
@@ -198,83 +84,50 @@ public class Transitions extends GQuery { | |||
} | |||
}); | |||
private static String getVendorPropertyName(String prop) { | |||
// we prefer vendor specific names by default | |||
String vendorProp = JsUtils.camelize("-" + prefix + "-" + prop); | |||
if (JsUtils.hasProperty(divStyle, vendorProp)) { | |||
return vendorProp; | |||
} | |||
if (JsUtils.hasProperty(divStyle, prop)) { | |||
return prop; | |||
} | |||
String camelProp = JsUtils.camelize(prop); | |||
if (JsUtils.hasProperty(divStyle, camelProp)) { | |||
return camelProp; | |||
} | |||
return null; | |||
} | |||
private static String property(String prop) { | |||
if (transformRegex.test(prop)) { | |||
if (isTransform(prop)) { | |||
return transform; | |||
} | |||
return prop.replaceFirst("^(margin|padding).+$", "$1"); | |||
} | |||
private static boolean supportsTransform3d() { | |||
if (transform == null) { | |||
return false; | |||
} | |||
String rotate = "rotateY(1deg)"; | |||
divStyle.setProperty(transform, rotate); | |||
rotate = divStyle.getProperty(transform); | |||
return rotate != null && !rotate.isEmpty(); | |||
} | |||
protected Transitions(GQuery gq) { | |||
super(gq); | |||
} | |||
@Override | |||
public String css(String prop, boolean force) { | |||
if ("transform".equals(prop)) { | |||
return isEmpty() ? "" : getTransform(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); | |||
prop = vendorProperty(prop); | |||
if (transform.equals(prop)) { | |||
return isEmpty() ? "" : getInstance(get(0), null).toString(); | |||
} else if (isTransform(prop)) { | |||
return isEmpty() ? "" : getInstance(get(0), null).get(prop); | |||
} else { | |||
String ret = super.css(prop, force); | |||
return ret; | |||
return super.css(prop, force); | |||
} | |||
} | |||
@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 = getTransform(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 (transformRegex.test(prop)) { | |||
} else if (isTransform(prop)) { | |||
for (Element e : elements()) { | |||
Transform t = getTransform(e, null); | |||
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; | |||
} | |||
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 +148,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 +164,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 +192,22 @@ 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(); | |||
} | |||
@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(); | |||
} | |||
} |
@@ -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,18 +63,11 @@ 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() { | |||
boolean hidden = !g.isVisible(); | |||
boolean hidden = !t.isVisible(); | |||
super.onStart(); | |||
if (action == null) { | |||
@@ -104,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, "")); | |||
} | |||
@@ -116,16 +108,16 @@ public class TransitionsAnimation extends PropertiesAnimation { | |||
return; | |||
} | |||
if (currentAction == Action.HIDE) { | |||
g.hide(); | |||
t.hide(); | |||
} | |||
g.css("transformOrigin", ""); | |||
g.css("transform", "scale(1 1)"); | |||
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"; | |||
} | |||
@@ -139,13 +131,21 @@ 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); | |||
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); | |||
@@ -156,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) { | |||
@@ -172,48 +173,67 @@ 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; | |||
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) { | |||
e = elem; | |||
g = t = $(elem).as(Transitions.Transitions); | |||
return this; | |||
} | |||
public TransitionsAnimation setDelay(int delay) { | |||
this.delay = delay; | |||
return this; | |||
} | |||
private Properties getFxProperties(boolean isStart) { | |||
public Properties getFxProperties(boolean isStart) { | |||
Properties p = $$(); | |||
for (int i = 0; i < effects.length(); i++) { | |||
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; | |||
@@ -221,7 +241,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 +249,43 @@ public class TransitionsAnimation extends PropertiesAnimation { | |||
} | |||
@Override | |||
public void onComplete() { | |||
t.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(); | |||
t.css(p); | |||
// Some browsers need re-flow after setting initial properties (FF 24.4.0). | |||
t.offset(); | |||
// Compute final properties | |||
p = getFxProperties(false); | |||
g.transition(p, duration, easing, delay, new Function() { | |||
public void f() { | |||
// Save old transition value | |||
oldTransitionValue = t.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; | |||
} | |||
t.css(Transitions.transition, newTransitionValue); | |||
// Set new css properties so as the element is animated | |||
t.css(p); | |||
// Wait until transition has finished to run finish animation and dequeue | |||
new Timer() { | |||
public void run() { | |||
onComplete(); | |||
} | |||
}); | |||
}.schedule(delay + duration); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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 |
@@ -17,11 +17,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.console; | |||
import static com.google.gwt.query.client.GQuery.document; | |||
import static com.google.gwt.query.client.GQuery.window; | |||
import com.google.gwt.core.client.js.JsType; | |||
import com.google.gwt.dom.client.Document; | |||
import com.google.gwt.dom.client.Element; | |||
import com.google.gwt.dom.client.InputElement; | |||
@@ -1032,11 +1030,19 @@ public class GQueryCoreTestGwt extends GWTTestCase { | |||
} | |||
public void testUtilsCallFunc() { | |||
assertTrue(JsUtils.hasProperty(window, "document.body.style.background")); | |||
assertTrue(JsUtils.hasProperty(window, "document.createElement")); | |||
assertFalse(JsUtils.hasProperty(window, "document.body.style.foo")); | |||
Element e = JsUtils.runJavascriptFunction(document, "createElement", "div"); | |||
assertNotNull(e); | |||
assertEquals(e.getTagName().toLowerCase(), "div"); | |||
e = JsUtils.runJavascriptFunction(document, "foo", "bar", 2, true); | |||
e = JsUtils.jsni("document.createElement", "span"); | |||
assertNotNull(e); | |||
assertEquals(e.getTagName().toLowerCase(), "span"); | |||
e = JsUtils.jsni("document.foo.bar"); | |||
assertNull(e); | |||
} | |||
@@ -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) { |
@@ -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,18 +26,24 @@ 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.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; | |||
import com.google.gwt.user.client.ui.HTML; | |||
import com.google.gwt.user.client.ui.Label; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
/** | |||
* Test class for testing gwtquery effects plugin api. | |||
*/ | |||
@@ -55,7 +63,6 @@ public class GQueryEffectsTestGwt extends GWTTestCase { | |||
} | |||
public void gwtSetUp() { | |||
Fx.css3 = false; | |||
if (e == null) { | |||
testPanel = new HTML(); | |||
RootPanel.get().add(testPanel); | |||
@@ -257,11 +264,16 @@ 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'"); | |||
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 +297,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 +323,130 @@ 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)"); | |||
List<String> vals = Arrays.asList(t.toString().split(" ")); | |||
// scale(1,1) matrix(1,2,3,4) rotateZ(90deg) translateZ(14px) rotateY(45deg) translateY(12px) skewX(4deg) translateX(10px) scaleZ(0.5) | |||
assertEquals(9, vals.size()); | |||
assertTrue(vals.contains("scaleZ(0.5)")); | |||
assertTrue(vals.contains("rotateZ(90deg)")); | |||
assertTrue(vals.contains("rotateY(45deg)")); | |||
assertTrue(vals.contains("skewX(4deg)")); | |||
assertTrue(vals.contains("rotateY(45deg)")); | |||
assertTrue(vals.contains("scale(1,1)")); | |||
assertTrue(vals.contains("translateX(10px)")); | |||
assertTrue(vals.contains("translateY(12px)")); | |||
assertTrue(vals.contains("translateZ(14px)")); | |||
assertTrue(vals.contains("matrix(1,2,3,4)")); | |||
Transform.has3d = false; | |||
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)"); | |||
vals = Arrays.asList(t.toString().split(" ")); | |||
// scale(1,1) matrix(1,2,3,4) translateY(12px) skewX(4deg) translateX(10px) | |||
assertEquals(5, vals.size()); | |||
assertTrue(vals.contains("scale(1,1)")); | |||
assertTrue(vals.contains("skewX(4deg)")); | |||
assertTrue(vals.contains("translateX(10px)")); | |||
assertTrue(vals.contains("translateY(12px)")); | |||
assertTrue(vals.contains("matrix(1,2,3,4)")); | |||
} | |||
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("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")); | |||
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); | |||
@@ -385,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( |