All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.query.client.plugins.effects.PropertiesAnimation Maven / Gradle / Ivy

There is a newer version: 1.5-beta1
Show newest version
/*
 * Copyright 2011, The gwtquery team.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.query.client.plugins.effects;

import com.google.gwt.dom.client.Element;
import com.google.gwt.query.client.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.js.JsRegexp;
import com.google.gwt.query.client.plugins.Effects;
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.ColorFx.BorderColorFx;

/**
 * Animation effects on any numeric CSS property.
 */
public class PropertiesAnimation extends GQAnimation {

  /**
   * Easing method to use.
   */
  public static interface Easing {
    public double interpolate(double progress);

    public Easing LINEAR = new Easing() {
      public double interpolate(double progress) {
        return progress;
      }
    };

    public Easing SWING = new Easing() {
      public double interpolate(double progress) {
        return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2;
      }
    };
  }

  private static final String[] ATTRS_TO_SAVE = new String[]{
      "overflow"};

  private static final JsRegexp REGEX_NUMBER_UNIT = new JsRegexp(
      "^([0-9+-.]+)(.*)?$");

  private static final JsRegexp REGEX_SYMBOL_NUMBER_UNIT = new JsRegexp(
      "^([+-]=)?([0-9+-.]+)(.*)?$");

  private static final JsRegexp REGEX_NON_PIXEL_ATTRS = new JsRegexp(
      "z-?index|font-?weight|opacity|zoom|line-?height|^\\$", "i");

  private static final JsRegexp REGEX_COLOR_ATTR = new JsRegexp(".*color$", "i");

  private static final JsRegexp REGEX_BORDERCOLOR = new JsRegexp("^bordercolor$", "i");

  private static final JsRegexp REGEX_BACKGROUNDCOLOR = new JsRegexp("^backgroundcolor$", "i");



  public static Fx computeFxProp(Element e, String key, String val,
      boolean hidden) {

    if (REGEX_COLOR_ATTR.test(key)) {
      return computeFxColorProp(e, key, val);
    }

    return computeFxNumericProp(e, key, val, hidden);
  }

  private static Fx computeFxColorProp(Element e, String key, String val) {

    if (REGEX_BORDERCOLOR.test(key)) {
      return new BorderColorFx(e, val);
    }

    String initialColor = null;
    if (REGEX_BACKGROUNDCOLOR.test(key)) {
      // find the first parent having a background-color value (other than
      // transparent)
      Element current = e;

      while ((initialColor == null || initialColor.length() == 0 || initialColor.equals("transparent"))
          && current != null) {
        initialColor = GQuery.$(current).css(key, false);
        current = !"body".equalsIgnoreCase(current.getTagName())
            ? current.getParentElement() : null;
      }
      if (initialColor == null || initialColor.length() == 0
          || initialColor.equals("transparent")) {
        initialColor = "white";
      }
    } else {
      initialColor = GQuery.$(e).css(key, true);
    }

    return new ColorFx(key, initialColor, val);
  }

  public static Fx computeFxNumericProp(Element e, String key, String val,
      boolean hidden) {

    GQuery g = Effects.$(e);
    String unit = "";
    if ("toggle".equals(val)) {
      val = hidden ? "show" : "hide";
    }

    if (("show".equals(val) && !hidden) || ("hide").equals(val) && hidden) {
      return null;
    }

    if (hidden) {
      g.show();
    }

    // If key starts with $ we animate node attributes, otherwise css properties
    double cur;
    String rkey = null;
    if (key.startsWith("$")) {
      rkey = key.substring(1).toLowerCase();
      String attr = g.attr(rkey);
      JsObjectArray parts = REGEX_NUMBER_UNIT.match(attr);
      if (parts != null) {
        String $1 = parts.get(1);
        String $2 = parts.get(2);
        cur = Double.parseDouble($1);
        unit = $2 == null ? "" : $2;
      } else {
        cur = g.cur(key, true);
        key = rkey;
      }
    } else {
      cur = g.cur(key, true);
    }

    double start = cur, end = start;

    if ("show".equals(val)) {
      g.saveCssAttrs(key);
      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";
    } else {
      JsObjectArray parts = REGEX_SYMBOL_NUMBER_UNIT.match(val);

      if (parts != null) {
        String $1 = parts.get(1);
        String $2 = parts.get(2);
        String $3 = parts.get(3);
        end = Double.parseDouble($2);

        if (rkey == null) {
          unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : //
            $3 == null || $3.isEmpty() ? "px" : $3;
          if (!"px".equals(unit)) {
            double to = end == 0 ? 1 : end;
            g.css(key, to + unit);
            start = to * start / g.cur(key, true);
            g.css(key, start + unit);
          }
        } else if ($3 != null && !$3.isEmpty()) {
          unit = $3;
        }

        if ($1 != null && !$1.isEmpty()) {
          end = (("-=".equals($1) ? -1 : 1) * end) + start;
        }
      }
    }

    return new Fx(key, val, start, end, unit, rkey);
  }

  private Easing easing = Easing.SWING;
  private JsObjectArray effects = JsObjectArray.create();
  private Function[] funcs;

  private Effects g;

  private Properties prps;

  public PropertiesAnimation(Easing easing, Element elem, Properties p,
      Function... funcs) {
    this.easing = easing;
    this.e = elem;
    this.funcs = funcs;
    this.prps = p;
    g = Effects.$(e).as(Effects.Effects);
  }

  @Override
  public void onCancel() {
    Boolean jumpToEnd = Effects.$(e).data(Effects.JUMP_TO_END, Boolean.class);
    if (jumpToEnd != null && jumpToEnd){
      onComplete();
    } else {
      g.dequeue();
      g.restoreCssAttrs(ATTRS_TO_SAVE);
    }
  }

  @Override
  public void onComplete() {
    super.onComplete();
    for (int i = 0; i < effects.length(); i++) {
      Fx fx = effects.get(i);
      if ("hide".equals(fx.value)) {
        g.hide();
        g.restoreCssAttrs(fx.cssprop);
      } else if ("show".equals(fx.value)) {
        g.show();
        g.restoreCssAttrs(fx.cssprop);
      }
    }
    g.restoreCssAttrs(ATTRS_TO_SAVE);
    g.each(funcs);
    g.dequeue();
  }

  @Override
  public void onStart() {
    boolean resize = false;
    boolean move = false;
    boolean hidden = !g.isVisible();
    Fx fx;
    // g.show();
    for (String key : prps.keys()) {
      String val = prps.getStr(key);
      if ((fx = computeFxProp(e, key, val, hidden)) != null) {
        effects.add(fx);
        resize = resize || "height".equals(key) || "width".equals(key);
        move = move || "top".equals(key) || "left".equals(key);
      }
    }
    g.saveCssAttrs(ATTRS_TO_SAVE);
    if (resize) {
      g.css("overflow", "hidden");
    }
    if (move && !g.css("position", true).matches("absolute|relative|fixed")) {
      g.css("position", "relative");
    }
    super.onStart();
  }

  @Override
  public void onUpdate(double progress) {
    for (int i = 0; i < effects.length(); i++) {
      effects.get(i).applyValue(g, progress);
    }
  }

  @Override
  protected double interpolate(double progress) {
    if (easing != null) {
      return easing.interpolate(progress);
    }
    // maybe return super.interpolate() instead ?
    return progress;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy