【问题标题】:using nextUntil function to toggle specific table row使用 nextUntil 函数来切换特定的表格行
【发布时间】:2012-10-16 15:40:49
【问题描述】:

我有这个包含事件的表,单击它的图标(箭头)我创建新行(称为子事件),然后将其添加到当前行下。我想点击同一个图标来隐藏它的子事件,但只有他的。现在,如果我点击一个新事件(不同的行),它将切换每个隐藏的行,即使它们与当前行无关......

只是我试图强制获取某种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 函数将选择链接(childEvent)到我的 Row 变量而不是其他变量的所有('tr')。

如果您不了解 asp 或 mvc4,我不确定人们是否会更了解 hthml,但这里是:编辑 ::

<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>

我会尽量简化我所说的:

你有行。(事件)当你点击一行(事件)时,新的动态行出现在它下面(称为 ChildEvent)。

如果您第二次单击某行(事件),如果这些行存在于他之下,您将隐藏这些行,但前提是它们是 ChildEvent 类。

我当前的代码隐藏了桌子上的所有 ChildEvent,我只想隐藏点击的(事件)下的那些。

如果用户点击一个行(事件),它会显示(ChildEvent)如果它们存在,但只有与点击的行(事件)相关的(childEvent),而不是整个表的ChildEvent。

childEvent 只能在其相关事件下添加。

重新编辑:

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

这就是我想要的,以文字形式显示:切换我单击的那个下面的 tr,如果他们有 ChildEvent 类。测试直到你到达一个拥有 "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>

点击同一个事件

 <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>

点击一个新的事件:

<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>

点击另一个新的事件

<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>

【问题讨论】:

  • 请向我们展示相关的 HTML。我怀疑如果您向我们展示实际的 HTML,我们可以将您的代码减少到只有几行,因为看起来您的代码中有很多冗余,但是我们需要知道 HTML 和类的确切结构才能知道最好的建议.
  • 我对这句话感到困惑:"select all('tr") that are direct child of my Row variable and not the others." 你的Row 变量已经是父tr。那么,为什么要选择作为当前tr 子级的tr 对象呢?你有嵌入式表格吗?再说一遍,你能明白为什么我们需要查看你的 HTML 吗?
  • 如果您真的来这里是为了回答问题以更清楚地说明您想要什么,我可以在几分钟内回答这个问题。
  • 抱歉,这是晚餐休息时间。我的意思是逻辑子,不是html子(不是embed table,只是Row变量调用了ChildEvent,是自己下面添加的新行。
  • 以后,我建议您在一个小时内无法回答相关问题时不要发布问题。当您发布问题时,您应该在接下来的 30 分钟内进行检查,看看人们是否理解您的问题或需要帮助来理解它。超过 90% 的观众将在第一个小时内观看。如果问题在那个时间窗口内不清楚,您将失去大部分获得好答案的机会。我下面的回答有用吗?

标签: jquery


【解决方案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/


由于您似乎遇到了性能问题,这里有一个特殊用途的 nextUntil 版本,在这个 jsperf 中测量它的速度提高了 3 倍: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();

好的,这是我想在当前行中隐藏所有 .ChildEvent 对象的第三个猜测。由于您包含的 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 必须是什么。这并不容易,有时甚至是不可能的,而且肯定永远不会导致最好的解决方案。

【讨论】:

  • 这不起作用,我将slideup更改为slidetoggle,并且子行不响应(他们不关闭或打开)我将添加到html中,很难我怀疑它会告诉你很多,因为它在 asp 中并以不同的布局构建
  • @ThierrySavardSaucier - 发布您的 HTML。我们无法进一步猜测我们要解决什么问题。在你显示 HTML 之前,我已经尝试过 GUESS。
  • 我在测试后 2 秒添加了它。我只是花时间测试你的答案 1st...
  • @ThierrySavardSaucier - 我在答案的顶部做了另一个猜测。
  • @ThierrySavardSaucier - 您是否尝试使用 .hide() 而不是 .slideToggle().slideUp()?可能是你不能一次做那么多动画。
【解决方案2】:

我想继续工作会更容易,而不是我的主要问题是谁变得非常聚集......

$('.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 将出现,但之后如果我尝试单击其他任何内容,我会收到一个错误框,提示脚本已崩溃。

【讨论】:

  • 您不会将 jQuery 对象传递给 nextUntil - 您会传递选择器。我在我的答案中添加了另一个修订版。请看那个。
  • 从 jQuery 1.6 开始,可以将 DOM 节点或 jQuery 对象而不是选择器传递给 .nextUntil() 方法。这就是他们所说的,但这可能是导致崩溃的原因,因为它太慢以至于无法经常测试 jquery 吗?
  • 这不是你想要的。它会让它慢很多,慢很多。我在答案中的代码现在可以工作并且只使用选择器。您还必须将 HTML 中的类名修复为只有空格,它们之间没有逗号。
  • 是的,它们在我的代码中是正确的,我只是放了一个示例 html 并快速构建它而不是真正正确
猜你喜欢
  • 2023-04-06
  • 2013-04-05
  • 1970-01-01
  • 2020-11-21
  • 2011-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-11
相关资源
最近更新 更多