Question

In my form I have a set of input boxes where a user can input a value. On change of one of these boxes, the form automatically gets submitted.

The problem now is however that a user stays in the last field, takes the mouse and presses the OK button (of another form) without leaving the textbox first. The change event doesn't get triggered and the old, incorrect values get passed to the next page.

I want to trigger the onchange event after a few miliseconds of inactive keyboard. Just like most autocomplete plugins do.
I think I could implement a timer that starts timing the moment you enter an input field and gets resetted everytime a keystroke is handled and then when it reaches zero the onchange event gets triggered.

I'm not up for re-inventing the wheel and was wondering if such a function is available somewhere.
Suggestions?

Was it helpful?

Solution

I had a similar problem and created a jQuery plugin currently in use in an internal application. It should trigger the change event after the user is done typing.

If you are not using jQuery, the code is still adaptable to anything else.

jQuery.fn.handleKeyboardChange = function(nDelay)
{
    // Utility function to test if a keyboard event should be ignored
    function shouldIgnore(event) 
    { 
        var mapIgnoredKeys = {
             9:true, // Tab
            16:true, 17:true, 18:true, // Shift, Alt, Ctrl
            37:true, 38:true, 39:true, 40:true, // Arrows 
            91:true, 92:true, 93:true // Windows keys
        };
        return mapIgnoredKeys[event.which];
    }

    // Utility function to fire OUR change event if the value was actually changed
    function fireChange($element)
    {
        if( $element.val() != jQuery.data($element[0], "valueLast") )
        {
            jQuery.data($element[0], "valueLast", $element.val())
            $element.trigger("change");
        }
    }

    // The currently running timeout,
    // will be accessed with closures
    var timeout = 0;

    // Utility function to cancel a previously set timeout
    function clearPreviousTimeout()
    {
        if( timeout )
        { 
            clearTimeout(timeout);
        }
    }

    return this
    .keydown(function(event)
    {
        if( shouldIgnore(event) ) return;
        // User pressed a key, stop the timeout for now
        clearPreviousTimeout();
        return null; 
    })
    .keyup(function(event)
    {
        if( shouldIgnore(event) ) return;
        // Start a timeout to fire our event after some time of inactivity
        // Eventually cancel a previously running timeout
        clearPreviousTimeout();
        var $self = $(this);
        timeout = setTimeout(function(){ fireChange($self) }, nDelay);
    })
    .change(function()
    {
        // Fire a change
        // Use our function instead of just firing the event
        // Because we want to check if value really changed since
        // our previous event.
        // This is for when the browser fires the change event
        // though we already fired the event because of the timeout
        fireChange($(this));
    })
    ;
}

Usage:

$("#my_input").handleKeyboardChange(300).change(function()
{
    // value has changed!
});

OTHER TIPS

Does it not work to do an onBlur, so both when the user moves to the next field or clicks something else, the value is saved?

I don't know that such a solution would be considered "re-inventing" anything. As you said, it sounds to be nothing more than a simple setTimeout once the page loads. After about 3,000 milliseconds, it runs form.submit().

I would probably restart the count-down with each keystroke too, to give the user enough time to make their entry.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top