YUI2.7.0のEditable Table(編集可能な表)で1クリックで行を削除する

YUI2.7.0のEditable Table(編集可能な表)について、バリデーションのコードを書いてきた。
バリデーションは、データの登録・更新に伴う処理。
今回は、

のような表を用意して、都道府県名の脇のマークをクリックしたら、行が削除される仕組みを作ってみる。このアイコンは、iconPodというありがたいサイトのものを使わせてもらった(Thank you so much)。サイトのトップに書かれているように、クレジットもバックリンクも不要、商用利用も可能でたくさんのアイコンが提供されている。

行の削除方法は、YUIOfficial Examplesに紹介されていて、以前のログで取り上げた(これ)。
ポイントは以下。

  • マークは、formatterとして都道府県名の脇に設定する。
  • 行のクリックイベントが発生したら、その発生源(YUIではEventのTargetといわれる模様)がこのイメージであるか特定する。
  • マークがクリックされていれば、行を削除する。

セルエディタ(Cell Editor)による更新と同様に、削除はYUI.widget.DataTableオブジェクト内で行われて永続化はされない。したがって、データベースやフラットファイルに永続化したい場合には、そのための実装が必要である。

また、行を削除するときに、確認用にコンファームすることがあるが、この例では行わない。以下が、HTMLの全文なので、これを見れば、コンファームの方法論は自明と思う。

<!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;
}

.actdel img {
	/* 都道府県に付ける「×(行削除)」イメージのスタイル */
	border:0;
	margin-bottom: -3px;
}


</style>

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

EzTable = function() {

	var myDataSource;
	var myDataTable;

	var Dom = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;

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

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

	// 削除された行と行数を保管
	var delRow;
	var delNum;

	/*
	*  都道府県に「×(行削除)」のマークを付ける
	*   (注)カラム定義より前のこと
	*/
        var ezInitFormatter = function(elCell, oRecord, oColumn, oData) { 
    	    elCell.innerHTML = oData + '&nbsp' + '&nbsp' +
    			'<a class="actdel" href="#">' 
    			+ '<img class="actdel" src="../images/action_delete.png">' + '</a>';
	};
	
	/* 
	* メモ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;

		// 行データを退避
		wData = Array();
		for(var i in _rowData){
			wData[i]=_rowData[i];
		}

		// 選ばれた行の取得
		var _rowIdx = this._oAnchorRecord._nCount;
		// 行を削除する関数
		// (注) 削除するとmyDataTable.deleteRow()のインデックスがずれるので補正する。
		var _corr = 0;
		for(var i=0; i<delRow.length; i++){
			if(delRow[i]<_rowIdx) _corr++;
		}
		var _wk = _rowIdx-_corr;
		if(onClickDelete(oArgs, _wk)){
		    // 削除した行の保管
		    delRow[delNum++] = _rowIdx;
                }		
		return;
	};

	/*
	*  クリック時に、選択された行を削除する
	*/
	var onClickDelete = function(oArgs, _rowIdx){

		// イベントの発生が画面のクリックか判定する。
		var _target = Event.getTarget(oArgs.event);
		var _targetClassName = getClassName(_target);
		var _idx = _targetClassName.indexOf('actdel',0)
		if(_idx != -1){
		    Event.preventDefault(oArgs.event);

		    // oArgsから行を取り出して削除する。
		    myDataTable.deleteRow(_rowIdx);
                    return true;
		}
                return false;
	};

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

	/*****************************************************
	* 汎用関数
	*****************************************************/
	/**
	*  クラス名の取得
	*/
	var getClassName = function(_obj){
		if(document.all){
			//for IE
			var _keys = _obj.getAttribute('className');
		}else{
			// for FF, Chrome, Safari
			var _keys = _obj.getAttribute('class');
		}
		return _keys;
	};
	
    return {
		/**
		* 初期処理
		*/
	   	init: function() {

    		// DataTable用:列定義
        	var myColumnDefs = [
                 	{	key:"areacode",
                     	label:"コード",
                     	width:50,
                     	resizeable:true,
                     	sortable:true},
                    {	key:"state",
                        label:"都道府県",
                        width:150,
                        formatter:ezInitFormatter, // 上で定義したフォーマッターを適用する
                        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();

		/*
		* 変数の初期化
		*/
		delRow = new Array();
		delNum = 0;
            
    	}, // initの終わり
        oDS: myDataSource,
        oDT: myDataTable
    };
}();

</script>
</head> 
 
<body class=" yui-skin-sam" onload="EzTable.init()">
test_datatable_validate5
<br>
<div id="main">
<p>いくつかのオプションを加えたサンプルです。<br/>
メモ1とメモ2はダブルクリックで変更できます。「メモ1<メモ2」という相関チェックを行います。<br>
都道府県名の右の<img src="../images/action_delete.png" style="margin-bottom:-3px;">をクリックすると、行を削除します。</p>
<div id="ez_error_res" class="ez_error"></div>
<div id="table1"></div>
<div id="result"></div>
</div>
</body> 
</html>