使用nextUntil函数来切换特定的表行

时间:2012-10-15 15:38:13

标签: jquery

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

简单地说我试图强制获得某种类型的UntilNext,但是我无法使该功能起作用,并且我正在做简单的循环,它会跳过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函数,它将选择所有('tr“)链接(childEvent)到我的Row变量而不是其他。

如果你不知道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>

我会尝试简化我的想法:

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

如果您在行(事件)上第二次单击,则隐藏行(如果它们存在于他下面),但仅限于它们是ChildEvent类。

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

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

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

重新编辑:

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

这就是我想要的文本:如果他们有ChildEvent类,那么切换我点击的那个人。测试直到你到达一个拥有“oneEvent”类的tr。

我只是不能确定哪些参数在哪里。

rererereedit:

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

点击新的一个事件:

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

2 个答案:

答案 0 :(得分: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次问题之后(因为你不在回答澄清问题),这是我对你问的最好的猜测。如果您要对函数中的最后一个代码块执行的操作是对任何位于单击之后的行进行slideUp并且不包含.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必须是什么。这并不容易,有时也不可能,当然也绝不会带来最好的解决方案。

答案 1 :(得分: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会出现,但之后如果我尝试点击其他任何内容,我会收到一个错误框,说明脚本已经崩溃。