UNPKG

@atlassian/aui

Version:

Atlassian User Interface library

163 lines (146 loc) 4.9 kB
import $ from '../../jquery'; import { I18n } from '../../i18n'; import Alignment from '../alignment'; import layer from '../../layer'; /** * @param {string} listId * @param {number} index * @returns {string} */ function generateListItemID(listId, index) { return listId + '-' + index; } /** * @param {SuggestionsViewType} view */ function enableAlignment(view) { if (view.anchor && !view._auiAlignment) { view._auiAlignment = new Alignment(view.el, view.anchor, { flipContainer: 'scrollParent', positionFixed: false, preventOverflow: false, flip: false, }); } if (view._auiAlignment) { view._auiAlignment.enable(); view._auiAlignment.scheduleUpdate(); } } /** * @param {SuggestionsViewType} view */ function disableAlignment(view) { if (view._auiAlignment) { view._auiAlignment.disable(); } } /** * @param {SuggestionsViewType} view */ function destroyAlignment(view) { if (view._auiAlignment) { view._auiAlignment.destroy(); delete view._auiAlignment; } } /** * @param {SuggestionsViewType} view */ function matchWidth(view) { $(view.el).css('min-width', $(view.anchor).outerWidth()); } /** * @param {HTMLElement} element */ function clearActive(element) { $(element).find('.aui-select-active').removeClass('aui-select-active'); } /** * @typedef {Object} Suggestion * @property {function(): string} getLabel * @property {function(string): string} get */ /** * @typedef {Object} SuggestionsViewType * @property {HTMLElement} el * @property {HTMLElement} anchor * @property {Alignment} [_auiAlignment] * @property {string} [currListId] * @property {(suggestions: Suggestion[], currentLength: number, listId: string, selected: number) => SuggestionsViewType} render * @property {(active: number) => void} setActive * @property {() => HTMLElement|null} getActive * @property {() => void} show * @property {() => void} hide * @property {() => void} destroy * @property {() => boolean} isVisible */ /** * @constructor * @param {HTMLElement} element * @param {HTMLElement} anchor * @returns {SuggestionsViewType} */ function SuggestionsView(element, anchor) { const view = { el: element, anchor: anchor, render: function (suggestions, currentLength, listId, selected) { this.currListId = listId; let html = ''; // Do nothing if we have no new suggestions, otherwise append anything else we find. if (suggestions.length) { for (let i = 0; i < suggestions.length; i++) { const suggestion = suggestions[i]; const currentIndex = i + currentLength; const label = suggestion.getLabel(); const imageSrc = suggestion.get('img-src'); const image = imageSrc ? `<img src="${encodeURI(imageSrc)}"/>` : ''; const newValueText = suggestion.get('new-value') ? ` (<em>${I18n.getText('aui.select.new.value')}</em>)` : ''; html += `<li role="option" class="aui-select-suggestion" aria-selected="${selected === currentIndex}" id="${generateListItemID(listId, currentIndex)}">${image}${label}${newValueText}</li>`; } // If the old suggestions were empty, a <li> of 'No suggestions' will be appended, we need to remove it if (currentLength) { this.el.querySelector('ul').innerHTML += html; } else { this.el.querySelector('ul').innerHTML = html; } } else if (!currentLength) { this.el.querySelector('ul').innerHTML = `<li role="option" class="aui-select-no-suggestions">${I18n.getText('aui.select.no.suggestions')}</li>`; } return this; }, setActive: function (active) { clearActive(this.el); $(this.el) .find('#' + generateListItemID(this.currListId, active)) .addClass('aui-select-active'); }, getActive: function () { return this.el.querySelector('.aui-select-active'); }, show: function () { matchWidth(this); layer(this.el).show(); enableAlignment(this); }, hide: function () { clearActive(this.el); layer(this.el).hide(); disableAlignment(this); }, destroy: function () { this.hide(); destroyAlignment(this); delete this.currListId; }, isVisible: function () { return $(this.el).is(':visible'); }, }; return view; } export default SuggestionsView;