mirror of
https://github.com/devbridge/jQuery-Autocomplete.git
synced 2024-11-14 09:14:09 +00:00
Merge branch 'develop' into develop_update-jasmine
This commit is contained in:
commit
d3e62d904d
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@
|
|||||||
/.idea*
|
/.idea*
|
||||||
/*.xml
|
/*.xml
|
||||||
/bower_components
|
/bower_components
|
||||||
|
/node_modules/*
|
||||||
|
44
bower.json
44
bower.json
@ -1,24 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "devbridge-autocomplete",
|
"name": "devbridge-autocomplete",
|
||||||
"version": "1.2.9",
|
"version": "1.2.12",
|
||||||
"homepage": "https://github.com/devbridge/jQuery-Autocomplete",
|
"homepage": "https://github.com/devbridge/jQuery-Autocomplete",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Tomas Kirda"
|
"Tomas Kirda"
|
||||||
],
|
],
|
||||||
"description": "Autocomplete provides suggestions while you type into the text field.",
|
"description": "Autocomplete provides suggestions while you type into the text field.",
|
||||||
"main": "dist/jquery.autocomplete.js",
|
"main": "dist/jquery.autocomplete.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ajax",
|
"ajax",
|
||||||
"autocomplete"
|
"autocomplete"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"**/.*",
|
"**/.*",
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"bower_components",
|
"bower_components",
|
||||||
"spec"
|
"spec"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jquery": ">=1.7"
|
"jquery": ">=1.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,7 @@
|
|||||||
"ajax",
|
"ajax",
|
||||||
"autocomplete"
|
"autocomplete"
|
||||||
],
|
],
|
||||||
"version": "1.2.9",
|
"version": "1.2.12",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Tomas Kirda",
|
"name": "Tomas Kirda",
|
||||||
"url": "https://github.com/tkirda"
|
"url": "https://github.com/tkirda"
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"bugs": "https://github.com/devbridge/jQuery-Autocomplete/issues?state=open",
|
"bugs": "https://github.com/devbridge/jQuery-Autocomplete/issues?state=open",
|
||||||
"homepage": "https://github.com/devbridge/jQuery-Autocomplete",
|
"homepage": "https://github.com/devbridge/jQuery-Autocomplete",
|
||||||
"docs": "https://github.com/devbridge/jQuery-Autocomplete",
|
"docs": "https://github.com/devbridge/jQuery-Autocomplete",
|
||||||
"demo": "http://www.devbridge.com/projects/autocomplete/jquery/",
|
"demo": "http://www.devbridge.com/sourcery/components/jquery-autocomplete/",
|
||||||
"download": "https://github.com/devbridge/jQuery-Autocomplete/tree/master/dist",
|
"download": "https://github.com/devbridge/jQuery-Autocomplete/tree/master/dist",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jquery": ">=1.7"
|
"jquery": ">=1.7"
|
||||||
|
206
dist/jquery.autocomplete.js
vendored
206
dist/jquery.autocomplete.js
vendored
@ -1,14 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* Ajax Autocomplete for jQuery, version 1.2.9
|
* Ajax Autocomplete for jQuery, version 1.2.12
|
||||||
* (c) 2013 Tomas Kirda
|
* (c) 2014 Tomas Kirda
|
||||||
*
|
*
|
||||||
* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
|
* 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
|
* For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*jslint browser: true, white: true, plusplus: true */
|
/*jslint browser: true, white: true, plusplus: true */
|
||||||
/*global define, window, document, jQuery */
|
/*global define, window, document, jQuery, exports */
|
||||||
|
|
||||||
// Expose plugin as an AMD module if AMD loader is present:
|
// Expose plugin as an AMD module if AMD loader is present:
|
||||||
(function (factory) {
|
(function (factory) {
|
||||||
@ -16,6 +15,9 @@
|
|||||||
if (typeof define === 'function' && define.amd) {
|
if (typeof define === 'function' && define.amd) {
|
||||||
// AMD. Register as an anonymous module.
|
// AMD. Register as an anonymous module.
|
||||||
define(['jquery'], factory);
|
define(['jquery'], factory);
|
||||||
|
} else if (typeof exports === 'object' && typeof require === 'function') {
|
||||||
|
// Browserify
|
||||||
|
factory(require('jquery'));
|
||||||
} else {
|
} else {
|
||||||
// Browser globals
|
// Browser globals
|
||||||
factory(jQuery);
|
factory(jQuery);
|
||||||
@ -53,8 +55,9 @@
|
|||||||
var noop = function () { },
|
var noop = function () { },
|
||||||
that = this,
|
that = this,
|
||||||
defaults = {
|
defaults = {
|
||||||
|
ajaxSettings: {},
|
||||||
autoSelectFirst: false,
|
autoSelectFirst: false,
|
||||||
appendTo: 'body',
|
appendTo: document.body,
|
||||||
serviceUrl: null,
|
serviceUrl: null,
|
||||||
lookup: null,
|
lookup: null,
|
||||||
onSelect: null,
|
onSelect: null,
|
||||||
@ -76,13 +79,18 @@
|
|||||||
dataType: 'text',
|
dataType: 'text',
|
||||||
currentRequest: null,
|
currentRequest: null,
|
||||||
triggerSelectOnValidInput: true,
|
triggerSelectOnValidInput: true,
|
||||||
|
preventBadQueries: true,
|
||||||
lookupFilter: function (suggestion, originalQuery, queryLowerCase) {
|
lookupFilter: function (suggestion, originalQuery, queryLowerCase) {
|
||||||
return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1;
|
return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1;
|
||||||
},
|
},
|
||||||
paramName: 'query',
|
paramName: 'query',
|
||||||
transformResult: function (response) {
|
transformResult: function (response) {
|
||||||
return typeof response === 'string' ? $.parseJSON(response) : response;
|
return typeof response === 'string' ? $.parseJSON(response) : response;
|
||||||
}
|
},
|
||||||
|
showNoSuggestionNotice: false,
|
||||||
|
noSuggestionNotice: 'No results',
|
||||||
|
orientation: 'bottom',
|
||||||
|
forceFixPosition: false
|
||||||
};
|
};
|
||||||
|
|
||||||
// Shared variables:
|
// Shared variables:
|
||||||
@ -98,6 +106,7 @@
|
|||||||
that.onChange = null;
|
that.onChange = null;
|
||||||
that.isLocal = false;
|
that.isLocal = false;
|
||||||
that.suggestionsContainer = null;
|
that.suggestionsContainer = null;
|
||||||
|
that.noSuggestionsContainer = null;
|
||||||
that.options = $.extend({}, defaults, options);
|
that.options = $.extend({}, defaults, options);
|
||||||
that.classes = {
|
that.classes = {
|
||||||
selected: 'autocomplete-selected',
|
selected: 'autocomplete-selected',
|
||||||
@ -143,6 +152,10 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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);
|
that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass);
|
||||||
|
|
||||||
container = $(that.suggestionsContainer);
|
container = $(that.suggestionsContainer);
|
||||||
@ -170,8 +183,6 @@
|
|||||||
that.select($(this).data('index'));
|
that.select($(this).data('index'));
|
||||||
});
|
});
|
||||||
|
|
||||||
that.fixPosition();
|
|
||||||
|
|
||||||
that.fixPositionCapture = function () {
|
that.fixPositionCapture = function () {
|
||||||
if (that.visible) {
|
if (that.visible) {
|
||||||
that.fixPosition();
|
that.fixPosition();
|
||||||
@ -211,6 +222,8 @@
|
|||||||
options.lookup = that.verifySuggestionsFormat(options.lookup);
|
options.lookup = that.verifySuggestionsFormat(options.lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.orientation = that.validateOrientation(options.orientation, 'bottom');
|
||||||
|
|
||||||
// Adjust height, width and z-index:
|
// Adjust height, width and z-index:
|
||||||
$(that.suggestionsContainer).css({
|
$(that.suggestionsContainer).css({
|
||||||
'max-height': options.maxHeight + 'px',
|
'max-height': options.maxHeight + 'px',
|
||||||
@ -219,6 +232,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
clearCache: function () {
|
clearCache: function () {
|
||||||
this.cachedResponse = {};
|
this.cachedResponse = {};
|
||||||
this.badQueries = [];
|
this.badQueries = [];
|
||||||
@ -243,27 +257,65 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
fixPosition: function () {
|
fixPosition: function () {
|
||||||
var that = this,
|
// Use only when container has already its content
|
||||||
offset,
|
|
||||||
styles;
|
|
||||||
|
|
||||||
// Don't adjsut position if custom container has been specified:
|
var that = this,
|
||||||
if (that.options.appendTo !== 'body') {
|
$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;
|
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';
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = that.el.offset();
|
if (orientation === 'top') {
|
||||||
|
styles.top += -containerHeight;
|
||||||
|
} else {
|
||||||
|
styles.top += height;
|
||||||
|
}
|
||||||
|
|
||||||
styles = {
|
// If container is not positioned to body,
|
||||||
top: (offset.top + that.el.outerHeight()) + 'px',
|
// correct its position using offset parent offset
|
||||||
left: offset.left + 'px'
|
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') {
|
if (that.options.width === 'auto') {
|
||||||
styles.width = (that.el.outerWidth() - 2) + 'px';
|
styles.width = (that.el.outerWidth() - 2) + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
$(that.suggestionsContainer).css(styles);
|
$container.css(styles);
|
||||||
},
|
},
|
||||||
|
|
||||||
enableKillerFn: function () {
|
enableKillerFn: function () {
|
||||||
@ -396,7 +448,7 @@
|
|||||||
query = that.getQuery(value),
|
query = that.getQuery(value),
|
||||||
index;
|
index;
|
||||||
|
|
||||||
if (that.selection) {
|
if (that.selection && that.currentValue !== query) {
|
||||||
that.selection = null;
|
that.selection = null;
|
||||||
(options.onInvalidateSelection || $.noop).call(that.element);
|
(options.onInvalidateSelection || $.noop).call(that.element);
|
||||||
}
|
}
|
||||||
@ -473,11 +525,12 @@
|
|||||||
that = this,
|
that = this,
|
||||||
options = that.options,
|
options = that.options,
|
||||||
serviceUrl = options.serviceUrl,
|
serviceUrl = options.serviceUrl,
|
||||||
data,
|
params,
|
||||||
cacheKey;
|
cacheKey,
|
||||||
|
ajaxSettings;
|
||||||
|
|
||||||
options.params[options.paramName] = q;
|
options.params[options.paramName] = q;
|
||||||
data = options.ignoreParams ? null : options.params;
|
params = options.ignoreParams ? null : options.params;
|
||||||
|
|
||||||
if (that.isLocal) {
|
if (that.isLocal) {
|
||||||
response = that.getSuggestionsLocal(q);
|
response = that.getSuggestionsLocal(q);
|
||||||
@ -485,7 +538,7 @@
|
|||||||
if ($.isFunction(serviceUrl)) {
|
if ($.isFunction(serviceUrl)) {
|
||||||
serviceUrl = serviceUrl.call(that.element, q);
|
serviceUrl = serviceUrl.call(that.element, q);
|
||||||
}
|
}
|
||||||
cacheKey = serviceUrl + '?' + $.param(data || {});
|
cacheKey = serviceUrl + '?' + $.param(params || {});
|
||||||
response = that.cachedResponse[cacheKey];
|
response = that.cachedResponse[cacheKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,15 +552,22 @@
|
|||||||
if (that.currentRequest) {
|
if (that.currentRequest) {
|
||||||
that.currentRequest.abort();
|
that.currentRequest.abort();
|
||||||
}
|
}
|
||||||
that.currentRequest = $.ajax({
|
|
||||||
|
ajaxSettings = {
|
||||||
url: serviceUrl,
|
url: serviceUrl,
|
||||||
data: data,
|
data: params,
|
||||||
type: options.type,
|
type: options.type,
|
||||||
dataType: options.dataType
|
dataType: options.dataType
|
||||||
}).done(function (data) {
|
};
|
||||||
|
|
||||||
|
$.extend(ajaxSettings, options.ajaxSettings);
|
||||||
|
|
||||||
|
that.currentRequest = $.ajax(ajaxSettings).done(function (data) {
|
||||||
|
var result;
|
||||||
that.currentRequest = null;
|
that.currentRequest = null;
|
||||||
that.processResponse(data, q, cacheKey);
|
result = options.transformResult(data);
|
||||||
options.onSearchComplete.call(that.element, q);
|
that.processResponse(result, q, cacheKey);
|
||||||
|
options.onSearchComplete.call(that.element, q, result.suggestions);
|
||||||
}).fail(function (jqXHR, textStatus, errorThrown) {
|
}).fail(function (jqXHR, textStatus, errorThrown) {
|
||||||
options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown);
|
options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown);
|
||||||
});
|
});
|
||||||
@ -515,6 +575,10 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
isBadQuery: function (q) {
|
isBadQuery: function (q) {
|
||||||
|
if (!this.options.preventBadQueries){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var badQueries = this.badQueries,
|
var badQueries = this.badQueries,
|
||||||
i = badQueries.length;
|
i = badQueries.length;
|
||||||
|
|
||||||
@ -537,7 +601,7 @@
|
|||||||
|
|
||||||
suggest: function () {
|
suggest: function () {
|
||||||
if (this.suggestions.length === 0) {
|
if (this.suggestions.length === 0) {
|
||||||
this.hide();
|
this.options.showNoSuggestionNotice ? this.noSuggestions() : this.hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,10 +612,10 @@
|
|||||||
className = that.classes.suggestion,
|
className = that.classes.suggestion,
|
||||||
classSelected = that.classes.selected,
|
classSelected = that.classes.selected,
|
||||||
container = $(that.suggestionsContainer),
|
container = $(that.suggestionsContainer),
|
||||||
|
noSuggestionsContainer = $(that.noSuggestionsContainer),
|
||||||
beforeRender = options.beforeRender,
|
beforeRender = options.beforeRender,
|
||||||
html = '',
|
html = '',
|
||||||
index,
|
index;
|
||||||
width;
|
|
||||||
|
|
||||||
if (options.triggerSelectOnValidInput) {
|
if (options.triggerSelectOnValidInput) {
|
||||||
index = that.findSuggestionIndex(value);
|
index = that.findSuggestionIndex(value);
|
||||||
@ -566,15 +630,9 @@
|
|||||||
html += '<div class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value) + '</div>';
|
html += '<div class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value) + '</div>';
|
||||||
});
|
});
|
||||||
|
|
||||||
// If width is auto, adjust width before displaying suggestions,
|
this.adjustContainerWidth();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
noSuggestionsContainer.detach();
|
||||||
container.html(html);
|
container.html(html);
|
||||||
|
|
||||||
// Select first value by default:
|
// Select first value by default:
|
||||||
@ -587,12 +645,49 @@
|
|||||||
beforeRender.call(that.element, container);
|
beforeRender.call(that.element, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
that.fixPosition();
|
||||||
|
|
||||||
container.show();
|
container.show();
|
||||||
that.visible = true;
|
that.visible = true;
|
||||||
|
|
||||||
that.findBestHint();
|
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 () {
|
findBestHint: function () {
|
||||||
var that = this,
|
var that = this,
|
||||||
value = that.el.val().toLowerCase(),
|
value = that.el.val().toLowerCase(),
|
||||||
@ -637,18 +732,27 @@
|
|||||||
return suggestions;
|
return suggestions;
|
||||||
},
|
},
|
||||||
|
|
||||||
processResponse: function (response, originalQuery, cacheKey) {
|
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,
|
var that = this,
|
||||||
options = that.options,
|
options = that.options;
|
||||||
result = options.transformResult(response, originalQuery);
|
|
||||||
|
|
||||||
result.suggestions = that.verifySuggestionsFormat(result.suggestions);
|
result.suggestions = that.verifySuggestionsFormat(result.suggestions);
|
||||||
|
|
||||||
// Cache results if cache is not disabled:
|
// Cache results if cache is not disabled:
|
||||||
if (!options.noCache) {
|
if (!options.noCache) {
|
||||||
that.cachedResponse[cacheKey] = result;
|
that.cachedResponse[cacheKey] = result;
|
||||||
if (result.suggestions.length === 0) {
|
if (options.preventBadQueries && result.suggestions.length === 0) {
|
||||||
that.badQueries.push(cacheKey);
|
that.badQueries.push(originalQuery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,9 +770,9 @@
|
|||||||
activeItem,
|
activeItem,
|
||||||
selected = that.classes.selected,
|
selected = that.classes.selected,
|
||||||
container = $(that.suggestionsContainer),
|
container = $(that.suggestionsContainer),
|
||||||
children = container.children();
|
children = container.find('.' + that.classes.suggestion);
|
||||||
|
|
||||||
container.children('.' + selected).removeClass(selected);
|
container.find('.' + selected).removeClass(selected);
|
||||||
|
|
||||||
that.selectedIndex = index;
|
that.selectedIndex = index;
|
||||||
|
|
||||||
@ -754,7 +858,11 @@
|
|||||||
suggestion = that.suggestions[index];
|
suggestion = that.suggestions[index];
|
||||||
|
|
||||||
that.currentValue = that.getValue(suggestion.value);
|
that.currentValue = that.getValue(suggestion.value);
|
||||||
that.el.val(that.currentValue);
|
|
||||||
|
if (that.currentValue !== that.el.val()) {
|
||||||
|
that.el.val(that.currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
that.signalHint(null);
|
that.signalHint(null);
|
||||||
that.suggestions = [];
|
that.suggestions = [];
|
||||||
that.selection = suggestion;
|
that.selection = suggestion;
|
||||||
@ -794,7 +902,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create chainable jQuery plugin:
|
// Create chainable jQuery plugin:
|
||||||
$.fn.autocomplete = function (options, args) {
|
$.fn.autocomplete = $.fn.devbridgeAutocomplete = function (options, args) {
|
||||||
var dataKey = 'autocomplete';
|
var dataKey = 'autocomplete';
|
||||||
// If function invoked without argument return
|
// If function invoked without argument return
|
||||||
// instance of the first matched element:
|
// instance of the first matched element:
|
||||||
|
29
dist/jquery.autocomplete.min.js
vendored
29
dist/jquery.autocomplete.min.js
vendored
File diff suppressed because one or more lines are too long
69
gruntfile.js
Normal file
69
gruntfile.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
|
var pkg = grunt.file.readJSON('package.json');
|
||||||
|
|
||||||
|
var banner = [
|
||||||
|
'/**',
|
||||||
|
'* Ajax Autocomplete for jQuery, version ' + pkg.version,
|
||||||
|
'* (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',
|
||||||
|
'*/'].join('\n') + '\n';
|
||||||
|
|
||||||
|
// Project configuration.
|
||||||
|
grunt.initConfig({
|
||||||
|
pkg: pkg,
|
||||||
|
uglify: {
|
||||||
|
options: {
|
||||||
|
banner: banner
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
src: 'src/jquery.autocomplete.js',
|
||||||
|
dest: 'dist/jquery.autocomplete.min.js'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load the plugin that provides the "uglify" task.
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
|
||||||
|
// Default task(s).
|
||||||
|
grunt.registerTask('default', ['uglify']);
|
||||||
|
|
||||||
|
grunt.task.registerTask('build', 'Create release', function() {
|
||||||
|
var version = pkg.version
|
||||||
|
src = grunt.file.read('src/jquery.autocomplete.js').replace('%version%', version),
|
||||||
|
filePath = 'dist/jquery.autocomplete.js';
|
||||||
|
|
||||||
|
// Update not minimized release version:
|
||||||
|
console.log('Updating: ' + filePath);
|
||||||
|
grunt.file.write(filePath, src);
|
||||||
|
|
||||||
|
// Update plugin version:
|
||||||
|
filePath = 'devbridge-autocomplete.jquery.json';
|
||||||
|
src = grunt.file.readJSON(filePath);
|
||||||
|
|
||||||
|
if (src.version !== version){
|
||||||
|
src.version = version;
|
||||||
|
console.log('Updating: ' + filePath);
|
||||||
|
grunt.file.write(filePath, JSON.stringify(src, null, 4));
|
||||||
|
} else {
|
||||||
|
console.log('No updates for: ' + filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update bower version:
|
||||||
|
filePath = 'bower.json';
|
||||||
|
src = grunt.file.readJSON(filePath);
|
||||||
|
|
||||||
|
if (src.version !== version){
|
||||||
|
src.version = version;
|
||||||
|
console.log('Updating: ' + filePath);
|
||||||
|
grunt.file.write(filePath, JSON.stringify(src, null, 4));
|
||||||
|
} else {
|
||||||
|
console.log('No updates for: ' + filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
16
package.json
Normal file
16
package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "devbridge-autocomplete",
|
||||||
|
"version": "1.2.12",
|
||||||
|
"description": "Autocomplete provides suggestions while you type into the text field.",
|
||||||
|
"homepage": "https://github.com/devbridge/jQuery-Autocomplete",
|
||||||
|
"author": "Tomas Kirda (https://twitter.com/tkirda)",
|
||||||
|
"main": "dist/jquery.autocomplete.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jquery": ">=1.7"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "^0.4.5",
|
||||||
|
"grunt-contrib-uglify": "^0.5.1"
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ The standard jquery.autocomplete.js file is around 2.7KB when minified via Closu
|
|||||||
* Sets up autocomplete for input field(s).
|
* Sets up autocomplete for input field(s).
|
||||||
* `options`: An object literal which defines the settings to use for the autocomplete plugin.
|
* `options`: An object literal which defines the settings to use for the autocomplete plugin.
|
||||||
* `serviceUrl`: Server side URL or callback function that returns serviceUrl string. Optional if local lookup data is provided.
|
* `serviceUrl`: Server side URL or callback function that returns serviceUrl string. Optional if local lookup data is provided.
|
||||||
|
* `ajaxSettings`: Any additional [Ajax Settings](http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings) that configure the jQuery Ajax request.
|
||||||
* `lookup`: Lookup array for the suggestions. It may be array of strings or `suggestion` object literals.
|
* `lookup`: Lookup array for the suggestions. It may be array of strings or `suggestion` object literals.
|
||||||
* `suggestion`: An object literal with the following format: `{ value: 'string', data: any }`.
|
* `suggestion`: An object literal with the following format: `{ value: 'string', data: any }`.
|
||||||
* `lookupFilter`: `function (suggestion, query, queryLowerCase) {}` filter function for local lookups. By default it does partial string match (case insensitive).
|
* `lookupFilter`: `function (suggestion, query, queryLowerCase) {}` filter function for local lookups. By default it does partial string match (case insensitive).
|
||||||
@ -158,6 +159,11 @@ you can supply the "paramName" and "transformResult" options:
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
##Known Issues
|
||||||
|
|
||||||
|
If you use it with jQuery UI library it also has plugin named `autocomplete`. In this case you can use plugin alias `devbridgeAutocomplete`:
|
||||||
|
|
||||||
|
$('.autocomplete').devbridgeAutocomplete({ ... });
|
||||||
|
|
||||||
##License
|
##License
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ $(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Initialize autocomplete with local lookup:
|
// Initialize autocomplete with local lookup:
|
||||||
$('#autocomplete').autocomplete({
|
$('#autocomplete').devbridgeAutocomplete({
|
||||||
lookup: countriesArray,
|
lookup: countriesArray,
|
||||||
minChars: 0,
|
minChars: 0,
|
||||||
onSelect: function (suggestion) {
|
onSelect: function (suggestion) {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* Ajax Autocomplete for jQuery, version 1.2.9
|
* Ajax Autocomplete for jQuery, version %version%
|
||||||
* (c) 2013 Tomas Kirda
|
* (c) 2014 Tomas Kirda
|
||||||
*
|
*
|
||||||
* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
|
* 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
|
* For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*jslint browser: true, white: true, plusplus: true */
|
/*jslint browser: true, white: true, plusplus: true */
|
||||||
/*global define, window, document, jQuery */
|
/*global define, window, document, jQuery, exports */
|
||||||
|
|
||||||
// Expose plugin as an AMD module if AMD loader is present:
|
// Expose plugin as an AMD module if AMD loader is present:
|
||||||
(function (factory) {
|
(function (factory) {
|
||||||
@ -16,6 +15,9 @@
|
|||||||
if (typeof define === 'function' && define.amd) {
|
if (typeof define === 'function' && define.amd) {
|
||||||
// AMD. Register as an anonymous module.
|
// AMD. Register as an anonymous module.
|
||||||
define(['jquery'], factory);
|
define(['jquery'], factory);
|
||||||
|
} else if (typeof exports === 'object' && typeof require === 'function') {
|
||||||
|
// Browserify
|
||||||
|
factory(require('jquery'));
|
||||||
} else {
|
} else {
|
||||||
// Browser globals
|
// Browser globals
|
||||||
factory(jQuery);
|
factory(jQuery);
|
||||||
@ -53,6 +55,7 @@
|
|||||||
var noop = function () { },
|
var noop = function () { },
|
||||||
that = this,
|
that = this,
|
||||||
defaults = {
|
defaults = {
|
||||||
|
ajaxSettings: {},
|
||||||
autoSelectFirst: false,
|
autoSelectFirst: false,
|
||||||
appendTo: document.body,
|
appendTo: document.body,
|
||||||
serviceUrl: null,
|
serviceUrl: null,
|
||||||
@ -137,8 +140,7 @@
|
|||||||
suggestionSelector = '.' + that.classes.suggestion,
|
suggestionSelector = '.' + that.classes.suggestion,
|
||||||
selected = that.classes.selected,
|
selected = that.classes.selected,
|
||||||
options = that.options,
|
options = that.options,
|
||||||
container,
|
container;
|
||||||
noSuggestionsContainer;
|
|
||||||
|
|
||||||
// Remove autocomplete attribute to prevent native suggestions:
|
// Remove autocomplete attribute to prevent native suggestions:
|
||||||
that.element.setAttribute('autocomplete', 'off');
|
that.element.setAttribute('autocomplete', 'off');
|
||||||
@ -275,34 +277,37 @@
|
|||||||
if (orientation == 'auto') {
|
if (orientation == 'auto') {
|
||||||
var viewPortHeight = $(window).height(),
|
var viewPortHeight = $(window).height(),
|
||||||
scrollTop = $(window).scrollTop(),
|
scrollTop = $(window).scrollTop(),
|
||||||
top_overflow = -scrollTop + offset.top - containerHeight,
|
topOverflow = -scrollTop + offset.top - containerHeight,
|
||||||
bottom_overflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight);
|
bottomOverflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight);
|
||||||
|
|
||||||
if (Math.max(top_overflow, bottom_overflow) === top_overflow)
|
orientation = (Math.max(topOverflow, bottomOverflow) === topOverflow)
|
||||||
orientation = 'top';
|
? 'top'
|
||||||
else
|
: 'bottom';
|
||||||
orientation = 'bottom';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (orientation === 'top')
|
if (orientation === 'top') {
|
||||||
styles.top += -containerHeight;
|
styles.top += -containerHeight;
|
||||||
else
|
} else {
|
||||||
styles.top += height;
|
styles.top += height;
|
||||||
|
}
|
||||||
|
|
||||||
// If container is not positioned to body,
|
// If container is not positioned to body,
|
||||||
// correct its position using offset parent offset
|
// correct its position using offset parent offset
|
||||||
if(containerParent !== document.body) {
|
if(containerParent !== document.body) {
|
||||||
var opacity = $container.css('opacity'),
|
var opacity = $container.css('opacity'),
|
||||||
parentOffsetDiff;
|
parentOffsetDiff;
|
||||||
if (!that.visible)
|
|
||||||
$container.css('opacity', 0).show();
|
if (!that.visible){
|
||||||
|
$container.css('opacity', 0).show();
|
||||||
|
}
|
||||||
|
|
||||||
parentOffsetDiff = $container.offsetParent().offset();
|
parentOffsetDiff = $container.offsetParent().offset();
|
||||||
styles.top -= parentOffsetDiff.top;
|
styles.top -= parentOffsetDiff.top;
|
||||||
styles.left -= parentOffsetDiff.left;
|
styles.left -= parentOffsetDiff.left;
|
||||||
|
|
||||||
if (!that.visible)
|
if (!that.visible){
|
||||||
$container.css('opacity', opacity).hide();
|
$container.css('opacity', opacity).hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -2px to account for suggestions border.
|
// -2px to account for suggestions border.
|
||||||
@ -443,7 +448,7 @@
|
|||||||
query = that.getQuery(value),
|
query = that.getQuery(value),
|
||||||
index;
|
index;
|
||||||
|
|
||||||
if (that.selection) {
|
if (that.selection && that.currentValue !== query) {
|
||||||
that.selection = null;
|
that.selection = null;
|
||||||
(options.onInvalidateSelection || $.noop).call(that.element);
|
(options.onInvalidateSelection || $.noop).call(that.element);
|
||||||
}
|
}
|
||||||
@ -521,7 +526,8 @@
|
|||||||
options = that.options,
|
options = that.options,
|
||||||
serviceUrl = options.serviceUrl,
|
serviceUrl = options.serviceUrl,
|
||||||
params,
|
params,
|
||||||
cacheKey;
|
cacheKey,
|
||||||
|
ajaxSettings;
|
||||||
|
|
||||||
options.params[options.paramName] = q;
|
options.params[options.paramName] = q;
|
||||||
params = options.ignoreParams ? null : options.params;
|
params = options.ignoreParams ? null : options.params;
|
||||||
@ -546,12 +552,17 @@
|
|||||||
if (that.currentRequest) {
|
if (that.currentRequest) {
|
||||||
that.currentRequest.abort();
|
that.currentRequest.abort();
|
||||||
}
|
}
|
||||||
that.currentRequest = $.ajax({
|
|
||||||
|
ajaxSettings = {
|
||||||
url: serviceUrl,
|
url: serviceUrl,
|
||||||
data: params,
|
data: params,
|
||||||
type: options.type,
|
type: options.type,
|
||||||
dataType: options.dataType
|
dataType: options.dataType
|
||||||
}).done(function (data) {
|
};
|
||||||
|
|
||||||
|
$.extend(ajaxSettings, options.ajaxSettings);
|
||||||
|
|
||||||
|
that.currentRequest = $.ajax(ajaxSettings).done(function (data) {
|
||||||
var result;
|
var result;
|
||||||
that.currentRequest = null;
|
that.currentRequest = null;
|
||||||
result = options.transformResult(data);
|
result = options.transformResult(data);
|
||||||
@ -604,8 +615,7 @@
|
|||||||
noSuggestionsContainer = $(that.noSuggestionsContainer),
|
noSuggestionsContainer = $(that.noSuggestionsContainer),
|
||||||
beforeRender = options.beforeRender,
|
beforeRender = options.beforeRender,
|
||||||
html = '',
|
html = '',
|
||||||
index,
|
index;
|
||||||
width;
|
|
||||||
|
|
||||||
if (options.triggerSelectOnValidInput) {
|
if (options.triggerSelectOnValidInput) {
|
||||||
index = that.findSuggestionIndex(value);
|
index = that.findSuggestionIndex(value);
|
||||||
@ -723,10 +733,13 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
validateOrientation: function(orientation, fallback) {
|
validateOrientation: function(orientation, fallback) {
|
||||||
orientation = orientation.trim().toLowerCase();
|
orientation = $.trim(orientation || '').toLowerCase();
|
||||||
if(['auto', 'bottom', 'top'].indexOf(orientation) == '-1')
|
|
||||||
|
if($.inArray(orientation, ['auto', 'bottom', 'top']) === -1){
|
||||||
orientation = fallback;
|
orientation = fallback;
|
||||||
return orientation
|
}
|
||||||
|
|
||||||
|
return orientation;
|
||||||
},
|
},
|
||||||
|
|
||||||
processResponse: function (result, originalQuery, cacheKey) {
|
processResponse: function (result, originalQuery, cacheKey) {
|
||||||
@ -757,9 +770,9 @@
|
|||||||
activeItem,
|
activeItem,
|
||||||
selected = that.classes.selected,
|
selected = that.classes.selected,
|
||||||
container = $(that.suggestionsContainer),
|
container = $(that.suggestionsContainer),
|
||||||
children = container.children();
|
children = container.find('.' + that.classes.suggestion);
|
||||||
|
|
||||||
container.children('.' + selected).removeClass(selected);
|
container.find('.' + selected).removeClass(selected);
|
||||||
|
|
||||||
that.selectedIndex = index;
|
that.selectedIndex = index;
|
||||||
|
|
||||||
@ -889,7 +902,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create chainable jQuery plugin:
|
// Create chainable jQuery plugin:
|
||||||
$.fn.autocomplete = function (options, args) {
|
$.fn.autocomplete = $.fn.devbridgeAutocomplete = function (options, args) {
|
||||||
var dataKey = 'autocomplete';
|
var dataKey = 'autocomplete';
|
||||||
// If function invoked without argument return
|
// If function invoked without argument return
|
||||||
// instance of the first matched element:
|
// instance of the first matched element:
|
||||||
|
Loading…
Reference in New Issue
Block a user