Come disabilitare i collegamenti HTML


263

Ho un pulsante di collegamento all'interno di un <td>che devo disabilitare. Funziona su IE ma non funziona su Firefox e Chrome. La struttura è - Collegamento all'interno di a <td>. Non riesco ad aggiungere alcun contenitore nel <td>(come div / span)

Ho provato tutto quanto segue ma non funziona su Firefox (usando 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');

Nota: non riesco a annullare la registrazione della funzione clic per il tag di ancoraggio poiché è registrato dinamicamente. E DEVO MOSTRARE IL LINK IN MODALITÀ DISATTIVATA.


Risposte:


510

Non è possibile disabilitare un collegamento (in modo portatile). È possibile utilizzare una di queste tecniche (ognuna con i propri vantaggi e svantaggi).

Modo CSS

Questo dovrebbe essere il modo giusto (ma vedi più avanti) di farlo quando la maggior parte dei browser lo supporterà:

a.disabled {
    pointer-events: none;
}

È ciò che fa Bootstrap 3.x, ad esempio. Attualmente (2016) è ben supportato solo da Chrome, FireFox e Opera (19+). Internet Explorer ha iniziato a supportarlo dalla versione 11 ma non per i collegamenti, tuttavia è disponibile in un elemento esterno come:

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

Con:

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

Soluzione

Probabilmente abbiamo bisogno di definire una classe CSS per, pointer-events: nonema cosa succede se riutilizziamo l' disabledattributo anziché una classe CSS? A rigor di termini disablednon è supportato, <a>ma i browser non si lamentano di attributi sconosciuti . L'uso disableddell'attributo IE ignorerà pointer-eventsma onorerà l' disabledattributo specifico di IE ; altri browser conformi a CSS ignoreranno l' attributo e l'onore sconosciuti . Più facile da scrivere che da spiegare:disabledpointer-events

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

Un'altra opzione per IE 11 è quella di impostare displaydegli elementi di collegamento a blocko inline-block:

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

Tieni presente che questa potrebbe essere una soluzione portatile se devi supportare IE (e puoi cambiare il tuo HTML) ma ...

Detto questo, tieni presente che pointer-eventsdisabilita solo ... eventi puntatore. I collegamenti saranno comunque navigabili tramite tastiera, quindi è necessario applicare anche una delle altre tecniche descritte qui.

Messa a fuoco

In combinazione con la tecnica CSS sopra descritta, è possibile utilizzare tabindexin modo non standard per impedire la messa a fuoco di un elemento:

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

Non ho mai verificato la sua compatibilità con molti browser, quindi potresti voler testarlo da solo prima di utilizzare questo. Ha il vantaggio di lavorare senza JavaScript. Purtroppo (ma ovviamente) tabindexnon può essere modificato dal CSS.

Intercetta i clic

Utilizzare hrefa una funzione JavaScript, verificare la condizione (o l'attributo disabilitato stesso) e non fare nulla nel caso.

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

Per disabilitare i collegamenti, procedere come segue:

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

Per riattivarli:

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

Se vuoi invece di .is("[disabled]")te puoi usare .attr("disabled") != undefined(jQuery 1.6+ tornerà sempre undefinedquando l'attributo non è impostato) ma is()è molto più chiaro (grazie a Dave Stewart per questo suggerimento). Nota che qui sto usando l' disabledattributo in modo non standard, se ti interessa, sostituisci l'attributo con una classe e sostituiscilo .is("[disabled]")con .hasClass("disabled")(aggiungendo e rimuovendo con addClass()e removeClass()).

Zoltán Tamási ha osservato in un commento che "in alcuni casi l'evento click è già associato a qualche funzione" reale "(ad esempio utilizzando knockoutjs) In tal caso l'ordinamento del gestore eventi può causare alcuni problemi. Quindi ho implementato collegamenti disabilitati vincolando un ritorno falso gestore per il collegamento touchstart, mousedowne keydowngli eventi. ha alcuni svantaggi (impedirà tocco scrolling iniziato sul link)" , ma la gestione di eventi di tastiera ha anche il vantaggio di evitare la navigazione da tastiera.

Nota che se hrefnon viene cancellato è possibile che l'utente visiti manualmente quella pagina.

Cancella il collegamento

Cancella l' hrefattributo. Con questo codice non si aggiunge un gestore eventi ma si modifica il collegamento stesso. Utilizzare questo codice per disabilitare i collegamenti:

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

E questo per riabilitarli:

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

Personalmente questa soluzione non mi piace molto (se non devi fare di più con i link disabilitati) ma potrebbe essere più compatibile a causa di vari modi per seguire un link.

Gestore di clic falso

Aggiungi / rimuovi una onclickfunzione in cui il return falsecollegamento non verrà seguito. Per disabilitare i collegamenti:

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

Per riattivarli:

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

Non credo che ci sia un motivo per preferire questa soluzione anziché la prima.

Messa in piega

Lo styling è ancora più semplice, qualunque sia la soluzione che stai utilizzando per disabilitare il collegamento che abbiamo aggiunto un disabledattributo in modo da poter utilizzare la seguente regola CSS:

a[disabled] {
    color: gray;
}

Se stai usando una classe anziché l'attributo:

a.disabled {
    color: gray;
}

Se si utilizza un framework dell'interfaccia utente, è possibile notare che i collegamenti disabilitati non sono stati disegnati correttamente. Bootstrap 3.x, ad esempio, gestisce questo scenario e il pulsante ha uno stile corretto sia con disabledattributo che con .disabledclasse. Se, invece, stai cancellando il collegamento (o usando una delle altre tecniche JavaScript) devi anche gestire lo stile perché un <a>senza hrefè ancora dipinto come abilitato.

Applicazioni accessibili per Internet (ARIA)

Non dimenticare di includere anche un attributo aria-disabled="true"insieme a disabledattributo / classe.


2
Destra. Ma per una manutenzione più semplice aggiungerei i gestori di eventi click a tutti td ai messaggi che potrebbero essere disabilitati, che chiameranno event.preventDefault()se $(this).data('disabled')è vero, e quindi impostato data('disabled', true)su qualsiasi link che voglio disabilitare (falso per abilitare, ecc.)
ori

1
@Ankit Per aspetto hai CSS! Imposta una regola per i collegamenti "disabilitati" come questo a [disabilitato] {color: grigio}
Adriano Repetti

1
Aggiornamento rapido sul supporto del browser . Nota anche se IE11 supporta puntatore-eventi, c'è un piccolo bocconcino che dice che non funziona ai link: (...
Agosto

1
$(this).is('[disabled]')potrebbe essere un modo migliore per rilevare l'attributo disabilitato
Dave Stewart,

2
Jon, non mi piace molto. Innanzitutto perché la navigazione da tastiera funziona ancora. In secondo luogo perché è un trucco (potrebbero essere utili solo se nient'altro funziona). Terzo perché alcune persone mantengono Javascript disabilitato e in questo caso non hai alcun "livello" di protezione. Quarto perché è la soluzione più complicata qui (quando poche linee Javascript possono funzionare)
Adriano Repetti,

23

Ho la correzione in CSS.

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

Sopra css, quando applicato al tag anchor, disabiliterà l'evento click.

Per dettagli controlla questo link


1
È una buona soluzione ma non è supportata da ... suppongo ... Internet Explorer.
Adriano Repetti,

È supportato da tutti i browser
Ankit

1
Non dovrebbe essere supportato per HTML in Internet Explorer e Opera.
Adriano Repetti

@Ankit, non funziona in IE 9 e versioni precedenti. Stai usando IE 10?
Mandeep Jain,

4
Ciò fallisce nel caso d'uso degli eventi della tastiera, come menzionato sopra Adriano Repetti. L'utente può comunque accedere al collegamento e premere Invio.
cage rattler,

12

Grazie a tutti coloro che hanno pubblicato soluzioni (in particolare @AdrianoRepetti), ho combinato diversi approcci per fornire alcune disabledfunzionalità più avanzate (e funziona su più browser). Il codice è sotto (sia ES2015 che coffeescript in base alle tue preferenze).

Ciò prevede più livelli di difesa in modo che le Ancore contrassegnate come disabilitate si comportino effettivamente come tali. Usando questo approccio, ottieni un'ancora che non puoi:

  • clic
  • scheda e premi invio
  • la tabulazione su di esso sposta lo stato attivo sul successivo elemento attivabile
  • è a conoscenza se l'ancora è successivamente abilitata

Come

  1. Includi questo CSS, in quanto è la prima linea di difesa. Ciò presuppone che sia il selettore che si utilizzaa.disabled

    a.disabled {
      pointer-events: none;
      cursor: default;
    }
    
  2. Quindi, istanza questa classe su pronto (con selettore opzionale):

      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

E se avessimo bisogno di una soluzione jQuery / javascript diretta? Vedi la mia risposta qui sotto.
Jon Crawford,

1
Bene, allora usi la classe ES2015 che ho appena aggiunto!
Kross,

7

Prova l'elemento:

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

Disabilitare un collegamento funziona per me in Chrome: http://jsfiddle.net/KeesCBakker/LGYpz/ .

Firefox non sembra funzionare bene. Questo esempio funziona:

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

Nota: aggiunta un'istruzione 'live' per futuri collegamenti disabilitati / abilitati.
Nota2: cambiato 'live' in 'on'.


6
Il nuovo esempio dovrebbe funzionare anche in Firefox. ;-) è un firefix: D
Kees C. Bakker,

Chrome impedisce la navigazione in jsFiddle a causa di "Rifiutato di visualizzare il documento perché la visualizzazione è vietata da X-Frame-Options". Scusate se l'esempio jsfiddle fa cose strane ;-)
Kees C. Bakker il

Devo mostrare anche il tag anchor come disabilitato. Come mostrato in IE. Inoltre non voglio modificare la funzione clic per inserire un segno di spunta se è disabilitata
Ankit

La parte spettacolo può essere eseguita da css e aggiungendo una classe che la rende grigia. Il vantaggio del clic 'live' è che risolverai il problema per tutti i link. Se posso aiutare di più, fammelo sapere. Spero che tu ci riesca.
Kees C. Bakker,

Prova la mia risposta qui sotto per una soluzione completamente cross-browser!
Jon Crawford,

4

Bootstrap 4.1 fornisce una classe denominata disablede un aria-disabled="true"attributo.

esempio"

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

Altro è su getbootstrap.com

Quindi, se vuoi farlo dinamicamente, e you don't want to care if it is button or ancorche nello script JS hai bisogno di qualcosa del genere

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

Ma stai attento

La soluzione funziona solo su collegamenti con le classi btn btn-link.

A volte bootstrap consiglia di utilizzare la card-linkclasse, in questo caso la soluzione non funzionerà .


1

Ho finito con la soluzione di seguito, che può funzionare con un attributo <a href="..." disabled="disabled">o una classe <a href="..." class="disabled">:

Stili CSS:

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

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

Javascript (in jQuery pronto):

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

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

0

non è possibile disabilitare un collegamento, se si desidera che l'evento click non venga attivato, semplicemente Removeil actionda quel collegamento.

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

Per maggiori informazioni: - Elementi che possono essere disabilitati


1
Questo non disabilita davvero il collegamento. L'elemento di ancoraggio verrà comunque attivato, anche se rimarrà sulla stessa pagina.
Florian Margaine,

0

Vorrei fare qualcosa del genere

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

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

qualcosa del genere dovrebbe funzionare. Aggiungi una classe per i link che desideri disabilitare e poi restituisci false quando qualcuno fa clic su di essi. Per abilitarli basta rimuovere la classe.


Questo non sarebbe d'aiuto. Devo registrare nuovamente l'evento click e la funzione è dinamica che viene chiamata. Una volta rimosso, non posso associarlo di nuovo
Ankit,

0

Per disabilitare il collegamento per accedere a un'altra pagina sul dispositivo touch:

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

La mia risposta funziona anche sul cellulare. Browser molto incrociato. Vedi sotto.
Jon Crawford,

Questo è sbagliato, se tu setAttribute('href', '');e l'URL della pagina sei http://example.com/page/?query=somethingil link quando fai clic su IE11 andresti a http://example.com/page/. Una soluzione alternativa potrebbe essere l'usosetAttribute('href', '#');
Marco Demaio,

0

In Razor (.cshtml) puoi fare:

@{
    var isDisabled = true;
}

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

-2

Puoi usarlo per disabilitare il collegamento ipertestuale di asp.net o i pulsanti di collegamento in html.

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

-2

C'è un altro modo possibile e quello che mi piace di più. Fondamentalmente è lo stesso modo in cui lightbox disabilita un'intera pagina, posizionando un div e giocherellando con z-index. Ecco alcuni frammenti rilevanti di un mio progetto. Funziona su tutti i browser !!!!!

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

e in 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"/>

Quindi il resizer trova le posizioni dell'ancora (le immagini sono solo frecce) e posiziona il disabler in cima. L'immagine del disabilitatore è un quadrato grigio traslucido (cambia la larghezza / altezza dei disabilitatori nell'html in modo che corrisponda al tuo link) per mostrare che è disabilitato. Il floating consente di ridimensionare dinamicamente la pagina e i disabilitanti seguiranno l'esempio in windowResizer (). Puoi trovare immagini adatte tramite google. Ho inserito i CSS pertinenti per semplicità.

quindi in base a qualche condizione,

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

4
Non ho effettuato il downgrade, ma la mia ipotesi: troppo sovraccarico per una cosa semplice, il tuo codice non è commentato abbastanza per una risposta su SO. È anche molto confuso, personalmente non lo userei.
Emile Bergeron,

-5

Penso che molti di questi stiano pensando troppo. Aggiungi una classe di quello che vuoi, come disabled_link.
Quindi fai in modo che i CSS abbiano .disabled_link { display: none }
Boom ora che l'utente non riesca a vedere il link, quindi non dovrai preoccuparti che facciano clic su di esso. Se fanno qualcosa per soddisfare il collegamento essendo cliccabile, è sufficiente rimuovere la classe con jQuery:
$("a.disabled_link").removeClass("super_disabled"). Boom fatto!


Dalla domanda: "E DEVO MOSTRARE IL LINK IN MODALITÀ DISABILITATA".
Marcelo,

Sì, hai ragione. Ho perso questo. Quindi, direi invece, sposta il valore href in data-href $("td a").each(function(i,v){ $(this).data('href',this.href); $(this).attr('href','#').css('color','grey'); });Quindi, quando vuoi renderlo indesiderabile: $(this).attr('href',$(this).data('href')).css('color','blue');
Jordan Michael Rushing,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.