Comment désactiver les liens HTML


263

J'ai un bouton de lien à l'intérieur d'un <td>que je dois désactiver. Cela fonctionne sur IE mais ne fonctionne pas sur Firefox et Chrome. La structure est - Lien à l'intérieur d'un <td>. Je ne peux pas ajouter de conteneur dans <td>(comme div / span)

J'ai essayé tout ce qui suit mais ne fonctionnais pas sur Firefox (en utilisant 1.4.2 js):

$(td).children().each(function () {
        $(this).attr('disabled', 'disabled');
  });


  $(td).children().attr('disabled', 'disabled');

  $(td).children().attr('disabled', true);

  $(td).children().attr('disabled', 'true');

Remarque - Je ne peux pas désenregistrer la fonction de clic pour la balise d'ancrage car elle est enregistrée dynamiquement. ET JE DOIS MONTRER LE LIEN EN MODE HANDICAPÉ.


Réponses:


510

Vous ne pouvez pas désactiver un lien (de manière portable). Vous pouvez utiliser l'une de ces techniques (chacune avec ses propres avantages et inconvénients).

Manière CSS

Cela devrait être la bonne façon (mais voir plus loin) de le faire lorsque la plupart des navigateurs le prendront en charge:

a.disabled {
    pointer-events: none;
}

C'est ce que fait, par exemple, Bootstrap 3.x. Actuellement (2016), il est bien pris en charge uniquement par Chrome, FireFox et Opera (19+). Internet Explorer a commencé à prendre en charge cela à partir de la version 11, mais pas pour les liens, mais il est disponible dans un élément externe comme:

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

Avec:

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

solution de contournement

Nous devons probablement définir une classe CSS, pointer-events: nonemais que faire si nous réutilisons l' disabledattribut au lieu d'une classe CSS? À proprement parler, ce disabledn'est pas pris en charge, <a>mais les navigateurs ne se plaindront pas d' attributs inconnus . L'utilisation de l' disabledattribut IE ignorera pointer-eventsmais il honorera l' disabledattribut spécifique IE ; les autres navigateurs compatibles CSS ignoreront les attributs et l'honneur inconnus . Plus facile à écrire qu'à expliquer:disabledpointer-events

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

Une autre option pour IE 11 consiste à définir displaydes éléments de lien vers blockou inline-block:

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

Notez que cela peut être une solution portable si vous devez prendre en charge IE (et vous pouvez changer votre HTML) mais ...

Tout cela dit, veuillez noter que pointer-eventsne désactive que ... les événements de pointeur. Les liens seront toujours navigables via le clavier, vous devez également appliquer l'une des autres techniques décrites ici.

Concentrer

En conjonction avec la technique CSS décrite ci-dessus, vous pouvez utiliser tabindexde manière non standard pour empêcher la focalisation d'un élément:

<a href="#" disabled tabindex="-1">...</a>

Je n'ai jamais vérifié sa compatibilité avec de nombreux navigateurs, alors vous voudrez peut-être le tester par vous-même avant de l'utiliser. Il a l'avantage de fonctionner sans JavaScript. Malheureusement (mais évidemment) tabindexne peut pas être changé depuis CSS.

Intercepter les clics

Utilisez a hrefpour une fonction JavaScript, vérifiez la condition (ou l'attribut désactivé lui-même) et ne faites rien au cas où.

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

Pour désactiver les liens, procédez comme suit:

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

Pour les réactiver:

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

Si vous le souhaitez, .is("[disabled]")vous pouvez utiliser .attr("disabled") != undefined(jQuery 1.6+ retournera toujours undefinedlorsque l'attribut n'est pas défini) mais is()est beaucoup plus clair (merci à Dave Stewart pour cette astuce). Veuillez noter ici que j'utilise l' disabledattribut d'une manière non standard, si vous vous souciez de cela, remplacez l'attribut par une classe et remplacez .is("[disabled]")par .hasClass("disabled")(en ajoutant et en supprimant avec addClass()et removeClass()).

Zoltán Tamási a noté dans un commentaire que "dans certains cas, l'événement click est déjà lié à une fonction" réelle "(par exemple en utilisant knockoutjs) Dans ce cas, la commande du gestionnaire d'événements peut causer des problèmes. faux gestionnaire à l'lien touchstart, mousedownet les keydownévénements. il a quelques inconvénients (elle permet d' éviter le défilement tactile a commencé sur le lien) » , mais la gestion des événements de clavier a également l'avantage d'éviter la navigation du clavier.

Notez que s'il hrefn'est pas effacé, il est possible que l'utilisateur visite manuellement cette page.

Supprimer le lien

Effacez l' hrefattribut. Avec ce code, vous n'ajoutez pas de gestionnaire d'événements mais vous modifiez le lien lui-même. Utilisez ce code pour désactiver les liens:

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

Et celui-ci pour les réactiver:

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

Personnellement, je n'aime pas beaucoup cette solution (si vous n'avez pas à en faire plus avec les liens désactivés) mais elle peut être plus compatible en raison des différentes manières de suivre un lien.

Gestionnaire de faux clics

Ajoutez / supprimez une onclickfonction où vous return false, le lien ne sera pas suivi. Pour désactiver les liens:

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

Pour les réactiver:

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

Je ne pense pas qu'il y ait une raison de préférer cette solution à la première.

Coiffant

Le style est encore plus simple, quelle que soit la solution que vous utilisez pour désactiver le lien, nous avons ajouté un disabledattribut afin que vous puissiez utiliser la règle CSS suivante:

a[disabled] {
    color: gray;
}

Si vous utilisez une classe au lieu d'un attribut:

a.disabled {
    color: gray;
}

Si vous utilisez un cadre d'interface utilisateur, vous pouvez constater que les liens désactivés ne sont pas correctement stylisés. Bootstrap 3.x, par exemple, gère ce scénario et le bouton est correctement stylisé à la fois avec disabledattribut et avec .disabledclasse. Si, au lieu de cela, vous effacez le lien (ou utilisez l'une des autres techniques JavaScript), vous devez également gérer le style car un <a>sans hrefest toujours peint comme activé.

Applications Internet riches accessibles (ARIA)

N'oubliez pas d'inclure également un attribut aria-disabled="true"avec l' disabledattribut / classe.


2
Droite. Mais pour une maintenance plus facile, j'ajouterais des gestionnaires d'événements de clic à tous les td as qui pourraient être désactivés, qui appelleront event.preventDefault()si $(this).data('disabled')est vrai, puis définirais data('disabled', true)sur n'importe quel lien que je veux désactiver (false pour activer, etc.)
ori

1
@Ankit Pour l'apparence, vous avez CSS! Définissez une règle pour les liens "désactivés" comme celui-ci a [désactivé] {couleur: gris}
Adriano Repetti

1
Mise à jour rapide sur la prise en charge du navigateur . Remarque même si IE11 supporte pointer-events, il y a une petite friandise qui dit qu'il ne fonctionne pas sur les liens: (...
août

1
$(this).is('[disabled]')pourrait être une meilleure façon de détecter l'attribut désactivé
Dave Stewart

2
Jon, je n'aime pas trop ça. Tout d'abord parce que la navigation au clavier fonctionne toujours. Ensuite parce que c'est un truc (eux ça ne peut être utile que si rien d'autre ne marche). Troisièmement parce que certaines personnes gardent Javascript désactivé et dans ce cas, vous n'avez aucun "niveau" de protection. Quatrièmement parce que c'est la solution la plus compliquée ici (lorsque quelques lignes Javascript peuvent fonctionner)
Adriano Repetti

23

Vous avez le correctif dans CSS.

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

Au-dessus de css lorsqu'il est appliqué à la balise d'ancrage, l'événement de clic sera désactivé.

Pour plus de détails, consultez ce lien


1
C'est une bonne solution mais elle n'est pas prise en charge par ... devinez ... Internet Explorer.
Adriano Repetti

Il est pris en charge par tous les navigateurs
Ankit

1
Il ne devrait pas être pris en charge pour HTML dans Internet Explorer et Opera.
Adriano Repetti

@Ankit, cela ne fonctionne pas dans IE 9 et les versions antérieures. Utilisez-vous IE 10?
Mandeep Jain

4
Cela échoue au cas d'utilisation des événements de clavier comme Adriano Repetti le mentionne ci-dessus. L'utilisateur peut toujours accéder au lien et appuyer sur Entrée.
crotale de cage

12

Merci à tous ceux qui ont publié des solutions (en particulier @AdrianoRepetti), j'ai combiné plusieurs approches pour fournir des disabledfonctionnalités plus avancées (et cela fonctionne sur plusieurs navigateurs). Le code est ci-dessous (ES2015 et coffeescript en fonction de vos préférences).

Cela fournit plusieurs niveaux de défense afin que les ancres marquées comme désactivées se comportent réellement comme telles. En utilisant cette approche, vous obtenez une ancre que vous ne pouvez pas:

  • Cliquez sur
  • tabulation et appuyez sur retour
  • tabuler pour déplacer le focus vers l'élément focusable suivant
  • il sait si l'ancrage est activé par la suite

Comment

  1. Incluez ce CSS, car il s'agit de la première ligne de défense. Cela suppose que le sélecteur que vous utilisez esta.disabled

    a.disabled {
      pointer-events: none;
      cursor: default;
    }
  2. Ensuite, instanciez cette classe sur ready (avec le sélecteur optionnel):

      new AnchorDisabler()

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

Classe Coffescript:

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

Mais que faire si nous avons besoin d'une solution jQuery / javascript simple? Voir ma réponse ci-dessous.
Jon Crawford

1
Eh bien, vous utilisez la classe ES2015 que je viens d'ajouter!
kross

7

Essayez l'élément:

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

La désactivation d'un lien fonctionne pour moi dans Chrome: http://jsfiddle.net/KeesCBakker/LGYpz/ .

Firefox ne semble pas bien jouer. Cet exemple fonctionne:

<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();
    }
});

Remarque: ajout d'une déclaration «en direct» pour les futurs liens désactivés / activés.
Note2: changé «live» en «on».


6
Le nouvel exemple devrait également fonctionner dans Firefox. ;-) c'est un correctif: D
Kees C. Bakker

Chrome empêche la navigation dans jsFiddle en raison de "Refus d'afficher le document car l'affichage est interdit par X-Frame-Options". Désolé si l'exemple jsfiddle fait des choses étranges ;-)
Kees C. Bakker

Je dois également montrer la balise d'ancrage comme désactivée. Identique à celui montré dans IE. De plus, je ne veux pas modifier la fonction de clic pour vérifier si elle est désactivée
Ankit

La partie show peut être effectuée par css et en ajoutant une classe qui la rend grisée. L'avantage du clic «en direct» est que vous réglerez le problème pour tous les liens. Si je peux vous aider davantage, faites le moi savoir. J'espère que vous réussirez.
Kees C. Bakker

Essayez ma réponse ci-dessous pour une solution entièrement cross browser!
Jon Crawford

4

Bootstrap 4.1 fournit une classe nommée disabledet un aria-disabled="true"attribut.

exemple"

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

Plus d'informations sur getbootstrap.com

Donc, si vous voulez le faire dynamiquement, et you don't want to care if it is button or ancorque dans le script JS, vous avez besoin de quelque chose comme ça

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

Mais attention

La solution ne fonctionne que sur les liens avec les classes btn btn-link.

Parfois, bootstrap recommande d'utiliser la card-linkclasse, dans ce cas, la solution ne fonctionnera pas .


1

Je me suis retrouvé avec la solution ci-dessous, qui peut fonctionner avec un attribut <a href="..." disabled="disabled">ou une classe <a href="..." class="disabled">:

Styles CSS:

a[disabled=disabled], a.disabled {
    color: gray;
    cursor: default;
}

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

Javascript (dans jQuery ready):

$("a[disabled], a.disabled").on("click", function(e){

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

0

vous ne pouvez pas désactiver un lien, si vous voulez que l' événement de clic ne doit pas tirer alors simplement Removele actionde ce lien.

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

Pour plus d'informations: - Éléments pouvant être désactivés


1
Cela ne désactive pas vraiment le lien. L'élément d'ancrage se déclenchera toujours, même s'il restera sur la même page.
Florian Margaine

0

Je ferais quelque chose comme

$('td').find('a').each(function(){
 $(this).addClass('disabled-link');
});

$('.disabled-link').on('click', false);

quelque chose comme ça devrait fonctionner. Vous ajoutez une classe pour les liens que vous souhaitez désactiver, puis vous retournez false lorsque quelqu'un clique dessus. Pour les activer, supprimez simplement la classe.


Cela n'aiderait pas. Je dois réenregistrer l'événement click et la fonction est dynamique qui est appelée. Une fois retiré, je ne peux plus l'associer
Ankit

0

Pour désactiver le lien pour accéder à une autre page sur l'appareil tactile:

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

Ma réponse fonctionne aussi sur mobile. Navigateur très croisé. Voir ci-dessous.
Jon Crawford

C'est faux, si vous setAttribute('href', '');et l'URL de la page sont http://example.com/page/?query=somethingle lien lorsque vous cliquez sur IE11, vous iriez http://example.com/page/. Une solution de contournement pourrait être d'utilisersetAttribute('href', '#');
Marco Demaio

0

Dans Razor (.cshtml), vous pouvez faire:

@{
    var isDisabled = true;
}

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

-2

Vous pouvez l'utiliser pour désactiver l'hyperlien d'asp.net ou les boutons de lien en html.

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

-2

Il y a une autre voie possible, et celle que j'aime le plus. Fondamentalement, c'est la même manière que la lightbox désactive une page entière, en plaçant un div et en jouant avec z-index. Voici des extraits pertinents d'un de mes projets. Cela fonctionne dans tous les navigateurs !!!!!

Javascript (jQuery):

var windowResizer = function(){
        var offset = $('#back').offset();   
        var buttontop = offset.top;
        var buttonleft = offset.left;
        $('#backdisabler').css({'top':buttontop,'left':buttonleft,'visibility':'visible'});
        offset = $('#next').offset();
        buttontop = offset.top;
        buttonleft = offset.left;
        $('#nextdisabler').css({'top':buttontop,'left':buttonleft,'visibility':'visible'});
}

$(document).ready(function() {
    $(window).resize(function() {   
        setTimeout(function() {
            windowResizer();
        }, 5); //when the maximize/restore buttons are pressed, we have to wait or it will fire to fast
    });
});

et en html

<a href="" id="back" style="float: left"><img src="images/icons/back.png" style="height: 50px; width: 50px" /></a>
<a href="" id="next" style="float: right"><img src="images/icons/next.png" style="height: 50px; width: 50px" /></a>
<img id="backdisabler" src="images/icons/disabled.png" style="visibility: hidden; position: absolute; padding: 5px; height: 62px; width: 62px; z-index: 9000"/>
<img id="nextdisabler" src="images/icons/disabled.png" style="visibility: hidden; position: absolute; padding: 5px; height: 62px; width: 62px; z-index: 9000"/>

Ainsi, le resizer trouve les emplacements de l'ancre (les images ne sont que des flèches) et place le désactivateur sur le dessus. L'image du désactivateur est un carré gris translucide (changez la largeur / hauteur des désactiveurs dans le html pour correspondre à votre lien) pour montrer qu'il est désactivé. Le flottant permet à la page de se redimensionner dynamiquement, et les désactivateurs emboîteront le pas dans windowResizer (). Vous pouvez trouver des images appropriées via google. J'ai placé le CSS pertinent en ligne pour plus de simplicité.

puis basé sur une condition,

$('#backdisabler').css({'visibility':'hidden'});
$('#nextdisabler').css({'visibility':'visible'});

4
N'a pas rétrogradé, mais je suppose: trop de frais généraux pour une chose simple, votre code n'est pas suffisamment commenté pour une réponse sur SO. C'est aussi beaucoup de hacky, je ne l'utiliserais pas personnellement.
Emile Bergeron

-5

Je pense que beaucoup d’entre eux sont trop réfléchis. Ajoutez une classe de tout ce que vous voulez, comme disabled_link.
Ensuite, faites en sorte que le CSS ait .disabled_link { display: none }
Boom maintenant, l'utilisateur ne peut pas voir le lien, vous n'aurez donc pas à vous soucier qu'il clique dessus. S'ils font quelque chose pour satisfaire le lien étant cliquable, il suffit de supprimer la classe avec jQuery:
$("a.disabled_link").removeClass("super_disabled"). Boum fait!


De la question: "ET JE DOIS MONTRER LE LIEN EN MODE HANDICAPÉ."
Marcelo

Ouais, tu as raison. J'ai manqué ça. Donc, je dirais plutôt, déplacez la valeur href vers data-href $("td a").each(function(i,v){ $(this).data('href',this.href); $(this).attr('href','#').css('color','grey'); });Ensuite, lorsque vous voulez en désactiver une: $(this).attr('href',$(this).data('href')).css('color','blue');
Jordan Michael Rushing
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.