/**
 * jquery.ripple.js
 * 
 * @version 0.0.1
 * @author SUSH <sush@sus-happy.ner>
 * https://github.com/sus-happy/jquery.ripple.js
 */

(function($, U) {
    // use border-radius
    $.support.borderRadius = false;
    // use transition
    $.support.transition = false;
    $(function() {
        $.each( [ 'borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius' ], function( i, v ) {
            if( document.body.style[v] !== undefined ) $.support.borderRadius = true;
            return (! $.support.borderRadius );
        } );

        var el = $("<div>");
        $.support.transition = typeof el.css("transitionProperty") === "string";
    } );

    $.extend( {
        // jquery.ripple用の関数
        ripple: {
            // アニメーションの裏に隠れないようにするDOM
            $textSpan: $('<span>').css( { position: 'relative', 'z-index': 2 } ),
            // アニメーション用のDOM
            $rippleWrap: $('<span>', { 'class': 'rippleWrap' } ).css( { position: 'absolute', 'z-index': 1, 'left': 0, 'top': 0, 'overflow': 'hidden' } ).append(
                            $('<span>', { 'class': 'rippleAnimate' } ).css( { position: 'absolute', 'left': 0, 'top': 0, 'width': 0, 'height': 0, 'border-radius': '50%' } )
                         ),
            // jquery.rippleが利用できるか？
            is: function() {
                return $.support.borderRadius && $.support.transition;
            },
            // coreクラス
            core: function( target, param ) {
                this.$target   = target;
                this._v_duration = 400;
                this._h_duration = 400;
                this._timer      = null;

                // paramに値があれば設定変更
                if( param !== U && Object.prototype.hasOwnProperty.call( param, 'v_duration' ) ) {
                    this.set_view_duration( param.v_duration );
                }
                if( param !== U && Object.prototype.hasOwnProperty.call( param, 'h_duration' ) ) {
                    this.set_hide_duration( param.h_duration );
                }

                // イベント初期設定
                this.init();
            }
        }
    } );

    // coreクラスを拡張しておく
    $.ripple.core.prototype = {
        // 設定変更
        set_view_duration: function( v_duration ) {
            this._v_duration = v_duration;
        },
        set_hide_duration: function( h_duration ) {
            this._h_duration = h_duration;
        },

        // イベント初期設定
        init: function() {
            var that = this;

            // position staticだったらrelativeにしておく
            if( this.$target.css( 'position' ) === 'static' ) {
                this.$target.css( 'position', 'relative' );
            }
            // スマホ端末のハイライトを切る
            this.$target.css( '-webkit-tap-highlight-color', 'rgba( 0, 0, 0, 0 )' );

            // 必要DOMを追加
            this.$target.wrapInner( $.ripple.$textSpan );
            this.$target.append( $.ripple.$rippleWrap.clone() );

            // 必要DOMを変数に入れておく
            this.$rippleWrap    = this.$target.find( '.rippleWrap' );
            this.$rippleAnimate = this.$target.find( '.rippleAnimate' );

            // マスクに関係するスタイルを反映する
            // border-radius
            this.$rippleWrap.css( 'border-radius', this.$target.css( 'border-radius' ) );

            // 色を指定
            this.$target.find( '.rippleAnimate' ).css( 'background-color', this.$target.attr( 'data-color' ) );

            // イベントを登録
            if( ('ontouchstart' in window) ) {
                this.$target.bind( 'touchstart.ripple', function( e ) {
                    that.view( e.originalEvent.touches[0] );
                } );
                this.$target.bind( 'touchend.ripple', function( e ) {
                    that.hidden( e.originalEvent.touches[0] );
                } );
                this.$target.bind( 'mouseleave.ripple', function( e ) {
                    that.hidden( e );
                } );
            } else {
                this.$target.bind( 'mousedown.ripple', function( e ) {
                    that.view( e );
                } );
                this.$target.bind( 'mouseup.ripple mouseleave.ripple', function( e ) {
                    that.hidden( e );
                } );
            }
        },

        // イベント廃止
        remove: function() {
        },

        // アニメーション開始
        view: function(e) {
            // タイマーは切っておく
            clearTimeout(this._timer);

            // マスク要素のサイズを再取得（変わる可能性も考慮して）
            var width  = this.$target.outerWidth();
            var height = this.$target.outerHeight();
            this.$rippleWrap.stop( true, false ).width( width ).height( height ).css( { 'opacity': 1, 'transition': 'none' } );

            // サイズを指定（縦横の大きい値）
            var circleRatio      = 2.8;
            var size = Math.max( width, height );

            // マウスボタンの位置を取得
            // offsetX, offsetYがおかしいのでpageX, pageYから計算する
            var offsetX = e.pageX - this.$target.offset().left;
            var offsetY = e.pageY - this.$target.offset().top;
            this.$rippleAnimate.css( { 'width': size, 'height': size, 'transform': 'scale3d( 0, 0, 1 )', 'left': offsetX-size/2, 'top': offsetY-size/2, 'transition': 'none' } );

            var animateTo        = {};
            animateTo.transform  = 'scale3d( ' + circleRatio + ', ' + circleRatio + ', 1 )';
            animateTo.transition = ( this._v_duration/1000 )+'s ease-out';

            // アニメーション開始
            this.$rippleAnimate.show()
                .css( animateTo );
        },

        // アニメーション終了
        hidden: function( e ) {
            var that = this;
            // Wrapの透明度を下げて隠していく
            this.$rippleWrap.stop( true, false ).css( { 'opacity': 0, 'transition': 'opacity '+( this._h_duration/1000 )+'s ease-out' } );

            // アニメーション終了タイミングでサイズ変更
            clearTimeout( this._timer );
            this._timer = setTimeout( function() {
                that.$rippleWrap.css( { 'opacity': 1, 'transition': 'none' } );
                that.$rippleAnimate.css( { 'transform': 'scale3d( 0, 0, 1 )', 'transition': 'none' } );
            }, this._v_duration );
        }
    };

    $.fn.extend( {
        // jquery.ripple
        ripple: function( opt ) {
            // 必要条件に満たさなければ終了
            // border-radiusとtransitionが使えればたぶん動く
            if(! $.ripple.is() ) {
                return $(this);
            }

            // 対象DOMに対してイベントを登録する
            $(this).each( function() {
                new $.ripple.core( $(this), opt );
            } );

            return $(this);
        }
    });
})(jQuery);


(function($) {
    $(function() {
        $('.ripple').ripple();
        $('.btn').ripple();
        $('.fab').ripple();
    });
})(jQuery);
