2
0
mirror of https://github.com/devbridge/jQuery-Autocomplete.git synced 2025-03-21 08:52:21 +00:00

Merge pull request #208 from tttomekkk/master

Vertical orientation of suggestions. fixPosition and noSuggestionNotice developed.
This commit is contained in:
Tomas Kirda 2014-07-28 07:33:40 -05:00
commit a9e79277fb
2 changed files with 90 additions and 26 deletions

View File

@ -42,10 +42,14 @@ The standard jquery.autocomplete.js file is around 2.7KB when minified via Closu
* `paramName`: Default `query`. The name of the request parameter that contains the query.
* `transformResult`: `function(response, originalQuery) {}` called after the result of the query is ready. Converts the result into response.suggestions format.
* `autoSelectFirst`: if set to `true`, first item will be selected when showing suggestions. Default value `false`.
* `appendTo`: container where suggestions will be appended. Default value `body`. Can be jQuery object, selector or html element. Make sure to set `position: absolute` or `position: relative` for that element.
* `appendTo`: container where suggestions will be appended. Default value `document.body`. Can be jQuery object, selector or html element. Make sure to set `position: absolute` or `position: relative` for that element.
* `dataType`: type of data returned from server. Either 'text' (default) or 'jsonp', which will cause the autocomplete to use jsonp. You may return a json object in your callback when using jsonp.
* `showNoSuggestionNotice`: Default `false`. When no matching results, display a notification label.
* `noSuggestionNotice`: Default `No results`. Text for no matching results label.
* `noSuggestionNotice`: Default `No results`. Text or htmlString or Element or jQuery object for no matching results label.
* `forceFixPosition`: Default: `false`. Suggestions are automatically positioned when their container is appended to body (look at `appendTo` option), in other cases suggestions are rendered but no positioning is applied.
Set this option to force auto positioning in other cases.
* `orientation`: Default `bottom`. Vertical orientation of the displayed suggestions, available values are `auto`, `top`, `bottom`.
If set to `auto`, the suggestions will be orientated it the way that place them closer to middle of the view port.
Autocomplete instance has following methods:

View File

@ -54,7 +54,7 @@
that = this,
defaults = {
autoSelectFirst: false,
appendTo: 'body',
appendTo: document.body,
serviceUrl: null,
lookup: null,
onSelect: null,
@ -85,7 +85,9 @@
return typeof response === 'string' ? $.parseJSON(response) : response;
},
showNoSuggestionNotice: false,
noSuggestionNotice: 'No results'
noSuggestionNotice: 'No results',
orientation: 'bottom',
forceFixPosition: false
};
// Shared variables:
@ -101,6 +103,7 @@
that.onChange = null;
that.isLocal = false;
that.suggestionsContainer = null;
that.noSuggestionsContainer = null;
that.options = $.extend({}, defaults, options);
that.classes = {
selected: 'autocomplete-selected',
@ -134,7 +137,8 @@
suggestionSelector = '.' + that.classes.suggestion,
selected = that.classes.selected,
options = that.options,
container;
container,
noSuggestionsContainer;
// Remove autocomplete attribute to prevent native suggestions:
that.element.setAttribute('autocomplete', 'off');
@ -146,6 +150,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);
container = $(that.suggestionsContainer);
@ -173,8 +181,6 @@
that.select($(this).data('index'));
});
that.fixPosition();
that.fixPositionCapture = function () {
if (that.visible) {
that.fixPosition();
@ -214,6 +220,8 @@
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',
@ -222,6 +230,7 @@
});
},
clearCache: function () {
this.cachedResponse = {};
this.badQueries = [];
@ -246,27 +255,62 @@
},
fixPosition: function () {
var that = this,
offset,
styles;
// Use only when container has already its content
// Don't adjsut position if custom container has been specified:
if (that.options.appendTo !== 'body') {
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(),
top_overflow = -scrollTop + offset.top - containerHeight,
bottom_overflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight);
if (Math.max(top_overflow, bottom_overflow) === top_overflow)
orientation = 'top';
else
orientation = 'bottom';
}
offset = that.el.offset();
if (orientation === 'top')
styles.top += -containerHeight;
else
styles.top += height;
styles = {
top: (offset.top + that.el.outerHeight()) + 'px',
left: offset.left + 'px'
};
// 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';
}
$(that.suggestionsContainer).css(styles);
$container.css(styles);
},
enableKillerFn: function () {
@ -557,6 +601,7 @@
className = that.classes.suggestion,
classSelected = that.classes.selected,
container = $(that.suggestionsContainer),
noSuggestionsContainer = $(that.noSuggestionsContainer),
beforeRender = options.beforeRender,
html = '',
index,
@ -577,6 +622,7 @@
this.adjustContainerWidth();
noSuggestionsContainer.detach();
container.html(html);
// Select first value by default:
@ -589,6 +635,8 @@
beforeRender.call(that.element, container);
}
that.fixPosition();
container.show();
that.visible = true;
@ -597,14 +645,19 @@
noSuggestions: function() {
var that = this,
container = $(that.suggestionsContainer),
html = '',
width;
html += '<div class="autocomplete-no-suggestion">' + this.options.noSuggestionNotice + '</div>';
container = $(that.suggestionsContainer),
noSuggestionsContainer = $(that.noSuggestionsContainer);
this.adjustContainerWidth();
container.html(html);
// 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;
},
@ -613,7 +666,7 @@
var that = this,
options = that.options,
width,
container = $(that.suggestionsContainer)
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.
@ -669,6 +722,13 @@
return suggestions;
},
validateOrientation: function(orientation, fallback) {
orientation = orientation.trim().toLowerCase();
if(['auto', 'bottom', 'top'].indexOf(orientation) == '-1')
orientation = fallback;
return orientation
},
processResponse: function (result, originalQuery, cacheKey) {
var that = this,
options = that.options;
@ -829,7 +889,7 @@
};
// Create chainable jQuery plugin:
$.fn.autocomplete = function (options, args) {
$.fn.autocomplete = function (options, args) {
var dataKey = 'autocomplete';
// If function invoked without argument return
// instance of the first matched element: