Ereignis bei einem deaktivierten Eingang


234

Anscheinend ein Behinderter <input> von keinem Ereignis behandelt

Gibt es eine Möglichkeit, dieses Problem zu umgehen?

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

Hier muss ich auf den Eingang klicken, um ihn zu aktivieren. Wenn ich es jedoch nicht aktiviere, sollte die Eingabe nicht veröffentlicht werden.


Hier ist eine gute Alternative blog.pengoworks.com/index.cfm/2010/4/23/…

Sie können CSS-pretend-disable verwenden und die Eingänge im onSubmit-Handler durchlaufen, um die nicht aktivierten Eingänge für real zu deaktivieren.
ptrk

Antworten:


267

Deaktivierte Elemente lösen keine Mausereignisse aus. Die meisten Browser verbreiten ein Ereignis, das vom deaktivierten Element stammt, im DOM-Baum, sodass Ereignishandler auf Containerelementen platziert werden können. Firefox zeigt dieses Verhalten jedoch nicht, es macht überhaupt nichts, wenn Sie auf ein deaktiviertes Element klicken.

Ich kann mir keine bessere Lösung vorstellen, aber für eine vollständige Cross-Browser-Kompatibilität können Sie ein Element vor die deaktivierte Eingabe stellen und den Klick auf dieses Element abfangen. Hier ist ein Beispiel dafür, was ich meine:

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

Beispiel: http://jsfiddle.net/RXqAm/170/ (aktualisiert, um jQuery 1.7 mit propanstelle von zu verwenden attr).


2
Kleine Sache: Wenn Sie das disabledAttribut ohne Wert verwenden, impliziert dies HTML anstelle von XHTML. In diesem Fall ist der schließende Schrägstrich nicht erforderlich.
Tim Down

11
@ Tim: Es ist zwar unnötig, aber es ist immer noch gültiges HTML. Es ist wirklich nur eine Gewohnheit und ich fühle, dass es besser aussieht.
Andy E

1
Danke Andy, das ist ziemlich klug. Gibt es nicht einfacher? Wissen Sie, warum deaktivierte Eingänge nicht handhabbar sind?
Pierre de LESPINAY

2
Dies macht keinen Sinn: Jedes andere HTML-Element behandelt Mausereignisse, warum nicht ein deaktiviertes Element (z. B. mouseenterusw.)
Augustin Riedinger

7
Sie können verhindern, dass das deaktivierte Element Ihre Klicks "wegwirft", indem Sie input[disabled] {pointer-events:none}Ihr CSS eingeben. Dann verhält sich der Klick so, als hätten Sie auf das übergeordnete Element geklickt. IMHO ist dies die einfachste und sauberste Lösung, aber leider funktioniert sie nur für Browser, die die pointer-eventsCSS-Eigenschaft unterstützen: caniuse.com/#search=pointer-events
Doin

70

Möglicherweise können Sie das Feld schreibgeschützt machen und beim Senden alle schreibgeschützten Felder deaktivieren

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

und die Eingabe (+ Skript) sollte sein

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

$('input[readonly]').click(function () {
    $(this).removeAttr('readonly');
})

5
+1, dies ist ein anständiger alternativer Vorschlag. Der einzige Nachteil ist, dass das Eingabefeld nicht das deaktivierte Styling annimmt, das zwischen den Browsern variiert, so dass es schwierig ist, es mit den Erwartungen des Benutzers an eine deaktivierte Eingabe in Einklang zu bringen.
Andy E

wahr. Vielleicht könnte dies mit CSS umgangen werden? Aber ja, es würde nicht das gleiche Aussehen haben wie normale deaktivierte Eingabefelder
Tokimon

Hervorragende alternative Lösung. Ich mag dieses besser, weil Sie jedes notwendige Styling mit CSS durchführen können (dh es LOOK deaktivieren lassen) und dennoch Ereignisse verfügbar haben.
Joshua

62

Deaktivierte Elemente "essen" Klicks in einigen Browsern - sie reagieren weder auf sie noch erlauben sie, dass sie von Ereignishandlern irgendwo auf dem Element oder einem seiner Container erfasst werden.

IMHO ist der einfachste und sauberste Weg, dies zu "beheben" (wenn Sie tatsächlich Klicks auf deaktivierte Elemente erfassen müssen, wie es das OP tut), einfach das folgende CSS zu Ihrer Seite hinzuzufügen:

input[disabled] {pointer-events:none}

Dadurch werden alle Klicks auf eine deaktivierte Eingabe auf das übergeordnete Element übertragen, wo Sie sie normal erfassen können. (Wenn Sie mehrere deaktivierte Eingaben haben, möchten Sie möglicherweise jede in einen eigenen Container einfügen, sofern diese nicht bereits so angeordnet sind - beispielsweise eine zusätzliche <span>oder eine <div>-, um die Unterscheidung der deaktivierten Eingaben zu vereinfachen wurde angeklickt).


Der Nachteil ist, dass dieser Trick leider nicht für ältere Browser funktioniert, die die pointer-eventsCSS-Eigenschaft nicht unterstützen . (Es sollte von IE 11, FF v3.6, Chrome v4 funktionieren): funktionieren caniuse.com/#search=pointer-events

Wenn Sie ältere Browser unterstützen müssen, müssen Sie eine der anderen Antworten verwenden!


Ich war mir nicht sicher, ob ich input[disabled]auch mit Elementen übereinstimmen würde, die durch JavaScript ( element.disabled = true;) deaktiviert wurden, aber es scheint so. Jedenfalls finde ich input:disabledsauberer.
Martin

Dies scheint eine gute Lösung zu sein, funktioniert aber in IE11 nicht für mich! Sie sagen auch FF 38+ und Chrome 31+, aber Ihr Caniuse-Link sagt FF 3.6+ und Chrome 4+?
user764754

@ user764754 ... mein Fehler, ich wusste nicht, dass ich auf der caniuse-Seite auf "Alle anzeigen" klicken musste, um frühere Browserversionen zu erhalten! Habe das behoben. IE11 habe ich gerade getestet und es funktioniert einwandfrei (siehe jsfiddle.net/7kkszq1c/1 für den Code, obwohl die jsFiddle-Site in IE11 aus irgendeinem Grund für mich nicht funktionierte, musste ich sie in eine einfügen. htm Datei stattdessen)
Doin

Danke für das Update! In der Zwischenzeit habe ich auch festgestellt, dass es auf einer Website in IE11 funktioniert, aber nicht mit jsfiddle. Vielleicht wegen des jsfiddle iframe ...
user764754

2
@Protectorone: deaktiviert ist eine Pseudoklasse seit CSS 3: w3.org/TR/css3-selectors/#UIstates
Martin

15

Ich würde eine Alternative vorschlagen - verwenden Sie CSS:

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

anstelle des deaktivierten Attributs. Anschließend können Sie Ihre eigenen CSS-Attribute hinzufügen, um eine deaktivierte Eingabe zu simulieren, jedoch mit mehr Kontrolle.


4
funktioniert nur mit ie10, zu viele benutzer haben ie9 / 8. also keine verlässliche alternative.
kodiert

Dies führt immer noch dazu, dass das Feld beim Absenden des Formulars gebucht wird, was in vielen Fällen unerwünscht ist.
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>


5
Aber das funktioniert nicht mit FireFox - und das war der springende Punkt!
GarethOwen

6

Stattdessen disabledkönnten Sie die Verwendung in Betracht ziehen readonly. Mit etwas zusätzlichem CSS können Sie die Eingabe so gestalten, dass sie wie eine aussiehtdisabled Feld .

Es gibt tatsächlich ein anderes Problem. Das Ereignis wird changenur ausgelöst, wenn das Element den Fokus verliert, was unter Berücksichtigung eines disabledFeldes nicht logisch ist. Wahrscheinlich schieben Sie Daten von einem anderen Anruf in dieses Feld. Damit dies funktioniert, können Sie das Ereignis 'bind' verwenden.

$('form').bind('change', 'input', function () {
    console.log('Do your thing.');
});

Eine schreibgeschützte Eingabe wird weiterhin mit dem Formular eingereicht, wenn ich mich nicht irre
Pierre de LESPINAY

Das ist richtig. Es sollte dann mit @npth anwsner kombiniert werden.
Nykac

Danke, das war klug, sauber und optimistisch für meinen Fall.
Sultanos

4

ODER machen Sie dies mit jQuery und CSS!

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

Auf diese Weise wird das Element deaktiviert und es werden keine Zeigerereignisse ausgelöst. Es ermöglicht jedoch die Weitergabe. Wenn es übermittelt wird, können Sie es mit dem Attribut 'ignorieren' ignorieren.


@Precastic, das stimmt, aber es funktioniert zu diesem Zeitpunkt für fast alle anderen Browser und Sie können eine Polyfüllung für <11 verwenden . Sidonaldson, warum nicht direktes CSS verwenden, um Stile anzuwenden?
KyleMit

@KyleMit Sie könnten eine Klasse hinzufügen, anstatt die Stile festzulegen, aber darum geht es in diesem Thread nicht! Ich habe nur Zeigerereignisse vorgeschlagen, was immer noch eine gute und korrekte Antwort ist, abhängig von der Browsermatrix, für die Sie erstellen. Und danke für alle, die diese Antwort
notiert

1
@sidonaldson, es ist eine gute Antwort, also wünschte ich mir auch, es wäre auch höher eingestuft. Ich bin nicht sicher, was das Ignorierattribut bewirkt . Mein Punkt zu CSS war jedoch, dass ich nicht glaube, dass wir jQuery als Vehikel für die Anwendung von CSS benötigen. Sie können einfach eine CSS-Regel einrichten, die auf denselben Selektor abzielt und auch Zeigerereignisse deaktiviert. In dieser Geige sollten jQuery und CSS dasselbe tun, aber das CSS wird weitaus leistungsfähiger sein.
KyleMit

@KyleMit ah, vorausgesetzt, das Formular wird gesendet, müssen Sie das Backend irgendwie anweisen, dieses Feld zu ignorieren, wenn es einen Wert enthält (da das Spoofing deaktiviert ist).
Sidonaldson

Ich bin damit einverstanden, dass CSS leistungsfähiger sein könnte, da Sie einen Selektor verwenden können, der auf einem Attribut basiert! Überprüfen Sie diese Demo, in der ich Chromes eigenes deaktiviertes Feld gefunden habe: jsfiddle.net/KyleMit/pxx8pk6v
Sidonaldson

0

Wir hatten heute ein solches Problem, aber wir wollten den HTML-Code nicht ändern. Deshalb haben wir das mouseenter- Ereignis verwendet, um dies zu erreichen

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

-1

Ich finde eine andere Lösung:

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

Klasse "disabled" imitiert deaktiviertes Element durch Deckkraft:

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

Brechen Sie das Ereignis ab, wenn das Element deaktiviert ist, und entfernen Sie die Klasse:

$(document).on('click','input.disabled',function(event) {
    event.preventDefault();
    $(this).removeClass('disabled');
});

Der JavaScript-Teil funktioniert bei mir nicht. Abgesehen davon wird die Frage nicht beantwortet, da es darum geht, eine deaktivierte Eingabe zu aktivieren. In diesem Beispiel ist es jedoch zu Beginn nicht deaktiviert und wird daher beim Senden gesendet.
Raimund Krämer

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.