Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #6586 from C-Lodder/js-libraries

Update jQuery autocomplete to 1.2.18
  • Loading branch information...
commit a83e8b6a9055658e047d083089a6fd3314e36998 2 parents 9468cdf + dfd05cb
@wilsonge wilsonge authored
View
1,936 media/jui/js/jquery.autocomplete.js
@@ -1,966 +1,982 @@
/**
- * Ajax Autocomplete for jQuery, version 1.2.14
- * (c) 2014 Tomas Kirda
- *
- * Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
- * For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
- */
+* Ajax Autocomplete for jQuery, version 1.2.18
+* (c) 2015 Tomas Kirda
+*
+* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
+* For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
+*/
-/*jslint browser: true, white: true, plusplus: true */
-/*global define, window, document, jQuery, exports */
+/*jslint browser: true, white: true, plusplus: true, vars: true */
+/*global define, window, document, jQuery, exports, require */
// Expose plugin as an AMD module if AMD loader is present:
(function (factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['jquery'], factory);
- } else if (typeof exports === 'object' && typeof require === 'function') {
- // Browserify
- factory(require('jquery'));
- } else {
- // Browser globals
- factory(jQuery);
- }
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object' && typeof require === 'function') {
+ // Browserify
+ factory(require('jquery'));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
}(function ($) {
- 'use strict';
-
- var
- utils = (function () {
- return {
- escapeRegExChars: function (value) {
- return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
- },
- createNode: function (containerClass) {
- var div = document.createElement('div');
- div.className = containerClass;
- div.style.position = 'absolute';
- div.style.display = 'none';
- return div;
- }
- };
- }()),
-
- keys = {
- ESC: 27,
- TAB: 9,
- RETURN: 13,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40
- };
-
- function Autocomplete(el, options) {
- var noop = function () { },
- that = this,
- defaults = {
- ajaxSettings: {},
- autoSelectFirst: false,
- appendTo: document.body,
- serviceUrl: null,
- lookup: null,
- onSelect: null,
- width: 'auto',
- minChars: 1,
- maxHeight: 300,
- deferRequestBy: 0,
- params: {},
- formatResult: Autocomplete.formatResult,
- delimiter: null,
- zIndex: 9999,
- type: 'GET',
- noCache: false,
- onSearchStart: noop,
- onSearchComplete: noop,
- onSearchError: noop,
- containerClass: 'autocomplete-suggestions',
- tabDisabled: false,
- dataType: 'text',
- currentRequest: null,
- triggerSelectOnValidInput: true,
- preventBadQueries: true,
- lookupFilter: function (suggestion, originalQuery, queryLowerCase) {
- return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1;
- },
- paramName: 'query',
- transformResult: function (response) {
- return typeof response === 'string' ? $.parseJSON(response) : response;
- },
- showNoSuggestionNotice: false,
- noSuggestionNotice: 'No results',
- orientation: 'bottom',
- forceFixPosition: false
- };
-
- // Shared variables:
- that.element = el;
- that.el = $(el);
- that.suggestions = [];
- that.badQueries = [];
- that.selectedIndex = -1;
- that.currentValue = that.element.value;
- that.intervalId = 0;
- that.cachedResponse = {};
- that.onChangeInterval = null;
- that.onChange = null;
- that.isLocal = false;
- that.suggestionsContainer = null;
- that.noSuggestionsContainer = null;
- that.options = $.extend({}, defaults, options);
- that.classes = {
- selected: 'autocomplete-selected',
- suggestion: 'autocomplete-suggestion'
- };
- that.hint = null;
- that.hintValue = '';
- that.selection = null;
-
- // Initialize and set options:
- that.initialize();
- that.setOptions(options);
- }
-
- Autocomplete.utils = utils;
-
- $.Autocomplete = Autocomplete;
-
- Autocomplete.formatResult = function (suggestion, currentValue) {
- var pattern = '(' + utils.escapeRegExChars(currentValue) + ')';
-
- return suggestion.value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
- };
-
- Autocomplete.prototype = {
-
- killerFn: null,
-
- initialize: function () {
- var that = this,
- suggestionSelector = '.' + that.classes.suggestion,
- selected = that.classes.selected,
- options = that.options,
- container;
-
- // Remove autocomplete attribute to prevent native suggestions:
- that.element.setAttribute('autocomplete', 'off');
-
- that.killerFn = function (e) {
- if ($(e.target).closest('.' + that.options.containerClass).length === 0) {
- that.killSuggestions();
- that.disableKillerFn();
- }
- };
-
- // html() deals with many types: htmlString or Element or Array or jQuery
- that.noSuggestionsContainer = $('<div class="autocomplete-no-suggestion"></div>')
- .html(this.options.noSuggestionNotice).get(0);
-
- that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass);
-
- container = $(that.suggestionsContainer);
-
- container.appendTo(options.appendTo);
-
- // Only set width if it was provided:
- if (options.width !== 'auto') {
- container.width(options.width);
- }
-
- // Listen for mouse over event on suggestions list:
- container.on('mouseover.autocomplete', suggestionSelector, function () {
- that.activate($(this).data('index'));
- });
-
- // Deselect active element when mouse leaves suggestions container:
- container.on('mouseout.autocomplete', function () {
- that.selectedIndex = -1;
- container.children('.' + selected).removeClass(selected);
- });
-
- // Listen for click event on suggestions list:
- container.on('click.autocomplete', suggestionSelector, function () {
- that.select($(this).data('index'));
- });
-
- that.fixPositionCapture = function () {
- if (that.visible) {
- that.fixPosition();
- }
- };
-
- $(window).on('resize.autocomplete', that.fixPositionCapture);
-
- that.el.on('keydown.autocomplete', function (e) { that.onKeyPress(e); });
- that.el.on('keyup.autocomplete', function (e) { that.onKeyUp(e); });
- that.el.on('blur.autocomplete', function () { that.onBlur(); });
- that.el.on('focus.autocomplete', function () { that.onFocus(); });
- that.el.on('change.autocomplete', function (e) { that.onKeyUp(e); });
- },
-
- onFocus: function () {
- var that = this;
- that.fixPosition();
- if (that.options.minChars <= that.el.val().length) {
- that.onValueChange();
- }
- },
-
- onBlur: function () {
- this.enableKillerFn();
- },
-
- setOptions: function (suppliedOptions) {
- var that = this,
- options = that.options;
-
- $.extend(options, suppliedOptions);
-
- that.isLocal = $.isArray(options.lookup);
-
- if (that.isLocal) {
- options.lookup = that.verifySuggestionsFormat(options.lookup);
- }
-
- options.orientation = that.validateOrientation(options.orientation, 'bottom');
-
- // Adjust height, width and z-index:
- $(that.suggestionsContainer).css({
- 'max-height': options.maxHeight + 'px',
- 'width': options.width + 'px',
- 'z-index': options.zIndex
- });
- },
-
-
- clearCache: function () {
- this.cachedResponse = {};
- this.badQueries = [];
- },
-
- clear: function () {
- this.clearCache();
- this.currentValue = '';
- this.suggestions = [];
- },
-
- disable: function () {
- var that = this;
- that.disabled = true;
- clearInterval(that.onChangeInterval);
- if (that.currentRequest) {
- that.currentRequest.abort();
- }
- },
-
- enable: function () {
- this.disabled = false;
- },
-
- fixPosition: function () {
- // Use only when container has already its content
-
- var that = this,
- $container = $(that.suggestionsContainer),
- containerParent = $container.parent().get(0);
- // Fix position automatically when appended to body.
- // In other cases force parameter must be given.
- if (containerParent !== document.body && !that.options.forceFixPosition)
- return;
-
- // Choose orientation
- var orientation = that.options.orientation,
- containerHeight = $container.outerHeight(),
- height = that.el.outerHeight(),
- offset = that.el.offset(),
- styles = { 'top': offset.top, 'left': offset.left };
-
- if (orientation == 'auto') {
- var viewPortHeight = $(window).height(),
- scrollTop = $(window).scrollTop(),
- topOverflow = -scrollTop + offset.top - containerHeight,
- bottomOverflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight);
-
- orientation = (Math.max(topOverflow, bottomOverflow) === topOverflow) ? 'top' : 'bottom';
- }
-
- if (orientation === 'top') {
- styles.top += -containerHeight;
- } else {
- styles.top += height;
- }
-
- // If container is not positioned to body,
- // correct its position using offset parent offset
- if(containerParent !== document.body) {
- var opacity = $container.css('opacity'),
- parentOffsetDiff;
-
- if (!that.visible){
- $container.css('opacity', 0).show();
- }
-
- parentOffsetDiff = $container.offsetParent().offset();
- styles.top -= parentOffsetDiff.top;
- styles.left -= parentOffsetDiff.left;
-
- if (!that.visible){
- $container.css('opacity', opacity).hide();
- }
- }
-
- // -2px to account for suggestions border.
- if (that.options.width === 'auto') {
- styles.width = (that.el.outerWidth() - 2) + 'px';
- }
-
- $container.css(styles);
- },
-
- enableKillerFn: function () {
- var that = this;
- $(document).on('click.autocomplete', that.killerFn);
- },
-
- disableKillerFn: function () {
- var that = this;
- $(document).off('click.autocomplete', that.killerFn);
- },
-
- killSuggestions: function () {
- var that = this;
- that.stopKillSuggestions();
- that.intervalId = window.setInterval(function () {
- that.hide();
- that.stopKillSuggestions();
- }, 50);
- },
-
- stopKillSuggestions: function () {
- window.clearInterval(this.intervalId);
- },
-
- isCursorAtEnd: function () {
- var that = this,
- valLength = that.el.val().length,
- selectionStart = that.element.selectionStart,
- range;
-
- if (typeof selectionStart === 'number') {
- return selectionStart === valLength;
- }
- if (document.selection) {
- range = document.selection.createRange();
- range.moveStart('character', -valLength);
- return valLength === range.text.length;
- }
- return true;
- },
-
- onKeyPress: function (e) {
- var that = this;
-
- // If suggestions are hidden and user presses arrow down, display suggestions:
- if (!that.disabled && !that.visible && e.which === keys.DOWN && that.currentValue) {
- that.suggest();
- return;
- }
-
- if (that.disabled || !that.visible) {
- return;
- }
-
- switch (e.which) {
- case keys.ESC:
- that.el.val(that.currentValue);
- that.hide();
- break;
- case keys.RIGHT:
- if (that.hint && that.options.onHint && that.isCursorAtEnd()) {
- that.selectHint();
- break;
- }
- return;
- case keys.TAB:
- if (that.hint && that.options.onHint) {
- that.selectHint();
- return;
- }
- /* falls through */
- case keys.RETURN:
- if (that.selectedIndex === -1) {
- that.hide();
- return;
- }
- that.select(that.selectedIndex);
- if (e.which === keys.TAB && that.options.tabDisabled === false) {
- return;
- }
- break;
- case keys.UP:
- that.moveUp();
- break;
- case keys.DOWN:
- that.moveDown();
- break;
- default:
- return;
- }
-
- // Cancel event if function did not return:
- e.stopImmediatePropagation();
- e.preventDefault();
- },
-
- onKeyUp: function (e) {
- var that = this;
-
- if (that.disabled) {
- return;
- }
-
- switch (e.which) {
- case keys.UP:
- case keys.DOWN:
- return;
- }
-
- clearInterval(that.onChangeInterval);
-
- if (that.currentValue !== that.el.val()) {
- that.findBestHint();
- if (that.options.deferRequestBy > 0) {
- // Defer lookup in case when value changes very quickly:
- that.onChangeInterval = setInterval(function () {
- that.onValueChange();
- }, that.options.deferRequestBy);
- } else {
- that.onValueChange();
- }
- }
- },
-
- onValueChange: function () {
- var that = this,
- options = that.options,
- value = that.el.val(),
- query = that.getQuery(value),
- index;
-
- if (that.selection && that.currentValue !== query) {
- that.selection = null;
- (options.onInvalidateSelection || $.noop).call(that.element);
- }
-
- clearInterval(that.onChangeInterval);
- that.currentValue = value;
- that.selectedIndex = -1;
-
- // Check existing suggestion for the match before proceeding:
- if (options.triggerSelectOnValidInput) {
- index = that.findSuggestionIndex(query);
- if (index !== -1) {
- that.select(index);
- return;
- }
- }
-
- if (query.length < options.minChars) {
- that.hide();
- } else {
- that.getSuggestions(query);
- }
- },
-
- findSuggestionIndex: function (query) {
- var that = this,
- index = -1,
- queryLowerCase = query.toLowerCase();
-
- $.each(that.suggestions, function (i, suggestion) {
- if (suggestion.value.toLowerCase() === queryLowerCase) {
- index = i;
- return false;
- }
- });
-
- return index;
- },
-
- getQuery: function (value) {
- var delimiter = this.options.delimiter,
- parts;
-
- if (!delimiter) {
- return value;
- }
- parts = value.split(delimiter);
- return $.trim(parts[parts.length - 1]);
- },
-
- getSuggestionsLocal: function (query) {
- var that = this,
- options = that.options,
- queryLowerCase = query.toLowerCase(),
- filter = options.lookupFilter,
- limit = parseInt(options.lookupLimit, 10),
- data;
-
- data = {
- suggestions: $.grep(options.lookup, function (suggestion) {
- return filter(suggestion, query, queryLowerCase);
- })
- };
-
- if (limit && data.suggestions.length > limit) {
- data.suggestions = data.suggestions.slice(0, limit);
- }
-
- return data;
- },
-
- getSuggestions: function (q) {
- var response,
- that = this,
- options = that.options,
- serviceUrl = options.serviceUrl,
- params,
- cacheKey,
- ajaxSettings;
-
- options.params[options.paramName] = q;
- params = options.ignoreParams ? null : options.params;
-
- if (options.onSearchStart.call(that.element, options.params) === false) {
- return;
- }
-
- if ($.isFunction(that.lookup)){
- that.lookup(q, function (data) {
- that.suggestions = data.suggestions;
- that.suggest();
- options.onSearchComplete.call(that.element, q, data.suggestions);
- });
- return;
- }
-
- if (that.isLocal) {
- response = that.getSuggestionsLocal(q);
- } else {
- if ($.isFunction(serviceUrl)) {
- serviceUrl = serviceUrl.call(that.element, q);
- }
- cacheKey = serviceUrl + '?' + $.param(params || {});
- response = that.cachedResponse[cacheKey];
- }
-
- if (response && $.isArray(response.suggestions)) {
- that.suggestions = response.suggestions;
- that.suggest();
- options.onSearchComplete.call(that.element, q, response.suggestions);
- } else if (!that.isBadQuery(q)) {
- if (that.currentRequest) {
- that.currentRequest.abort();
- }
-
- ajaxSettings = {
- url: serviceUrl,
- data: params,
- type: options.type,
- dataType: options.dataType
- };
-
- $.extend(ajaxSettings, options.ajaxSettings);
-
- that.currentRequest = $.ajax(ajaxSettings).done(function (data) {
- var result;
- that.currentRequest = null;
- result = options.transformResult(data);
- that.processResponse(result, q, cacheKey);
- options.onSearchComplete.call(that.element, q, result.suggestions);
- }).fail(function (jqXHR, textStatus, errorThrown) {
- options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown);
- });
- } else {
- options.onSearchComplete.call(that.element, q, []);
- }
- },
-
- isBadQuery: function (q) {
- if (!this.options.preventBadQueries){
- return false;
- }
-
- var badQueries = this.badQueries,
- i = badQueries.length;
-
- while (i--) {
- if (q.indexOf(badQueries[i]) === 0) {
- return true;
- }
- }
-
- return false;
- },
-
- hide: function () {
- var that = this;
- that.visible = false;
- that.selectedIndex = -1;
- clearInterval(that.onChangeInterval);
- $(that.suggestionsContainer).hide();
- that.signalHint(null);
- },
-
- suggest: function () {
- if (this.suggestions.length === 0) {
- if (this.options.showNoSuggestionNotice) {
- this.noSuggestions();
- } else {
- this.hide();
- }
- return;
- }
-
- var that = this,
- options = that.options,
- groupBy = options.groupBy,
- formatResult = options.formatResult,
- value = that.getQuery(that.currentValue),
- className = that.classes.suggestion,
- classSelected = that.classes.selected,
- container = $(that.suggestionsContainer),
- noSuggestionsContainer = $(that.noSuggestionsContainer),
- beforeRender = options.beforeRender,
- html = '',
- category,
- formatGroup = function (suggestion, index) {
- var currentCategory = suggestion.data[groupBy];
-
- if (category === currentCategory){
- return '';
- }
-
- category = currentCategory;
-
- return '<div class="autocomplete-group"><strong>' + category + '</strong></div>';
- },
- index;
-
- if (options.triggerSelectOnValidInput) {
- index = that.findSuggestionIndex(value);
- if (index !== -1) {
- that.select(index);
- return;
- }
- }
-
- // Build suggestions inner HTML:
- $.each(that.suggestions, function (i, suggestion) {
- if (groupBy){
- html += formatGroup(suggestion, value, i);
- }
-
- html += '<div class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value) + '</div>';
- });
-
- this.adjustContainerWidth();
-
- noSuggestionsContainer.detach();
- container.html(html);
-
- if ($.isFunction(beforeRender)) {
- beforeRender.call(that.element, container);
- }
-
- that.fixPosition();
- container.show();
-
- // Select first value by default:
- if (options.autoSelectFirst) {
- that.selectedIndex = 0;
- container.scrollTop(0);
- container.children().first().addClass(classSelected);
- }
-
- that.visible = true;
- that.findBestHint();
- },
-
- noSuggestions: function() {
- var that = this,
- container = $(that.suggestionsContainer),
- noSuggestionsContainer = $(that.noSuggestionsContainer);
-
- this.adjustContainerWidth();
-
- // Some explicit steps. Be careful here as it easy to get
- // noSuggestionsContainer removed from DOM if not detached properly.
- noSuggestionsContainer.detach();
- container.empty(); // clean suggestions if any
- container.append(noSuggestionsContainer);
-
- that.fixPosition();
-
- container.show();
- that.visible = true;
- },
-
- adjustContainerWidth: function() {
- var that = this,
- options = that.options,
- width,
- container = $(that.suggestionsContainer);
-
- // If width is auto, adjust width before displaying suggestions,
- // because if instance was created before input had width, it will be zero.
- // Also it adjusts if input width has changed.
- // -2px to account for suggestions border.
- if (options.width === 'auto') {
- width = that.el.outerWidth() - 2;
- container.width(width > 0 ? width : 300);
- }
- },
-
- findBestHint: function () {
- var that = this,
- value = that.el.val().toLowerCase(),
- bestMatch = null;
-
- if (!value) {
- return;
- }
-
- $.each(that.suggestions, function (i, suggestion) {
- var foundMatch = suggestion.value.toLowerCase().indexOf(value) === 0;
- if (foundMatch) {
- bestMatch = suggestion;
- }
- return !foundMatch;
- });
-
- that.signalHint(bestMatch);
- },
-
- signalHint: function (suggestion) {
- var hintValue = '',
- that = this;
- if (suggestion) {
- hintValue = that.currentValue + suggestion.value.substr(that.currentValue.length);
- }
- if (that.hintValue !== hintValue) {
- that.hintValue = hintValue;
- that.hint = suggestion;
- (this.options.onHint || $.noop)(hintValue);
- }
- },
-
- verifySuggestionsFormat: function (suggestions) {
- // If suggestions is string array, convert them to supported format:
- if (suggestions.length && typeof suggestions[0] === 'string') {
- return $.map(suggestions, function (value) {
- return { value: value, data: null };
- });
- }
-
- return suggestions;
- },
-
- validateOrientation: function(orientation, fallback) {
- orientation = $.trim(orientation || '').toLowerCase();
-
- if($.inArray(orientation, ['auto', 'bottom', 'top']) === -1){
- orientation = fallback;
- }
-
- return orientation;
- },
-
- processResponse: function (result, originalQuery, cacheKey) {
- var that = this,
- options = that.options;
-
- result.suggestions = that.verifySuggestionsFormat(result.suggestions);
-
- // Cache results if cache is not disabled:
- if (!options.noCache) {
- that.cachedResponse[cacheKey] = result;
- if (options.preventBadQueries && result.suggestions.length === 0) {
- that.badQueries.push(originalQuery);
- }
- }
-
- // Return if originalQuery is not matching current query:
- if (originalQuery !== that.getQuery(that.currentValue)) {
- return;
- }
-
- that.suggestions = result.suggestions;
- that.suggest();
- },
-
- activate: function (index) {
- var that = this,
- activeItem,
- selected = that.classes.selected,
- container = $(that.suggestionsContainer),
- children = container.find('.' + that.classes.suggestion);
-
- container.find('.' + selected).removeClass(selected);
-
- that.selectedIndex = index;
-
- if (that.selectedIndex !== -1 && children.length > that.selectedIndex) {
- activeItem = children.get(that.selectedIndex);
- $(activeItem).addClass(selected);
- return activeItem;
- }
-
- return null;
- },
-
- selectHint: function () {
- var that = this,
- i = $.inArray(that.hint, that.suggestions);
-
- that.select(i);
- },
-
- select: function (i) {
- var that = this;
- that.hide();
- that.onSelect(i);
- },
-
- moveUp: function () {
- var that = this;
-
- if (that.selectedIndex === -1) {
- return;
- }
-
- if (that.selectedIndex === 0) {
- $(that.suggestionsContainer).children().first().removeClass(that.classes.selected);
- that.selectedIndex = -1;
- that.el.val(that.currentValue);
- that.findBestHint();
- return;
- }
-
- that.adjustScroll(that.selectedIndex - 1);
- },
-
- moveDown: function () {
- var that = this;
-
- if (that.selectedIndex === (that.suggestions.length - 1)) {
- return;
- }
-
- that.adjustScroll(that.selectedIndex + 1);
- },
-
- adjustScroll: function (index) {
- var that = this,
- activeItem = that.activate(index);
-
- if (!activeItem) {
- return;
- }
-
- var offsetTop,
- upperBound,
- lowerBound,
- heightDelta = $(activeItem).outerHeight();
-
- offsetTop = activeItem.offsetTop;
- upperBound = $(that.suggestionsContainer).scrollTop();
- lowerBound = upperBound + that.options.maxHeight - heightDelta;
-
- if (offsetTop < upperBound) {
- $(that.suggestionsContainer).scrollTop(offsetTop);
- } else if (offsetTop > lowerBound) {
- $(that.suggestionsContainer).scrollTop(offsetTop - that.options.maxHeight + heightDelta);
- }
-
- that.el.val(that.getValue(that.suggestions[index].value));
- that.signalHint(null);
- },
-
- onSelect: function (index) {
- var that = this,
- onSelectCallback = that.options.onSelect,
- suggestion = that.suggestions[index];
-
- that.currentValue = that.getValue(suggestion.value);
-
- if (that.currentValue !== that.el.val()) {
- that.el.val(that.currentValue);
- }
-
- that.signalHint(null);
- that.suggestions = [];
- that.selection = suggestion;
-
- if ($.isFunction(onSelectCallback)) {
- onSelectCallback.call(that.element, suggestion);
- }
- },
-
- getValue: function (value) {
- var that = this,
- delimiter = that.options.delimiter,
- currentValue,
- parts;
-
- if (!delimiter) {
- return value;
- }
-
- currentValue = that.currentValue;
- parts = currentValue.split(delimiter);
-
- if (parts.length === 1) {
- return value;
- }
-
- return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value;
- },
-
- dispose: function () {
- var that = this;
- that.el.off('.autocomplete').removeData('autocomplete');
- that.disableKillerFn();
- $(window).off('resize.autocomplete', that.fixPositionCapture);
- $(that.suggestionsContainer).remove();
- }
- };
-
- // Create chainable jQuery plugin:
- $.fn.autocomplete = $.fn.devbridgeAutocomplete = function (options, args) {
- var dataKey = 'autocomplete';
- // If function invoked without argument return
- // instance of the first matched element:
- if (arguments.length === 0) {
- return this.first().data(dataKey);
- }
-
- return this.each(function () {
- var inputElement = $(this),
- instance = inputElement.data(dataKey);
-
- if (typeof options === 'string') {
- if (instance && typeof instance[options] === 'function') {
- instance[options](args);
- }
- } else {
- // If instance already exists, destroy it:
- if (instance && instance.dispose) {
- instance.dispose();
- }
- instance = new Autocomplete(this, options);
- inputElement.data(dataKey, instance);
- }
- });
- };
-}));
+ 'use strict';
+
+ var
+ utils = (function () {
+ return {
+ escapeRegExChars: function (value) {
+ return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+ },
+ createNode: function (containerClass) {
+ var div = document.createElement('div');
+ div.className = containerClass;
+ div.style.position = 'absolute';
+ div.style.display = 'none';
+ return div;
+ }
+ };
+ }()),
+
+ keys = {
+ ESC: 27,
+ TAB: 9,
+ RETURN: 13,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40
+ };
+
+ function Autocomplete(el, options) {
+ var noop = function () { },
+ that = this,
+ defaults = {
+ ajaxSettings: {},
+ autoSelectFirst: false,
+ appendTo: document.body,
+ serviceUrl: null,
+ lookup: null,
+ onSelect: null,
+ width: 'auto',
+ minChars: 1,
+ maxHeight: 300,
+ deferRequestBy: 0,
+ params: {},
+ formatResult: Autocomplete.formatResult,
+ delimiter: null,
+ zIndex: 9999,
+ type: 'GET',
+ noCache: false,
+ onSearchStart: noop,
+ onSearchComplete: noop,
+ onSearchError: noop,
+ preserveInput: false,
+ containerClass: 'autocomplete-suggestions',
+ tabDisabled: false,
+ dataType: 'text',
+ currentRequest: null,
+ triggerSelectOnValidInput: true,
+ preventBadQueries: true,
+ lookupFilter: function (suggestion, originalQuery, queryLowerCase) {
+ return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1;
+ },
+ paramName: 'query',
+ transformResult: function (response) {
+ return typeof response === 'string' ? $.parseJSON(response) : response;
+ },
+ showNoSuggestionNotice: false,
+ noSuggestionNotice: 'No results',
+ orientation: 'bottom',
+ forceFixPosition: false
+ };
+
+ // Shared variables:
+ that.element = el;
+ that.el = $(el);
+ that.suggestions = [];
+ that.badQueries = [];
+ that.selectedIndex = -1;
+ that.currentValue = that.element.value;
+ that.intervalId = 0;
+ that.cachedResponse = {};
+ that.onChangeInterval = null;
+ that.onChange = null;
+ that.isLocal = false;
+ that.suggestionsContainer = null;
+ that.noSuggestionsContainer = null;
+ that.options = $.extend({}, defaults, options);
+ that.classes = {
+ selected: 'autocomplete-selected',
+ suggestion: 'autocomplete-suggestion'
+ };
+ that.hint = null;
+ that.hintValue = '';
+ that.selection = null;
+
+ // Initialize and set options:
+ that.initialize();
+ that.setOptions(options);
+ }
+
+ Autocomplete.utils = utils;
+
+ $.Autocomplete = Autocomplete;
+
+ Autocomplete.formatResult = function (suggestion, currentValue) {
+ var pattern = '(' + utils.escapeRegExChars(currentValue) + ')';
+
+ return suggestion.value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
+ };
+
+ Autocomplete.prototype = {
+
+ killerFn: null,
+
+ initialize: function () {
+ var that = this,
+ suggestionSelector = '.' + that.classes.suggestion,
+ selected = that.classes.selected,
+ options = that.options,
+ container;
+
+ // Remove autocomplete attribute to prevent native suggestions:
+ that.element.setAttribute('autocomplete', 'off');
+
+ that.killerFn = function (e) {
+ if ($(e.target).closest('.' + that.options.containerClass).length === 0) {
+ that.killSuggestions();
+ that.disableKillerFn();
+ }
+ };
+
+ // html() deals with many types: htmlString or Element or Array or jQuery
+ that.noSuggestionsContainer = $('<div class="autocomplete-no-suggestion"></div>')
+ .html(this.options.noSuggestionNotice).get(0);
+
+ that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass);
+
+ container = $(that.suggestionsContainer);
+
+ container.appendTo(options.appendTo);
+
+ // Only set width if it was provided:
+ if (options.width !== 'auto') {
+ container.width(options.width);
+ }
+
+ // Listen for mouse over event on suggestions list:
+ container.on('mouseover.autocomplete', suggestionSelector, function () {
+ that.activate($(this).data('index'));
+ });
+
+ // Deselect active element when mouse leaves suggestions container:
+ container.on('mouseout.autocomplete', function () {
+ that.selectedIndex = -1;
+ container.children('.' + selected).removeClass(selected);
+ });
+
+ // Listen for click event on suggestions list:
+ container.on('click.autocomplete', suggestionSelector, function () {
+ that.select($(this).data('index'));
+ });
+
+ that.fixPositionCapture = function () {
+ if (that.visible) {
+ that.fixPosition();
+ }
+ };
+
+ $(window).on('resize.autocomplete', that.fixPositionCapture);
+
+ that.el.on('keydown.autocomplete', function (e) { that.onKeyPress(e); });
+ that.el.on('keyup.autocomplete', function (e) { that.onKeyUp(e); });
+ that.el.on('blur.autocomplete', function () { that.onBlur(); });
+ that.el.on('focus.autocomplete', function () { that.onFocus(); });
+ that.el.on('change.autocomplete', function (e) { that.onKeyUp(e); });
+ that.el.on('input.autocomplete', function (e) { that.onKeyUp(e); });
+ },
+
+ onFocus: function () {
+ var that = this;
+ that.fixPosition();
+ if (that.options.minChars <= that.el.val().length) {
+ that.onValueChange();
+ }
+ },
+
+ onBlur: function () {
+ this.enableKillerFn();
+ },
+
+ setOptions: function (suppliedOptions) {
+ var that = this,
+ options = that.options;
+
+ $.extend(options, suppliedOptions);
+
+ that.isLocal = $.isArray(options.lookup);
+
+ if (that.isLocal) {
+ options.lookup = that.verifySuggestionsFormat(options.lookup);
+ }
+
+ options.orientation = that.validateOrientation(options.orientation, 'bottom');
+
+ // Adjust height, width and z-index:
+ $(that.suggestionsContainer).css({
+ 'max-height': options.maxHeight + 'px',
+ 'width': options.width + 'px',
+ 'z-index': options.zIndex
+ });
+ },
+
+
+ clearCache: function () {
+ this.cachedResponse = {};
+ this.badQueries = [];
+ },
+
+ clear: function () {
+ this.clearCache();
+ this.currentValue = '';
+ this.suggestions = [];
+ },
+
+ disable: function () {
+ var that = this;
+ that.disabled = true;
+ clearInterval(that.onChangeInterval);
+ if (that.currentRequest) {
+ that.currentRequest.abort();
+ }
+ },
+
+ enable: function () {
+ this.disabled = false;
+ },
+
+ fixPosition: function () {
+ // Use only when container has already its content
+
+ var that = this,
+ $container = $(that.suggestionsContainer),
+ containerParent = $container.parent().get(0);
+ // Fix position automatically when appended to body.
+ // In other cases force parameter must be given.
+ if (containerParent !== document.body && !that.options.forceFixPosition) {
+ return;
+ }
+
+ // Choose orientation
+ var orientation = that.options.orientation,
+ containerHeight = $container.outerHeight(),
+ height = that.el.outerHeight(),
+ offset = that.el.offset(),
+ styles = { 'top': offset.top, 'left': offset.left };
+
+ if (orientation === 'auto') {
+ var viewPortHeight = $(window).height(),
+ scrollTop = $(window).scrollTop(),
+ topOverflow = -scrollTop + offset.top - containerHeight,
+ bottomOverflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight);
+
+ orientation = (Math.max(topOverflow, bottomOverflow) === topOverflow) ? 'top' : 'bottom';
+ }
+
+ if (orientation === 'top') {
+ styles.top += -containerHeight;
+ } else {
+ styles.top += height;
+ }
+
+ // If container is not positioned to body,
+ // correct its position using offset parent offset
+ if(containerParent !== document.body) {
+ var opacity = $container.css('opacity'),
+ parentOffsetDiff;
+
+ if (!that.visible){
+ $container.css('opacity', 0).show();
+ }
+
+ parentOffsetDiff = $container.offsetParent().offset();
+ styles.top -= parentOffsetDiff.top;
+ styles.left -= parentOffsetDiff.left;
+
+ if (!that.visible){
+ $container.css('opacity', opacity).hide();
+ }
+ }
+
+ // -2px to account for suggestions border.
+ if (that.options.width === 'auto') {
+ styles.width = (that.el.outerWidth() - 2) + 'px';
+ }
+
+ $container.css(styles);
+ },
+
+ enableKillerFn: function () {
+ var that = this;
+ $(document).on('click.autocomplete', that.killerFn);
+ },
+
+ disableKillerFn: function () {
+ var that = this;
+ $(document).off('click.autocomplete', that.killerFn);
+ },
+
+ killSuggestions: function () {
+ var that = this;
+ that.stopKillSuggestions();
+ that.intervalId = window.setInterval(function () {
+ that.hide();
+ that.stopKillSuggestions();
+ }, 50);
+ },
+
+ stopKillSuggestions: function () {
+ window.clearInterval(this.intervalId);
+ },
+
+ isCursorAtEnd: function () {
+ var that = this,
+ valLength = that.el.val().length,
+ selectionStart = that.element.selectionStart,
+ range;
+
+ if (typeof selectionStart === 'number') {
+ return selectionStart === valLength;
+ }
+ if (document.selection) {
+ range = document.selection.createRange();
+ range.moveStart('character', -valLength);
+ return valLength === range.text.length;
+ }
+ return true;
+ },
+
+ onKeyPress: function (e) {
+ var that = this;
+
+ // If suggestions are hidden and user presses arrow down, display suggestions:
+ if (!that.disabled && !that.visible && e.which === keys.DOWN && that.currentValue) {
+ that.suggest();
+ return;
+ }
+
+ if (that.disabled || !that.visible) {
+ return;
+ }
+
+ switch (e.which) {
+ case keys.ESC:
+ that.el.val(that.currentValue);
+ that.hide();
+ break;
+ case keys.RIGHT:
+ if (that.hint && that.options.onHint && that.isCursorAtEnd()) {
+ that.selectHint();
+ break;
+ }
+ return;
+ case keys.TAB:
+ if (that.hint && that.options.onHint) {
+ that.selectHint();
+ return;
+ }
+ if (that.selectedIndex === -1) {
+ that.hide();
+ return;
+ }
+ that.select(that.selectedIndex);
+ if (that.options.tabDisabled === false) {
+ return;
+ }
+ break;
+ case keys.RETURN:
+ if (that.selectedIndex === -1) {
+ that.hide();
+ return;
+ }
+ that.select(that.selectedIndex);
+ break;
+ case keys.UP:
+ that.moveUp();
+ break;
+ case keys.DOWN:
+ that.moveDown();
+ break;
+ default:
+ return;
+ }
+
+ // Cancel event if function did not return:
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ },
+
+ onKeyUp: function (e) {
+ var that = this;
+
+ if (that.disabled) {
+ return;
+ }
+
+ switch (e.which) {
+ case keys.UP:
+ case keys.DOWN:
+ return;
+ }
+
+ clearInterval(that.onChangeInterval);
+
+ if (that.currentValue !== that.el.val()) {
+ that.findBestHint();
+ if (that.options.deferRequestBy > 0) {
+ // Defer lookup in case when value changes very quickly:
+ that.onChangeInterval = setInterval(function () {
+ that.onValueChange();
+ }, that.options.deferRequestBy);
+ } else {
+ that.onValueChange();
+ }
+ }
+ },
+
+ onValueChange: function () {
+ var that = this,
+ options = that.options,
+ value = that.el.val(),
+ query = that.getQuery(value),
+ index;
+
+ if (that.selection && that.currentValue !== query) {
+ that.selection = null;
+ (options.onInvalidateSelection || $.noop).call(that.element);
+ }
+
+ clearInterval(that.onChangeInterval);
+ that.currentValue = value;
+ that.selectedIndex = -1;
+
+ // Check existing suggestion for the match before proceeding:
+ if (options.triggerSelectOnValidInput) {
+ index = that.findSuggestionIndex(query);
+ if (index !== -1) {
+ that.select(index);
+ return;
+ }
+ }
+
+ if (query.length < options.minChars) {
+ that.hide();
+ } else {
+ that.getSuggestions(query);
+ }
+ },
+
+ findSuggestionIndex: function (query) {
+ var that = this,
+ index = -1,
+ queryLowerCase = query.toLowerCase();
+
+ $.each(that.suggestions, function (i, suggestion) {
+ if (suggestion.value.toLowerCase() === queryLowerCase) {
+ index = i;
+ return false;
+ }
+ });
+
+ return index;
+ },
+
+ getQuery: function (value) {
+ var delimiter = this.options.delimiter,
+ parts;
+
+ if (!delimiter) {
+ return value;
+ }
+ parts = value.split(delimiter);
+ return $.trim(parts[parts.length - 1]);
+ },
+
+ getSuggestionsLocal: function (query) {
+ var that = this,
+ options = that.options,
+ queryLowerCase = query.toLowerCase(),
+ filter = options.lookupFilter,
+ limit = parseInt(options.lookupLimit, 10),
+ data;
+
+ data = {
+ suggestions: $.grep(options.lookup, function (suggestion) {
+ return filter(suggestion, query, queryLowerCase);
+ })
+ };
+
+ if (limit && data.suggestions.length > limit) {
+ data.suggestions = data.suggestions.slice(0, limit);
+ }
+
+ return data;
+ },
+
+ getSuggestions: function (q) {
+ var response,
+ that = this,
+ options = that.options,
+ serviceUrl = options.serviceUrl,
+ params,
+ cacheKey,
+ ajaxSettings;
+
+ options.params[options.paramName] = q;
+ params = options.ignoreParams ? null : options.params;
+
+ if (options.onSearchStart.call(that.element, options.params) === false) {
+ return;
+ }
+
+ if ($.isFunction(options.lookup)){
+ options.lookup(q, function (data) {
+ that.suggestions = data.suggestions;
+ that.suggest();
+ options.onSearchComplete.call(that.element, q, data.suggestions);
+ });
+ return;
+ }
+
+ if (that.isLocal) {
+ response = that.getSuggestionsLocal(q);
+ } else {
+ if ($.isFunction(serviceUrl)) {
+ serviceUrl = serviceUrl.call(that.element, q);
+ }
+ cacheKey = serviceUrl + '?' + $.param(params || {});
+ response = that.cachedResponse[cacheKey];
+ }
+
+ if (response && $.isArray(response.suggestions)) {
+ that.suggestions = response.suggestions;
+ that.suggest();
+ options.onSearchComplete.call(that.element, q, response.suggestions);
+ } else if (!that.isBadQuery(q)) {
+ if (that.currentRequest) {
+ that.currentRequest.abort();
+ }
+
+ ajaxSettings = {
+ url: serviceUrl,
+ data: params,
+ type: options.type,
+ dataType: options.dataType
+ };
+
+ $.extend(ajaxSettings, options.ajaxSettings);
+
+ that.currentRequest = $.ajax(ajaxSettings).done(function (data) {
+ var result;
+ that.currentRequest = null;
+ result = options.transformResult(data);
+ that.processResponse(result, q, cacheKey);
+ options.onSearchComplete.call(that.element, q, result.suggestions);
+ }).fail(function (jqXHR, textStatus, errorThrown) {
+ options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown);
+ });
+ } else {
+ options.onSearchComplete.call(that.element, q, []);
+ }
+ },
+
+ isBadQuery: function (q) {
+ if (!this.options.preventBadQueries){
+ return false;
+ }
+
+ var badQueries = this.badQueries,
+ i = badQueries.length;
+
+ while (i--) {
+ if (q.indexOf(badQueries[i]) === 0) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ hide: function () {
+ var that = this,
+ container = $(that.suggestionsContainer);
+
+ if ($.isFunction(that.options.onHide) && that.visible) {
+ that.options.onHide.call(that.element, container);
+ }
+
+ that.visible = false;
+ that.selectedIndex = -1;
+ clearInterval(that.onChangeInterval);
+ $(that.suggestionsContainer).hide();
+ that.signalHint(null);
+ },
+
+ suggest: function () {
+ if (this.suggestions.length === 0) {
+ if (this.options.showNoSuggestionNotice) {
+ this.noSuggestions();
+ } else {
+ this.hide();
+ }
+ return;
+ }
+
+ var that = this,
+ options = that.options,
+ groupBy = options.groupBy,
+ formatResult = options.formatResult,
+ value = that.getQuery(that.currentValue),
+ className = that.classes.suggestion,
+ classSelected = that.classes.selected,
+ container = $(that.suggestionsContainer),
+ noSuggestionsContainer = $(that.noSuggestionsContainer),
+ beforeRender = options.beforeRender,
+ html = '',
+ category,
+ formatGroup = function (suggestion, index) {
+ var currentCategory = suggestion.data[groupBy];
+
+ if (category === currentCategory){
+ return '';
+ }
+
+ category = currentCategory;
+
+ return '<div class="autocomplete-group"><strong>' + category + '</strong></div>';
+ },
+ index;
+
+ if (options.triggerSelectOnValidInput) {
+ index = that.findSuggestionIndex(value);
+ if (index !== -1) {
+ that.select(index);
+ return;
+ }
+ }
+
+ // Build suggestions inner HTML:
+ $.each(that.suggestions, function (i, suggestion) {
+ if (groupBy){
+ html += formatGroup(suggestion, value, i);
+ }
+
+ html += '<div class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value) + '</div>';
+ });
+
+ this.adjustContainerWidth();
+
+ noSuggestionsContainer.detach();
+ container.html(html);
+
+ if ($.isFunction(beforeRender)) {
+ beforeRender.call(that.element, container);
+ }
+
+ that.fixPosition();
+ container.show();
+
+ // Select first value by default:
+ if (options.autoSelectFirst) {
+ that.selectedIndex = 0;
+ container.scrollTop(0);
+ container.children('.' + className).first().addClass(classSelected);
+ }
+
+ that.visible = true;
+ that.findBestHint();
+ },
+
+ noSuggestions: function() {
+ var that = this,
+ container = $(that.suggestionsContainer),
+ noSuggestionsContainer = $(that.noSuggestionsContainer);
+
+ this.adjustContainerWidth();
+
+ // Some explicit steps. Be careful here as it easy to get
+ // noSuggestionsContainer removed from DOM if not detached properly.
+ noSuggestionsContainer.detach();
+ container.empty(); // clean suggestions if any
+ container.append(noSuggestionsContainer);
+
+ that.fixPosition();
+
+ container.show();
+ that.visible = true;
+ },
+
+ adjustContainerWidth: function() {
+ var that = this,
+ options = that.options,
+ width,
+ container = $(that.suggestionsContainer);
+
+ // If width is auto, adjust width before displaying suggestions,
+ // because if instance was created before input had width, it will be zero.
+ // Also it adjusts if input width has changed.
+ // -2px to account for suggestions border.
+ if (options.width === 'auto') {
+ width = that.el.outerWidth() - 2;
+ container.width(width > 0 ? width : 300);
+ }
+ },
+
+ findBestHint: function () {
+ var that = this,
+ value = that.el.val().toLowerCase(),
+ bestMatch = null;
+
+ if (!value) {
+ return;
+ }
+
+ $.each(that.suggestions, function (i, suggestion) {
+ var foundMatch = suggestion.value.toLowerCase().indexOf(value) === 0;
+ if (foundMatch) {
+ bestMatch = suggestion;
+ }
+ return !foundMatch;
+ });
+
+ that.signalHint(bestMatch);
+ },
+
+ signalHint: function (suggestion) {
+ var hintValue = '',
+ that = this;
+ if (suggestion) {
+ hintValue = that.currentValue + suggestion.value.substr(that.currentValue.length);
+ }
+ if (that.hintValue !== hintValue) {
+ that.hintValue = hintValue;
+ that.hint = suggestion;
+ (this.options.onHint || $.noop)(hintValue);
+ }
+ },
+
+ verifySuggestionsFormat: function (suggestions) {
+ // If suggestions is string array, convert them to supported format:
+ if (suggestions.length && typeof suggestions[0] === 'string') {
+ return $.map(suggestions, function (value) {
+ return { value: value, data: null };
+ });
+ }
+
+ return suggestions;
+ },
+
+ validateOrientation: function(orientation, fallback) {
+ orientation = $.trim(orientation || '').toLowerCase();
+
+ if($.inArray(orientation, ['auto', 'bottom', 'top']) === -1){
+ orientation = fallback;
+ }
+
+ return orientation;
+ },
+
+ processResponse: function (result, originalQuery, cacheKey) {
+ var that = this,
+ options = that.options;
+
+ result.suggestions = that.verifySuggestionsFormat(result.suggestions);
+
+ // Cache results if cache is not disabled:
+ if (!options.noCache) {
+ that.cachedResponse[cacheKey] = result;
+ if (options.preventBadQueries && result.suggestions.length === 0) {
+ that.badQueries.push(originalQuery);
+ }
+ }
+
+ // Return if originalQuery is not matching current query:
+ if (originalQuery !== that.getQuery(that.currentValue)) {
+ return;
+ }
+
+ that.suggestions = result.suggestions;
+ that.suggest();
+ },
+
+ activate: function (index) {
+ var that = this,
+ activeItem,
+ selected = that.classes.selected,
+ container = $(that.suggestionsContainer),
+ children = container.find('.' + that.classes.suggestion);
+
+ container.find('.' + selected).removeClass(selected);
+
+ that.selectedIndex = index;
+
+ if (that.selectedIndex !== -1 && children.length > that.selectedIndex) {
+ activeItem = children.get(that.selectedIndex);
+ $(activeItem).addClass(selected);
+ return activeItem;
+ }
+
+ return null;
+ },
+
+ selectHint: function () {
+ var that = this,
+ i = $.inArray(that.hint, that.suggestions);
+
+ that.select(i);
+ },
+
+ select: function (i) {
+ var that = this;
+ that.hide();
+ that.onSelect(i);
+ },
+
+ moveUp: function () {
+ var that = this;
+
+ if (that.selectedIndex === -1) {
+ return;
+ }
+
+ if (that.selectedIndex === 0) {
+ $(that.suggestionsContainer).children().first().removeClass(that.classes.selected);
+ that.selectedIndex = -1;
+ that.el.val(that.currentValue);
+ that.findBestHint();
+ return;
+ }
+
+ that.adjustScroll(that.selectedIndex - 1);
+ },
+
+ moveDown: function () {
+ var that = this;
+
+ if (that.selectedIndex === (that.suggestions.length - 1)) {
+ return;
+ }
+
+ that.adjustScroll(that.selectedIndex + 1);
+ },
+
+ adjustScroll: function (index) {
+ var that = this,
+ activeItem = that.activate(index);
+
+ if (!activeItem) {
+ return;
+ }
+
+ var offsetTop,
+ upperBound,
+ lowerBound,
+ heightDelta = $(activeItem).outerHeight();
+
+ offsetTop = activeItem.offsetTop;
+ upperBound = $(that.suggestionsContainer).scrollTop();
+ lowerBound = upperBound + that.options.maxHeight - heightDelta;
+
+ if (offsetTop < upperBound) {
+ $(that.suggestionsContainer).scrollTop(offsetTop);
+ } else if (offsetTop > lowerBound) {
+ $(that.suggestionsContainer).scrollTop(offsetTop - that.options.maxHeight + heightDelta);
+ }
+
+ if (!that.options.preserveInput) {
+ that.el.val(that.getValue(that.suggestions[index].value));
+ }
+ that.signalHint(null);
+ },
+
+ onSelect: function (index) {
+ var that = this,
+ onSelectCallback = that.options.onSelect,
+ suggestion = that.suggestions[index];
+
+ that.currentValue = that.getValue(suggestion.value);
+
+ if (that.currentValue !== that.el.val() && !that.options.preserveInput) {
+ that.el.val(that.currentValue);
+ }
+
+ that.signalHint(null);
+ that.suggestions = [];
+ that.selection = suggestion;
+
+ if ($.isFunction(onSelectCallback)) {
+ onSelectCallback.call(that.element, suggestion);
+ }
+ },
+
+ getValue: function (value) {
+ var that = this,
+ delimiter = that.options.delimiter,
+ currentValue,
+ parts;
+
+ if (!delimiter) {
+ return value;
+ }
+
+ currentValue = that.currentValue;
+ parts = currentValue.split(delimiter);
+
+ if (parts.length === 1) {
+ return value;
+ }
+
+ return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value;
+ },
+
+ dispose: function () {
+ var that = this;
+ that.el.off('.autocomplete').removeData('autocomplete');
+ that.disableKillerFn();
+ $(window).off('resize.autocomplete', that.fixPositionCapture);
+ $(that.suggestionsContainer).remove();
+ }
+ };
+
+ // Create chainable jQuery plugin:
+ $.fn.autocomplete = $.fn.devbridgeAutocomplete = function (options, args) {
+ var dataKey = 'autocomplete';
+ // If function invoked without argument return
+ // instance of the first matched element:
+ if (arguments.length === 0) {
+ return this.first().data(dataKey);
+ }
+
+ return this.each(function () {
+ var inputElement = $(this),
+ instance = inputElement.data(dataKey);
+
+ if (typeof options === 'string') {
+ if (instance && typeof instance[options] === 'function') {
+ instance[options](args);
+ }
+ } else {
+ // If instance already exists, destroy it:
+ if (instance && instance.dispose) {
+ instance.dispose();
+ }
+ instance = new Autocomplete(this, options);
+ inputElement.data(dataKey, instance);
+ }
+ });
+ };
+}));
View
14 media/jui/js/jquery.autocomplete.min.js
@@ -1,8 +1,8 @@
/**
- * Ajax Autocomplete for jQuery, version 1.2.14
- * (c) 2014 Tomas Kirda
- *
- * Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
- * For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
- */
-!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports&&"function"==typeof require?require("jquery"):jQuery)}(function(a){"use strict";function b(c,d){var e=function(){},f=this,g={ajaxSettings:{},autoSelectFirst:!1,appendTo:document.body,serviceUrl:null,lookup:null,onSelect:null,width:"auto",minChars:1,maxHeight:300,deferRequestBy:0,params:{},formatResult:b.formatResult,delimiter:null,zIndex:9999,type:"GET",noCache:!1,onSearchStart:e,onSearchComplete:e,onSearchError:e,containerClass:"autocomplete-suggestions",tabDisabled:!1,dataType:"text",currentRequest:null,triggerSelectOnValidInput:!0,preventBadQueries:!0,lookupFilter:function(a,b,c){return-1!==a.value.toLowerCase().indexOf(c)},paramName:"query",transformResult:function(b){return"string"==typeof b?a.parseJSON(b):b},showNoSuggestionNotice:!1,noSuggestionNotice:"No results",orientation:"bottom",forceFixPosition:!1};f.element=c,f.el=a(c),f.suggestions=[],f.badQueries=[],f.selectedIndex=-1,f.currentValue=f.element.value,f.intervalId=0,f.cachedResponse={},f.onChangeInterval=null,f.onChange=null,f.isLocal=!1,f.suggestionsContainer=null,f.noSuggestionsContainer=null,f.options=a.extend({},g,d),f.classes={selected:"autocomplete-selected",suggestion:"autocomplete-suggestion"},f.hint=null,f.hintValue="",f.selection=null,f.initialize(),f.setOptions(d)}var c=function(){return{escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},createNode:function(a){var b=document.createElement("div");return b.className=a,b.style.position="absolute",b.style.display="none",b}}}(),d={ESC:27,TAB:9,RETURN:13,LEFT:37,UP:38,RIGHT:39,DOWN:40};b.utils=c,a.Autocomplete=b,b.formatResult=function(a,b){var d="("+c.escapeRegExChars(b)+")";return a.value.replace(new RegExp(d,"gi"),"<strong>$1</strong>")},b.prototype={killerFn:null,initialize:function(){var c,d=this,e="."+d.classes.suggestion,f=d.classes.selected,g=d.options;d.element.setAttribute("autocomplete","off"),d.killerFn=function(b){0===a(b.target).closest("."+d.options.containerClass).length&&(d.killSuggestions(),d.disableKillerFn())},d.noSuggestionsContainer=a('<div class="autocomplete-no-suggestion"></div>').html(this.options.noSuggestionNotice).get(0),d.suggestionsContainer=b.utils.createNode(g.containerClass),c=a(d.suggestionsContainer),c.appendTo(g.appendTo),"auto"!==g.width&&c.width(g.width),c.on("mouseover.autocomplete",e,function(){d.activate(a(this).data("index"))}),c.on("mouseout.autocomplete",function(){d.selectedIndex=-1,c.children("."+f).removeClass(f)}),c.on("click.autocomplete",e,function(){d.select(a(this).data("index"))}),d.fixPositionCapture=function(){d.visible&&d.fixPosition()},a(window).on("resize.autocomplete",d.fixPositionCapture),d.el.on("keydown.autocomplete",function(a){d.onKeyPress(a)}),d.el.on("keyup.autocomplete",function(a){d.onKeyUp(a)}),d.el.on("blur.autocomplete",function(){d.onBlur()}),d.el.on("focus.autocomplete",function(){d.onFocus()}),d.el.on("change.autocomplete",function(a){d.onKeyUp(a)})},onFocus:function(){var a=this;a.fixPosition(),a.options.minChars<=a.el.val().length&&a.onValueChange()},onBlur:function(){this.enableKillerFn()},setOptions:function(b){var c=this,d=c.options;a.extend(d,b),c.isLocal=a.isArray(d.lookup),c.isLocal&&(d.lookup=c.verifySuggestionsFormat(d.lookup)),d.orientation=c.validateOrientation(d.orientation,"bottom"),a(c.suggestionsContainer).css({"max-height":d.maxHeight+"px",width:d.width+"px","z-index":d.zIndex})},clearCache:function(){this.cachedResponse={},this.badQueries=[]},clear:function(){this.clearCache(),this.currentValue="",this.suggestions=[]},disable:function(){var a=this;a.disabled=!0,clearInterval(a.onChangeInterval),a.currentRequest&&a.currentRequest.abort()},enable:function(){this.disabled=!1},fixPosition:function(){var b=this,c=a(b.suggestionsContainer),d=c.parent().get(0);if(d===document.body||b.options.forceFixPosition){var e=b.options.orientation,f=c.outerHeight(),g=b.el.outerHeight(),h=b.el.offset(),i={top:h.top,left:h.left};if("auto"==e){var j=a(window).height(),k=a(window).scrollTop(),l=-k+h.top-f,m=k+j-(h.top+g+f);e=Math.max(l,m)===l?"top":"bottom"}if(i.top+="top"===e?-f:g,d!==document.body){var n,o=c.css("opacity");b.visible||c.css("opacity",0).show(),n=c.offsetParent().offset(),i.top-=n.top,i.left-=n.left,b.visible||c.css("opacity",o).hide()}"auto"===b.options.width&&(i.width=b.el.outerWidth()-2+"px"),c.css(i)}},enableKillerFn:function(){var b=this;a(document).on("click.autocomplete",b.killerFn)},disableKillerFn:function(){var b=this;a(document).off("click.autocomplete",b.killerFn)},killSuggestions:function(){var a=this;a.stopKillSuggestions(),a.intervalId=window.setInterval(function(){a.hide(),a.stopKillSuggestions()},50)},stopKillSuggestions:function(){window.clearInterval(this.intervalId)},isCursorAtEnd:function(){var a,b=this,c=b.el.val().length,d=b.element.selectionStart;return"number"==typeof d?d===c:document.selection?(a=document.selection.createRange(),a.moveStart("character",-c),c===a.text.length):!0},onKeyPress:function(a){var b=this;if(!b.disabled&&!b.visible&&a.which===d.DOWN&&b.currentValue)return void b.suggest();if(!b.disabled&&b.visible){switch(a.which){case d.ESC:b.el.val(b.currentValue),b.hide();break;case d.RIGHT:if(b.hint&&b.options.onHint&&b.isCursorAtEnd()){b.selectHint();break}return;case d.TAB:if(b.hint&&b.options.onHint)return void b.selectHint();case d.RETURN:if(-1===b.selectedIndex)return void b.hide();if(b.select(b.selectedIndex),a.which===d.TAB&&b.options.tabDisabled===!1)return;break;case d.UP:b.moveUp();break;case d.DOWN:b.moveDown();break;default:return}a.stopImmediatePropagation(),a.preventDefault()}},onKeyUp:function(a){var b=this;if(!b.disabled){switch(a.which){case d.UP:case d.DOWN:return}clearInterval(b.onChangeInterval),b.currentValue!==b.el.val()&&(b.findBestHint(),b.options.deferRequestBy>0?b.onChangeInterval=setInterval(function(){b.onValueChange()},b.options.deferRequestBy):b.onValueChange())}},onValueChange:function(){var b,c=this,d=c.options,e=c.el.val(),f=c.getQuery(e);return c.selection&&c.currentValue!==f&&(c.selection=null,(d.onInvalidateSelection||a.noop).call(c.element)),clearInterval(c.onChangeInterval),c.currentValue=e,c.selectedIndex=-1,d.triggerSelectOnValidInput&&(b=c.findSuggestionIndex(f),-1!==b)?void c.select(b):void(f.length<d.minChars?c.hide():c.getSuggestions(f))},findSuggestionIndex:function(b){var c=this,d=-1,e=b.toLowerCase();return a.each(c.suggestions,function(a,b){return b.value.toLowerCase()===e?(d=a,!1):void 0}),d},getQuery:function(b){var c,d=this.options.delimiter;return d?(c=b.split(d),a.trim(c[c.length-1])):b},getSuggestionsLocal:function(b){var c,d=this,e=d.options,f=b.toLowerCase(),g=e.lookupFilter,h=parseInt(e.lookupLimit,10);return c={suggestions:a.grep(e.lookup,function(a){return g(a,b,f)})},h&&c.suggestions.length>h&&(c.suggestions=c.suggestions.slice(0,h)),c},getSuggestions:function(b){var c,d,e,f,g=this,h=g.options,i=h.serviceUrl;if(h.params[h.paramName]=b,d=h.ignoreParams?null:h.params,h.onSearchStart.call(g.element,h.params)!==!1){if(a.isFunction(g.lookup))return void g.lookup(b,function(a){g.suggestions=a.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,a.suggestions)});g.isLocal?c=g.getSuggestionsLocal(b):(a.isFunction(i)&&(i=i.call(g.element,b)),e=i+"?"+a.param(d||{}),c=g.cachedResponse[e]),c&&a.isArray(c.suggestions)?(g.suggestions=c.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,c.suggestions)):g.isBadQuery(b)?h.onSearchComplete.call(g.element,b,[]):(g.currentRequest&&g.currentRequest.abort(),f={url:i,data:d,type:h.type,dataType:h.dataType},a.extend(f,h.ajaxSettings),g.currentRequest=a.ajax(f).done(function(a){var c;g.currentRequest=null,c=h.transformResult(a),g.processResponse(c,b,e),h.onSearchComplete.call(g.element,b,c.suggestions)}).fail(function(a,c,d){h.onSearchError.call(g.element,b,a,c,d)}))}},isBadQuery:function(a){if(!this.options.preventBadQueries)return!1;for(var b=this.badQueries,c=b.length;c--;)if(0===a.indexOf(b[c]))return!0;return!1},hide:function(){var b=this;b.visible=!1,b.selectedIndex=-1,clearInterval(b.onChangeInterval),a(b.suggestionsContainer).hide(),b.signalHint(null)},suggest:function(){if(0===this.suggestions.length)return void(this.options.showNoSuggestionNotice?this.noSuggestions():this.hide());var b,c,d=this,e=d.options,f=e.groupBy,g=e.formatResult,h=d.getQuery(d.currentValue),i=d.classes.suggestion,j=d.classes.selected,k=a(d.suggestionsContainer),l=a(d.noSuggestionsContainer),m=e.beforeRender,n="",o=function(a){var c=a.data[f];return b===c?"":(b=c,'<div class="autocomplete-group"><strong>'+b+"</strong></div>")};return e.triggerSelectOnValidInput&&(c=d.findSuggestionIndex(h),-1!==c)?void d.select(c):(a.each(d.suggestions,function(a,b){f&&(n+=o(b,h,a)),n+='<div class="'+i+'" data-index="'+a+'">'+g(b,h)+"</div>"}),this.adjustContainerWidth(),l.detach(),k.html(n),a.isFunction(m)&&m.call(d.element,k),d.fixPosition(),k.show(),e.autoSelectFirst&&(d.selectedIndex=0,k.scrollTop(0),k.children().first().addClass(j)),d.visible=!0,void d.findBestHint())},noSuggestions:function(){var b=this,c=a(b.suggestionsContainer),d=a(b.noSuggestionsContainer);this.adjustContainerWidth(),d.detach(),c.empty(),c.append(d),b.fixPosition(),c.show(),b.visible=!0},adjustContainerWidth:function(){var b,c=this,d=c.options,e=a(c.suggestionsContainer);"auto"===d.width&&(b=c.el.outerWidth()-2,e.width(b>0?b:300))},findBestHint:function(){var b=this,c=b.el.val().toLowerCase(),d=null;c&&(a.each(b.suggestions,function(a,b){var e=0===b.value.toLowerCase().indexOf(c);return e&&(d=b),!e}),b.signalHint(d))},signalHint:function(b){var c="",d=this;b&&(c=d.currentValue+b.value.substr(d.currentValue.length)),d.hintValue!==c&&(d.hintValue=c,d.hint=b,(this.options.onHint||a.noop)(c))},verifySuggestionsFormat:function(b){return b.length&&"string"==typeof b[0]?a.map(b,function(a){return{value:a,data:null}}):b},validateOrientation:function(b,c){return b=a.trim(b||"").toLowerCase(),-1===a.inArray(b,["auto","bottom","top"])&&(b=c),b},processResponse:function(a,b,c){var d=this,e=d.options;a.suggestions=d.verifySuggestionsFormat(a.suggestions),e.noCache||(d.cachedResponse[c]=a,e.preventBadQueries&&0===a.suggestions.length&&d.badQueries.push(b)),b===d.getQuery(d.currentValue)&&(d.suggestions=a.suggestions,d.suggest())},activate:function(b){var c,d=this,e=d.classes.selected,f=a(d.suggestionsContainer),g=f.find("."+d.classes.suggestion);return f.find("."+e).removeClass(e),d.selectedIndex=b,-1!==d.selectedIndex&&g.length>d.selectedIndex?(c=g.get(d.selectedIndex),a(c).addClass(e),c):null},selectHint:function(){var b=this,c=a.inArray(b.hint,b.suggestions);b.select(c)},select:function(a){var b=this;b.hide(),b.onSelect(a)},moveUp:function(){var b=this;if(-1!==b.selectedIndex)return 0===b.selectedIndex?(a(b.suggestionsContainer).children().first().removeClass(b.classes.selected),b.selectedIndex=-1,b.el.val(b.currentValue),void b.findBestHint()):void b.adjustScroll(b.selectedIndex-1)},moveDown:function(){var a=this;a.selectedIndex!==a.suggestions.length-1&&a.adjustScroll(a.selectedIndex+1)},adjustScroll:function(b){var c=this,d=c.activate(b);if(d){var e,f,g,h=a(d).outerHeight();e=d.offsetTop,f=a(c.suggestionsContainer).scrollTop(),g=f+c.options.maxHeight-h,f>e?a(c.suggestionsContainer).scrollTop(e):e>g&&a(c.suggestionsContainer).scrollTop(e-c.options.maxHeight+h),c.el.val(c.getValue(c.suggestions[b].value)),c.signalHint(null)}},onSelect:function(b){var c=this,d=c.options.onSelect,e=c.suggestions[b];c.currentValue=c.getValue(e.value),c.currentValue!==c.el.val()&&c.el.val(c.currentValue),c.signalHint(null),c.suggestions=[],c.selection=e,a.isFunction(d)&&d.call(c.element,e)},getValue:function(a){var b,c,d=this,e=d.options.delimiter;return e?(b=d.currentValue,c=b.split(e),1===c.length?a:b.substr(0,b.length-c[c.length-1].length)+a):a},dispose:function(){var b=this;b.el.off(".autocomplete").removeData("autocomplete"),b.disableKillerFn(),a(window).off("resize.autocomplete",b.fixPositionCapture),a(b.suggestionsContainer).remove()}},a.fn.autocomplete=a.fn.devbridgeAutocomplete=function(c,d){var e="autocomplete";return 0===arguments.length?this.first().data(e):this.each(function(){var f=a(this),g=f.data(e);"string"==typeof c?g&&"function"==typeof g[c]&&g[c](d):(g&&g.dispose&&g.dispose(),g=new b(this,c),f.data(e,g))})}});
+* Ajax Autocomplete for jQuery, version 1.2.18
+* (c) 2014 Tomas Kirda
+*
+* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
+* For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
+*/
+!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports&&"function"==typeof require?require("jquery"):jQuery)}(function(a){"use strict";function b(c,d){var e=function(){},f=this,g={ajaxSettings:{},autoSelectFirst:!1,appendTo:document.body,serviceUrl:null,lookup:null,onSelect:null,width:"auto",minChars:1,maxHeight:300,deferRequestBy:0,params:{},formatResult:b.formatResult,delimiter:null,zIndex:9999,type:"GET",noCache:!1,onSearchStart:e,onSearchComplete:e,onSearchError:e,preserveInput:!1,containerClass:"autocomplete-suggestions",tabDisabled:!1,dataType:"text",currentRequest:null,triggerSelectOnValidInput:!0,preventBadQueries:!0,lookupFilter:function(a,b,c){return-1!==a.value.toLowerCase().indexOf(c)},paramName:"query",transformResult:function(b){return"string"==typeof b?a.parseJSON(b):b},showNoSuggestionNotice:!1,noSuggestionNotice:"No results",orientation:"bottom",forceFixPosition:!1};f.element=c,f.el=a(c),f.suggestions=[],f.badQueries=[],f.selectedIndex=-1,f.currentValue=f.element.value,f.intervalId=0,f.cachedResponse={},f.onChangeInterval=null,f.onChange=null,f.isLocal=!1,f.suggestionsContainer=null,f.noSuggestionsContainer=null,f.options=a.extend({},g,d),f.classes={selected:"autocomplete-selected",suggestion:"autocomplete-suggestion"},f.hint=null,f.hintValue="",f.selection=null,f.initialize(),f.setOptions(d)}var c=function(){return{escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},createNode:function(a){var b=document.createElement("div");return b.className=a,b.style.position="absolute",b.style.display="none",b}}}(),d={ESC:27,TAB:9,RETURN:13,LEFT:37,UP:38,RIGHT:39,DOWN:40};b.utils=c,a.Autocomplete=b,b.formatResult=function(a,b){var d="("+c.escapeRegExChars(b)+")";return a.value.replace(new RegExp(d,"gi"),"<strong>$1</strong>")},b.prototype={killerFn:null,initialize:function(){var c,d=this,e="."+d.classes.suggestion,f=d.classes.selected,g=d.options;d.element.setAttribute("autocomplete","off"),d.killerFn=function(b){0===a(b.target).closest("."+d.options.containerClass).length&&(d.killSuggestions(),d.disableKillerFn())},d.noSuggestionsContainer=a('<div class="autocomplete-no-suggestion"></div>').html(this.options.noSuggestionNotice).get(0),d.suggestionsContainer=b.utils.createNode(g.containerClass),c=a(d.suggestionsContainer),c.appendTo(g.appendTo),"auto"!==g.width&&c.width(g.width),c.on("mouseover.autocomplete",e,function(){d.activate(a(this).data("index"))}),c.on("mouseout.autocomplete",function(){d.selectedIndex=-1,c.children("."+f).removeClass(f)}),c.on("click.autocomplete",e,function(){d.select(a(this).data("index"))}),d.fixPositionCapture=function(){d.visible&&d.fixPosition()},a(window).on("resize.autocomplete",d.fixPositionCapture),d.el.on("keydown.autocomplete",function(a){d.onKeyPress(a)}),d.el.on("keyup.autocomplete",function(a){d.onKeyUp(a)}),d.el.on("blur.autocomplete",function(){d.onBlur()}),d.el.on("focus.autocomplete",function(){d.onFocus()}),d.el.on("change.autocomplete",function(a){d.onKeyUp(a)}),d.el.on("input.autocomplete",function(a){d.onKeyUp(a)})},onFocus:function(){var a=this;a.fixPosition(),a.options.minChars<=a.el.val().length&&a.onValueChange()},onBlur:function(){this.enableKillerFn()},setOptions:function(b){var c=this,d=c.options;a.extend(d,b),c.isLocal=a.isArray(d.lookup),c.isLocal&&(d.lookup=c.verifySuggestionsFormat(d.lookup)),d.orientation=c.validateOrientation(d.orientation,"bottom"),a(c.suggestionsContainer).css({"max-height":d.maxHeight+"px",width:d.width+"px","z-index":d.zIndex})},clearCache:function(){this.cachedResponse={},this.badQueries=[]},clear:function(){this.clearCache(),this.currentValue="",this.suggestions=[]},disable:function(){var a=this;a.disabled=!0,clearInterval(a.onChangeInterval),a.currentRequest&&a.currentRequest.abort()},enable:function(){this.disabled=!1},fixPosition:function(){var b=this,c=a(b.suggestionsContainer),d=c.parent().get(0);if(d===document.body||b.options.forceFixPosition){var e=b.options.orientation,f=c.outerHeight(),g=b.el.outerHeight(),h=b.el.offset(),i={top:h.top,left:h.left};if("auto"===e){var j=a(window).height(),k=a(window).scrollTop(),l=-k+h.top-f,m=k+j-(h.top+g+f);e=Math.max(l,m)===l?"top":"bottom"}if(i.top+="top"===e?-f:g,d!==document.body){var n,o=c.css("opacity");b.visible||c.css("opacity",0).show(),n=c.offsetParent().offset(),i.top-=n.top,i.left-=n.left,b.visible||c.css("opacity",o).hide()}"auto"===b.options.width&&(i.width=b.el.outerWidth()-2+"px"),c.css(i)}},enableKillerFn:function(){var b=this;a(document).on("click.autocomplete",b.killerFn)},disableKillerFn:function(){var b=this;a(document).off("click.autocomplete",b.killerFn)},killSuggestions:function(){var a=this;a.stopKillSuggestions(),a.intervalId=window.setInterval(function(){a.hide(),a.stopKillSuggestions()},50)},stopKillSuggestions:function(){window.clearInterval(this.intervalId)},isCursorAtEnd:function(){var a,b=this,c=b.el.val().length,d=b.element.selectionStart;return"number"==typeof d?d===c:document.selection?(a=document.selection.createRange(),a.moveStart("character",-c),c===a.text.length):!0},onKeyPress:function(a){var b=this;if(!b.disabled&&!b.visible&&a.which===d.DOWN&&b.currentValue)return void b.suggest();if(!b.disabled&&b.visible){switch(a.which){case d.ESC:b.el.val(b.currentValue),b.hide();break;case d.RIGHT:if(b.hint&&b.options.onHint&&b.isCursorAtEnd()){b.selectHint();break}return;case d.TAB:if(b.hint&&b.options.onHint)return void b.selectHint();if(-1===b.selectedIndex)return void b.hide();if(b.select(b.selectedIndex),b.options.tabDisabled===!1)return;break;case d.RETURN:if(-1===b.selectedIndex)return void b.hide();b.select(b.selectedIndex);break;case d.UP:b.moveUp();break;case d.DOWN:b.moveDown();break;default:return}a.stopImmediatePropagation(),a.preventDefault()}},onKeyUp:function(a){var b=this;if(!b.disabled){switch(a.which){case d.UP:case d.DOWN:return}clearInterval(b.onChangeInterval),b.currentValue!==b.el.val()&&(b.findBestHint(),b.options.deferRequestBy>0?b.onChangeInterval=setInterval(function(){b.onValueChange()},b.options.deferRequestBy):b.onValueChange())}},onValueChange:function(){var b,c=this,d=c.options,e=c.el.val(),f=c.getQuery(e);return c.selection&&c.currentValue!==f&&(c.selection=null,(d.onInvalidateSelection||a.noop).call(c.element)),clearInterval(c.onChangeInterval),c.currentValue=e,c.selectedIndex=-1,d.triggerSelectOnValidInput&&(b=c.findSuggestionIndex(f),-1!==b)?void c.select(b):void(f.length<d.minChars?c.hide():c.getSuggestions(f))},findSuggestionIndex:function(b){var c=this,d=-1,e=b.toLowerCase();return a.each(c.suggestions,function(a,b){return b.value.toLowerCase()===e?(d=a,!1):void 0}),d},getQuery:function(b){var c,d=this.options.delimiter;return d?(c=b.split(d),a.trim(c[c.length-1])):b},getSuggestionsLocal:function(b){var c,d=this,e=d.options,f=b.toLowerCase(),g=e.lookupFilter,h=parseInt(e.lookupLimit,10);return c={suggestions:a.grep(e.lookup,function(a){return g(a,b,f)})},h&&c.suggestions.length>h&&(c.suggestions=c.suggestions.slice(0,h)),c},getSuggestions:function(b){var c,d,e,f,g=this,h=g.options,i=h.serviceUrl;if(h.params[h.paramName]=b,d=h.ignoreParams?null:h.params,h.onSearchStart.call(g.element,h.params)!==!1){if(a.isFunction(h.lookup))return void h.lookup(b,function(a){g.suggestions=a.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,a.suggestions)});g.isLocal?c=g.getSuggestionsLocal(b):(a.isFunction(i)&&(i=i.call(g.element,b)),e=i+"?"+a.param(d||{}),c=g.cachedResponse[e]),c&&a.isArray(c.suggestions)?(g.suggestions=c.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,c.suggestions)):g.isBadQuery(b)?h.onSearchComplete.call(g.element,b,[]):(g.currentRequest&&g.currentRequest.abort(),f={url:i,data:d,type:h.type,dataType:h.dataType},a.extend(f,h.ajaxSettings),g.currentRequest=a.ajax(f).done(function(a){var c;g.currentRequest=null,c=h.transformResult(a),g.processResponse(c,b,e),h.onSearchComplete.call(g.element,b,c.suggestions)}).fail(function(a,c,d){h.onSearchError.call(g.element,b,a,c,d)}))}},isBadQuery:function(a){if(!this.options.preventBadQueries)return!1;for(var b=this.badQueries,c=b.length;c--;)if(0===a.indexOf(b[c]))return!0;return!1},hide:function(){var b=this,c=a(b.suggestionsContainer);a.isFunction(b.options.onHide)&&b.visible&&b.options.onHide.call(b.element,c),b.visible=!1,b.selectedIndex=-1,clearInterval(b.onChangeInterval),a(b.suggestionsContainer).hide(),b.signalHint(null)},suggest:function(){if(0===this.suggestions.length)return void(this.options.showNoSuggestionNotice?this.noSuggestions():this.hide());var b,c,d=this,e=d.options,f=e.groupBy,g=e.formatResult,h=d.getQuery(d.currentValue),i=d.classes.suggestion,j=d.classes.selected,k=a(d.suggestionsContainer),l=a(d.noSuggestionsContainer),m=e.beforeRender,n="",o=function(a){var c=a.data[f];return b===c?"":(b=c,'<div class="autocomplete-group"><strong>'+b+"</strong></div>")};return e.triggerSelectOnValidInput&&(c=d.findSuggestionIndex(h),-1!==c)?void d.select(c):(a.each(d.suggestions,function(a,b){f&&(n+=o(b,h,a)),n+='<div class="'+i+'" data-index="'+a+'">'+g(b,h)+"</div>"}),this.adjustContainerWidth(),l.detach(),k.html(n),a.isFunction(m)&&m.call(d.element,k),d.fixPosition(),k.show(),e.autoSelectFirst&&(d.selectedIndex=0,k.scrollTop(0),k.children("."+i).first().addClass(j)),d.visible=!0,void d.findBestHint())},noSuggestions:function(){var b=this,c=a(b.suggestionsContainer),d=a(b.noSuggestionsContainer);this.adjustContainerWidth(),d.detach(),c.empty(),c.append(d),b.fixPosition(),c.show(),b.visible=!0},adjustContainerWidth:function(){var b,c=this,d=c.options,e=a(c.suggestionsContainer);"auto"===d.width&&(b=c.el.outerWidth()-2,e.width(b>0?b:300))},findBestHint:function(){var b=this,c=b.el.val().toLowerCase(),d=null;c&&(a.each(b.suggestions,function(a,b){var e=0===b.value.toLowerCase().indexOf(c);return e&&(d=b),!e}),b.signalHint(d))},signalHint:function(b){var c="",d=this;b&&(c=d.currentValue+b.value.substr(d.currentValue.length)),d.hintValue!==c&&(d.hintValue=c,d.hint=b,(this.options.onHint||a.noop)(c))},verifySuggestionsFormat:function(b){return b.length&&"string"==typeof b[0]?a.map(b,function(a){return{value:a,data:null}}):b},validateOrientation:function(b,c){return b=a.trim(b||"").toLowerCase(),-1===a.inArray(b,["auto","bottom","top"])&&(b=c),b},processResponse:function(a,b,c){var d=this,e=d.options;a.suggestions=d.verifySuggestionsFormat(a.suggestions),e.noCache||(d.cachedResponse[c]=a,e.preventBadQueries&&0===a.suggestions.length&&d.badQueries.push(b)),b===d.getQuery(d.currentValue)&&(d.suggestions=a.suggestions,d.suggest())},activate:function(b){var c,d=this,e=d.classes.selected,f=a(d.suggestionsContainer),g=f.find("."+d.classes.suggestion);return f.find("."+e).removeClass(e),d.selectedIndex=b,-1!==d.selectedIndex&&g.length>d.selectedIndex?(c=g.get(d.selectedIndex),a(c).addClass(e),c):null},selectHint:function(){var b=this,c=a.inArray(b.hint,b.suggestions);b.select(c)},select:function(a){var b=this;b.hide(),b.onSelect(a)},moveUp:function(){var b=this;if(-1!==b.selectedIndex)return 0===b.selectedIndex?(a(b.suggestionsContainer).children().first().removeClass(b.classes.selected),b.selectedIndex=-1,b.el.val(b.currentValue),void b.findBestHint()):void b.adjustScroll(b.selectedIndex-1)},moveDown:function(){var a=this;a.selectedIndex!==a.suggestions.length-1&&a.adjustScroll(a.selectedIndex+1)},adjustScroll:function(b){var c=this,d=c.activate(b);if(d){var e,f,g,h=a(d).outerHeight();e=d.offsetTop,f=a(c.suggestionsContainer).scrollTop(),g=f+c.options.maxHeight-h,f>e?a(c.suggestionsContainer).scrollTop(e):e>g&&a(c.suggestionsContainer).scrollTop(e-c.options.maxHeight+h),c.options.preserveInput||c.el.val(c.getValue(c.suggestions[b].value)),c.signalHint(null)}},onSelect:function(b){var c=this,d=c.options.onSelect,e=c.suggestions[b];c.currentValue=c.getValue(e.value),c.currentValue===c.el.val()||c.options.preserveInput||c.el.val(c.currentValue),c.signalHint(null),c.suggestions=[],c.selection=e,a.isFunction(d)&&d.call(c.element,e)},getValue:function(a){var b,c,d=this,e=d.options.delimiter;return e?(b=d.currentValue,c=b.split(e),1===c.length?a:b.substr(0,b.length-c[c.length-1].length)+a):a},dispose:function(){var b=this;b.el.off(".autocomplete").removeData("autocomplete"),b.disableKillerFn(),a(window).off("resize.autocomplete",b.fixPositionCapture),a(b.suggestionsContainer).remove()}},a.fn.autocomplete=a.fn.devbridgeAutocomplete=function(c,d){var e="autocomplete";return 0===arguments.length?this.first().data(e):this.each(function(){var f=a(this),g=f.data(e);"string"==typeof c?g&&"function"==typeof g[c]&&g[c](d):(g&&g.dispose&&g.dispose(),g=new b(this,c),f.data(e,g))})}});
Please sign in to comment.
Something went wrong with that request. Please try again.