API Docs for: 1.0.0
Show:

File: nablarch-widget-event-toggle\ui_public\js\nablarch\ui\event\TogglePropertyAction.js

define(['jquery', './Listener', 'nablarch/ui/readonly', 'sugar'],
function($, Listener, readony) { 'use strict';
  /**
   * プロパティ切替アクション
   * =============================================
   * 初期ロード時と発生したイベントに応じて、対象要素のプロパティの切り替えを行うアクション。
   * 切り替え可能なタグはinput:checkbox,:radio,select
   * 切り替える値はbooleanをサポートする。
   *
   * マークアップ仕様
   * -------------------------------------------
   * 本機能を使用する場合以下のマーカCSSを使用する。
   *
   * 1. イベントを管理するための指定
   *
   *   機能のプロパティを定義する要素に
   *   マーカCSSとして `nablarch_event_Action -type ToggleProperty` を指定する。
   *
   * 2. イベント発生時にプロパティを切り替える要素の制御
   *
   *   監視対象のイベントが発生した場合、
   *   切り替える対象、切り替える条件を指定する。
   *
   * 以下は、このウィジェットのオプションの一覧である。
   *
   * **-toggleType (String):**
   *   booleanによって切り替えられるプロパティ名、または `readonly`
   *
   * **-condition (セレクタ方式):**
   *   監視対象の要素がセレクタに一致した場合に、プロパティの切り替えを行う。
   *
   * **-toggleTarget (セレクタ方式):**
   *   監視対象の要素が条件(condition)に一致した場合、プロパティを切り替える対象の要素のセレクタ。
   *   イベントを定義したコンテキスト内から対象を検索する。
   *
   * **-reverse (boolean):**
   *   プロパティの切り替えを逆転させる。
   *
   * **実装例 (HTML)**
   *
   * 以下は、監視対象の要素が「value=1」のとき「name属性がform.ではじまる要素」を「活性化」する場合のマークアップ。
   *
   * <div style="display:none;"
   *      class="nablarch_event_Action
   *        -type         ToggleProperty
   *        -toggleType   disabled
   *        -toggleTarget [name^="form."]
   *        -condition    [value="1"]
   *        -reverse      true
   *      ">
   * </div>
   *
   * @class nablarch.ui.event.ToggleAction
   *
   * @author tani takanori
   * @since  1.4
   *
   */
  TogglePropertyAction.prototype = {
    /**
     * コンストラクタ。
     * @constructor
     */
    constructor    : TogglePropertyAction
    /**
     * 処理判定を行う。
     * 監視対象がこの条件に一致する場合、プロパティの設定を行う。
     *
     * @property condition
     * @type String
     */
  , condition     : null
    /**
     * プロパティを切り替える対象を示すプロパティ。
     * @property toggleTarget
     * @type String
     */
  , toggleTarget  : null
    /**
     * どのプロパティを切り替えるかを示すプロパティ。
     * @property toggleTarget
     * @type String
     */
  , toggleType    : null
    /**
     * 監視対象のイベントが発火した際に呼び出されるメソッド。
     *
     * @method fire
     */
  , fire          : TogglePropertyAction_fire
    /**
     * 対象要素のプロパティを切り替える。
     *
     * @method toggle
     */
  , toggle        : TogglePropertyAction_toggle
    /**
     * 対象要素について、プロパティの設定をクリアする。
     * @method clear
     */
  , clear         : TogglePropertyAction_clear
    /**
     * イベント発火時に監視対象要素が条件に一致した場合に
     * プロパティの設定を行う。
     *
     * @method set
     */
  , set           : TogglePropertyAction_set
    /**
     * 初期イベント時にプロパティを切り替える。
     *
     * @method init
     */
  , init          : TogglePropertyAction_init
  };

  function TogglePropertyAction(opts) {
    this.constructor = TogglePropertyAction;
    Object.merge(this, opts);
    this.reverse = opts.reverse === 'true';
  }

  function TogglePropertyAction_fire(listener, event) {
    var $watchTarget = $(event.currentTarget);
    this.toggle($watchTarget, listener.$context);
    return this;
  }

  function TogglePropertyAction_toggle($watchTarget, $context) {
    var $target = $context.find(this.toggleTarget)
     ,  match   = conditionOf($watchTarget);

    if (needsClear($watchTarget, this.condition)) {
      this.clear($target);
    }
    if (match($watchTarget, this.condition)) {
      this.set($target);
    }
  };

  function conditionOf($watchTarget) {
    return $watchTarget.is('select')      ? conditionOfSelect
         : $watchTarget.is('input:radio') ? conditionOfRadio
                                          : conditionOfCheckbox;
  }

  function conditionOfSelect($node, condition) {
    return $node.find(condition).is(':selected');
  }

  function conditionOfRadio($node, condition) {
    return $node.filter(condition).is(':checked');
  }

  function conditionOfCheckbox($node, condition) {
    var checkbox = $node.filter(condition);
    return checkbox.length === 0 ? false
                                 : checkbox.is(':checked');
  }

  function needsClear($node, condition) {
    return $node.is(':not(:checkbox)') || $node.filter(condition).length > 0;
  }

  function TogglePropertyAction_clear($target) {
    setPropertyOf(this.toggleType, $target, this.reverse);
  }

  function TogglePropertyAction_set($target) {
    setPropertyOf(this.toggleType, $target, !this.reverse);
  }

  function setPropertyOf(type, $target, value) {
     return type === "readonly" ? setReadonly($target, value)
                                : setDisabled($target, value);
  }

  function setReadonly($target, readonly) {
    $target.readonly(readonly);
  }

  function setDisabled($target, disabled) {
    var type = "disabled";
    disabled ? $target.attr(type, type).closest('div.field').addClass(type)
             : $target.removeAttr(type).closest('div.field').removeClass(type);
  }

  function TogglePropertyAction_init(listener, $watchTarget) {
    var $context = listener.$context
      , event = listener.event.split('|')[0].split(/\s/)
      , node = event.length === 3 ? event[1] : event[0];
    this.toggle($(node, $context), $context);
  }

  Listener.register('ToggleProperty', TogglePropertyAction);
  return TogglePropertyAction;
});