วิธีการตรวจสอบเนื้อหาของกล่องข้อความมีการเปลี่ยนแปลง


417

ฉันต้องการตรวจสอบเมื่อใดก็ตามที่เนื้อหาของกล่องข้อความเปลี่ยนไป ฉันสามารถใช้วิธีการคีย์อัพ แต่จะตรวจจับการกดแป้นที่ไม่ได้สร้างตัวอักษรเช่นเดียวกับปุ่มลูกศร ฉันคิดถึงวิธีการสองวิธีในการทำเช่นนี้โดยใช้เหตุการณ์คีย์อัป:

  1. ตรวจสอบอย่างชัดเจนว่ารหัส ascii ของปุ่มกดเป็นตัวอักษร \ backspace \ delete
  2. ใช้การปิดเพื่อจดจำสิ่งที่เป็นข้อความในกล่องข้อความก่อนการกดแป้นและตรวจสอบว่ามีการเปลี่ยนแปลงหรือไม่

ทั้งคู่ดูค่อนข้างยุ่งยาก


7
ใช่การจับคีย์อัพสำหรับสิ่งนี้ไม่ดี คุณสามารถวางสิ่งต่าง ๆ โดยไม่ต้องกดปุ่มใด ๆ เลย
อะไรต่อมิอะไร

2
โอกาสใดที่คุณสามารถโพสต์โซลูชั่นสุดท้ายของคุณ? ฉันจำเป็นต้องแก้ปัญหานี้ด้วย :)
48425 Matt

1
หรือ.keyup()กิจกรรม ... ข้อมูลเพิ่มเติมได้ที่นี่: stackoverflow.com/questions/3003879/…
Victor S

1
ดู$ ("# some-input") changePolling () ; สำหรับ wrapper ที่ตรวจสอบค่าปัจจุบันและทริกเกอร์.change()หากมีการเปลี่ยนแปลง
Joel Purra

คุณต้องตรวจสอบstackoverflow.com/a/23266812/3160597
azerafati

คำตอบ:


714

เริ่มสังเกตเหตุการณ์ 'อินพุต' แทน 'เปลี่ยน'

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

... ซึ่งดีและสะอาด แต่อาจขยายเพิ่มเติมไปที่:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});

12
'สด' เลิกใช้แล้ว เพื่อใช้ประโยชน์จาก 'กับ' stackoverflow.com/a/15111970/1724777
NavaRajan

21
ข้อเสียเพียงอย่างเดียวของ 'อินพุต' คือไม่เข้ากันได้กับ IE <9
Catfish

5
input เป็นเหตุการณ์ html5 ที่ไม่รองรับในเบราว์เซอร์ทั้งหมด developer.mozilla.org/en-US/docs/Web/API/window.oninput
commonpike

18
คุณสามารถครอบคลุมฐานเพิ่มเติมได้โดยใช้: .on ('input property paste paste', function () {
Graeck

23
ข้อเสียเพียงอย่างเดียวของ IE <9 คือไม่มีใครใช้เลย!
sohaiby

67

ใช้เหตุการณ์ onchange ใน HTML / JavaScript มาตรฐาน

ใน jQuery นั่นคือการเปลี่ยนแปลง ()เหตุการณ์ ตัวอย่างเช่น:

$('element').change(function() { // do something } );

แก้ไข

หลังจากอ่านความคิดเห็นแล้วคุณจะทำอย่างไร:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});

3
ใช่มันคล้ายกับสิ่งที่ฉันแนะนำในตัวเลือก # 2 ในคำถามของฉัน ฉันชอบการปิดเพราะใช้ทั่วโลกจะทำให้ฟังก์ชั่นนี้ใช้ได้กับกล่องข้อความเดียวเท่านั้น อย่างไรก็ตามดูเหมือนว่า jquery แปลก ๆ ไม่มีวิธีการที่ง่ายกว่านี้
olamundo

1
มันแปลกจริง ๆ แต่ฉันสงสัยว่ามีวิธีที่ดีกว่าในการทำมัน คุณสามารถใช้ setInterval แล้วตรวจสอบว่าเนื้อหามีการเปลี่ยนแปลงทุกๆ 0.1 วินาทีหรือไม่และทำอะไรบางอย่าง ซึ่งจะรวมถึงการวางเมาส์และอื่น ๆ แต่มันไม่ได้ฟังดูหรูหราเกินไป
Waleed Amjad

4
ยังคงเป็นไปได้ว่าเนื้อหาสามารถเปลี่ยนแปลงได้โดยไม่ต้องกดแป้นตัวอย่างเช่นโดยการวางเมาส์ หากคุณสนใจในเรื่องนี้คุณสามารถจับเหตุการณ์เมาส์ในทางทฤษฎีได้เช่นกัน แต่การตั้งค่านั้นก็น่าเกลียดกว่าเดิม ในทางกลับกันถ้าคุณยินดีที่จะเพิกเฉยต่อการเปลี่ยนแปลงที่เกิดจากเมาส์สิ่งนี้จะทำ
Adam Bellaire

45

เหตุการณ์ 'เปลี่ยน' ไม่ทำงานอย่างถูกต้อง แต่ 'อินพุต' นั้นสมบูรณ์แบบ

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );

7
สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับสถานการณ์ของฉันแม้ว่า.onจะแนะนำให้ใช้ตั้งแต่ 1.7 เป็นต้นไป (มากกว่า.bind)
Nick

8
OP ไม่ได้ระบุความจำเป็นในการใช้งานร่วมกันข้ามเบราว์เซอร์ @schwarzkopfb จัดหาวิธีแก้ปัญหา ไม่มีเหตุผลในการลงคะแนนเพราะคุณมีตัวแทนที่จะทำเช่นนั้น
David East

3
@ David นอกจากนี้เขายังไม่ได้ระบุเบราว์เซอร์
Ozz

9
@ jmo21 ฉันคิดว่าเราสามารถสันนิษฐานได้สำหรับการพัฒนาเว็บเมื่อเบราว์เซอร์ไม่เฉพาะเจาะจงโซลูชันควรทำงานข้ามระบบ บรรทัดฐานรองรับเบราว์เซอร์ทั้งหมด
Chris

3
@Chris "บรรทัดฐานรองรับเบราว์เซอร์ทั้งหมด" - เฉพาะในกรณีที่คุณเป็นคนซาดิสม์ ไม่มีเหตุผลที่ดีที่จะหลีกเลี่ยงความดีของ HTML5 สำหรับผู้ใช้ทั่วโลก 2% ใน IE 8/9 caniuse.com/#feat=input-event
Yarin

39

เกี่ยวกับสิ่งนี้:

<jQuery 1.7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> jQuery 1.7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

สามารถใช้งานได้กับ IE8 / IE9, FF, Chrome


1
ปัญหาที่ฉันมีกับคำตอบนี้คือไฟเมื่อคุณเบลอกล่องข้อความแม้ว่าค่าจะไม่เปลี่ยนแปลง ผู้กระทำผิดคือ "เปลี่ยน"
Justin

คุณใช้ Chrome อยู่หรือเปล่า ดูเหมือนว่ามันเป็นข้อผิดพลาดกับโครเมี่ยมและไม่ใช่เหตุการณ์การเปลี่ยนแปลงของ jQuery bugs.jquery.com/ticket/9335
Catfish

ใช้งานได้ แต่มีข้อผิดพลาดเล็กน้อยหากคุณทำconsole.logค่าของฟิลด์ที่บันทึกสองครั้งเมื่อคุณป้อนอักขระ
ซามูเอลเอ็ม

21

ใช้การปิดเพื่อจดจำสิ่งที่เป็นข้อความในช่องทำเครื่องหมายก่อนที่จะกดปุ่มและตรวจสอบว่ามีการเปลี่ยนแปลง

อ๋อ คุณไม่จำเป็นต้องใช้การปิด แต่คุณจำเป็นต้องจำค่าเก่าและเปรียบเทียบกับสิ่งใหม่

แต่! สิ่งนี้ยังคงไม่เปลี่ยนแปลงทุกครั้งเนื่องจากมีวิธีการแก้ไขเนื้อหากล่องข้อความที่ไม่เกี่ยวข้องกับการกดปุ่มใด ๆ ตัวอย่างเช่นการเลือกช่วงของข้อความจากนั้นคลิกขวาที่ตัด หรือลากมัน หรือวางข้อความจากแอพอื่นลงในกล่องข้อความ หรือเปลี่ยนคำผ่านการตรวจการสะกดของเบราว์เซอร์ หรือ...

ดังนั้นหากคุณต้องตรวจจับการเปลี่ยนแปลงทุกครั้งคุณต้องสำรวจความคิดเห็น คุณสามารถwindow.setIntervalตรวจสอบฟิลด์กับค่าก่อนหน้านี้ทุก ๆ (พูด) วินาที นอกจากนี้คุณยังสามารถลวดonkeyupฟังก์ชั่นเดียวกันดังนั้นการเปลี่ยนแปลงที่จะเกิดจากการกดแป้นจะสะท้อนให้เห็นได้เร็วขึ้น

ยุ่งยาก? ใช่. แต่นั่นเป็นเพียงวิธีการเปลี่ยน HTML ปกติและอย่าพยายามอัปเดตทันที


1
ทุกวันนี้inputเหตุการณ์HTML5 สามารถใช้งานได้และทำงานได้กับเบราว์เซอร์หลักทุกรุ่นในปัจจุบัน
Tim Down

13
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

คุณสามารถใช้เหตุการณ์ 'อินพุท' เพื่อตรวจจับการเปลี่ยนแปลงเนื้อหาในกล่องข้อความ อย่าใช้ 'สด' เพื่อผูกกิจกรรมเนื่องจากเลิกใช้ใน Jquery-1.7 ดังนั้นใช้ประโยชน์จาก 'เปิด'


@NavaRajan เพิ่งทดสอบอีกครั้งใน IE9 ไม่ทำงานบน backspace จริงๆ
ฟลอเรส

ฉันไม่ต้องการใช้ชีวิต แต่ปัญหาที่ฉันมีคือฉันกลับไป "กลับสู่อนาคต" และในโครงการ mvc3 ซึ่งผู้นำทีมต้องการติดกับ "นอกกรอบ" ดังนั้นจึงไม่ เฉพาะ EF 4.0 แต่กำลังใช้ jquery 1.5.1 THUS .on () ไม่ได้อยู่ใน 1.5.1 เนื่องจากมีการเพิ่มใน jquery เวอร์ชัน 1.7 api.jquery.com/on
Tom Stickel

5

ฉันคิดว่าคุณกำลังมองหาที่จะทำสิ่งที่โต้ตอบเมื่อกล่องข้อความเปลี่ยนแปลง (เช่นดึงข้อมูลบางอย่างผ่าน ajax) ฉันกำลังมองหาฟังก์ชั่นเดียวกันนี้ ฉันรู้ว่าการใช้ทั่วโลกไม่ใช่โซลูชันที่แข็งแกร่งหรือสง่างามที่สุด แต่นั่นคือสิ่งที่ฉันไปด้วย นี่คือตัวอย่าง:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

สิ่งสำคัญประการหนึ่งที่ควรทราบที่นี่คือฉันใช้ setTimeout และไม่ได้ตั้งค่า Interterval เนื่องจากฉันไม่ต้องการส่งคำขอหลายรายการพร้อมกัน สิ่งนี้ทำให้มั่นใจได้ว่าตัวจับเวลา "หยุด" เมื่อส่งแบบฟอร์มและ "เริ่มต้น" เมื่อคำขอเสร็จสมบูรณ์ ฉันทำสิ่งนี้โดยการเรียก checkSearchChanged เมื่อการโทร ajax ของฉันเสร็จสิ้น เห็นได้ชัดว่าคุณสามารถขยายสิ่งนี้เพื่อตรวจสอบความยาวขั้นต่ำ ฯลฯ

ในกรณีของฉันฉันใช้ ASP.Net MVC เพื่อให้คุณสามารถดูวิธีการผูกกับ MVC Ajax และในโพสต์ต่อไปนี้:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx


4

ฉันอยากจะแนะนำให้ดูที่วิดเจ็ตเติมข้อความอัตโนมัติ jQuery UI พวกเขาจัดการกรณีส่วนใหญ่ที่นั่นเนื่องจากฐานรหัสของพวกเขาเป็นผู้ใหญ่กว่าคนส่วนใหญ่ออกมี

ด้านล่างคือลิงค์ไปยังหน้าตัวอย่างเพื่อให้คุณสามารถตรวจสอบได้ http://jqueryui.com/demos/autocomplete/#default

คุณจะได้รับประโยชน์สูงสุดจากการอ่านแหล่งข้อมูลและดูว่าพวกเขาแก้ไขอย่างไร คุณสามารถค้นหาได้ที่นี่: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js

โดยพื้นฐานแล้วพวกเขาทำทุกinput, keydown, keyup, keypress, focus and blurอย่าง page up, page down, up arrow key and down arrow keyจากนั้นพวกเขามีการจัดการพิเศษสำหรับทุกประเภทของคีย์เช่น มีการใช้ตัวจับเวลาก่อนรับเนื้อหาของกล่องข้อความ เมื่อผู้ใช้พิมพ์คีย์ที่ไม่สอดคล้องกับคำสั่ง (คีย์ up, down down และอื่น ๆ ) จะมีตัวจับเวลาที่สำรวจเนื้อหาหลังจากนั้นประมาณ 300 มิลลิวินาที ดูเหมือนว่าในรหัส:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

เหตุผลที่ใช้ตัวจับเวลาคือเพื่อให้ UI ได้รับโอกาสในการอัปเดต เมื่อ Javascript กำลังเรียกใช้ UI ไม่สามารถอัปเดตได้ดังนั้นการเรียกไปยังฟังก์ชั่นการหน่วงเวลา สิ่งนี้ทำงานได้ดีสำหรับสถานการณ์อื่น ๆ เช่นการมุ่งเน้นไปที่กล่องข้อความ (ใช้โดยรหัสนั้น)

ดังนั้นคุณสามารถใช้วิดเจ็ตหรือคัดลอกรหัสลงในวิดเจ็ตของคุณเองหากคุณไม่ได้ใช้ jQuery UI (หรือในกรณีของฉันในการพัฒนาวิดเจ็ตที่กำหนดเอง)


2

ผมอยากจะถามว่าทำไมคุณกำลังพยายามที่จะตรวจสอบเมื่อเนื้อหาของช่องที่มีการเปลี่ยนแปลงในเวลาจริง ?

อีกทางเลือกหนึ่งคือการตั้งเวลา (ผ่าน setIntval?) และเปรียบเทียบค่าที่บันทึกล่าสุดกับค่าปัจจุบันแล้วรีเซ็ตตัวจับเวลา สิ่งนี้จะรับประกันว่าจะได้รับการเปลี่ยนแปลงใด ๆ ไม่ว่าจะเกิดจากกุญแจ, เมาส์, อุปกรณ์ป้อนข้อมูลอื่น ๆ ที่คุณไม่ได้พิจารณาหรือแม้แต่การเปลี่ยนค่าจาวาสคริปต์


สถานการณ์ของฉัน (ซึ่งทำให้ฉันมีคำถามนี้) คือฉันต้องแสดงปุ่ม 'อัปเดตรถเข็น' เมื่อปริมาณในกล่องข้อความเปลี่ยนไป ผู้ใช้ไม่มีความคิดที่พวกเขาต้องสูญเสียการโฟกัสและอาจไม่เห็นปุ่ม
Simon_Weaver

ขออภัยฉันไม่แน่ใจว่านี่จะตอบคำถามของ "ทำไมไม่ตรวจสอบความแตกต่างในตาราง" เพียงตรวจสอบบ่อยครั้งพอ (ทุก ๆ 1/4 ของวินาที) และผู้ใช้จะไม่ทราบความแตกต่าง
DVK

1

คุณพิจารณาใช้เหตุการณ์การเปลี่ยนแปลงหรือไม่

$("#myTextBox").change(function() { alert("content changed"); });

5
AFAIK จะถูกกระตุ้นเมื่อการโฟกัสขององค์ประกอบหายไป คนที่คุ้นเคยกับการปิดอาจรู้เกี่ยวกับเรื่องนี้ :)
simon

ใช่สิ่งนี้จะไม่ทำ - เหตุการณ์การเปลี่ยนแปลงจะถูกเรียกก็ต่อเมื่อกล่องข้อความหมดโฟกัส ฉันต้องการจัดการการเปลี่ยนแปลงทันทีหลังจากกดแป้น
olamundo

1

ใช้textchangeเหตุการณ์ผ่าน jQuery shim ที่กำหนดเองเพื่อinputความเข้ากันได้ข้ามเบราว์เซอร์ http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html http://genubperpert.com/?hl=th (GitHub ที่แยกจากกันล่าสุด: https://github.com/pandell /jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

จับนี้แท็กเข้าทั้งหมดรวมทั้ง<textarea>content</textarea>ที่ไม่เคยทำงานร่วมกับchange keyupฯลฯ (!) เท่านั้น jQuery on("input propertychange")จับ<textarea>แท็กอย่างต่อเนื่องและที่กล่าวมาเป็นชิมเบราว์เซอร์ทั้งหมดที่ไม่เข้าใจinputเหตุการณ์

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

ทดสอบ JS Bin

นอกจากนี้ยังจัดการวางลบและไม่ทำซ้ำความพยายามในการคีย์

หากไม่ได้ใช้ชิมให้ใช้ jQuery on("input propertychange")events

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  

0

มีตัวอย่างการทำงานที่สมบูรณ์เป็นที่นี่

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>

0

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

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}

0

รหัสนี้จะตรวจจับเมื่อใดก็ตามที่เนื้อหาของกล่องข้อความมีการเปลี่ยนแปลงโดยผู้ใช้และแก้ไขโดยรหัส Javascript

var $myText = jQuery("#textbox");

$myText.data("value", $myText.val());

setInterval(function() {
    var data = $myText.data("value"),
    val = $myText.val();

    if (data !== val) {
        console.log("changed");
        $myText.data("value", val);
    }
}, 100);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.