it-swarm.com.de

Führen Sie die JavaScript-Funktion aus, wenn der Benutzer die Eingabe abgeschlossen hat, anstatt die Taste zu drücken.

Ich möchte eine Ajax-Anfrage auslösen, wenn der Benutzer die Eingabe in ein Textfeld abgeschlossen hat. Ich möchte nicht, dass die Funktion jedes Mal ausgeführt wird, wenn der Benutzer einen Buchstaben eingibt, da dies zu einer Menge ajax-Anfragen führen würde.

Gibt es eine Möglichkeit, zu erkennen, wann der Benutzer die Eingabe abgeschlossen hat, und dann die Ajax-Anforderung ausführen?

Verwenden Sie jQuery hier! Dave

384
Macmee

Ich schätze, das Ende der Eingabe bedeutet, dass Sie nur eine Weile aufhören, sagen wir 5 Sekunden. In diesem Sinne können Sie einen Timer starten, wenn der Benutzer eine Taste loslässt, und die Taste löschen, wenn Sie eine Taste drücken. Ich entschied, dass die fragliche Eingabe #myInput sein wird.

Einige Annahmen machen ...

//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
}
565
Surreal Dreams

Die oben gewählte Antwort funktioniert nicht.

Da typingTimer gelegentlich mehrmals eingestellt wird (die Taste zweimal gedrückt wird, bevor der Auslöser für schnelle Eingabe usw. ausgelöst wird), wird sie nicht richtig gelöscht.

Die Lösung unten löst dieses Problem und ruft nach dem OP-Aufruf X Sekunden nach Beendigung auf. Es erfordert auch nicht mehr die redundante Keydown-Funktion. Ich habe auch einen Check hinzugefügt, damit Ihr Funktionsaufruf nicht erfolgt, wenn Ihre Eingabe leer ist.

//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
}

Und derselbe Code in der Vanilla JavaScript-Lösung:

//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
}

Diese Lösung verwendet ES6, ist aber hier nicht erforderlich. Ersetzen Sie einfach let durch var und die Pfeilfunktion durch eine reguläre Funktion.

325
going

Es ist nur eine Zeile mit underscore.js Debounce-Funktion:

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

Dies bedeutet im Grunde doSomething 500 Millisekunden, nachdem ich aufgehört habe zu tippen.

Für weitere Informationen: http://underscorejs.org/#debounce

70
bit2pixel

Ja, Sie können für jedes Key-Up-Ereignis ein Timeout von etwa 2 Sekunden festlegen, das eine Ajax-Anforderung auslöst. Sie können die XHR-Methode auch speichern und bei nachfolgenden Tastendruckereignissen abbrechen, um noch mehr Bandbreite zu sparen. Hier ist etwas, was ich für ein Autocomplete-Skript von mir geschrieben habe.

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

Hoffe das hilft,

Marko

40
Marko
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);
    }
});

vollständiges Beispiel hier: http://jsfiddle.net/ZYXp4/8/

16
azzy81

Ich mag die Antwort von Surreal Dream, aber ich habe festgestellt, dass meine "doneTyping" -Funktion bei jedem Tastendruck ausgelöst wird, d. H. Wenn Sie "Hallo" wirklich schnell eingeben; Anstatt nur einmal zu feuern, wenn Sie aufhören zu tippen, wird die Funktion fünfmal ausgelöst.

Das Problem war, dass die JavaScript-Funktion setTimeout die gesetzten alten Zeitüberschreitungen nicht zu überschreiben oder zu beenden scheint, aber wenn Sie es selbst tun, funktioniert es! Also habe ich kurz vor dem setTimeout einen clearTimeout-Aufruf hinzugefügt, wenn der typingTimer gesetzt ist. Siehe unten:

//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
}

N.B. Ich hätte es gerne als Kommentar zu Surreal Dreams Antwort hinzugefügt, aber ich bin ein neuer Benutzer und habe nicht genug Ruf. Es tut uns leid!

10
Liam Flanagan

Ändern der akzeptierten Antwort, um zusätzliche Fälle wie Einfügen zu behandeln:

//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
}
8
Jecoms

Beide Top-2-Antworten funktionieren für mich nicht. Also hier ist meine Lösung:

var timeout = null;

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

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

Ich denke nicht, dass das keyDown-Ereignis in diesem Fall notwendig ist (bitte sagen Sie mir, warum ich falsch liege). In meinem (nicht jquery) Skript sieht eine ähnliche Lösung so aus:

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)
    }

}

Es ist meine erste Antwort auf Stack Overflow, also hoffe ich, dass dies jemandem irgendwann hilft :)

4
Rafal Pastuszak

Nun, streng genommen nein, da der Computer nicht ahnen kann, wann der Benutzer mit der Eingabe fertig ist. Sie können natürlich einen Timer beim Einschalten der Taste auslösen und bei jeder nachfolgenden Taste zurücksetzen. Wenn der Timer abläuft, hat der Benutzer die Timer-Dauer nicht eingegeben. Sie können dies als "Eingabe abschließen" bezeichnen.

Wenn Sie erwarten, dass Benutzer beim Tippen Pausen einlegen, können Sie nicht wissen, wann sie fertig sind.

(Außer natürlich können Sie an den Daten erkennen, wann sie fertig sind.) 

4
sleske

Ich finde, dass die Lösung mit dem Ereignis input etwas einfacher ist:

var typingTimer;
var doneTypingInterval = 500;

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

function doneTyping () {
    // code here
}
2
Adrien Brunelat

LÖSUNG:

Ich habe die Suche in meinem Angebot implementiert und brauche sie auf Ajax-Basis. Das bedeutet, dass bei jeder Schlüsseländerung die Suchergebnisse aktualisiert und angezeigt werden sollten. Dies führt dazu, dass so viele Ajax-Aufrufe an den Server gesendet werden, was keine gute Sache ist. Nach einiger Arbeit machte ich einen Ansatz für den Ping-Server, wenn der Client die Eingabe aufhört.

Die Lösung, die für mich funktioniert hat, ist:

$(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

Sie haben festgestellt, dass bei der Implementierung kein Timer verwendet werden muss.

Ich bin sicher, das wird anderen helfen.

An einer

2
Ata ul Mustafa

Sie können das onblur -Ereignis verwenden, um zu erkennen, wann das Textfeld den Fokus verliert: https://developer.mozilla.org/de/DOM/element.onblur

Das ist nicht dasselbe wie "hört auf zu tippen", wenn Sie sich um den Fall kümmern, in dem der Benutzer ein paar Sachen eingibt und dann dort sitzt, während das Textfeld noch fokussiert ist.

Dafür würde ich vorschlagen, ein setTimeout an das onclick -Ereignis zu binden, und davon auszugehen, dass der Benutzer nach x Zeit ohne Tastenanschläge aufgehört hat zu tippen.

1
Mike Ruhlin

Dies ist der einfache JS-Code, den ich geschrieben habe:

<!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>

Sobald Sie den Fokus auf dem Textfeld erkennen, führen Sie bei aktivierter Taste eine Zeitüberschreitungsprüfung durch und setzen Sie sie bei jeder Auslösung zurück.

Wenn das Timeout abgeschlossen ist, führen Sie Ihre Ajax-Anforderung aus.

0
ocodo

Ich bin mir nicht sicher, ob meine Bedürfnisse irgendwie komisch sind, aber ich brauchte etwas Ähnliches, und das ist es, was ich am Ende verwendet habe:

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

Das erlaubt mir, solche Elemente in meiner Anwendung zu haben:

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

Die Aktualisierung erfolgt, wenn der Benutzer mit der Eingabe fertig ist (keine Aktion für 2 Sekunden) oder in ein anderes Feld wechselt (verwischt das Element).

0

Mehrere Timer pro Seite

Alle anderen Antworten funktionieren nur für ein Steuerelement ( meine andere Antwort eingeschlossen). Wenn Sie mehrere Steuerelemente pro Seite haben (z. B. in einem Einkaufswagen) wird nur das letzte Steuerelement aufgerufen, bei dem der Benutzer etwas eingegeben hat . In meinem Fall ist dies sicherlich nicht das gewünschte Verhalten - jedes Steuerelement sollte einen eigenen Timer haben.

Um dies zu lösen, müssen Sie lediglich eine ID an die Funktion übergeben und ein timeoutHandles-Wörterbuch wie im folgenden Code verwalten:

Funktionserklärung:

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

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

Funktionsnutzung:

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

Warum nicht einfach onfocusout verwenden?

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

Wenn es sich um ein Formular handelt, wird der Fokus jedes Eingabefeldes immer beibehalten, um auf die Schaltfläche "Abschicken" zu klicken, damit Sie wissen, dass keine Eingabe den Aufruf des onfocusout-Ereignishandlers verpassen wird. 

0
coffeeeee

Ich habe gerade einen einfachen Code gefunden, um darauf zu warten, dass der Benutzer die Eingabe beendet hat:

setzen Sie das Zeitlimit auf null und löschen Sie das aktuelle Zeitlimit, wenn der Benutzer eingibt.

schritt 2.Trigger-Zeitüberschreitung für die definierte Variable, bevor das Keyup-Ereignis ausgelöst wird.

schritt 3. Definieren Sie ein Timeout für die oben deklarierte Variable.

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

javascript-Code

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);
};
0

Wenn Sie warten müssen, bis der Benutzer mit der Eingabe fertig ist, verwenden Sie einfach Folgendes:

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

Vollständiges Beispiel mit ajax-Aufruf - dies funktioniert für meinen Pager - Anzahl der Elemente pro Liste

$(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
Miroslav Siska

Wenn Sie nach einer bestimmten Länge suchen (z. B. nach einem Postleitzahlfeld):

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

stimme der Antwort von @going zu. Eine andere ähnliche Lösung, die für mich funktioniert hat, ist die folgende. Der einzige Unterschied ist, dass ich .on ("Eingabe" ...) anstelle von keyup verwende. Dadurch werden nur Änderungen in der Eingabe erfasst. andere Tasten wie Strg, Umschalt usw. werden ignoriert

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);
});
0
Grace.io

Deklarieren Sie die folgende delay-Funktion:

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

und dann verwenden Sie es:

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