Zdarzenie na wyłączonym wejściu

234

Najwyraźniej wyłączone <input>nie jest obsługiwane przez żadne zdarzenie

Czy istnieje sposób obejścia tego problemu?

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

Tutaj muszę kliknąć dane wejściowe, aby je włączyć. Ale jeśli go nie aktywuję, dane wejściowe nie powinny być publikowane.

Pierre de LESPINAY
źródło
Możesz użyć CSS-udawaj-wyłącz i zapętlaj dane wejściowe w module obsługi onSubmit, wyłączając te nieaktywowane na stałe.
ptrk

Odpowiedzi:

267

Wyłączone elementy nie uruchamiają zdarzeń myszy. Większość przeglądarek będzie propagować zdarzenia pochodzące z wyłączonego elementu w górę drzewa DOM, aby procedury obsługi zdarzeń mogły być umieszczane na elementach kontenera. Jednak Firefox nie wykazuje takiego zachowania, po prostu nic nie robi po kliknięciu wyłączonego elementu.

Nie mogę wymyślić lepszego rozwiązania, ale dla pełnej kompatybilności z różnymi przeglądarkami możesz umieścić element przed wyłączonym wejściem i złapać kliknięcie tego elementu. Oto przykład tego, co mam na myśli:

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

Przykład: http://jsfiddle.net/RXqAm/170/ (zaktualizowany, aby używać jQuery 1.7 propzamiast attr).

Andy E.
źródło
2
Mała rzecz: jeśli używasz disabledatrybutu bez wartości, oznacza to HTML zamiast XHTML, w którym to przypadku zamykanie ukośnika nie jest konieczne.
Tim Down
11
@Tim: rzeczywiście nie jest to konieczne, ale nadal jest prawidłowym HTML. To naprawdę siła nawyku i wydaje mi się, że wygląda lepiej.
Andy E,
1
Dzięki Andy, to całkiem sprytne. Czy nie ma prostszego? Czy wiesz, dlaczego nie można obsłużyć żądanych danych wejściowych?
Pierre de LESPINAY
2
To nie ma sensu: jakikolwiek inny element HTML obsługuje zdarzenia myszy, dlaczego nie element wyłączony (np. mouseenterItp.)
Augustin Riedinger
7
Możesz powstrzymać wyłączony element przed „wyrzucaniem” twoich kliknięć, wstawiając input[disabled] {pointer-events:none}CSS. Następnie kliknięcie zachowuje się tak, jakbyś kliknął element nadrzędny. IMHO jest to najprostsze, najczystsze rozwiązanie, ale niestety działa tylko w przeglądarkach, które obsługują pointer-eventswłaściwość CSS: caniuse.com/#search=pointer-events
Doin
70

Być może możesz zrobić pole tylko do odczytu, a po przesłaniu wyłączyć wszystkie pola tylko do odczytu

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

a wejście (+ skrypt) powinno być

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

$('input[readonly]').click(function () {
    $(this).removeAttr('readonly');
})
Tokimon
źródło
5
+1, to przyzwoita propozycja alternatywna. Jedynym minusem jest to, że pole wprowadzania nie przyjmie wyłączonego stylu, który różni się w różnych przeglądarkach, więc trudno byłoby uzyskać spójność z oczekiwaniami użytkownika dotyczącymi wyłączonego wejścia.
Andy E.
prawdziwe. Być może można to obejść za pomocą CSS? Ale tak, nie wyglądałby tak samo, jak normalne zmienne pola wejściowe
Tokimon
Doskonałe alternatywne rozwiązanie. Podoba mi się to bardziej, ponieważ możesz wykonać dowolną stylizację za pomocą CSS (tj. Wyłączyć LOOK), a mimo to mieć dostępne zdarzenia.
Joshua
62

Wyłączone elementy „jedzą” kliknięcia w niektórych przeglądarkach - nie reagują na nie ani nie pozwalają na przechwytywanie ich przez moduły obsługi zdarzeń w dowolnym miejscu elementu lub dowolnego z jego kontenerów.

IMHO najprostszym, najczystszym sposobem na „naprawienie” tego (jeśli tak naprawdę musisz rejestrować kliknięcia na wyłączone elementy, tak jak robi to OP), wystarczy dodać następujący CSS do swojej strony:

input[disabled] {pointer-events:none}

Spowoduje to, że wszelkie kliknięcia wyłączonego wejścia przejdą do elementu nadrzędnego, gdzie można je przechwycić normalnie. (Jeśli masz kilka wyłączonych danych wejściowych, możesz chcieć umieścić każde z nich w osobnym kontenerze, jeśli nie zostały one jeszcze ułożone w ten sposób - dodatkowe <span>lub <div>, powiedzmy - tylko po to, aby ułatwić rozróżnienie, które wyłączone dane wejściowe został kliknięty).


Minusem jest to, że ta sztuczka niestety nie działa w starszych przeglądarkach, które nie obsługują pointer-eventswłaściwości CSS. (Powinien działać z IE 11, FF v3.6, Chrome v4): caniuse.com/#search=pointer-events

Jeśli potrzebujesz obsługi starszych przeglądarek, musisz użyć jednej z pozostałych odpowiedzi!

Doin
źródło
Nie byłem pewien, czy input[disabled]pasują również do elementów wyłączonych przez JavaScript ( element.disabled = true;), ale wydaje się, że tak. W każdym razie uważam, że jest input:disabledczystszy.
Martin
To wydaje się być dobrym rozwiązaniem, jednak nie działa dla mnie w IE11! Mówisz także FF 38+ i Chrome 31+, ale twój link caniuse mówi FF 3.6+ i Chrome 4+?
user764754
@ user764754 ... mój błąd, nie zdawałem sobie sprawy, że muszę kliknąć „Pokaż wszystko” na stronie caniuse, aby uzyskać wcześniejsze wersje przeglądarki! Naprawiłem to. Jeśli chodzi o IE11, właśnie go przetestowałem i działa dobrze (zobacz kod jsfiddle.net/7kkszq1c/1 , chociaż z jakiegoś powodu strona jsFiddle nie działała dla mnie w IE11, musiałem wkleić go do pliku. plik htm zamiast)
Doin
Dziękuję za aktualizację! W międzyczasie zauważyłem również, że działa na stronie internetowej w IE11, ale nie z jsfiddle. Może z powodu iframe jsfiddle ...
user764754
2
@Protectorone: disabled jest pseudoklasą od CSS 3: w3.org/TR/css3-selectors/#UIstates
Martin
15

Sugerowałbym alternatywę - użyj CSS:

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

zamiast atrybutu disabled. Następnie możesz dodać własne atrybuty CSS, aby zasymulować wyłączone wejście, ale z większą kontrolą.

Ron Reiter
źródło
4
działa tylko z ie10, zbyt wielu użytkowników ma ie9 / 8. więc nie jest to wiarygodna alternatywa.
koduje
Nadal powoduje to opublikowanie pola po przesłaniu formularza, co w wielu przypadkach jest niepożądane.
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
źródło
5
Ale to nie działa w FireFox - i o to właśnie chodziło!
GarethOwen,
6

Zamiast tego disabledmożesz rozważyć użycie readonly. Za pomocą dodatkowego CSS możesz stylizować dane wejściowe, aby wyglądały jak disabledpole.

W rzeczywistości jest inny problem. Zdarzenie jest changeuruchamiane tylko wtedy, gdy element traci fokus, co nie jest logiczne w przypadku disabledpola. Prawdopodobnie wypychasz dane do tego pola z innego połączenia. Aby to zadziałało, możesz użyć zdarzenia „bind”.

$('form').bind('change', 'input', function () {
    console.log('Do your thing.');
});
Nykac
źródło
Jeśli się nie mylę, formularz zostanie przesłany tylko do odczytu
Pierre de LESPINAY,
To jest poprawne. Następnie należy go połączyć z @ npth anwsner.
Nykac,
Dzięki, to było inteligentnie czyste i optymalne dla mojej sprawy.
Sultanos
4

LUB zrób to za pomocą jQuery i CSS!

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

W ten sposób sprawiasz, że element wygląda na wyłączony i żadne zdarzenia wskaźnika nie są uruchamiane, ale umożliwia propagację, a po przesłaniu możesz użyć atrybutu „ignoruj”, aby go zignorować.

Sidonaldson
źródło
@Precastic, to prawda, ale w tym momencie działa prawie dla wszystkich innych przeglądarek i możesz użyć wielopełniacza dla np. <11 . Sidonaldson, dlaczego nie użyć prostego CSS do zastosowania stylów?
KyleMit,
@KyleMit możesz dodać klasę zamiast ustawiać style, ale nie o to chodzi w tym wątku! Sugerowałem tylko zdarzenia wskaźnikowe, które nadal są dobrą i poprawną odpowiedzią w zależności od macierzy przeglądarki, dla której budujesz. I dzięki za każdego, kto zaznaczył tę odpowiedź, to trochę jest do bani, ponieważ nic tutaj nie jest niepoprawne: /
sidonaldson
1
@sidonaldson, To dobra odpowiedź, więc również chciałbym, żeby była wyżej w rankingu. Nie jestem pewien, co robi atrybut ignorowania . Ale chodziło mi o CSS, że nie sądzę, że potrzebujemy jQuery, aby być narzędziem do stosowania CSS. Możesz po prostu skonfigurować regułę CSS, która była kierowana na ten sam selektor, a także wyłączała zdarzenia wskaźnika. W tym skrzydle jQuery i CSS powinny robić to samo, ale CSS będzie znacznie wydajniejszy.
KyleMit,
@KyleMit ah, dobrze zakładając, że formularz jest przesłany, będziesz musiał w jakiś sposób powiedzieć backendowi, aby zignorował to pole, jeśli zawierało ono wartość (ponieważ fałszowanie jest wyłączone).
sidonaldson
Zgadzam się, że CSS może być bardziej wydajny, ponieważ możesz używać selektora opartego na atrybucie! Sprawdź to demo, w którym dopasowałem własne wyłączone pole chromes
sidonaldson
0

Mieliśmy dzisiaj taki problem, ale nie chcieliśmy zmieniać HTML. Aby to osiągnąć, użyliśmy zdarzenia mouseenter

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');
Raul Sanchez
źródło
-1

Znajduję inne rozwiązanie:

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

Klasa „disabled” imituje wyłączony element przez krycie:

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

A następnie anuluj zdarzenie, jeśli element jest wyłączony i usuń klasę:

$(document).on('click','input.disabled',function(event) {
    event.preventDefault();
    $(this).removeClass('disabled');
});
npth
źródło
Część JavaScript nie działa dla mnie. Poza tym nie odpowiada na pytanie, ponieważ dotyczy włączenia nieaktywnego wejścia. W tym przykładzie nie jest on jednak wyłączony na początku i dlatego jest wysyłany po przesłaniu.
Raimund Krämer