使用Javascript类显示/隐藏表格行

17

我有一个表格,它可以展开和折叠,但使用起来变得太混乱了,而且IE和Firefox不能正常工作。

于是,这里是JavaScript代码:

  function toggle_it(itemID){ 
      // Toggle visibility between none and '' 
      if ((document.getElementById(itemID).style.display == 'none')) { 
            document.getElementById(itemID).style.display = '' 
            event.preventDefault()
      } else { 
            document.getElementById(itemID).style.display = 'none'; 
            event.preventDefault()
      }    
  } 

还有一个示例HTML:

<table>
    <tr>
        <td>Product</td>
        <td>Price</td>
        <td>Destination</td>
        <td>Updated on</td>
    </tr>
    <tr>
        <td>Oranges</td>
        <td>100</td>
        <td><a href="#" id="toggle" onClick="toggle_it('tr1');toggle_it('tr2')">+ On Store</a></td>
        <td>22/10</td>
    </tr>
    <tr id="tr1" style="display:none">
        <td></td>
        <td>120</td>
        <td>City 1</td>
        <td>22/10</td>
    </tr>
    <tr id="tr2" style="display:none">
        <td></td>
        <td>140</td>
        <td>City 2</td>
        <td>22/10</td>
    </tr>
    <tr>
        <td>Apples</td>
        <td>100</td>
        <td><a href="#" id="toggle" onClick="toggle_it('tr3');toggle_it('tr4')">+ On Store</a></td>
        <td>22/10</td>
    </tr>
    <tr id="tr3" style="display:none">
        <td></td>
        <td>120</td>
        <td>City 1</td>
        <td>22/10</td>
    </tr>
    <tr id="tr4" style="display:none">
        <td></td>
        <td>140</td>
        <td>City 2</td>
        <td>22/10</td>
    </tr>
</table>
问题是我对每个父元素使用一个ID,这非常令人烦恼,因为我想要为每个父元素设置许多隐藏行,并且有很多父元素,所以处理太多ID会很麻烦。而IE和FireFox只显示第一个隐藏的行,而不是其他的。我怀疑这是因为我已经通过同时触发所有ID来使其工作。
我认为如果我使用类来标识隐藏行会更好。
我对这一切都很陌生,请尽量用简单的方式解释。另外,我已经尝试过jQuery,但无法成功。
6个回答

21

虽然很难弄清楚你在这个样例中想做什么,但你考虑使用类(class)的思路是正确的。我创建了一个JSFiddle来演示一种稍微更好(希望如此)的方法。

这是fiddle链接:link

你需要做的是,不再使用ID,而是使用类(class)。在你的代码样例中,有橙子和苹果。我把它们看作是产品类别(因为我真的不知道你的目的是什么),具有自己的ID。因此,我用 class="cat1"class="cat2" 标记产品的。

我还用简单的 .toggler 类标记链接。在元素本身上使用onclick属性不是好习惯。您应该使用JavaScript在页面加载时“绑定”事件。我使用jQuery完成此操作。

$(".toggler").click(function(e){
    // you handle the event here
});
使用这种格式,您可以将事件处理程序绑定到具有类别为“toggler”的链接的click事件。在我的代码中,我添加了一个data-prod-cat属性到toggler链接,以指定它们应该控制哪些产品行。(我使用data-*属性的原因在此处解释。您可以通过搜索'html5 data attributes'了解更多信息。)
在事件处理程序中,我做了这个:
$('.cat'+$(this).attr('data-prod-cat')).toggle();

我正在尝试创建一个选择器,类似于$('.cat1'),以便可以选择特定产品类别的行,并更改它们的可见性。我使用$(this).attr('data-prod-cat')来访问用户单击链接时的data-prod-cat属性。我使用jQuery toggle函数,这样我就不必像在您的JS代码中那样编写逻辑,例如if visible, then hide element, else make it visible。jQuery会处理掉这个过程。toggle函数按照其名称切换指定元素的可见性。

希望这是足够解释了。


老兄,非常感谢!那正是我在寻找的东西! 它完美地运行了,甚至在其他浏览器中也是如此。我知道这很简单,但我不懂JavaScript,只懂一些html。我“编造”这个示例表格的原因是因为这段代码是为我们公司的网站(我正在制作)而编写的,没有必要使用实际的表格(带有大量css和其他东西),因为疑问只涉及该机制。再次感谢! - user2957683
我可以使用滑动效果而不是突然弹出吗?怎么做? - user2957683
这对我很有帮助,但我是在复选框上使用它,而不是链接文本。为了使其工作,我必须删除“e.preventDefault();”这一行。否则,复选框将无法选中。希望这能帮助到某些人! - nbardach

8

有一种方法可以做到这一点,就是在“父级”行上放置一个类,并删除所有id和内联 onclick 属性:

<table id="products">
    <thead>
    <tr>
        <th>Product</th>
        <th>Price</th>
        <th>Destination</th>
        <th>Updated on</th>
    </tr>
    </thead>
    <tbody>
    <tr class="parent">
        <td>Oranges</td>
        <td>100</td>
        <td><a href="#">+ On Store</a></td>
        <td>22/10</td>
    </tr>
    <tr>
        <td></td>
        <td>120</td>
        <td>City 1</td>
        <td>22/10</td>
    </tr>
    <tr>
        <td></td>
        <td>140</td>
        <td>City 2</td>
        <td>22/10</td>
    </tr>
    ...etc.
    </tbody>
</table>

然后使用一些CSS来隐藏所有非父级元素:

tbody tr {
    display : none;          // default is hidden
}
tr.parent {
    display : table-row;     // parents are shown
}
tr.open {
    display : table-row;     // class to be given to "open" child rows
}

这大大简化了你的html。请注意,我已经在你的标记中添加了<thead><tbody>以便于隐藏数据行并忽略标题行。

使用jQuery,您只需要这样做:

// when an anchor in the table is clicked
$("#products").on("click","a",function(e) {
    // prevent default behaviour
    e.preventDefault();
    // find all the following TR elements up to the next "parent"
    // and toggle their "open" class
    $(this).closest("tr").nextUntil(".parent").toggleClass("open");
});

演示:http://jsfiddle.net/CBLWS/1/

或者,要在纯JavaScript中实现类似的功能,可以尝试以下方法:

document.getElementById("products").addEventListener("click", function(e) {
    // if clicked item is an anchor
    if (e.target.tagName === "A") {
        e.preventDefault();
        // get reference to anchor's parent TR
        var row = e.target.parentNode.parentNode;
        // loop through all of the following TRs until the next parent is found
        while ((row = nextTr(row)) && !/\bparent\b/.test(row.className))
            toggle_it(row);
    }
});

function nextTr(row) {
    // find next sibling that is an element (skip text nodes, etc.)
    while ((row = row.nextSibling) && row.nodeType != 1);
    return row;
}

function toggle_it(item){ 
     if (/\bopen\b/.test(item.className))       // if item already has the class
         item.className = item.className.replace(/\bopen\b/," "); // remove it
     else                                       // otherwise
         item.className += " open";             // add it
}

示范: http://jsfiddle.net/CBLWS/

无论如何,将JavaScript放置在结束标签前的


1
谢谢你的帮助!我先尝试了vape的想法,结果非常好,不过还是感谢你的帮助! - user2957683

7

2
event.preventDefault()

不适用于所有浏览器。相反,您可以在OnClick事件中返回false。

onClick="toggle_it('tr1');toggle_it('tr2'); return false;">

不确定这是否是最佳方法,但我在IE、FF和Chrome上测试过了,它能正常工作。


返回 false 而不是使用 event.preventDefault() 可能更好,但使用 onclick 属性绝对不是更好的做法。(另外,我不确定 event.preventDefault() 在所有浏览器中是否都有效。它应该有效。jQuery 在几乎所有主要浏览器上都可以工作。如果您必须支持旧版本的 IE [如 7、8、9],则可以使用带有 jQuery 迁移的 1.9.+ 版本) - Taylan Aydinli
@vape - 如果使用纯JS,preventDefault()在旧版IE上肯定不起作用,但是当您使用jQuery事件绑定时,jQuery(和其他库)会为所有浏览器实现它。如果您正在使用v1.x,则无需使用jQuery迁移来支持旧版IE。 - nnnnnn
@nnnnn 我知道如果使用纯JS,preventDefault在旧浏览器上不起作用。但是如果我没记错的话,jQuery的preventDefault增强了本地JS preventDefault方法,并使其与旧浏览器兼容。另外,据我所知,如果您正在使用jQuery 1.9.x,则需要jQuery migrate来支持旧版IE,如jQuery 1.9升级指南[http://jquery.com/upgrade-guide/1.9/]中所述。当然,我可能是错的,其中一些或全部内容 :) - Taylan Aydinli
是的,jQuery以多种方式增强了本地“事件”对象,使其跨浏览器保持一致,包括为所有浏览器提供“preventDefault()”。但您绝对不需要迁移插件。1.x版本支持旧版IE。2.x版本不支持。(您可能需要迁移插件的情况是,如果您使用旧版本的jQuery并升级到1.9+,因为在该版本中删除了几个先前弃用的功能,迁移插件可以将它们放回。) - nnnnnn
谢谢提供信息。我原以为1.9.x版本也会破坏与旧版IE的兼容性,需要使用迁移插件。看来我错了 :) - Taylan Aydinli
谢谢大家,我按照vape所说的做了,完美地解决了问题。感谢你们的帮助。我对Stack Overflow感到惊讶,这么快就有这么多答案! - user2957683

2
以下是我的脚本,它可以显示/隐藏ID为“agencyrow”的表格行。
<script type="text/javascript">

                        function showhiderow() {
                            if (document.getElementById("<%=RadioButton1.ClientID %>").checked == true) {

                                document.getElementById("agencyrow").style.display = '';
                            } else {

                                document.getElementById("agencyrow").style.display = 'none';
                            }


                        }
    </script> 

只需在单选按钮onClick事件上调用函数showhiderow()


你的回答中为什么有一个ASP标签? - AaA

0

AngularJS指令ng-show、ng-hide允许显示和隐藏一行:

   <tr ng-show="rw.isExpanded">
   </tr>

当rw.isExpanded == true时,该行将可见;当rw.isExpanded == false时,该行将隐藏。 ng-hide执行相同的任务,但需要相反的条件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接