ライブラリとプラグインの違い
業務システムのマスタ管理画面にはCRUD(Create/Retrieve/Update/Delete)機能付きのデータグリッドが便利なのですが、一番シンプルなのはjQueryとJQuery Easy UIのみで実現するDataGridです。
ツリー表示で使ったjsTreeはjQueryのプラグインであり<script>タグの中に別途jstreeプラグインを読み込む必要がありましたが、DataGridはTabsなどと同じようにJQuery UIのウィジェットにあたります。
ライブラリとプラグインの違いは汎用的か特定ソフト用かなのでjQuery UIはライブラリでもありjQuery用のプラグインでもあると言えると思います。またWordPressのウィジェットがサイドバーへの機能追加に特化したプラグインなのに対し、jQuery UIのウィジェットは言葉の使われ方が若干異なります。
ということでちょっと言葉の整理をしておきたいのですが・・・
- ライブラリは汎用的関数の集合体
- プラグインは特定ソフト用拡張プログラム
- ウィジェットはライブラリ(プラグイン)が提供するコントロール(部品)
- jQueryはJavaScriptでよく使われる機能を簡単に呼び出せるようにしたライブラリ
- AjaxはJavaScriptの非同期通信に焦点をあてた概念
DataGridがあるにもかかわらず多くのメーカーがデータグリッド用のライブラリ(プラグイン)を出している理由は以下の2つで差別化を図りたいからです。
- 見栄え > 見栄えの良いRIA(Rich Internet Applications)技術
- スピード > 時間のかかる処理を非同期実行(Ajax利用)
jQuery UIの基本DataGrid実装方法
それで今回はDataGridを使うのですが、ざっくり以下の3つを実装すれば実現できそうです。
- HTMLテーブルにグリッド装飾class要素とCRUDアクションのid要素
- 親子関係からデータを取得する再帰処理関数を作成
- CRUDアクション時のダイアログを定義し新規・更新・削除ボタンにマッピング
まずタブ&パネルと同じようにheadタグの中でjQueryライブラリとjQuery用のUIライブラリ(インターフェースデザイン用ライブラリ)であるjQuery UIを読み込む必要がありますが、jQuery UIはライブラリ本体とスタイルシートを読み込む必要があります。
<head> //jQuery EasyUI用のスタイルシート <link rel="stylesheet" type="text/css" href="jquery_easyui/themes/default/easyui.css"> <link rel="stylesheet" type="text/css" href="jquery_easyui/themes/icon.css"> <link rel="stylesheet" type="text/css" href="jquery_easyui/themes/style.css" /> //jQueryとjQuery EasyUIライブラリ本体 <script type="text/javascript" src="jquery_easyui/jquery.min.js"></script> <script type="text/javascript" src="jquery_easyui/jquery.easyui.min.js"></script> </head>
データグリッド画面はid要素dgで定義し、HTMLテーブルをデータグリッド化するためのclass要素easyui-datagridを指定し、データは再帰関数で取得しレコードセットの値を表に表示します。
//初期表示画面 <table id="dg" title="" class="easyui-datagrid" style="height:auto;" toolbar="#toolbar" pagination="true" rownumbers="true" fitColumns="false" singleSelect="true"> <thead> <tr> <th field="P_ITM_CD">Parent Item Code</th> <th field="IMaster_ProcNo">Proc No</th> <th field="IMaster_ProcCode">Proc Code</th> <th field="IMaster_InstructionType">Instruction Type</th> <th field="IMaster_InstructionCode">Instruction Code</th> <th field="C_ITM_CD">Child Item Code</th> <th field="IMaster_Task2Expr">Production</th> </tr> </thead> <tbody> <?php if($_GET['node'] != ""){ while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { $main[] = $row["P_ITM_CD"]; } if(isset($main)){ foreach($main as $main_item){ echo getChild($koneksi, $main_item, $table); } } }else{ while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { echo "<tr>"; echo "<td>".$row["P_ITM_CD"]."</td>"; echo "<td>".$row["IMaster_ProcNo"]."</td>"; echo "<td>".$row["IMaster_ProcCode"]."</td>"; echo "<td>".$row["IMaster_InstructionType"]."</td>"; echo "<td>".$row["IMaster_InstructionCode"]."</td>"; echo "<td>".$row["C_ITM_CD"]."</td>"; echo "<td>".$row["IMaster_Task2Expr"]."</td>"; echo "</tr>"; } } ?> </tbody> </table> <div id="toolbar"> <a href="#" class="easyui-linkbutton" iconCls="icon-add" plain="true" onclick="newData()">新規</a> <a href="#" class="easyui-linkbutton" iconCls="icon-edit" plain="true" onclick="editData()">更新</a> <a href="#" class="easyui-linkbutton" iconCls="icon-remove" plain="true" onclick="removeData()">削除</a> </div>
DBから再帰処理で親子関係のデータを取得しDataGridに流す処理
ツリー表示でやった再帰処理のテーブルバージョンです。やってることは同じで、子品目(C_ITM_CD)にマッチする親品目(P_ITM_CD)があればデータを表示し、再帰的に自関数を読む処理をマッチする親品目がなくなる(最下層品目)まで繰り返します。
function getChild($con, $item, $table){ $sql = "select * from $table where P_ITM_CD='".$item."' and IMaster_InstructionType<>'U'"; $result = mysql_query($sql, $con); $num_rows = mysql_num_rows($result); if($num_rows > 0){ //子品目ありの場合 unset($sem); while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { if($row["C_ITM_CD"] != ""){ $sem[] = $row["C_ITM_CD"]; } } $str = ""; foreach($sem as $sem_item){ $test = getChild($con, $sem_item, $table); if( $test == ""){ $sql_detil = "select IMaster_ProcNo, IMaster_ProcCode, IMaster_InstructionCode, IMaster_Task2Expr, IMaster_InstructionType from $table where P_ITM_CD='".$item."' and C_ITM_CD='".$sem_item."'"; $result_detil = mysql_query($sql_detil, $con); $row_detil = mysql_fetch_array($result_detil, MYSQL_ASSOC); $str .= "<tr>"; $str .= "<td>".$item."</td>"; $str .= "<td>".$row_detil["IMaster_ProcNo"]."</td>"; $str .= "<td>".$row_detil["IMaster_ProcCode"]."</td>"; $str .= "<td>".$row_detil["IMaster_InstructionType"]."</td>"; $str .= "<td>".$row_detil["IMaster_InstructionCode"]."</td>"; $str .= "<td>".$sem_item."</td>"; $str .= "<td>".$row_detil["IMaster_Task2Expr"]."</td>"; $str .= "</tr>"; $sql_blue = "select * from $table where P_ITM_CD='".$item."' and IMaster_InstructionType='U'"; $result_blue = mysql_query($sql_blue, $con); $num_rows_blue = mysql_num_rows($result_blue); if($num_rows_blue > 0){ while ($row_blue = mysql_fetch_array($result_blue, MYSQL_ASSOC)) { $str .= "<tr>"; $str .= "<td>".$row_blue["P_ITM_CD"]."</td>"; $str .= "<td>".$row_blue["IMaster_ProcNo"]."</td>"; $str .= "<td>".$row_blue["IMaster_ProcCode"]."</td>"; $str .= "<td>".$row_blue["IMaster_InstructionType"]."</td>"; $str .= "<td>".$row_blue["IMaster_InstructionCode"]."</td>"; $str .= "<td>".$row_blue["C_ITM_CD"]."</td>"; $str .= "<td>".$row_blue["IMaster_Task2Expr"]."</td>"; $str .= "</tr>"; } } }else{ $sql_detil = "select IMaster_ProcNo, IMaster_ProcCode, IMaster_InstructionCode, IMaster_Task2Expr, IMaster_InstructionType from $table where P_ITM_CD='".$item."' and C_ITM_CD='".$sem_item."'"; $result_detil = mysql_query($sql_detil, $con); $row_detil = mysql_fetch_array($result_detil, MYSQL_ASSOC); $str .= "<tr>"; $str .= "<td>".$item."</td>"; $str .= "<td>".$row_detil["IMaster_ProcNo"]."</td>"; $str .= "<td>".$row_detil["IMaster_ProcCode"]."</td>"; $str .= "<td>".$row_detil["IMaster_InstructionType"]."</td>"; $str .= "<td>".$row_detil["IMaster_InstructionCode"]."</td>"; $str .= "<td>".$sem_item."</td>"; $str .= "<td>".$row_detil["IMaster_Task2Expr"]."</td>"; $str .= "</tr>"; $str .= $test; $sql_blue = "select * from $table where P_ITM_CD='".$item."' and IMaster_InstructionType='U'"; $result_blue = mysql_query($sql_blue, $con); $num_rows_blue = mysql_num_rows($result_blue); if($num_rows_blue > 0){ while ($row_blue = mysql_fetch_array($result_blue, MYSQL_ASSOC)) { $str .= "<tr>"; $str .= "<td>".$row_blue["P_ITM_CD"]."</td>"; $str .= "<td>".$row_blue["IMaster_ProcNo"]."</td>"; $str .= "<td>".$row_blue["IMaster_ProcCode"]."</td>"; $str .= "<td>".$row_blue["IMaster_InstructionType"]."</td>"; $str .= "<td>".$row_blue["IMaster_InstructionCode"]."</td>"; $str .= "<td>".$row_blue["C_ITM_CD"]."</td>"; $str .= "<td>".$row_blue["IMaster_Task2Expr"]."</td>"; $str .= "</tr>"; } } } } unset($row); return $str; }else{ //子品目なしの場合 return ""; } }
関数を定義しidセレクタでダイアログを取得し、datagridメソッドで選択行に対して処理を行います。
<script> //新規 function newData(){ $('#dlg').dialog('open').dialog('setTitle','Tambah Data'); $('#fm').form('clear'); $('#id_user').removeAttr('readonly','readonly'); url = 'proses.php?cmd=newrow'; } //修正 function editData(){ var row = $('#dg').datagrid('getSelected'); if (row){ $('#dlg').dialog('open').dialog('setTitle','Edit Data'); $('#fm').form('load',row); $('#id_user').attr('readonly','readonly'); url = 'proses.php?cmd=updaterow'; document.getElementById('hdn_P_ITM_CD').value = document.getElementById('P_ITM_CD').value; document.getElementById('hdn_IMaster_InstructionType').value = document.getElementById('IMaster_InstructionType').value; document.getElementById('hdn_C_ITM_CD').value = document.getElementById('C_ITM_CD').value; } } //削除 function removeData(){ var row = $('#dg').datagrid('getSelected'); if (row){ $.messager.confirm('Confirm','Anda yakin akan menghapus data ini?',function(r){ if (r){ $.post('proses.php?cmd=deleterow',{ P_ITM_CD:row.P_ITM_CD, IMaster_ProcNo:row.IMaster_ProcNo, IMaster_ProcCode:row.IMaster_ProcCode, IMaster_InstructionType:row.IMaster_InstructionType, IMaster_InstructionCode:row.IMaster_InstructionCode, C_ITM_CD:row.C_ITM_CD, IMaster_Task2Expr:row.IMaster_Task2Expr },function(result){ if (result.success){ $('#dg').datagrid('reload'); // reload the user data location.reload(); } else { $.messager.show({ // show error message title: 'Error', msg: result.msg }); } },'json'); } }); } } //保存 function saveData(){ $('#fm').form('submit',{ url: url, onSubmit: function(){ return $(this).form('validate'); }, success: function(result){ var result = eval('('+result+')'); if (result.success){ $('#dlg').dialog('close'); // close the dialog $('#dg').datagrid('reload'); // reload the user data location.reload(); } else { $.messager.show({ title: 'Error', msg: result.msg }); } } }); } document.getElementById("msg").innerHTML = ""; </script>
新規・更新・削除用のダイアログはid要素dlgで定義し、それぞれの関数にマッピングする。
//新規・修正・削除ポップアップ <div id="dlg" class="easyui-dialog" style="width:400px;height:280px;padding:10px 20px" closed="true" buttons="#dlg-buttons"> <div class="ftitle">Informasi Record</div> <form id="fm" method="post" novalidate> <input type="hidden" name="hdn_P_ITM_CD" id="hdn_P_ITM_CD"> <input type="hidden" name="hdn_IMaster_InstructionType" id="hdn_IMaster_InstructionType"> <input type="hidden" name="hdn_C_ITM_CD" id="hdn_C_ITM_CD"> <div class="fitem"> <table> <tr> <td>Final Item Code:</td> <td><input name="P_ITM_CD" id="P_ITM_CD" class="easyui-validatebox" required="true"></td> </tr> <tr> <td>Proc No:</td> <td><input name="IMaster_ProcNo" id="IMaster_ProcNo" class="easyui-validatebox" required="true"></td> </tr> <tr> <td>Proc Code:</td> <td><input name="IMaster_ProcCode" id="IMaster_ProcCode" class="easyui-validatebox" required="true"></td> </tr> <tr> <td>Instruction Type:</td> <td><input name="IMaster_InstructionType" id="IMaster_InstructionType" class="easyui-validatebox" required="true"></td> </tr> <tr> <td>Instruction Code:</td> <td><input name="IMaster_InstructionCode" id="IMaster_InstructionCode" class="easyui-validatebox" required="true"></td> </tr> <tr> <td>Item Or Resource:</td> <td><input name="C_ITM_CD" id="C_ITM_CD" class="easyui-validatebox" required="true"></td> </tr> <tr> <td>Production:</td> <td><input name="IMaster_Task2Expr" id="IMaster_Task2Expr" class="easyui-validatebox"></td> </tr> </table> </div> </form> </div> <div id="dlg-buttons"> <a href="#" class="easyui-linkbutton" iconCls="icon-ok" onclick="saveData()">Save</a> <a href="#" class="easyui-linkbutton" iconCls="icon-cancel" onclick="javascript:$('#dlg').dialog('close')">Cancel</a> </div>