DataTable Control: Custom Cell Formatting
このExampleの目的は、
- カスタムのフォーマッターを作ってみること(タイトルの通り)。
- デフォルトのフォーマッターをoverrideしてみること(Javascriptの場合は、overrideというよりも、むしろ置換してしまう、という言い方の方が正しい)。
- 色々な入力項目(radioボタン、checkボックス、listボックス、ボタン)が押されたときの挙動と確認すること。
である。
1,2番目の項目については、その引数と使い方。
3番目については、入力項目の変更イベントをListenして、何か渡ってきて、それからどのように情報を引き出すか、ということが実践では必要になってくる。
また、この例に、(図らずも)YUI Loaderを初めて使うこととなった。
以下が、サンプリングした画面画面である。
外見上は、YUIのExampleから、日付のフォーマット(MM/DD/YYYYをYYYY/MM/DDに変更)と、通貨コード("$" Dollar Markを"¥" YEN Markに変更)を変更してある。
入力イベント(チェックボックスのチェックなど)が発生した際、イベントハンドラに渡ってくるもの(引数)のうち主要な役割を果たすのは、引数.targetで取得できるHTMLInputElementであって、これを起点として、変更レコードの取得などが可能となる。
また、レコードはRecordオブジェクトとして取得することができ、getData()メソッドによりDataSourceのfields属性として定義したcolumn要素が取得できる。また、setaData()メソッドにより、Recordオブジェクトの変更が可能である。
DataTableは、原則として、tableタグから生成されている場合と同じであるから、Styleの変更などは、先の例「DataTable Control: Progressive Enhancement」に習えばよい。
1コラム目は、bg-colorを、field3が100より大きければ青、以外であれば赤として、画像の入れ替えを行うというカスタムフォーマッターにより編集される。これも、tdの子要素であるテキストノード(これが、フォーマッターに渡ってくるElementとなる)と、tdタグ(Elementのparentとなる)のclass属性のコントロールで行うことができる。
以下に、Javascriptを含む、HTMLの全文をしめす。
ソースコード中、イベントハンドラーはある程度統一感を持たせるように変更を加えてある。
また、各入力要素に関して(イベントハンドラに渡ってくる引数が同じことを確認するため)のAlertが上がるようにしている。
最後にYUI Loaderであるが、これを用いた場合の「適切なコードスタイル」が思いつかなかったため、コードの形式はYUIのExampleの形式をそのまま採用した。
YUI Loaderは、機能をrequireすることで、必要なモジュール、CSS(の依存性を解決して)読み込んでくる「優れもの」であるが、実際の開発局面では、あまり使わないのではないかと思われる(YUIモジュールをそのまま無条件に使うという前提に縛られてしまうため)。
<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <TITLE>Ajax_Sampling</TITLE> <style type="text/css"> body { margin:0; padding:0; } </style> <style type="text/css" id="defaultstyle"> #main { margin: 2px; padding: 3px; /* width: 560px; height: auto; border:1px dashed #999999; */ } /* ※1 */ .yui-skin-sam .yui-dt tbody td.up { background-color: #efe; } .yui-skin-sam .yui-dt tbody td.down { background-color: #fee; } /* 実験 1: thead th の範囲*/ .yui-skin-sam .yui-dt thead th { font-weight: bold; } /* 実験 2: tbody tds の範囲*/ .yui-skin-sam .yui-dt tbody td { color: purple; } </style> <script type="text/javascript" src="scripts/yui/yuiloader/yuiloader.js"></script> <!-- データテーブルの読み込み --> <!-- field2では、new Date(2007, 1, 1)と指定 YAHOO.example.Data = { multitypes: { items: [ {field1: "bananas", field2:new Date(2007, 1, 1), field3:111, field4:"23.4", field5:"bob", field6:"http://www.yahoo.com"}, {field1: "cherries", field2:new Date(2006, 1, 1), field3:12.3, field4:"35.12", field5:"ann", field6:"http://www.yahoo.com"}, {field1: "apples", field2:new Date(2007, 11, 1), field3:1, field4:34.12, field5:"charlie", field6:"http://www.yahoo.com"}, {field1: "bananas", field2:new Date(2007, 1, 11), field3:1112, field4:"03", field5:"diane", field6:"http://www.yahoo.com"}, {field1: "cherries", field2:new Date(1999, 1, 11), field3:124, field4:03, field5:"edgar", field6:"http://www.yahoo.com"}, {field1: "bananas", field2:"January 10, 2005", field3:"12", field4:"34", field5:"francine", field6:"http://www.yahoo.com"}, {field1: "apples", field2:"January 1, 2005", field3:"19.1", field4:"234.5", field5:"george", field6:"http://www.yahoo.com"}, {field1: "bananas", field2:"1/11/05", field3:"10.02", field4:"345.654", field5:"hannah", field6:"http://www.yahoo.com"}, {field1: "cherries", field2:"1/11/2005", field3:"109", field4:23.456, field5:"igor", field6:"http://www.yahoo.com"}, {field1: "bananas", field2:"November 1, 2005", field3:"11111", field4:23.0123, field5:"julie", field6:"http://www.yahoo.com"} ] }, } --> <!-- データテーブル --> <script type="text/javascript" src="scripts/yui/datatable/assets/js/data.js"></script> <script type="text/javascript"> var loader = new YAHOO.util.YUILoader(); loader.insert({ // loaderで読み込みたいmoduleをしてい。fonts(css)、datatable(js)、json(js)を指定している。 require: ["fonts", "datatable", "json"], // debugレベルのモジュールも使用する。 filter: 'debug', // 読み込み元をローカルの特定ディレクトリに指定 base: 'scripts/yui/', // loadに成功したとき onSuccess: function() { YAHOO.example.CustomFormatting = function() { // Define a custom formatter for the Column labeled "flag" // draws an up icon and adds class "up" to the cell liner to affect // a green background color if value of field3 is greater than 100. // Otherwise renders a down icon and assigns class "down", setting // the background color to red. // カスタム・フォーマッターの作り方(引数) var myCustomFormatter = function(elCell, oRecord, oColumn, oData) { if(oRecord.getData("field3") > 100) { // elCell(Textノード)の親ノード(td)のclassをupにすることで、色を変える。 // 上※1参照; .yui-dt tbody td.up YAHOO.util.Dom.replaceClass(elCell.parentNode, "down", "up"); elCell.innerHTML = ' <img src="scripts/yui/datatable/assets/skins/sam/dt-arrow-up.png">'; } else { YAHOO.util.Dom.replaceClass(elCell.parentNode, "up","down"); elCell.innerHTML = ' <img src="scripts/yui/datatable/assets/skins/sam/dt-arrow-dn.png">'; } }; // Add the custom formatter to the shortcuts // 「YAHOO.widget.DataTable.Formatter.」までが、YAHOOで規定されている、フォーマッターの名前空間 // これにmtCustomを追加する。 YAHOO.widget.DataTable.Formatter.myCustom = myCustomFormatter; // Override the built-in formatter // フォーマッターの上書き(引数) YAHOO.widget.DataTable.formatEmail = function(elCell, oRecord, oColumn, oData) { var user = oData; elCell.innerHTML = "<a href=\"mailto:" + user + "@mycompany.com\">" + user + "</a>"; }; var myColumnDefs = [ {key:"flag", formatter:"myCustom"}, // use custom shortcut {key:"radio", formatter:"radio"}, // use the built-in radio formatter {key:"check", formatter:"checkbox"}, // use the built-in checkbox formatter (shortcut) {key:"button", label:"Show record data", formatter:YAHOO.widget.DataTable.formatButton}, // use the built-in button formatter {key:"field1", formatter:"dropdown", dropdownOptions:["apples","bananas","cherries"],sortable:true}, {key:"field2", sortable:true, formatter:"date"}, // use the built-in date formatter {key:"field3", sortable:true, formatter:"number"}, {key:"field4", sortable:true, formatter:"currency"}, // use the built-in currency formatter {key:"field5", sortable:true, formatter:YAHOO.widget.DataTable.formatEmail}, // use the overridden email formatter {key:"field6", sortable:true, formatter:YAHOO.widget.DataTable.formatLink} // use the built-in link formatter ]; // データの読み込み※2 var myDataSource = new YAHOO.util.DataSource(YAHOO.example.Data.multitypes); // 読み込んだデータをparseする時のタイプを指定 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON; // 読み込んだデータをparseする時のタイプを指定 // YUIのDataSourceのページ(http://developer.yahoo.com/yui/datasource/)のJSONの項を参照。 myDataSource.responseSchema = { // JSONデータのどのノードを使うか? ※2では、YAHOO.example.Dataのmultitypesまでを指定。 resultsList: "items", // 読み込むデータとパーサーを指定して、RecordSetを生成させる。 fields: [ {key:"field1", parser:"string"}, // point to the string parser {key:"field2", parser:"date"}, // point to the date parser {key:"field3", parser:"number"}, // point to the number parser {key:"field4", parser:"number"}, // point to the number parser {key:"field5"}, // this is already string data so no parser needed {key:"field6"} // this is already string data so no parser needed ] }; var myDataTable = new YAHOO.widget.DataTable("formatting", myColumnDefs, myDataSource, // APIドキュメント http://developer.yahoo.com/yui/docs/YAHOO.widget.DataTable.html // のConfiguration Attributesを参照のこと。 {caption:"キャプション", // Yen markを出すにはhtml表現。 currencyOptions:{prefix: "¥", decimalPlaces:2, decimalSeparator:".", thousandsSeparator:","}, // 年月日に変更 dateOptions:{format:"%Y/%m/%d", locale:"ja"} }); //-------- 以下、イベントハンドラー --------------------- // radioボタンクリック時のイベントハンドラ var lastSelectedRadioRecord = null; myDataTable.subscribe("radioClickEvent", function(oArgs){ if(lastSelectedRadioRecord) { lastSelectedRadioRecord.setData("radio",false); } // oArgs.targetの戻りはHTMLInputElement。 var elRadio = oArgs.target; // チェックされたレコードオブジェクトの取得 var oRecord = this.getRecord(oArgs.target); // oRecord.getData()でDataSourceで定義したresponseSchema.fieldsの中身が取れる。 alert('oRecord: '+YAHOO.lang.dump(oRecord,1)); // oRecordの操作はDataTableインスタンスのcolumn定義に従って行うことが出来る。 // (注) radioはデータではない。 oRecord.setData("radio",true); // 選ばれたRecordオブジェクトの保管 lastSelectedRadioRecord = oRecord; var name = oRecord.getData("field5"); }); // checkboxクリック時のイベントハンドラ myDataTable.subscribe("checkboxClickEvent", function(oArgs){ var elCheckbox = oArgs.target; // チェックされたレコードオブジェクトの取得 var oRecord = this.getRecord(oArgs.target); // oArgs.target=HTMLInputElement alert('oArgs.target: '+YAHOO.lang.dump(oArgs.target)); oRecord.setData("check",elCheckbox.checked); }); // buttonクリック時のイベントハンドラ myDataTable.subscribe("buttonClickEvent", function(oArgs){ // チェックされたレコードオブジェクトの取得 var oRecord = this.getRecord(oArgs.target); alert('oRecord.getData(): '+YAHOO.lang.dump(oRecord.getData())); }); // リストボックス変更時のイベントハンドラ myDataTable.subscribe("dropdownChangeEvent", function(oArgs){ var elDropdown = oArgs.target; // チェックされたレコードオブジェクトの取得 var oRecord = this.getRecord(oArgs.target); alert('変更前 oRecord.getData(): '+YAHOO.lang.dump(oRecord.getData())); oRecord.setData("field1",elDropdown.options[elDropdown.selectedIndex].value); alert('変更後 oRecord.getData(): '+YAHOO.lang.dump(oRecord.getData())); }); return { oDS: myDataSource, oDT: myDataTable }; }(); } }); </script> </HEAD> <BODY class="yui-skin-sam"> <div id="main"> <p> DataTableの動きをチェックするサンプルです。 </p> <div id="formatting"></div> </div> </BODY> </HTML>