DataTable Control: Showing, Hiding, and Reordering Columns(その2)

先の「DataTable Control: Showing, Hiding, and Reordering Columns(その1)」では、列のDrag and Dropだけに着目したが、ここでは、YUIのExampleそのものについて説明する。

YUIに示されている例では、Table Optionという(擬似)リンクをクリックすると、以下のような「列の表示・非表示」を選択させる画面が表示される。
大きなテーブルを表示する際に、横に広がりすぎて見づらくなってしまう場合がよくあるが、そういった場合には、このような実装が極めて効果的だと思う。

このモーダルな画面は、「closeボタンだけのSimpleDialog」で出来ていて、そこに列の分だけの「表示・非表示のボタン」が配置されている。

この「表示・非表示のボタン」はよくできている。
以下は、1列目を非表示にして、2列目と3列目をDrag and Dropで移動させた後に表示させたものだが、列の変更にあわせて、ボタンの配列が変更されている。
これは、列の「並び順変更のイベント」で、ボタンを再配置するハンドラを仕込むことで実装されている。

以下に、HTMLの全文を示す。
凝った画面だけに、些か煩雑なコードになっているが、出来る限り注釈を加えた。
また、今回も、YUIのLoaderは利用していない。

<!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>Ajax Sample</title> 
 
<style type="text/css"> 
body {
	margin:0;
	padding:0;
}
</style> 

<!-- Individual YUI CSS files -->
<link rel="stylesheet" type="text/css" href="scripts/yui/fonts/fonts-min.css">
<link rel="stylesheet" type="text/css" href="scripts/yui/assets/skins/sam/skin.css">
<!-- Individual YUI JS files -->
<script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="scripts/yui/element/element-beta-min.js"></script>
<script type="text/javascript" src="scripts/yui/button/button-min.js"></script>
<script type="text/javascript" src="scripts/yui/dragdrop/dragdrop-min.js"></script>
<script type="text/javascript" src="scripts/yui/container/container-min.js"></script>
<script type="text/javascript" src="scripts/yui/datasource/datasource-min.js"></script>
<script type="text/javascript" src="scripts/yui/datatable/datatable-min.js"></script>

<style type="text/css" id="defaultstyle">
#main {
	margin: 2px;
	padding: 3px;
}
/* custom styles for this example */
#dt-example {
	width:45em;
/*	margin:0 auto;*/
}
#dt-options {
	text-align:right;
	margin:1em 0;
}

/* dlgがついてる奴はみんなdialog用 */
#dt-dlg {
	visibility:hidden;
	border:1px solid #808080;
	background-color:#E3E3E3;
}
#dt-dlg .hd {
	font-weight:bold;
	padding:1em;
	background:none;
	background-color:#E3E3E3;
	border-bottom:0;
}
#dt-dlg .ft {
	text-align:right;
	padding:.5em;
	background-color:#E3E3E3;
}
#dt-dlg .bd {
	height:10em;
	margin:0 1em;
	overflow:auto;
	border:1px solid black;
	background-color:white;
}
#dt-dlg .dt-dlg-pickercol {
	clear:both;
	padding:.5em 1em 3em;
	border-bottom:1px solid gray;
}
#dt-dlg .dt-dlg-pickerkey {
	float:left;
}
#dt-dlg .dt-dlg-pickerbtns {
	float:right;
}

/* Container workarounds for Mac Gecko scrollbar issues */
.yui-panel-container.hide-scrollbars #dt-dlg .bd {
    /* Hide scrollbars by default for Gecko on OS X */
    overflow: hidden;
}
.yui-panel-container.show-scrollbars #dt-dlg .bd {
    /* Show scrollbars for Gecko on OS X when the Panel is visible  */
    overflow: auto;
}
#dt-dlg_c .underlay {overflow:hidden;}


/* rounded corners */
#dt-dlg .corner_tr {
    background-image: url(scripts/yui/datatable/assets/img/tr.gif);
    position: absolute;
    background-repeat: no-repeat;
    top: -1px;
    right: -1px;
    height: 4px;
    width: 4px;
}
#dt-dlg .corner_tl {
    background-image: url(scripts/yui/datatable/assets/img/tl.gif);
    background-repeat: no-repeat;
    position: absolute;
    top: -1px;
    left: -1px;
    height: 4px;
    width: 4px;
}
#dt-dlg .corner_br {
    background-image: url(scripts/yui/datatable/assets/img/br.gif);
    position: absolute;
    background-repeat: no-repeat;
    bottom: -1px;
    right: -1px;
    height: 4px;
    width: 4px;
}
#dt-dlg .corner_bl {
    background-image: url(scripts/yui/datatable/assets/img/bl.gif);
    background-repeat: no-repeat;
    position: absolute;
    bottom: -1px;
    left: -1px;
    height: 4px;
    width: 4px;
}

.inprogress {position:absolute;} /* transitional progressive enhancement state */

.yui-dt-liner {white-space:nowrap;}

</style>

<script type="text/javascript" src="scripts/yui/datatable/assets/js/data.js"></script> 
<script type="text/javascript"> 
YAHOO.util.Event.addListener(window, "load", function() {
	
	YAHOO.example.ColumnShowHide = function() {
		var Dom=YAHOO.util.Dom;
		
		// 列定義
        var myColumnDefs = [
                {key:"address"},
                {key:"city"},
                {key:"state"},
                {key:"amount"},
                {key:"active"},
                {key:"colors"},
                {key:"last_login", formatter:YAHOO.widget.DataTable.formatDate}
        ];

        // データソースの作成
        var myDataSource = new YAHOO.util.DataSource(YAHOO.example.Data.addresses);
        myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
        myDataSource.responseSchema = {
            fields: ["address","city","state","amount","active","colors",{key:"last_login",parser:"date"}]
        };
 
        // Create DataTable
        var myDataTable = 
            new YAHOO.widget.DataTable("columnshowhide", 
                    myColumnDefs, 
                    myDataSource, 
                    // カラムのDrag and Dropを可能にする。
                    {draggableColumns:true});

        // 以下はDialog Boxの処理 ===========================================================

        	// 初めての処理かを判断するフラグ
            var newCols = true;

            // (※1)のイベントハンドラー
            var showDlg = function(e) {
                YAHOO.util.Event.stopEvent(e);

                if(newCols) {
                    // Populate Dialog
                    // Using a template to create elements for the SimpleDialog
                    // 列名を全て取得
                    var allColumns = myDataTable.getColumnSet().keys;
                    
                    // 選択画面の中身(ボタンの集まり)は、markupを元にSimpleDialogの中に作成する。
                    var elPicker = YAHOO.util.Dom.get("dt-dlg-picker");
                    
					// 列用のテンプレート(elTemplateCol)の作成
                    var elTemplateCol = document.createElement("div");
                    Dom.addClass(elTemplateCol, "dt-dlg-pickercol");

                    // 上で作成した、列用のテンプレート(elTemplateCol)にpickerのkey(列名)を追加
                    var elTemplateKey = elTemplateCol.appendChild(document.createElement("span"));
                    Dom.addClass(elTemplateKey, "dt-dlg-pickerkey");

                    // 上で作成した、列用のテンプレート(elTemplateCol)にpickerのボタンを追加
                    var elTemplateBtns = elTemplateCol.appendChild(document.createElement("span"));
                    Dom.addClass(elTemplateBtns, "dt-dlg-pickerbtns");

                    // (※2)ボタンに仕込むハンドラ
                    var onclickObj = {
                            fn:handleButtonClick, 
                            obj:this, 
                            scope:false };
                    
                    // 全ての列に対して、ボタングループを作成して、elpickerに追加していく。
                    var elColumn, elKey, elButton, oButtonGrp;
                    for(var i=0,l=allColumns.length;i<l;i++) {
                        var oColumn = allColumns[i];
                        
                        // 列用のテンプレート(elTemplateCol)のクローンを作成する。
                        elColumn = elTemplateCol.cloneNode(true);
                        
                        // 列名をセット
                        elKey = elColumn.firstChild;
                        elKey.innerHTML = oColumn.getKey();
                        
                        // ボタングループを作成して、次のコンテナ(次の列用のコンテナ)に入れる。
                        oButtonGrp = new YAHOO.widget.ButtonGroup({ 
                                        id: "buttongrp"+i, 
                                        name: oColumn.getKey(), 
                                        container: elKey.nextSibling
                        });
                        // ボタングループにshowとhideを追加する。(toggle化させる)
                        oButtonGrp.addButtons([
                            { label: "Show", value: "Show", checked: ((!oColumn.hidden)), onclick: onclickObj},
                            { label: "Hide", value: "Hide", checked: ((oColumn.hidden)), onclick: onclickObj}
                        ]);
                                        
                        elPicker.appendChild(elColumn);
                    }
                    // フラグをオフ
                    newCols = false;
            	}
            	// SimpleDialog(大枠)を表示する。
                myDlg.show();
            };
            
			// SimpleDialogのHideのハンドラ。
            var hideDlg = function(e) {
                this.hide();
            };
            
         	// (※2)で使用するハンドラ
            var handleButtonClick = function(e, oSelf) {
                var sKey = this.get("name");
                if(this.get("value") === "Hide") {
                    // Hides a Column
                    myDataTable.hideColumn(sKey);
                }
                else {
                    // Shows a Column
                    myDataTable.showColumn(sKey);
                }
            };
            
            // 選択画面の大枠は、markupを元にcloseボタンだけのSimpleDialog。
            YAHOO.util.Dom.removeClass("dt-dlg", "inprogress");
            var myDlg = new YAHOO.widget.SimpleDialog("dt-dlg", {
                    width: "30em",
    			    visible: false,
    			    modal: true,
    			    buttons: [ 
    					{ text:"Close",  handler:hideDlg }
                    ],
                    fixedcenter: true,
                    constrainToViewport: true
    		});
    		myDlg.render();

            // 列の並べ替えが起こったら、ボタングループを消去してしまう(ボタンの並び順を変える為)。
            myDataTable.subscribe("columnReorderEvent", 
                function(){
                	newCols = true;
                	YAHOO.util.Event.purgeElement("dt-dlg-picker", true);
                	YAHOO.util.Dom.get("dt-dlg-picker").innerHTML = "";
            	}, 
            	this, 
            	true);
    		
    		// Table OptionのクリックイベントにshowDialogを引っ掛ける。(※1)
    		YAHOO.util.Event.addListener("dt-options-link", 
    	    		"click", 
    	    		showDlg, 
    	    		this, 
    	    		true);
        
               
        return {
            oDS: myDataSource,
            oDT: myDataTable
       };
    }();
});
</script>
</head> 
 
<body class=" yui-skin-sam">
<div id="main">
<p>Drag and Dropで列を並べ替えることができます。<br/>
また、Table Optionsより列の表示・非表示が選択できます。</p>
<div id="dt-example">
    <div id="dt-options"><a id="dt-options-link" href="fallbacklink.html">Table Options</a></div>
	<!-- テーブルの表示エリア -->
    <div id="columnshowhide"></div>
</div>

<div id="dt-dlg" class="inprogress">
    <span class="corner_tr"></span>
    <span class="corner_tl"></span>
    <span class="corner_br"></span>
    <span class="corner_bl"></span>
    <div class="hd">
        	どの列を表示しますか?:
    </div>

    <div id="dt-dlg-picker" class="bd">
    </div>
</div>

</div>
</body> 
</html>