วิธีรับข้อความของกล่องข้อความอินพุตระหว่าง onKeyPress?


87

ฉันกำลังพยายามรับข้อความในกล่องข้อความตามที่ผู้ใช้พิมพ์ ( jsfiddle playground ):

function edValueKeyPress() {
    var edValue = document.getElementById("edValue");
    var s = edValue.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onKeyPress="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

รหัสทำงานโดยไม่มีข้อผิดพลาดยกเว้นว่าค่าของinput textกล่องระหว่างonKeyPressจะเป็นค่าก่อนการเปลี่ยนแปลงเสมอ:

ใส่คำอธิบายภาพที่นี่

คำถาม : ฉันจะรับข้อความของกล่องข้อความได้onKeyPressอย่างไร?

โบนัสแช็ต

มีสามเหตุการณ์ที่เกี่ยวข้องกับ"ผู้ใช้กำลังพิมพ์"ใน HTML DOM:

  • onKeyDown
  • onKeyPress
  • onKeyUp

ในWindowsลำดับของWM_Keyข้อความจะมีความสำคัญเมื่อผู้ใช้กดคีย์ค้างไว้และคีย์จะเริ่มซ้ำ:

  • WM_KEYDOWN('a')- ผู้ใช้มีการผลักดันให้ลงAที่สำคัญ
  • WM_CHAR('a')- aได้รับตัวละครจากผู้ใช้
  • WM_CHAR('a')- aได้รับตัวละครจากผู้ใช้
  • WM_CHAR('a')- aได้รับตัวละครจากผู้ใช้
  • WM_CHAR('a')- aได้รับตัวละครจากผู้ใช้
  • WM_CHAR('a')- aได้รับตัวละครจากผู้ใช้
  • WM_KEYUP('a')- ผู้ใช้ปล่อยAคีย์

จะส่งผลให้อักขระห้าตัวปรากฏในตัวควบคุมข้อความ: aaaaa

ประเด็นสำคัญคือคุณตอบสนองต่อWM_CHARข้อความที่เกิดขึ้นซ้ำ ๆ มิฉะนั้นคุณจะพลาดเหตุการณ์เมื่อกดปุ่ม

ในHTMLสิ่งที่แตกต่างกันเล็กน้อย:

  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyUp

html มอบKeyDownและKeyPressทุกซ้ำที่สำคัญ และKeyUpเหตุการณ์จะเพิ่มขึ้นเมื่อผู้ใช้ปล่อยคีย์เท่านั้น

นำไป

  • ฉันสามารถตอบสนองonKeyDownหรือonKeyPressแต่ทั้งสองยังคงถูกยกขึ้นก่อนที่จะinput.valueมีการอัปเดต
  • ฉันไม่สามารถตอบสนองได้onKeyUpเพราะมันไม่เกิดขึ้นเมื่อข้อความในกล่องข้อความเปลี่ยนไป

คำถาม:ฉันจะรับข้อความของกล่องข้อความได้onKeyPressอย่างไร?

การอ่านโบนัส


1
ฉันเชื่อว่าคุณต้องผนวกการกดแป้นปัจจุบันเข้ากับค่าก่อนที่จะส่งคืน ค่าจะได้รับการอัปเดตใน keyUp แต่ข้อมูลจะพร้อมใช้งานสำหรับคุณใน keyDown
Mathletics

คีย์อัพใช้งานได้สำหรับฉันคุณไม่จำเป็นต้องใช้ jQ สำหรับสิ่งนี้เว้นแต่คุณต้องการเพิ่ม bloat
Ryan B

ก็เพียงพอแล้วเฉพาะ onKeyUp สำหรับงานของคุณ
dmytro

@mit เฉพาะการจัดการonKeyUpไม่แสดงการเปลี่ยนแปลงในกล่องข้อความเมื่อเกิดขึ้น
Ian Boyd

ถ้าคุณต้องการที่จะกดปุ่มใด ๆ และได้รับผลในช่องของสาเหตุที่คุณควรใช้ทั้ง onkeypress และเหตุการณ์ onkeydown ซอโจนาธานเอ็มแต่ถ้าคุณต้องการที่จะได้รับผลโดยไม่ต้องกดปุ่มก็พอเพียง OnKeyUp ไวโอลินของฉัน
dmytro

คำตอบ:


20

การจัดการกับinputเหตุการณ์ที่เป็นโซลูชั่นที่สอดคล้อง: จะได้รับการสนับสนุนสำหรับtextareaและinputองค์ประกอบในเบราว์เซอร์ร่วมสมัยและความรุนแรงว่าเมื่อคุณต้องการ:

function edValueKeyPress() {
    var edValue = document.getElementById("edValue");
    var s = edValue.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;
}
<input id="edValue" type="text" onInput="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

ฉันจะเขียนมันใหม่สักหน่อยแม้ว่า:

function showCurrentValue(event)
{
    const value = event.target.value;
    document.getElementById("lblValue").innerText = value;
}
<input id="edValue" type="text" onInput="showCurrentValue(event)"><br>
The text box contains: <span id="lblValue"></span>


54

ง่าย ๆ เข้าไว้. ใช้ทั้งสองอย่างonKeyPress()และonKeyUp():

<input id="edValue" type="text" onKeyPress="edValueKeyPress()" onKeyUp="edValueKeyPress()">

สิ่งนี้จะดูแลการรับค่าสตริงที่อัปเดตที่สุด (หลังจากคีย์ขึ้น) และยังอัปเดตหากผู้ใช้กดคีย์ค้างไว้

jsfiddle: http://jsfiddle.net/VDd6C/8/


เนื่องจากคำตอบของ arnaud576875 ต้องยอมแพ้และถอยกลับไปที่onKeyUp(การเอาชนะจุดประสงค์ของการใช้งานonKeypress) นี่คือคำตอบที่ง่ายที่สุดสะอาดที่สุดและใกล้เคียงที่สุดที่ทุกคนจะเห็น เฉพาะผู้ใช้ที่สังเกตอย่างรอบคอบที่สุดเท่านั้นที่จะสังเกตเห็นความคิดเห็นไม่ตรงกับสิ่งที่ป้อน
Ian Boyd

@ เอียนยินดีช่วย "ความคิดเห็นไม่ตรงกับสิ่งที่ป้อน" หมายความว่าอย่างไร จำเป็นต้องมีการปรับเปลี่ยนหรือไม่?
Jonathan M

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

19

ค่าของกล่องข้อความอินพุตระหว่าง onKeyPress จะเป็นค่าก่อนการเปลี่ยนแปลงเสมอ

นี่คือวัตถุประสงค์: ช่วยให้ผู้ฟังเหตุการณ์สามารถยกเลิกการกดแป้นได้

หากผู้ฟังเหตุการณ์ยกเลิกเหตุการณ์ค่าจะไม่อัปเดต หากเหตุการณ์จะไม่ถูกยกเลิกค่าที่มีการปรับปรุง แต่หลังจากฟังเหตุการณ์ที่เรียกว่า

หากต้องการรับค่าหลังจากอัปเดตค่าฟิลด์แล้วให้กำหนดเวลาให้ฟังก์ชันทำงานในลูปเหตุการณ์ถัดไป วิธีปกติในการทำเช่นนี้คือการเรียกsetTimeoutด้วยหมดเวลาของ0:

$('#field').keyup(function() {
    var $field = $(this);

    // this is the value before the keypress
    var beforeVal = $field.val();

    setTimeout(function() {

        // this is the value after the keypress
        var afterVal = $field.val();
    }, 0);
});

ลองดูที่นี่: http://jsfiddle.net/Q57gY/2/

แก้ไข : เบราว์เซอร์บางตัว (เช่น Chrome) ไม่ทริกเกอร์เหตุการณ์การกดแป้นพิมพ์สำหรับ backspace เปลี่ยนการกดแป้นพิมพ์เป็นการป้อนรหัส


กำลังจะโพสต์สิ่งนี้ นี่คือjsFiddle ที่ฉันทำ
kapa

คุณพูดถูก Chrome ดูเหมือนจะไม่ทริกเกอร์เหตุการณ์การกดแป้นพิมพ์สำหรับ backspace ปรับปรุง
Arnaud Le Blanc

@ เอียน OP ที่ต้องการให้อัปเดตเป็นคีย์ค้างไว้หรือไม่? ไม่แน่ใจเหมือนกันว่านี่เป็นข้อกำหนดหรือไม่ โซลูชันนี้ไม่มีฟังก์ชันดังกล่าว
Jonathan M

ต้องมีความชัดเจน: ไม่ได้กับเหตุการณ์ที่ทริกเกอร์ปุ่มกดสำหรับ Backspace เป็นต่อมาตรฐาน: "ที่สำคัญที่ก่อให้เกิดความคุ้มค่าของตัวละคร" - สำหรับปุ่มอื่น ๆ ใช้ "keydown" (ก่อนการเปลี่ยนแปลงที่ยกเลิก) หรือ "keyup" (หลังการเปลี่ยนแปลง)
sebilasse

5

ให้มันกะทัดรัด
ทุกครั้งที่คุณกดปุ่มฟังก์ชันedValueKeyPress()จะถูกเรียกใช้
คุณยังได้ประกาศและเตรียมใช้งานตัวแปรบางตัวในฟังก์ชันนั้นซึ่งทำให้กระบวนการช้าลงและต้องใช้ CPU และหน่วยความจำมากขึ้นเช่นกัน
คุณสามารถใช้รหัสนี้ - ได้มาจากการแทนที่อย่างง่าย

function edValueKeyPress()
{
    document.getElementById("lblValue").innerText =""+document.getElementById("edValue").value;
}

นั่นคือทั้งหมดที่คุณต้องการและเร็วขึ้น!


3
<asp:TextBox ID="txtMobile" runat="server" CssClass="form-control" style="width:92%;  margin:0px 5px 0px 5px;" onkeypress="javascript:return isNumberKey(event);" MaxLength="12"></asp:TextBox>

<script>
    function isNumberKey(evt) {
        var charCode = (evt.which) ? evt.which : event.keyCode;
        if (charCode > 31 && (charCode < 48 || charCode > 57)) {
            return false;
        }
        return true;
    }
</script>

3

จนถึงขณะนี้ไม่มีคำตอบใดที่มีโซลูชันที่สมบูรณ์ มีปัญหาค่อนข้างน้อยที่ต้องแก้ไข:

  1. ไม่ได้ส่งการกดแป้นทั้งหมดไปยังkeydownและkeypressตัวจัดการ (เช่นปุ่มย้อนกลับและปุ่มลบจะถูกระงับโดยเบราว์เซอร์บางตัว)
  2. การจัดการkeydownไม่ใช่ความคิดที่ดี มีสถานการณ์ที่การกดปุ่มลงไม่ส่งผลให้เกิดการกดแป้น!
  3. setTimeout() การแก้ปัญหาสไตล์ล่าช้าภายใต้เว็บเบราว์เซอร์ Google Chrome / Blink จนกว่าผู้ใช้จะหยุดพิมพ์
  4. อาจใช้เมาส์และเหตุการณ์การสัมผัสเพื่อดำเนินการต่างๆเช่นตัดคัดลอกและวาง เหตุการณ์เหล่านั้นจะไม่ทำให้เกิดเหตุการณ์แป้นพิมพ์
  5. เบราว์เซอร์ขึ้นอยู่กับวิธีการป้อนข้อมูลอาจไม่ส่งการแจ้งเตือนว่าองค์ประกอบมีการเปลี่ยนแปลงจนกว่าผู้ใช้จะออกไปจากฟิลด์

วิธีการแก้ปัญหาที่ถูกต้องมากขึ้นจะจัดการkeypress, keyup, inputและchangeเหตุการณ์ที่เกิดขึ้น

ตัวอย่าง:

<p><input id="editvalue" type="text"></p>
<p>The text box contains: <span id="labelvalue"></span></p>

<script>
function UpdateDisplay()
{
    var inputelem = document.getElementById("editvalue");
    var s = inputelem.value;

    var labelelem = document.getElementById("labelvalue");
    labelelem.innerText = s;
}

// Initial update.
UpdateDisplay();

// Register event handlers.
var inputelem = document.getElementById("editvalue");
inputelem.addEventListener('keypress', UpdateDisplay);
inputelem.addEventListener('keyup', UpdateDisplay);
inputelem.addEventListener('input', UpdateDisplay);
inputelem.addEventListener('change', UpdateDisplay);
</script>

ซอ:

http://jsfiddle.net/VDd6C/2175/

การจัดการทั้งสี่เหตุการณ์สามารถจับขอบได้ทั้งหมด เมื่อทำงานกับอินพุตจากผู้ใช้ควรพิจารณาวิธีการป้อนข้อมูลทุกประเภทและควรตรวจสอบการทำงานข้ามเบราว์เซอร์และข้ามอุปกรณ์ โค้ดด้านบนได้รับการทดสอบใน Firefox, Edge และ Chrome บนเดสก์ท็อปรวมถึงอุปกรณ์เคลื่อนที่ที่ฉันเป็นเจ้าของ


ทำไมไม่เพียงinputเหตุการณ์?
YakovL

inputไม่เสมอไป ไม่มีเหตุการณ์เดียวที่ครอบคลุมทุกสถานการณ์
CubicleSoft

จะดีสำหรับคุณถ้าคุณอธิบาย "ไม่เสมอไป" ในรายละเอียดเพิ่มเติมเช่นที่คุณระบุไว้keypressในคำตอบ
YakovL

1

โดยปกติฉันจะเชื่อมต่อค่าของฟิลด์ (เช่นก่อนที่จะอัปเดต) กับคีย์ที่เกี่ยวข้องกับเหตุการณ์สำคัญ ต่อไปนี้ใช้ JS ล่าสุดดังนั้นจึงต้องปรับเปลี่ยนเพื่อรองรับ IE รุ่นเก่า

ตัวอย่าง JS ล่าสุด

document.querySelector('#test').addEventListener('keypress', function(evt) {
    var real_val = this.value + String.fromCharCode(evt.which);
    if (evt.which == 8) real_val = real_val.substr(0, real_val.length - 2);
    alert(real_val);
}, false);

รองรับ IE รุ่นเก่า

//get field
var field = document.getElementById('test');

//bind, somehow
if (window.addEventListener)
    field.addEventListener('keypress', keypress_cb, false);
else
    field.attachEvent('onkeypress', keypress_cb);

//callback
function keypress_cb(evt) {
    evt = evt || window.event;
    var code = evt.which || evt.keyCode,
        real_val = this.value + String.fromCharCode(code);
    if (code == 8) real_val = real_val.substr(0, real_val.length - 2);
}

[แก้ไข - โดยค่าเริ่มต้นวิธีนี้จะปิดใช้งานการกดแป้นสำหรับสิ่งต่างๆเช่น back space, CTRL + A รหัสด้านบนรองรับสำหรับอดีต แต่จะต้องมีการแก้ไขเพิ่มเติมเพื่อให้สามารถใช้งานได้ในภายหลังและเหตุการณ์อื่น ๆ อีกเล็กน้อย ดูความคิดเห็นของ Ian Boyd ด้านล่าง]


1
@ bažmegakapaหรือด้วยdeleteปุ่มหรือหากผู้ใช้กดปุ่มที่ไม่ได้แก้ไขเนื้อหา ( Ctrl+A) หรือหากผู้ใช้เลือกข้อความบางส่วนแล้วกดaเพื่อแทนที่ชุดย่อย เป็นความคิดที่ดี Utkanos แต่เป็นความคิดที่เปราะบาง
Ian Boyd

1
ตกลง ฉันจะทิ้งมันไว้เพราะมีระยะทางอยู่ แต่อย่างที่คุณบอกคุณต้องสร้างเผื่อไว้สำหรับคำเตือนเหล่านี้
Mitya

1

ง่าย...

ในตัวจัดการเหตุการณ์คีย์กดเขียน

void ValidateKeyPressHandler(object sender, KeyPressEventArgs e)
{
    var tb = sender as TextBox;
    var startPos = tb.SelectionStart;
    var selLen= tb.SelectionLength;

    var afterEditValue = tb.Text.Remove(startPos, selLen)
                .Insert(startPos, e.KeyChar.ToString()); 
    //  ... more here
}

จะเกิดอะไรขึ้นถ้าe.KeyCharเป็นBackspaceกุญแจ? หรือDeleteคีย์? หรือCtrl+A?
Ian Boyd

นี่เป็น JavaScript หรือไม่? voidเหรอ? objectเหรอ? วิธีการกรณีแรก?
YakovL

1

ดังนั้นจึงมีข้อดีและข้อเสียในแต่ละเหตุการณ์ เหตุการณ์onkeypressและonkeydownไม่ดึงค่าล่าสุดและonkeypressไม่เริ่มทำงานสำหรับอักขระที่ไม่สามารถพิมพ์ได้ในบางเบราว์เซอร์ onkeyupเหตุการณ์ไม่ได้ตรวจสอบเมื่อคีย์ค้างไว้เป็นตัวละครหลาย ๆ

นี่เป็นการแฮ็กเล็กน้อย แต่การทำสิ่งที่ชอบ

function edValueKeyDown(input) {
    var s = input.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: "+s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onkeydown="setTimeout(edValueKeyDown, 0, this)" />

ดูเหมือนจะจัดการกับสิ่งที่ดีที่สุดในโลกทั้งหมด


1

ด้วยการใช้event.keyเราสามารถรับค่าก่อนเข้าสู่ HTML Input Text Box นี่คือรหัส

function checkText()
{
  console.log("Value Entered which was prevented was - " + event.key);
  
  //Following will prevent displaying value on textbox
  //You need to use your validation functions here and return value true or false.
  return false;
}
<input type="text" placeholder="Enter Value" onkeypress="return checkText()" />


สิ่งนี้แตกต่างกันเมื่อข้อความถูกเปลี่ยนผ่านสิ่งที่ไม่ใช่การกดแป้น (ตัดวางลบรายการที่เลือก ฯลฯ )
Ian Boyd

@IanBoyd เห็นด้วย เพื่อให้เป็นตัวอย่างง่ายๆฉันได้ใช้การตรวจสอบการกดแป้นเท่านั้น
vibs2006

0

พยายามเชื่อมต่อ charCode เหตุการณ์กับค่าที่คุณได้รับ นี่คือตัวอย่างรหัสของฉัน:

<input type="text" name="price" onkeypress="return (cnum(event,this))" maxlength="10">
<p id="demo"></p>

js:

function cnum(event, str) {
    var a = event.charCode;
    var ab = str.value + String.fromCharCode(a);
    document.getElementById('demo').innerHTML = ab;
}

ค่าในabจะได้รับค่าล่าสุดในช่องป้อนข้อมูล


ขออภัยฉันสังเกตเห็นโพสต์อื่นที่มีแนวทางที่ดียิ่งขึ้นในหน้านี้หลังจากที่ฉันโพสต์สิ่งนี้ ฉันไม่เห็นสิ่งนั้นก่อนโพสต์ แต่ฉันคิดว่าของฉันเข้าใจแนวคิดได้ง่ายกว่า
พระรามกฤษณะ

ที่ตกออกจากกันอย่างรวดเร็วสวยเมื่อที่สำคัญคือการลบ , Backspace , Ctrl + XหรือCtrl + Vหรือเมื่อเมาส์เลือกข้อความทั้งหมดและกด i อวกาศ
เอียนบอยด์

ฉันเพิ่งเขียนความคิดของฉัน คุณสามารถใช้งานได้ตามความต้องการของคุณโดยใช้รหัสหรือวิธีการอื่น ๆ นี่เป็นเพียงความคิดของฉัน
พระรามกฤษณะ

1
ความคิดไม่ใช่คำตอบ คำตอบเกี่ยวกับ SO ควรเป็นคำตอบที่กระชับซึ่งตอบคำถามของ OP ได้อย่างชัดเจนเพื่อให้ทุกคนได้รับประโยชน์ สิ่งนี้ไม่ตรงตามเกณฑ์ดังกล่าวอย่างชัดเจน
CubicleSoft

0

มีวิธีที่ดีกว่านี้คือ ใช้วิธี concat ตัวอย่าง

ประกาศตัวแปรส่วนกลาง ใช้งานได้ดีกับ angular 10 เพียงแค่ส่งไปยัง Vanilla JavaScript ตัวอย่าง:

HTML

<input id="edValue" type="text" onKeyPress="edValueKeyPress($event)"><br>
<span id="lblValue">The text box contains: </span>

รหัส

emptyString = ''

edValueKeyPress ($event){
   this.emptyString = this.emptyString.concat($event.key);
   console.log(this.emptyString);
}

และเมื่อที่สำคัญคือDelete, Ctrl+ X, Ctrl+ V, Backspace? หรือถ้าพวกเขาเลือกข้อความบางส่วนแล้วกดA?
Ian Boyd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.