MDL-59836 core_amd: Use only one input event handler
authorJun Pataleta <jun@moodle.com>
Fri, 18 Aug 2017 03:19:08 +0000 (11:19 +0800)
committerJun Pataleta <jun@moodle.com>
Fri, 18 Aug 2017 03:19:08 +0000 (11:19 +0800)
* We have duplicate input event handlers for the autocomplete element
which are both firing when the input element's value is being set.
In case an AJAX handler is defined for the autocomplete suggestions,
this causes the autocomplete suggestions so show "No suggestions" first
and then load the results from the AJAX handler a little bit later.

lib/amd/build/form-autocomplete.min.js
lib/amd/src/form-autocomplete.js

index 233e46e..e0e9f5d 100644 (file)
Binary files a/lib/amd/build/form-autocomplete.min.js and b/lib/amd/build/form-autocomplete.min.js differ
index 17e7adf..12f44eb 100644 (file)
@@ -687,19 +687,40 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
         });
         // Whenever the input field changes, update the suggestion list.
         if (options.showSuggestions) {
-            inputElement.on('input', function(e) {
-                var query = $(e.currentTarget).val();
-                var last = $(e.currentTarget).data('last-value');
-                // IE11 fires many more input events than required - even when the value has not changed.
-                // We need to only do this for real value changed events or the suggestions will be
-                // unclickable on IE11 (because they will be rebuilt before the click event fires).
-                // Note - because of this we cannot close the list when the query is empty or it will break
-                // on IE11.
-                if (last !== query) {
-                    updateSuggestions(options, state, query, originalSelect);
-                }
-                $(e.currentTarget).data('last-value', query);
-            });
+            // If this field uses ajax, set it up.
+            if (options.ajax) {
+                require([options.ajax], function(ajaxHandler) {
+                    var throttleTimeout = null;
+                    var handler = function(e) {
+                        updateAjax(e, options, state, originalSelect, ajaxHandler);
+                    };
+
+                    // For input events, we do not want to trigger many, many updates.
+                    var throttledHandler = function(e) {
+                        if (throttleTimeout !== null) {
+                            window.clearTimeout(throttleTimeout);
+                            throttleTimeout = null;
+                        }
+                        throttleTimeout = window.setTimeout(handler.bind(this, e), 300);
+                    };
+                    // Trigger an ajax update after the text field value changes.
+                    inputElement.on("input", throttledHandler);
+                });
+            } else {
+                inputElement.on('input', function(e) {
+                    var query = $(e.currentTarget).val();
+                    var last = $(e.currentTarget).data('last-value');
+                    // IE11 fires many more input events than required - even when the value has not changed.
+                    // We need to only do this for real value changed events or the suggestions will be
+                    // unclickable on IE11 (because they will be rebuilt before the click event fires).
+                    // Note - because of this we cannot close the list when the query is empty or it will break
+                    // on IE11.
+                    if (last !== query) {
+                        updateSuggestions(options, state, query, originalSelect);
+                    }
+                    $(e.currentTarget).data('last-value', query);
+                });
+            }
         }
     };
 
@@ -804,31 +825,10 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
                 // Add the event handlers.
                 addNavigation(options, state, originalSelect);
 
-                var inputElement = $(document.getElementById(state.inputId));
                 var suggestionsElement = $(document.getElementById(state.suggestionsId));
                 // Hide the suggestions by default.
                 suggestionsElement.hide().attr('aria-hidden', true);
 
-                // If this field uses ajax, set it up.
-                if (options.ajax) {
-                    require([options.ajax], function(ajaxHandler) {
-                        var throttleTimeout = null;
-                        var handler = function(e) {
-                            updateAjax(e, options, state, originalSelect, ajaxHandler);
-                        };
-
-                        // For input events, we do not want to trigger many, many updates.
-                        var throttledHandler = function(e) {
-                            if (throttleTimeout !== null) {
-                                window.clearTimeout(throttleTimeout);
-                                throttleTimeout = null;
-                            }
-                            throttleTimeout = window.setTimeout(handler.bind(this, e), 300);
-                        };
-                        // Trigger an ajax update after the text field value changes.
-                        inputElement.on("input", throttledHandler);
-                    });
-                }
                 // Show the current values in the selection list.
                 updateSelectionList(options, state, originalSelect);
                 return true;