0

イベントを含むこのテーブルがあり、そのアイコン (矢印) をクリックすると、新しい行 (子イベントと呼ばれます) が作成され、現在の行の下に追加されます。同じアイコンをクリックして子イベントを非表示にしたいのですが、彼だけです。現在、新しいイベント(別の行)をクリックすると、現在の行に関連していなくても、すべての非表示の行が切り替わります...

単純に、ある種のUntilNextを強制的に取得しようとしていますが、その機能を機能させることができません.atmを実行している単純なループでは、oneEventをスキップしますが、すべての子行をトリガーし、必要なものではありません.

$('.JSONArrow').on("click", function () {

    var image = $(this);
    var Row = image.closest("tr");

    Row.toggleClass("Opened");

    if (Row.hasClass("Opened")) {

        image.attr("src", "/Images/downArrow.png")

        if (!(Row.hasClass("alreadyOpen"))) {
            var id = image.attr("id");

            $.get("/Home/Child/" + id, function (data) {
                Row.after(data);
                Row.addClass("alreadyOpen");
            });
        }
    } else {
        image.attr("src", "/Images/rightArrow.png");
    }

    var tr = Row.nextAll('tr');

    for (i = 0; i < tr.length; i++) {
        var eventClass = $(tr[i]).attr('class');
        if (eventClass == 'ChildEvent')
            $(tr[i]).slideToggle()
        else {
            if (eventClass == 'oneEvent')
                return;
        }
    }
});

子行でのみ動作するように nextUntil を作成するのは簡単なものでなければなりませんが、jquery docによると、これまでのところ管理していません。

   var tr = Row.nextUntil('tr',$(".oneEvent"));

    for (i = 0; i < tr.length; i++) {
        var eventClass = $(tr[i]).attr('class');
        if (eventClass == 'ChildEvent'){
            $(tr[i]).slideToggle()
        }
    }

しかし、私はそれを機能させることができません。誰もがそれを行う方法を指摘するか、私が知らない別の jquery 関数を使用して、Row 変数にリンクされている (childEvent) すべて ('tr") を選択し、他の変数は選択しません。

aspまたはmvc4を知らない場合、人々がhthmlをもっと理解するかどうかはわかりませんが、ここに行きます:EDIT ::

<div class="TableHolder">
    <table id="mainTable">
        <thead> 
            <tr class="header">

                <th class="iconColumn">Child</th>

                <th>Date </th>
                .... other <th>
                </th>
        </tr>
    </thead>

            @Html.EditorFor(x => x.logs)

 </table>

そして、それは言うごとのテーブル行です:

     string dynamicClass = "";
if (Model.Parent == null )
{
    dynamicClass = "oneEvent";
}
else 
{  
    dynamicClass = "ChildEvent";
}

}

  <tr class="@dynamicClass">

      <td class="iconColumn">
        @if (Model.Parent == null )
        {
            <img class="JSONArrow" id="@Model.EventID" src="~/Images/rightArrow.png"/>
        }
    </td>

    <td>@Model.TimeUTC.ToString("dddd, dd MMMM yyyy")<br />@Model.TimeUTC.ToString("HH:mm:ss") </td>
    .... other column

</tr>

私が言及していることを単純化しようとします:

行があります。(Event) 行 (Event) をクリックすると、新しい動的行がその下に表示されます (ChildEvent と呼ばれます)。

行 (イベント) をもう一度クリックすると、その下に行が存在する場合は行が非表示になりますが、それは ChildEvent クラスの場合のみです。

私の現在のコードは、テーブル上のすべての ChildEvent を非表示にします。クリックされた (イベント) の下にあるものだけを非表示にしたいと考えています。

ユーザーが行 (イベント) をクリックして戻すと、存在する場合は (ChildEvent) が表示されますが、クリックされた行 (イベント) に関連する (childEvent) のみが表示され、テーブル全体の ChildEvent は表示されません。

childEvent は、関連する Event の下にのみ追加できます。

再編集:

     row.nextUntil(".oneEvent", ".ChildEvent").slidetoggle();

これは私が望んでいることです。ChildEvent クラスがある場合は、クリックしたものの下にある tr を切り替えます。クラス「oneEvent」を持つtrに到達するまでテストします。

どのパラメーターがどこに行くのか理解できません。

再再編集:

<table>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
</table>

クリック時:

 <table>
  <tr class="oneEvent, Opened, alreadyOpened"></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
</table>

同じ oneEvent をクリックします

 <table>
  <tr class="oneEvent, alreadyOpened"></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
</table>

新しい oneEvent をクリックします。

<table>
  <tr class="oneEvent, alreadyOpened"></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
  <tr class="oneEvent, Opened, alreadyOpened"></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>
</table>

別の新しい oneEvent をクリックします

<table>
  <tr class="oneEvent, alreadyOpened"></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
  <tr class=oneEvent></tr>
  <tr class="oneEvent, Opened, alreadyOpened"></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
  <tr class="oneEvent, Opened, alreadyOpened"></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>

前のイベントをクリックして戻します。

<table>
  <tr class="oneEvent, alreadyOpened"></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
  <tr class=oneEvent></tr>
  <tr class="oneEvent, Opened, alreadyOpened"></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
  <tr class="oneEvent, alreadyOpened"></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>

最初の OneEvent をクリックします。

<table>
  <tr class="oneEvent, Opened, alreadyOpened"></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
  <tr class=oneEvent></tr>
  <tr class="oneEvent, Opened, alreadyOpened"></tr>
   <tr class=ChildEvent display = true></tr>
   <tr class=ChildEvent display = true></tr>
  <tr class="oneEvent, alreadyOpened"></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
   <tr class=ChildEvent display = false></tr>
  <tr class=oneEvent></tr>
  <tr class=oneEvent></tr>

4

2 に答える 2

1

うん。あなたが求めているものを確認するのに十分な HTML があります。これが私が提案するものです:

$('.JSONArrow').on("click", function () {
    var row = $(this).closest("tr");
    if (row.hasClass("Opened")) {
        // click on an already opened row
        this.src = "/Images/rightArrow.png";
        row.removeClass("Opened");
        // close all following .ChildEvent rows until you get to the next .oneEvent
        row.nextUntil(".oneEvent", ".ChildEvent").slideUp();
    } else {
        // click on a closed row
        this.src = "/Images/downArrow.png";
        row.addClass("Opened");
        // if not previously opened, then add the child HTML
        if (!row.hasClass("alreadyOpened")) {
            $.get("/Home/Child/" + this.id, function(data) {
                row.after(data);
                row.addClass("alreadyOpened");
            });
        } else {
            // show all following .ChildEvent rows until you get to the next .oneEvent
            row.nextUntil(".oneEvent", ".ChildEvent").slideDown();
        }
    }
});

HTML も修正する必要があります。HTML に複数のクラス名を入れるときは、コンマではなくスペースでクラス名を区切ります。実際のデモについては、こちらを参照してください。

http://jsfiddle.net/jfriend00/ZkvgN/


パフォーマンスの問題があるようですので、この jsperf で測定して 3 倍高速な nextUntil の特別な目的のバージョンを次に示します: http://jsperf.com/nextuntilfast

jQuery.fn.nextUntilFast = function(untilClass) {
    // for speed reasons, this operates only on the 
    // first DOM object in the jQuery object
    var result = [], cur;
    if (this.length) {
        cur = this[0];
        while (cur = cur.nextSibling) {
            // check elements only
            if (cur.nodeType === 1) {
                if ($(cur).hasClass(untilClass)) {
                    break;
                } else {
                    result.push(cur);
                }
            }
        }
    }
    return this.pushStack(result, "nextUntilFast", untilClass);
};

これを次のように置き換えて使用します。

 row.nextUntil(".oneEvent", ".ChildEvent").slideDown();

これとともに:

 row.nextUntilFast("oneEvent").slideDown();

.ChildEventOK、これが現在の行のすべてのオブジェクトを非表示にしたいという私の 3 番目の推測です。含めた HTML には.ChildEventオブジェクトが含まれていないため、これも推測です。

Row.find(".ChildEvent").slideToggle();

HTML が含まれていないため、この問題を正確に解決する方法を知ることは困難です。

あなたの質問を約 20 回読んだ後 (明確な質問に答えることができないため)、これがあなたが何を求めているかについての私の最善の推測です。関数のコードの最後のブロックでやりたいことが、クリックがあった場所の後にある行をスライドアップすることであり、 の行を含まない場合、次の.oneEventコードでそれを行うことができます:

 Row.nextUntil(".oneEvent", ".ChildEvent").slideUp();

.oneEventは、兄弟要素の一致を停止する場所を示します。は、その.ChildEventセレクターに一致しないアイテムを結果から削除するフィルターです。.oneEventこれにより、次のすべての行がその行まで (ただし含まれていない) 表示され.ChildEvent、上にスライドされます。すでに閉じている場合は、閉じたままになります。本当にトグルが必要な場合.slideToggle()は、元のコードと同じように使用できますが、実際に行っているのは他の行の折りたたみであると推測していました。

これは、コードの改訂版になります。

$('.JSONArrow').on("click", function () {
    var row = $(this).closest("tr");
    if (row.hasClass("Opened")) {
        this.src = "/Images/rightArrow.png";
        row.removeClass("Opened");
    } else {
        this.src = "/Images/downArrow.png";
        row.addClass("Opened");
        // if not previously opened, then add the child HTML
        if (!row.hasClass("alreadyOpen")) {
            $.get("/Home/Child/" + this.id, function(date) {
                row.after(data);
                row.addClass("alreadyOpen");
            });
        }
    }

    // now close all the following rows up to .oneEvent
    row.nextUntil(".oneEvent", ".ChildEvent").slideUp();
});

これは、あなたが助けを必要としているものの最初の推測でした...

ドキュメント内のすべての領域ではなく、クリックが発生したのと同じ領域にクリック アクションが適用される一般的な方法は、次のアルゴリズムです。

$(this).closest("parent container selector").find("target selector").action()

.closest()適切な親コンテナーを見つけるために使用します。.find()このコンテナー内にあるセレクターに一致するオブジェクトを検索するために使用します。

コンテナー内のすべてのアイテムに何かを適用する場合は、上位のコンテナー セレクター (テーブル全体など) を選択します。このリージョンだけに何かを適用したい場合は.closest()、直近のリージョンにのみ適用される呼び出しのコンテナー セレクターを選択します。次に.find()、選択した地域のターゲットを識別します。このようにして、任意のスコープの子オブジェクトのみをターゲットにすることができます。

たとえば、クリックが発生したときに同じ行のセレクターに一致するすべてのアイテムにアクションを適用するには、次のようにします。

$(this).closest("tr").find("target selector").action()

より具体的なコードについては、HTML を質問に追加してください。ご存じのように、コードを見て HTML がどうあるべきかを判断するよう私たちに求めています。それは簡単なことではなく、時には不可能であり、可能な限り最善の解決策につながることは決してありません.

于 2012-10-15T15:45:15.093 に答える
0

かなりクラスター化している私の主な質問の代わりに、これから作業を続ける方が簡単だと思います...

$('.JSONArrow').on("click", function () {

    var image = $(this);
    var Row = image.closest("tr");

    Row.toggleClass("Opened");

    if (Row.hasClass("Opened")) {

        image.attr("src", "/Images/downArrow.png")

        if (!(Row.hasClass("alreadyOpen"))) {
            var id = image.attr("id");

            $.get("/Home/Child/" + id, function (data) {
                Row.after(data);
                Row.addClass("alreadyOpen");
            });
        }
    } else {
        image.attr("src", "/Images/rightArrow.png");
    }

    Row.nextUntil($(".oneEvent"), $(".ChildEvent")).slideToggle();
});

私はそれをそのように動作させました。しかし、たくさんのchildEventを持つoneEvent trを開くと、ブラウザをクラッシュさせるスクリプトエラーが発生します。chilldEvent が表示されますが、その後他のものをクリックしようとすると、スクリプトがクラッシュしたというエラー ボックスが表示されます。

于 2012-10-15T18:11:35.410 に答える