jqGrid グリッドデータをクリップボードにコピー

< 画面例 >

1) ナビゲーションボタンにコピーボタンを配置

2) クリックすると全選択 => 選択内容がクリップボードにコピーされる

< コード例 >

1) 呼び出し元


// クリップボードコピー //  
clipCopyButtonJSfunc($("#addrlist"), $("#addrlistpager"), "");

2) コピーボタン追加


**
 * jqGrid table contents copy to clipboard
 * @returns {undefined}
 */
function clipCopyButtonJSfunc(objtable, objpager, idcmpltdmsg) {

  // ==== Clipboard copy ==== //
  $(objtable).jqGrid('navButtonAdd', objpager,
          {
            caption: 'Copy',
            //id: "copygmapdest",
            title: "Copy table contents",
            onClickButton: function () {
              //alert($(this).attr("id"));
              selectDomElm(this);

              // 選択しているテキストをクリップボードにコピーする
              document.execCommand("Copy");
              // 選択の解除 //
              //window.getSelection().removeAllRanges();


            },
          }
  );


}

3) 指定DOMエレメント選択


// 指定DOMエレメント選択 //
function selectDomElm(obj) {
  // Rangeオブジェクトの取得
  var range = document.createRange();
  // 範囲の指定
  range.selectNodeContents(obj);

  // Selectionオブジェクトを返す。ユーザが選択した範囲が格納されている
  var selection = window.getSelection();
  // 選択をすべてクリア
  selection.removeAllRanges();
  // 新規の範囲を選択に指定
  selection.addRange(range);
}

ここで教えていただきました : https://9-bb.com/javascript-3/

jqGrid サブグリッドの表示非表示をプロパティでセット

jqGrid の最近のアップデートのドキュメントを見ていたら、ありましたので、早速実装してみました。

前は、loadComplete でグリッドデータをループして、クラスをセットしていたので、すっきりわかりやすくなりました。

isHasSubGrid: で出来ます。



 // ######### サブグリッド ######### //
 subGrid: true,
 isHasSubGrid: function (rowid) {   // <=== New from 5.3
   // if custommerid begin with B, do not use subgrid
   var cell = $(this).jqGrid('getCell', rowid, "cnt_img");
   //console.log(cell, rowid);
   if (cell && cell == 0) {    // <=== === は使えない
     return false;
   }
   return true;
 },
 subGridOptions: {
   // configure the icons from theme rolloer
   plusicon: "ui-icon-triangle-1-e",
   minusicon: "ui-icon-triangle-1-s",
   openicon: "ui-icon-arrowreturn-1-e"
 },
 subGridRowExpanded: showChildGrid,    // <=== 展開した時の処理
 // ######### サブグリッド ######### //     

PHP jqGrid用JSON応答用コード

いちばん簡潔に書くと、以下のようになります。

[ コード例 ]


<?php  

try {
  
  // 接続定義 //
  $connect_db = "mysql:dbname=databasename;host=localhost;charset=utf8";
  $connect_user = '?????';
  $connect_passwd = '??????';

  //データベース接続
  $dbm = new PDO($connect_db, $connect_user, $connect_passwd);
  // 検索 //
  $stmt = $dbm->query($SQL);
  
  // JSONクラスのインスタンス化 //
  $responce = new stdClass();

  $i = 0;
  while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    foreach ($row as $fld => $val) {
       //echo $val."\n";
      $responce->rows[$i][$fld] = mb_convert_encoding($val, "UTF-8", "auto");
    }
    $i++;
  }

  // JSONに変換して出力 //
  echo json_encode($responce, JSON_PRETTY_PRINT);
  
} catch (Exception $ex) {
  var_dump($ex->getMessage());
}

// 切断 //
$dbm = null;

?>

jQuery-ui テーマの設定と読込

[ 設定と読込 ]

    1. データベースにマスタを用意

CREATE TABLE `m_themacol` (
	`NM_THEMA` VARCHAR(20) NOT NULL COMMENT 'テーマ名',
	`NM_MENUCOL` VARCHAR(7) NOT NULL DEFAULT '' COMMENT 'メニュー背景色',
	`IS_DARKTHEME` TINYINT(4) NOT NULL DEFAULT '0',
	`TM_ADD` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '追加時刻',
	`TM_UPDT` DATETIME NOT NULL DEFAULT '2000-01-01 00:00:00' COMMENT '最終更新時刻',
	PRIMARY KEY (`NM_THEMA`)
)
COMMENT='jQueryUIテーマ別色設定'
COLLATE='sjis_japanese_ci'
ENGINE=InnoDB
;
  1. Startupのサーブレットでデータベースを読込、public static な変数に格納
  2. JSPで読込み、pageContextに格納
  3. スタイルシートのファイル名またはディレクトリ名のテーマ名部分を、pageContextの変数にする

jqGrid colModel, colNames (JSONファイル読込)

列数が多かったり、複雑な設定の colModel の場合、ページと同じファイルに記述すると、長くわかりにくくメンテナンス性低下なので、JSONファイルを読み込んでます。

[ コード例 ]


  // 一覧表のcolModelをファイルから読み込む //
  $.ajaxSetup({async: false});     // <== 非同期を解除
  var shipmentColmodel;
  var tmpname;
  $.getJSON("shipment.json", function (json) {
    shipmentColmodel = json;
    var len = json.length;
    for (var i = 0; i < len; i++) {
      tmpname = shipmentColmodel[i]['name'];

      // ローカルストレージに保存した列幅にする //
      if (name_widthMap[tmpname]) {
        shipmentColmodel[i]['width'] = name_widthMap[tmpname];
      }

    }
  });
  $.ajaxSetup({async: true});   // <== 非同期に戻す

[ JSONファイル例 ]

— 省略 —

jqGrid セルのコンテキストメニュー

[ Javascript, CSSのセット ]


    <!-- ContextMenu -->
    <script type="text/javascript" src="Script/js/jquery.contextmenu.r2.js" charset="UTF-8"></script>
    <link rel="stylesheet" type="text/css" src="Script/css/contextmenu.css" charset="UTF-8" />

[ contextMenuのセット ]


      <!--  Another Photos, Get Another details のコンテキストメニュー -->
      <div class="contextMenu" id="cntxtidphotos">
        <ul>
          <li id="mtphotos">
            <img src="Img/mt.png"/>
            Open Another Photos
          </li>

          <li id="mtdtlapi">
            <img src="Img/mt.png"/>
            Get detailed spec from MT
          </li>
        </ul>       
      </div>

[ コード例 ]

loadCompleteで、行走査して各行の指定位置セルに設定


          var rowId;

            $.each(rows, function (i) { 


             // === 写真ページ用コンテキストメニュー === //
              $('#' + rows[i]['id']).children('td').eq(0).contextMenu('cntxtidphotos', {
                menuStyle: {width: '200px'},
                bindings: {
                  'mtphotos': function (t) {
                    var url = PHOTOS_URL + rowId;
                    // ページフィルターログ書込み //
                    $.post("paramCheck", {});
                    window.open(url);
                  },
                  'mtdtlapi': function (t) {

                    $.ajax({
                      url: "ReqUpdtAvesselSpecMTGroovy",
                      type: "POST",
                      dataType: "json",
                      async: false,
                      data: {imo: rowId},
                      success: function (res) {

                        // リフレッシュを発生 //
                        $('#refresh_specs').click();

                      },
                    });

                  },
                },
                // これでpublicな変数が不要 //
                onContextMenu: function (event, menu) {
                  rowId = $(event.target).parent("tr").attr("id");  // = imo
                  var grid = $("#jqGrid");
                  grid.setSelection(rowId);   // 行を選ばせる
                  return true;
                }
              });

[ 画面例 ]

jqGrid フッター、ヘッダーに集計値表示

[ フッター配置例 ]

[ ヘッダー配置例 ]

[ jqGrid コード例 ]

デフォルトはフッター
footerrow, userDataOnFooter を true にする


footerrow: true,
userDataOnFooter: true,

ヘッダーにしたい時は、gridComplete で DOM操作して明細行と合計行の位置を入れ替える


  // フッター合計を上にする, 境界線スタイルを変える //
  var dtlobj = $('#gview_asivlist').children('div').eq(3);   // 明細行
  var fttlobj = $('#gview_asivlist').children('div').eq(4);  // 合計行
  $(fttlobj).css({
    "border-bottom-style": "solid",
    "border-bottom-color": '#008600',
    "border-bottom-width": "2px"
  }).insertBefore($(dtlobj));

[ Servlet コード例 ]

集計値用マップ


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

検索後、集計値を格納


  /**
   * テーブルスキーマ情報取得
   *
   * @param usrdata 合計値マップ
   * @return テーブルスキーマ型リスト
   */
  public ArrayList<TableSchema> getTableSchemaList(HashMap<String, String> usrdata) {

    List list = null;
    try (SqlSession session = sqlSessionFactory.openSession()) {

      list = session.selectList("selTableSchemaList", this);
      System.out.println("getTableSchemaList ():" + list.size());

      // フッター用 //
      // ストリームで合計を格納 //
      ArrayList<TableSchema> slist = new ArrayList(list);
      int cntRow = (int)slist.stream().count();    // 件数 long なので intにキャスト     
      int colTotal = slist.stream().mapToInt(v -> v.getCntCol()).sum();     // 列数
      int rowTotal = slist.stream().mapToInt(v -> v.getCntRow()).sum();     // 行数
      int totalTotal = slist.stream().mapToInt(v -> v.getLenTotal()).sum(); // 合計サイズ
      int dataTotal = slist.stream().mapToInt(v -> v.getLenData()).sum();   // データサイズ
      int indexTotal = slist.stream().mapToInt(v -> v.getLenIndex()).sum(); // インデックスサイズ
      
      // HashMapに追加 //
      usrdata.put("cntCol", String.valueOf(colTotal));
      usrdata.put("cntRow", String.valueOf(rowTotal));
      usrdata.put("lenTotal", String.valueOf(totalTotal));
      usrdata.put("lenData", String.valueOf(dataTotal));
      usrdata.put("lenIndex", String.valueOf(indexTotal));
      usrdata.put("comment", "    Total " + String.valueOf(cntRow) + " Tables" );
      
    }
    catch (Exception se) {
      se.printStackTrace();
    }
    return new ArrayList(list);

  }

応答JSONのセット


    // +++ 結果返却用 +++ //
    JSONResultGrid loggrid = new JSONResultGrid();
    loggrid.setPage(1);
    loggrid.setTotal(1);
    loggrid.setRows(loglist);
    loggrid.setUserdata(usrdata);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String gsonstr = gson.toJson(loggrid);

応答データ


  "userdata": {
    "cntRow": "27494440",
    "lenTotal": "4135942",
    "cntCol": "1689",
    "lenData": "2479938",
    "comment": "    Total 173 Tables",
    "lenIndex": "1656004",
    "sidx": "1"
  }

jqGrid タイトルセルに画像を配置

タイトル行の各thタグの id は、gridのid + “_” + colModelのnameプロパティ になっていて、textはcolNames配列の値となってますので、idを指定して、html を置き換えれば出来ます。

[ コード例 ]


// 国旗スパン //
var FLAG_SPAN = '<span><img src="Img/flag/TH.gif" /><span style="margin-left:4px;">HSCD</span></span>';

// HSCDに国旗をつける //
$('#' + $(this).attr('id') + '_cdHST').html(FLAG_SPAN);

[ 画面例 ]

MySQL 日付指定年齢関数

誕生年月日を渡せば、今日の年齢を返します。


CREATE DEFINER=`root`@`localhost` FUNCTION `fc_age_by_birthdate`(
	`bdate` date

)
RETURNS int(11)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT '日付値指定年齢取得スカラー関数'
begin
  declare agetoday int;
  select year(current_date) - year(bdate) - (right(current_date, 5) < right(bdate, 5)) into agetoday;
  return agetoday;
  
end

DATE型値をキャストなしで部分文字列取得できます。

下は今日以外を指定した年齢取得


CREATE DEFINER=`root`@`localhost` FUNCTION `fc_age_by_birthdate_tgtdt`(
	`bdate` date,
	`tgtdt` date
)
RETURNS int(11)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT '日付値指定年齢取得スカラー関数'
begin
  declare agetoday int;
  select year(tgtdt) - year(bdate) - (right(tgtdt, 5) < right(bdate, 5)) into agetoday;
  return agetoday;
  
end

[ 利用場面 ]