assets/js/romo/select_dropdown.js in romo-0.17.0 vs assets/js/romo/select_dropdown.js in romo-0.17.1
- old
+ new
@@ -3,18 +3,21 @@
return new RomoSelectDropdown(element, optionElemsParent);
});
}
var RomoSelectDropdown = function(element, optionElemsParent) {
- this.elem = $(element);
- this.itemSelector = 'LI[data-romo-select-item="opt"]:not(.disabled)';
- this.prevValue = '';
+ this.elem = $(element);
+ this.prevValue = '';
- var optsParent = (optionElemsParent || this.elem.find('.romo-select-dropdown-options-parent'));
- this.optionElems = optsParent.children();
- this.optionList = this._buildOptionList(this.optionElems);
+ this.filterHiddenClass = 'romo-select-filter-hidden';
+ this.itemSelector = 'LI[data-romo-select-item="opt"]:not(.disabled):not(.'+this.filterHiddenClass+')';
+ var optsParent = (optionElemsParent || this.elem.find('.romo-select-dropdown-options-parent'));
+ this.optionElems = optsParent.children();
+ this.optionList = this._buildOptionList(this.optionElems);
+ this.optionFilter = undefined;
+
this.doInit();
this.doBindDropdown();
if (this.elem.attr('id') !== undefined) {
$('label[for="'+this.elem.attr('id')+'"]').on('click', $.proxy(function(e) {
@@ -42,19 +45,14 @@
RomoSelectDropdown.prototype.doBindDropdown = function() {
this.romoDropdown = this.elem.romoDropdown()[0];
this.romoDropdown.doSetPopupZIndex(this.elem);
this.romoDropdown.bodyElem.addClass('romo-select-option-list');
+
this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(this.onPopupOpen, this));
this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(this.onPopupClose, this));
- this.romoDropdown.elem.on('blur', $.proxy(function(e) {
- this.blurTimeoutId = setTimeout($.proxy(function() {
- if (this.popupMouseDown !== true) {
- this.romoDropdown.elem.trigger('dropdown:triggerPopupClose', []);
- }
- }, this), 10);
- }, this));
+
this.romoDropdown.elem.on('keydown', $.proxy(this.onElemKeyDown, this));
this.romoDropdown.popupElem.on('keydown', $.proxy(this.onElemKeyDown, this));
this.romoDropdown.elem.on('dropdown:toggle', $.proxy(function(e, dropdown) {
this.elem.trigger('selectDropdown:dropdown:toggle', [dropdown, this]);
@@ -75,29 +73,138 @@
this.elem.on('selectDropdown:triggerPopupClose', $.proxy(function(e) {
this.romoDropdown.elem.trigger('dropdown:triggerPopupClose', []);
}, this));
this.romoDropdown.bodyElem.html('');
+
+ if (this.elem.data('romo-select-dropdown-no-filter') !== true) {
+ this.optionFilter = this._buildOptionFilter();
+ var optionFilterWrapper = $('<div class="romo-select-dropdown-option-filter-wrapper"></div>');
+ optionFilterWrapper.append(this.optionFilter);
+ this.romoDropdown.popupElem.prepend(optionFilterWrapper);
+ this.doBindDropdownOptionFilter();
+ }
+
this.romoDropdown.bodyElem.append(this.optionList);
this.romoDropdown.bodyElem.find(this.itemSelector).on('mouseenter', $.proxy(this.onItemEnter, this));
this.romoDropdown.bodyElem.find(this.itemSelector).on('click', $.proxy(this.onItemClick, this));
this.romoDropdown.popupElem.on('mousedown', $.proxy(this.onPopupMouseDown, this));
this.romoDropdown.popupElem.on('mouseup', $.proxy(this.onPopupMouseUp, this));
}
+RomoSelectDropdown.prototype.doBindDropdownOptionFilter = function() {
+ this.optionFilter.romoIndicatorTextInput();
+ this.optionFilter.romoOnkey();
+
+ this.romoDropdown.elem.on('focus', $.proxy(function(e) {
+ if (this.blurTimeoutId !== undefined) {
+ clearTimeout(this.blurTimeoutId);
+ }
+ // remove any manual elem focus when elem is actually focused
+ this.optionFilterFocused = false;
+ this.romoDropdown.elem.removeClass('romo-select-focus');
+ }, this));
+ this.romoDropdown.elem.on('blur', $.proxy(function(e) {
+ if (this.blurTimeoutId !== undefined) {
+ clearTimeout(this.blurTimeoutId);
+ }
+ // close the dropdown when elem is blurred
+ // remove any manual focus as well
+ this.romoDropdown.elem.removeClass('romo-select-focus');
+ this.blurTimeoutId = setTimeout($.proxy(function() {
+ if (this.popupMouseDown !== true && this.optionFilterFocused !== true) {
+ this.romoDropdown.elem.trigger('dropdown:triggerPopupClose', []);
+ }
+ }, this), 10);
+ }, this));
+ this.optionFilter.on('focus', $.proxy(function(e) {
+ if (this.blurTimeoutId !== undefined) {
+ clearTimeout(this.blurTimeoutId);
+ }
+ // manually make the elem focused when its filter is focused
+ this.optionFilterFocused = true;
+ this.romoDropdown.elem.addClass('romo-select-focus');
+ }, this));
+ this.optionFilter.on('blur', $.proxy(function(e) {
+ // remove any manual elem focus when its filter is blurred
+ this.optionFilterFocused = false;
+ this.romoDropdown.elem.removeClass('romo-select-focus');
+ }, this));
+
+ this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(function(e, dropdown) {
+ this.optionFilter.trigger('indicatorTextInput:triggerPlaceIndicator');
+ this.optionFilter.focus();
+ this.doFilterOptionElems();
+ }, this));
+ this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(function(e, dropdown) {
+ this.optionFilter.val('');
+ }, this));
+ this.romoDropdown.elem.on('dropdown:popupClosedByEsc', $.proxy(function(e, dropdown) {
+ this.romoDropdown.elem.focus();
+ }, this));
+ this.optionFilter.on('click', $.proxy(function(e) {
+ if (e !== undefined) {
+ e.stopPropagation();
+ }
+ }, this));
+ this.romoDropdown.popupElem.on('click', $.proxy(function(e) {
+ this.optionFilter.focus();
+ }, this));
+
+ this.onkeySearchTimeout = undefined;
+ this.onkeySearchDelay = 100; // 0.1 secs, want it to be really responsive
+
+ this.optionFilter.on('onkey:trigger', $.proxy(function(e, triggerEvent, onkey) {
+ // TODO: incorp this timeout logic into the onkey component so don't have to repeat it
+ clearTimeout(this.onkeySearchTimeout);
+ this.onkeySearchTimeout = setTimeout($.proxy(function() {
+ if (Romo.nonInputTextKeyCodes().indexOf(triggerEvent.keyCode) === -1 /* Input Text */) {
+ this.doFilterOptionElems();
+ }
+ }, this), this.onkeySearchDelay);
+ }, this));
+}
+
+RomoSelectDropdown.prototype.doFilterOptionElems = function() {
+ var wbFilter = new RomoWordBoundaryFilter(
+ this.optionFilter.val(),
+ this.romoDropdown.bodyElem.find('LI[data-romo-select-item="opt"]'),
+ function(elem) {
+ return elem[0].textContent;
+ }
+ );
+
+ wbFilter.matchingElems.show();
+ wbFilter.notMatchingElems.hide();
+ wbFilter.matchingElems.removeClass(this.filterHiddenClass);
+ wbFilter.notMatchingElems.addClass(this.filterHiddenClass);
+
+ this.romoDropdown.doPlacePopupElem();
+ if (this.optionFilter.val() !== '') {
+ this._highlightItem(wbFilter.matchingElems.first());
+ this._scrollTopToItem(wbFilter.matchingElems.first());
+ } else {
+ this._highlightItem(this.selectedListing());
+ this._scrollTopToItem(this.selectedListing());
+ }
+}
+
RomoSelectDropdown.prototype.doSelectHighlightedItem = function() {
- var prevValue = this.prevValue;
- var newValue = this.romoDropdown.bodyElem.find('LI.romo-select-highlight').data('romo-select-option-value');
+ var curr = this._getHighlightedItem();
+ if (curr.length !== 0) {
+ var prevValue = this.prevValue;
+ var newValue = curr.data('romo-select-option-value');
- this.romoDropdown.doPopupClose();
- this.elem.trigger('selectDropdown:itemSelected', [newValue, prevValue, this]);
+ this.romoDropdown.doPopupClose();
+ this.elem.trigger('selectDropdown:itemSelected', [newValue, prevValue, this]);
- if (newValue !== prevValue) {
- this.doSetNewValue(newValue);
- this.elem.trigger('selectDropdown:change', [newValue, prevValue, this]);
+ if (newValue !== prevValue) {
+ this.doSetNewValue(newValue);
+ this.elem.trigger('selectDropdown:change', [newValue, prevValue, this]);
+ }
}
}
RomoSelectDropdown.prototype.onPopupOpen = function(e) {
if (this.elem.hasClass('disabled') === false) {
@@ -170,21 +277,34 @@
return false;
} else if (e.keyCode === 13 /* Enter */ ) {
this.doSelectHighlightedItem();
return false;
+ } else if (e.keyCode === 9 /* Tab */ ) {
+ e.preventDefault();
+ return false;
} else {
return true;
}
}
RomoSelectDropdown.prototype.onElemKeyDown = function(e) {
if (this.elem.hasClass('disabled') === false) {
if (this.romoDropdown.popupElem.hasClass('romo-dropdown-open') === false) {
- if(e.keyCode === 40 /* Down */ ) {
+ if (e.keyCode === 40 /* Down */ || e.keyCode === 38 /* Up */) {
this.romoDropdown.doPopupOpen();
return false;
+ } else if (this.optionFilter !== undefined &&
+ Romo.nonInputTextKeyCodes().indexOf(e.keyCode) === -1 /* Input Text */) {
+ if (e.metaKey === false) {
+ // don't prevent default on Cmd-* keys (preserve Cmd-R refresh, etc)
+ e.preventDefault();
+ }
+ e.stopPropagation();
+ this.optionFilter.val(e.key);
+ this.romoDropdown.doPopupOpen();
+ return true;
} else {
return true;
}
}
}
@@ -256,70 +376,75 @@
item.text(optgroup.attr('label'));
return item;
}
-RomoSelectDropdown.prototype._nextListItem = function() {
- var listOrItemSelector = 'UL, '+this.itemSelector;
- var curr = this.romoDropdown.bodyElem.find('LI.romo-select-highlight');
- var next = this._nextAll(curr, listOrItemSelector).first();
+RomoSelectDropdown.prototype._buildOptionFilter = function() {
+ var filter = $('<input type="text" class="romo-select-dropdown-option-filter"></input>');
- if (next.size() === 0) {
- next = this._nextAll(curr.closest('UL'), listOrItemSelector).first();
+ if (this.elem.data('romo-select-dropdown-filter-placeholder') !== undefined) {
+ filter.attr('placeholder', this.elem.data('romo-select-dropdown-filter-placeholder'));
}
- if (next.size() !== 0 && next[0].tagName === 'UL') {
- next = next.find(this.itemSelector).first()
+ filter.attr('data-romo-indicator-text-input-elem-display', "block");
+ if (this.elem.data('romo-select-dropdown-filter-indicator') !== undefined) {
+ filter.attr('data-romo-indicator-text-input-indicator', this.elem.data('romo-select-dropdown-filter-indicator'));
}
- if (next.size() === 0) {
- next = this.romoDropdown.bodyElem.find(this.itemSelector).first();
+ if (this.elem.data('romo-select-dropdown-filter-indicator-width-px') !== undefined) {
+ filter.attr('data-romo-indicator-text-input-indicator-width-px', this.elem.data('romo-select-dropdown-filter-indicator-width-px'));
}
- return next;
-}
+ filter.attr('data-romo-form-disable-enter-submit', "true");
+ filter.attr('data-romo-onkey-on', "keydown");
-RomoSelectDropdown.prototype._prevListItem = function() {
- var listOrItemSelector = 'UL, '+this.itemSelector;
- var curr = this.romoDropdown.bodyElem.find('LI.romo-select-highlight');
- var prev = this._prevAll(curr, listOrItemSelector).last();
+ filter.attr('autocomplete', 'off');
- if (prev.size() === 0) {
- prev = this._prevAll(curr.closest('UL'), listOrItemSelector).last();
- }
- if (prev.size() !== 0 && prev[0].tagName === 'UL') {
- prev = prev.find(this.itemSelector).last()
- }
- if (prev.size() === 0) {
- prev = this.romoDropdown.bodyElem.find(this.itemSelector).last();
- }
- return prev;
+ return filter;
}
-RomoSelectDropdown.prototype._nextAll = function(elem, selector) {
- var els = $();
- var el = elem.next();
- while( el.length ) {
- if (selector === undefined || el.is(selector)) {
- els = els.add(el);
+RomoSelectDropdown.prototype._nextListItem = function() {
+ var curr = this._getHighlightedItem();
+ if (curr.length === 0) {
+ return curr;
+ }
+ var currList = curr.closest('UL');
+ var next = Romo.selectNext(curr, this.itemSelector);
+
+ while (next.length === 0) {
+ currList = Romo.selectNext(currList, 'UL');
+ if (currList.length !== 0) {
+ next = currList.find(this.itemSelector).first();
+ } else {
+ next = this.romoDropdown.bodyElem.find(this.itemSelector).first();
}
- el = el.next();
}
- return els;
+ return next;
}
-RomoSelectDropdown.prototype._prevAll = function(elem, selector) {
- var els = $();
- var el = elem.prev();
- while( el.length ) {
- if (selector === undefined || el.is(selector)) {
- els = els.add(el);
+RomoSelectDropdown.prototype._prevListItem = function() {
+ var curr = this._getHighlightedItem();
+ if (curr.length === 0) {
+ return curr;
+ }
+ var currList = curr.closest('UL');
+ var prev = Romo.selectPrev(curr, this.itemSelector);
+
+ while (prev.length === 0) {
+ currList = Romo.selectPrev(currList, 'UL');
+ if (currList.length !== 0) {
+ prev = currList.find(this.itemSelector).last();
+ } else {
+ prev = this.romoDropdown.bodyElem.find(this.itemSelector).last();
}
- el = el.prev();
}
- return els;
+ return prev;
}
RomoSelectDropdown.prototype._highlightItem = function(item) {
- this.romoDropdown.bodyElem.find('LI.romo-select-highlight').removeClass('romo-select-highlight');
+ this._getHighlightedItem().removeClass('romo-select-highlight');
item.addClass('romo-select-highlight');
+}
+
+RomoSelectDropdown.prototype._getHighlightedItem = function() {
+ return this.romoDropdown.bodyElem.find('LI.romo-select-highlight');
}
Romo.onInitUI(function(e) {
Romo.initUIElems(e, '[data-romo-select-dropdown-auto="true"]').romoSelectDropdown();
});