assets/js/romo/select_dropdown.js in romo-0.19.3 vs assets/js/romo/select_dropdown.js in romo-0.19.4
- old
+ new
@@ -3,452 +3,175 @@
return new RomoSelectDropdown(element, optionElemsParent);
});
}
var RomoSelectDropdown = function(element, optionElemsParent) {
- this.elem = $(element);
- this.prevValue = '';
+ this.elem = $(element);
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;
+ var optsParent = (optionElemsParent || this.elem.find('.romo-select-dropdown-options-parent'));
+ this.optionElems = optsParent.children();
this.doInit();
- this.doBindDropdown();
+ this._bindElem();
if (this.elem.attr('id') !== undefined) {
$('label[for="'+this.elem.attr('id')+'"]').on('click', $.proxy(function(e) {
this.elem.focus();
}, this));
}
this.elem.trigger('selectDropdown:ready', [this]);
}
-RomoSelectDropdown.prototype.selectedListing = function() {
- return this.romoDropdown.bodyElem.find('LI.selected');
+RomoSelectDropdown.prototype.bodyElem = function() {
+ return this.romoOptionListDropdown.bodyElem();
}
+RomoSelectDropdown.prototype.popupElem = function() {
+ return this.romoOptionListDropdown.popupElem();
+}
+
+RomoSelectDropdown.prototype.selectedItemElem = function() {
+ return this.romoOptionListDropdown.selectedItemElem();
+}
+
+RomoSelectDropdown.prototype.selectedItemValue = function() {
+ return this.romoOptionListDropdown.selectedItemValue();
+}
+
+RomoSelectDropdown.prototype.selectedItemText = function() {
+ return this.romoOptionListDropdown.selectedItemText();
+}
+
+RomoSelectDropdown.prototype.optItemElems = function() {
+ return this.romoOptionListDropdown.optItemElems();
+}
+
+RomoSelectDropdown.prototype.optgroupItemElems = function() {
+ return this.romoOptionListDropdown.optgroupItemElems();
+}
+
RomoSelectDropdown.prototype.doInit = function() {
// override as needed
}
RomoSelectDropdown.prototype.doSetNewValue = function(newValue) {
- this.selectedListing().removeClass('selected');
- this.romoDropdown.bodyElem.find('LI[data-romo-select-option-value="'+newValue+'"]').addClass('selected');
-
- this.prevValue = newValue;
+ this.romoOptionListDropdown.doSetNewValue(newValue);
}
-RomoSelectDropdown.prototype.doBindDropdown = function() {
- this.romoDropdown = this.elem.romoDropdown()[0];
- this.romoDropdown.doSetPopupZIndex(this.elem);
- this.romoDropdown.bodyElem.addClass('romo-select-option-list');
+/* private */
- this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(this.onPopupOpen, this));
- this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(this.onPopupClose, this));
+RomoSelectDropdown.prototype._bindElem = function() {
+ this.elem.attr('data-romo-option-list-dropdown-item-selector-customization', ':not(.'+this.filterHiddenClass+')');
+ this.elem.attr('data-romo-option-list-focus-style-class', 'romo-select-focus');
- this.romoDropdown.elem.on('keydown', $.proxy(this.onElemKeyDown, this));
- this.romoDropdown.popupElem.on('keydown', $.proxy(this.onElemKeyDown, this));
+ if (this.elem.data('romo-select-dropdown-no-filter') !== undefined) {
+ this.elem.attr('data-romo-option-list-dropdown-no-filter', this.elem.data('romo-select-dropdown-no-filter'));
+ }
+ if (this.elem.data('romo-select-dropdown-filter-placeholder') !== undefined) {
+ this.elem.attr('data-romo-option-list-dropdown-filter-placeholder', this.elem.data('romo-select-dropdown-filter-placeholder'));
+ }
+ if (this.elem.data('romo-select-dropdown-filter-indicator') !== undefined) {
+ this.elem.attr('data-romo-option-list-dropdown-filter-indicator', this.elem.data('romo-select-dropdown-filter-indicator'));
+ }
+ if (this.elem.data('romo-select-dropdown-filter-indicator-width-px') !== undefined) {
+ this.elem.attr('data-romo-option-list-dropdown-filter-indicator-width-px', this.elem.data('romo-select-dropdown-filter-indicator-width-px'));
+ }
- this.romoDropdown.elem.on('dropdown:toggle', $.proxy(function(e, dropdown) {
+ this.elem.on('romoOptionListDropdown:dropdown:toggle', $.proxy(function(e, dropdown) {
this.elem.trigger('selectDropdown:dropdown:toggle', [dropdown, this]);
}, this));
- this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(function(e, dropdown) {
+ this.elem.on('romoOptionListDropdown:dropdown:popupOpen', $.proxy(function(e, dropdown) {
this.elem.trigger('selectDropdown:dropdown:popupOpen', [dropdown, this]);
}, this));
- this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(function(e, dropdown) {
+ this.elem.on('romoOptionListDropdown:dropdown:popupClose', $.proxy(function(e, dropdown) {
this.elem.trigger('selectDropdown:dropdown:popupClose', [dropdown, this]);
}, this));
+ this.elem.on('romoOptionListDropdown:itemSelected', $.proxy(function(e, newValue, prevValue, romoOptionListDropdown) {
+ this.elem.trigger('selectDropdown:itemSelected', [newValue, prevValue, this]);
+ }, this));
+ this.elem.on('romoOptionListDropdown:change', $.proxy(function(e, newValue, prevValue, romoOptionListDropdown) {
+ this.elem.trigger('selectDropdown:change', [newValue, prevValue, this]);
+ }, this));
+
this.elem.on('selectDropdown:triggerToggle', $.proxy(function(e) {
- this.romoDropdown.elem.trigger('dropdown:triggerToggle', []);
+ this.elem.trigger('romoOptionListDropdown:triggerToggle', []);
}, this));
this.elem.on('selectDropdown:triggerPopupOpen', $.proxy(function(e) {
- this.romoDropdown.elem.trigger('dropdown:triggerPopupOpen', []);
+ this.elem.trigger('romoOptionListDropdown:triggerPopupOpen', []);
}, this));
this.elem.on('selectDropdown:triggerPopupClose', $.proxy(function(e) {
- this.romoDropdown.elem.trigger('dropdown:triggerPopupClose', []);
+ this.elem.trigger('romoOptionListDropdown:triggerPopupClose', []);
}, this));
- this.romoDropdown.bodyElem.html('');
+ this.romoOptionListDropdown = this.elem.romoOptionListDropdown()[0];
- 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) {
+ this.elem.on('romoOptionListDropdown:filterChange', $.proxy(function(e, filterValue, romoOptionListDropdown) {
+ var wbFilter = new RomoWordBoundaryFilter(filterValue, this.optItemElems(), function(elem) {
// The romo word boundary filter by default considers a space, "-" and "_" as word boundaries.
// We want to also consider other non-word characters (such as ":", "/", ".", "?", "=", "&")
// as word boundaries as well.
return elem[0].textContent.replace(/\W/g, ' ');
- }
- );
+ });
- wbFilter.matchingElems.show();
- wbFilter.notMatchingElems.hide();
- wbFilter.matchingElems.removeClass(this.filterHiddenClass);
- wbFilter.notMatchingElems.addClass(this.filterHiddenClass);
+ 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 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]);
-
- if (newValue !== prevValue) {
- this.doSetNewValue(newValue);
- this.elem.trigger('selectDropdown:change', [newValue, prevValue, this]);
+ if (filterValue !== '') {
+ this.elem.trigger('romoOptionListDropdown:triggerListOptionsUpdate', [wbFilter.matchingElems.first()]);
+ } else {
+ this.elem.trigger('romoOptionListDropdown:triggerListOptionsUpdate', [this.selectedItemElem()]);
}
- }
-}
+ }, this));
-RomoSelectDropdown.prototype.onPopupOpen = function(e) {
- if (this.elem.hasClass('disabled') === false) {
- this._highlightItem(this.selectedListing());
- this._scrollTopToItem(this.selectedListing());
- }
- $('body').on('keydown', $.proxy(this.onPopupOpenBodyKeyDown, this));
+ this.romoOptionListDropdown.doSetListItems(this._buildOptionList(this.optionElems));
}
-RomoSelectDropdown.prototype.onPopupClose = function(e) {
- this._highlightItem($());
- $('body').off('keydown', $.proxy(this.onPopupOpenBodyKeyDown, this));
-}
+RomoSelectDropdown.prototype._buildOptionList = function(optionElems) {
+ var list = [];
-RomoSelectDropdown.prototype.onItemEnter = function(e) {
- if (e !== undefined) {
- e.preventDefault();
- e.stopPropagation();
- }
- this._highlightItem($(e.target));
-}
-
-RomoSelectDropdown.prototype.onItemClick = function(e) {
- if (this.blurTimeoutId !== undefined) {
- clearTimeout(this.blurTimeoutId);
- this.blurTimeoutId = undefined;
- }
- if (e !== undefined) {
- e.preventDefault();
- e.stopPropagation();
- }
- this.doSelectHighlightedItem();
-}
-
-RomoSelectDropdown.prototype.onPopupMouseDown = function(e) {
- this.popupMouseDown = true;
-}
-
-RomoSelectDropdown.prototype.onPopupMouseUp = function(e) {
- this.popupMouseDown = false;
-}
-
-RomoSelectDropdown.prototype.onPopupOpenBodyKeyDown = function(e) {
- if (e !== undefined) {
- e.stopPropagation();
- }
-
- var scroll = this.romoDropdown.bodyElem;
-
- if (e.keyCode === 38 /* Up */) {
- var prev = this._prevListItem();
-
- this._highlightItem(prev);
- if (scroll.offset().top > prev.offset().top) {
- this._scrollTopToItem(prev);
- } else if ((scroll.offset().top + scroll.height()) < prev.offset().top) {
- this._scrollTopToItem(prev);
+ $.each(optionElems, $.proxy(function(idx, optionNode) {
+ if (optionNode.tagName === "OPTION") {
+ list.push(this._buildOptionItem($(optionNode)));
+ } else if (optionNode.tagName === "OPTGROUP") {
+ list.push(this._buildOptGroupItem($(optionNode)));
}
+ }, this));
- return false;
- } else if(e.keyCode === 40 /* Down */) {
- var next = this._nextListItem();
-
- this._highlightItem(next);
- if ((scroll.offset().top + scroll.height()) < next.offset().top + next.height()) {
- this._scrollBottomToItem(next);
- } else if (scroll.offset().top > next.offset().top) {
- this._scrollTopToItem(next);
- }
-
- 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;
- }
+ return list;
}
-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 */ || 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;
- }
- }
- }
- return true;
-}
+RomoSelectDropdown.prototype._buildOptionItem = function(optionElem) {
+ var item = {}
-RomoSelectDropdown.prototype._scrollTopToItem = function(item) {
- if (item.size() > 0) {
- var scroll = this.romoDropdown.bodyElem;
- scroll.scrollTop(0);
+ item['type'] = 'option';
+ item['value'] = (optionElem.attr('value') || '');
+ item['displayText'] = (optionElem.text().trim() || '');
+ item['displayHtml'] = (optionElem.text().trim() || ' ');
- var scrollOffsetTop = scroll.offset().top;
- var selOffsetTop = item.offset().top;
- var selOffset = item.height() / 2;
-
- scroll.scrollTop(selOffsetTop - scrollOffsetTop - selOffset);
+ if (optionElem.prop('selected')) {
+ item['selected'] = true;
}
-}
-
-RomoSelectDropdown.prototype._scrollBottomToItem = function(item) {
- if (item.size() > 0) {
- var scroll = this.romoDropdown.bodyElem;
- scroll.scrollTop(0);
-
- var scrollOffsetTop = scroll.offset().top;
- var selOffsetTop = item.offset().top;
- var selOffset = scroll[0].offsetHeight - item.height();
-
- scroll.scrollTop(selOffsetTop - scrollOffsetTop - selOffset);
+ if (optionElem.attr('disabled') !== undefined) {
+ item['disabled'] = true;
}
-}
-RomoSelectDropdown.prototype._buildOptionList = function(optionElems, listClass) {
- var list = $('<ul></ul>');
- list.addClass(listClass);
- $.each(optionElems, $.proxy(function(idx, elem) {
- if (elem.tagName === "OPTION") {
- list.append(this._buildOptionListItem(elem));
- } else if (elem.tagName === "OPTGROUP") {
- list.append(this._buildOptGroupListItem(elem));
- list.append(this._buildOptionList($(elem).children(), 'romo-select-optgroup'));
- }
- }, this));
- return list;
-}
-
-RomoSelectDropdown.prototype._buildOptionListItem = function(optionElem) {
- var opt = $(optionElem);
- var item = $('<li data-romo-select-item="opt"></li>');
- var value = opt.attr('value') || '';
-
- item.attr('data-romo-select-option-value', value);
- item.html(opt.text().trim() || ' ');
- if (opt.prop('selected')) {
- item.addClass('selected');
- this.prevValue = value; // the last option marked selected is used
- }
- if (opt.attr('disabled') !== undefined) {
- item.addClass('disabled');
- }
-
return item;
}
-RomoSelectDropdown.prototype._buildOptGroupListItem = function(optGroupElem) {
- var optgroup = $(optGroupElem);
- var item = $('<li data-romo-select-item="optgroup"></li>');
+RomoSelectDropdown.prototype._buildOptGroupItem = function(optGroupElem) {
+ var item = {};
- item.text(optgroup.attr('label'));
+ item['type'] = 'optgroup';
+ item['label'] = optGroupElem.attr('label');
+ item['items'] = this._buildOptionList(optGroupElem.children());
return item;
-}
-
-RomoSelectDropdown.prototype._buildOptionFilter = function() {
- var filter = $('<input type="text" size="1" class="romo-select-dropdown-option-filter"></input>');
-
- if (this.elem.data('romo-select-dropdown-filter-placeholder') !== undefined) {
- filter.attr('placeholder', this.elem.data('romo-select-dropdown-filter-placeholder'));
- }
- filter.attr('data-romo-indicator-text-input-elem-display', "block");
- filter.attr('data-romo-indicator-text-input-indicator-position', "right");
- 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 (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'));
- }
- filter.attr('data-romo-form-disable-enter-submit', "true");
- filter.attr('data-romo-onkey-on', "keydown");
-
- filter.attr('autocomplete', 'off');
-
- return filter;
-}
-
-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();
- }
- }
- return next;
-}
-
-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();
- }
- }
- return prev;
-}
-
-RomoSelectDropdown.prototype._highlightItem = function(item) {
- 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();
});