combojs
Version:
A combobox for intelligent, responsive search and filtering.
1,058 lines (960 loc) • 35.1 kB
JavaScript
// Generated by CoffeeScript 1.12.0
(function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
hasProp = {}.hasOwnProperty,
slice = [].slice,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
(function($, window) {
var Combo, setters;
Combo = (function() {
var evaluate;
Combo.prototype.maxHeight = 300;
Combo.prototype.pageSize = 10;
Combo.prototype.expandOnFocus = false;
Combo.prototype.selectOnTab = true;
Combo.prototype.tabIndex = null;
Combo.prototype.forceNonEmpty = false;
Combo.prototype.forceSelectionFromList = false;
Combo.prototype.keepListOpen = false;
Combo.prototype.emptyListText = '(ingen valgmuligheder)';
Combo.prototype.forceAllOnButtonClick = true;
Combo.prototype.matchBy = 'inText';
Combo.prototype.onlyShowEnabled = false;
Combo.prototype.spellcheck = false;
Combo.prototype.valueField = 'id';
Combo.prototype.titleField = null;
Combo.prototype.displayField = 'text';
Combo.prototype.litraField = null;
Combo.prototype.enabledField = function() {
return true;
};
Combo.prototype.modifiers = [];
Combo.prototype.specifications = [];
Combo.prototype.placeholder = "";
Combo.prototype.showUnmatchedRawValue = false;
Combo.prototype.classNameOnEmpty = false;
Combo.prototype.label = null;
Combo.prototype.source = [];
Combo.prototype.secondarySource = [];
Combo.prototype.disabled = false;
Combo.prototype.activeLi = null;
Combo.prototype.isExpanded = false;
Combo.prototype.inputLabel = null;
Combo.prototype.key = {
DOWN: 40,
END: 35,
ENTER: 13,
ESCAPE: 27,
HOME: 36,
INSERT: 45,
LEFT: 37,
PAGE_DOWN: 34,
PAGE_UP: 33,
RIGHT: 39,
SPACE: 32,
TAB: 9,
UP: 38,
BACKSPACE: 8,
DELETE: 46,
NUMPAD_ENTER: 108
};
function Combo(wrapper, options) {
var key, value;
if (options == null) {
options = {};
}
this.enable = bind(this.enable, this);
this.disable = bind(this.disable, this);
this.collapse = bind(this.collapse, this);
this.internalCollapse = bind(this.internalCollapse, this);
this.expand = bind(this.expand, this);
this.scrollIntoView = bind(this.scrollIntoView, this);
this.lastItemIsActive = bind(this.lastItemIsActive, this);
this.firstItemIsActive = bind(this.firstItemIsActive, this);
this.highlightValue = bind(this.highlightValue, this);
this.renderItem = bind(this.renderItem, this);
this.renderItems = bind(this.renderItems, this);
this.renderList = bind(this.renderList, this);
this.renderFullList = bind(this.renderFullList, this);
this.renderFilteredList = bind(this.renderFilteredList, this);
this.searchAndExpand = bind(this.searchAndExpand, this);
this.activateSelectedItem = bind(this.activateSelectedItem, this);
this.focus = bind(this.focus, this);
this.suppressNextBlur = bind(this.suppressNextBlur, this);
this.updateLastSelection = bind(this.updateLastSelection, this);
this.onBlur = bind(this.onBlur, this);
this.onFocus = bind(this.onFocus, this);
this.onMouseUp = bind(this.onMouseUp, this);
this.onKeyUp = bind(this.onKeyUp, this);
this.onKeyDown = bind(this.onKeyDown, this);
this.onButtonClick = bind(this.onButtonClick, this);
this.onListMouseDown = bind(this.onListMouseDown, this);
this.onListClick = bind(this.onListClick, this);
this.selectLi = bind(this.selectLi, this);
this.isEmpty = bind(this.isEmpty, this);
this.getRawValue = bind(this.getRawValue, this);
this.getValue = bind(this.getValue, this);
this.getSelectedItemAndIndex = bind(this.getSelectedItemAndIndex, this);
this.getSelectedIndex = bind(this.getSelectedIndex, this);
this.getSelectedItem = bind(this.getSelectedItem, this);
this.getSelectedValue = bind(this.getSelectedValue, this);
this.selectItem = bind(this.selectItem, this);
this.setValue = bind(this.setValue, this);
this.itemTitle = bind(this.itemTitle, this);
this.itemDisplay = bind(this.itemDisplay, this);
this.itemEnabled = bind(this.itemEnabled, this);
this.itemLitra = bind(this.itemLitra, this);
this.itemValue = bind(this.itemValue, this);
for (key in options) {
if (!hasProp.call(options, key)) continue;
value = options[key];
if (value != null) {
this[key] = value;
}
}
if (this.forceSelectionFromList && this.showUnmatchedRawValue) {
throw new Error('invalid configuration, forceSelectionFromList and showUnmatchedRawValue cannot both be true');
}
this.el = $(wrapper).addClass("combo-container").on('click', '.combo-list li', this.onListClick);
this.input = $("<input type='text' class='combo-input' autocomplete='off' disabled='disabled' spellcheck='" + this.spellcheck + "' placeholder='" + this.placeholder + "' " + (this.tabIndex != null ? "tabindex='" + this.tabIndex + "'" : "") + " />").bind({
keydown: this.onKeyDown,
keyup: this.onKeyUp,
mouseup: this.onMouseUp,
focus: _.throttle(this.onFocus, 0),
blur: this.onBlur
}).appendTo(this.el);
this.button = $('<button class="combo-button" tabindex="-1" disabled="disabled" />').bind({
click: this.onButtonClick,
mousedown: this.suppressNextBlur
}).appendTo(this.el);
this.list = $('<ul class="combo-list"/>').css({
maxHeight: this.maxHeight
}).bind({
mousedown: this.onListMouseDown
}).appendTo(this.el).hide();
if (!_.isEmpty(this.source) || !_.isEmpty(this.secondarySource)) {
this.link(this.source, this.secondarySource);
}
if (!this.disabled) {
this.enable();
}
this.updateClassNames();
this;
}
Combo.prototype.link = function(source, secondarySource) {
if (secondarySource == null) {
secondarySource = [];
}
this.source = source;
this.secondarySource = secondarySource;
this.ensureSelection();
this.lastQuery = this.input.val();
this.input.trigger('linked');
return this;
};
Combo.prototype.itemValue = function(item) {
if (item.__isRawValueItem) {
return null;
} else {
return evaluate(this.valueField, item);
}
};
Combo.prototype.itemLitra = function(item) {
if (item.__isRawValueItem) {
return null;
} else {
return evaluate(this.litraField, item);
}
};
Combo.prototype.itemEnabled = function(item) {
if (item.__isRawValueItem) {
return true;
} else {
return evaluate(this.enabledField, item);
}
};
Combo.prototype.itemDisplay = function(item) {
if (item.__isRawValueItem) {
return item.__rawValue;
} else {
return evaluate(this.displayField, item);
}
};
Combo.prototype.itemTitle = function(item) {
var ref;
if (item.__isRawValueItem) {
return item.__rawValue;
} else {
return this.stripMarkup((ref = evaluate(this.titleField, item)) != null ? ref : this.itemDisplay(item));
}
};
Combo.prototype.itemModifier = function(modifier) {
return (function(_this) {
return function(item) {
if (item.__isRawValueItem) {
return null;
} else {
return evaluate(modifier.field, item);
}
};
})(this);
};
Combo.prototype.itemSpecification = function(specification) {
return (function(_this) {
return function(item) {
if (item.__isRawValueItem) {
return null;
} else {
return evaluate(specification.field, item);
}
};
})(this);
};
Combo.prototype.setValue = function(value) {
var i, item, j, len, len1, ref, ref1;
this.updateInputLabel();
if (this.input.val() === value) {
return;
}
ref = this.source;
for (i = 0, len = ref.length; i < len; i++) {
item = ref[i];
if (!(this.itemValue(item) === value)) {
continue;
}
this.selectItem(item, {
forced: true
});
return;
}
ref1 = this.secondarySource;
for (j = 0, len1 = ref1.length; j < len1; j++) {
item = ref1[j];
if (!(this.itemValue(item) === value)) {
continue;
}
this.selectItem(item, {
forced: true
});
return;
}
this.input.val(value);
return this.updateClassNames();
};
Combo.prototype.selectItem = function(item, options) {
if (options == null) {
options = {};
}
if (!this.itemEnabled(item) && !options.forced) {
return;
}
if (!item.__isRawValueItem && this.input.val() === this.itemTitle(item)) {
this.internalCollapse();
return;
}
this.input.val(this.itemTitle(item));
this.updateClassNames();
this.lastQuery = this.input.val();
this.updateLastSelection();
this.internalCollapse();
return _.delay(((function(_this) {
return function() {
return _this.input.trigger('itemSelect', item);
};
})(this)), 10);
};
Combo.prototype.getSelectedValue = function() {
var item, ref;
item = (ref = this.getSelectedItemAndIndex()) != null ? ref.item : void 0;
if (item != null) {
return this.itemValue(item);
} else {
return null;
}
};
Combo.prototype.getSelectedItem = function() {
var ref;
return (ref = this.getSelectedItemAndIndex()) != null ? ref.item : void 0;
};
Combo.prototype.getSelectedIndex = function() {
var ref;
return (ref = this.getSelectedItemAndIndex()) != null ? ref.index : void 0;
};
Combo.prototype.getSelectedItemAndIndex = function() {
var i, index, item, j, len, len1, ref, ref1;
ref = this.source;
for (index = i = 0, len = ref.length; i < len; index = ++i) {
item = ref[index];
if (this.itemTitle(item) === this.input.val()) {
return {
item: item,
index: index
};
}
}
ref1 = this.secondarySource;
for (index = j = 0, len1 = ref1.length; j < len1; index = ++j) {
item = ref1[index];
if (this.itemTitle(item) === this.input.val()) {
return {
item: item,
index: index + this.source.length
};
}
}
};
Combo.prototype.hasSelection = function() {
return this.getSelectedItemAndIndex() != null;
};
Combo.prototype.getValue = function() {
var ref;
return (ref = this.getSelectedValue()) != null ? ref : this.getRawValue();
};
Combo.prototype.getRawValue = function() {
return this.input.val();
};
Combo.prototype.isEmpty = function() {
return this.input.val() === null || this.input.val().trim() === '';
};
Combo.prototype.selectLi = function(li) {
var comboId;
comboId = $(li).data('combo-id');
if (comboId === 'emptylist-item') {
this.internalCollapse();
return;
}
if (this.source[comboId] != null) {
this.selectItem(this.source[comboId]);
} else if (this.secondarySource[comboId - this.source.length] != null) {
this.selectItem(this.secondarySource[comboId - this.source.length]);
} else if (this.showUnmatchedRawValue) {
this.selectItem({
__isRawValueItem: true,
__rawValue: this.stripMarkup(this.getRawValue())
});
} else {
this.selectItem(null);
}
return this.refocus();
};
Combo.prototype.onListClick = function(event) {
return this.selectLi(event.currentTarget);
};
Combo.prototype.onListMouseDown = function(event) {
this.suppressNextBlur();
if (!$(event.target).closest('ul.combo-list li').length) {
return this.refocus();
}
};
Combo.prototype.onButtonClick = function(event) {
if (this.disabled) {
return;
}
if (this.isExpanded && $('li', this.list).length) {
this.internalCollapse();
} else {
this.searchAndExpand({
forceAll: this.forceAllOnButtonClick
});
}
return this.focus();
};
Combo.prototype.onKeyDown = function(event) {
if (this.disabled) {
return;
}
if (this.isExpanded) {
switch (event.keyCode) {
case this.key.HOME:
return this.moveHome() && event.preventDefault();
case this.key.END:
return this.moveEnd() && event.preventDefault();
case this.key.PAGE_UP:
this.movePreviousPage();
return event.preventDefault();
case this.key.PAGE_DOWN:
this.moveNextPage();
return event.preventDefault();
case this.key.UP:
this.movePrevious();
return event.preventDefault();
case this.key.DOWN:
this.moveNext();
return event.preventDefault();
case this.key.ENTER:
case this.key.NUMPAD_ENTER:
if (this.activeLi) {
this.selectLi(this.activeLi);
}
event.preventDefault();
return event.stopPropagation();
case this.key.TAB:
if (this.selectOnTab) {
if (this.activeLi) {
this.selectLi(this.activeLi);
}
event.preventDefault();
return event.stopPropagation();
}
break;
case this.key.ESCAPE:
return this.internalCollapse();
}
} else {
switch (event.keyCode) {
case this.key.PAGE_UP:
case this.key.PAGE_DOWN:
case this.key.UP:
case this.key.DOWN:
this.searchAndExpand();
return event.preventDefault();
case this.key.ENTER:
this.input.trigger('enterpress');
return event.preventDefault();
case this.key.ESCAPE:
return this.input.select();
}
}
};
Combo.prototype.onKeyUp = function(event) {
if (this.disabled) {
return;
}
this.updateClassNames();
this.updateInputLabel();
this.updateLastSelection();
if (this.lastQuery === this.input.val()) {
return;
}
switch (event.keyCode) {
case this.key.BACKSPACE:
case this.key.DELETE:
case this.key.ENTER:
if (!this.isExpanded) {
return;
}
}
return this.searchAndExpand();
};
Combo.prototype.onMouseUp = function() {
if (this.disabled) {
return;
}
return this.updateLastSelection();
};
Combo.prototype.onFocus = function(event, data) {
clearTimeout(this.closing);
if (this.disabled) {
return;
}
if (!(data != null ? data.forcedFocus : void 0)) {
this.input.trigger('enter');
if (this.expandOnFocus) {
this.searchAndExpand();
}
return _.defer((function(_this) {
return function() {
return _this.input.select();
};
})(this));
}
};
Combo.prototype.onBlur = function(event) {
if (this.disabled || this.blurIsSuppressed) {
this.blurIsSuppressed = false;
return;
}
this.ensureSelection();
this.internalCollapse();
return this.input.trigger('leave');
};
Combo.prototype.ensureSelection = function() {
if (this.hasSelection()) {
return;
}
if (this.isEmpty() && this.forceNonEmpty) {
if (this.lastSelection != null) {
return this.selectItem(this.lastSelection.item);
}
if (this.source.length) {
return this.selectItem(this.source[0]);
}
if (this.secondarySource.length) {
return this.selectItem(this.secondarySource[0]);
}
throw new Error("consistency error: forceNonEmpty require forced item selection but no items can be selected! (either list is empty or all items are disabled)");
}
if (!this.isEmpty() && this.forceSelectionFromList) {
if (this.lastSelection != null) {
return this.selectItem(this.lastSelection.item);
}
this.input.val('');
this.updateClassNames();
return this.lastSelection = null;
}
};
Combo.prototype.updateLastSelection = function() {
var currentSelection;
if (!this.forceSelectionFromList) {
return;
}
currentSelection = this.getSelectedItemAndIndex();
if (currentSelection != null) {
return this.lastSelection = currentSelection;
}
};
Combo.prototype.suppressNextBlur = function() {
if (this.input.is(':focus')) {
return this.blurIsSuppressed = true;
}
};
Combo.prototype.refocus = function() {
return _.delay(((function(_this) {
return function() {
if (!_this.input.is(':focus')) {
return _this.input.trigger('focus', {
forcedFocus: true
});
}
};
})(this)), 1);
};
Combo.prototype.focus = function() {
return _.delay(((function(_this) {
return function() {
if (!_this.input.is(':focus')) {
return _this.input.trigger('focus');
}
};
})(this)), 1);
};
Combo.prototype.activateSelectedItem = function() {
var i, index, len, li, ref, results;
index = this.getSelectedIndex();
if (index == null) {
return;
}
ref = this.list.children();
results = [];
for (i = 0, len = ref.length; i < len; i++) {
li = ref[i];
if (!($(li).data('combo-id') === index)) {
continue;
}
this.activate($(li));
results.push($(li).addClass('selected'));
}
return results;
};
Combo.prototype.stripMarkup = function(text) {
return text != null ? text.replace(/<br[^>]*>/g, " | ").replace(/<.*?>/g, '').replace(/[\n\r]/g, '') : void 0;
};
Combo.prototype.searchAndExpand = function(options) {
if (options == null) {
options = {};
}
this.lastQuery = this.input.val();
if (this.hasSelection() || options.forceAll) {
this.renderFullList();
this.activateSelectedItem();
this.expand(options);
return;
}
this.renderFilteredList();
this.activate($('li:first', this.list));
return this.expand();
};
Combo.prototype.buildFilters = function(queryString) {
var currentWord, dontSearchInsideTags, filters, first, firstChar, i, j, k, len, len1, len2, modifier, queryStringSplit, ref, ref1, specFinder, specification, specsInQuery;
filters = [];
queryString = queryString.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
queryString = queryString.replace(/([<>])/g, "");
firstChar = queryString.substr(0, 1);
ref = this.modifiers;
for (i = 0, len = ref.length; i < len; i++) {
modifier = ref[i];
if (firstChar === modifier.modifier) {
filters.push({
getter: this.itemModifier(modifier),
predicate: function(value) {
return value;
}
});
queryString = queryString.substr(1);
}
}
ref1 = this.specifications;
for (j = 0, len1 = ref1.length; j < len1; j++) {
specification = ref1[j];
specFinder = new RegExp(specification.alias + ":\\s*(\\w+)");
specsInQuery = specFinder.exec(queryString);
if (specsInQuery) {
filters.push({
getter: this.itemSpecification(specification),
predicate: function(value) {
return value === specsInQuery[1];
}
});
queryString = queryString.replace(specFinder, "");
}
}
queryStringSplit = queryString.split(" ");
if (((this.litraField != null) != null) && queryString.match(/^[#,]\w[\w\\\.,]*(\s|$)/)) {
first = queryStringSplit.shift();
filters.push({
getter: this.itemLitra,
regex: new RegExp("^()(" + first.substr(1).replace(/,/g, "\\.") + ")", "i"),
predicate: function(value) {
return this.regex.test(value);
}
});
}
for (k = 0, len2 = queryStringSplit.length; k < len2; k++) {
currentWord = queryStringSplit[k];
if (!(currentWord !== "")) {
continue;
}
currentWord = currentWord.replace(/\\\*/g, "[\\wæøåÆØÅ]*");
currentWord = currentWord.replace(/\\\+/g, " ");
dontSearchInsideTags = "(?![^><\\[\\]]*(>|\\]))";
switch (this.matchBy) {
case "none":
break;
case "inText":
filters.push({
getter: this.itemDisplay,
regex: new RegExp("()(" + currentWord + ")()" + dontSearchInsideTags, "i"),
predicate: function(value) {
return this.regex.test(value);
}
});
break;
case "firstInText":
filters.push({
getter: this.itemDisplay,
regex: new RegExp("^()(" + currentWord + ")()" + dontSearchInsideTags, "i"),
predicate: function(value) {
return this.regex.test(value);
}
});
break;
case "firstInWord":
filters.push({
getter: this.itemDisplay,
regex: new RegExp("(^|[^\\wæøåÆØÅ\\[\\]])(" + currentWord + ")()" + dontSearchInsideTags, "i"),
predicate: function(value) {
return this.regex.test(value);
}
});
break;
case "wholeWord":
filters.push({
getter: this.itemDisplay,
regex: new RegExp("(^|[^\\wæøåÆØÅ\\[\\]])(" + currentWord + ")($|[^\\wæøåÆØÅ\\[\\]])", "i"),
predicate: function(value) {
return this.regex.test(value);
}
});
break;
default:
throw new Error("matchBy not set to a valid value");
}
}
return filters;
};
Combo.prototype.renderFilteredList = function() {
var filters;
filters = this.input.val() === '' ? [] : this.buildFilters(this.input.val());
return this.renderList(this.source, this.secondarySource, filters);
};
Combo.prototype.renderFullList = function() {
return this.renderList(this.source, this.secondarySource);
};
Combo.prototype.renderList = function(items, secondaryItems, filters) {
var htmls, rawValue;
if (secondaryItems == null) {
secondaryItems = [];
}
if (filters == null) {
filters = [];
}
htmls = [];
if (this.showUnmatchedRawValue) {
rawValue = this.stripMarkup(this.getRawValue());
if (rawValue !== "" && !this.hasSelection()) {
if ((typeof this.label === "function" ? this.label(null, this.getRawValue()) : void 0) != null) {
htmls.push("<li class='unmatched-raw-value " + "has-label" + "'>" + rawValue + " " + (this.createLabel()) + "</li>");
} else {
htmls.push("<li class='unmatched-raw-value'>" + rawValue + "</li>");
}
}
}
htmls.push.apply(htmls, this.renderItems(items, filters));
htmls.push.apply(htmls, this.renderItems(secondaryItems, filters, 'secondary-source', items.length));
if (htmls.length) {
this.list.html(htmls.join(''));
return this.list.find('.secondary-source').first().addClass('first');
} else {
return this.list.html("<li class='disabled' data-combo-id='emptylist-item'>" + this.emptyListText + "</li>");
}
};
Combo.prototype.renderItems = function(items, filters, className, itemOffset) {
var i, index, item, len, results;
if (className == null) {
className = '';
}
if (itemOffset == null) {
itemOffset = 0;
}
results = [];
for (index = i = 0, len = items.length; i < len; index = ++i) {
item = items[index];
if (this.onlyShowEnabled && !this.itemEnabled(item)) {
continue;
}
if (!_.all(filters, function(filter) {
return filter.predicate(filter.getter(item));
})) {
continue;
}
results.push(this.renderItem(item, index + itemOffset, filters, className));
}
return results;
};
Combo.prototype.renderItem = function(item, index, filters, className) {
var classes, litra, text;
if ((this.litraField != null) && ((litra = this.itemLitra(item)) != null)) {
text = "[" + litra + "] " + (this.highlightValue(item, filters));
} else {
text = this.highlightValue(item, filters);
}
classes = [className, this.onlyShowEnabled || this.itemEnabled(item) ? 'enabled' : 'disabled', (typeof this.label === "function" ? this.label(item, this.getRawValue()) : void 0) != null ? "has-label" : ""];
if (this.createLabel(item) !== "") {
return "<li data-combo-id=\"" + index + "\" class=\"" + (classes.join(' ')) + "\">" + text + " " + (this.createLabel(item)) + "</li>";
} else {
return "<li data-combo-id=\"" + index + "\" class=\"" + (classes.join(' ')) + "\">" + text + "</li>";
}
};
Combo.prototype.highlightValue = function(item, filters) {
var filter, i, len, value;
value = this.itemDisplay(item);
if (value == null) {
return null;
}
for (i = 0, len = filters.length; i < len; i++) {
filter = filters[i];
if (filter.getter === this.itemDisplay && (filter.regex != null)) {
value = value.replace(filter.regex, "<b>$2</b>");
}
}
return value;
};
Combo.prototype.moveNext = function() {
if (this.activeLi) {
if (!this.lastItemIsActive()) {
return this.activate(this.activeLi.next());
}
} else {
return this.moveHome();
}
};
Combo.prototype.movePrevious = function() {
if (this.activeLi) {
if (!this.firstItemIsActive()) {
return this.activate(this.activeLi.prev());
}
} else {
return this.moveEnd();
}
};
Combo.prototype.moveNextPage = function() {
var rest;
if (!this.activeLi) {
this.moveHome();
}
rest = this.activeLi.nextAll();
if (rest.length >= this.pageSize) {
return this.activate(rest.eq(this.pageSize - 1));
} else {
return this.moveEnd();
}
};
Combo.prototype.movePreviousPage = function() {
var rest;
if (!this.activeLi) {
this.activate($('li:last', this.list));
}
rest = this.activeLi.prevAll();
if (rest.length >= this.pageSize) {
return this.activate(rest.eq(this.pageSize - 1));
} else {
return this.moveHome();
}
};
Combo.prototype.moveHome = function() {
return this.activate($('li:first', this.list));
};
Combo.prototype.moveEnd = function() {
return this.activate($('li:last', this.list));
};
Combo.prototype.activate = function(item) {
var ref;
if ((ref = this.activeLi) != null) {
ref.removeClass('active');
}
if ((item != null) && item.length) {
item.addClass('active');
this.activeLi = item;
this.scrollIntoView();
} else {
this.activeLi = null;
}
return this.activeLi;
};
Combo.prototype.firstItemIsActive = function() {
var ref;
return ((ref = this.activeLi) != null ? ref[0] : void 0) === $("li:first", this.list)[0];
};
Combo.prototype.lastItemIsActive = function() {
var ref;
return ((ref = this.activeLi) != null ? ref[0] : void 0) === $('li:last', this.list)[0];
};
Combo.prototype.scrollIntoView = function() {
var currentScroll, hasScroll, itemHeight, itemOffset, listHeight, listTopBorder, listTopPadding, scroll;
if (!(this.isExpanded && this.activeLi)) {
return;
}
if (this.firstItemIsActive()) {
if (this.list[0].scrollTop > 0) {
this.list.scrollTop(0);
}
return;
}
hasScroll = this.list.prop('scrollHeight') > this.maxHeight;
if (hasScroll) {
listTopBorder = parseFloat($.css(this.list[0], 'borderTopWidth')) || 0;
listTopPadding = parseFloat($.css(this.list[0], 'paddingTop')) || 0;
itemOffset = this.activeLi.offset().top - this.list.offset().top - listTopBorder - listTopPadding;
listHeight = this.maxHeight;
currentScroll = this.list.scrollTop();
itemHeight = this.activeLi.outerHeight();
scroll = itemOffset < 0 ? currentScroll + itemOffset : itemOffset + itemHeight > listHeight ? currentScroll + itemOffset - listHeight + itemHeight : void 0;
return this.list.scrollTop(scroll);
}
};
Combo.prototype.expand = function(options) {
if (options == null) {
options = {};
}
if (this.disabled) {
return;
}
if (this.isExpanded) {
return;
}
this.el.addClass('expanded');
this.isExpanded = true;
this.list.show(options.callback);
this.scrollIntoView();
return this.updateInputLabel();
};
Combo.prototype.internalCollapse = function() {
if (this.keepListOpen) {
return this.searchAndExpand();
} else {
return this.collapse();
}
};
Combo.prototype.collapse = function(options) {
if (options == null) {
options = {};
}
this.el.removeClass('expanded');
this.isExpanded = false;
this.list.hide(options.callback);
return this.updateInputLabel();
};
Combo.prototype.disable = function() {
this.disabled = true;
this.input.attr({
disabled: true
});
return this.button.attr({
disabled: true
});
};
Combo.prototype.enable = function() {
this.disabled = false;
this.input.attr({
disabled: false
});
return this.button.attr({
disabled: false
});
};
evaluate = function(fieldGetter, item) {
if (fieldGetter == null) {
return null;
} else if (_.isFunction(fieldGetter)) {
return fieldGetter(item);
} else if (_.isFunction(item[fieldGetter])) {
return item[fieldGetter]();
} else {
return item[fieldGetter];
}
};
Combo.prototype.updateClassNames = function() {
if (this.classNameOnEmpty) {
return this.input.toggleClass(this.classNameOnEmpty, !this.getRawValue());
}
};
Combo.prototype.createLabel = function(item) {
var label;
label = typeof this.label === "function" ? this.label(item, this.getRawValue()) : void 0;
if (label != null) {
return "<span class='" + label.className + "'>" + label.text + "</span>";
} else {
return "";
}
};
Combo.prototype.updateInputLabel = function() {
var label;
label = this.createLabel(this.getSelectedItem());
if ((this.inputLabel != null) && (this.isExpanded || label === "")) {
this.inputLabel.remove();
this.inputLabel = null;
return this.el.removeClass('has-label');
} else if (this.inputLabel === null && !this.isExpanded && label !== "") {
this.inputLabel = $(label).insertAfter(this.input);
return this.el.addClass('has-label');
}
};
return Combo;
})();
setters = ["link", "renderFullList"];
return $.fn.extend({
combo: function() {
var args, option, value;
option = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
value = this;
this.each(function() {
var $this, _value, data, plugin;
$this = $(this);
plugin = $this.data('combo');
if (!plugin) {
return $this.data('combo', (data = new Combo(this, option)));
} else if (typeof option === 'string') {
if (!option in plugin) {
throw new Error("Unknown combo method " + option);
}
_value = plugin[option].apply(plugin, args);
if (!(indexOf.call(setters, option) >= 0)) {
return value = _value;
}
}
});
return value;
}
});
})(window.jQuery || require('jquery')(window), window);
}).call(this);