jqGrid ツールバーのカスタマイズ

検索条件設定用のパーツとか、jqGridとは別に上とかに配置してもいいですが、デザイン合わすためのCSSが別に必要になったり、グリッドと連動させて折り畳みとかしようとすると、別にコード書くという煩雑さもあるので、ツールバーの中に入れるのが、すっきりすると思います。

方法としては、2種類あって、

1)  jqGridの設定コードの後に書く

2) jqGridのgridCompoleteに書く

にしてます。

[ 後に書くコードサンプル ]


        // == ツールバー == //
        var htmlds = 'Last Revising Executed Date From ' + "${dtdssel}";
        $('#t_delayskip').prepend(htmlds); // 後でリフレッシュボタンを付けてるのでprepend

        // == From日を変えた時 == //
        $('#dtdssel').on('change', function () {

          $('#delayskip').jqGrid('setGridParam', {
            serializeGridData: function (postData) {
              postData['mindt'] = $('#dtdssel').val();
              return postData;
            }
          }).trigger('reloadGrid');
        });

・jqGridのtableのidの前に “t_” がついやのが、ツールバーのid
・${dtdssel}はJSPのpageContextで作ったセレクトタグ
・jQueryのセレクタを使って配置
・日付条件を変えて再検索できる

画面例


        // == ツールバー == //
        var PCTGT_SEARCH_BUTTON = '' +
                '';
        var htmlmt = 'Type ' + TP_SEL +
                'Add From ' + "${dtpcsel}" +
                'Res From ' + "${dtpcselres}" +
                ' Vessel ' +
                "${azselpc}" + ' No Res ' + WITH_NORES_SEL;
        $('#t_pctgt').prepend(htmlmt + PCTGT_SEARCH_BUTTON); // 後でリフレッシュボタンを付けてるのでprepend
        //$('#t_pctgt').before(htmlmt);    // 後でリフレッシュボタンを付けてるのでprepend
        $('#pctgtsearchbtn').button();


        // == Searchボタンを押した時 == //
        $('#pctgtsearchbtn').on('click', function () {

          $('#pctgt').jqGrid('setGridParam', {
            serializeGridData: function (postData) {
              postData['mindt'] = $('#dtpcsel').val();
              postData['mindtpcres'] = $('#dtpcselres').val();
              postData['hchr'] = $('#azselpc').val();
              postData['withnoressel'] = $('#withnoressel').val();
              postData['pctgttpsel'] = $('#pctgttpsel').val();
              return postData;
            }
          }).trigger('reloadGrid');

          // ローカルストレージに保存 //
          if (localStorage) {
            var pctgtMap = {};
            pctgtMap['mindt'] = $('#dtpcsel').val();
            pctgtMap['mindtpcres'] = $('#dtpcselres').val();
            pctgtMap['hchr'] = $('#azselpc').val();
            pctgtMap['withnoressel'] = $('#withnoressel').val();
            pctgtMap['pctgttpsel'] = $('#pctgttpsel').val();
            localStorage.setItem('vesselsch_pctgt', JSON.stringify(pctgtMap));
          }


        });

jqGrid userData の使い方

検索結果レコードの他、各種の付属データ(合計、平均、検索条件でもって結果としてあれば便利なデータまたは必要なデータなど)が必要な場合があると思います。

jqGrid の userData を使えば出来ます。

画面例

< 設定例 >

[ JavaScript ]

gridComplete で取得

gridComplete: function () {
// == userdata取得 == //
var userdata = $(this).jqGrid('getGridParam', 'userData');
},

 

表示例


           // 最終更新時刻 処理コスト //
            //$('#vslgridpager_left').text(userdata['lastupdttm'] + '  Cost : ' + userdata['tmcost'] + ' ms');
            var INFO_SPAN = '</>';
            $('#infospan').remove();
            $('#vslgrid_toppager_right').before(INFO_SPAN);
            $('#infospan').text(userdata['tmcost'] + ' ms');

            // スケジュール遵守率 2018-11-22 //
            var complratio = userdata['compl_ratio'];
            var compltxt = userdata['compl_txt'];
            var COMPL_SPAN = '</>';
            $('#complspan').remove();
            if (complratio != undefined) {
              $('#infospan').before(COMPL_SPAN);
              $('#complspan').text("JPort Arrival Accurancy Percentage Past 6 months : " + complratio + " (" + compltxt + ")");
            }

[ Servlet ]

HashMapに格納


    // +++ 結果メッセージ用 +++ //
    HashMap<String, String> usrdata = new HashMap<String, String>();

    DBini ini = new DBini();

    if (reslist.size() > -1) {    // <=== * 注意 *  ない場合も含む 2018-07-14 Position API 全対象用

      // 船スペック //
      String spec = PV.getAVesselspecALine(vessel, true);    // 2018-01-17 trueで短縮
      spec = spec == null ? "" : spec;
      System.out.println("spec:" + spec);

      usrdata.put("spec", spec);
      usrdata.put("vessel", vessel);
      usrdata.put("imo", spec == null ? "" : spec.trim().substring(spec.length() - 8));

結果応答用JSONオブジェクトに格納


    // ++ JSONオブジェクトに格納 ++ //
    JSONResultGrid grid = new JSONResultGrid();
    grid.setPage(1);
    grid.setTotal(1);
    grid.setRecords(reslist.size());
    grid.setRows(reslist);
    grid.setUserdata(usrdata);

    //Gson gson = new Gson();  
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String gsonstr = gson.toJson(grid);
    String gsonliststr = gson.toJson(reslist);

JSONオブジェクトクラス


package vesselsch;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * jqGrid JSONデータソース用
 * @author 
 */
public class JSONResultGrid {

  private int page = 1;
  private int total = 1;
  private int records = 0;
  
  private ArrayList<?> rows;
  private ArrayList<?> rows2;
  private ArrayList<?> rows3;
  
  private HashMap<String, String> userdata = null;
  private HashMap<String, Integer> userData = null;
  
  private ArrayList strlist = null;
  
  private HashMap<String, Integer> itmCntMap = null;

  /**
   * @return the page
   */
  public int getPage() {
    return page;
  }

  /**
   * @param page the page to set
   */
  public void setPage(int page) {
    this.page = page;
  }

  /**
   * @return the total
   */
  public int getTotal() {
    return total;
  }

  /**
   * @param total the total to set
   */
  public void setTotal(int total) {
    this.total = total;
  }

  /**
   * @return the records
   */
  public int getRecords() {
    return records;
  }

  /**
   * @param records the records to set
   */
  public void setRecords(int records) {
    this.records = records;
  }


  /**
   * @return the userdata
   */
  public HashMap<String, String> getUserdata() {
    return userdata;
  }

  /**
   * @param userdata the userdata to set
   */
  public void setUserdata(HashMap<String, String> userdata) {
    this.userdata = userdata;
  }


  /**
   * @return the rows
   */
  public ArrayList<?> getRows() {  
    return rows;
  }

  /**
   * @param rows the rows to set
   */
  public void setRows(ArrayList<?> rows) {
    this.rows = rows;
  }

  /**
   * @return the rows
   */
  public ArrayList<?> getRows2() {  
    return rows2;
  }

  /**
   * @param rows the rows to set
   */
  public void setRows2(ArrayList<?> rows2) {
    this.rows2 = rows2;
  }  
  
  /**
   * @return the userData
   */
  public HashMap<String, Integer> getUserData() {
    return userData;
  }

  /**
   * @param userData the userData to set
   */
  public void setUserData(HashMap<String, Integer> userData) {
    this.userData = userData;
  }

  /**
   * @return the strlist
   */
  public ArrayList getStrlist() {
    return strlist;
  }

  /**
   * @param strlist the strlist to set
   */
  public void setStrlist(ArrayList strlist) {
    this.strlist = new ArrayList(strlist);
  }

  /**
   * @return the rows3
   */
  public ArrayList<?> getRows3() {
    return rows3;
  }

  /**
   * @param rows3 the rows3 to set
   */
  public void setRows3(ArrayList<?> rows3) {
    this.rows3 = rows3;
  }

  /**
   * @return the itmCntMap
   */
  public HashMap<String, Integer> getItmCntMap() {
    return itmCntMap;
  }

  /**
   * @param itmCntMap the itmCntMap to set
   */
  public void setItmCntMap(HashMap<String, Integer> itmCntMap) {
    this.itmCntMap = itmCntMap;
  }
  
  
  
  
}


応答JSON文字列 userData部分


  "userdata": {
    "opeseltag": "\u003cselect name\u003d\u0027opesel\u0027 id\u003d\u0027opesel\u0027 multiple\u003d\u0027multiple\u0027 size\u003d\u00273\u0027\u003e\u003coption value\u003d\u0027APL\u0027 selected\u003eAPL\u003coption value\u003d\u0027Ben(Swire)\u0027 selected\u003eBen(Swire)\u003coption value\u003d\u0027__\u0027 selected\u003e__\u003c/select\u003e",
    "pnmccdmaptxt": "Yokohama:JP,Guam:GU,Saipan:MP,YOKOHAMA:JP",
    "nationseltag": "\u003cselect name\u003d\u0027nationsel\u0027 id\u003d\u0027nationsel\u0027 multiple\u003d\u0027multiple\u0027 size\u003d\u00273\u0027\u003e\u003coption value\u003d\u0027Guam\u0027 selected\u003eGuam\u003coption value\u003d\u0027Japan\u0027 selected\u003eJapan\u003coption value\u003d\u0027North mariana is\u0027 selected\u003eNorth mariana is\u003c/select\u003e",
    "cntrycdtxt": "GU,JP,MP",
    "tmcost": "3958",
    "compl_ratio": "33 %",
    "imo": "9229609",
    "spec": "Year:2001 Speed:19.5 TEU:1078 Length:154.00 Width:25.00 IMO:9229609 ",
    "compl_txt": "3 / 9",
    "opecnttxt": "12,12,2",
    "opestxt": "APL,Ben(Swire),__",
    "vessel": "APL GUAM",
    "pnmseltag": "\u003cselect name\u003d\u0027pnmsel\u0027 id\u003d\u0027pnmsel\u0027 multiple\u003d\u0027multiple\u0027 size\u003d\u00274\u0027\u003e\u003coption value\u003d\u0027Guam\u0027 selected\u003eGuam\u003coption value\u003d\u0027Saipan\u0027 selected\u003eSaipan\u003coption value\u003d\u0027YOKOHAMA\u0027 selected\u003eYOKOHAMA\u003coption value\u003d\u0027Yokohama\u0027 selected\u003eYokohama\u003c/select\u003e",
    "lastupdttm": "LU:2018-12-01 00:06:17",
    "voyseltag": "\u003cselect name\u003d\u0027voysel\u0027 id\u003d\u0027voysel\u0027 multiple\u003d\u0027multiple\u0027 size\u003d\u00275\u0027\u003e\u003coption value\u003d\u00270DQ2UR1PL\u0027 selected\u003e0DQ2UR1PL\u003coption value\u003d\u00270DQ2WR1PL\u0027 selected\u003e0DQ2WR1PL\u003coption value\u003d\u00270DQ2WR1PL/0DQ2W\u0027 selected\u003e0DQ2WR1PL/0DQ2W\u003coption value\u003d\u00270DQ2YR1PL\u0027 selected\u003e0DQ2YR1PL\u003coption value\u003d\u00270DQ30R1PL\u0027 selected\u003e0DQ30R1PL\u003c/select\u003e"
  }

                            

jqGrid グリッド高を検索結果数に合わせて低くする

gridComplete に下のような関数を入れてます。


// 高さを行数に応じてアジャストする //
adjustGridHeight($(this), 20, reccnt, 30);

/**
 * グリッド高のアジャスト
 * @param {type} gridobj 対象グリッド
 * @param {type} maxreccnt アジャスト適用最大レコード数
 * @param {type} reccnt 検索結果レコード数
 * @returns {undefined} なし
 */
function adjustGridHeight(gridobj, maxreccnt, reccnt) {

  //var reccnt = $(gridobj).jqGrid("getGridParam", "records");

  // 高さを行数に応じてアジャストする //
  if (reccnt <= maxreccnt) {
    $(gridobj).parents(".ui-jqgrid-bdiv").css('height', $(gridobj).css('height'));
    var hv = $(gridobj).parents(".ui-jqgrid-bdiv").css('height').replace('px', '');
    var hvadj = eval(hv) + eval(40) + 'px';
    $(gridobj).parents(".ui-jqgrid-bdiv").css('height', hvadj);
  }
  // これがないと復帰しないので //
  else {
    $(gridobj).parents(".ui-jqgrid-bdiv").css('height', $(gridobj).jqGrid('getGridParam', 'height'));
  }

}

[ 適用前 ]

[ 適用後 ]

jqGrid (Guriddo 5.3.1) へのバージョンアップによるCSSの対応

jqGrid5.3.1 にバージョンを上げたところ、4.7とデフォルトのスタイルが異なり、タイトル行の折り返しが効かないので、サポートに聞いたところ、以下のようにCSSをオーバーライトしたら、元のスタイルに出来ました。


      /* Guriddo 5.3.1 (for same style as 4.7's default) */
      .ui-jqgrid tr.jqgrow td, .ui-userdata, .ui-jqgrid-pager, .ui-jqgrid-titlebar {
        height: auto;
        font-size:11px;
        padding: 2px;
      }

      /* Guriddo 5.3.1 (for same style as 4.7's default) */
      .ui-jqgrid .ui-jqgrid-htable th div, .ui-jqgrid-sortable, .ui-jqgrid-title  {
        height:auto;
        overflow:hidden;
        white-space:normal !important;
        font-size:11px;

      }

ポイントは、thにwhite-space:normal !important;を効かすこと。フォントサイズ、パッディングの指定になります。

jqGrid が優れてる(と思う)点

2014年より前まで、

WEBページの作成としては、JSP, JavaBean を使って、sessionにデータ保持して同期リクエスト、ページ再読込、全更新という、過去からある伝統的方法でした。

googleマップの出現以来、AJax利用のページ再読込なしのページが普通となりつつある頃において、もう限界を感じ始めてました。

時代の流れにちゃんとついて行く為、jQueryベースのグリッドUIをいくつか試しはじめました。

いくつか試した結果、あくまで主観ですが、

1) ネットでの日本語情報が、比較的多い。StackOverFlowのトピックも多い

2) 追加、編集、削除とかのコーディングがわかりやすく書ける

3) 編集フォームがカスタマイズしやすい

4) jQuery-uiのテーマが全部使え、スタイルシートの記述だけで切替られる

5) カラム定義のバリエーションが豊富で、バリデーションチェックも楽

6) DOMがtableを基本としてるので、ツールバーのカスタマイズなどもわかりやすい

7) 他と比べて、デザインが平凡なので、業務システムにふさわしく、ユーザーサイドで好まれる

8) 他と共通してますが、全ブラウザ対応、スマホ、タブレットでも変更なしで表示できる

9) 積極的にバージョンアップ、バグフィックスがなされてる

10) ライセンスが安い

などです。

jqGridリンク集

本家 : http://guriddo.net/

本家デモ : http://www.guriddo.net/demo/guriddojs/

本家デモ(旧) : http://www.trirand.com/blog/jqgrid/jqgrid.html

ドキュメントwiki : http://www.trirand.com/jqgridwiki/doku.php?id=wiki:jqgriddocs

trirand.com ブログ : http://www.trirand.com/blog/

入門 : https://qiita.com/k499778/items/65db2380d989b1d70985

逆引きリファレンス : https://javascript.programmer-reference.com/category/plugin/jqgrid/