Sự kiện trên đầu vào bị vô hiệu hóa


234

Rõ ràng một người khuyết tật <input>không được xử lý bởi bất kỳ sự kiện

Có cách nào để giải quyết vấn đề này không?

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

Ở đây, tôi cần nhấp vào đầu vào để kích hoạt nó. Nhưng nếu tôi không kích hoạt nó, đầu vào không nên được đăng.


Đây là một blog

Bạn có thể sử dụng CSS giả vờ vô hiệu hóa và lặp qua các đầu vào trong trình xử lý onSubmit, vô hiệu hóa các đầu vào không được kích hoạt thực sự.
ptrk

Câu trả lời:


267

Các phần tử bị vô hiệu hóa không bắn các sự kiện chuột. Hầu hết các trình duyệt sẽ truyền bá một sự kiện bắt nguồn từ phần tử bị vô hiệu hóa trên cây DOM, vì vậy trình xử lý sự kiện có thể được đặt trên các phần tử container. Tuy nhiên, Firefox không thể hiện hành vi này, nó hoàn toàn không làm gì khi bạn nhấp vào một yếu tố bị vô hiệu hóa.

Tôi không thể nghĩ ra giải pháp nào tốt hơn, nhưng để tương thích hoàn toàn với trình duyệt, bạn có thể đặt một phần tử trước đầu vào bị vô hiệu hóa và bắt nhấp vào phần tử đó. Đây là một ví dụ về những gì tôi muốn nói:

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

Ví dụ: http://jsfiddle.net/RXqAm/170/ (được cập nhật để sử dụng jQuery 1.7 propthay vì attr).


2
Điều nhỏ: nếu bạn đang sử dụng disabledthuộc tính không có giá trị, điều đó hàm ý HTML chứ không phải XHTML, trong trường hợp đó, dấu gạch chéo đóng là không cần thiết.
Tim Down

11
@Tim: thực sự không cần thiết, nhưng nó vẫn là HTML hợp lệ. Đó chỉ là một thói quen thực sự và tôi cảm thấy nó có vẻ tốt hơn.
Andy E

1
Thx Andy, điều này khá thông minh. Có đơn giản hơn không? Bạn có biết tại sao các đầu vào được kích hoạt không thể cầm tay được không?
Pierre de LESPINAY

2
Điều này không có ý nghĩa: bất kỳ phần tử html nào khác xử lý các sự kiện chuột, tại sao không phải là phần tử bị vô hiệu hóa (ví dụ: mouseenterv.v.)
Augustin Riedinger

7
Bạn có thể ngăn phần tử bị vô hiệu hóa "vứt bỏ" các nhấp chuột của mình bằng cách đưa input[disabled] {pointer-events:none}vào CSS của bạn. Sau đó, nhấp chuột hoạt động như thể bạn đã nhấp vào phần tử cha. IMHO đây là giải pháp đơn giản nhất, gọn gàng nhất, nhưng thật không may, nó chỉ hoạt động đối với các trình duyệt hỗ trợ thuộc tính pointer-eventsCSS: caniuse.com/#search=pulum-events
Doin

70

Có lẽ bạn có thể làm cho trường chỉ đọc và khi gửi vô hiệu hóa tất cả các trường chỉ đọc

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

và đầu vào (+ script) phải là

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

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

5
+1, đây là một đề xuất thay thế hợp lý. Nhược điểm duy nhất là hộp đầu vào sẽ không có kiểu dáng bị vô hiệu hóa, nó khác nhau giữa các trình duyệt nên khó có thể làm cho nó trông phù hợp với mong đợi của người dùng về đầu vào bị vô hiệu hóa.
Andy E

thật. Có lẽ điều này có thể được giải quyết xung quanh với CSS? Nhưng vâng, nó sẽ không có giao diện giống như các trường nhập liệu bị
xáo trộn

Giải pháp thay thế tuyệt vời. Tôi thích cái này hơn vì bạn có thể thực hiện bất kỳ kiểu dáng cần thiết nào với CSS (nghĩa là làm cho nó bị vô hiệu hóa) mà vẫn có sẵn các sự kiện.
Joshua

62

Các phần tử bị vô hiệu hóa "ăn" các nhấp chuột trong một số trình duyệt - chúng không phản hồi với chúng, cũng không cho phép chúng bị bắt bởi các trình xử lý sự kiện ở bất kỳ đâu trên phần tử hoặc bất kỳ vùng chứa nào của nó.

IMHO cách đơn giản nhất, gọn gàng nhất để "khắc phục" điều này (nếu thực tế bạn cần phải nắm bắt các nhấp chuột vào các yếu tố bị vô hiệu hóa như OP) chỉ là thêm CSS sau vào trang của bạn:

input[disabled] {pointer-events:none}

Điều này sẽ làm cho bất kỳ nhấp chuột nào vào đầu vào bị vô hiệu hóa rơi vào phần tử cha, nơi bạn có thể chụp chúng bình thường. (Nếu bạn có một vài đầu vào bị vô hiệu hóa, bạn có thể muốn đặt từng loại vào một thùng chứa riêng, nếu chúng chưa được đặt theo cách đó - thêm <span>hoặc <div>nói, chỉ để giúp dễ dàng phân biệt đầu vào bị vô hiệu hóa nào đã được nhấp).


Nhược điểm là thủ thuật này không may không hoạt động đối với các trình duyệt cũ không hỗ trợ thuộc tính pointer-eventsCSS. (Nó nên hoạt động từ IE 11, FF v3.6, Chrome v4): caniuse.com/#search=pulum-events

Nếu bạn cần hỗ trợ các trình duyệt cũ hơn, bạn sẽ cần sử dụng một trong những câu trả lời khác!


Tôi không chắc liệu input[disabled]có khớp với các phần tử bị vô hiệu hóa bởi JavaScript ( element.disabled = true;) không nhưng có vẻ như vậy. Dù sao, tôi thấy input:disabledsạch hơn.
Martin

Đây có vẻ là một giải pháp tốt, mặc dù tôi không làm việc với IE11! Ngoài ra, bạn nói FF 38+ và Chrome 31+ nhưng liên kết caniuse của bạn nói FF 3.6+ và Chrome 4+?
user764754

@ user764754 ... lỗi của tôi, tôi không nhận ra mình cần nhấp vào "Hiển thị tất cả" trên trang caniuse để có các phiên bản trình duyệt cũ hơn! Đã sửa nó rồi. Đối với IE11, tôi mới thử nghiệm và nó hoạt động tốt (xem jsfiddle.net/7kkszq1c/1 để biết mã, mặc dù vì một số lý do, trang jsFiddle không hoạt động với tôi trong IE11, tôi đã phải dán nó vào. tập tin htm thay thế)
Doin

Cảm ơn các cập nhật! Trong khi đó, tôi cũng quan sát thấy rằng nó hoạt động trên một trang web trong IE11 nhưng không phải với jsfiddle. Có lẽ vì ifs jsfiddle ...
user764754

2
@Protectorone: bị vô hiệu hóa là lớp giả vì CSS 3: w3.org/TR/css3-selector/#UIstates
Martin

15

Tôi sẽ đề xuất một giải pháp thay thế - sử dụng CSS:

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

thay vì thuộc tính bị vô hiệu hóa. Sau đó, bạn có thể thêm các thuộc tính CSS của riêng mình để mô phỏng đầu vào bị vô hiệu hóa, nhưng với nhiều quyền kiểm soát hơn.


4
chỉ hoạt động với eg10, quá nhiều người dùng có eg9 / 8. vì vậy không phải là sự thay thế đáng tin cậy.
mã hóa

Điều này vẫn khiến trường được đăng khi biểu mẫu được gửi, điều không mong muốn trong nhiều trường hợp.
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
Nhưng điều này không hoạt động trên FireFox - và đó là toàn bộ vấn đề!
GarethOwen

6

Thay vì disabled , bạn có thể xem xét sử dụng readonly. Với một số CSS bổ sung, bạn có thể định kiểu đầu vào để nó trông giống như một disabledtrường.

Thực sự có một vấn đề khác. Sự kiện changechỉ kích hoạt khi phần tử mất tập trung, không logic khi xem xét một disabledtrường. Có lẽ bạn đang đẩy dữ liệu vào trường này từ một cuộc gọi khác. Để thực hiện công việc này, bạn có thể sử dụng sự kiện 'liên kết'.

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

Một đầu vào chỉ đọc sẽ vẫn được gửi với biểu mẫu nếu tôi không nhầm
Pierre de LESPINAY

Đúng rồi. Sau đó nên kết hợp với @npth anwsner.
Nykac

Cảm ơn, đó là thông minh sạch sẽ và tối ưu cho trường hợp của tôi.
Sultanos

4

HOẶC làm điều này với jQuery và CSS!

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

Bằng cách này, bạn làm cho phần tử trông bị vô hiệu hóa và không có sự kiện con trỏ nào sẽ kích hoạt, tuy nhiên nó cho phép lan truyền và nếu được gửi, bạn có thể sử dụng thuộc tính 'bỏ qua' để bỏ qua nó.


@Precastic, điều đó đúng, nhưng nó hoạt động cho hầu hết các trình duyệt khác tại thời điểm này và bạn có thể sử dụng một polyfill cho tức là <11 . sidonaldson, tại sao không sử dụng CSS thẳng để áp dụng các kiểu?
KyleMit

@KyleMit bạn có thể thêm một lớp thay vì đặt kiểu, nhưng đó không phải là chủ đề này! Tôi chỉ đề xuất các sự kiện con trỏ vẫn là một câu trả lời đúng và chính xác tùy thuộc vào ma trận trình duyệt mà bạn đang xây dựng. Và cảm ơn tất cả những người đã đánh dấu câu trả lời này rằng điều đó thật tệ vì không có gì ở đây là không chính xác: /
sidonaldson

1
@sidonaldson, Đó là một câu trả lời hay vì vậy tôi cũng mong muốn nó được xếp hạng cao hơn. Tôi không chắc thuộc tính bỏ qua làm gì . Nhưng quan điểm của tôi về CSS là tôi không nghĩ rằng chúng ta cần jQuery là phương tiện để áp dụng CSS. Bạn chỉ có thể thiết lập quy tắc CSS nhắm mục tiêu vào cùng một bộ chọn và cũng vô hiệu hóa các sự kiện con trỏ. Trong câu đố này , jQuery và CSS sẽ làm điều tương tự, nhưng CSS sẽ hiệu quả hơn nhiều.
KyleMit

@KyleMit ah, giả sử mẫu đã được gửi, bạn sẽ phải bằng cách nào đó nói với phụ trợ bỏ qua trường đó nếu nó chứa một giá trị (vì chúng tôi giả mạo bị vô hiệu hóa).
sidonaldson

Tôi đồng ý CSS có thể mạnh hơn vì bạn có thể sử dụng bộ chọn dựa trên một thuộc tính! Kiểm tra bản demo này trong đó tôi đã khớp với trường bị vô hiệu hóa của riêng chromes
sidonaldson

0

Hôm nay chúng tôi có một vấn đề như thế này, nhưng chúng tôi không muốn thay đổi HTML. Vì vậy, chúng tôi đã sử dụng sự kiện mouseenter để đạt được điều đó

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

Tôi tìm một giải pháp khác:

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

Lớp "bị vô hiệu hóa" bắt chước phần tử bị vô hiệu hóa bằng độ mờ:

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

Và sau đó hủy bỏ sự kiện nếu phần tử bị vô hiệu hóa và xóa lớp:

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

Phần JavaScript không hoạt động đối với tôi. Ngoài ra, nó không trả lời câu hỏi, vì đó là về việc cho phép một đầu vào bị vô hiệu hóa. Tuy nhiên, trong ví dụ này, nó không bị vô hiệu hóa khi bắt đầu và do đó được gửi khi gửi.
Raimund Krämer

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.