【问题标题】:Click Entire Row (preserving middle click and ctrl+click)单击整行(保留中间单击和 ctrl+单击)
【发布时间】:2023-04-02 12:33:01
【问题描述】:

我有一个 HTML 表格,第一列中有一个链接。我想允许用户单击行中的任意位置来激活该链接。同时,我想保留打开新选项卡/窗口的中键单击和 ctrl+单击功能。这是一个表格的例子:

<table id="row_link"> 
  <tbody> 
    <tr>
      <td><a href="link1.html">link</a></td> 
      <td>info 1</td> 
    </tr>       
    <tr>
      <td><a href="link2.html">link</a></td> 
      <td>info 2</td> 
    </tr>       
  </tbody> 
</table> 

使用 jQuery 我可以让用户在一行中的任意位置左键单击:

$("table#row_link tbody tr").click(function () {
    window.location = $(this).find("a:first").attr("href");
});

这当然会禁用打开新选项卡的标准中键单击和 ctrl+单击功能。有没有更好的方法让用户点击整行,同时保留标准的中间点击和 ctrl+clcik 行为?

【问题讨论】:

    标签: javascript jquery events


    【解决方案1】:

    不幸的是,没有办法在每个浏览器中模拟链接和所有相关行为。因此,实现您想要的唯一方法是在&lt;tr&gt; 元素周围有一个跟随光标的链接;这个链接是不可见的,所以对于用户来说,看起来他们正在点击&lt;tr&gt;,但他们实际上是在点击一个隐藏的链接。使用该方法,中键、ctrl+click等任何行为都保持原样!

    这是一个演示:http://jsbin.com/ufugo

    这是代码:

    $("table tr").each(function(){
    
        var $link = $('a:first', this).clone(true),
            dim = {
                x: [
                    $(this).offset().left,
                    $(this).offset().left + $(this).outerWidth()
                ],
                y: [
                    $(this).offset().top,
                    $(this).offset().top + $(this).outerHeight()
                ]
            }
    
        $link
            .click(function(){
                $(this).blur();
            })
            .css({
                position: 'absolute',
                display: 'none',
                // Opacity:0  means it's invisible
                opacity: 0
            })
            .appendTo('body');
    
        $(this).mouseover(function(){
            $link.show();
        });
    
        $(document).mousemove(function(e){
            var y = e.pageY,
                x = e.pageX;
            // Check to see if cursor is outside of <tr>
            // If it is then hide the cloned link (display:none;)
            if (x < dim.x[0] || x > dim.x[1] || y < dim.y[0] || y > dim.y[1]) {  
                return $link.hide();
            }
            $link.css({
                top: e.pageY - 5,
                left: e.pageX - 5
            })
        });
    
    });
    

    编辑:

    我使用比上面更好的方法创建了一个 jQuery 插件:http://james.padolsey.com/javascript/table-rows-as-clickable-anchors/

    【讨论】:

    • 很棒的插件,它确实提高了示例代码的性能(对于更大的表)!我遇到了一个小问题,在速度较慢的计算机上,当我在桌子上快速移动鼠标时,即使鼠标不再悬停在行上,行仍然突出显示。
    • 我能够通过将 tr mouseover 事件传输到 $targetLink 来解决此问题,类似于您对 mouseout 事件所做的事情。之后,我使用 $targetLink.show(); 绑定到 tr mouseover 事件
    • 伟大的修复布赖恩!谢谢!我已将其添加到插件中。
    • 这很聪明。我喜欢这个想法,但是现在您无法选择任何表格数据是一个问题。 +1 虽然。
    • @Pim,常规锚点也是如此。可惜没有妥协。
    【解决方案2】:

    编辑

    这是一个简单的问题,有一个简单的解决方案。我认为不需要可能会在某些浏览器上中断或需要处理时间的讨厌的黑客攻击。尤其是因为有一个简洁易用的 CSS 解决方案。

    首先是demo

    @Nick solution 的启发,我提出了一个简单的 css+jquery 解决方案。

    首先,这是我编写的迷你插件。该插件将使用链接包装每个单元格:

    jQuery.fn.linker = function(selector) {
        $(this).each(function() {
            var href = $(selector, this).attr('href');
            if (href) {
                var link = $('<a href="' + $(selector, this).attr('href') + '"></a>').css({
                    'text-decoration': 'none',
                    'display': 'block',
                    'padding': '0px',
                    'color': $(this).css('color')
                })
                $(this).children()
                       .css('padding', '0')
                       .wrapInner(link);
            }
        });
    };
    

    这是一个用法示例:

    $('table.collection tr').linker('a:first');
    

    还有你需要的所有 CSS:

    table.collection {
        border-collapse:collapse;
    }
    

    就这么简单。


    您可以使用事件对象来检查鼠标点击类型。这个article 正在讨论一个类似的问题。

    无论如何,这里是如何做到的:

    $("table#row_link tbody tr").click(function () {
    
        if((!$.browser.msie && e.button == 0) || ($.browser.msie && e.button == 1)){
            if (!e.ctrlKey) {
                // Left mouse button was clicked without ctrl
                window.location = $(this).find("a:first").attr("href");
            }
        }
    });
    

    【讨论】:

    • 感谢文章参考。这让我大部分时间到达我想要的地方。我唯一的问题是,在鼠标中键或 ctrl+click 的情况下,我使用 window.open($(this).find("a:first").attr("href")); 打开一个新窗口。 ,将焦点放在新窗口上。我想专注于当前窗口,以便用户可以打开多个选项卡,每个选项卡对应于表中的行。谢谢你的帮助。
    • 小心未定义的变量。由于 $().each 中的 href 和 link 没有用 'var' 定义,它们将是全局的。因此,您可能会在以前的迭代中遇到 href 或 link 值的奇怪错误。
    【解决方案3】:

    我将从 HTML/css 方面对此进行攻击。当大多数网站都在表格中进行所有布局时,这曾经是一个常见问题。

    首先将所有表格单元格的内容做成链接。如果您不希望它们看起来像链接,您可以使用 CSS 从“非链接”单元格中删除下划线。但它们将是链接,这在语义上是你想要的。

    接下来,您要使链接展开以填充整个单元格。 StackOverflow 已经知道answer to this

    td a { display: block; width: 100%; height: 100%; line-height: 100%; }

    对于一个单元格之间没有空格的典型表格,整行都是可点击的。而且由于这不依赖于任何技巧或特定于浏览器的 hack,它应该可以在任何地方使用。

    【讨论】:

    • 完全同意;绝对比所有其他选项更干净。
    【解决方案4】:

    你想要这个:

    $('table#row_link tbody tr').mousedown( function(e){
        if(e.ctrlKey || (!$.browser.msie && e.button == 1) || ($.browser.msie && e.button == 4)){
            //middle mouse button or ctrl+click
        } else {
            //normal left click
        }
    });
    

    这是在 FF3.0.10、Chrome 1.0 和 IE6 中测试的。我使用 mousedown 事件是因为 firefox 或 IE 都没有将鼠标中键单击传递给 .click(fn) 事件。

    【讨论】:

    • 这让我大部分时间都在我想要的地方(只是快速说明你在 if 语句的末尾缺少一个右括号。我唯一的问题是在鼠标中间或ctrl+click case 我使用 window.open($(this).find("a:first").attr("href")); 打开一个新窗口,它将焦点放在新窗口上。我想保留关注当前窗口,以便用户可以打开多个选项卡,每个选项卡对应于表中的行。感谢您的帮助。
    【解决方案5】:

    您可以抓取该事件并查看它的事件代码。但是没有真正的方法可以知道浏览器对这些事件的行为。

    【讨论】:

      【解决方案6】:

      您可以创建一个链接,让它在您的 tr 中浮动,等待 mouveover 事件,更新 href 和位置

      创建一个像素链接

      <table id="row_link">....</table>
      <a id="onepixel" style="position:absolute;z-index:1000;width:1px;height:1px;"></a>
      

      鼠标悬停时更新href和位置

      $("#row_link tr").mouseover(
         function(event){
            //update href
            $("#onepixel").attr("href",$(this).find("a:first").attr("href"));
            //update position, just move to current mouse position
            $("#onepixel").css("top",event.pageY).css("left",event.pageX);
         }
      );
      

      【讨论】:

        【解决方案7】:

        下面是一些应该起作用的东西:我们不使用 window.location,而是使用 .click() 来模拟对元素内部的第一个点击。另外,使用条件来检查 CTRL+Click.

        应该是这样的:

        $("table#row_link tbody tr").click(function (e) {
            if(e.ctrlKey) { 
                // Run Ctl+Click Code Here
            } else { 
                $(this).children('a').eq(0).click(); 
            }
        }
        

        希望这会有所帮助!

        戴夫·罗梅罗

        【讨论】:

          【解决方案8】:

          尝试将 a 放在 td 周围,然后将 display:block CSS 元素应用于 td。

          这应该使 td 的整个区域都可以点击所有按钮作为“正常”链接。

          举个例子可能更好:

          <table id="row_link"> 
            <tbody> 
              <tr>
                <a href="link1.html"><td style="display: block;">link</td></a> 
                <td>info 1</td> 
              </tr>       
              <tr>
                <a href="link2.html"><td style="display: block;">link</td></a>
                <td>info 2</td> 
              </tr>       
            </tbody> 
          </table>
          

          过去我也曾采用过类似的方法,尽管它并不完全适用于表格元素。未经表格测试,请尝试一下。

          【讨论】:

          • 刚刚意识到也许您希望两个 TD 在行中都可以点击。我的建议仅适用于包含实际锚点的特定 TD。我想您仍然可以将相同的概念应用于 TR 而不是 TD。只需将 A 移到 TR 外,使其“包围”它。
          • ...显然现在将 display: 块应用到 TR。而不是 TD。
          • 是的,为什么不呢?如上所述,我没有机会对其进行测试,但由于该方法适用于其他元素,为什么不试一试。
          • 语义上应该是正确的。在使用 Javascript 走捷径之前,我总是尝试找到一个纯 HTML/CSS 解决方案。
          【解决方案9】:

          我认为biggerlink plugin 会满足您的要求。这里是

          【讨论】:

            【解决方案10】:

            你需要去掉

            标签

            并且只使用'href'属性来获取链接目标,不要选择锚标签,因为那包含href属性。

            $("table#row_link tbody tr a").click(function () {
            
                 window.location = $(this).attr("href");
            
            });
            

            或者只是让链接打开一个新标签。

            希望对你有帮助。

            【讨论】:

            • 感谢您的想法,但是,这仅允许用户单击实际链接,而不是行中的任何位置。另外我不确定为什么删除 tbody 标签会有所帮助。
            猜你喜欢
            • 2018-07-22
            • 2015-01-26
            • 1970-01-01
            • 2013-07-31
            • 2021-12-07
            • 2013-04-11
            • 2011-05-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多