Lebowtech Blog

Delay Ajax on Selects

| Comments

Recently I made an application that would reload the data via AJAX when data in a form was changed, standard stuff. The submit action of the form was connected to the AJAX request and the form elements have their onChange action submit the parent form.

A strange issue that we noticed was when using select elements. If you tab to one of the elements and start typing the select box will change to the option that matches what you started typing.

1
2
3
4
5
<select>
    <option value="a">a</option>
    <option value="ab">ab</option>
    <option value="abc">abc</option>
</select>

If you were to type abc the browser would change the value of our select box first to a then ab then abc, each time firing our form’s AJAX submit each time. You can see how this can add unneeded stress requests to the server, especially if you have a lot of options in your select tag.

The solution that we came up with is to insert a delay before firing the submit action when we are dealing with the onchange handler for selects.

using clearTimeoutlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//form submitter waits after event before sending.
var  formSubmit ={
    submit: function () {
        console.log('submting form');
        $('form#ajaxForm').submit();
        delete this.timeoutID;
    },

    setup: function(timeout) {
        console.log('setting up submitter');
        this.cancel();
        var self = this;
        this.timeoutID = window.setTimeout(function() {self.submit();}, timeout);
        console.log(this.timeoutID);
    },

    cancel: function() {
        console.log('cancel');
        console.log(this.timeoutID);
        if(typeof this.timeoutID == "number") {
            window.clearTimeout(this.timeoutID);
            delete this.timeoutID;
        }
    }

}

Then we attach it to the select elements.

using cakephp’s Js helper.
1
2
3
4
$this->Js->get("form#ajaxForm select");
$this->Js->event('change',
                 "formSubmit.setup(3000)"
    );  

So now what happens, when the select box changes, we start the timeout timer for 3 seconds, and if we get another change within the 3 seconds we cancel the first one.

Now some times we want the event to fire right away, so we can just add to the blur event and the change event for regular inputs to use a smaller time out.

using cakephp’s JS helper
1
2
3
4
5
6
7
8
9
10
11
$this->Js->get("form#ajaxForm select");
$this->Js->event('change',
                 "formSubmit.setup(1500)"
    );  
$this->Js->event('blur',
                "formSubmit.setup(10)"
                );
$this->Js->get("form#ajaxForm input");
$this->Js->event('change',
                 "formSubmit.setup(10)"
    );  

The next thing to do would be to cancel any outstanding AJAX requests, but I’ll save that for another time.

Comments