เรียกใช้ฟังก์ชั่นจาวาสคริปต์เมื่อผู้ใช้เสร็จสิ้นการพิมพ์แทนการกดคีย์?


463

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

มีวิธีใดบ้างที่ฉันสามารถตรวจจับได้เมื่อผู้ใช้พิมพ์เสร็จแล้วจึงทำการร้องขอ ajax

ใช้ jQuery ที่นี่! เดฟ


21
ฉันคิดว่าคุณจะต้องกำหนด "เสร็จสิ้นการพิมพ์" สำหรับเรา
Surreal Dreams

8
ในขณะที่ @Surreal Dreams 'ตอบสนองความต้องการส่วนใหญ่ของคุณได้หากผู้ใช้เริ่มพิมพ์อีกครั้งหลังจากหมดเวลาที่ระบุไว้คำขอจำนวนมากจะถูกส่งไปยังเซิร์ฟเวอร์ ดูคำตอบของฉันด้านล่างซึ่งเก็บคำขอ XHR แต่ละรายการในตัวแปรและยกเลิกก่อนที่จะปิดคำขอใหม่ นี่คือสิ่งที่ Google ทำในการค้นหาทันใจของพวกเขา
Marko

1
เป็นไปได้ที่ซ้ำกันของความล่าช้าคีย์ jquery?
CMS

1
แล้วเบลอล่ะ ฉันเดาว่าผู้ใช้พิมพ์เสร็จแล้วอย่างแน่นอนเมื่อองค์ประกอบอินพุตขาดการโฟกัส
อย่า P

3
การค้นหา google อย่างง่ายอาจทำให้คุณได้คำตอบง่ายๆ: schier.co/blog/2014/12/08/…
Cannicide

คำตอบ:


688

ดังนั้นฉันจะเดาว่าพิมพ์เสร็จหมายความว่าคุณหยุดซักครู่พูด 5 วินาที ดังนั้นเมื่อทราบแล้วให้เริ่มจับเวลาเมื่อผู้ใช้ปล่อยปุ่มและล้างเมื่อกดปุ่มเดียว ฉันตัดสินใจว่าอินพุตที่เป็นปัญหาจะเป็น #myInput

ทำให้สมมติฐานไม่กี่ ...

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example
var $input = $('#myInput');

//on keyup, start the countdown
$input.on('keyup', function () {
  clearTimeout(typingTimer);
  typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$input.on('keydown', function () {
  clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

4
ขอบคุณ :) ฉันเริ่มพิมพ์ความคิดเห็นในคำถามและตระหนักว่าฉันมีความคิดที่ดี
Surreal Dreams

26
คำตอบนี้ทำงานไม่ถูกต้องมันจะทำงานหลังจาก 5 วินาทีเว้นแต่ว่าผู้ใช้พิมพ์ช้ามาก ดูวิธีการทำงานด้านล่าง
ไป

3
หากคุณพบปัญหาที่นี่เนื่องจากตัวจับเวลาเริ่มทำงานทันทีลองเพิ่มเครื่องหมายคำพูดรอบการเรียกใช้ฟังก์ชัน: setTimeout ('functionToBeCalled', doneTypingInterval);
Largo

3
ฉันเห็นความคิดเห็นเล็กน้อยที่ฟังก์ชันการโทรกลับdoneTypingในตัวอย่างกำลังทำงานทันที ซึ่งมักเป็นผลมาจากอุบัติเหตุโดยรวม()หลังจากชื่อฟังก์ชัน หมายเหตุว่ามันควรจะอ่านsetTimeout(doneTyping,ไม่ได้setTimeout(doneTyping(),
แอนโธนี DiSanti

2
@Jessica เพื่อทำงานกับการวางคุณต้องเพิ่มเหตุการณ์ 'วาง' เช่นนี้: เปิด ('keyup paste',
Sergey

397

คำตอบที่เลือกไว้ด้านบนไม่ทำงาน

เนื่องจากการตั้งค่าไทม์เมอร์พิมพ์เป็นครั้งคราวหลายครั้ง (กดคีย์อัพสองครั้งก่อนที่คีย์ดาวน์จะถูกเรียกใช้สำหรับตัวพิมพ์เร็ว ฯลฯ ) ดังนั้นจึงไม่ชัดเจนอย่างถูกต้อง

วิธีการแก้ปัญหาด้านล่างแก้ปัญหานี้และจะเรียก X วินาทีหลังจากเสร็จสิ้นตามที่ OP ร้องขอ นอกจากนี้ยังไม่ต้องการฟังก์ชั่นการกดแป้นซ้ำซ้อนอีกต่อไป ฉันได้เพิ่มการตรวจสอบเพื่อให้การเรียกใช้ฟังก์ชันของคุณจะไม่เกิดขึ้นหากอินพุตของคุณว่างเปล่า

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms (5 seconds)

//on keyup, start the countdown
$('#myInput').keyup(function(){
    clearTimeout(typingTimer);
    if ($('#myInput').val()) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

และรหัสเดียวกันในโซลูชัน JavaScript ของ vanilla:

//setup before functions
let typingTimer;                //timer identifier
let doneTypingInterval = 5000;  //time in ms (5 seconds)
let myInput = document.getElementById('myInput');

//on keyup, start the countdown
myInput.addEventListener('keyup', () => {
    clearTimeout(typingTimer);
    if (myInput.value) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

โซลูชันนี้ใช้ ES6 แต่ไม่จำเป็นที่นี่ เพียงแทนที่letด้วยvarและฟังก์ชั่นลูกศรด้วยฟังก์ชั่นปกติ


5
มันอาจมีประโยชน์ที่จะยังคงเรียกใช้ฟังก์ชันแม้ว่าอินพุตจะว่างเปล่า ถ้าคุณต้องการล้างผลลัพธ์การค้นหาบางอย่าง (เช่น) เมื่ออินพุตว่างอีกครั้ง
rvighne

7
ฉันคิดว่าเราควรพิจารณาถึงเงื่อนไขที่ผู้ใช้เพียงแค่วางสตริงเข้ามาในเขตข้อมูล
Vishal Nair

10
ใช้$('#myInput').on('input', function() {ถ้าคุณต้องการให้มันทำงานกับการคัดลอกและวาง ฉันไม่เห็นจุดตรวจสอบว่าอินพุตว่างหรือไม่ สมมติว่าเขาต้องการลบสิ่งที่เขาพิมพ์สิ่งนี้จะล้มเหลวในการโทรอาแจ็กซ์
billynoah

3
ทำไมมันif ($('#myInput').val)แทนif ($('#myInput').val())? ควร.valเป็นฟังก์ชั่นหรือไม่?
wlnirvana

4
ทำไมไม่ใช้ $ (นี่) .val ()
JoelFan

76

เป็นเพียงหนึ่งบรรทัดที่มีฟังก์ชันการหักล้างunderscore.js :

$('#my-input-box').keyup(_.debounce(doSomething , 500));

โดยพื้นฐานแล้วสิ่งนี้บอกว่าdoSomething 500 มิลลิวินาทีหลังจากการพิมพ์หยุดฉัน

สำหรับข้อมูลเพิ่มเติม: http://underscorejs.org/#debounce


5
ดูเหมือนว่าจะมีให้สำหรับ jQuery ด้วยเช่นกัน: code.google.com/p/jquery-debounceและgithub.com/diaspora/jquery-debounce
koppor

63
มันทำให้ฉันประหลาดใจว่าผู้คนต่างพูดถึง "หนึ่งบรรทัดแห่งรหัส" ว่าเป็นเรื่องสำคัญอย่างยิ่ง ยิ่งใหญ่ โค้ดหนึ่งบรรทัดที่ต้องการโหลดไฟล์ 1.1k JS ฉันไม่ได้ลงคะแนนเพราะเป็นวิธีแก้ปัญหา แต่ตัวหนาของบรรทัดเดียวทำให้ฉันโกรธและนำไปสู่การขยายตัวของโค้ด
Wolfie

1
@ Wolfie ฉันเห็นด้วยกับคุณเกี่ยวกับการขยายตัวของโค้ด แต่ Underscore และ Lodash เป็นอันดับสองที่ขึ้นอยู่กับยูทิลิตี้ที่NPMดังนั้นนี่อาจเป็นทางออกเดียวสำหรับหลาย ๆ คน
พอล

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

ทำไมฉันถึงได้:Uncaught ReferenceError: _ is not defined
วิลฟ์

44

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

var timer;
var x;

$(".some-input").keyup(function () {
    if (x) { x.abort() } // If there is an existing XHR, abort it.
    clearTimeout(timer); // Clear the timer so we don't end up with dupes.
    timer = setTimeout(function() { // assign timer a new timeout 
        x = $.getJSON(...); // run ajax request and store in x variable (so we can cancel)
    }, 2000); // 2000ms delay, tweak for faster/slower
});

หวังว่าจะช่วยได้

มาร์โค


ฉันจะไม่แนะนำสิ่งนี้ รหัสจะทริกเกอร์คำขอ API ทุกครั้งที่กดปุ่ม จากนั้นจะยกเลิกการร้องขอหากกดคีย์อื่น แม้ว่าวิธีนี้จะป้องกันไม่ให้ AJAX โทรกลับถูกเรียกในขณะที่ผู้ใช้ประเภทมันจะยังคงตอกย้ำเซิร์ฟเวอร์ที่มีการร้องขอ
lxg

Ixg ไม่นี้จะไม่ ฟังก์ชั่น clearTimeout ที่เขาใช้จะเคลียร์เหตุการณ์ไทม์เอาต์ก่อนหน้าเพื่อเรียกใช้การเรียก API
John Smith

@JohnSmith ผมไม่เห็นด้วยก็อาจจะดีกว่าที่จะล้างครั้งแรกจับเวลาแล้วตรวจสอบว่า XHR เป็นที่ว่างเปล่าหรืออะไรก็ตามที่สภาพของคุณอาจจะมีและในที่สุดก็วิ่งจับเวลาด้วยการเรียกอาแจ็กซ์
Fleuv

20
var timer;
var timeout = 1000;

$('#in').keyup(function(){
    clearTimeout(timer);
    if ($('#in').val) {
        timer = setTimeout(function(){
            //do stuff here e.g ajax call etc....
             var v = $("#in").val();
             $("#out").html(v);
        }, timeout);
    }
});

ตัวอย่างเต็มรูปแบบที่นี่: http://jsfiddle.net/ZYXp4/8/


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

12

คำตอบทั้งสองข้อแรกไม่ได้ผลสำหรับฉัน ดังนั้นนี่คือทางออกของฉัน:

var timeout = null;

$('#myInput').keyup(function() {
    clearTimeout(timeout);

    timeout = setTimeout(function() {
        //do stuff here
    }, 500);
});

11

ฉันชอบคำตอบของ Surreal Dream แต่ฉันพบว่าฟังก์ชั่น "doneTyping" ของฉันจะเริ่มทำงานสำหรับทุกปุ่มกดนั่นคือถ้าคุณพิมพ์ "Hello" อย่างรวดเร็ว แทนที่จะทำการยิงเพียงครั้งเดียวเมื่อคุณหยุดพิมพ์ฟังก์ชั่นจะทำงาน 5 ครั้ง

ปัญหาคือว่าฟังก์ชั่น setTimeout ของจาวาสคริปต์ไม่ปรากฏว่าเขียนทับหรือฆ่าการหมดเวลาเก่า ๆ ที่ตั้งไว้ แต่ถ้าคุณทำด้วยตัวเองมันใช้งานได้! ดังนั้นฉันเพิ่งเพิ่มการเรียกใช้ clearTimeout ก่อน setTimeout หากตั้งค่าการพิมพ์ไทม์เมอร์ ดูด้านล่าง:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example

//on keyup, start the countdown
$('#myInput').on("keyup", function(){
    if (typingTimer) clearTimeout(typingTimer);                 // Clear if already set     
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$('#myInput').on("keydown", function(){
    clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

NB ฉันอยากจะเพิ่มความคิดเห็นนี้ในคำตอบของ Surreal Dream แต่ฉันเป็นผู้ใช้ใหม่และไม่มีชื่อเสียงเพียงพอ ขออภัย!


10

การแก้ไขคำตอบที่ยอมรับเพื่อจัดการกรณีเพิ่มเติมเช่นวาง:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 2000;  //time in ms, 2 second for example
var $input = $('#myInput');

// updated events 
$input.on('input propertychange paste', function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(doneTyping, doneTypingInterval);      
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

6

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

var _timer, _timeOut = 2000; 



function _onKeyUp(e) {
    clearTimeout(_timer);
    if (e.keyCode == 13) {      // close on ENTER key
        _onCloseClick();
    } else {                    // send xhr requests
        _timer = window.setTimeout(function() {
            _onInputChange();
        }, _timeOut)
    }

}

มันเป็นคำตอบแรกของฉันเกี่ยวกับ Stack Overflow ดังนั้นฉันหวังว่านี่จะช่วยให้ใครซักคนในวันนี้ :)


6

ประกาศdelayฟังก์ชันต่อไปนี้:

var delay = (function () {
    var timer = 0;
    return function (callback, ms) {
        clearTimeout(timer);
        timer = setTimeout(callback, ms);
    };
})()

แล้วใช้มัน:

let $filter = $('#item-filter');
$filter.on('keydown', function () {
    delay(function () {            
        console.log('this will hit, once user has not typed for 1 second');            
    }, 1000);
});    

ทางออกของคุณยอดเยี่ยมมาก!
นักพัฒนา

1
@ นักพัฒนาขอบคุณมาก ฉันได้เพิ่มคำตอบอื่นเพื่อแก้ไขสถานการณ์ที่ซับซ้อนขึ้นเล็กน้อย (การควบคุมหลายรายการต่อหน้า)
Fabian Bigler

ทางออกที่ดี ฉันใช้สิ่งนี้ แต่แทนที่จะใช้ keydown ฉันใช้เหตุการณ์ 'อินพุต'
Budyn

ด้วยเหตุการณ์การกดปุ่มมันใช้งานได้ดีสำหรับฉัน ขอบคุณ
Sinan Eldem

6

คำตอบที่ล่าช้า แต่ฉันเพิ่มเพราะมันเป็นปี 2019 และนี่เป็นสิ่งที่ทำได้โดยใช้ ES6 ที่สวยไม่มีห้องสมุดของบุคคลที่สามและฉันพบว่าคำตอบที่ได้รับความนิยมสูงส่วนใหญ่นั้นมีขนาดใหญ่และมีน้ำหนักมากเกินไป

ทางออกที่สวยงามนำมาจากโพสต์บล็อกที่ยอดเยี่ยมนี้

function debounce(callback, wait) {
  let timeout;
  return (...args) => {
      const context = this;
      clearTimeout(timeout);
      timeout = setTimeout(() => callback.apply(context, args), wait);
  };
}

window.addEventListener('keyup', debounce( () => {
    // code you would like to run 1000ms after the keyup event has stopped firing
    // further keyup events reset the timer, as expected
}, 1000))

1
นี่ควรเป็นคำตอบที่ดีที่สุดที่ได้รับในปี
Dark Hippo

4

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

หากคุณคาดหวังให้ผู้ใช้หยุดชั่วคราวขณะพิมพ์ไม่มีวิธีทราบเมื่อดำเนินการเสร็จ

(ยกเว้นคุณสามารถบอกได้จากข้อมูลเมื่อเสร็จสิ้น)


3

ฉันรู้สึกว่าวิธีการแก้ปัญหาค่อนข้างง่ายขึ้นกับinputเหตุการณ์:

var typingTimer;
var doneTypingInterval = 500;

$("#myInput").on("input", function () {
    window.clearTimeout(typingTimer);
    typingTimer = window.setTimeout(doneTyping, doneTypingInterval);
});

function doneTyping () {
    // code here
}

3

เห็นด้วยกับคำตอบของ @going อีกโซลูชันที่คล้ายกันที่ใช้งานได้สำหรับฉันคือโซลูชันด้านล่าง ข้อแตกต่างเพียงอย่างเดียวคือฉันใช้. on ("อินพุต" ... ) แทนที่จะเป็นคีย์อัป สิ่งนี้จะบันทึกการเปลี่ยนแปลงในอินพุตเท่านั้น ปุ่มอื่น ๆ เช่น Ctrl, Shift ฯลฯ จะถูกละเว้น

var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms (5 seconds)

//on input change, start the countdown

$('#myInput').on("input", function() {    
    clearTimeout(typingTimer);
    typingTimer = setTimeout(function(){
        // doSomething...
    }, doneTypingInterval);
});

3

ฉันเพิ่งรู้รหัสง่าย ๆ เพื่อรอให้ผู้ใช้พิมพ์เสร็จ:

ขั้นตอนที่ 1.set timeout เป็น null จากนั้นให้ล้างการหมดเวลาปัจจุบันเมื่อผู้ใช้พิมพ์

ขั้นตอนที่ 2.trigger clear timeout ให้กับตัวแปรที่กำหนดก่อนที่เหตุการณ์ keyup จะถูกทริกเกอร์

ขั้นตอน 3. กำหนดหมดเวลาเป็นตัวแปรที่ประกาศข้างต้น;

<input type="text" id="input" placeholder="please type" style="padding-left:20px;"/>
<div class="data"></div>

รหัสจาวาสคริปต์

var textInput = document.getElementById('input');
var textdata = document.querySelector('.data');
// Init a timeout variable to be used below
var timefired = null;

// Listen for keystroke events
// Init a timeout variable to be used below
var timefired = null;// Listen for keystroke events
textInput.onkeyup = function (event) {
clearTimeout(timefired);
timefired = setTimeout(function () {
    textdata.innerHTML = 'Input Value:'+ textInput.value;
  }, 600);
};

1
คำถามได้รับคำตอบแล้ว ... และมันก็คล้าย ๆ กับเรื่องนี้
Mixone

3

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

หลังจากทำงานฉันก็ใช้วิธีการ ping เซิร์ฟเวอร์เมื่อผู้ใช้หยุดพิมพ์

วิธีนี้ใช้ได้ผลสำหรับฉัน:

$(document).ready(function() {
    $('#yourtextfield').keyup(function() {
        s = $('#yourtextfield').val();
        setTimeout(function() { 
            if($('#yourtextfield').val() == s){ // Check the value searched is the latest one or not. This will help in making the ajax call work when client stops writing.
                $.ajax({
                    type: "POST",
                    url: "yoururl",
                    data: 'search=' + s,
                    cache: false,
                    beforeSend: function() {
                       // loading image
                    },
                    success: function(data) {
                        // Your response will come here
                    }
                })
            }
        }, 1000); // 1 sec delay to check.
    }); // End of  keyup function
}); // End of document.ready

คุณจะสังเกตเห็นว่าไม่จำเป็นต้องใช้ตัวจับเวลาใด ๆ ในขณะที่ใช้งาน


2

นี่คือรหัส JS ที่ฉันเขียน:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
    var date = new Date();
    initial_time = date.getTime();
    if (typeof setInverval_Variable == 'undefined') {
            setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
    } 
}
function DelayedSubmission_Check() {
    var date = new Date();
    check_time = date.getTime();
    var limit_ms=check_time-initial_time;
    if (limit_ms > 800) { //Change value in milliseconds
        alert("insert your function"); //Insert your function
        clearInterval(setInverval_Variable);
        delete setInverval_Variable;
    }
}

</script>
</head>
<body>

<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />

</body>
</html>

1

คุณสามารถใช้เหตุการณ์ onblur เพื่อตรวจสอบเมื่อกล่องข้อความหมดโฟกัส: https://developer.mozilla.org/en/DOM/element.onblur

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

เพื่อที่ฉันจะแนะนำให้ผูก setTimeout กับเหตุการณ์ onclick และสมมติว่าหลังจาก x จำนวนเวลาโดยไม่มีการกดแป้นพิมพ์ผู้ใช้หยุดพิมพ์


1

ทำไมไม่ใช้แค่โฟกัสบน?

https://www.w3schools.com/jsreF/event_onfocusout.asp

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


1
onfocusout ได้รับการสนับสนุนไม่ดีเมื่อคำถามถูกถาม (เกือบ 7 ปีที่แล้ว) และผลกระทบของ onfocusout ก็จะแตกต่างกันบ้าง คุณจะต้องรอให้ผู้ใช้ให้ความสำคัญกับองค์ประกอบในขณะที่ทางออกหมดเวลา / debounce มัน "ไฟ" ทันทีที่ผู้ใช้หยุดพิมพ์และผู้ใช้ไม่จำเป็นต้องสลับโฟกัส ตัวอย่างกรณีการใช้งานจะเป็นหนึ่งในแบบฟอร์มการลงทะเบียนซึ่งเมื่อผู้ใช้หยุดป้อนชื่อผู้ใช้ที่อาจเกิดขึ้นเครื่องหมายถูกหรือ "X" จะปรากฏขึ้นทางด้านขวาของเขตข้อมูลฟอร์มที่ระบุว่าชื่อนั้นมีอยู่
David Zorychta

หากแถบค้นหาอยู่ในโฟกัสไม่จำเป็นต้องออกไปข้างนอกหลังจากเวลาผ่านไปผลลัพธ์จะปรากฏขึ้นโดยตรงเนื่องจากไม่มีการเปิดพิมพ์ใด ๆ เพิ่มเติม
P Satish Patro

1

หากมีความจำเป็นสำหรับผู้ใช้ที่จะย้ายออกจากสนามเราสามารถใช้ "onBlur" แทน Onchange ใน Javascript

  <TextField id="outlined-basic"  variant="outlined" defaultValue={CardValue} onBlur={cardTitleFn} />

หากไม่จำเป็นต้องตั้งเวลาจับเวลาจะเป็นตัวเลือกที่ดี


0

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

เมื่อหมดเวลาใช้งานทำคำขอ ajax ของคุณ


0

หากคุณกำลังมองหาความยาวที่เฉพาะเจาะจง (เช่นฟิลด์รหัสไปรษณีย์):

$("input").live("keyup", function( event ){
if(this.value.length == this.getAttribute('maxlength')) {
        //make ajax request here after.
    }
  });

ไม่ใช่ความคิดที่ดีที่จะทำการตรวจสอบแบบ จำกัด ก่อนที่จะส่งคำขอ ajax
chim

0

ไม่แน่ใจว่าสิ่งที่ฉันต้องการนั้นแปลกหรือเปล่า แต่ฉันต้องการบางสิ่งที่คล้ายกับสิ่งนี้และนี่คือสิ่งที่ฉันใช้:

$('input.update').bind('sync', function() {
    clearTimeout($(this).data('timer'));            
    $.post($(this).attr('data-url'), {value: $(this).val()}, function(x) {
        if(x.success != true) {
            triggerError(x.message);    
        }
    }, 'json');
}).keyup(function() {
    clearTimeout($(this).data('timer'));
    var val = $.trim($(this).val());
    if(val) {
        var $this = $(this);
        var timer = setTimeout(function() {
            $this.trigger('sync');
        }, 2000);
        $(this).data('timer', timer);
    }
}).blur(function() {
    clearTimeout($(this).data('timer'));     
    $(this).trigger('sync');
});

ซึ่งทำให้ฉันมีองค์ประกอบเช่นนี้ในแอปพลิเคชันของฉัน:

<input type="text" data-url="/controller/action/" class="update">

สิ่งใดที่ได้รับการอัปเดตเมื่อผู้ใช้ "พิมพ์เสร็จแล้ว" (ไม่มีการดำเนินการ 2 วินาที) หรือไปที่ฟิลด์อื่น (พร่ามัวจากองค์ประกอบ)


0

หากคุณต้องการให้รอจนกว่าผู้ใช้จะพิมพ์เสร็จแล้วให้ใช้วิธีนี้:

$(document).on('change','#PageSize', function () {
    //Do something after new value in #PageSize       
});

ตัวอย่างที่สมบูรณ์ด้วยการโทร ajax การทำงานกับเพจเจอร์ของฉัน - นับจำนวนต่อรายการ:

$(document).ready(function () {
    $(document).on('change','#PageSize', function (e) {
        e.preventDefault();
        var page = 1;
        var pagesize = $("#PageSize").val();
        var q = $("#q").val();
        $.ajax({
            url: '@Url.Action("IndexAjax", "Materials", new { Area = "TenantManage" })',
            data: { q: q, pagesize: pagesize, page: page },
            type: 'post',
            datatype: "json",
            success: function (data) {
                $('#tablecontainer').html(data);
               // toastr.success('Pager has been changed', "Success!");
            },
            error: function (jqXHR, exception) {
                ShowErrorMessage(jqXHR, exception);
            }
        });  
    });
});    

0

หลายตัวนับต่อหน้า

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

เพื่อแก้ปัญหานี้คุณเพียงแค่ส่ง ID ไปยังฟังก์ชั่นและรักษาพจนานุกรม timeoutHandles ไว้ในรหัสต่อไปนี้:

ประกาศฟังก์ชั่น:

var delayUserInput = (function () {
    var timeoutHandles = {};    
    return function (id, callback, ms) {        
        if (timeoutHandles[id]) {
            clearTimeout(timeoutHandles[id]);
        }

        timeoutHandles[id] = setTimeout(callback, ms);             
    };
})();

ฟังก์ชั่นการใช้งาน:

  delayUserInput('yourID', function () {
     //do some stuff
  }, 1000);

0

ง่ายและเข้าใจง่าย

var mySearchTimeout;
$('#ctl00_mainContent_CaseSearch').keyup(function () {
   clearTimeout(mySearchTimeout);
   var filter = $(this).val();
   mySearchTimeout = setTimeout(function () { myAjaxCall(filter); }, 700);
   return true;
});

0

สำหรับการส่งพารามิเตอร์ไปยังฟังก์ชันของคุณพร้อมกับไวยากรณ์ ES6

$(document).ready(() => {
    let timer = null;
     $('.classSelector').keydown(() => {
     clearTimeout(timer); 
     timer = setTimeout(() => foo('params'), 500);
  });
});

const foo = (params) => {
  console.log(`In foo ${params}`);
}

-2

ว้าวแม้ความเห็น 3 ข้อก็ค่อนข้างถูกต้อง!

  1. อินพุตเปล่านั้นไม่มีเหตุผลที่จะข้ามการเรียกใช้ฟังก์ชันเช่นฉันลบพารามิเตอร์ของเสียออกจาก url ก่อนที่จะเปลี่ยนเส้นทาง

  2. .on ('input', function() { ... });ควรจะใช้เพื่อทริกเกอร์keyup, pasteและchangeเหตุการณ์ที่เกิดขึ้น

  3. แน่นอน.val()หรือ.valueจะต้องใช้

  4. คุณสามารถใช้$(this)ฟังก์ชั่นเหตุการณ์ภายในแทนที่จะ#idทำงานกับหลายอินพุต

  5. (การตัดสินใจของฉัน) ฉันใช้ฟังก์ชั่นนิรนามแทนการdoneTypingเข้าsetTimeoutเพื่อเข้าถึงได้ง่าย$(this)จาก n.4 แต่คุณต้องบันทึกก่อนvar $currentInput = $(this);

แก้ไขฉันเห็นว่าบางคนไม่เข้าใจเส้นทางโดยไม่สามารถคัดลอกโค้ดที่พร้อมวางได้ ที่นี่คุณ

var typingTimer;
//                  2
$("#myinput").on('input', function () {
    //             4     3
    var input = $(this).val();
    clearTimeout(typingTimer);
    //                           5
    typingTimer = setTimeout(function() {
        // do something with input
        alert(input);
    }, 5000);      
});

สิ่งนี้ตอบคำถามได้อย่างไร
โทมัส Orlita

@ThomasOrlita this answer supplements 3 most rated answers. Take a look at accepted one: 1. it doesn't support paste, it doesn't use this, etc. (I think it's important but I don't want to get lost in tons of comments)
vladkras

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