;
/*************************************************************
 *
 * Copyright (c) 2022 ysrock Co., Ltd.	<info@ysrock.co.jp>
 * Copyright (c) 2022 Yasuo Sugano	<sugano@ysrock.co.jp>
 *
 * Version	: 1.0.0
 * Update	: 2022.09.15
 *
 ************************************************************/
'use strict';
(function($){
  /*
   * アラートを表示
   *	$.fn.ysAlert( string $subject, ?array $opts)
   *		$opts = array( ?'body' = string $body, ?'buttons' = array $buttons );
   *			$buttons = array(
   *				array( 'text' = string $text, ?'style' = string $style, ?'callback' = callback $callback )
   *				...
   *			);
   *
   * 非同期通信の準備
   *	$( ?element $element='form' ).ysAjax():object
   *
   * iOS風のスピナー
   *	$.fn.ysIosSpinner( ?array $opts ):element
   *
   * JSONに変換
   *	$.fn.ysToJSON( string|JSON $arg ):boolean [ JSON | false ]
   *
   * UUIDv4を生成
   *	$.fn.ysMkUUID():string
   *
   * 各イベントにUUIDを付加（アンカークリック、フォーム送信）
   *	$.fn.setEventUUID()
   *
   * 左からスワイプで浮遊要素を画面外に（その後削除）
   *	$( element $element ).swipeOut( ?array $opts )
   *		$opts = array( ?'startArea' = int $startArea = 5, ?'percent' = int $percent = 50 );
   *
   */



  /**********************************************************************
   *
   *　アラートを表示
   *
   *	使い方
   *		$.fn.ysAlert( string $subject, ?array $opts)
   *
   *	パラメータ
   *		$subject
   *			件名
   *		$opts
   *			オプション配列
   *
   *	戻り値
   *		アラート要素
   *
   *	備考
   *
   **********************************************************************
   *
   *	オプション配列
   *		$opts = array(
   *			?'body' = string $body,
   *			?'buttons' = array $buttons
   *		);
   *
   *	パラメータ
   *		$body
   *			本文
   *		$buttons
   *			ボタン配列
   *
   **********************************************************************
   *
   *	ボタン配列
   *		$buttons = array(
   *			array(
   *				'text' = string $text,
   *				?'style' = string $style,
   *				?'callback' = callback $callback
   *			)
   *			...
   *		);
   *
   *	パラメータ
   *		$text
   *			表示文字
   *		$style
   *			スタイルシート
   *		$callback
   *			クリックイベント
   *
   **********************************************************************/
  let ysAlert = {
    init : function( subject, args ){
      if(typeof subject != "string") return;
      // オプションを定義
      if(args === undefined) args = {};
      // ボタンが未定義
      if(args['buttons'] === undefined || args['buttons'].length == 0) args['buttons'] = [{ 'text':'OK' }];

      // HTMLを作成
      let html = ysAlert.makeHtml( subject, args );
      // エレメント化
      let elem = $(html);
      // 背景スクロールを禁止する
      elem.on('mousewheel', function(e){ e.preventDefault(); });
      elem.on('touchmove', function(e){ e.preventDefault(); });
      // ボタンを追加
      elem = ysAlert.insButtons( elem, args['buttons'] );
      // 要素を追加
      $('body').append( elem );
      // 戻り値
      return elem;
    },

    /*
     * HTMLを作成
     */
    makeHtml : function( subject, args ){
      let html = "";
      html += "<div class=\"ysrock_ios_alert\">";
      html += " <div class=\"wrap\">";
      html += "  <div class=\"subject\">" + subject + "</div>";
      if(typeof args['body'] === "string") html += "  <div class=\"body\">" + args['body'] + "</div>";
      html += "  <div class=\"buttons\"></div>";
      html += " </div><!-- END div.wrap -->";
      html += "</div><!-- END div.ysrock_ios_alert -->";
      return html;
    },

    /*
     * ボタンを追加
     */
    insButtons : function( element, buttons ){
      for(let i=0, len=buttons.length; i<len; i++){
        // 配列
        let btn = buttons[i];
        // HTMLを作成
        let html = '<div ' + (btn['style'] ? ' style="'+btn['style']+'"' : '') + '>' + btn['text'] + '</div>';
        // エレメント化
        let elem = $(html);
        // クリックイベント
        if(typeof btn['callback'] === "function") elem.click( btn['callback'](elem) );
        else elem.click(function(){ $(this).closest('div.ysrock_ios_alert').remove(); });
        // 追加する
        $('div.wrap > div.buttons', element).append(elem);
      };// END for
      return element;
    },

  };
  $.fn.ysAlert = function(){
    return ysAlert.init.apply( this, arguments );
  };
  /********** END アラートを表示 ********************/



  /**********************************************************************
   *
   *　非同期通信の準備
   *
   *	使い方
   *		$( ?element $element='form' ).ysAjax():object
   *
   *	パラメータ
   *		$element
   *			対象のform
   *
   *	戻り値
   *		オブジェクト
   *
   **********************************************************************/
  let ysAjax = {
    init : function(){
      // 戻り値
      let result = {};

      /*
       * 設定
       */
      result.settings = {
        url : $(this).attr('action') ? $(this).attr('action') : ""
       ,method : $(this).attr('method') ? $(this).attr('method') : 'GET'
       ,dataType : $(this).attr('dataType') ? $(this).attr('dataType') : 'json'
       ,cache : false
      };
      if( $(this)[0] ) result.settings.data = $(this).serialize();

      /*
       * 失敗時コンソールに表示する
       */
      result.fail = function( args ){
        return(function(xhr, textStatus, errorThrown){
          // コンソールに出力
          console.log([ args, xhr, textStatus, errorThrown ]);
        });
      };

      return result;
    },
  };
  $.fn.ysAjax = function( method ){
    if( ysAjax[method] ) return ysAjax[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    else if( typeof method === 'object' || !method) return ysAjax.init.apply( this, arguments );
    else $.error('Method' + method + ' does not exist on jQuery.ysAjax');
  };
  /********** END 非同期通信の準備 ********************/



  /**********************************************************************
   *
   *　iOS風のスピナー
   *
   *	使い方
   *		$.fn.ysIosSpinner( ?array $opts ):element
   *
   *	パラメータ
   *		$element
   *			この属性の末尾にスピナーを追加する
   *
   *		$opts
   *			オプション配列
   *
   *	戻り値
   *		element スピナー要素
   *
   *	備考
   *		スピナーを閉じる場合は、$(スピナー要素).remove();
   *
   **********************************************************************
   *
   *	オプション配列
   *		$opts = array(
   *			?'close_button' = callback $close_button,
   *		);
   *
   *	パラメータ
   *		$close_button
   *			閉じるボタンクリック
   *
   **********************************************************************/
  let ysIosSpinner = {
    init : function( opts ){
      // オプション
      if(opts === undefined) opts = {};

      // HTMLを作成
      let html = ysIosSpinner.makeHtml( opts );
      // エレメント化
      let elem = $(html);
      // 背景スクロールを禁止する
      elem.on('mousewheel', function(e){ e.preventDefault(); });
      elem.on('touchmove', function(e){ e.preventDefault(); });
      // イベント：閉じる
      if(typeof opts.close_button == "function") $('div.close', elem).click( opts.close_button() );
      // 要素を追加
      $('body').append( elem );
      // 戻り値
      return elem;
    },

    /*
     * HTMLを作成
     */
    makeHtml : function( opts ){
      let html = "";
      html += "<div class=\"ysrock_ios_spinner\">";
      if(typeof opts.close_button == "function") html += " <div class=\"close\"></div>";
      html += " <div class=\"wrap\">";
      for(let i=0; i<15; i++) html += "<div></div>";
      html += " </div>";
      html += "</div>";
      return html;
    },
  };
  $.fn.ysIosSpinner = function( method ){
    if( ysIosSpinner[method] ) return ysIosSpinner[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    else if( typeof method === 'object' || !method) return ysIosSpinner.init.apply( this, arguments );
    else $.error('Method' + method + ' does not exist on jQuery.ysIosSpinner');
  };
  /********** END END iOS風のスピナー ********************/



  /**********************************************************************
   *
   *　JSONに変換
   *
   *	使い方
   *		$.fn.ysToJSON( string|object $arg ):boolean [ JSON | false ]
   *
   *	パラメータ
   *		$arg
   *			文字列もしくはJSON
   *
   *	戻り値
   *		JSON｜false
   *
   *	備考
   *
   **********************************************************************/
  $.fn.ysToJSON = function( arg ){
    // 引数がobject
    if(typeof(arg) == "object"){
      try{
        // JSONを文字列に変換
        JSON.stringify( arg );
        // 成功した場合はそのまま返す
        return arg;
      }catch(e){
        console.log(e);
      }
      return false;
    };// END if 引数がobject

    // 引数がstring
    if(typeof(arg) == "string"){
      try{
        // 文字列をJSONに変換
        return JSON.parse( arg );
      }catch(e){
//        console.log(e);
      }
      return false;
    };// END if 引数がstring

    return false;
  };
  /********** END JSONに変換 ********************/



  /**********************************************************************
   *
   *　UUIDv4を生成
   *
   *	使い方
   *		$.fn.ysMkUUID():string
   *
   *	パラメータ
   *		なし
   *
   *	戻り値
   *		文字列
   *
   *	備考
   *
   **********************************************************************/
  $.fn.ysMkUUID = function(){
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c){
      let r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
      return v.toString(16);
    });
  };
  /********** END プラグイン ********************/



  /**********************************************************************
   *
   *　各イベントにUUIDを付加
   *
   *	使い方
   *		$.fn.setEventUUID()
   *
   *	パラメータ
   *		なし
   *
   *	戻り値
   *		なし
   *
   *	備考
   *		アンカーリンクとフォームにUUIDを付加する
   *
   **********************************************************************/
  $.fn.setEventUUID = function( UUID ){
    // アンカーリンク
    $(document).on('click', 'a', function(e){
      let href = $(this).attr('href');
      // URLからUUIDを取得
      let uuid = location.search.match(/[\?&]?uuid=([^\x26]+)\x26?/) ? RegExp.$1 : "";

      // 処理しない：UUIDが無い
      if(!uuid) return;
      // 処理しない：ハッシュタグのみ
      if(href.match(/^#/)) return;
      // 処理しない：既にUUIDがある
      if(href.match(/uuid=/)) return;
      // 処理しない：外部リンク
      if(href.match(/\/\//)) return;

      // UUIDを付加する
      $(this).attr('href', href + (href.match(/\?/) ? "&" : "?") + 'uuid=' + uuid);
    });// END アンカーリンク

    // フォーム
    $(document).on('submit', 'form', function(e){
      let action = $(this).attr('action');
      // URLからUUIDを取得
      let uuid = location.search.match(/[\?&]?uuid=([^\x26]+)\x26?/) ? RegExp.$1 : "";

      // 処理しない：UUIDが無い
      if(!uuid) return;
      // 処理しない：既にUUIDがある
      if(action.match(/uuid=/)) return;
      // 処理しない：外部リンク
      if(action.match(/\/\//)) return;

      // UUIDを付加する
      $(this).attr('action', action + (action.match(/\?/) ? "&" : "?") + 'uuid=' + uuid);
    });// END フォーム
  };
  /********** END 各イベントにUUIDを付加 ********************/



  /**********************************************************************
   *
   *　左からスワイプで浮遊要素を画面外に（その後削除）
   *
   *	使い方
   *		$( element $element ).swipeOut( ?array $opts )
   *
   *	パラメータ
   *		$element
   *			スワイプ対象
   *		$opts
   *			オプション配列
   *
   *	戻り値
   *		なし
   *
   *	備考
   *
   **********************************************************************
   *
   *	オプション配列
   *		$opts = array(
   *			?'startArea' = int $startArea = 5,
   *			?'percent' = int $percent = 50
   *		);
   *
   *	パラメータ
   *		$startArea
   *			開始領域（パーセント）
   *		$percent
   *			実行・キャンセルの境界線（パーセント）
   *
   **********************************************************************/
  let ysSwipeOut = {
    init : function( args ){
      // オプションを定義
      if(args === undefined) args = {};
      // 開始領域
      if(args.startArea === undefined) args.startArea = 5;
      // 境界線
      if(args.percent === undefined) args.percent = 50;

      // タッチ開始
      $(this).on('touchstart', ysSwipeOut['touchStart'](args));
      // 移動中
      $(this).on('touchmove', ysSwipeOut['touchMove'](args));
      // タッチ終了
      $(this).on('touchend', ysSwipeOut['funcEnd'](args));
      $(this).on('touchcancel', ysSwipeOut['funcEnd'](args));
    },

    /*
     * タッチ開始
     */
    'touchStart' : function(args){
      return(function(e){
        // Safariの戻る処理を無効化
        e.preventDefault();
        // 開始位置を初期化
        ysSwipeOut.x = undefined;
        // タッチ情報
        let obj = e.changedTouches[0];
        // 左端以外からのスタートは処理しない
        if( obj.clientX / $(this).width() * 100 > args.startArea ) return;
        // 開始位置を保存
        ysSwipeOut.x = obj.clientX;
        // トランジションを無効化
        $(this).addClass('ysrock_ios_no_transition');
      });
    },

    /*
     * 移動中
     */
    'touchMove' : function(args){
      return(function(e){
        // 開始していない場合は処理しない
        if(ysSwipeOut.x === undefined) return;
        // タッチ情報
        let obj = e.changedTouches[0];
        // 移動距離
        let diffX = obj.clientX - ysSwipeOut.x;
        // 移動させる
        $(this).css('left', diffX);
      });
    },

    /*
     * タッチ終了
     */
    'funcEnd' : function(args){
      return(function(e){
        // 開始していない場合は処理しない
        if(ysSwipeOut.x === undefined) return;
        // トランジションを有効化
        $(this).removeClass('ysrock_ios_no_transition');
        // タッチ情報
        let obj = e.changedTouches[0];
        // 移動距離
        let diffX = obj.clientX - ysSwipeOut.x;
        // 元に戻す
        if(obj.clientX / $(this).width() * 100 < args.percent) $(this).css('left', 0);
        // 画面外へ
        else{
          $(this).css('left', '100vw');
          // 要素を削除
          let removeElem = function(elem){ $(elem).remove(); };
          setTimeout(removeElem, 1000, this);
        };
      });
    },

  };
  $.fn.ysSwipeOut = function( method ){
    if( ysSwipeOut[method] ) return ysSwipeOut[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    else if( typeof method === 'object' || !method) return ysSwipeOut.init.apply( this, arguments );
    else $.error('Method' + method + ' does not exist on jQuery.ysSwipeOut');
  };
  /********** END 左からスワイプで浮遊要素を画面外に（その後削除） ********************/



//  /**********************************************************************
//   *
//   *　プラグイン
//   *
//   *	使い方
//   *		
//   *
//   *	パラメータ
//   *		
//   *
//   *	戻り値
//   *		
//   *
//   *	備考
//   *
//   **********************************************************************/
//  let ysPlugin = {
//    init : function( opts ){
//      // オプション
//      if(opts === undefined) opts = {};
//    },
//  };
//  $.fn.ysPlugin = function( method ){
//    if( ysPlugin[method] ) return ysPlugin[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
//    else if( typeof method === 'object' || !method) return ysPlugin.init.apply( this, arguments );
//    else $.error('Method' + method + ' does not exist on jQuery.ysPlugin');
//  };
//  /********** END プラグイン ********************/
})(jQuery);