MDL-35680 user selector: more usable when queries are slow.
authorTim Hunt <T.J.Hunt@open.ac.uk>
Thu, 27 Sep 2012 18:03:34 +0000 (19:03 +0100)
committerTim Hunt <T.J.Hunt@open.ac.uk>
Thu, 27 Sep 2012 18:10:41 +0000 (19:10 +0100)
The problem is to do when you pause a bit, so a search starts, and then
type a bit more before the search finishes. It was behaving like this:

1. Type a bit, then pause.
2. First search request sent.
3. Type a bit more, then pause.
4. Second search request sent.
5. First search request completes.
6. You try to select one result.
7. Second search request comples, overwriting what you are selecting.

This fix works by cancelling the first request before sending the
second.

user/selector/module.js

index 68b743d..de2f500 100644 (file)
@@ -43,6 +43,8 @@ M.core_user.init_user_selector = function (Y, name, hash, extrafields, lastsearc
         listbox : Y.one('#'+name),
         /** Used to hold the timeout id of the timeout that waits before doing a search. */
         timeoutid : null,
+        /** Stores any in-progress remote requests. */
+        iotransactions : {},
         /** The last string that we searched for, so we can avoid unnecessary repeat searches. */
         lastsearch : lastsearch,
         /** Whether any options where selected last time we checked. Used by
@@ -140,7 +142,12 @@ M.core_user.init_user_selector = function (Y, name, hash, extrafields, lastsearc
                 return;
             }
 
-            Y.io(M.cfg.wwwroot + '/user/selector/search.php', {
+            // Try to cancel existing transactions.
+            Y.Object.each(this.iotransactions, function(trans) {
+                trans.abort();
+            });
+
+            var iotrans = Y.io(M.cfg.wwwroot + '/user/selector/search.php', {
                 method: 'POST',
                 data: 'selectorid='+hash+'&sesskey='+M.cfg.sesskey+'&search='+value + '&userselector_searchanywhere=' + this.get_option('searchanywhere'),
                 on: {
@@ -149,6 +156,7 @@ M.core_user.init_user_selector = function (Y, name, hash, extrafields, lastsearc
                 },
                 context:this
             });
+            this.iotransactions[iotrans.id] = iotrans;
 
             this.lastsearch = value;
             this.listbox.setStyle('background','url(' + M.util.image_url('i/loading', 'moodle') + ') no-repeat center center');
@@ -160,17 +168,27 @@ M.core_user.init_user_selector = function (Y, name, hash, extrafields, lastsearc
          */
         handle_response : function(requestid, response) {
             try {
+                delete this.iotransactions[requestid];
+                if (!Y.Object.isEmpty(this.iotransactions)) {
+                    // More searches pending. Wait until they are all done.
+                    return;
+                }
                 this.listbox.setStyle('background','');
                 var data = Y.JSON.parse(response.responseText);
                 this.output_options(data);
             } catch (e) {
-                this.handle_failure();
+                this.handle_failure(requestid);
             }
         },
         /**
          * Handles what happens when the ajax request fails.
          */
-        handle_failure : function() {
+        handle_failure : function(requestid) {
+            delete this.iotransactions[requestid];
+            if (!Y.Object.isEmpty(this.iotransactions)) {
+                // More searches pending. Wait until they are all done.
+                return;
+            }
             this.listbox.setStyle('background','');
             this.searchfield.addClass('error');