288 votes

Comment désactiver les liens HTML

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

J'ai essayé tout ce qui suit mais cela ne fonctionne pas sur Firefox (qui utilise les js 1.4.2) :

$(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 de manière dynamique. JE DOIS DONC AFFICHER LE LIEN EN MODE DÉSACTIVÉ.

0 votes

541voto

Adriano Repetti Points 22087

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

Méthode CSS

Cela devrait être la bonne façon (mais voir plus loin) pour le faire quand la plupart des navigateurs le supporteront :

a.disabled {
    pointer-events: none;
}

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

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

Avec :

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

Solution de rechange

Nous devons probablement définir une classe CSS pour pointer-events: none mais si nous réutiliser le site disabled au lieu d'une classe CSS ? À proprement parler disabled n'est pas pris en charge pour <a> mais les navigateurs ne se plaindront pas pour inconnu attributs. En utilisant le disabled IE ignorera l'attribut pointer-events mais il honorera l'IE spécifique disabled Les autres navigateurs conformes à la norme CSS ne tiendront pas compte de cet attribut. inconnu disabled attribut et honneur pointer-events . Plus facile à écrire qu'à expliquer :

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

Une autre option pour IE 11 est de définir display d'éléments de liaison à block ou inline-block :

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

Notez que cela peut être un portable solution si vous devez supporter IE (et vous pouvez changer votre HTML) mais...

Tout ceci étant dit, veuillez noter que pointer-events ne désactive que les événements liés aux pointeurs. Les liens seront toujours navigables au moyen du clavier alors vous devez également appliquer l'une des autres techniques décrites ici.

Focus

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

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

Je n'ai jamais vérifié sa compatibilité avec de nombreux navigateurs. Vous pouvez donc la tester vous-même avant de l'utiliser. Il a l'avantage de fonctionner sans JavaScript. Malheureusement (mais évidemment) tabindex ne peut être modifié à partir de CSS.

Clics d'interception

Utilisez un href à une fonction JavaScript, vérifier la condition (ou l'attribut désactivé lui-même) et ne rien faire dans ce cas.

$("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 voulez, au lieu de .is("[disabled]") vous pouvez utiliser .attr("disabled") != undefined (jQuery 1.6+ retournera toujours undefined lorsque l'attribut n'est pas défini) mais is() est beaucoup plus claire (merci à Dave Stewart pour cette astuce). Veuillez noter qu'ici j'utilise l'option disabled d'une manière non standard, si vous y tenez, remplacez l'attribut par une classe et l'attribut .is("[disabled]") avec .hasClass("disabled") (ajout et suppression avec addClass() et removeClass() ).

Zoltán Tamási a noté dans un commentaire que "dans certains cas, l'événement de clic est déjà lié à une fonction "réelle" (par exemple en utilisant knockoutjs). Dans ce cas, l'ordre des gestionnaires d'événements peut causer des problèmes. C'est pourquoi j'ai implémenté des liens désactivés en liant un gestionnaire de retour faux à la fonction touchstart , mousedown et keydown événements. Il a quelques inconvénients (il empêchera le défilement tactile commencé sur le lien)" mais le traitement des événements clavier a également l'avantage d'empêcher la navigation au clavier.

Notez que si href n'est pas autorisé, il est possible pour l'utilisateur de visiter manuellement cette page.

Effacer le lien

Effacer le href attribut. Avec ce code, vous n'ajoutez pas un gestionnaire d'événement 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 ne devez pas en faire plus avec les liens désactivés) mais elle mai être plus compatible en raison des différentes manières de suivre un lien.

Faux gestionnaire de clics

Ajouter/supprimer un onclick fonction 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.

Styling

Le style est encore plus simple, quelle que soit la solution que vous utilisez pour désactiver le lien, nous avons ajouté une balise disabled 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 UI, vous pouvez voir que désactivé les liens ne sont pas stylisés correctement. Bootstrap 3.x, par exemple, gère ce scénario et le bouton est correctement stylé à la fois avec disabled et avec l'attribut .disabled classe. Si, au contraire, vous effacez le lien (ou si vous utilisez l'une des autres techniques JavaScript), vous devez également gérer le style car une classe <a> sans href est toujours peint comme activé.

Applications Internet riches accessibles (ARIA)

N'oubliez pas d'inclure également un attribut aria-disabled="true" en même temps que disabled attribut/classe.

2 votes

C'est vrai. Mais pour une maintenance plus facile, j'ajouterais des gestionnaires d'événements de clics à toutes les td a qui pourraient être désactivés, ce qui appellera event.preventDefault() si $(this).data('disabled') est vrai, et ensuite mettre data('disabled', true) à tout lien que je veux désactiver (faux pour activer, etc.)

0 votes

Je dois également indiquer que le lien est désactivé. Ce n'est pas seulement que le clic ne doit pas fonctionner. Il doit être affiché comme désactivé. La balise d'ancrage est affichée désactivée sur IE mais pas sur Firefox.

1 votes

@Ankit Pour l'apparence, vous avez CSS ! Définissez une règle pour les liens 'désactivés' comme ceci a[disabled] { color : gray }.

24voto

Ankit Points 1447

J'ai trouvé le correctif en css.

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

Le code CSS ci-dessus, lorsqu'il est appliqué à la balise d'ancrage, désactive l'événement de clic.

Pour plus de détails, consultez ce site link

1 votes

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

0 votes

Il est pris en charge par tous les navigateurs

1 votes

Il ne devrait pas être supporté pour le HTML dans Internet Explorer et Opera.

12voto

kross Points 635

Grâce à tous ceux qui ont posté des solutions (en particulier @AdrianoRepetti), j'ai combiné plusieurs approches pour fournir des solutions plus avancées. disabled (et cela fonctionne dans tous les navigateurs). Le code est ci-dessous (à la fois ES2015 et coffeescript selon votre préférence).

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

  • cliquez sur
  • tabulateur à et appuyez sur retour
  • En cliquant dessus, le focus sera déplacé vers l'élément suivant.
  • il sait si l'ancre est activée ultérieurement

Comment

  1. Incluez cette css, car elle constitue la première ligne de défense. Cela suppose que le sélecteur que vous utilisez est a.disabled

    a.disabled {
      pointer-events: none;
      cursor: default;
    }
  2. Ensuite, instanciez cette classe sur ready (avec un 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

0 votes

Mais qu'en est-il si nous avons besoin d'une solution purement jQuery/javascript ? Voir ma réponse ci-dessous.

1 votes

Alors, utilisez la classe ES2015 que je viens d'ajouter !

7voto

Kees C. Bakker Points 7504

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 vouloir jouer le jeu. 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();
    }
});

Note : ajout d'une mention "live" pour les futurs liens désactivés/activés.
Note 2 : remplacement de "live" par "on".

6 votes

Le nouvel exemple devrait aussi fonctionner dans Firefox ;-) c'est un firefix :D

0 votes

Chrome empêche la navigation dans jsFiddle en raison du message "Refused to display document because display forbidden by X-Frame-Options". Désolé si l'exemple de jsfiddle fait des choses bizarres ;-)

0 votes

Je dois également indiquer que la balise d'ancrage est désactivée. Comme c'est le cas dans IE. De plus, je ne veux pas modifier la fonction de clic pour placer une vérification si elle est désactivée.

0voto

mkk Points 4071

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 et vous renvoyez false lorsque quelqu'un clique dessus. Pour les activer, il suffit de supprimer la classe.

0 votes

Cela ne m'aide pas. Je dois réenregistrer l'événement de clic et la fonction est dynamique qui est appelée. Une fois supprimée, je ne peux pas l'associer à nouveau

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X