/* you will need these imports in your ts, and the jquery-ui css in your scss to use these functions import * as $ from 'jquery'; import 'jquery-ui'; import * as popper from 'popper.js'; import * as bootstrap from 'bootstrap'; */ declare let $: any; export function getAutocompleteDefaultConfig() { return { minLength: 2, delay: 300, delimiter: ', ', }; } export function singleAutocomplete(selector, parentSelector, url, config) { if (config === undefined) { config = getAutocompleteDefaultConfig(); } else { config = Object.assign(getAutocompleteDefaultConfig(), config); } /** * @param selector: id of input * @param parentSelector: id of dom element that ul will be added to * @param url: api that returns a list of strings, which will be the list of suggested values in the typeahead * @param config * minLength: length of characters before typeahead suggestions pop up. jquery-ui default is 0 * delay: how long this function shoul wait before showing typeahead. jquery-ui default is 300 */ $(function () { $(selector).autocomplete({ appendTo: parentSelector, source: function (request, response) { let searchParams = { term: request.term, }, additionalParameters = {}, queryParams; if (config.getAdditionalParameters) { additionalParameters = config.getAdditionalParameters(); } queryParams = { ...searchParams, ...additionalParameters }; $.getJSON(url, $.param(queryParams, true), response); }, minLength: config.minLength, delay: config.delay, select: function (event, ui) { if (config.onSelectCallback) { return config.onSelectCallback(event, ui); } }, }); }); } export function multiAutocomplete(selector, parentSelector, url, config: any) { if (config === undefined) { config = getAutocompleteDefaultConfig(); } else { config = Object.assign(getAutocompleteDefaultConfig(), config); } /** * @param selector: id of input * @param parentSelector: id of dom element that ul will be added to * @param url: api that returns a list of strings, which will be the list of suggested values in the typeahead. Can filter out PreviouslySelected. * @param config * minLength: length of characters before typeahead suggestions pop up. jquery-ui default is 0 * delay: how long this function shoul wait before showing typeahead. jquery-ui default is 300 * delimiter: the string that separates each value. note that THERE IS A SPACE!! * functions: getAdditionalParameters, onSelectCallback */ $(function () { function split(val) { const separator = new RegExp(config.delimiter); return val.split(separator); } function extractLast(term) { return split(term).pop(); } $(selector) // don't navigate away from the field on tab when selecting an item .on('keydown', function (event) { if ( event.keyCode === $.ui.keyCode.TAB && $(this).autocomplete('instance').menu.active ) { event.preventDefault(); } }) .autocomplete({ //methods are called in order of 1.search 2.source 3.focus 4.select appendTo: parentSelector, source: function (request, response) { const split_terms = split(request.term), terms_length = split_terms.length, previouslySelected = split_terms.slice(0, terms_length - 1); let searchParams = { term: extractLast(request.term), previouslySelected: previouslySelected.map(function (item) { return encodeURIComponent(item); }), }, additionalParameters = {}, queryParams; if (config.getAdditionalParameters) { additionalParameters = config.getAdditionalParameters(); } queryParams = { ...searchParams, ...additionalParameters }; $.getJSON(url, $.param(queryParams, true), response); }, search: function () { // custom minLength const term = extractLast(this.value); if (term.length < config.minLength) { return false; } }, focus: function () { // prevent value inserted on focus return false; }, select: function (event, ui) { const terms = split(this.value); // remove the current input terms.pop(); // add the selected item terms.push(ui.item.value); // add placeholder to get the comma-and-space at the end terms.push(''); this.value = terms.join(config.delimiter); if (config.onSelectCallback) { config.onSelectCallback(event, ui); } return false; }, delay: config.delay, }); }); } export function multiTextAreaAutocomplete( selector, parentSelector, url, config: any ) { if (config === undefined) { config = getAutocompleteDefaultConfig(); } else { config = Object.assign(getAutocompleteDefaultConfig(), config); } /** * @param selector: id of input * @param parentSelector: id of dom element that ul will be added to * @param url: api that returns a list of strings, which will be the list of suggested values in the typeahead. Can filter out PreviouslySelected. * @param config * minLength: length of characters before typeahead suggestions pop up. jquery-ui default is 0 * delay: how long this function shoul wait before showing typeahead. jquery-ui default is 300 * delimiter: the string that separates each value. note that THERE IS A SPACE!! * functions: getAdditionalParameters, onSelectCallback */ $(function () { function split(val) { const separator = new RegExp(config.delimiter); return val.split(separator); } function extractLast(term) { return split(term).pop(); } $(selector) // don't navigate away from the field on tab when selecting an item .on('keydown', function (event) { if ( event.keyCode === $.ui.keyCode.TAB && $(this).autocomplete('instance').menu.active ) { event.preventDefault(); } }) .autocomplete({ //methods are called in order of 1.search 2.source 3.focus 4.select appendTo: parentSelector, source: function (request, response) { const split_terms = split(request.term), terms_length = split_terms.length, previouslySelected = split_terms.slice(0, terms_length - 1); let searchParams = { term: extractLast(request.term), previouslySelected: previouslySelected.map(function (item) { return encodeURIComponent(item); }), }, additionalParameters = {}, queryParams; if (config.getAdditionalParameters) { additionalParameters = config.getAdditionalParameters(); } queryParams = { ...searchParams, ...additionalParameters }; $.getJSON(url, $.param(queryParams, true), response); }, search: function () { // custom minLength const term = extractLast(this.value); if (term.length < config.minLength) { return false; } }, focus: function () { // prevent value inserted on focus return false; }, select: function (event, ui) { const terms = split(this.value); // remove the current input terms.pop(); // add the selected item terms.push(ui.item.value); // add placeholder to get the comma-and-space at the end terms.push(''); $(this).html(terms.join(config.delimiter)); this.value = terms.join(config.delimiter); //to change displayed content of text area, still need to use .value if (config.onSelectCallback) { config.onSelectCallback(); } return false; }, delay: config.delay, }); }); }