如何让 jqgrid 冻结列与自动换行一起使用

Posted

技术标签:

【中文标题】如何让 jqgrid 冻结列与自动换行一起使用【英文标题】:How can i get jqgrid frozen columns to work with word wrap on 【发布时间】:2012-01-30 23:29:09 【问题描述】:

我正在使用最新的 jqgrid 4.3.1,并且我正在尝试使用冻结列。

问题是我在 jqgrid 中覆盖了默认 css 以支持自动换行(css 解决方案可以看到 in this question),我认为这就是冻结列与常规列不正确对齐的原因.冻结行的高度与网格其余部分的高度不同。这是一个屏幕截图.. 冻结的列在红色框中突出显示(注意:我划掉了内容,因为它不是一个公共站点:

在 jqgrid 中是否有冻结列与单词包裹的单元格对齐

注意:在尝试了下面 Oleg 的解决方案后,它可以在 Firefox 中运行,但在 IE8 中我看不到水平滚动条(见图)

火狐:

IE:(注意没有水平滚动条)

注意:

为了帮助回答 Oleg 的问题,这里是我的 jqgrid 设置的转储:

jQuery(gridSelector).jqGrid(
    mtype: 'POST',
    toppager: true,
    url: siteRoot + controller + "/" + gridDataName + "?" + querystring,
    datatype: "json",
    colNames: names,
    colModel: model,
  shrinkToFit: false,

    imgpath: siteRoot + "Scripts/jqGrid431/themes/steel/images",
    rowNum: 20,
    rowList: [10, 20, 50, 999],
    altRows: true,
    altclass: "altRow",
    jsonReader: 
        root: "Rows",
        page: "Page",
        total: "Total",
        records: "Records",
        repeatitems: false,
        id: "Id"
    ,
    search: true,
    postData: (myfilter) ?  filters: JSON.stringify(myfilter) : ,
    //postData:   filters: JSON.stringify(myfilter) ,
    pager: pagerSelector,
    height: "auto",
    sortname: sortCol,
    viewrecords: true,
    sortorder: sortDirection,
    beforeRequest: function () 

        var grid = jQuery(gridSelector);
        if (gridprefs && gridprefs.filter) 
            grid.setPostDataItem('_search', true);
            for (var prop in gridprefs.filter) 
                var value = eval('gridprefs.filter.' + prop);
                if ('' + value != '') 
                    grid.setPostDataItem(prop, value);
                
            

            grid.setPostDataItem('sidx', gridprefs.scol);
            grid.setPostDataItem('sord', gridprefs.sord);
            grid.setPostDataItem('page', gridprefs.page);
            grid.setPostDataItem('rows', gridprefs.rows);
            grid.jqGrid('setGridParam', 
                sortname: gridprefs.scol,
                sortorder: gridprefs.sord,
                page: gridprefs.page,
                rowNum: gridprefs.rows
            );
        
    ,
    loadComplete: function () 

        var newCapture = "", filters, rules, rule, op, i, iOp,
                    postData = jQuery(gridSelector).jqGrid("getGridParam", "postData"),
                    isFiltering = jQuery(gridSelector).jqGrid("getGridParam", "search");

        if (isFiltering === true && typeof postData.filters !== "undefined") 
            filters = $.parseJSON(postData.filters);
            newCapture = "Filter: [";
            rules = filters.rules;
            for (i = 0; i < rules.length; i++) 
                rule = rules[i];
                op = rule.op;  // the code name of the operation
                iOp = $.inArray(op, arOps);
                if (iOp >= 0 && typeof $.jgrid.search.odata[iOp] !== "undefined") 
                    op = $.jgrid.search.odata[iOp];
                
                newCapture += rule.field + " " + op + " '" + rule.data + "'";
                if (i + 1 !== rules.length) 
                    newCapture += ", ";
                
            
            newCapture += "]";
        
        jQuery(gridSelector).jqGrid("setCaption", newCapture);
        fixPositionsOfFrozenDivs.call(this);

        $(gridSelector).supersleight( shim: siteRoot + 'Content/Images/shim.gif' );
        if (gridprefs && gridprefs.filter) 
            for (var prop in gridprefs.filter) 
                $('#gs_' + prop).val(eval('gridprefs.filter.' + prop));
            
            $(".ui-pg-selbox").val(gridprefs.rows);
            $(".ui-pg-input").val(gridprefs.page);
        
        gridprefs = ;
    ,
    editurl: siteRoot + controller + "/Update" + appendRoute,
    ondblClickRow: editable ?
        function (rowid) 
            jQuery(gridSelector).editGridRow(rowid,  width: 600 );
         :
        function (rowid)  
);

//$(gridSelector).jqGrid('navGrid', '#pager',  search: true, cloneToTop: true );
$(gridSelector).jqGrid('filterToolbar',  stringResult: true, searchOnEnter: true );

jQuery(gridSelector).jqGrid('bindKeys', );

if (editable) 
    jQuery(gridSelector).navGrid(pagerSelector,
         cloneToTop: true, refresh: false
        ,
         height: 380, width: 500, reloadAfterSubmit: true, closeAfterEdit: true, url: siteRoot + controller + "/Update", zIndex: 1100 ,
         height: 380, width: 500, reloadAfterSubmit: true, closeAfterAdd: true, url: siteRoot + controller + "/Add", zIndex: 1100 ,
         reloadAfterSubmit: true, url: siteRoot + controller + "/Delete" ,
         multipleSearch: true,
            beforeShowSearch: function($form) 
                $('#searchmodfbox_' + $(gridSelector)[0].id).width(560);
            
        );

 else 
    jQuery(gridSelector).navGrid(pagerSelector,
         cloneToTop: true, refresh: false, add: false, edit: false, del: false ,
         ,  ,  ,  multipleSearch: true,
            beforeShowSearch: function($form) 
                $('#searchmodfbox_' + $(gridSelector)[0].id).width(560);
            
        );
    

    myAddButton(gridSelector, 
        caption: "",
        title: "Reload Grid",
        buttonicon: 'ui-icon-refresh',
        onClickButton: function () 
            $(gridSelector).trigger("reloadGrid");
        
    );


【问题讨论】:

问题是标题中的滚动条吗?还是标题“工作流”下方的单元格应该更高并与“团队”下方的单元格匹配? @ThinkingStiff - 两者:) 你想在正文中自动换行,还是只是在标题中? @ThinkingStiff - 两者:) 【参考方案1】:

jqGrid 中冻结列的实现是基于创建两个具有绝对位置标准网格上的附加 div。如果所有列标题的高度和网格主体的所有行都相同,则冻结列的效果很好,但在可变高度的情况下(使用height: auto CSS),结果如下(参见the first demo):

第一个 div,命名为 fhDiv,我用黄色标记,包含列标题的副本(hDiv),其中最后一个非冻结列被删除。以同样的方式,第二个 div 被命名为fbDiv,我用红色标记了它包含网格体的副本(bDiv),其中最后一个非冻结列被删除。您可以阅读here 了解更多关于标准网格元素的信息。

在演示中,我在the answer 中描述的列标题中使用了字符换行,以及例如here 中描述的自动换行。

fhDivfbDiv 的每一行的高度将独立于非冻结列的高度计算。所以行的高度可以根据需要减少。

很难提出问题的完美解决方案,但似乎我找到了足够实用的方法。这个想法是根据主要潜水hDivbDiv中相应行的大小显式设置fhDivfbDiv中每一行的高度。所以我将the answer中描述的fixPositionsOfFrozenDivs函数的代码扩展为如下:

var fixPositionsOfFrozenDivs = function () 
        var $rows;
        if (typeof this.grid.fbDiv !== "undefined") 
            $rows = $('>div>table.ui-jqgrid-btable>tbody>tr', this.grid.bDiv);
            $('>table.ui-jqgrid-btable>tbody>tr', this.grid.fbDiv).each(function (i) 
                var rowHight = $($rows[i]).height(), rowHightFrozen = $(this).height();
                if ($(this).hasClass("jqgrow")) 
                    $(this).height(rowHight);
                    rowHightFrozen = $(this).height();
                    if (rowHight !== rowHightFrozen) 
                        $(this).height(rowHight + (rowHight - rowHightFrozen));
                    
                
            );
            $(this.grid.fbDiv).height(this.grid.bDiv.clientHeight);
            $(this.grid.fbDiv).css($(this.grid.bDiv).position());
        
        if (typeof this.grid.fhDiv !== "undefined") 
            $rows = $('>div>table.ui-jqgrid-htable>thead>tr', this.grid.hDiv);
            $('>table.ui-jqgrid-htable>thead>tr', this.grid.fhDiv).each(function (i) 
                var rowHight = $($rows[i]).height(), rowHightFrozen = $(this).height();
                $(this).height(rowHight);
                rowHightFrozen = $(this).height();
                if (rowHight !== rowHightFrozen) 
                    $(this).height(rowHight + (rowHight - rowHightFrozen));
                
            );
            $(this.grid.fhDiv).height(this.grid.hDiv.clientHeight);
            $(this.grid.fhDiv).css($(this.grid.hDiv).position());
        
    ;

我在resizeStoploadComplete 回调中调用了该方法。如果使用gridResize 方法,则需要在stop 处理程序中包含其他修复。

您可以在the demo 上看到我的完整建议,它将第一个演示的结果修复为以下内容:

已更新:The answer 包含演示的更新版本:this one。

【讨论】:

感谢奥列格。 .我注意到了一些事情。我必须添加: resizeColumnHeader.call($grid[0]);在停止:功能。此外,这在 Firefox 中效果很好,但我只是在 IE 中进行了测试,我没有在底部看到任何水平滚动条。我在问题中添加了一张图片以显示 @leora:我在 IE8 上测试了my demo,但看不到您描述的问题。能否提供有问题的在线测试演示?您使用的 CSS 可能还有其他一些问题。看看我在演示中使用的 CSS 并与青年进行比较。 好主意。 .我将恢复为开箱即用的原始 css,并且只进行您添加的更改。 . 所以我现在知道它与任何冻结列的内容都无关。即使我创建了一个基本的 jqgrid 并设置了一个明确的宽度(小于 col 宽度的总和),firefox 和 chrome 都显示了一个水平滚动条,但 IE 没有 另外,为了帮助澄清我上面的评论,我已将所有 jqgrid 设置转储到问题的底部【参考方案2】:

所以这是调整列大小的函数。

function updateSize()

    //getting all lines in two tables by they id
    var lines = $("tr", this),
        flines = $("tr", "#"+$(this).attr("id")+"_frozen" );

    //setting in all frozen lines height equel to grid
    flines.each(function(i, item)

        //i%2 check because of border collapse
        $(item).height( $(lines[i]).innerHeight() - (i%2?1:0) );
    );

CSS 规则

.ui-jqgrid tr.jqgrow td
    height: auto;
    white-space: normal;

还有初始化

jQuery("#gfrc1").jqGrid( 
    //options
    'loadComplete': updateSize,
    'resizeStop': updateSize
);
//Frozen Columns init
jQuery("#gfrc1").jqGrid('setFrozenColumns');

不好,但可以。 当我尝试使用 setParams 方法设置它时,出现了一些错误,上下文正在发生变化,因此最好在 jqGrid 的 init 上进行设置。如果您需要设置功能,只需在函数中使用 apply 到 updateSize 方法并保存此上下文。

另一件事是高度和边框折叠,我真的不知道如何更好地解决这个问题:)

还有example 带有静态数据。

【讨论】:

【参考方案3】:

假设这是您使用的 CSS(来自您的链接):

.ui-jqgrid tr.jqgrow td 
    white-space: normal !important;
    height:auto;
    vertical-align:text-top;
    padding-top:2px;

您应该能够摆脱滚动条(注意选择器是.ui-jqgrid tr.jqgrow 而不是.ui-jqgrid tr.jqgrow td):

.ui-jqgrid tr.jqgrow 
    overflow: hidden;

height: auto; 是导致行变短的原因。尝试从您的 CSS 中完全删除它。如果这不起作用,您也可以将所有 &lt;td&gt; 元素设置为相同的高度或全部设置为 auto(两者都未经测试,因为您没有发布代码)。

【讨论】:

【参考方案4】:

试试这个:

qgrid tr.jqgrow td 

white-space: nowrap !important;


【讨论】:

【参考方案5】:

我无法让 Oleg 的解决方案发挥作用,但我根据他的工作制作了一些对我有用的东西。不知道我是否错过了什么,但由于这对我有用,我想我会分享:

我还必须在我的 CSS 文件中添加一行

.frozen-divoverflow:hidden;

 var fixPositionsOfFrozenDivs = function () 
     var originalRowHeightArray = new Array();
     var gridId = $(this).attr("id");

     $("#" + gridId).find("tr").each(function () 
         originalRowHeightArray.push($(this).find("td").first().height() + 1);
     );

     $rows = $('>div>table.ui-jqgrid-btable>tbody>tr', this.grid.bDiv);

     $rows.each(function (i) 
         var rowHight = $($rows[i]).height(), rowHightFrozen = $(this).height();
         $(this).height(originalRowHeightArray[i] + "px");
     );
 ;

【讨论】:

您的解决方案非常适合我。有同样的问题并在加载网格后调用您的函数。冻结和非冻结的行现在更加对齐。谢谢!【参考方案6】:

我看过了,知道为什么会出现这个问题。

当显示冻结列时,实际上存在一些重复的表格,但只有冻结列,如果您将空白设置为正常,并且网格中的某处在未冻结区域中出现不等高列,则高度开始不匹配.

表的复制是为了不重新计算 js 中表的参数,所以如果你需要这个 css 属性,你应该将你的 gridComplete 和 resizeStop 事件(或任何其他会改变 cols 宽度的事件)设置为函数如下:

function onChangeGrid()
   var frozen = $("#grid_frozen tr", this),
       rows = $("#grid tr", this);

   frozen.each(function(i, item)
     var fEl = $(item),
         h = $(rows[i]).height();

     if( fEl.height() < h )
       fEl.height(h); 
      else 
       fEl.css("height", "auto");
     
   );



$("#my_grid").jqGrid(
  gridComplete: onChangeGrid,
  resizeStop: onChangeGrid
);

我在这里写的不是testetd,而是一些修复,应该可以正常工作,我现在还没有设置jqGrid。

玩得开心:)

顺便说一句,如果您需要查看很多行,这是一个糟糕的解决方案,最好在 github 上设置问题任务

【讨论】:

以上是关于如何让 jqgrid 冻结列与自动换行一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使用Java生成XML文件时,如何能让文件自动换行?

如何在 c# mvc 中自动刷新 jqgrid

excel里如何让文字自动换行显示

excel中如何让文字自动换行?

怎么让DIV里面的文字自动换行

如何让 Flex 文本控件自动换行