Evento en una entrada deshabilitada

234

Aparentemente un <input>evento deshabilitado no es manejado por ningún evento

¿Hay alguna forma de solucionar este problema?

<input type="text" disabled="disabled" name="test" value="test" />
$(':input').click(function () {
    $(this).removeAttr('disabled');
})

Aquí, necesito hacer clic en la entrada para habilitarla. Pero si no lo activo, la entrada no debería publicarse.

Pierre de LESPINAY
fuente
Aquí hay una buena alternativa blog.pengoworks.com/index.cfm/2010/4/23/…
Puede usar CSS-pretend-disable y recorrer las entradas en el controlador onSubmit, deshabilitando las no activadas de verdad.
ptrk

Respuestas:

267

Los elementos deshabilitados no disparan eventos del mouse. La mayoría de los navegadores propagarán un evento que se origina desde el elemento deshabilitado hasta el árbol DOM, por lo que los controladores de eventos podrían ubicarse en elementos del contenedor. Sin embargo, Firefox no exhibe este comportamiento, simplemente no hace nada cuando hace clic en un elemento deshabilitado.

No puedo pensar en una solución mejor, pero, para una compatibilidad cruzada completa del navegador, podría colocar un elemento delante de la entrada deshabilitada y hacer clic en ese elemento. Aquí hay un ejemplo de lo que quiero decir:

<div style="display:inline-block; position:relative;">
  <input type="text" disabled />
  <div style="position:absolute; left:0; right:0; top:0; bottom:0;"></div>
</div>​

jq:

$("div > div").click(function (evt) {
    $(this).hide().prev("input[disabled]").prop("disabled", false).focus();
});​

Ejemplo: http://jsfiddle.net/RXqAm/170/ (actualizado para usar jQuery 1.7 con en proplugar de attr).

Andy E
fuente
2
Pequeña cosa: si está utilizando el disabledatributo sin valor, eso implica HTML en lugar de XHTML, en cuyo caso la barra diagonal de cierre es innecesaria.
Tim Down
11
@Tim: de hecho es innecesario, pero sigue siendo HTML válido. Es solo una fuerza de hábito realmente y siento que se ve mejor.
Andy E
1
Gracias Andy, esto es bastante inteligente. ¿No hay más simple? ¿Sabes por qué las entradas deshabilitadas no son manejables?
Pierre de LESPINAY
2
Esto no tiene sentido: cualquier otro elemento html eventos asas del ratón, por qué no un elemento de personas con discapacidad (por ejemplo. mouseenter, Etc.)
Augustin Riedinger
77
Puede evitar que el elemento deshabilitado "deseche" sus clics colocando input[disabled] {pointer-events:none}su CSS. Luego, el clic se comporta como si hubiera hecho clic en el elemento primario. En mi humilde opinión, esta es la solución más simple y limpia, pero desafortunadamente solo funciona para los navegadores que admiten la pointer-eventspropiedad CSS: caniuse.com/#search=pointer-events
Doin
70

Tal vez podría hacer que el campo sea de solo lectura y al enviarlo deshabilite todos los campos de solo lectura

$(".myform").submit(function(e) {
    $("input[readonly]", this).attr("disabled", true);
});

y la entrada (+ script) debe ser

<input type="text" readonly="readonly" name="test" value="test" />

$('input[readonly]').click(function () {
    $(this).removeAttr('readonly');
})
Tokimon
fuente
55
+1, esta es una sugerencia alternativa decente. El único inconveniente es que el cuadro de entrada no adoptará el estilo deshabilitado, que varía entre los navegadores, por lo que sería difícil hacer que parezca coherente con las expectativas del usuario de una entrada deshabilitada.
Andy E
cierto. ¿Quizás esto podría solucionarse con CSS? Pero sí, no tendría el mismo aspecto que los campos de entrada marcados normales
Tokimon
Excelente solución alternativa. Este me gusta más porque puedes hacer cualquier estilo necesario con CSS (es decir, deshabilitar LOOK) y aún así tener eventos disponibles.
Joshua
62

Los elementos deshabilitados "comen" clics en algunos navegadores: no responden a ellos ni permiten que sean capturados por los controladores de eventos en cualquier parte del elemento o cualquiera de sus contenedores.

En mi humilde opinión, la forma más simple y limpia de "arreglar" esto (si realmente necesita capturar clics en elementos deshabilitados como lo hace el OP) es simplemente agregar el siguiente CSS a su página:

input[disabled] {pointer-events:none}

Esto hará que cualquier clic en una entrada deshabilitada caiga al elemento principal, donde puede capturarlos normalmente. (Si tiene varias entradas deshabilitadas, es posible que desee colocar cada una en un contenedor individual, si aún no se han presentado de esa manera, un extra <span>o un <div>, por ejemplo, solo para que sea fácil distinguir qué entrada deshabilitada fue hecho clic).


La desventaja es que este truco desafortunadamente no funcionará para los navegadores más antiguos que no admiten la pointer-eventspropiedad CSS. (Debería funcionar desde IE 11, FF v3.6, Chrome v4): caniuse.com/#search=pointer-events

Si necesita admitir navegadores antiguos, deberá usar una de las otras respuestas.

Doin
fuente
No estaba seguro de si input[disabled]también coincidiría con elementos deshabilitados por JavaScript ( element.disabled = true;), pero parece que sí. De todos modos, me parece input:disabledmás limpio.
Martin
¡Esto parece una buena solución, aunque no funciona para mí en IE11! ¿También dice FF 38+ y Chrome 31+ pero su enlace de caniuse dice FF 3.6+ y Chrome 4+?
user764754
@ user764754 ... mi error, ¡no me di cuenta de que necesitaba hacer clic en "Mostrar todo" en la página de Caniuse para obtener versiones anteriores del navegador! Han arreglado eso. En cuanto a IE11, acabo de probarlo y funciona bien (ver jsfiddle.net/7kkszq1c/1 para el código, aunque por alguna razón el sitio jsFiddle no funcionó para mí en IE11, tuve que pegarlo en un. htm en su lugar)
Doin
¡Gracias por la actualización! Mientras tanto, también observé que funciona en un sitio web en IE11 pero no con jsfiddle. Quizás por el iframe jsfiddle ...
user764754
2
@Protectorone: disabled es una pseudo-clase desde CSS 3: w3.org/TR/css3-selectors/#UIstates
Martin
15

Sugeriría una alternativa: use CSS:

input.disabled {
    user-select : none;
    -moz-user-select : none;
    -webkit-user-select : none;
    color: gray;
    cursor: pointer;
}

en lugar del atributo deshabilitado. Luego, puede agregar sus propios atributos CSS para simular una entrada deshabilitada, pero con más control.

Ron Reiter
fuente
44
solo funciona con ie10, demasiados usuarios tienen ie9 / 8. por lo que no es una alternativa confiable.
codifica el
Esto todavía hace que el campo se publique cuando se envía el formulario, lo que no es deseable en muchos casos.
cimmanon
7

$(function() {

  $("input:disabled").closest("div").click(function() {
    $(this).find("input:disabled").attr("disabled", false).focus();
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<div>
  <input type="text" disabled />
</div>

Rejeesh Prarath
fuente
55
Pero esto no funciona en FireFox, ¡y ese fue el punto!
GarethOwen
6

En lugar de disabled, podría considerar usar readonly. Con un poco de CSS adicional, puede diseñar la entrada para que se vea como un disabledcampo.

En realidad hay otro problema. El evento changesolo se dispara cuando el elemento pierde el foco, lo que no es lógico considerando un disabledcampo. Probablemente esté enviando datos a este campo desde otra llamada. Para que esto funcione, puede usar el evento 'bind'.

$('form').bind('change', 'input', function () {
    console.log('Do your thing.');
});
Nykac
fuente
Se enviará una entrada de solo lectura con el formulario si no me equivoco
Pierre de LESPINAY
Eso es correcto. Luego se debe combinar con @npth anwsner.
Nykac
Gracias, eso fue inteligente, limpio y óptimo para mi caso.
Sultanos
4

¡O haga esto con jQuery y CSS!

$('input.disabled').attr('ignore','true').css({
    'pointer-events':'none',
     'color': 'gray'
});

De esta manera, hace que el elemento se vea deshabilitado y no se dispararán eventos de puntero, sin embargo, permite la propagación y, si se envía, puede usar el atributo 'ignorar' para ignorarlo.

sidonaldson
fuente
@Precastic, eso es cierto, pero funciona para casi todos los demás navegadores en este momento y puede usar un polyfill para, por ejemplo, <11 . sidonaldson, ¿por qué no usar CSS directo para aplicar estilos?
KyleMit
@KyleMit podría agregar una clase en lugar de configurar los estilos, ¡pero de eso no se trata este hilo! Solo sugería eventos de puntero, que sigue siendo una respuesta buena y correcta, dependiendo de la matriz del navegador para la que esté construyendo. Y gracias a todos los que han marcado esta respuesta que apesta, ya que nada aquí es incorrecto: /
sidonaldson
1
@sidonaldson, es una buena respuesta, así que también desearía que estuviera mejor clasificado. No estoy seguro de lo que hace el atributo ignorar . Pero mi punto sobre CSS fue que no creo que necesitemos jQuery para ser el vehículo para aplicar CSS. Simplemente puede configurar una regla CSS que apunte al mismo selector y también deshabilite los eventos de puntero. En este violín , jQuery y CSS deberían estar haciendo lo mismo, pero el CSS será mucho más eficiente.
KyleMit
@KyleMit ah, suponiendo que se envíe el formulario, de alguna manera tendrá que decirle al backend que ignore ese campo si contenía un valor (ya que estamos falsificando la suplantación).
sidonaldson
¡Estoy de acuerdo en que CSS podría ser más poderoso ya que puedes usar un selector basado en un atributo! Verifique esta demostración en la que coincida con el campo deshabilitado propio de chromes: jsfiddle.net/KyleMit/pxx8pk6v
sidonaldson
0

Hoy tuvimos un problema como este, pero no queríamos cambiar el HTML. Así que utilizamos el evento mouseenter para lograr eso

var doThingsOnClick = function() {
    // your click function here
};

$(document).on({
    'mouseenter': function () {
        $(this).removeAttr('disabled').bind('click', doThingsOnClick);
    },
    'mouseleave': function () {
        $(this).unbind('click', doThingsOnClick).attr('disabled', 'disabled');
    },
}, 'input.disabled');
Raúl Sánchez
fuente
-1

Encuentro otra solución:

<input type="text" class="disabled" name="test" value="test" />

La clase "deshabilitado" imita el elemento deshabilitado por opacidad:

<style type="text/css">
    input.disabled {
        opacity: 0.5;
    }
</style>

Y luego cancele el evento si el elemento está deshabilitado y elimine la clase:

$(document).on('click','input.disabled',function(event) {
    event.preventDefault();
    $(this).removeClass('disabled');
});
npth
fuente
La parte de JavaScript no me funciona. Aparte de eso, no responde la pregunta, ya que se trata de habilitar una entrada deshabilitada. En este ejemplo, sin embargo, no está deshabilitado al inicio y, por lo tanto, se envía al enviar.
Raimund Krämer