mseemann/angular2-mdl

View on GitHub
projects/core/src/lib/ripple/ripple.vendor.ts

Summary

Maintainability
D
1 day
Test Coverage
/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */
/* eslint-disable */
/* istanbul ignore file */
// @ts-nocheck
"use strict";

/**
 * Class constructor for Ripple MDL component.
 * Implements MDL component design pattern defined at:
 * https://github.com/jasonmayes/mdl-component-design-pattern
 *
 */
export function MaterialRipple(renderer, element): void {
  this.renderer_ = renderer;
  this.element_ = element;

  // Initialize instance.
  this.init();
}

/**
 * Store constants in one place so they can be updated easily.
 */
MaterialRipple.prototype.Constant_ = {
  INITIAL_SCALE: "scale(0.0001, 0.0001)",
  INITIAL_SIZE: "1px",
  INITIAL_OPACITY: "0.4",
  FINAL_OPACITY: "0",
  FINAL_SCALE: "",
};

/**
 * Store strings for class names defined by this component that are used in
 * JavaScript. This allows us to simply change it in one place should we
 * decide to modify at a later date.
 */
MaterialRipple.prototype.CssClasses_ = {
  RIPPLE_CENTER: "mdl-ripple--center",
  RIPPLE_EFFECT_IGNORE_EVENTS: "mdl-js-ripple-effect--ignore-events",
  RIPPLE: "mdl-ripple",
  IS_ANIMATING: "is-animating",
  IS_VISIBLE: "is-visible",
};

/**
 * Handle mouse / finger down on element.
 *
 */
// eslint-disable-next-line
MaterialRipple.prototype.downHandler_ = function (event) {
  if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) {
    const rect = this.element_.getBoundingClientRect();
    this.boundHeight = rect.height;
    this.boundWidth = rect.width;
    this.rippleSize_ =
      Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2;
    this.rippleElement_.style.width = this.rippleSize_ + "px";
    this.rippleElement_.style.height = this.rippleSize_ + "px";
  }

  this.renderer_.addClass(this.rippleElement_, this.CssClasses_.IS_VISIBLE);

  if (event.type === "mousedown" && this.ignoringMouseDown_) {
    this.ignoringMouseDown_ = false;
  } else {
    if (event.type === "touchstart") {
      this.ignoringMouseDown_ = true;
    }
    const frameCount = this.getFrameCount();
    if (frameCount > 0) {
      return;
    }
    this.setFrameCount(1);
    const bound = event.currentTarget.getBoundingClientRect();
    let x;
    let y;
    // Check if we are handling a keyboard click.
    if (event.clientX === 0 && event.clientY === 0) {
      x = Math.round(bound.width / 2);
      y = Math.round(bound.height / 2);
    } else {
      const clientX =
        event.clientX !== undefined ? event.clientX : event.touches[0].clientX;
      const clientY =
        event.clientY !== undefined ? event.clientY : event.touches[0].clientY;
      x = Math.round(clientX - bound.left);
      y = Math.round(clientY - bound.top);
    }
    this.setRippleXY(x, y);
    this.setRippleStyles(true);
    window.requestAnimationFrame(this.animFrameHandler.bind(this));
  }
};

/**
 * Handle mouse / finger up on element.
 *
 */
// eslint-disable-next-line
MaterialRipple.prototype.upHandler_ = function (event) {
  // Don't fire for the artificial "mouseup" generated by a double-click.
  if (event && event.detail !== 2) {
    // Allow a repaint to occur before removing this class, so the animation
    // shows for tap events, which seem to trigger a mouseup too soon after
    // mousedown.
    // eslint-disable-next-line
    setTimeout(
      function () {
        this.renderer_.removeClass(
          this.rippleElement_,
          this.CssClasses_.IS_VISIBLE
        );
      }.bind(this),
      0
    );
  }
};

/**
 * Initialize element.
 */
// eslint-disable-next-line
MaterialRipple.prototype.init = function () {
  if (this.element_) {
    const recentering = this.element_.classList.contains(
      this.CssClasses_.RIPPLE_CENTER
    );
    if (
      !this.element_.classList.contains(
        this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS
      )
    ) {
      this.rippleElement_ = this.element_.querySelector(
        "." + this.CssClasses_.RIPPLE
      );
      this.frameCount_ = 0;
      this.rippleSize_ = 0;
      this.x_ = 0;
      this.y_ = 0;

      // Touch start produces a compat mouse down event, which would cause a
      // second ripples. To avoid that, we use this property to ignore the first
      // mouse down after a touch start.
      this.ignoringMouseDown_ = false;

      this.boundDownHandler = this.downHandler_.bind(this);
      this.element_.addEventListener("mousedown", this.boundDownHandler);
      this.element_.addEventListener("touchstart", this.boundDownHandler);

      this.boundUpHandler = this.upHandler_.bind(this);
      this.element_.addEventListener("mouseup", this.boundUpHandler);
      this.element_.addEventListener("mouseleave", this.boundUpHandler);
      this.element_.addEventListener("touchend", this.boundUpHandler);
      this.element_.addEventListener("blur", this.boundUpHandler);

      // eslint-disable-next-line
      this.getFrameCount = function () {
        return this.frameCount_;
      };

      // eslint-disable-next-line
      this.setFrameCount = function (fC) {
        this.frameCount_ = fC;
      };

      // eslint-disable-next-line
      this.getRippleElement = function () {
        return this.rippleElement_;
      };

      // eslint-disable-next-line
      this.setRippleXY = function (newX, newY) {
        this.x_ = newX;
        this.y_ = newY;
      };

      // eslint-disable-next-line
      this.setRippleStyles = function (start) {
        if (this.rippleElement_ !== null) {
          let transformString;
          let scale;
          let size;
          let offset = "translate(" + this.x_ + "px, " + this.y_ + "px)";

          if (start) {
            scale = this.Constant_.INITIAL_SCALE;
            size = this.Constant_.INITIAL_SIZE;
          } else {
            scale = this.Constant_.FINAL_SCALE;
            size = this.rippleSize_ + "px";
            if (recentering) {
              offset =
                "translate(" +
                this.boundWidth / 2 +
                "px, " +
                this.boundHeight / 2 +
                "px)";
            }
          }

          transformString = "translate(-50%, -50%) " + offset + scale;

          this.rippleElement_.style.webkitTransform = transformString;
          this.rippleElement_.style.msTransform = transformString;
          this.rippleElement_.style.transform = transformString;

          if (start) {
            this.renderer_.removeClass(
              this.rippleElement_,
              this.CssClasses_.IS_ANIMATING
            );
          } else {
            this.renderer_.addClass(
              this.rippleElement_,
              this.CssClasses_.IS_ANIMATING
            );
          }
        }
      };

      /**
       * Handles an animation frame.
       */
      // eslint-disable-next-line
      this.animFrameHandler = function () {
        if (this.frameCount_-- > 0) {
          window.requestAnimationFrame(this.animFrameHandler.bind(this));
        } else {
          this.setRippleStyles(false);
        }
      };
    }
  }
};