4

固定幅の HTML テーブル セルで最も幅の広いコンテンツを特定しようとしています。現在、外部サイザー DIV を使用しています。

 <div id="xdivSizer" style="position:absolute;display:inline;visibility:hidden">
 </div>

このコードで

var iColWidth = 0;

for (var Y = 0; Y < oDataTable.rows.length; Y++) {
    oDivSizer.innerHTML = oDataTable.rows[Y].cells[0].innerHTML;
    iColWidth = Math.max(oDivSizer.offsetWidth, iColWidth)
}

テーブルに100行程度しかない場合でも、機能しますが、非常に遅くなります。主な犯罪者は を計算しているようですoffsetWidth。これを達成するためのより効率的な方法はありますか?

そのテーブル列のサイズを最も広いデータのサイズに変更する必要があるため、これを行っています。他に良い方法があれば、それも素晴らしいでしょう。

(より正確には、ASP.NET の Infragistics WebHierarchicalDataGrid コントロールで「列の自動サイズ変更」機能を実装しようとしています -Max(Header Width, Data Width)固定のヘッダー/ページャー位置を維持しながら、列は最も広い幅を取る必要があります)。

ありがとう!

4

2 に答える 2

2

DIV コンテンツを書き換えると、大量の再描画、CSS の適用、DOM 操作などがトリガーされます。

列のすべてのセルを一度に DIVに配置して、改行で区切るか、それぞれを独自のサブ DIV に配置してみてください。結果の DIV の幅は、最も長いセルの幅にする必要があります。

var html = [];
for (var Y = 0; Y < oDataTable.rows.length; Y++) {
    html.push(oDataTable.rows[Y].cells[0].innerHTML);
}

oDivSizer.innerHTML = html.join("<br />");
var iColWidth = Math.max(oDivSizer.offsetWidth, 1);

もう 1 つの可能性は、各セルの innerText に基づく単純なヒューリスティックです。

var iColWidth = 0;
for (var Y = 0; Y < oDataTable.rows.length; Y++) {
    var w = Math.floor(oDataTable.rows[Y].cells[0].innerText.length * 11.5);
    iColWidth = Math.max(w, iColWidth);
}

私の最後のコメントで示したように、さらに別の可能性は、最大の領域を消費する列の TDのみを再描画することです。

var a = 0;
var n = null;
for (var Y = 0; Y < oDataTable.rows.length; Y++) {
    var _a = oDataTable.rows[Y].cells[0].offsetHeight * oDataTable.rows[Y].cells[0].offsetWidth;
    if (Number(_a) > a) {
      a = _a;
      n = oDataTable.rows[Y].cells[0];
    }
}
oDivSizer.innerHTML = n.innerHTML;
var iColWidth = Math.max(oDivSizer.offsetWidth, 1);

または、さらに一歩進んで、計算された各セルの面積を、「意図的に」背の高いセルを考慮して見つかった BR の数で割ります。

var a = 0;
var n = null;
for (var Y = 0; Y < oDataTable.rows.length; Y++) {
    var _a = oDataTable.rows[Y].cells[0].offsetHeight * oDataTable.rows[Y].cells[0].offsetWidth;
    var brs = oDataTable.rows[Y].cells[0].getElementsByTagName('br');
    _a = Number(_a) / brs.length;
    if (_a > a) {
      a = _a;
      n = oDataTable.rows[Y].cells[0];
    }
}
oDivSizer.innerHTML = n.innerHTML;
var iColWidth = Math.max(oDivSizer.offsetWidth, 1);

ただし、ファジー アプローチの複雑さが増し、結果がより正確になるにつれて、パフォーマンスが低下することが予想されます。

補足として、この自動サイズ変更がユーザーの操作の結果として適用されている場合は、ユーザーが開始するのを待つのではなく、テーブルが分析可能になった直後にサイズ変更の計算/プロセスを実行することをお勧めしますサイズを変更します。

于 2012-12-13T18:30:43.933 に答える
0

デフォルトで、WebDataGrid は、列およびグリッド自体に幅が指定されていない場合、グリッドのコンテンツ領域をその内容に合わせてサイズ変更します。次に、ヘッダーのサイズがデータ部分に合わせられます。これは、グリッドがコンテナー内にあるかコンテナー外にあるかに関係なくうまく機能します。

グリッドのデータ部分のサイズが適切に設定されているため、グリッドの最初のセルの幅、またはヘッダー全体を表示するための測定値のいずれか大きい方に列のサイズを変更するだけです。次の JavaScript はこれを行います。

function resizeGrid(grid) {
    var textWidthChecker = document.getElementById('textWidthChecker');
    var columns = grid.get_columns();
    var widths = new Array(columns.get_length());
    var row = grid.get_rows().get_row(0);
    var newGridWidth = 0;
    for (var colIdx = 0; colIdx < columns.get_length(); colIdx++) {
        var col = columns.get_column(colIdx);
        textWidthChecker.innerHTML = col.get_headerText();
        var cellElement = row.get_cell(colIdx)._element;
        if (!col.get_hidden()) {
            if (textWidthChecker.offsetWidth > cellElement.offsetWidth) {
                // 8 for padding in header.
                newGridWidth += textWidthChecker.offsetWidth + 8;
                widths[colIdx] = textWidthChecker.offsetWidth + 8;
            } else {
                widths[colIdx] = cellElement.offsetWidth;
                newGridWidth += cellElement.offsetWidth;
            }
        }
    }
    newGridWidth += columns.get_length() * 16; // added for padding on cells
    var gridElement = grid.get_element();            
    gridElement.style.width = newGridWidth + 'px';
    for (var colIdx = 0; colIdx < columns.get_length(); colIdx++) {
        var col = columns.get_column(colIdx);
        col.set_width(widths[colIdx] + 'px');
    }
}

上記では、フォントのグリッドのヘッダーと同じ CSS クラスを使用してこれが機能するために、id が「textWidthChecker」のスパンが必要です。

<div style="height: 0px;overflow: hidden;" class="igg_HeaderCaption ig_Control">
    <span id="textWidthChecker"></span>
</div>

このアプローチは、ヘッダーのサイズが変更されたときにグリッドに対して十分な幅のコンテナー内にグリッドがある限り、クライアント側の Initialize メソッドから resizeGrid 関数が呼び出されたときにうまく機能します。

グリッドがより小さいコンテナにある場合、WebDataGrid が内部で幅を設定し、これが列のサイズに影響するため、これは失敗します。これを回避するには、resizeGrid 関数を先に呼び出す必要がありますが、このためのイベントはありません。

具体的には、_initializeObjects と _adjustGridLayout の呼び出しの間のグリッドの初期化関数中に、resizeGrid を呼び出す必要があります。これを行うには、WebDataGrid のプロトタイプを変更して、_adjustGridLayout を、resizeGrid を呼び出して元の _adjustGridLayout を呼び出す別のものに置き換えることができます。

var adjustGridLayoutFunction = $IG.WebDataGrid.prototype._adjustGridLayout;
$IG.WebDataGrid.prototype._originalAdjustGridLayout = adjustGridLayoutFunction;
$IG.WebDataGrid.prototype._adjustGridLayout = function () {
    resizeGrid(this);
    this._originalAdjustGridLayout();
}; 

プロトタイプを変更すると、ページ上のすべてのグリッドに影響することに注意してください。これを適用するグリッドを制御したい場合は、新しい _adjustGridLayout 関数に条件付きロジックを追加する必要があります。例えば:

if (this.get_id() == "WebDataGrid1")
    resizeGrid(this);

グリッド内でテキストが折り返されないようにするには、ItemStyle にも css を使用する必要があります。

.noWrapCellStyle {
    white-space: nowrap;
}

これを機能させるには、グリッドのコンテナーに目的の幅を設定し、グリッドの幅を空のままにする必要があります。

<div style="width:300px;overflow: auto;">
    <ig:WebDataGrid ID="WebDataGrid1" runat="server" Height="450px" AutoGenerateColumns="True" ItemCssClass="noWrapCellStyle">
    </ig:WebDataGrid>
</div>

行セレクターを使用している場合は、行セレクターを説明するために提供しているロジックで計算を更新する必要があります。

于 2013-02-20T19:14:26.503 に答える