เหตุการณ์ในอินพุตที่ปิดใช้งาน


234

เห็นได้ชัดว่าปิดการใช้งาน<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 และวนลูปของอินพุตในตัวจัดการส่งได้โดยปิดใช้งานสิ่งที่ไม่เปิดใช้งานจริง
ptrk

คำตอบ:


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 ซึ่งในกรณีนี้การปิดทับจะไม่จำเป็น
Tim Down

11
@Tim: แน่นอนมันไม่จำเป็น แต่ก็ยังคงเป็น HTML ที่ถูกต้อง มันเป็นเพียงแค่พลังแห่งนิสัยและฉันรู้สึกว่ามันดูดีขึ้น
Andy E

1
ขอบคุณแอนดี้มันค่อนข้างฉลาด ไม่ง่ายกว่านี้อีกเหรอ? คุณรู้หรือไม่ว่าทำไมสัญญาณอินพุตที่ถูกป้อนเข้าไม่สามารถจัดการได้?
Pierre de LESPINAY

2
สิ่งนี้ไม่สมเหตุสมผล: องค์ประกอบ html อื่น ๆ จัดการกับเหตุการณ์เมาส์ทำไมจึงไม่ใช่องค์ประกอบที่ถูกปิดใช้งาน (เช่นmouseenterฯลฯ )
Augustin Riedinger

7
คุณสามารถหยุดองค์ประกอบที่ถูกปิดใช้งานจาก "ทิ้ง" การคลิกของคุณโดยใส่input[disabled] {pointer-events:none}CSS ของคุณ จากนั้นคลิกจะทำงานเหมือนกับว่าคุณคลิกองค์ประกอบหลัก IMHO นี่เป็นวิธีที่ง่ายและสะอาดที่สุด แต่น่าเสียดายที่ใช้ได้เฉพาะกับเบราว์เซอร์ที่สนับสนุน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');
})

5
+1 นี่คือข้อเสนอแนะทางเลือกที่เหมาะสม ข้อเสียเพียงอย่างเดียวคือกล่องอินพุตจะไม่ใช้สไตล์การปิดการใช้งานซึ่งแตกต่างกันไประหว่างเบราว์เซอร์ดังนั้นจึงยากที่จะทำให้มันดูสอดคล้องกับความคาดหวังของผู้ใช้เกี่ยวกับอินพุตที่ปิดใช้งาน
Andy E

จริง บางทีนี่อาจใช้งานกับ CSS ได้ใช่ไหม แต่ใช่มันจะไม่ได้มีลักษณะเช่นเดียวกับช่องป้อนข้อมูลปกติ diabled
Tokimon

ทางเลือกที่ยอดเยี่ยม ฉันชอบอันนี้ดีกว่าเพราะคุณสามารถจัดแต่งทรงผมที่จำเป็นด้วย CSS (เช่นทำให้ปิดการใช้งาน LOOK) แต่ยังมีกิจกรรมให้ใช้งาน
Joshua

62

องค์ประกอบที่ปิดใช้งานคลิก "กิน" ในบางเบราว์เซอร์ - พวกเขาไม่ตอบสนองต่อพวกเขาและไม่อนุญาตให้มีการจัดการโดยตัวจัดการเหตุการณ์ที่ใดก็ได้ในองค์ประกอบหรือภาชนะใด ๆ

IMHO วิธีที่ง่ายและสะอาดที่สุดในการ "แก้ไข" สิ่งนี้ (ถ้าคุณจำเป็นต้องบันทึกการคลิกในองค์ประกอบที่ถูกปิดใช้งานเช่น OP) เพียงเพิ่ม CSS ต่อไปนี้ในหน้าของคุณ:

input[disabled] {pointer-events:none}

สิ่งนี้จะทำการคลิกใด ๆ ที่อินพุตที่ถูกปิดใช้งานอยู่ในองค์ประกอบหลักซึ่งคุณสามารถจับภาพได้ตามปกติ (หากคุณมีอินพุตที่ถูกปิดใช้งานหลายตัวคุณอาจต้องการใส่แต่ละอันลงในคอนเทนเนอร์ส่วนตัวของมันเองหากยังไม่ได้จัดวางไว้เช่นนั้นเป็นพิเศษ<span>หรือก<div>พูดเพียงเพื่อให้แยกแยะอินพุตที่ปิดใช้งานได้ง่าย ถูกคลิก)


ข้อเสียคือเคล็ดลับนี้น่าเสียดายที่ไม่สามารถใช้ได้กับเบราว์เซอร์รุ่นเก่าที่ไม่สนับสนุนpointer-eventsคุณสมบัติ CSS (ควรทำงานได้จาก IE 11, FF v3.6, Chrome v4): caniuse.com/#search=pointer-events

หากคุณต้องการสนับสนุนเบราว์เซอร์รุ่นเก่าคุณจะต้องใช้คำตอบอย่างใดอย่างหนึ่ง!


ฉันไม่แน่ใจว่าinput[disabled]จะจับคู่องค์ประกอบที่ปิดใช้งานโดย JavaScript ( element.disabled = true;) แต่ดูเหมือนว่าจะเป็นเช่นนั้น อย่างไรก็ตามฉันพบว่าinput:disabledสะอาดขึ้น
Martin

ดูเหมือนว่าจะเป็นทางออกที่ดี แต่ไม่ได้ผลสำหรับฉันใน IE11! คุณบอกว่า FF 38+ และ Chrome 31+ แต่ลิงก์ caniuse ของคุณบอกว่า FF 3.6+ และ Chrome 4+?
user764754

@ user764754 ... ความผิดพลาดของฉันฉันไม่ทราบว่าฉันต้องคลิก "แสดงทั้งหมด" บนหน้า caniuse เพื่อรับเบราว์เซอร์เวอร์ชันก่อนหน้า! ได้แก้ไขแล้วว่า สำหรับ IE11 ฉันเพิ่งทดสอบและใช้งานได้ดี (ดูjsfiddle.net/7kkszq1c/1สำหรับรหัสแม้ว่าด้วยเหตุผลบางอย่างที่ไซต์ jsFiddle ไม่ทำงานสำหรับฉันใน IE11 ฉันต้องวางลงใน a ไฟล์ htm แทน)
Doin

ขอบคุณสำหรับการอัพเดท! ในขณะเดียวกันฉันก็สังเกตเห็นว่ามันทำงานบนเว็บไซต์ใน IE11 แต่ไม่ได้มี jsfiddle อาจเป็นเพราะ iframe ของ jsfiddle ...
user764754

2
@Protectorone: ปิดใช้งานเป็นคลาสหลอกตั้งแต่ CSS 3: w3.org/TR/css3-selectors/#UIstates
Martin

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

การป้อนข้อมูลแบบอ่านอย่างเดียวจะยังคงถูกส่งมาพร้อมกับแบบฟอร์มหากฉันไม่เข้าใจผิด
Pierre de LESPINAY

ถูกต้อง. มันควรจะรวมกับ @npth anwsner
Nykac

ขอบคุณนั่นสะอาดและฉลาดสำหรับกรณีของฉัน
Sultanos

4

หรือทำสิ่งนี้กับ jQuery และ CSS!

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

วิธีนี้คุณทำให้องค์ประกอบดูไม่ทำงานและไม่มีเหตุการณ์ตัวชี้ใด ๆ ทำงาน แต่จะอนุญาตการเผยแพร่และหากส่งคุณสามารถใช้แอตทริบิวต์ 'ละเว้น' เพื่อเพิกเฉยได้


@Precastic ว่าเป็นความจริง แต่มันเหมาะกับเกือบทุกเบราว์เซอร์อื่น ๆ ที่จุดนี้และคุณสามารถใช้polyfill สำหรับ IE <11 อย่างไรก็ตามทำไมไม่ใช้ CSS แบบตรงเพื่อใช้สไตล์?
KyleMit

@ KyleMit คุณสามารถเพิ่มคลาสได้แทนที่จะกำหนดสไตล์ แต่นั่นไม่ใช่สิ่งที่หัวข้อนี้เกี่ยวข้อง! ฉันแค่แนะนำเหตุการณ์ตัวชี้ซึ่งยังคงเป็นคำตอบที่ดีและถูกต้องขึ้นอยู่กับเมทริกซ์เบราว์เซอร์ที่คุณกำลังสร้าง และขอบคุณสำหรับทุกคนที่ทำเครื่องหมายคำตอบนี้ลงว่า kinda sucks เพราะไม่มีอะไรที่นี่ไม่ถูกต้อง: /
sidonaldson

1
@sidonaldson มันเป็นคำตอบที่ดีดังนั้นฉันก็หวังว่ามันจะได้อันดับที่สูงขึ้นเช่นกัน ฉันไม่แน่ใจว่าแอตทริบิวต์การเพิกเฉยทำอะไร แต่ประเด็นของฉันเกี่ยวกับ CSS คือฉันไม่คิดว่าเราต้องการ jQuery เพื่อเป็นพาหนะสำหรับการใช้ CSS คุณสามารถตั้งค่ากฎ CSS ที่กำหนดเป้าหมายตัวเลือกเดียวกันและปิดใช้งานกิจกรรมตัวชี้ ในซอนี้ jQuery และ CSS ควรทำสิ่งเดียวกัน แต่ CSS จะมีประสิทธิภาพมากกว่า
KyleMit

@ KyleMit อ่าสมมติว่ามีการส่งแบบฟอร์มคุณจะต้องบอกแบ็กเอนด์ให้ละเว้นฟิลด์นั้นถ้ามีค่า (เนื่องจากเรากำลังปิดใช้งานการปลอมแปลง)
sidonaldson

ฉันเห็นด้วย 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');
});

ส่วน JavaScript ไม่ทำงานสำหรับฉัน นอกเหนือจากนั้นจะไม่ตอบคำถามเนื่องจากเป็นเรื่องเกี่ยวกับการเปิดใช้งานอินพุตที่ปิดใช้งาน ในตัวอย่างนี้อย่างไรก็ตามมันจะไม่ถูกปิดใช้งานเมื่อเริ่มต้นและจะถูกส่งเมื่อส่ง
Raimund Krämer

-2

ข้อเสนอแนะที่นี่ดูเหมือนจะเป็นตัวเลือกที่ดีสำหรับคำถามนี้เช่นกัน

กำลังทำการคลิกเหตุการณ์บนองค์ประกอบที่ถูกปิดใช้งานหรือไม่ Javascript jQuery

jQuery('input#submit').click(function(e) {
    if ( something ) {        
        return false;
    } 
});

เหตุการณ์การคลิกอาจไม่เกิดขึ้นกับคุณลักษณะที่ปิดใช้งาน
สวัสดีจักรวาล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.