2015/12/25

20151222-程式-讓jqGrid支援RWD的功能(橫列轉直列)(responsible web design)



(這就是jqGrid橫列轉成直列的結果圖)
=================================================
2017/06/28  - 增加程式原始碼 & 線上Demo Page

add Live Demo:
https://hougii.github.io/jqgridrwd/GridRWD.html

Source Code:
https://github.com/hougii/jqgridrwd

=================================================
以下為個人心得 + 一些小小分享給需要此功能的人員。

這段jqGird 轉直列功能,處理過程有幾個我思考重點:

1.  如何將jqGrid 欄位資料轉呈直列呈現?
2. 如何在每一筆前加上「欄位名稱」?
3. 呈現直列時,它的美工Style 調整。
4. 分頁的功能處理。



==========
這樣的需求,若僅是採用原生的Table /Tr / Td 網路上是有很多資料可參考的。

但若是JqGrid ,網路上查到的,大多是在RWD下,支援出現ScrollBar 、或是欄位可自動減少呈現.......但,就是沒有找到「現成」的jqGrid 橫列轉直列


這一項的需求,已被Manager念很久了。會拖好一陣子,一來是沒有心思處理,二來找不到關鍵技術該如何達成?

實在是......茫茫然。

好在就這樣一步一步,一個一個問題接續解決!看到了「清楚」的方向......它是可以被解決的

=========================================

在處理JqGrid之前,一定要了解jqGrid 的一項特性

就是jqGrid 是由「三個Table 」組合出來:
「.ui-jqgrid」這是最外層包住三個Table的Class

標頭:「.ui-jqgrid-htable」: 放標頭的Table,它底下是thead所包附著。
內容:「.ui-jqgrid-btable」:放Data的Table,它底下是由tbody所包附著。
分頁:「.ui-pg-table」:它放分頁等相關footer功能的Table。

懂得這些關係,才較好處理jqGrid的Style

=========================================
第一步,就是要了解,簡單的Table ,它是如何達到「橫列轉直列」的。
=========================================

這一版的概念結果就是我要的!(註:但它不是jqGrid架構)
http://css-stars.com/responsive-table/
http://demos.webtricksplus.com/responsive-table-demo.html

當它縮小後的呈現結果,就是我預期要的結果!
就開始看它是如何達到的??

只要將 Tr /Td 設定display: block ,它就會變成直列!!
   /*僅要jqGrid下的tr td 呈現-靠它才可以轉成直式*/
        .ui-jqgrid .ui-jqgrid-btable tr, .ui-jqgrid .ui-jqgrid-btable td {
            display: block;
        }

這點,是我實作過程中,最神奇的地方!(還想不出是為什麼會這樣)


=================================================
第二步:如何讓資料列的前面,留一個空間放「欄位名稱」?
=================================================


這分兩部份:1. 如何謄出空間???  2. 如何放jqGrid 欄位名稱??

針對第一點:如何謄出空間?
    靠的就是:
          a.先讓資料右移:利用 CSS:td「padding-left: 50%
  td { 
   
   border: none;
   border-bottom: 1px solid #eee; 
   position: relative;
   padding-left: 50% !important; //因為這一行,資料可以往中間靠,以讓右邊可以填data
     text-align: left !important;
  }


          b.利用CSS:「td:nth-of-type(n):before」的方式,動態放入資料:
             例如:td:nth-of-type(2):before { content: "Last Name"; color: #0e9893;}
                     解釋:在第二個列前面,放入content = "Last Name"的內容。

針對第二點:如何放jqGrid 欄位名稱?

    我利用CSS:「attr (attribute)」資訊,只要是該Element上的 attribute,到時就可以直接透過這方式取得內容資料,




所以,我在TD的屬性上,定義了「mycolname」,目的用來放該欄位的名稱:

至於要如何在每個TD上「精準」地放上欄位名稱,靠的就是 jqGrid「gridComplete」Event下所寫的JQuery了。
/完成後的處理
function gridComplete() {
    //讓每個row下的cell 都有colname(供RWD使用)
    var cm = $(this).jqGrid("getGridParam", "colNames");
    var trs = $(this).find('tr');
    $.each(trs, function (tri, tritem) {
        var tds = $(tritem).find('td');
        $.each(tds, function (tdi, tditem) {
            $(tditem).attr('mycolname', cm[tdi]);
        });
    });
    //讓它再執行一次Resize(可移除body出現scrollbar的問題)
    jqGridResize();
}


  • 取到Grid的ColumnName定義資訊。
  • 一層一層Loop取到每一列的資料TD。
  • 將欄位名稱資訊,設定在attribute上。



到這一步,基本上以達成:轉直列 、填上欄位名稱 之功能了!

==============================================
針對第三步:呈現直列時,它的美工Style 調整。
==============================================

第一點:先達到 window resize 時,jqGrid 的縮放要跟著調整
       調整jqGrid寬度就是:$("#xxx").jqGrid('setGridWidth', nowwidth-1);

第二點:開始調整Table / Tr / Td 下的CSS Style
這部份,我是透過 Chrome F12的偵錯工具,查看CSS的套用關係。
而RWD的css,關鍵的我都會套用「!important;」以防被蓋掉。
(詳情見最後的Style)


==============================================
最後一步:分頁的功能處理
==============================================

這一點,我打算採用原本的分頁功能 & 呈現方式去做呈現。

因為「ui-pg-table」下的
第一個TD是「功能列」,空的,我沒有要用,所以第一個TD隱藏。
最後一個TD是「總頁數」,調整間距,讓它好看一些。

這是第一個TD要把它隱藏 (但要排除「最上頁」Icon所在的TD)



最後調整完的「分頁」按鍵,就是長這樣子的。




總結以上,最後成果就如下圖了




================================================
相關程式碼
================================================

透過Less 來控管 寬度小於 532時,再做RWD呈現:
grid-mobile.less
/*2015/04/05 for jqgird 的Mobile 轉為直列資料呈現的 css*/
/*針對JQGrid的RWD處理*/
/*@media only screen and (max-width: 760px),(min-device-width: 768px) and (max-device-width: 1024px)  {*/
@media only screen and (max-width:532px) {

    /*RWD下最外層的table要距右側要有間距,且broder移除*/
    .ui-jqgrid {
        margin-right: 20px;
        border: 0px !important;
    }


        /*僅要jqGrid下的tr td 呈現-靠它才可以轉成直式*/
        .ui-jqgrid .ui-jqgrid-btable tr, .ui-jqgrid .ui-jqgrid-btable td {
            display: block;
        }
        /*.ui-jqgrid table, thead, tbody,td, th,tr {
   display: block;
  }*/

        /*把Header全部移除*/
        .ui-jqgrid thead tr {
            position: absolute;
            top: -9999px;
            left: -9999px;
        }

        /*RWD下移掉htable的border*/
        .ui-jqgrid .ui-jqgrid-htable {
            margin: 0em;
            font-size: 15px;
            border: 0px;
        }

        .ui-jqgrid tr {
            /*border-bottom: 2px solid #690461;*/
        }
            /*RWD下這是讓直列每個row有間距*/
            .ui-jqgrid tr.jqgrow {
                border: #dddddd 1px solid;
                background-color: #FFFFFF;
                margin-bottom: 10px;
            }
            /*內文底*/ /* Horse edit #ecf0ee */
            .ui-jqgrid tr.jqgrow2 {
                border: #dddddd 1px solid;
                background-color: #FFFFFF;
                margin-bottom: 10px;
            }
        /*內文底*/

        .ui-jqgrid td {
            border: none;
            border-bottom: 1px solid #eee;
            position: relative;
            padding-left: 40% !important;/*空出左側空間*/
            text-align: left !important;
        }

        /*在td前空出一個空間*/
            .ui-jqgrid td:before {
                position: absolute;
                /*width: 35%;這個沒有用*/
                left: 10px;/*靠position後再右推10px*/
                text-align: left;
                /*border-right-width: 1px;
                border-right-color: #CBDAB6;*/
                /*border-right-style: dashed;*/
                font-family: MingLiU,Helvetica, sans-serif;
                vertical-align: bottom;
            }
            /*加上欄位名稱Data*/
            .ui-jqgrid td:nth-of-type(n):before {
                content: attr(mycolname);
            }

        /*它是RWD的第一列td style*/
        .ui-jqgrid .ui-widget-content .ui-state-default {
            border: #d2dedb 0px solid;
            font-weight: bold;
            color: #4b7676;
            width: inherit !important;
            background-image: none;
            background-color: #cbddd5;
        }
        /*處理分頁相關的*/
    /*RWD下分頁的tabl:ui-pg-table的button呈現:*/
     .ui-jqgrid .ui-pg-table td {           
            padding-left: 0% !important;
            text-align: left !important;
        }
  /*分頁第一個的td元件:把它縮小(注意:它的ui-pg-table有兩層,不可把Icon藏掉)*/
      .ui-jqgrid .ui-pg-table td:first-child:not(.ui-pg-button){           
           display:none;
        }
     /*分頁最後的td元件(筆數的):把它靠左*/
      .ui-jqgrid .ui-pg-table td:last-child div{       
          text-align:center !important;
            position:relative;/*讓它離分頁近一點*/
            left:-30px;
        }

   /*.ui-jqgrid  .ui-jqgrid-pager {
        display: block;
         position:relative !important;
         text-align: left !important;
    }*/

     /*.ui-jqgrid .ui-pg-table tr {
            display: block;
        }*/
}


===============================================
jqGrid 相關的Javascript處理部份:.jqGrid.js
===============================================
//定義jqGrid的預設值及Function Event
$(function () {
    $.extend($.jgrid.defaults, {
        //==========屬性處理================
        multiselect: false,//不多選
        rowNum: 10,
        rowList: [10, 20, 30],
        toppager: false,
        viewrecords: true,
        rownumbers: true,
        autowidth: true,
        altRows: true,
        altclass: 'jqgrow2',
        height: "100%",//高度隨筆數而定
        rownumWidth: 30,//RowNum寬度 default:25 http://goo.gl/y8BqR
        //==========Event處理===============
        //錯誤處理
        loadError: Microsoft.UI.Grid.loadError,
        serializeGridData: Microsoft.UI.Grid.serializeGridData,
        loadComplete: Microsoft.UI.Grid.loadComplete,
        gridComplete: gridComplete
    });
})


//完成後的處理
function gridComplete() {
    //讓每個row下的cell 都有colname(供RWD使用)
    var cm = $(this).jqGrid("getGridParam", "colNames");
    var trs = $(this).find('tr');
    $.each(trs, function (tri, tritem) {
        var tds = $(tritem).find('td');
        $.each(tds, function (tdi, tditem) {
            $(tditem).attr('mycolname', cm[tdi]);
        });
    });
    //讓它再執行一次Resize(可移除body出現scrollbar的問題)
    jqGridResize();
}


//讓grid它重新調整寬度(電腦版)
$(function () {
    $(window).bind('resize', jqGridResize);
})

function jqGridResize() {
    var grids = $(".ui-jqgrid-btable,.ui-pg-table,.ui-jqgrid-htable");
    $.each(grids, function (i, item) {
        //排外不自動resize
        if ($(item).parents(".dialogpage").length > 0 ||
            $(item).parents(".ExcludeGridResize").length > 0) {

        }
        else {
            //最大寬度取決於div contentBlock
            //因pc.css有定義
            //( in screen and (max-width: 1200px) and (min-width: 533px))=980 所有要限制grid大小
            //( in screen and (max-width: 1500px) and (min-width: 1200px))=1200
            //screen and (min-width: 1501px) =1500
            var nowwidth = $(window).width(); //$(item).width();
            var contentwidth = $(".mainConetnt").width();
            contentwidth = contentwidth == null ? $("#contentBlock").width() : contentwidth;
            //若contentwidth比較小,則採用它的
            nowwidth = (contentwidth <= nowwidth) ? contentwidth : nowwidth;
            nowwidth = (nowwidth <= 980) ? nowwidth : 
                (nowwidth > 980 && nowwidth < 1200) ? contentwidth :
                (nowwidth > 1200 && nowwidth < 1500) ? contentwidth : contentwidth
            ;
            if (nowwidth <= 533)
                nowwidth = nowwidth - 20;//在RWD下要減20才可以
            $(item).jqGrid('setGridWidth', nowwidth-1);
            $(".ui-jqgrid-btable").width(nowwidth - 2);//jqgrid body再減1才不會有Srollbar
            //console.log(nowwidth + "," + contentwidth);
        }
    });
}




===============================================
相關的HTML範例程式,請自已套用自已的Layout外框 (這是MVC Razor 的寫法) ===============================================

@{
    ViewBag.Title = "GridRWD";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

GridRWD

@section Scripts{ }







0 意見 :

張貼留言