6

jQuery を使用して階層テーブルの行を展開/折りたたむ効率的な方法を探しています。問題は、展開と折りたたみの機能が異なることです。

  • 最初は、クラスのある行のみlevel_0が表示され、他のすべての行は非表示になります。
  • expand は次のレベルのみを表示する必要があるため、行をクリックすると、行id=10のみが表示さid=11id=14ます。
  • 一方、 collapseは、現在のレベルよりも深いレベルで連続するすべての行を折りたたむ必要があります。たとえば、行の折りたたみをクリックすると、表示されている場合id=10、 ids11, 12, 13, 14の行が非表示になります。

テーブル データは次のようになります。

<table id="mytable">
    <tr class="level_0" id="10">...</td>
    <tr class="level_1 parent_10" id="11">...</td>
    <tr class="level_2 parent_11" id="12">...</td>
    <tr class="level_2 parent_11" id="13">...</td>
    <tr class="level_1 parent_10" id="14">...</td>
    <tr class="level_0" id="15">...</td>
</table>

私の動かない解決策:

$('#mytable tr').live('click', function() {
  var toggleClass = 'parent_' + $(this).attr('id');
  $(this).nextAll('tr').each(function() {
    if ($(this).is('.'+toggleClass)) {
      $(this).toggleClass("showme");
    }
  });
});

問題は、次のレベルの行のみを折りたたむことです。クリックされた行の下に表示されている、より深いレベルの行は引き続き表示されます。


効率的な方法でこれを行う方法について、誰かがヒントを教えてくれますか? 必要に応じて、HTML コードを調整できます。

ヒントをありがとう。

4

3 に答える 3

2

投稿のテーブル html が無効です (tr は td で囲まれています)。適切に構造化されたテーブルでは、このコードは機能します。

$("tr.level_0").live("click", function () {
  $(this).nextUntil(".level_0").toggle();
});
于 2011-02-13T08:44:50.040 に答える
0

閉じた状態と開いた状態の両方ですべての行のクリックを処理できるように、もう少しコードが必要になると思います。

行が開いていることを示すクラス スイッチを追加し、その状態に基づいてクリックを異なる方法で処理しました。との両方collapseexpandwhile ループがあり、クリックされた行の直後の行から順に行をウォークスルーし、同じレベルの行に到達すると停止します。このロジックは、0 だけでなく、どのレベルでも機能するはずです。また、派手なセレクターを使用したロジックをwhile使用すると、おそらくループがよりクリーンになる可能性がありますnextUntil。Jules の回答を見るまで、その jQuery メソッドに精通していませんでした。

また、このサンプル コードをよりシンプルにするために、レベル クラスの命名システムを HTML データ属性として扱ったので、特定の行は次のようになります<tr data-level="0" id="10">。への呼び出しを.dataコードに置き換えて、クラス名を解析できます。

var $rows = $('#mytable tr');

$rows.live('click', function() {
$(this).toggleClass('open');

if ($this.hasClass('open')){
    collapse($(this));
} else {
    expand($this);
}
}

function collapse ($row) {
    $row.removeClass('open');
var rowIndex = $rows.index($row);
var siblingOrAncestorRowFound = false;

while (!siblingOrAncestorRowFound){
    var $nextRow = $rows.eq(rowIndex + 1);
    if ($nextRow.level  > $row.level){
        $nextRow.hide().removeClass('open');
        rowIndex++;
    } else {
        siblingOrAncestorRowFound = true;
    }
}
}

function expand ($row) {
    $row.addClass('open')
var rowIndex = $rows.index($row);
var siblingOrAncestorRowFound = false;

while (!siblingOrAncestorRowFound){
    var $nextRow = $rows.eq(rowIndex + 1);
    if ($nextRow.level  > $row.level){

        // only show rows exactly one level below
        if ($nextRow.level == $row.level + 1){
            $nextRow.show();
        }

        rowIndex++;
    } else {
        siblingOrAncestorRowFound = true;
    }
}
}

(これはテストされていません - ごめんなさい!)

于 2011-02-15T04:48:39.213 に答える
0

別の質問への回答として、階層の複数レベルのバージョンを作成しました。

テーブルの jQuery は次のようになります。

var treeTable = {
    parentClassPrefix : '',
    collapsedClass : 'collapsed',
    init : function(parentClassPrefix) {
        this.parentClassPrefix = parentClassPrefix;
        $('table').on('click', 'tr', function () { 
            treeTable.toggleRowChildren($(this));
        });
    },
    toggleRowChildren : function(parentRow) {
        var childClass = this.parentClassPrefix+parentRow.attr('id');
        var childrenRows = $('tr', parentRow.parent()).filter('.'+childClass);
        childrenRows.toggle();
        childrenRows.each(function(){
            if (!$(this).hasClass(treeTable.collapsedClass)) {
                treeTable.toggleRowChildren($(this));
            }
        });
        parentRow.toggleClass(this.collapsedClass);
    }
};

treeTable.init('parent_');

動作については、このJSFiddleを参照してください。

最適化

検索をより効率的にするために、親と子を指定することを含む、少し異なるテーブル構造があります。

次に、そこからGist を切り替える jQuery 階層テーブル行を作成し、それを最適化されたオブジェクト化された JavaScript に変換しました。最適化はhttp://24ways.org/2011/your-jquery-now-with-less-suck/から来ています。

具体的には:

行ではなくテーブルでのイベント委任。

$('table').on('click', 'tr.'+treeTable.parentClass, function () {
    treeTable.toggleRowChildren($(this));
});

子の選択をキャッシュします。

.childClass でより高速な要素セレクターを使用し、その後に低速なフィルターを使用します。

var childrenRows = $('tr', parentRow.parent()).filter('.'+childClass);
于 2014-01-27T17:03:12.483 に答える