YUI2.7.0のEditable Table(編集可能な表)でのバリデーション(その3:相関チェックをする)

先のログで、DataTableのセルエディタ(Cell Editor)についてバリデータを自作してみた。ここで一点気になるのが、表の同一行内の値との「相関チェック」をどうするか?ということ。先のログのバリデーションでは、「そのセルの値」のみがチェックの対象。これでは不十分だ。
ということで、相関チェックを実装してみた。

戦略は以下。

  • (セルエディタを開くための)ダブルクリックに先んじて、クリックイベントで選択された行の(表内に保管されている)データを保管する。
  • セルエディタのバリデーション内で、保管した「行データ」を相関チェックを行う。

したがって、セルエディタのバリデーションロジックの中には、

  1. そのセルの入力値の(簡単な)妥当性検証
  2. そのセルの入力値と、同一行内にあるデータとの相関チェック

が入る(必要であれば、サーバーサイドでの非同期でのチェックも入る)。

前者には、以前に作成したMyValidatorが使えるので、それを使うことにしよう。

まず、これまでのサンプルを変更して、以下のように編集可能な列を2つにする。これらに以下のような制約をつけてみる。

  1. 2列ともに、数値(int,float)のみ入力
  2. メモ2の入力値 > メモ1の入力値


純化のため、メモ1の入力値には、defaultValue:0と、validator:YAHOO.widget.DataTable.validateNumberを設定し、メモ2の入力値のバリデーションを自作した。以下の2つは、メモ2に「数値以外」を入力したときのスナップショットである。
「ああああ」を入力すると、

以下のようにバリデーションがかかって、セルエディタが再度の入力を要求する。


以下のスナップショットは、メモ1の値(10)に対して、メモ2に"5"を入力した際のスナップショットである。同様にバリデーションがかかって、セルエディタが再度の入力を促す。


以下にHTMLの全文を示す。validateNotes2()が、メモ2の相関チェックをしている関数である。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
    <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
<title>DataTable Validate</title> 
 
<style type="text/css"> 
</style> 

<link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/fonts/fonts-min.css" /> 
<link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/paginator/assets/skins/sam/paginator.css" /> 
<link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/datatable/assets/skins/sam/datatable.css" /> 
<script type="text/javascript" src="../scripts/lib/yui/build/yahoo-dom-event/yahoo-dom-event.js"></script> 
<script type="text/javascript" src="../scripts/lib/yui/build/animation/animation.js"></script> 
<script type="text/javascript" src="../scripts/lib/yui/build/element/element.js"></script> 
<script type="text/javascript" src="../scripts/lib/yui/build/paginator/paginator-min.js"></script> 
<script type="text/javascript" src="../scripts/lib/yui/build/datasource/datasource-min.js"></script> 
<script type="text/javascript" src="../scripts/lib/yui/build/datatable/datatable-min.js"></script> 
<!--// MyValidatorの読み込み  -->
<script type="text/javascript" src="../scripts/myznala.js">
</script> 

<style type="text/css" id="defaultstyle">
#main {
	margin: 2px;
	padding: 3px;
}

.ez_error {
	/* red(エラー用) */
	color:#ff0000;
}

</style>

<script type="text/javascript" src="data.js"></script> 
<script type="text/javascript">

EzTable = function() {

	var myDataSource;
	var myDataTable;

	var Dom = YAHOO.util.Dom;

	// MyValidatorオブジェクト
	var valObj;

	// 選択された行を保管
	var wData;

	/* 
	* メモ2のバリデーション
	*/
	var validateNotes2 = function(oData){

		// エラーメッセージのクリア
		clearErrorMsg();
		
		// MyValidatorをつかって数値チェックをする。
		var _ret = valObj.validate('ja','isNum',oData);
		if(_ret['isNum']!=null &&_ret['isNum'].length > 0){
			Dom.get('ez_error_res').innerHTML = _ret['isNum'];
                        return undefined;
		}

		/*
		* 以下、相関チェック
		*/
		// 数値化
		var _numData = 1 * oData;
		if("notes1" in wData){
			var _savData = 1 * wData["notes1"];
		}else{
			var _savData = 0;
		}
		
		// 相関チェック
		if(_savData >= _numData){
		    // エラーの場合、undefindを返せばいい。
		    Dom.get('ez_error_res').innerHTML = 'メモ2>メモ1でなければなりません。';
                    return undefined;
		}
		return oData;
	};

	/* 
	* クリックイベントで行データを退避する
	*/
	var onRowClick = function(oArgs){
		// 選ばれた行のデータ
		var _rowData = this._oAnchorRecord._oData;
		
                // 以下の方法でRowのデータが取り出せる。
		wData = Array();
		for(var i in _rowData){
			wData[i]=_rowData[i];
		}
		return;
		
	};

	/* 
	* ダブルクリックイベントでエラーメッセージを消す
	*/
	var clearErrorMsg = function(){
		Dom.get('ez_error_res').innerHTML = '';
		return;
	};
	
    return {
		/**
		* 初期処理
		*/
	   	init: function() {

    		// DataTable用:列定義
        	var myColumnDefs = [
               	    {	key:"areacode",
                     	label:"コード",
                     	width:50,
                     	resizeable:true,
                     	sortable:true},
                    {	key:"state",
                        label:"都道府県",
                        width:150,
                        resizeable:true,
                        sortable:true},
                    {	key:"notes1",
                        label:"メモ1 (編集可:数値)",
                        editor:new YAHOO.widget.TextboxCellEditor(
               			{	
					validator:YAHOO.widget.DataTable.validateNumber,
					defaultValue:0
    	                	}
						),
                        resizeable:true,
                        sortable:true},
                   {	key:"notes2",
                        label:"メモ 2(編集可:数値)",
                        editor:new YAHOO.widget.TextboxCellEditor(
               			{	
					validator:validateNotes2,
					defaultValue:0
       	                	}
			),
                        resizeable:true,
                        sortable:true}
        	];

        	// DataTable用:コンフィグ属性
        	var myConfigs = {
                sortedBy:{key:"areacode",dir:"asc"},
                paginator: 
                    new YAHOO.widget.Paginator({
                    	rowsPerPage: 10,
                    	template: YAHOO.widget.Paginator.TEMPLATE_ROWS_PER_PAGE,
                    	rowsPerPageOptions: [10,25,50,100],
                    	pageLinks: 5
                	}),
               	caption:"都道府県"
        	};

        	// DataSourceのインスタンス化
	        myDataSource = new YAHOO.util.DataSource(Data.areacodes);
    	        myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
        	myDataSource.responseSchema = {
            	fields: ["areacode","state"]
        	};

	        // DataTableのインスタンス化
    	        myDataTable = new YAHOO.widget.DataTable("table1", myColumnDefs, myDataSource, myConfigs);

		/*
		* 行の選択補助。
		*/
		// クリックでハイライトするようにハンドラを設定
	        myDataTable.subscribe("rowClickEvent",
                myDataTable.onEventSelectRow);
                myDataTable.subscribe("rowMouseoverEvent", 
            		myDataTable.onEventHighlightRow);
                myDataTable.subscribe("rowMouseoutEvent", 
            		myDataTable.onEventUnhighlightRow);

		// クリック時にデータを退避する。
                myDataTable.subscribe("rowClickEvent",
            		onRowClick);

                /*
                * セルの処理
                */
            
		// ダブルクリックでエラーメッセージを消す。
        	myDataTable.subscribe("cellDblclickEvent",
                clearErrorMsg);
			// ダブルクリックでセルのエディターを呼ぶ。
        	myDataTable.subscribe("cellDblclickEvent",
                myDataTable.onEventShowCellEditor);

		/*
		* MyValidatorの初期化
		*/
		valObj 	= 	new MyValidator();
            
    	}, // initの終わり
        oDS: myDataSource,
        oDT: myDataTable
    };
}();

</script>
</head> 
 
<body class=" yui-skin-sam" onload="EzTable.init()">
test_datatable_validate4
<br>
<div id="main">
<p>いくつかのオプションを加えたサンプルです。<br/>
メモ1とメモ2はダブルクリックで変更できます。「メモ1<メモ2」という相関チェックを行います。</p>
<div id="ez_error_res" class="ez_error"></div>
<div id="table1"></div>
<div id="result"></div>
</div>
</body> 
</html>