Cómo deshabilitar enlaces HTML
Tengo un botón de enlace dentro <td>
que tengo que desactivar. Esto funciona en IE pero no en Firefox y Chrome.
Intenté todo lo siguiente pero no funcionó en Firefox (usando 1.4.2 js):
$(".myLink").attr('disabled', 'disabled');
$(".myLink").attr('disabled', true);
$(".myLink").attr('disabled', 'true');
Nota: No puedo cancelar el registro de la función de clic para la etiqueta de anclaje ya que está registrada dinámicamente. Y TENGO QUE MOSTRAR EL ENLACE EN MODO DESHABILITADO.
No puedes desactivar un enlace (de forma portátil). Puedes utilizar una de estas técnicas (cada una con sus propios beneficios y desventajas).
Manera CSS
Esta debería ser la forma correcta (pero verá más adelante) de hacerlo cuando la mayoría de los navegadores lo admitan:
a.disabled {
pointer-events: none;
}
Es lo que hace, por ejemplo, Bootstrap 3.x. Actualmente (2016) solo es compatible con Chrome, Firefox y Opera (19+). Internet Explorer comenzó a admitir esto desde la versión 11, pero no para enlaces ; sin embargo, está disponible en un elemento externo como:
span.disable-links {
pointer-events: none;
}
Con:
<span class="disable-links"><a href="#">...</a></span>
Solución alterna
Probablemente necesitemos definir una clase CSS, pointer-events: none
pero ¿qué pasa si reutilizamos el disabled
atributo en lugar de una clase CSS? Estrictamente hablando, disabled
no es compatible, <a>
pero los navegadores no se quejarán de atributos desconocidos . El uso del disabled
atributo IE lo ignorará pointer-events
pero respetará el disabled
atributo específico de IE; otros navegadores compatibles con CSS ignorarán los atributos desconocidos disabled
y los respetarán pointer-events
. Es más fácil escribir que explicar:
a[disabled] {
pointer-events: none;
}
Otra opción para IE 11 es establecer display
elementos de enlace a block
o inline-block
:
<a style="pointer-events: none; display: inline-block;" href="#">...</a>
Tenga en cuenta que esta puede ser una solución portátil si necesita admitir IE (y puede cambiar su HTML) pero...
Dicho todo esto, tenga en cuenta que pointer-events
solo desactiva... eventos de puntero. Los enlaces seguirán siendo navegables a través del teclado, entonces también deberá aplicar una de las otras técnicas que se describen aquí.
Enfocar
Junto con la técnica CSS descrita anteriormente, puede utilizarla tabindex
de forma no estándar para evitar que un elemento se centre en:
<a href="#" disabled tabindex="-1">...</a>
Nunca verifiqué su compatibilidad con muchos navegadores, entonces quizás quieras probarlo tú mismo antes de usarlo. Tiene la ventaja de funcionar sin JavaScript. Desafortunadamente (pero obviamente) tabindex
no se puede cambiar desde CSS.
Interceptar clics
Utilice a href
para una función de JavaScript, verifique la condición (o el atributo deshabilitado en sí) y no haga nada por si acaso.
$("td > a").on("click", function(event){
if ($(this).is("[disabled]")) {
event.preventDefault();
}
});
Para deshabilitar enlaces haga esto:
$("td > a").attr("disabled", "disabled");
Para volver a habilitarlos:
$("td > a").removeAttr("disabled");
Si lo desea, .is("[disabled]")
puede usarlo en lugar de .attr("disabled") != undefined
(jQuery 1.6+ siempre regresará undefined
cuando el atributo no esté configurado) pero is()
es mucho más claro (gracias a Dave Stewart por este consejo). Tenga en cuenta que aquí estoy usando el disabled
atributo de una manera no estándar; si esto le interesa, reemplace el atributo con una clase y reemplácelo .is("[disabled]")
con .hasClass("disabled")
(agregando y eliminando con addClass()
y removeClass()
).
Zoltán Tamási señaló en un comentario que "en algunos casos, el evento de clic ya está vinculado a alguna función" real "(por ejemplo, usando knockoutjs). En ese caso, el orden del controlador de eventos puede causar algunos problemas. Por lo tanto, implementé enlaces deshabilitados vinculando un retorno controlador falso para los eventos touchstart
y del enlace. Tiene algunos inconvenientes (evitará que se inicie el desplazamiento táctil en el enlace), mousedown
perokeydown
el manejo de eventos del teclado también tiene la ventaja de evitar la navegación con el teclado.
Tenga en cuenta que si href
no se borra, es posible que el usuario visite esa página manualmente.
Limpiar el enlace
Borre el href
atributo. Con este código no agregas un controlador de eventos pero cambias el enlace en sí. Utilice este código para desactivar enlaces:
$("td > a").each(function() {
this.data("href", this.attr("href"))
.attr("href", "javascript:void(0)")
.attr("disabled", "disabled");
});
Y este para volver a habilitarlos:
$("td > a").each(function() {
this.attr("href", this.data("href")).removeAttr("disabled");
});
Personalmente no me gusta mucho esta solución (si no tienes que hacer más con enlaces deshabilitados) pero puede ser más compatible debido a las varias formas de seguir un enlace.
Controlador de clics falsos
Agregue o elimine una onclick
función en la que return false
no se seguirá su enlace. Para desactivar enlaces:
$("td > a").attr("disabled", "disabled").on("click", function() {
return false;
});
Para volver a habilitarlos:
$("td > a").removeAttr("disabled").off("click");
No creo que haya motivo para preferir esta solución a la primera.
Estilo
El estilo es aún más simple, sea cual sea la solución que estés usando para deshabilitar el enlace, agregamos un disabled
atributo para que puedas usar la siguiente regla CSS:
a[disabled] {
color: gray;
}
Si estás usando una clase en lugar de un atributo:
a.disabled {
color: gray;
}
Si está utilizando un marco de interfaz de usuario, es posible que vea que los enlaces deshabilitados no tienen el estilo adecuado. Bootstrap 3.x, por ejemplo, maneja este escenario y el botón tiene el estilo correcto tanto con disabled
atributo como con .disabled
clase. Si, en cambio, estás borrando el enlace (o usando una de las otras técnicas de JavaScript), también debes manejar el estilo porque un <a>
sin href
todavía está pintado como habilitado.
Aplicaciones enriquecidas de Internet accesibles (ARIA)
No olvide incluir también un atributo aria-disabled="true"
junto con disabled
atributo/clase.
Obtuve la solución en CSS.
td.disabledAnchor a{
pointer-events: none !important;
cursor: default;
color:Gray;
}
El CSS anterior, cuando se aplica a la etiqueta de anclaje, deshabilitará el evento de clic.
Para más detalles consulte este enlace
Gracias a todos los que publicaron soluciones (especialmente @AdrianoRepetti), combiné múltiples enfoques para proporcionar una disabled
funcionalidad más avanzada (y funciona en todos los navegadores). El código se encuentra a continuación (tanto ES2015 como Coffeescript según sus preferencias).
Esto proporciona múltiples niveles de defensa para que los anclajes marcados como deshabilitados realmente se comporten como tales. Con este enfoque, obtienes un ancla que no puedes:
- hacer clic
- tabulador y presione regresar
- al tabularlo se moverá el foco al siguiente elemento enfocable
- sabe si el ancla se habilita posteriormente
Cómo
Incluya este CSS, ya que es la primera línea de defensa. Esto supone que el selector que utiliza es
a.disabled
a.disabled { pointer-events: none; cursor: default; }
A continuación, cree una instancia de esta clase cuando esté lista (con selector opcional):
new AnchorDisabler()
Clase 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
}
}
Clase de café:
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
Prueba el elemento:
$(td).find('a').attr('disabled', 'disabled');
Deshabilitar un enlace me funciona en Chrome: http://jsfiddle.net/KeesCBakker/LGYpz/ .
Firefox no parece funcionar bien. Este ejemplo funciona:
<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: se agregó una declaración "en vivo" para futuros enlaces habilitados o deshabilitados.
Nota 2: se cambió "en vivo" a "activado".