You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Effects.java 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * Copyright 2011, The gwtquery team.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.google.gwt.query.client.plugins;
  17. import com.google.gwt.animation.client.Animation;
  18. import com.google.gwt.core.client.GWT;
  19. import com.google.gwt.dom.client.Element;
  20. import com.google.gwt.query.client.Function;
  21. import com.google.gwt.query.client.GQuery;
  22. import com.google.gwt.query.client.Properties;
  23. import com.google.gwt.query.client.js.JsMap;
  24. import com.google.gwt.query.client.plugins.effects.Fx;
  25. import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
  26. import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.EasingCurve;
  27. /**
  28. * Effects plugin for Gwt Query.
  29. */
  30. public class Effects extends QueuePlugin<Effects> {
  31. /**
  32. * Class to access protected methods in Animation.
  33. */
  34. public abstract static class GQAnimation extends Animation {
  35. private static final String ACTUAL_ANIMATION = "EffectsRunnning";
  36. // Each Animation is associated to one element
  37. protected Element e;
  38. protected Properties prps;
  39. protected Easing easing;
  40. protected Function[] funcs;
  41. protected Effects g;
  42. public GQAnimation setElement(Element element) {
  43. e = element;
  44. g = $(e).as(Effects);
  45. return this;
  46. }
  47. public GQAnimation setProperties(Properties properties) {
  48. prps = properties == null ? Properties.create() : properties;
  49. if (prps.defined("easing")) {
  50. try {
  51. easing = EasingCurve.valueOf(prps.getStr("easing"));
  52. } catch (Exception ignore) {
  53. }
  54. }
  55. return this;
  56. }
  57. public GQAnimation setEasing(Easing ease) {
  58. easing = ease != null ? ease : EasingCurve.swing;
  59. return this;
  60. }
  61. public GQAnimation setCallback(Function... f) {
  62. funcs = f;
  63. return this;
  64. }
  65. protected void onStart() {
  66. // Mark this animation as actual, so as we can stop it in the GQuery.stop() method
  67. $(e).data(ACTUAL_ANIMATION, this);
  68. super.onStart();
  69. }
  70. protected void onComplete() {
  71. // avoid memory leak (issue #132)
  72. $(e).removeData(ACTUAL_ANIMATION);
  73. super.onComplete();
  74. }
  75. public void cancel() {
  76. // avoid memory leak (issue #132)
  77. $(e).removeData(ACTUAL_ANIMATION);
  78. super.cancel();
  79. }
  80. }
  81. /**
  82. * Just a class to store predefined speed constant values.
  83. */
  84. public static class Speed {
  85. public static final int DEFAULT = 400;
  86. public static final int FAST = 200;
  87. public static final int SLOW = 600;
  88. }
  89. public static final Class<Effects> Effects = GQuery.registerPlugin(
  90. Effects.class, new Plugin<Effects>() {
  91. public Effects init(GQuery gq) {
  92. return new Effects(gq);
  93. }
  94. });
  95. protected Effects(GQuery gq) {
  96. super(gq);
  97. }
  98. /**
  99. * Queue an animation for an element.
  100. *
  101. * The goal of this method is to reuse animations.
  102. * @param e
  103. * @param anim
  104. * @param duration
  105. */
  106. public void queueAnimation(final GQAnimation anim, final int duration) {
  107. if (isOff()) {
  108. anim.onStart();
  109. anim.onComplete();
  110. } else {
  111. queue(anim.e, DEFAULT_NAME, new Function() {
  112. public void cancel(Element e) {
  113. Animation anim = (Animation) data(e, GQAnimation.ACTUAL_ANIMATION, null);
  114. if (anim != null) {
  115. anim.cancel();
  116. }
  117. }
  118. public void f(Element e) {
  119. anim.run(duration);
  120. }
  121. });
  122. }
  123. }
  124. protected boolean isOff() {
  125. return Fx.off;
  126. }
  127. /**
  128. * Maintain a cache table with vendor properties so as plugins can use it.
  129. */
  130. public static JsMap<String, String>vendorPropNames;
  131. /**
  132. * Browser prefix for vendor spedific properties.
  133. */
  134. public static String prefix;
  135. static {
  136. if (GWT.isClient()) {
  137. vendorPropNames = JsMap.create();
  138. prefix = browser.msie ? "ms" : browser.opera ? "o" : browser.mozilla ? "moz" : browser.webkit ? "webkit" : "";
  139. }
  140. }
  141. /**
  142. * Get the cached vendor property name.
  143. */
  144. public static String vendorProperty(String prop) {
  145. return vendorPropNames.get(prop) != null ? vendorPropNames.get(prop) : prop;
  146. }
  147. /**
  148. * The animate() method allows you to create animation effects on any numeric
  149. * Attribute, CSS property, or color CSS property.
  150. *
  151. * Concerning to numeric properties, values are treated as a number of pixels
  152. * unless otherwise specified. The units em and % can be specified where
  153. * applicable.
  154. *
  155. * By default animate considers css properties, if you wanted to animate element
  156. * attributes you should to prepend the symbol dollar to the attribute name.
  157. *
  158. * Example:
  159. *
  160. * <pre class="code">
  161. * // move the element from its original position to the position top:500px and left:500px for 400ms.
  162. * // use a swing easing function for the transition
  163. * $("#foo").animate(Properties.create("{top:'500px',left:'500px'}"), 400, EasingCurve.swing);
  164. * // Change the width and border attributes of a table
  165. * $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, EasingCurve.linear);
  166. * </pre>
  167. *
  168. * In addition to numeric values, each property can take the strings 'show',
  169. * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing
  170. * animations that take into account the display type of the element. Animated
  171. * properties can also be relative. If a value is supplied with a leading +=
  172. * or -= sequence of characters, then the target value is computed by adding
  173. * or subtracting the given number from the current value of the property.
  174. *
  175. * Example:
  176. *
  177. * <pre class="code">
  178. * // move the element from its original position to 500px to the left and 5OOpx down for 400ms.
  179. * // use a swing easing function for the transition
  180. * $("#foo").animate(Properties.create("{top:'+=500px',left:'+=500px'}"), 400, Easing.SWING);
  181. * </pre>
  182. *
  183. * For color css properties, values can be specified via hexadecimal or rgb or
  184. * literal values.
  185. *
  186. * Example:
  187. *
  188. * <pre class="code">
  189. * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'", 400, EasingCurve.swing);
  190. * $("#foo").animate($$("{backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'}"), 400, EasingCurve.swing);
  191. * </pre>
  192. *
  193. * @param stringOrProperties object containing css properties to animate.
  194. * @param funcs an array of {@link Function} called once the animation is
  195. * complete
  196. * @param duration the duration in milliseconds of the animation
  197. * @param easing the easing function to use for the transition
  198. */
  199. public Effects animate(Object stringOrProperties, int duration, Easing easing, Function... funcs) {
  200. final Properties p = (stringOrProperties instanceof String)
  201. ? (Properties) $$((String) stringOrProperties)
  202. : (Properties) stringOrProperties;
  203. if (p.getStr("duration") != null) {
  204. duration = p.getInt("duration");
  205. }
  206. duration = Math.abs(duration);
  207. for (Element e : elements()) {
  208. GQAnimation a = createAnimation();
  209. a.setEasing(easing).setProperties(p).setElement(e).setCallback(funcs);
  210. queueAnimation(a, duration);
  211. }
  212. return this;
  213. }
  214. /**
  215. * Override this to create plugins with customized animation implementation.
  216. *
  217. * By default it uses deferred binding.
  218. */
  219. protected GQAnimation createAnimation() {
  220. return GWT.create(GQAnimation.class);
  221. }
  222. /**
  223. *
  224. * The animate() method allows you to create animation effects on any numeric
  225. * Attribute, CSS property, or color CSS property.
  226. *
  227. * Concerning to numeric properties, values are treated as a number of pixels
  228. * unless otherwise specified. The units em and % can be specified where
  229. * applicable.
  230. *
  231. * By default animate considers css properties, if you wanted to animate element
  232. * attributes you should to prepend the symbol dollar to the attribute name.
  233. *
  234. * Example:
  235. *
  236. * <pre class="code">
  237. * // move the element from its original position to left:500px for 500ms
  238. * $("#foo").animate("left:'500'");
  239. * // Change the width attribute of a table
  240. * $("table").animate("$width:'500'"), 400, EasingCurve.swing);
  241. * </pre>
  242. *
  243. * In addition to numeric values, each property can take the strings 'show',
  244. * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing
  245. * animations that take into account the display type of the element. Animated
  246. * properties can also be relative. If a value is supplied with a leading +=
  247. * or -= sequence of characters, then the target value is computed by adding
  248. * or subtracting the given number from the current value of the property.
  249. *
  250. * Example:
  251. *
  252. * <pre class="code">
  253. * // move the element from its original position to 500px to the left for 500ms and
  254. * // change the background color of the element at the end of the animation
  255. * $("#foo").animate("left:'+=500'", new Function(){
  256. *
  257. * public void f(Element e){
  258. * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED);
  259. * }
  260. *
  261. * });
  262. * </pre>
  263. *
  264. * The duration of the animation is 500ms.
  265. *
  266. * For color css properties, values can be specified via hexadecimal or rgb or
  267. * literal values.
  268. *
  269. * Example:
  270. *
  271. * <pre class="code">
  272. * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'");
  273. * </pre>
  274. *
  275. * @param stringOrProperties the property to animate : "cssName:'value'"
  276. * @param funcs an array of {@link Function} called once the animation is
  277. * complete
  278. */
  279. public Effects animate(Object stringOrProperties, Function... funcs) {
  280. return animate(stringOrProperties, Speed.DEFAULT, funcs);
  281. }
  282. /**
  283. * The animate() method allows you to create animation effects on any numeric
  284. * Attribute, CSS properties, or color CSS property.
  285. *
  286. * Concerning to numeric property, values are treated as a number of pixels
  287. * unless otherwise specified. The units em and % can be specified where
  288. * applicable.
  289. *
  290. * By default animate considers css properties, if you wanted to animate element
  291. * attributes you should to prepend the symbol dollar to the attribute name.
  292. *
  293. * Example:
  294. *
  295. * <pre class="code">
  296. * // move the element from its original position to left:500px for 2s
  297. * $("#foo").animate("left:'500px'", 2000);
  298. * // Change the width attribute of a table
  299. * $("table").animate("$width:'500'"), 400);
  300. * </pre>
  301. *
  302. * In addition to numeric values, each property can take the strings 'show',
  303. * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing
  304. * animations that take into account the display type of the element. Animated
  305. * properties can also be relative. If a value is supplied with a leading +=
  306. * or -= sequence of characters, then the target value is computed by adding
  307. * or subtracting the given number from the current value of the property.
  308. *
  309. * Example:
  310. *
  311. * <pre class="code">
  312. * // move the element from its original position to 500px to the left for 1000ms and
  313. * // change the background color of the element at the end of the animation
  314. * $("#foo").animate("left:'+=500'", 1000, new Function(){
  315. * public void f(Element e){
  316. * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED);
  317. * }
  318. * });
  319. * </pre>
  320. *
  321. * For color css properties, values can be specified via hexadecimal or rgb or
  322. * literal values.
  323. *
  324. * Example:
  325. *
  326. * <pre class="code">
  327. * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)', 1000");
  328. * </pre>
  329. *
  330. * @param stringOrProperties the property to animate : "cssName:'value'"
  331. * @param funcs an array of {@link Function} called once the animation is
  332. * complete
  333. * @param duration the duration in milliseconds of the animation
  334. */
  335. public Effects animate(Object stringOrProperties, int duration, Function... funcs) {
  336. return animate(stringOrProperties, duration, EasingCurve.linear, funcs);
  337. }
  338. /**
  339. * Reveal all matched elements by adjusting the clip or scale property firing an optional callback
  340. * after completion. The effect goes from the center to the perimeter.
  341. */
  342. public Effects clipAppear(Function... f) {
  343. return clipAppear(Speed.DEFAULT, f);
  344. }
  345. /**
  346. * Reveal all matched elements by adjusting the clip or scale property firing an optional callback
  347. * after completion. The effect goes from the center to the perimeter.
  348. */
  349. public Effects clipAppear(int millisecs, Function... f) {
  350. return animate($$("clip-action: show"), millisecs, f);
  351. }
  352. /**
  353. * Hide all matched elements by adjusting the clip or scale property firing an optional callback
  354. * after completion. The effect goes from the perimeter to the center.
  355. */
  356. public Effects clipDisappear(Function... f) {
  357. return clipDisappear(Speed.DEFAULT, f);
  358. }
  359. /**
  360. * Hide all matched elements by adjusting the clip or scale property firing an optional callback
  361. * after completion. The effect goes from the perimeter to the center.
  362. */
  363. public Effects clipDisappear(int millisecs, Function... f) {
  364. return animate($$("clip-action: hide"), millisecs, f);
  365. }
  366. /**
  367. * Reveal all matched elements by adjusting the clip or scale property firing an optional callback
  368. * after completion. The effect goes from the top to the bottom.
  369. */
  370. public Effects clipDown(Function... f) {
  371. return clipDown(Speed.DEFAULT, f);
  372. }
  373. /**
  374. * Reveal all matched elements by adjusting the clip or scale property firing an optional callback
  375. * after completion. The effect goes from the top to the bottom.
  376. */
  377. public Effects clipDown(int millisecs, Function... f) {
  378. return animate($$("clip-action: show, clip-origin: top-left"), millisecs, f);
  379. }
  380. /**
  381. * Toggle the visibility of all matched elements by adjusting the clip or scale property and
  382. * firing an optional callback after completion. The effect goes from the bottom to the top.
  383. */
  384. public Effects clipToggle(Function... f) {
  385. return clipToggle(Speed.DEFAULT, f);
  386. }
  387. /**
  388. * Toggle the visibility of all matched elements by adjusting the clip or scale or scale property
  389. * and firing an optional callback after completion. The effect goes from the bottom to the top.
  390. */
  391. public Effects clipToggle(int millisecs, Function... f) {
  392. return animate($$("clip-action: toggle, clip-origin: top-left"), millisecs, f);
  393. }
  394. /**
  395. * Hide all matched elements by adjusting the clip or scale property firing an optional callback
  396. * after completion. The effect goes from the bottom to the top.
  397. */
  398. public Effects clipUp(Function... f) {
  399. return clipUp(Speed.DEFAULT, f);
  400. }
  401. /**
  402. * Hide all matched elements by adjusting the clip or scale property firing an optional callback
  403. * after completion. The effect goes from the bottom to the top.
  404. */
  405. public Effects clipUp(int millisecs, Function... f) {
  406. return animate($$("clip-action: hide, clip-origin: top-left"), millisecs, f);
  407. }
  408. /**
  409. * Fade in all matched elements by adjusting their opacity and firing an
  410. * optional callback after completion. Only the opacity is adjusted for this
  411. * animation, meaning that all of the matched elements should already have
  412. * some form of height and width associated with them.
  413. */
  414. public Effects fadeIn(Function... f) {
  415. return fadeIn(Speed.DEFAULT, f);
  416. }
  417. /**
  418. * Fade in all matched elements by adjusting their opacity and firing an
  419. * optional callback after completion. Only the opacity is adjusted for this
  420. * animation, meaning that all of the matched elements should already have
  421. * some form of height and width associated with them.
  422. */
  423. public Effects fadeIn(int millisecs, Function... f) {
  424. return animate("opacity: 'show'", millisecs, f);
  425. }
  426. /**
  427. * Fade out all matched elements by adjusting their opacity to 0, then setting
  428. * display to "none" and firing an optional callback after completion. Only
  429. * the opacity is adjusted for this animation, meaning that all of the matched
  430. * elements should already have some form of height and width associated with
  431. * them.
  432. */
  433. public Effects fadeOut(Function... f) {
  434. return fadeOut(Speed.DEFAULT, f);
  435. }
  436. /**
  437. * Fade out all matched elements by adjusting their opacity to 0, then setting
  438. * display to "none" and firing an optional callback after completion. Only
  439. * the opacity is adjusted for this animation, meaning that all of the matched
  440. * elements should already have some form of height and width associated with
  441. * them.
  442. */
  443. public Effects fadeOut(int millisecs, Function... f) {
  444. return animate("opacity: 'hide'", millisecs, f);
  445. };
  446. /**
  447. * Fade the opacity of all matched elements to a specified opacity and firing
  448. * an optional callback after completion. Only the opacity is adjusted for
  449. * this animation, meaning that all of the matched elements should already
  450. * have some form of height and width associated with them.
  451. */
  452. public Effects fadeTo(double opacity, Function... f) {
  453. return fadeTo(Speed.DEFAULT, opacity, f);
  454. }
  455. /**
  456. * Fade the opacity of all matched elements to a specified opacity and firing
  457. * an optional callback after completion. Only the opacity is adjusted for
  458. * this animation, meaning that all of the matched elements should already
  459. * have some form of height and width associated with them.
  460. */
  461. public Effects fadeTo(int millisecs, double opacity, Function... f) {
  462. return animate("opacity: " + opacity, millisecs, f);
  463. }
  464. /**
  465. * Display or hide the matched elements by animating their opacity. and firing
  466. * an optional callback after completion. Only the opacity is adjusted for
  467. * this animation, meaning that all of the matched elements should already
  468. * have some form of height and width associated with them.
  469. */
  470. public Effects fadeToggle(Function... f) {
  471. return fadeToggle(Speed.DEFAULT, f);
  472. }
  473. /**
  474. * Display or hide the matched elements by animating their opacity. and firing
  475. * an optional callback after completion. Only the opacity is adjusted for
  476. * this animation, meaning that all of the matched elements should already
  477. * have some form of height and width associated with them.
  478. */
  479. public Effects fadeToggle(int millisecs, Function... f) {
  480. return animate("opacity: 'toggle'", millisecs, f);
  481. };
  482. /**
  483. * Reveal all matched elements by adjusting their height and firing an
  484. * optional callback after completion.
  485. */
  486. public Effects slideDown(Function... f) {
  487. return slideDown(Speed.DEFAULT, f);
  488. }
  489. /**
  490. * Reveal all matched elements by adjusting their height and firing an
  491. * optional callback after completion.
  492. */
  493. public Effects slideDown(int millisecs, Function... f) {
  494. return animate("height: 'show'", millisecs, f);
  495. }
  496. /**
  497. * Hide all matched elements by adjusting their width and firing an optional
  498. * callback after completion.
  499. */
  500. public Effects slideLeft(Function... f) {
  501. return slideLeft(Speed.DEFAULT, f);
  502. }
  503. /**
  504. * Hide all matched elements by adjusting their width and firing an optional
  505. * callback after completion.
  506. */
  507. public Effects slideLeft(int millisecs, Function... f) {
  508. return animate("width: 'hide'", millisecs, f);
  509. }
  510. /**
  511. * Reveal all matched elements by adjusting their width and firing an optional
  512. * callback after completion.
  513. */
  514. public Effects slideRight(Function... f) {
  515. return slideRight(Speed.DEFAULT, f);
  516. }
  517. /**
  518. * Reveal all matched elements by adjusting their width and firing an optional
  519. * callback after completion.
  520. */
  521. public Effects slideRight(final int millisecs, Function... f) {
  522. return animate("width: 'show'", millisecs, f);
  523. }
  524. /**
  525. * Toggle the visibility of all matched elements by adjusting their height and firing an optional
  526. * callback after completion. Only the height is adjusted for this animation, causing all matched
  527. * elements to be hidden or shown in a "sliding" manner
  528. */
  529. public Effects slideToggle(Function... f) {
  530. return as(Effects).slideToggle(Speed.DEFAULT, f);
  531. }
  532. /**
  533. * Toggle the visibility of all matched elements by adjusting their height and
  534. * firing an optional callback after completion. Only the height is adjusted
  535. * for this animation, causing all matched elements to be hidden or shown in a
  536. * "sliding" manner
  537. */
  538. public Effects slideToggle(int millisecs, Function... f) {
  539. return animate("height: 'toggle'", millisecs, f);
  540. }
  541. /**
  542. * Hide all matched elements by adjusting their height and firing an optional
  543. * callback after completion.
  544. */
  545. public Effects slideUp(Function... f) {
  546. return slideUp(Speed.DEFAULT, f);
  547. }
  548. /**
  549. * Hide all matched elements by adjusting their height and firing an optional
  550. * callback after completion.
  551. */
  552. public Effects slideUp(int millisecs, Function... f) {
  553. return animate("height: 'hide'", millisecs, f);
  554. }
  555. /**
  556. * Toggle displaying each of the set of matched elements by animating the
  557. * width, height, and opacity of the matched elements simultaneously. When
  558. * these properties reach 0 after a hiding animation, the display style
  559. * property is set to none to ensure that the element no longer affects the
  560. * layout of the page.
  561. */
  562. public Effects toggle(int millisecs, Function... f) {
  563. return animate("opacity: 'toggle', width : 'toggle', height : 'toggle'",
  564. millisecs, f);
  565. }
  566. }