如何禁用HTML链接

329

我有一个链接按钮在 <td> 中,我必须将其禁用。这在IE上可以工作,但在Firefox和Chrome上不起作用。

我尝试了以下所有方法,但在Firefox上无法工作(使用1.4.2的js):

$(".myLink").attr('disabled', 'disabled');

$(".myLink").attr('disabled', true);

$(".myLink").attr('disabled', 'true');

注意-我无法取消注册锚标记的点击函数,因为它是动态注册的。而且我必须以禁用模式显示链接。


仅使用CSS的问题:https://dev59.com/G3I95IYBdhLWcg3w7CnL - Ciro Santilli OurBigBook.com
16个回答

607

您无法以可移植的方式禁用链接。您可以使用以下技术之一(每种技术都有其自身的优缺点)。

CSS 方式

当大多数浏览器支持它时,这应该是正确的方式(但稍后请参见):

a.disabled {
    pointer-events: none;
}

比如,Bootstrap 3.x就是这样做的。目前(2016年),它只有在Chrome、FireFox和Opera(19+)中得到良好的支持。Internet Explorer从版本11开始支持此功能,但不适用于链接,但可以在外部元素中使用,例如:

span.disable-links {
    pointer-events: none;
}

使用:

<span class="disable-links"><a href="#">...</a></span>

解决方法

我们可能需要为pointer-events: none定义一个CSS类,但如果我们重用disabled属性而不是CSS类会怎样呢?严格来说,<a>不支持disabled,但浏览器不会对未知属性抱怨。使用disabled属性,IE将忽略pointer-events,但它将尊重IE特定的disabled属性;其他符合CSS的浏览器将忽略未知disabled属性并尊重pointer-events。比解释更容易写:

a[disabled] {
    pointer-events: none;
}

对于IE 11,另一个选择是将链接元素的display设置为blockinline-block

<a style="pointer-events: none; display: inline-block;" href="#">...</a>

请注意,如果您需要支持IE(且可以更改HTML),则这可能是一种可移植的解决方案,但……
所有这些说法请注意,pointer-events仅禁用……指针事件。 链接仍然可以通过键盘进行导航,那么您还需要应用此处描述的其他技术之一。

焦点

与上述CSS技术相结合,您可以以非标准的方式使用tabindex来防止元素被聚焦:
<a href="#" disabled tabindex="-1">...</a>

我从未检查过它与许多浏览器的兼容性,因此在使用之前您可能希望自行测试。它的优点是可以在没有JavaScript的情况下工作。不幸的是(但显然)tabindex无法从CSS更改。

拦截点击事件

使用href到JavaScript函数,检查条件(或禁用属性本身),并在这种情况下什么也不做。

$("td > a").on("click", function(event){
    if ($(this).is("[disabled]")) {
        event.preventDefault();
    }
});

禁用链接,请执行以下操作:

$("td > a").attr("disabled", "disabled");

重新启用它们:
$("td > a").removeAttr("disabled");

如果你想使用 .is("[disabled]") 的替代方法,你可以使用 .attr("disabled") != undefined(jQuery 1.6+ 在属性未设置时始终返回 undefined),但是 is() 更加清晰易懂(感谢 Dave Stewart 提供的提示)。请注意,这里我在非标准方式下使用了 disabled 属性,如果您关心此事,请将属性替换为类,并使用 .hasClass("disabled") 替换 .is("[disabled]")(使用 addClass()removeClass() 添加和删除)。

Zoltán Tamási 在评论中指出“在某些情况下,点击事件已经绑定到一些‘真实’函数上(例如使用knockoutjs)。在这种情况下,事件处理程序的顺序可能会引起一些麻烦。因此,我通过将一个返回false的处理程序绑定到链接的touchstartmousedownkeydown事件来实现禁用链接。它有一些缺点(它将防止在链接上开始的触摸滚动)”,但处理键盘事件也有防止键盘导航的好处。

请注意,如果没有清除href,用户仍然可以手动访问该页面。

清除链接

清除href属性。使用此代码,您不会添加事件处理程序,而是更改链接本身。使用此代码禁用链接:

$("td > a").each(function() {
    this.data("href", this.attr("href"))
        .attr("href", "javascript:void(0)")
        .attr("disabled", "disabled");
});

这个用来重新启用它们:

$("td > a").each(function() {
    this.attr("href", this.data("href")).removeAttr("disabled");
});

个人而言,我不太喜欢这种解决方案(如果您与无效链接没有更多关联),但它可能更兼容,因为有各种方式可以跟踪链接。

虚假点击处理程序

添加/删除一个onclick函数,在其中return false,链接将不会被跟踪。要禁用链接:

$("td > a").attr("disabled", "disabled").on("click", function() {
    return false; 
});

要重新启用它们:

$("td > a").removeAttr("disabled").off("click");

我认为没有理由选择这种解决方案而不是第一个。

样式

样式甚至更简单,无论你使用什么解决方案来禁用链接,我们都添加了disabled属性,因此您可以使用以下CSS规则:

a[disabled] {
    color: gray;
}

如果您使用的是类而不是属性:
a.disabled {
    color: gray;
}

如果您正在使用用户界面框架,您可能会发现禁用链接的样式不正确。例如,Bootstrap 3.x可以处理此场景,并且按钮在具有disabled属性和.disabled类时都正确地进行了样式设置。相反,如果您清除了链接(或使用其他JavaScript技术之一),则还必须处理样式,因为没有href<a>仍然被绘制为启用状态。

可访问的富互联网应用程序(ARIA)

不要忘记在disabled属性/类别中同时包含一个aria-disabled="true"属性。

2
没错。但为了更方便的维护,我会给所有可能被禁用的 td a 添加点击事件处理程序,如果 $(this).data('disabled') 为真,则调用 event.preventDefault(),然后将 data('disabled', true) 设置为任何我想要禁用的链接(false 表示启用,等等)。 - ori
1
@Ankit 对于外观,你可以使用 CSS!设置一个对“禁用”链接生效的规则,例如:a[disabled] { color: gray }。 - Adriano Repetti
3
Jon,我不太喜欢它。首先因为键盘导航仍然可以使用。其次,因为这是一种技巧(只有在没有其他方法可用时才可能有用)。第三,因为有些人禁用了Javascript,在这种情况下您就没有任何“保护”级别。第四,因为这是最复杂的解决方案(很少的Javascript代码行可能会起作用)。 - Adriano Repetti
1
我同意@AdrianoRepetti的观点。我的下面的答案本质上是Adriano提出的方法的编码版本。Adriano的方法考虑了所有可能性并且效果很好。 - kross
1
pointer-events: none; 添加到 CSS 中,以及 cursor: not-allowed 或任何光标都将无效。 - vee
显示剩余10条评论

25

已经在 CSS 中进行了修复。

td.disabledAnchor a{
       pointer-events: none !important;
       cursor: default;
       color:Gray;
}

应用以上CSS到锚点标签上将禁用点击事件。

有关详细信息,请查看此链接


1
这是一个不错的解决方案,但是它不被支持...猜猜看...Internet Explorer。 - Adriano Repetti
1
在Internet Explorer和Opera中不应支持HTML。 - Adriano Repetti
@Ankit,它在IE 9及以下版本中无法工作。你使用的是IE 10吗? - Mandeep Jain
简单但是不太正规。如果你需要使用 !important,那么你的 CSS 写得不对。请看下面我的回答!而且我的方法在所有浏览器中都可以运行,包括旧版 IE! - Jon Crawford
5
正如Adriano Repetti上面提到的,这不能满足键盘事件的使用情况。用户仍然可以通过Tab键定位到链接并按Enter键。 - cage rattler
显示剩余2条评论

13

感谢所有发布解决方案的人(特别是@AdrianoRepetti),我结合了多种方法来提供一些更高级的disabled功能(它可以跨浏览器工作)。以下是代码(基于您的喜好,包括ES2015和coffeescript)。

这提供了多层防御,以便标记为禁用的锚点实际上就是禁用的。使用此方法,您可以获得一个无法执行以下操作的锚点:

  • 点击
  • 通过键盘 tab 键选中并按回车键
  • 通过键盘 tab 键选中后会将焦点移动到下一个可聚焦元素上
  • 它知道如果随后启用了该锚点

如何实现

  1. 将以下 CSS 包含在首行作为第一道防线。假定您使用的选择器是 a.disabled

    a.disabled {
      pointer-events: none;
      cursor: default;
    }
    
  2. 接下来,在ready事件中实例化该类(带可选选择器):

  3.   new AnchorDisabler()
    

ES2015类

npm install -S key.js

import {Key, Keycodes} from 'key.js'

export default class AnchorDisabler {
  constructor (config = { selector: 'a.disabled' }) {
    this.config = config
    $(this.config.selector)
      .click((ev) => this.onClick(ev))
      .keyup((ev) => this.onKeyup(ev))
      .focus((ev) => this.onFocus(ev))
  }

  isStillDisabled (ev) {
    //  since disabled can be a class or an attribute, and it can be dynamically removed, always recheck on a watched event
    let target = $(ev.target)
    if (target.hasClass('disabled') || target.prop('disabled') == 'disabled') {
      return true
    }
    else {
      return false
    }
  }

  onFocus (ev) {
    //  if an attempt is made to focus on a disabled element, just move it along to the next focusable one.
    if (!this.isStillDisabled(ev)) {
      return
    }

    let focusables = $(':focusable')
    if (!focusables) {
      return
    }

    let current = focusables.index(ev.target)
    let next = null
    if (focusables.eq(current + 1).length) {
      next = focusables.eq(current + 1)
    } else {
      next = focusables.eq(0)
    }

    if (next) {
      next.focus()
    }
  }

  onClick (ev) {
    // disabled could be dynamically removed
    if (!this.isStillDisabled(ev)) {
      return
    }

    ev.preventDefault()
    return false
  }

  onKeyup (ev) {
    // We are only interested in disabling Enter so get out fast
    if (Key.isNot(ev, Keycodes.ENTER)) {
      return
    }

    // disabled could be dynamically removed
    if (!this.isStillDisabled(ev)) {
      return
    }

    ev.preventDefault()
    return false
  }
}

Coffeescript类:

class AnchorDisabler
  constructor: (selector = 'a.disabled') ->
    $(selector).click(@onClick).keyup(@onKeyup).focus(@onFocus)

  isStillDisabled: (ev) =>
    ### since disabled can be a class or an attribute, and it can be dynamically removed, always recheck on a watched event ###
    target = $(ev.target)
    return true if target.hasClass('disabled')
    return true if target.attr('disabled') is 'disabled'
    return false

  onFocus: (ev) =>
    ### if an attempt is made to focus on a disabled element, just move it along to the next focusable one. ###
    return unless @isStillDisabled(ev)

    focusables = $(':focusable')
    return unless focusables

    current = focusables.index(ev.target)
    next = (if focusables.eq(current + 1).length then focusables.eq(current + 1) else focusables.eq(0))

    next.focus() if next


  onClick: (ev) =>
    # disabled could be dynamically removed
    return unless @isStillDisabled(ev)

    ev.preventDefault()
    return false

  onKeyup: (ev) =>

    # 13 is the js key code for Enter, we are only interested in disabling that so get out fast
    code = ev.keyCode or ev.which
    return unless code is 13

    # disabled could be dynamically removed
    return unless @isStillDisabled(ev)

    ev.preventDefault()
    return false

但是如果我们需要一个纯jQuery / javascript的解决方案呢?请看下面我的答案。 - Jon Crawford
1
那么,你可以使用我刚刚添加的ES2015类! - kross

8

尝试使用该元素:

$(td).find('a').attr('disabled', 'disabled');

在Chrome中,禁用链接对我有效:http://jsfiddle.net/KeesCBakker/LGYpz/

但是Firefox似乎不太好用。这个示例可以正常工作:

<a id="a1" href="http://www.google.com">Google 1</a>
<a id="a2" href="http://www.google.com">Google 2</a>

$('#a1').attr('disabled', 'disabled');

$(document).on('click', 'a', function(e) {
    if ($(this).attr('disabled') == 'disabled') {
        e.preventDefault();
    }
});

注意:添加了一个“live”语句,以便将来禁用/启用链接。
注意2:将“live”更改为“on”。

6
新的示例应该也能在Firefox中正常工作。;-) 它是一个火狐浏览器 :D - Kees C. Bakker
Chrome因“Refused to display document because display forbidden by X-Frame-Options.”而阻止在jsFiddle中导航。如果jsfiddle示例出现异常,请见谅;-) - Kees C. Bakker
我必须将锚点显示为禁用状态,就像在IE中显示的那样。此外,我不想修改单击函数以放置检查是否已禁用。 - Ankit
展示部分可以通过CSS和添加使其变灰的类来完成。'live'点击的优点是您将为所有链接解决问题。如果我能提供更多帮助,请告诉我。希望您成功。 - Kees C. Bakker
尝试使用我下面的答案,以获得完全跨浏览器的解决方案! - Jon Crawford

6

Bootstrap 4.1提供了一个名为disabled的类和aria-disabled="true"属性。

例子:

<a href="#" 
        class="btn btn-primary btn-lg disabled" 
        tabindex="-1" 
        role="button" aria-disabled="true"
>
    Primary link
</a>

更多内容在getbootstrap.com上

如果您想要实现动态按钮,而且不需要关心它是按钮还是锚点,在JS脚本中你需要像这样写:

   let $btn=$('.myClass');
   $btn.attr('disabled', true);
   if ($btn[0].tagName == 'A'){
        $btn.off();
        $btn.addClass('disabled');
        $btn.attr('aria-disabled', true);
   }

但要注意

该解决方案仅适用于带有类别为btn btn-link的链接。

有时Bootstrap建议使用card-link类,在这种情况下,该解决方案将无法工作


1
使用Bootstrap是现代的方式(当它被使用时),所以我点赞这个! - Fumisky Wells

6

只需添加一个CSS属性:

<style>   
a {
 pointer-events: none;
}
</style>

这样做可以禁用锚标记。


2
我最终得出了下面的解决方案,它可以与属性 <a href="..." disabled="disabled"> 或类 <a href="..." class="disabled"> 一起使用:
CSS 样式:
a[disabled=disabled], a.disabled {
    color: gray;
    cursor: default;
}

a[disabled=disabled]:hover, a.disabled:hover {
    text-decoration: none;
}

JavaScript(在jQuery准备好后):
$("a[disabled], a.disabled").on("click", function(e){

    var $this = $(this);
    if ($this.is("[disabled=disabled]") || $this.hasClass("disabled"))
        e.preventDefault();
})

1
您可以按照以下方式禁用HTML链接:

<style>
    .disabled-link {
        pointer-events: none;
    }
</style>
<a href="https://google.com" class="disabled-link">Google.com</a>

您可以使用内联JavaScript:

<a href="javascript:void(0)">Google.com</a>

1
在Razor(.cshtml)中,您可以这样做:

@{
    var isDisabled = true;
}

<a href="@(isDisabled ? "#" : @Url.Action("Index", "Home"))" @(isDisabled ? "disabled=disabled" : "") class="btn btn-default btn-lg btn-block">Home</a>

0

禁用触摸设备上的链接以访问另一页:

if (control == false)
  document.getElementById('id_link').setAttribute('href', '#');
else
  document.getElementById('id_link').setAttribute('href', 'page/link.html');
end if;

我的答案也适用于移动设备。非常跨浏览器。请参见下文。 - Jon Crawford
如果您使用setAttribute('href', '');,并且页面的URL为http://example.com/page/?query=something,则在IE11上单击链接时,链接将跳转到http://example.com/page/。解决方法是使用setAttribute('href', '#'); - Marco Demaio

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