JavascriptのDom操作用ライブラリを実装してみた

毎度同じようなDom操作をするのが面倒になったのでHelper的なライブラリを実装してみた。
インスタンスとして宣言しておくことで よく使うDOM操作を大体扱うことが出来る。

var App = {};
    App.Helper={};

/**-------------------------------------------------------------------------------------*
 * App.Helper.DomHelper
 **-------------------------------------------------------------------------------------*/
App.Helper.DomHelper = {
    convertToArray : function(node_list){
      return Array.prototype.slice.call(node_list);
    }
};
App.Helper.DateHelper = {
    /**
     * 日付データを指定フォーマット文字列に変換
     * @format : Y,M,D,H,M,S    ※SAMPLE => y/m/d h:i:s
     * @dt    : Dateオブジェクト Nullの場合は当日
     */
    convertDate : function(format, dt){
      var date = dt === undefined ? new Date() : new Date(dt),
            convert = "",
            param = {};

            param.year = date.getFullYear();
      param.month = date.getMonth()+1;
      param.date = date.getDate();
      param.hour = date.getHours();
      param.minute = date.getMinutes();
      param.second = date.getSeconds();

      //1桁なら0付与
      var private_format = function(value){
        return ('0' + value).slice(-2);
      };

      convert = format.replace(/y/g,param.year)
                   .replace(/m/g,private_format(param.month))
                   .replace(/d/g,private_format(param.date))
                   .replace(/h/g,private_format(param.hour))
                   .replace(/i/g,private_format(param.minute))
                   .replace(/s/g,private_format(param.second));
      return convert;
    },
};

/**-------------------------------------------------------------------------------------*
 * FormElementModule
 **-------------------------------------------------------------------------------------*/
App.Helper.FormElementModule  = function(){}
/**
 * インスタンスの持つバリデーションをリアルタイムチェックする
 * @element   : 対象の要素
 * @error_id  :  エラーメッセージ出力フィールド
 */
App.Helper.FormElementModule.prototype.validate = function(){
  var own = this;

  this.element.addEventListener('input',function(event){
    //setCustomValidityはデフォルト意外の場合 強制的にバリデーションエラーを引き起こす
    own.element.setCustomValidity("");
    //エラーメッセージ表示
    if(own.element.checkValidity() === false) own.element.setCustomValidity(own.element.getAttribute("data-custom-message") || "");
    own.error.innerHTML = own.element.checkValidity() === false ?  own.element.validationMessage : "";
  },false);
};

/**
 * 入力値を取得
 * @return 入力された値 未入力の場合はNullを返す
 */
App.Helper.FormElementModule.prototype.getValue = function(){
  return this.element.value || null; //undifind対策
};

/**
 * 入力値をセット
 * @value : 入力値
 */
App.Helper.FormElementModule.prototype.setValue = function(value){
  this.element.value = value;
};

/**
 * 自身のelement要素に対してイベントを定義
 */
App.Helper.FormElementModule.prototype.addEventListener = function(event,callback){

  //イベントリスナを登録し、イベントオブジェクトをコールバック関数に返す
  this.element.addEventListener(event,function(e){
    callback.bind(callback(e));
  });

}

/**-------------------------------------------------------------------------------------*
 * TextBoxClass
 **-------------------------------------------------------------------------------------*/
/**
 * コンストラクタ
 * @element_id : インスタンス化する要素のID
 * @error_id   :  エラーメッセージ出力フィールド
 */
App.Helper.TextBoxClass = function(element_id,error_id){
  this.element = document.getElementById(element_id);
  this.error =document.getElementById(error_id);
  this.validate();
}
//共通モジュールを継承
App.Helper.TextBoxClass.prototype = new App.Helper.FormElementModule();

/**-------------------------------------------------------------------------------------*
 * TextAreaClass
 **-------------------------------------------------------------------------------------*/
/**
 * コンストラクタ
 * @element_id : インスタンス化する要素のID
 * @error_id   :  エラーメッセージ出力フィールド
 */
App.Helper.TextAreaClass = function(element_id,error_id){
  this.element = document.getElementById(element_id);
  this.error = document.getElementById(error_id);
  this.validate();
}
//共通モジュールを継承
App.Helper.TextAreaClass.prototype = new App.Helper.FormElementModule();

/**
 * <br>タグを\nに変換後、文字列をセットする。
 * @text : 入力文字列
 * @override : FormElementModule::getValue()
 */
App.Helper.TextAreaClass.prototype.setValue = function(text){
  this.element.value = text.replace(/<br>/g,"\n");
};

/**-------------------------------------------------------------------------------------*
 * SelectBoxClass
 **-------------------------------------------------------------------------------------*/
/**
 * コンストラクタ
 * @element_id : インスタンス化する要素のID
 * @error_id   :  エラーメッセージ出力フィールド
 */
App.Helper.SelectBoxClass = function(element_id,error_id,resource){
  this.element = document.getElementById(element_id);
  this.error = document.getElementById(error_id);
  this.resource = resource;
  this.validate();

  /**
   * Option要素を追加
   */
  this.addOption = function(options){
    var own = this;

    Object.keys(options).forEach(function(key){
      var option = document.createElement('option');
            option.setAttribute('value', options[key]);
            option.innerHTML = key;

            own.element.appendChild(option);

            own.resource[key] = options[key]
    });
  };
  this.addOption(this.resource);
}

//共通モジュールを継承
App.Helper.SelectBoxClass.prototype = new App.Helper.FormElementModule();

/**
 * 表示するデータをセット
 * @options(Object{key : value})
 *                 key   => 表示する文字列
 *                 value => 選択値
 * @override : FormElementModule::getValue()
 */
App.Helper.SelectBoxClass.prototype.setValue = function(options){
  //要素全削除 ⇒ 追加で初期化(リソースも更新)
  this.clear();
  this.addOption(options);
  this.resource = options;
};

/**
 * 表示するデータを追加
 * @options(Object{key : value})
 *                 key   => 表示する文字列
 *                 value => 選択値
 * @override : FormElementModule::getValue()
 */
App.Helper.SelectBoxClass.prototype.addValue = function(options){
  var own = this,
       unique = {};

  //重複するOption要素は追加しない
  Object.keys(options).forEach(function(key){
    if (own.resource.hasOwnProperty(key) === false) unique[key] = options[key]
  });
  this.addOption(unique);
};

/**
 * 指定したvalue値のoptionを選択
 * @option : 選択状態にするoption要素の値
 */
App.Helper.SelectBoxClass.prototype.select = function(value){
  App.Helper.DomHelper.convertToArray(this.element.getElementsByTagName('option')).forEach(function(option){
    if (option.value == value ) option.selected = true;
  });
};

/**
 * 指定したvalue値のoptionを削除
 * @option : 削除対象のoption要素の値
 */
App.Helper.SelectBoxClass.prototype.remove = function(value){
  var own = this;
  App.Helper.DomHelper.convertToArray(this.element.getElementsByTagName('option')).forEach(function(option){
    if (option.value == value ) own.element.removeChild(option)
  });
}

/**
 * optionを全削除
 * @option : 削除対象のoption要素の値
 */
App.Helper.SelectBoxClass.prototype.clear = function(){
  var own = this;
  App.Helper.DomHelper.convertToArray(this.element.getElementsByTagName('option')).forEach(function(option){
    own.element.removeChild(option);
  });
};

/**
 * 指定したvalue値以外のoptionを非表示
 * @option : 選択状態にするoption要素の値
 */
App.Helper.SelectBoxClass.prototype.filter = function(value){
  this.setValue(this.resource)
  var own = this;
  if(value == null) return ;
  App.Helper.DomHelper.convertToArray(this.element.getElementsByTagName('option')).forEach(function(option){
    if (option.value != value ) own.element.removeChild(option)
  });
}


/**-------------------------------------------------------------------------------------*
 * DatetBoxClass
 **-------------------------------------------------------------------------------------*/
/**
 * コンストラクタ
 * @element_id : インスタンス化する要素のID
 * @error_id   :  エラーメッセージ出力フィールド
 */
App.Helper.DateBoxClass = function(element_id,error_id){
  this.element = document.getElementById(element_id);
  this.error = document.getElementById(error_id);
  this.validate();
};
//共通モジュールを継承
App.Helper.DateBoxClass.prototype = new App.Helper.FormElementModule();

/**
 * 指定日付で文字列をセット
 * @date : 指定日付
 * @override : FormElementModule::setValue()
 */
App.Helper.DateBoxClass.prototype.setValue = function(date){
  //HTML5 Dateフォームはyyy-MM-dd形式のみ対応
  this.element.value = App.Helper.DateHelper.convertDate("y-m-d",date);
};

/**
 * 指定フォーマットで入力値を取得
 * @format : 指定フォーマット  y/m/d h:i:s
 * @override : FormElementModule::getValue()
 */
App.Helper.DateBoxClass.prototype.getValue = function(format){
  return App.Helper.DateHelper.convertDate(format,this.element.value);
};

/**-------------------------------------------------------------------------------------*
 * CheckBoxClass
 **-------------------------------------------------------------------------------------*/
/**
 * コンストラクタ
 * @element_name : インスタンス化する要素のname属性
 * @error_id   :  エラーメッセージ出力フィールド
 */
App.Helper.CheckBoxClass = function(element_name,error_id){
  this.elements = App.Helper.DomHelper.convertToArray(document.getElementsByName(element_name));
  this.error = document.getElementById(error_id);
  delete this.setValue;
  delete this.getValue;

  /**
   * validateメソッドを強制実行
   * @override : FormElementModule::validate()
   */
  var own = this,
        error_messages = [],
        //チェックボックスがバリデーション違反かをチェック
        checkbox_errorCheck = function(checkbox){
       checkbox.setCustomValidity('');
       if(checkbox.checkValidity() === false)  checkbox.setCustomValidity(checkbox.getAttribute("data-custom-message" || ''));
       return checkbox.checkValidity() === false ? checkbox.validationMessage : null;
        };

  this.elements.forEach(function(element){
    element.addEventListener('change',function(event){
      //グループとして指定された全チェックボックス要素を検査しエラーメッセージを表示
      own.elements.forEach(function(checkbox){
        if(checkbox_errorCheck(checkbox) !== null)  error_messages.push(checkbox_errorCheck(checkbox));
      });
      //バリデーション違反を起した要素のメッセージを表示
      own.error.innerHTML = error_messages.length > 0 ?  error_messages[0] : "";
      error_messages = [];
    });
  });
};
App.Helper.CheckBoxClass.prototype = new App.Helper.FormElementModule();

/**
 * チェックされているチェックボックスを取得
 */
App.Helper.CheckBoxClass.prototype.checked = function(){
  return this.elements.filter(function(element){
    if (element.checked) return element;
  });
};
/**
 * チェックボックスを切り替える
 * @flag : true => ON, false => OFF
 */
App.Helper.CheckBoxClass.prototype.change = function(flag){
  this.elements.forEach(function(element){
    element.checked = flag;
  });
};

/**
 * 指定したvalue値を持つチェックボックスを選択
 * @target : 指定するvalue値
 */
App.Helper.CheckBoxClass.prototype.doCheck= function(target){
  this.elements.forEach(function(element){
    if (element.value === target) element.checked = true;
  });
};

/**-------------------------------------------------------------------------------------*
 * RadioBoxClass
 **-------------------------------------------------------------------------------------*/
/**
 * コンストラクタ
 * @element_id : インスタンス化する要素のname属性
 * @error_id   :  エラーメッセージ出力フィールド
 */
App.Helper.RadioButtonClass = function(element_name,error_id){
  this.elements = App.Helper.DomHelper.convertToArray(document.getElementsByName(element_name));
  this.error = document.getElementById(error_id);
  delete this.setValue;
  delete this.getValue;
  delete this.validate;
};
App.Helper.RadioButtonClass.prototype = new App.Helper.FormElementModule();

/**
 * チェックされているチェックボックスを取得
 */
App.Helper.RadioButtonClass.prototype.checked = function(){
  return this.elements.filter(function(element){
    if (element.checked) return element;
  });
};

/**
 * 指定したvalue値を持つチェックボックスを選択
 * @target : 指定するvalue値
 */
App.Helper.RadioButtonClass.prototype.doCheck= function(target){
  this.elements.forEach(function(element){
    if (element.value === target) element.checked = true;
  });
};