Событие на отключенном входе

235

Видимо отключенный <input>не обрабатывается ни одним событием

Есть ли способ обойти эту проблему?

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

Здесь мне нужно нажать на вход, чтобы включить его. Но если я не активирую его, вход не должен быть опубликован.

Пьер де ЛЕСПИНАЙ
источник
Вот хорошая альтернатива blog.pengoworks.com/index.cfm/2010/4/23/...
Вы можете использовать CSS-pretend-disable и перебирать входы в обработчике onSubmit, отключая неактивированные по-настоящему.
ПТРК

Ответы:

267

Отключенные элементы не запускают события мыши. Большинство браузеров распространяют событие, происходящее из отключенного элемента, вверх по дереву DOM, поэтому обработчики событий могут быть размещены на элементах контейнера. Тем не менее, Firefox не демонстрирует такого поведения, он просто ничего не делает, когда вы нажимаете на отключенный элемент.

Я не могу придумать лучшего решения, но для полной кросс-браузерной совместимости вы можете поместить элемент перед отключенным вводом и поймать щелчок по этому элементу. Вот пример того, что я имею в виду:

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

Пример: http://jsfiddle.net/RXqAm/170/ (обновлено для использования jQuery 1.7 с propвместо attr).

Энди Э
источник
2
Маленькая вещь: если вы используете disabledатрибут без значения, это подразумевает HTML, а не XHTML, и в этом случае закрывающий слеш не нужен.
Тим Даун
11
@Tim: на самом деле это не нужно, но все равно это действительный HTML. Это просто сила привычки, и я чувствую, что это выглядит лучше.
Энди Э
1
Спасибо Энди, это довольно умно. Разве не проще? Знаете ли вы, почему неактивные входные данные не обрабатываются?
Пьер де Леспинэй
2
Это не имеет смысла: любой другой html-элемент обрабатывает события мыши, почему бы не отключить элемент (например mouseenter, и т . Д.)
Августин Ридингер,
8
Вы можете остановить отключенный элемент от «отбрасывания» ваших кликов, вставив input[disabled] {pointer-events:none}свой CSS. Тогда щелчок ведет себя так, как будто вы щелкнули родительский элемент. ИМХО, это самое простое и чистое решение, но, к сожалению, оно работает только для браузеров, которые поддерживают pointer-eventsсвойство CSS: caniuse.com/#search=pointer-events
Doin
70

Может быть, вы могли бы сделать поле доступным только для чтения и при отправке отключить все поля только для чтения

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

и вход (+ скрипт) должен быть

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

$('input[readonly]').click(function () {
    $(this).removeAttr('readonly');
})
Tokimon
источник
5
+1, это достойное альтернативное предложение. Единственным недостатком является то, что поле ввода не будет принимать отключенный стиль, который варьируется в разных браузерах, поэтому было бы трудно заставить его выглядеть в соответствии с ожиданиями пользователя относительно отключенного ввода.
Энди
правда. Возможно, это можно обойти с помощью CSS? Но да, это не выглядело бы так же, как обычные поля ввода с
диалектами
Отличное альтернативное решение. Мне это нравится больше, потому что вы можете делать любые необходимые стили с помощью CSS (т.е. отключать LOOK), но при этом иметь доступные события.
Джошуа
63

Отключенные элементы «съедают» клики в некоторых браузерах - они не реагируют на них и не позволяют захватывать их обработчиками событий в любом месте элемента или любого из его контейнеров.

ИМХО самый простой и чистый способ «исправить» это (если вам действительно нужно захватывать клики на отключенных элементах, как это делает OP), это просто добавить следующий CSS на вашу страницу:

input[disabled] {pointer-events:none}

Это приведет к тому, что любые щелчки на отключенном входе будут попадать на родительский элемент, где вы сможете их нормально захватывать. (Если у вас есть несколько отключенных входов, вы можете захотеть поместить каждый в отдельный контейнер самостоятельно, если они еще не выложены таким образом - дополнительный <span>или <div>, скажем, - просто, чтобы было легко отличить, какой отключенный ввод была нажата).


Недостатком является то, что этот трюк, к сожалению, не работает для старых браузеров, которые не поддерживают pointer-eventsсвойство CSS. (Должно работать с IE 11, FF v3.6, Chrome v4): caniuse.com/#search=pointer-events

Если вам нужна поддержка старых браузеров, вам нужно использовать один из других ответов!

Doin
источник
Я не был уверен, input[disabled]будут ли совпадать элементы, отключенные JavaScript ( element.disabled = true;), но, похоже, так и есть. Во всяком случае, я нахожу input:disabledчище.
Мартин
Это похоже на хорошее решение, хотя в IE11 у меня не работает! Также вы говорите FF 38+ и Chrome 31+, но ваша ссылка caniuse говорит FF 3.6+ и Chrome 4+?
user764754
@ user764754 ... моя ошибка, я не осознавал, что мне нужно нажать "Показать все" на странице caniuse, чтобы получить более ранние версии браузера! Исправили это. Что касается IE11, я только что протестировал его, и он отлично работает (см. Jsfiddle.net/7kkszq1c/1 для кода, хотя по какой-то причине сайт jsFiddle у меня не работал в IE11, мне пришлось вставить его в. вместо файла htm)
Doin
Спасибо за обновление! В то же время я также заметил, что он работает на веб-сайте в IE11, но не с jsfiddle. Может быть из-за jsfiddle iframe ...
user764754
2
@Protectorone: disabled является псевдоклассом начиная с CSS 3: w3.org/TR/css3-selectors/#UIstates
Мартин,
15

Я бы предложил альтернативу - использовать CSS:

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

вместо отключенного атрибута. Затем вы можете добавить свои собственные атрибуты CSS для имитации отключенного ввода, но с большим контролем.

Рон Рейтер
источник
4
работает только с ie10, слишком много пользователей имеют ie9 / 8. так что не надежная альтернатива.
кодирует
Это по-прежнему приводит к тому, что поле отправляется при отправке формы, что нежелательно во многих случаях.
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
Но это не работает на FireFox - и в этом весь смысл!
GarethOwen
6

Вместо этого disabledвы можете рассмотреть возможность использования readonly. С некоторым дополнительным CSS вы можете стилизовать ввод, чтобы он выглядел какdisabled поле.

На самом деле есть еще одна проблема. Событие changeсрабатывает только тогда, когда элемент теряет фокус, что не логично, если рассматривать disabledполе. Возможно, вы вводите данные в это поле из другого вызова. Чтобы сделать эту работу, вы можете использовать событие «связать».

$('form').bind('change', 'input', function () {
    console.log('Do your thing.');
});
Nykac
источник
Если я не ошибаюсь,
входные данные только для чтения
Это правильно. Затем его следует объединить с @npth anwsner.
Nykac
Спасибо, это было умно и чисто для моего случая.
Султанос
4

ИЛИ сделать это с помощью jQuery и CSS!

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

Таким образом, вы заставляете элемент выглядеть отключенным, и никакие события указателя не сработают, но все же он разрешает распространение, и если он представлен, вы можете использовать атрибут ignore, чтобы игнорировать его.

sidonaldson
источник
@Precastic, это правда, но на данный момент он работает почти для всех других браузеров, и вы можете использовать polyfill для ie <11 . Сидональдсон, почему бы не использовать прямой CSS для применения стилей?
KyleMit
@KyleMit, вы можете добавить класс, а не устанавливать стили, но это не то, о чем этот поток! Я только предлагал указатель событий, который все еще является хорошим и правильным ответом в зависимости от матрицы браузера, для которой вы строите. И спасибо всем, кто отметил этот ответ, что это отстой, потому что здесь нет ничего неправильного: /
sidonaldson
1
@sidonaldson, это хороший ответ, поэтому я бы тоже хотел, чтобы он был выше. Я не уверен, что делает атрибут ignore . Но моя точка зрения на CSS заключалась в том, что я не думаю, что нам нужен jQuery, чтобы быть средством для применения CSS. Вы можете просто установить правило CSS, которое предназначено для того же селектора, а также отключить события указателя. В этой скрипке jQuery и CSS должны делать одно и то же, но CSS будет гораздо более производительным.
KyleMit
@KyleMit ах, хорошо предполагая, что форма отправлена, вам придется каким-то образом указать бэкэнду игнорировать это поле, если оно содержит значение (так как мы подделываем спуфинг).
Сидональдсон
Я согласен, что CSS может быть более мощным, так как вы можете использовать селектор на основе атрибута! Проверьте это демо, где я соответствовал собственному отключенному полю chromes
sidonaldson
0

У нас сегодня была такая проблема, но мы не хотели менять HTML. Таким образом, мы использовали событие 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');
Рауль Санчес
источник
-1

Я нахожу другое решение:

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

Класс "disabled" имитирует отключенный элемент по непрозрачности:

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

А затем отмените событие, если элемент отключен, и удалите класс:

$(document).on('click','input.disabled',function(event) {
    event.preventDefault();
    $(this).removeClass('disabled');
});
NPTH
источник
Часть JavaScript не работает для меня. Кроме того, он не отвечает на вопрос, поскольку касается включения отключенного ввода. В этом примере, однако, он не отключен в начале и, следовательно, отправляется при отправке.
Раймунд Кремер
-2

предложение здесь выглядит хорошим кандидатом на этот вопрос, а также

Выполнение события клика на отключенном элементе? Javascript JQuery

jQuery('input#submit').click(function(e) {
    if ( something ) {        
        return false;
    } 
});
katzmopolitan
источник
Событие щелчка, вероятно, не произойдет с отключенными атрибутами.
Привет Вселенная