weekly release 4.0dev+
[moodle.git] / lib / amd / build / form-autocomplete.min.js.map
1 {"version":3,"sources":["../src/form-autocomplete.js"],"names":["define","$","log","str","templates","notification","LoadingIcon","Aria","FormChangeChecker","KEYS","DOWN","ENTER","SPACE","ESCAPE","COMMA","UP","LEFT","RIGHT","uniqueId","Date","now","activateSelection","index","state","selectionElement","document","getElementById","selectionId","length","children","element","get","itemId","attr","Deferred","resolve","getActiveElementFromState","selectionRegion","activeId","activeElement","activeValue","replace","find","updateActiveSelectionFromState","activeIndex","updateSelectionList","options","originalSelect","pendingKey","inputId","M","util","js_pending","items","newSelection","each","ele","prop","label","data","html","push","value","hasItemListChanged","js_complete","Promise","context","extend","render","then","js","replaceNodeContents","catch","exception","filter","item","indexOf","notifyChange","markFormChangedFromNode","dispatchEvent","Event","deselectItem","selectedItemValue","remove","activateItem","inputElement","suggestionsElement","suggestionsId","globalIndex","scrollPos","offset","top","scrollTop","height","animate","promise","activateNextItem","current","activatePreviousSelection","selectionsElement","activateNextSelection","activatePreviousItem","closeSuggestions","hide","updateSuggestions","query","matchingElements","suggestions","option","innerHTML","searchquery","caseSensitive","toLocaleLowerCase","returnVal","replaceNode","unhide","show","node","text","tags","get_string","done","nosuggestionsstr","createItem","val","split","found","tagindex","tag","trim","multiple","append","createTextNode","selectCurrentItem","closeSuggestionsOnSelect","focus","updateAjax","e","ajaxHandler","pendingPromise","addPendingJSPromise","parentElement","selectId","parent","addIconToContainerRemoveOnCompletion","currentTarget","transport","selector","results","processedResults","processResults","existingValues","optionIndex","isArray","resultIndex","result","error","reject","addNavigation","on","pendingJsPromise","keyCode","showSuggestions","ajax","require","preventDefault","closest","window","setTimeout","focusElement","timeoutPromise","is","arrowElement","downArrowId","off","selectedItem","throttleTimeout","inProgress","handler","arguments","throttledHandler","clearTimeout","bind","last","key","enhance","placeholder","noSelectionString","templateOverrides","input","layout","selection","fail","debug","css","prepend","originalLabel","collectedjs","renderLayout","renderInput","renderDatalist","renderSelection","when","container","replaceWith","runTemplateJS"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Autocomplete wrapper for select2 library.\n *\n * @module     core/form-autocomplete\n * @copyright  2015 Damyon Wiese <damyon@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since      3.0\n */\ndefine([\n    'jquery',\n    'core/log',\n    'core/str',\n    'core/templates',\n    'core/notification',\n    'core/loadingicon',\n    'core/aria',\n    'core_form/changechecker',\n], function(\n    $,\n    log,\n    str,\n    templates,\n    notification,\n    LoadingIcon,\n    Aria,\n    FormChangeChecker\n) {\n    // Private functions and variables.\n    /** @var {Object} KEYS - List of keycode constants. */\n    var KEYS = {\n        DOWN: 40,\n        ENTER: 13,\n        SPACE: 32,\n        ESCAPE: 27,\n        COMMA: 44,\n        UP: 38,\n        LEFT: 37,\n        RIGHT: 39\n    };\n\n    var uniqueId = Date.now();\n\n    /**\n     * Make an item in the selection list \"active\".\n     *\n     * @method activateSelection\n     * @private\n     * @param {Number} index The index in the current (visible) list of selection.\n     * @param {Object} state State variables for this autocomplete element.\n     * @return {Promise}\n     */\n    var activateSelection = function(index, state) {\n        // Find the elements in the DOM.\n        var selectionElement = $(document.getElementById(state.selectionId));\n\n        // Count the visible items.\n        var length = selectionElement.children('[aria-selected=true]').length;\n        // Limit the index to the upper/lower bounds of the list (wrap in both directions).\n        index = index % length;\n        while (index < 0) {\n            index += length;\n        }\n        // Find the specified element.\n        var element = $(selectionElement.children('[aria-selected=true]').get(index));\n        // Create an id we can assign to this element.\n        var itemId = state.selectionId + '-' + index;\n\n        // Deselect all the selections.\n        selectionElement.children().attr('data-active-selection', null).attr('id', '');\n\n        // Select only this suggestion and assign it the id.\n        element.attr('data-active-selection', true).attr('id', itemId);\n\n        // Tell the input field it has a new active descendant so the item is announced.\n        selectionElement.attr('aria-activedescendant', itemId);\n        selectionElement.attr('data-active-value', element.attr('data-value'));\n\n        return $.Deferred().resolve();\n    };\n\n    /**\n     * Get the actively selected element from the state object.\n     *\n     * @param   {Object} state\n     * @returns {jQuery}\n     */\n    var getActiveElementFromState = function(state) {\n        var selectionRegion = $(document.getElementById(state.selectionId));\n        var activeId = selectionRegion.attr('aria-activedescendant');\n\n        if (activeId) {\n            var activeElement = $(document.getElementById(activeId));\n            if (activeElement.length) {\n                // The active descendent still exists.\n                return activeElement;\n            }\n        }\n\n        // Ensure we are creating a properly formed selector based on the active value.\n        var activeValue = selectionRegion.attr('data-active-value')?.replace(/\"/g, '\\\\\"');\n        return selectionRegion.find('[data-value=\"' + activeValue + '\"]');\n    };\n\n    /**\n     * Update the active selection from the given state object.\n     *\n     * @param   {Object} state\n     */\n    var updateActiveSelectionFromState = function(state) {\n        var activeElement = getActiveElementFromState(state);\n        var activeValue = activeElement.attr('data-value');\n\n        var selectionRegion = $(document.getElementById(state.selectionId));\n        if (activeValue) {\n            // Find the index of the currently selected index.\n            var activeIndex = selectionRegion.find('[aria-selected=true]').index(activeElement);\n\n            if (activeIndex !== -1) {\n                activateSelection(activeIndex, state);\n                return;\n            }\n        }\n\n        // Either the active index was not set, or it could not be found.\n        // Select the first value instead.\n        activateSelection(0, state);\n    };\n\n    /**\n     * Update the element that shows the currently selected items.\n     *\n     * @method updateSelectionList\n     * @private\n     * @param {Object} options Original options for this autocomplete element.\n     * @param {Object} state State variables for this autocomplete element.\n     * @param {JQuery} originalSelect The JQuery object matching the hidden select list.\n     * @return {Promise}\n     */\n    var updateSelectionList = function(options, state, originalSelect) {\n        var pendingKey = 'form-autocomplete-updateSelectionList-' + state.inputId;\n        M.util.js_pending(pendingKey);\n\n        // Build up a valid context to re-render the template.\n        var items = [];\n        var newSelection = $(document.getElementById(state.selectionId));\n        originalSelect.children('option').each(function(index, ele) {\n            if ($(ele).prop('selected')) {\n                var label;\n                if ($(ele).data('html')) {\n                    label = $(ele).data('html');\n                } else {\n                    label = $(ele).html();\n                }\n                if (label !== '') {\n                    items.push({label: label, value: $(ele).attr('value')});\n                }\n            }\n        });\n\n        if (!hasItemListChanged(state, items)) {\n            M.util.js_complete(pendingKey);\n            return Promise.resolve();\n        }\n\n        state.items = items;\n\n        var context = $.extend(options, state);\n        // Render the template.\n        return templates.render(options.templates.items, context)\n        .then(function(html, js) {\n            // Add it to the page.\n            templates.replaceNodeContents(newSelection, html, js);\n\n            updateActiveSelectionFromState(state);\n\n            return;\n        })\n        .then(function() {\n            return M.util.js_complete(pendingKey);\n        })\n        .catch(notification.exception);\n    };\n\n    /**\n     * Check whether the list of items stored in the state has changed.\n     *\n     * @param   {Object} state\n     * @param   {Array} items\n     * @returns {Boolean}\n     */\n    var hasItemListChanged = function(state, items) {\n        if (state.items.length !== items.length) {\n            return true;\n        }\n\n        // Check for any items in the state items which are not present in the new items list.\n        return state.items.filter(item => items.indexOf(item) === -1).length > 0;\n    };\n\n    /**\n     * Notify of a change in the selection.\n     *\n     * @param {jQuery} originalSelect The jQuery object matching the hidden select list.\n     */\n    var notifyChange = function(originalSelect) {\n        FormChangeChecker.markFormChangedFromNode(originalSelect[0]);\n\n        // Note, jQuery .change() was not working here. Better to\n        // use plain JavaScript anyway.\n        originalSelect[0].dispatchEvent(new Event('change'));\n    };\n\n    /**\n     * Remove the given item from the list of selected things.\n     *\n     * @method deselectItem\n     * @private\n     * @param {Object} options Original options for this autocomplete element.\n     * @param {Object} state State variables for this autocomplete element.\n     * @param {Element} item The item to be deselected.\n     * @param {Element} originalSelect The original select list.\n     * @return {Promise}\n     */\n    var deselectItem = function(options, state, item, originalSelect) {\n        var selectedItemValue = $(item).attr('data-value');\n\n        // Look for a match, and toggle the selected property if there is a match.\n        originalSelect.children('option').each(function(index, ele) {\n            if ($(ele).attr('value') == selectedItemValue) {\n                $(ele).prop('selected', false);\n                // We remove newly created custom tags from the suggestions list when they are deselected.\n                if ($(ele).attr('data-iscustom')) {\n                    $(ele).remove();\n                }\n            }\n        });\n        // Rerender the selection list.\n        return updateSelectionList(options, state, originalSelect)\n        .then(function() {\n            // Notify that the selection changed.\n            notifyChange(originalSelect);\n\n            return;\n        });\n    };\n\n    /**\n     * Make an item in the suggestions \"active\" (about to be selected).\n     *\n     * @method activateItem\n     * @private\n     * @param {Number} index The index in the current (visible) list of suggestions.\n     * @param {Object} state State variables for this instance of autocomplete.\n     * @return {Promise}\n     */\n    var activateItem = function(index, state) {\n        // Find the elements in the DOM.\n        var inputElement = $(document.getElementById(state.inputId));\n        var suggestionsElement = $(document.getElementById(state.suggestionsId));\n\n        // Count the visible items.\n        var length = suggestionsElement.children(':not([aria-hidden])').length;\n        // Limit the index to the upper/lower bounds of the list (wrap in both directions).\n        index = index % length;\n        while (index < 0) {\n            index += length;\n        }\n        // Find the specified element.\n        var element = $(suggestionsElement.children(':not([aria-hidden])').get(index));\n        // Find the index of this item in the full list of suggestions (including hidden).\n        var globalIndex = $(suggestionsElement.children('[role=option]')).index(element);\n        // Create an id we can assign to this element.\n        var itemId = state.suggestionsId + '-' + globalIndex;\n\n        // Deselect all the suggestions.\n        suggestionsElement.children().attr('aria-selected', false).attr('id', '');\n        // Select only this suggestion and assign it the id.\n        element.attr('aria-selected', true).attr('id', itemId);\n        // Tell the input field it has a new active descendant so the item is announced.\n        inputElement.attr('aria-activedescendant', itemId);\n\n        // Scroll it into view.\n        var scrollPos = element.offset().top\n                       - suggestionsElement.offset().top\n                       + suggestionsElement.scrollTop()\n                       - (suggestionsElement.height() / 2);\n        return suggestionsElement.animate({\n            scrollTop: scrollPos\n        }, 100).promise();\n    };\n\n    /**\n     * Find the index of the current active suggestion, and activate the next one.\n     *\n     * @method activateNextItem\n     * @private\n     * @param {Object} state State variable for this auto complete element.\n     * @return {Promise}\n     */\n    var activateNextItem = function(state) {\n        // Find the list of suggestions.\n        var suggestionsElement = $(document.getElementById(state.suggestionsId));\n        // Find the active one.\n        var element = suggestionsElement.children('[aria-selected=true]');\n        // Find it's index.\n        var current = suggestionsElement.children(':not([aria-hidden])').index(element);\n        // Activate the next one.\n        return activateItem(current + 1, state);\n    };\n\n    /**\n     * Find the index of the current active selection, and activate the previous one.\n     *\n     * @method activatePreviousSelection\n     * @private\n     * @param {Object} state State variables for this instance of autocomplete.\n     * @return {Promise}\n     */\n    var activatePreviousSelection = function(state) {\n        // Find the list of selections.\n        var selectionsElement = $(document.getElementById(state.selectionId));\n        // Find the active one.\n        var element = selectionsElement.children('[data-active-selection]');\n        if (!element) {\n            return activateSelection(0, state);\n        }\n        // Find it's index.\n        var current = selectionsElement.children('[aria-selected=true]').index(element);\n        // Activate the next one.\n        return activateSelection(current - 1, state);\n    };\n\n    /**\n     * Find the index of the current active selection, and activate the next one.\n     *\n     * @method activateNextSelection\n     * @private\n     * @param {Object} state State variables for this instance of autocomplete.\n     * @return {Promise}\n     */\n    var activateNextSelection = function(state) {\n        // Find the list of selections.\n        var selectionsElement = $(document.getElementById(state.selectionId));\n\n        // Find the active one.\n        var element = selectionsElement.children('[data-active-selection]');\n        var current = 0;\n\n        if (element) {\n            // The element was found. Determine the index and move to the next one.\n            current = selectionsElement.children('[aria-selected=true]').index(element);\n            current = current + 1;\n        } else {\n            // No selected item found. Move to the first.\n            current = 0;\n        }\n\n        return activateSelection(current, state);\n    };\n\n    /**\n     * Find the index of the current active suggestion, and activate the previous one.\n     *\n     * @method activatePreviousItem\n     * @private\n     * @param {Object} state State variables for this autocomplete element.\n     * @return {Promise}\n     */\n    var activatePreviousItem = function(state) {\n        // Find the list of suggestions.\n        var suggestionsElement = $(document.getElementById(state.suggestionsId));\n\n        // Find the active one.\n        var element = suggestionsElement.children('[aria-selected=true]');\n\n        // Find it's index.\n        var current = suggestionsElement.children(':not([aria-hidden])').index(element);\n\n        // Activate the previous one.\n        return activateItem(current - 1, state);\n    };\n\n    /**\n     * Close the list of suggestions.\n     *\n     * @method closeSuggestions\n     * @private\n     * @param {Object} state State variables for this autocomplete element.\n     * @return {Promise}\n     */\n    var closeSuggestions = function(state) {\n        // Find the elements in the DOM.\n        var inputElement = $(document.getElementById(state.inputId));\n        var suggestionsElement = $(document.getElementById(state.suggestionsId));\n\n        if (inputElement.attr('aria-expanded') === \"true\") {\n            // Announce the list of suggestions was closed.\n            inputElement.attr('aria-expanded', false);\n        }\n        // Read the current list of selections.\n        inputElement.attr('aria-activedescendant', state.selectionId);\n\n        // Hide the suggestions list (from screen readers too).\n        Aria.hide(suggestionsElement.get());\n        suggestionsElement.hide();\n\n        return $.Deferred().resolve();\n    };\n\n    /**\n     * Rebuild the list of suggestions based on the current values in the select list, and the query.\n     *\n     * @method updateSuggestions\n     * @private\n     * @param {Object} options The original options for this autocomplete.\n     * @param {Object} state The state variables for this autocomplete.\n     * @param {String} query The current text for the search string.\n     * @param {JQuery} originalSelect The JQuery object matching the hidden select list.\n     * @return {Promise}\n     */\n    var updateSuggestions = function(options, state, query, originalSelect) {\n        var pendingKey = 'form-autocomplete-updateSuggestions-' + state.inputId;\n        M.util.js_pending(pendingKey);\n\n        // Find the elements in the DOM.\n        var inputElement = $(document.getElementById(state.inputId));\n        var suggestionsElement = $(document.getElementById(state.suggestionsId));\n\n        // Used to track if we found any visible suggestions.\n        var matchingElements = false;\n        // Options is used by the context when rendering the suggestions from a template.\n        var suggestions = [];\n        originalSelect.children('option').each(function(index, option) {\n            if ($(option).prop('selected') !== true) {\n                suggestions[suggestions.length] = {label: option.innerHTML, value: $(option).attr('value')};\n            }\n        });\n\n        // Re-render the list of suggestions.\n        var searchquery = state.caseSensitive ? query : query.toLocaleLowerCase();\n        var context = $.extend({options: suggestions}, options, state);\n        var returnVal = templates.render(\n            'core/form_autocomplete_suggestions',\n            context\n        )\n        .then(function(html, js) {\n            // We have the new template, insert it in the page.\n            templates.replaceNode(suggestionsElement, html, js);\n\n            // Get the element again.\n            suggestionsElement = $(document.getElementById(state.suggestionsId));\n\n            // Show it if it is hidden.\n            Aria.unhide(suggestionsElement.get());\n            suggestionsElement.show();\n\n            // For each option in the list, hide it if it doesn't match the query.\n            suggestionsElement.children().each(function(index, node) {\n                node = $(node);\n                if ((options.caseSensitive && node.text().indexOf(searchquery) > -1) ||\n                        (!options.caseSensitive && node.text().toLocaleLowerCase().indexOf(searchquery) > -1)) {\n                    Aria.unhide(node.get());\n                    node.show();\n                    matchingElements = true;\n                } else {\n                    node.hide();\n                    Aria.hide(node.get());\n                }\n            });\n            // If we found any matches, show the list.\n            inputElement.attr('aria-expanded', true);\n            if (originalSelect.attr('data-notice')) {\n                // Display a notice rather than actual suggestions.\n                suggestionsElement.html(originalSelect.attr('data-notice'));\n            } else if (matchingElements) {\n                // We only activate the first item in the list if tags is false,\n                // because otherwise \"Enter\" would select the first item, instead of\n                // creating a new tag.\n                if (!options.tags) {\n                    activateItem(0, state);\n                }\n            } else {\n                // Nothing matches. Tell them that.\n                str.get_string('nosuggestions', 'form').done(function(nosuggestionsstr) {\n                    suggestionsElement.html(nosuggestionsstr);\n                });\n            }\n\n            return suggestionsElement;\n        })\n        .then(function() {\n            return M.util.js_complete(pendingKey);\n        })\n        .catch(notification.exception);\n\n        return returnVal;\n    };\n\n    /**\n     * Create a new item for the list (a tag).\n     *\n     * @method createItem\n     * @private\n     * @param {Object} options The original options for the autocomplete.\n     * @param {Object} state State variables for the autocomplete.\n     * @param {JQuery} originalSelect The JQuery object matching the hidden select list.\n     * @return {Promise}\n     */\n    var createItem = function(options, state, originalSelect) {\n        // Find the element in the DOM.\n        var inputElement = $(document.getElementById(state.inputId));\n        // Get the current text in the input field.\n        var query = inputElement.val();\n        var tags = query.split(',');\n        var found = false;\n\n        $.each(tags, function(tagindex, tag) {\n            // If we can only select one at a time, deselect any current value.\n            tag = tag.trim();\n            if (tag !== '') {\n                if (!options.multiple) {\n                    originalSelect.children('option').prop('selected', false);\n                }\n                // Look for an existing option in the select list that matches this new tag.\n                originalSelect.children('option').each(function(index, ele) {\n                    if ($(ele).attr('value') == tag) {\n                        found = true;\n                        $(ele).prop('selected', true);\n                    }\n                });\n                // Only create the item if it's new.\n                if (!found) {\n                    var option = $('<option>');\n                    option.append(document.createTextNode(tag));\n                    option.attr('value', tag);\n                    originalSelect.append(option);\n                    option.prop('selected', true);\n                    // We mark newly created custom options as we handle them differently if they are \"deselected\".\n                    option.attr('data-iscustom', true);\n                }\n            }\n        });\n\n        return updateSelectionList(options, state, originalSelect)\n        .then(function() {\n            // Notify that the selection changed.\n            notifyChange(originalSelect);\n\n            return;\n        })\n        .then(function() {\n            // Clear the input field.\n            inputElement.val('');\n\n            return;\n        })\n        .then(function() {\n            // Close the suggestions list.\n            return closeSuggestions(state);\n        });\n    };\n\n    /**\n     * Select the currently active item from the suggestions list.\n     *\n     * @method selectCurrentItem\n     * @private\n     * @param {Object} options The original options for the autocomplete.\n     * @param {Object} state State variables for the autocomplete.\n     * @param {JQuery} originalSelect The JQuery object matching the hidden select list.\n     * @return {Promise}\n     */\n    var selectCurrentItem = function(options, state, originalSelect) {\n        // Find the elements in the page.\n        var inputElement = $(document.getElementById(state.inputId));\n        var suggestionsElement = $(document.getElementById(state.suggestionsId));\n        // Here loop through suggestions and set val to join of all selected items.\n\n        var selectedItemValue = suggestionsElement.children('[aria-selected=true]').attr('data-value');\n        // The select will either be a single or multi select, so the following will either\n        // select one or more items correctly.\n        // Take care to use 'prop' and not 'attr' for selected properties.\n        // If only one can be selected at a time, start by deselecting everything.\n        if (!options.multiple) {\n            originalSelect.children('option').prop('selected', false);\n        }\n        // Look for a match, and toggle the selected property if there is a match.\n        originalSelect.children('option').each(function(index, ele) {\n            if ($(ele).attr('value') == selectedItemValue) {\n                $(ele).prop('selected', true);\n            }\n        });\n\n        return updateSelectionList(options, state, originalSelect)\n        .then(function() {\n            // Notify that the selection changed.\n            notifyChange(originalSelect);\n\n            return;\n        })\n        .then(function() {\n            if (options.closeSuggestionsOnSelect) {\n                // Clear the input element.\n                inputElement.val('');\n                // Close the list of suggestions.\n                return closeSuggestions(state);\n            } else {\n                // Focus on the input element so the suggestions does not auto-close.\n                inputElement.focus();\n                // Remove the last selected item from the suggestions list.\n                return updateSuggestions(options, state, inputElement.val(), originalSelect);\n            }\n        });\n    };\n\n    /**\n     * Fetch a new list of options via ajax.\n     *\n     * @method updateAjax\n     * @private\n     * @param {Event} e The event that triggered this update.\n     * @param {Object} options The original options for the autocomplete.\n     * @param {Object} state The state variables for the autocomplete.\n     * @param {JQuery} originalSelect The JQuery object matching the hidden select list.\n     * @param {Object} ajaxHandler This is a module that does the ajax fetch and translates the results.\n     * @return {Promise}\n     */\n    var updateAjax = function(e, options, state, originalSelect, ajaxHandler) {\n        var pendingPromise = addPendingJSPromise('updateAjax');\n        // We need to show the indicator outside of the hidden select list.\n        // So we get the parent id of the hidden select list.\n        var parentElement = $(document.getElementById(state.selectId)).parent();\n        LoadingIcon.addIconToContainerRemoveOnCompletion(parentElement, pendingPromise);\n\n        // Get the query to pass to the ajax function.\n        var query = $(e.currentTarget).val();\n        // Call the transport function to do the ajax (name taken from Select2).\n        ajaxHandler.transport(options.selector, query, function(results) {\n            // We got a result - pass it through the translator before using it.\n            var processedResults = ajaxHandler.processResults(options.selector, results);\n            var existingValues = [];\n\n            // Now destroy all options that are not currently selected.\n            if (!options.multiple) {\n                originalSelect.children('option').remove();\n            }\n            originalSelect.children('option').each(function(optionIndex, option) {\n                option = $(option);\n                if (!option.prop('selected')) {\n                    option.remove();\n                } else {\n                    existingValues.push(String(option.attr('value')));\n                }\n            });\n\n            if (!options.multiple && originalSelect.children('option').length === 0) {\n                // If this is a single select - and there are no current options\n                // the first option added will be selected by the browser. This causes a bug!\n                // We need to insert an empty option so that none of the real options are selected.\n                var option = $('<option>');\n                originalSelect.append(option);\n            }\n            if ($.isArray(processedResults)) {\n                // Add all the new ones returned from ajax.\n                $.each(processedResults, function(resultIndex, result) {\n                    if (existingValues.indexOf(String(result.value)) === -1) {\n                        var option = $('<option>');\n                        option.append(result.label);\n                        option.attr('value', result.value);\n                        originalSelect.append(option);\n                    }\n                });\n                originalSelect.attr('data-notice', '');\n            } else {\n                // The AJAX handler returned a string instead of the array.\n                originalSelect.attr('data-notice', processedResults);\n            }\n            // Update the list of suggestions now from the new values in the select list.\n            pendingPromise.resolve(updateSuggestions(options, state, '', originalSelect));\n        }, function(error) {\n            pendingPromise.reject(error);\n        });\n\n        return pendingPromise;\n    };\n\n    /**\n     * Add all the event listeners required for keyboard nav, blur clicks etc.\n     *\n     * @method addNavigation\n     * @private\n     * @param {Object} options The options used to create this autocomplete element.\n     * @param {Object} state State variables for this autocomplete element.\n     * @param {JQuery} originalSelect The JQuery object matching the hidden select list.\n     */\n    var addNavigation = function(options, state, originalSelect) {\n        // Start with the input element.\n        var inputElement = $(document.getElementById(state.inputId));\n        // Add keyboard nav with keydown.\n        inputElement.on('keydown', function(e) {\n            var pendingJsPromise = addPendingJSPromise('addNavigation-' + state.inputId + '-' + e.keyCode);\n\n            switch (e.keyCode) {\n                case KEYS.DOWN:\n                    // If the suggestion list is open, move to the next item.\n                    if (!options.showSuggestions) {\n                        // Do not consume this event.\n                        pendingJsPromise.resolve();\n                        return true;\n                    } else if (inputElement.attr('aria-expanded') === \"true\") {\n                        pendingJsPromise.resolve(activateNextItem(state));\n                    } else {\n                        // Handle ajax population of suggestions.\n                        if (!inputElement.val() && options.ajax) {\n                            require([options.ajax], function(ajaxHandler) {\n                                pendingJsPromise.resolve(updateAjax(e, options, state, originalSelect, ajaxHandler));\n                            });\n                        } else {\n                            // Open the suggestions list.\n                            pendingJsPromise.resolve(updateSuggestions(options, state, inputElement.val(), originalSelect));\n                        }\n                    }\n                    // We handled this event, so prevent it.\n                    e.preventDefault();\n                    return false;\n                case KEYS.UP:\n                    // Choose the previous active item.\n                    pendingJsPromise.resolve(activatePreviousItem(state));\n\n                    // We handled this event, so prevent it.\n                    e.preventDefault();\n                    return false;\n                case KEYS.ENTER:\n                    var suggestionsElement = $(document.getElementById(state.suggestionsId));\n                    if ((inputElement.attr('aria-expanded') === \"true\") &&\n                            (suggestionsElement.children('[aria-selected=true]').length > 0)) {\n                        // If the suggestion list has an active item, select it.\n                        pendingJsPromise.resolve(selectCurrentItem(options, state, originalSelect));\n                    } else if (options.tags) {\n                        // If tags are enabled, create a tag.\n                        pendingJsPromise.resolve(createItem(options, state, originalSelect));\n                    } else {\n                        pendingJsPromise.resolve();\n                    }\n\n                    // We handled this event, so prevent it.\n                    e.preventDefault();\n                    return false;\n                case KEYS.ESCAPE:\n                    if (inputElement.attr('aria-expanded') === \"true\") {\n                        // If the suggestion list is open, close it.\n                        pendingJsPromise.resolve(closeSuggestions(state));\n                    } else {\n                        pendingJsPromise.resolve();\n                    }\n                    // We handled this event, so prevent it.\n                    e.preventDefault();\n                    return false;\n            }\n            pendingJsPromise.resolve();\n            return true;\n        });\n        // Support multi lingual COMMA keycode (44).\n        inputElement.on('keypress', function(e) {\n\n            if (e.keyCode === KEYS.COMMA) {\n                if (options.tags) {\n                    // If we are allowing tags, comma should create a tag (or enter).\n                    addPendingJSPromise('keypress-' + e.keyCode)\n                    .resolve(createItem(options, state, originalSelect));\n                }\n                // We handled this event, so prevent it.\n                e.preventDefault();\n                return false;\n            }\n            return true;\n        });\n        // Support submitting the form without leaving the autocomplete element,\n        // or submitting too quick before the blur handler action is completed.\n        inputElement.closest('form').on('submit', function() {\n            if (options.tags) {\n                // If tags are enabled, create a tag.\n                addPendingJSPromise('form-autocomplete-submit')\n                .resolve(createItem(options, state, originalSelect));\n            }\n\n            return true;\n        });\n        inputElement.on('blur', function() {\n            var pendingPromise = addPendingJSPromise('form-autocomplete-blur');\n            window.setTimeout(function() {\n                // Get the current element with focus.\n                var focusElement = $(document.activeElement);\n                var timeoutPromise = $.Deferred();\n\n                // Only close the menu if the input hasn't regained focus and if the element still exists,\n                // and regain focus if the scrollbar is clicked.\n                // Due to the half a second delay, it is possible that the input element no longer exist\n                // by the time this code is being executed.\n                if (focusElement.is(document.getElementById(state.suggestionsId))) {\n                    inputElement.focus(); // Probably the scrollbar is clicked. Regain focus.\n                } else if (!focusElement.is(inputElement) && $(document.getElementById(state.inputId)).length) {\n                    if (options.tags) {\n                        timeoutPromise.then(function() {\n                            return createItem(options, state, originalSelect);\n                        })\n                        .catch();\n                    }\n                    timeoutPromise.then(function() {\n                        return closeSuggestions(state);\n                    })\n                    .catch();\n                }\n\n                timeoutPromise.then(function() {\n                    return pendingPromise.resolve();\n                })\n                .catch();\n                timeoutPromise.resolve();\n            }, 500);\n        });\n        if (options.showSuggestions) {\n            var arrowElement = $(document.getElementById(state.downArrowId));\n            arrowElement.on('click', function(e) {\n                var pendingPromise = addPendingJSPromise('form-autocomplete-show-suggestions');\n\n                // Prevent the close timer, or we will open, then close the suggestions.\n                inputElement.focus();\n\n                // Handle ajax population of suggestions.\n                if (!inputElement.val() && options.ajax) {\n                    require([options.ajax], function(ajaxHandler) {\n                        pendingPromise.resolve(updateAjax(e, options, state, originalSelect, ajaxHandler));\n                    });\n                } else {\n                    // Else - open the suggestions list.\n                    pendingPromise.resolve(updateSuggestions(options, state, inputElement.val(), originalSelect));\n                }\n            });\n        }\n\n        var suggestionsElement = $(document.getElementById(state.suggestionsId));\n        // Remove any click handler first.\n        suggestionsElement.parent().prop(\"onclick\", null).off(\"click\");\n        suggestionsElement.parent().on('click', `#${state.suggestionsId} [role=option]`, function(e) {\n            var pendingPromise = addPendingJSPromise('form-autocomplete-parent');\n            // Handle clicks on suggestions.\n            var element = $(e.currentTarget).closest('[role=option]');\n            var suggestionsElement = $(document.getElementById(state.suggestionsId));\n            // Find the index of the clicked on suggestion.\n            var current = suggestionsElement.children(':not([aria-hidden])').index(element);\n\n            // Activate it.\n            activateItem(current, state)\n            .then(function() {\n                // And select it.\n                return selectCurrentItem(options, state, originalSelect);\n            })\n            .then(function() {\n                return pendingPromise.resolve();\n            })\n            .catch();\n        });\n        var selectionElement = $(document.getElementById(state.selectionId));\n\n        // Handle clicks on the selected items (will unselect an item).\n        selectionElement.on('click', '[role=option]', function(e) {\n            var pendingPromise = addPendingJSPromise('form-autocomplete-clicks');\n\n            // Remove it from the selection.\n            pendingPromise.resolve(deselectItem(options, state, $(e.currentTarget), originalSelect));\n        });\n\n        // When listbox is focused, focus on the first option if there is no focused option.\n        selectionElement.on('focus', function() {\n            updateActiveSelectionFromState(state);\n        });\n\n        // Keyboard navigation for the selection list.\n        selectionElement.on('keydown', function(e) {\n            var pendingPromise = addPendingJSPromise('form-autocomplete-keydown-' + e.keyCode);\n            switch (e.keyCode) {\n                case KEYS.RIGHT:\n                case KEYS.DOWN:\n                    // We handled this event, so prevent it.\n                    e.preventDefault();\n\n                    // Choose the next selection item.\n                    pendingPromise.resolve(activateNextSelection(state));\n                    return;\n                case KEYS.LEFT:\n                case KEYS.UP:\n                    // We handled this event, so prevent it.\n                    e.preventDefault();\n\n                    // Choose the previous selection item.\n                    pendingPromise.resolve(activatePreviousSelection(state));\n                    return;\n                case KEYS.SPACE:\n                case KEYS.ENTER:\n                    // Get the item that is currently selected.\n                    var selectedItem = $(document.getElementById(state.selectionId)).children('[data-active-selection]');\n                    if (selectedItem) {\n                        e.preventDefault();\n\n                        // Unselect this item.\n                        pendingPromise.resolve(deselectItem(options, state, selectedItem, originalSelect));\n                    }\n                    return;\n            }\n\n            // Not handled. Resolve the promise.\n            pendingPromise.resolve();\n        });\n        // Whenever the input field changes, update the suggestion list.\n        if (options.showSuggestions) {\n            // Store the value of the field as its last value, when the field gains focus.\n            inputElement.on('focus', function(e) {\n                var query = $(e.currentTarget).val();\n                $(e.currentTarget).data('last-value', query);\n            });\n\n            // If this field uses ajax, set it up.\n            if (options.ajax) {\n                require([options.ajax], function(ajaxHandler) {\n                    // Creating throttled handlers free of race conditions, and accurate.\n                    // This code keeps track of a throttleTimeout, which is periodically polled.\n                    // Once the throttled function is executed, the fact that it is running is noted.\n                    // If a subsequent request comes in whilst it is running, this request is re-applied.\n                    var throttleTimeout = null;\n                    var inProgress = false;\n                    var pendingKey = 'autocomplete-throttledhandler';\n                    var handler = function(e) {\n                        // Empty the current timeout.\n                        throttleTimeout = null;\n\n                        // Mark this request as in-progress.\n                        inProgress = true;\n\n                        // Process the request.\n                        updateAjax(e, options, state, originalSelect, ajaxHandler)\n                        .then(function() {\n                            // Check if the throttleTimeout is still empty.\n                            // There's a potential condition whereby the JS request takes long enough to complete that\n                            // another task has been queued.\n                            // In this case another task will be kicked off and we must wait for that before marking htis as\n                            // complete.\n                            if (null === throttleTimeout) {\n                                // Mark this task as complete.\n                                M.util.js_complete(pendingKey);\n                            }\n                            inProgress = false;\n\n                            return arguments[0];\n                        })\n                        .catch(notification.exception);\n                    };\n\n                    // For input events, we do not want to trigger many, many updates.\n                    var throttledHandler = function(e) {\n                        window.clearTimeout(throttleTimeout);\n                        if (inProgress) {\n                            // A request is currently ongoing.\n                            // Delay this request another 100ms.\n                            throttleTimeout = window.setTimeout(throttledHandler.bind(this, e), 100);\n                            return;\n                        }\n\n                        if (throttleTimeout === null) {\n                            // There is currently no existing timeout handler, and it has not been recently cleared, so\n                            // this is the start of a throttling check.\n                            M.util.js_pending(pendingKey);\n                        }\n\n                        // There is currently no existing timeout handler, and it has not been recently cleared, so this\n                        // is the start of a throttling check.\n                        // Queue a call to the handler.\n                        throttleTimeout = window.setTimeout(handler.bind(this, e), 300);\n                    };\n\n                    // Trigger an ajax update after the text field value changes.\n                    inputElement.on('input', function(e) {\n                        var query = $(e.currentTarget).val();\n                        var last = $(e.currentTarget).data('last-value');\n                        // IE11 fires many more input events than required - even when the value has not changed.\n                        if (last !== query) {\n                            throttledHandler(e);\n                        }\n                        $(e.currentTarget).data('last-value', query);\n                    });\n                });\n            } else {\n                inputElement.on('input', function(e) {\n                    var query = $(e.currentTarget).val();\n                    var last = $(e.currentTarget).data('last-value');\n                    // IE11 fires many more input events than required - even when the value has not changed.\n                    // We need to only do this for real value changed events or the suggestions will be\n                    // unclickable on IE11 (because they will be rebuilt before the click event fires).\n                    // Note - because of this we cannot close the list when the query is empty or it will break\n                    // on IE11.\n                    if (last !== query) {\n                        updateSuggestions(options, state, query, originalSelect);\n                    }\n                    $(e.currentTarget).data('last-value', query);\n                });\n            }\n        }\n    };\n\n    /**\n     * Create and return an unresolved Promise for some pending JS.\n     *\n     * @param   {String} key The unique identifier for this promise\n     * @return  {Promise}\n     */\n    var addPendingJSPromise = function(key) {\n            var pendingKey = 'form-autocomplete:' + key;\n\n            M.util.js_pending(pendingKey);\n\n            var pendingPromise = $.Deferred();\n\n            pendingPromise\n            .then(function() {\n                M.util.js_complete(pendingKey);\n\n                return arguments[0];\n            })\n            .catch(notification.exception);\n\n            return pendingPromise;\n    };\n\n    return {\n        // Public variables and functions.\n        /**\n         * Turn a boring select box into an auto-complete beast.\n         *\n         * @method enhance\n         * @param {string} selector The selector that identifies the select box.\n         * @param {boolean} tags Whether to allow support for tags (can define new entries).\n         * @param {string} ajax Name of an AMD module to handle ajax requests. If specified, the AMD\n         *                      module must expose 2 functions \"transport\" and \"processResults\".\n         *                      These are modeled on Select2 see: https://select2.github.io/options.html#ajax\n         * @param {String} placeholder - The text to display before a selection is made.\n         * @param {Boolean} caseSensitive - If search has to be made case sensitive.\n         * @param {Boolean} showSuggestions - If suggestions should be shown\n         * @param {String} noSelectionString - Text to display when there is no selection\n         * @param {Boolean} closeSuggestionsOnSelect - Whether to close the suggestions immediately after making a selection.\n         * @param {Object} templateOverrides A set of templates to use instead of the standard templates\n         * @return {Promise}\n         */\n        enhance: function(selector, tags, ajax, placeholder, caseSensitive, showSuggestions, noSelectionString,\n                          closeSuggestionsOnSelect, templateOverrides) {\n            // Set some default values.\n            var options = {\n                selector: selector,\n                tags: false,\n                ajax: false,\n                placeholder: placeholder,\n                caseSensitive: false,\n                showSuggestions: true,\n                noSelectionString: noSelectionString,\n                templates: $.extend({\n                        input: 'core/form_autocomplete_input',\n                        items: 'core/form_autocomplete_selection_items',\n                        layout: 'core/form_autocomplete_layout',\n                        selection: 'core/form_autocomplete_selection',\n                        suggestions: 'core/form_autocomplete_suggestions',\n                    }, templateOverrides),\n            };\n            var pendingKey = 'autocomplete-setup-' + selector;\n            M.util.js_pending(pendingKey);\n            if (typeof tags !== \"undefined\") {\n                options.tags = tags;\n            }\n            if (typeof ajax !== \"undefined\") {\n                options.ajax = ajax;\n            }\n            if (typeof caseSensitive !== \"undefined\") {\n                options.caseSensitive = caseSensitive;\n            }\n            if (typeof showSuggestions !== \"undefined\") {\n                options.showSuggestions = showSuggestions;\n            }\n            if (typeof noSelectionString === \"undefined\") {\n                str.get_string('noselection', 'form').done(function(result) {\n                    options.noSelectionString = result;\n                }).fail(notification.exception);\n            }\n\n            // Look for the select element.\n            var originalSelect = $(selector);\n            if (!originalSelect) {\n                log.debug('Selector not found: ' + selector);\n                M.util.js_complete(pendingKey);\n                return false;\n            }\n\n            // Ensure we enhance the element only once.\n            if (originalSelect.data('enhanced') === 'enhanced') {\n                M.util.js_complete(pendingKey);\n                return false;\n            }\n            originalSelect.data('enhanced', 'enhanced');\n\n            // Hide the original select.\n            Aria.hide(originalSelect.get());\n            originalSelect.css('visibility', 'hidden');\n\n            // Find or generate some ids.\n            var state = {\n                selectId: originalSelect.attr('id'),\n                inputId: 'form_autocomplete_input-' + uniqueId,\n                suggestionsId: 'form_autocomplete_suggestions-' + uniqueId,\n                selectionId: 'form_autocomplete_selection-' + uniqueId,\n                downArrowId: 'form_autocomplete_downarrow-' + uniqueId,\n                items: [],\n            };\n\n            // Increment the unique counter so we don't get duplicates ever.\n            uniqueId++;\n\n            options.multiple = originalSelect.attr('multiple');\n            if (!options.multiple) {\n                // If this is a single select then there is no way to de-select the current value -\n                // unless we add a bogus blank option to be selected when nothing else is.\n                // This matches similar code in updateAjax above.\n                originalSelect.prepend('<option>');\n            }\n\n            if (typeof closeSuggestionsOnSelect !== \"undefined\") {\n                options.closeSuggestionsOnSelect = closeSuggestionsOnSelect;\n            } else {\n                // If not specified, this will close suggestions by default for single-select elements only.\n                options.closeSuggestionsOnSelect = !options.multiple;\n            }\n\n            var originalLabel = $('[for=' + state.selectId + ']');\n            // Create the new markup and insert it after the select.\n            var suggestions = [];\n            originalSelect.children('option').each(function(index, option) {\n                suggestions[index] = {label: option.innerHTML, value: $(option).attr('value')};\n            });\n\n            // Render all the parts of our UI.\n            var context = $.extend({}, options, state);\n            context.options = suggestions;\n            context.items = [];\n\n            // Collect rendered inline JS to be executed once the HTML is shown.\n            var collectedjs = '';\n\n            var renderLayout = templates.render(options.templates.layout, {})\n            .then(function(html) {\n                return $(html);\n            });\n\n            var renderInput = templates.render(options.templates.input, context).then(function(html, js) {\n                collectedjs += js;\n                return $(html);\n            });\n\n            var renderDatalist = templates.render(options.templates.suggestions, context).then(function(html, js) {\n                collectedjs += js;\n                return $(html);\n            });\n\n            var renderSelection = templates.render(options.templates.selection, context).then(function(html, js) {\n                collectedjs += js;\n                return $(html);\n            });\n\n            return $.when(renderLayout, renderInput, renderDatalist, renderSelection)\n            .then(function(layout, input, suggestions, selection) {\n                originalSelect.hide();\n                var container = originalSelect.parent();\n\n                // Ensure that the data-fieldtype is set for behat.\n                input.find('input').attr('data-fieldtype', 'autocomplete');\n\n                container.append(layout);\n                container.find('[data-region=\"form_autocomplete-input\"]').replaceWith(input);\n                container.find('[data-region=\"form_autocomplete-suggestions\"]').replaceWith(suggestions);\n                container.find('[data-region=\"form_autocomplete-selection\"]').replaceWith(selection);\n\n                templates.runTemplateJS(collectedjs);\n\n                // Update the form label to point to the text input.\n                originalLabel.attr('for', state.inputId);\n                // Add the event handlers.\n                addNavigation(options, state, originalSelect);\n\n                var suggestionsElement = $(document.getElementById(state.suggestionsId));\n                // Hide the suggestions by default.\n                suggestionsElement.hide();\n                Aria.hide(suggestionsElement.get());\n\n                return;\n            })\n            .then(function() {\n                // Show the current values in the selection list.\n                return updateSelectionList(options, state, originalSelect);\n            })\n            .then(function() {\n                return M.util.js_complete(pendingKey);\n            })\n            .catch(function(error) {\n                M.util.js_complete(pendingKey);\n                notification.exception(error);\n            });\n        }\n    };\n});\n"],"file":"form-autocomplete.min.js"}