2017-03-13 11:46:43 +00:00
|
|
|
import FilteredSearchContainer from './container';
|
2017-03-10 17:40:38 +00:00
|
|
|
|
2016-12-13 14:52:43 +00:00
|
|
|
(() => {
|
2016-11-04 21:27:11 +00:00
|
|
|
class FilteredSearchManager {
|
2017-03-10 17:40:38 +00:00
|
|
|
constructor(page) {
|
|
|
|
this.container = FilteredSearchContainer.container;
|
2017-03-10 12:08:19 +00:00
|
|
|
this.filteredSearchInput = this.container.querySelector('.filtered-search');
|
|
|
|
this.clearSearchButton = this.container.querySelector('.clear-search');
|
|
|
|
this.tokensContainer = this.container.querySelector('.tokens-container');
|
2017-02-15 22:13:53 +00:00
|
|
|
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys;
|
2016-12-09 17:44:09 +00:00
|
|
|
|
2017-01-09 18:15:10 +00:00
|
|
|
if (this.filteredSearchInput) {
|
|
|
|
this.tokenizer = gl.FilteredSearchTokenizer;
|
2017-03-10 17:40:38 +00:00
|
|
|
this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', page);
|
2016-12-08 21:42:58 +00:00
|
|
|
|
2017-01-09 18:15:10 +00:00
|
|
|
this.bindEvents();
|
|
|
|
this.loadSearchParamsFromURL();
|
|
|
|
this.dropdownManager.setDropdown();
|
|
|
|
|
|
|
|
this.cleanupWrapper = this.cleanup.bind(this);
|
2017-01-13 21:54:16 +00:00
|
|
|
document.addEventListener('beforeunload', this.cleanupWrapper);
|
2017-01-09 18:15:10 +00:00
|
|
|
}
|
2016-12-08 21:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanup() {
|
2016-12-09 21:36:44 +00:00
|
|
|
this.unbindEvents();
|
2017-01-13 21:54:16 +00:00
|
|
|
document.removeEventListener('beforeunload', this.cleanupWrapper);
|
2016-12-09 17:44:09 +00:00
|
|
|
}
|
2016-12-08 21:42:58 +00:00
|
|
|
|
2016-11-04 21:27:11 +00:00
|
|
|
bindEvents() {
|
2017-01-21 07:44:36 +00:00
|
|
|
this.handleFormSubmit = this.handleFormSubmit.bind(this);
|
2016-12-12 15:21:38 +00:00
|
|
|
this.setDropdownWrapper = this.dropdownManager.setDropdown.bind(this.dropdownManager);
|
2016-12-12 22:37:49 +00:00
|
|
|
this.toggleClearSearchButtonWrapper = this.toggleClearSearchButton.bind(this);
|
2017-01-30 22:53:18 +00:00
|
|
|
this.handleInputPlaceholderWrapper = this.handleInputPlaceholder.bind(this);
|
|
|
|
this.handleInputVisualTokenWrapper = this.handleInputVisualToken.bind(this);
|
2016-12-09 21:36:44 +00:00
|
|
|
this.checkForEnterWrapper = this.checkForEnter.bind(this);
|
|
|
|
this.clearSearchWrapper = this.clearSearch.bind(this);
|
|
|
|
this.checkForBackspaceWrapper = this.checkForBackspace.bind(this);
|
2017-01-30 22:53:18 +00:00
|
|
|
this.removeSelectedTokenWrapper = this.removeSelectedToken.bind(this);
|
|
|
|
this.unselectEditTokensWrapper = this.unselectEditTokens.bind(this);
|
2017-03-08 01:36:02 +00:00
|
|
|
this.editTokenWrapper = this.editToken.bind(this);
|
2017-01-19 10:37:54 +00:00
|
|
|
this.tokenChange = this.tokenChange.bind(this);
|
2017-03-10 22:30:42 +00:00
|
|
|
this.addInputContainerFocusWrapper = this.addInputContainerFocus.bind(this);
|
|
|
|
this.removeInputContainerFocusWrapper = this.removeInputContainerFocus.bind(this);
|
2016-12-09 21:36:44 +00:00
|
|
|
|
2017-03-13 21:48:32 +00:00
|
|
|
this.filteredSearchInputForm = this.filteredSearchInput.form;
|
|
|
|
this.filteredSearchInputForm.addEventListener('submit', this.handleFormSubmit);
|
2016-12-09 21:36:44 +00:00
|
|
|
this.filteredSearchInput.addEventListener('input', this.setDropdownWrapper);
|
2016-12-12 22:37:49 +00:00
|
|
|
this.filteredSearchInput.addEventListener('input', this.toggleClearSearchButtonWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
this.filteredSearchInput.addEventListener('input', this.handleInputPlaceholderWrapper);
|
|
|
|
this.filteredSearchInput.addEventListener('input', this.handleInputVisualTokenWrapper);
|
2016-12-09 21:36:44 +00:00
|
|
|
this.filteredSearchInput.addEventListener('keydown', this.checkForEnterWrapper);
|
|
|
|
this.filteredSearchInput.addEventListener('keyup', this.checkForBackspaceWrapper);
|
2017-01-19 10:37:54 +00:00
|
|
|
this.filteredSearchInput.addEventListener('click', this.tokenChange);
|
|
|
|
this.filteredSearchInput.addEventListener('keyup', this.tokenChange);
|
2017-03-10 22:30:42 +00:00
|
|
|
this.filteredSearchInput.addEventListener('focus', this.addInputContainerFocusWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
this.tokensContainer.addEventListener('click', FilteredSearchManager.selectToken);
|
2017-03-08 01:36:02 +00:00
|
|
|
this.tokensContainer.addEventListener('dblclick', this.editTokenWrapper);
|
2016-12-09 21:36:44 +00:00
|
|
|
this.clearSearchButton.addEventListener('click', this.clearSearchWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
document.addEventListener('click', gl.FilteredSearchVisualTokens.unselectTokens);
|
|
|
|
document.addEventListener('click', this.unselectEditTokensWrapper);
|
2017-03-10 22:30:42 +00:00
|
|
|
document.addEventListener('click', this.removeInputContainerFocusWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
document.addEventListener('keydown', this.removeSelectedTokenWrapper);
|
2016-12-09 21:36:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unbindEvents() {
|
2017-03-13 21:48:32 +00:00
|
|
|
this.filteredSearchInputForm.removeEventListener('submit', this.handleFormSubmit);
|
2016-12-09 21:36:44 +00:00
|
|
|
this.filteredSearchInput.removeEventListener('input', this.setDropdownWrapper);
|
2016-12-12 22:37:49 +00:00
|
|
|
this.filteredSearchInput.removeEventListener('input', this.toggleClearSearchButtonWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
this.filteredSearchInput.removeEventListener('input', this.handleInputPlaceholderWrapper);
|
|
|
|
this.filteredSearchInput.removeEventListener('input', this.handleInputVisualTokenWrapper);
|
2016-12-09 21:36:44 +00:00
|
|
|
this.filteredSearchInput.removeEventListener('keydown', this.checkForEnterWrapper);
|
|
|
|
this.filteredSearchInput.removeEventListener('keyup', this.checkForBackspaceWrapper);
|
2017-01-19 10:37:54 +00:00
|
|
|
this.filteredSearchInput.removeEventListener('click', this.tokenChange);
|
|
|
|
this.filteredSearchInput.removeEventListener('keyup', this.tokenChange);
|
2017-03-10 22:30:42 +00:00
|
|
|
this.filteredSearchInput.removeEventListener('focus', this.addInputContainerFocusWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
this.tokensContainer.removeEventListener('click', FilteredSearchManager.selectToken);
|
2017-03-08 01:36:02 +00:00
|
|
|
this.tokensContainer.removeEventListener('dblclick', this.editTokenWrapper);
|
2016-12-09 21:36:44 +00:00
|
|
|
this.clearSearchButton.removeEventListener('click', this.clearSearchWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
document.removeEventListener('click', gl.FilteredSearchVisualTokens.unselectTokens);
|
|
|
|
document.removeEventListener('click', this.unselectEditTokensWrapper);
|
2017-03-10 22:30:42 +00:00
|
|
|
document.removeEventListener('click', this.removeInputContainerFocusWrapper);
|
2017-01-30 22:53:18 +00:00
|
|
|
document.removeEventListener('keydown', this.removeSelectedTokenWrapper);
|
2016-12-07 18:55:03 +00:00
|
|
|
}
|
|
|
|
|
2016-12-09 21:36:44 +00:00
|
|
|
checkForBackspace(e) {
|
2016-12-12 22:27:10 +00:00
|
|
|
// 8 = Backspace Key
|
|
|
|
// 46 = Delete Key
|
|
|
|
if (e.keyCode === 8 || e.keyCode === 46) {
|
2017-01-30 22:53:18 +00:00
|
|
|
const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
|
|
|
if (this.filteredSearchInput.value === '' && lastVisualToken) {
|
|
|
|
this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial();
|
|
|
|
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
|
|
|
|
}
|
|
|
|
|
2016-12-09 21:36:44 +00:00
|
|
|
// Reposition dropdown so that it is aligned with cursor
|
2016-12-12 15:21:38 +00:00
|
|
|
this.dropdownManager.updateCurrentDropdownOffset();
|
2016-12-09 21:36:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-14 16:37:55 +00:00
|
|
|
checkForEnter(e) {
|
2017-01-20 11:19:15 +00:00
|
|
|
if (e.keyCode === 38 || e.keyCode === 40) {
|
|
|
|
const selectionStart = this.filteredSearchInput.selectionStart;
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
this.filteredSearchInput.setSelectionRange(selectionStart, selectionStart);
|
|
|
|
}
|
|
|
|
|
2016-11-14 16:37:55 +00:00
|
|
|
if (e.keyCode === 13) {
|
2017-01-20 11:19:15 +00:00
|
|
|
const dropdown = this.dropdownManager.mapping[this.dropdownManager.currentDropdown];
|
|
|
|
const dropdownEl = dropdown.element;
|
|
|
|
const activeElements = dropdownEl.querySelectorAll('.dropdown-active');
|
|
|
|
|
2016-11-14 16:37:55 +00:00
|
|
|
e.preventDefault();
|
2016-12-09 21:20:41 +00:00
|
|
|
|
2017-01-20 11:19:15 +00:00
|
|
|
if (!activeElements.length) {
|
2017-03-07 14:28:50 +00:00
|
|
|
if (this.isHandledAsync) {
|
|
|
|
e.stopImmediatePropagation();
|
2017-03-07 15:54:45 +00:00
|
|
|
|
2017-03-07 14:28:50 +00:00
|
|
|
this.filteredSearchInput.blur();
|
|
|
|
this.dropdownManager.resetDropdowns();
|
|
|
|
} else {
|
|
|
|
// Prevent droplab from opening dropdown
|
|
|
|
this.dropdownManager.destroyDroplab();
|
|
|
|
}
|
2016-12-09 21:20:41 +00:00
|
|
|
|
2017-01-20 11:19:15 +00:00
|
|
|
this.search();
|
|
|
|
}
|
2016-11-04 21:27:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 22:30:42 +00:00
|
|
|
addInputContainerFocus() {
|
|
|
|
this.filteredSearchInput.closest('.filtered-search-input-container').classList.add('focus');
|
|
|
|
}
|
|
|
|
|
|
|
|
removeInputContainerFocus(e) {
|
|
|
|
const inputContainer = this.filteredSearchInput.closest('.filtered-search-input-container');
|
|
|
|
const isElementInFilteredSearch = inputContainer && inputContainer.contains(e.target);
|
|
|
|
const isElementInDynamicFilterDropdown = e.target.closest('.filter-dropdown') !== null;
|
|
|
|
const isElementInStaticFilterDropdown = e.target.closest('ul[data-dropdown]') !== null;
|
|
|
|
|
|
|
|
if (!isElementInFilteredSearch &&
|
|
|
|
!isElementInDynamicFilterDropdown &&
|
|
|
|
!isElementInStaticFilterDropdown) {
|
|
|
|
inputContainer.classList.remove('focus');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-30 22:53:18 +00:00
|
|
|
static selectToken(e) {
|
|
|
|
const button = e.target.closest('.selectable');
|
|
|
|
|
|
|
|
if (button) {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
gl.FilteredSearchVisualTokens.selectToken(button);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unselectEditTokens(e) {
|
2017-03-10 12:08:19 +00:00
|
|
|
const inputContainer = this.container.querySelector('.filtered-search-input-container');
|
2017-01-30 22:53:18 +00:00
|
|
|
const isElementInFilteredSearch = inputContainer && inputContainer.contains(e.target);
|
|
|
|
const isElementInFilterDropdown = e.target.closest('.filter-dropdown') !== null;
|
|
|
|
const isElementTokensContainer = e.target.classList.contains('tokens-container');
|
|
|
|
|
|
|
|
if ((!isElementInFilteredSearch && !isElementInFilterDropdown) || isElementTokensContainer) {
|
|
|
|
gl.FilteredSearchVisualTokens.moveInputToTheRight();
|
|
|
|
this.dropdownManager.resetDropdowns();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-08 01:36:02 +00:00
|
|
|
editToken(e) {
|
2017-01-30 22:53:18 +00:00
|
|
|
const token = e.target.closest('.js-visual-token');
|
|
|
|
|
|
|
|
if (token) {
|
|
|
|
gl.FilteredSearchVisualTokens.editToken(token);
|
2017-03-08 01:36:02 +00:00
|
|
|
this.tokenChange();
|
2017-01-30 22:53:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleClearSearchButton() {
|
|
|
|
const query = gl.DropdownUtils.getSearchQuery();
|
|
|
|
const hidden = 'hidden';
|
|
|
|
const hasHidden = this.clearSearchButton.classList.contains(hidden);
|
|
|
|
|
|
|
|
if (query.length === 0 && !hasHidden) {
|
|
|
|
this.clearSearchButton.classList.add(hidden);
|
|
|
|
} else if (query.length && hasHidden) {
|
|
|
|
this.clearSearchButton.classList.remove(hidden);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handleInputPlaceholder() {
|
|
|
|
const query = gl.DropdownUtils.getSearchQuery();
|
|
|
|
const placeholder = 'Search or filter results...';
|
|
|
|
const currentPlaceholder = this.filteredSearchInput.placeholder;
|
|
|
|
|
|
|
|
if (query.length === 0 && currentPlaceholder !== placeholder) {
|
|
|
|
this.filteredSearchInput.placeholder = placeholder;
|
|
|
|
} else if (query.length > 0 && currentPlaceholder !== '') {
|
|
|
|
this.filteredSearchInput.placeholder = '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
removeSelectedToken(e) {
|
|
|
|
// 8 = Backspace Key
|
|
|
|
// 46 = Delete Key
|
|
|
|
if (e.keyCode === 8 || e.keyCode === 46) {
|
|
|
|
gl.FilteredSearchVisualTokens.removeSelectedToken();
|
|
|
|
this.handleInputPlaceholder();
|
|
|
|
this.toggleClearSearchButton();
|
2016-12-12 22:37:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clearSearch(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
this.filteredSearchInput.value = '';
|
2017-01-30 22:53:18 +00:00
|
|
|
|
|
|
|
const removeElements = [];
|
|
|
|
|
|
|
|
[].forEach.call(this.tokensContainer.children, (t) => {
|
|
|
|
if (t.classList.contains('js-visual-token')) {
|
|
|
|
removeElements.push(t);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
removeElements.forEach((el) => {
|
|
|
|
el.parentElement.removeChild(el);
|
|
|
|
});
|
|
|
|
|
2016-12-12 22:37:49 +00:00
|
|
|
this.clearSearchButton.classList.add('hidden');
|
2017-01-30 22:53:18 +00:00
|
|
|
this.handleInputPlaceholder();
|
2016-12-12 22:37:49 +00:00
|
|
|
|
|
|
|
this.dropdownManager.resetDropdowns();
|
2017-03-07 15:54:45 +00:00
|
|
|
|
|
|
|
if (this.isHandledAsync) {
|
|
|
|
this.search();
|
|
|
|
}
|
2016-12-12 22:37:49 +00:00
|
|
|
}
|
|
|
|
|
2017-01-30 22:53:18 +00:00
|
|
|
handleInputVisualToken() {
|
|
|
|
const input = this.filteredSearchInput;
|
|
|
|
const { tokens, searchToken }
|
|
|
|
= gl.FilteredSearchTokenizer.processTokens(input.value);
|
|
|
|
const { isLastVisualTokenValid }
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
|
|
|
if (isLastVisualTokenValid) {
|
|
|
|
tokens.forEach((t) => {
|
|
|
|
input.value = input.value.replace(`${t.key}:${t.symbol}${t.value}`, '');
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken(t.key, `${t.symbol}${t.value}`);
|
|
|
|
});
|
|
|
|
|
|
|
|
const fragments = searchToken.split(':');
|
|
|
|
if (fragments.length > 1) {
|
|
|
|
const inputValues = fragments[0].split(' ');
|
|
|
|
const tokenKey = inputValues.last();
|
|
|
|
|
|
|
|
if (inputValues.length > 1) {
|
|
|
|
inputValues.pop();
|
|
|
|
const searchTerms = inputValues.join(' ');
|
|
|
|
|
|
|
|
input.value = input.value.replace(searchTerms, '');
|
|
|
|
gl.FilteredSearchVisualTokens.addSearchVisualToken(searchTerms);
|
|
|
|
}
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken(tokenKey);
|
|
|
|
input.value = input.value.replace(`${tokenKey}:`, '');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Keep listening to token until we determine that the user is done typing the token value
|
|
|
|
const valueCompletedRegex = /([~%@]{0,1}".+")|([~%@]{0,1}'.+')|^((?![~%@]')(?![~%@]")(?!')(?!")).*/g;
|
|
|
|
|
|
|
|
if (searchToken.match(valueCompletedRegex) && input.value[input.value.length - 1] === ' ') {
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken(searchToken);
|
|
|
|
|
|
|
|
// Trim the last space as seen in the if statement above
|
|
|
|
input.value = input.value.replace(searchToken, '').trim();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-21 07:44:36 +00:00
|
|
|
handleFormSubmit(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.search();
|
|
|
|
}
|
|
|
|
|
2016-12-12 22:37:49 +00:00
|
|
|
loadSearchParamsFromURL() {
|
2016-12-13 03:24:55 +00:00
|
|
|
const params = gl.utils.getUrlParamsArray();
|
2017-01-20 21:35:39 +00:00
|
|
|
const usernameParams = this.getUsernameParams();
|
2017-01-30 22:53:18 +00:00
|
|
|
let hasFilteredSearch = false;
|
2016-12-12 22:37:49 +00:00
|
|
|
|
|
|
|
params.forEach((p) => {
|
|
|
|
const split = p.split('=');
|
2016-12-13 04:15:31 +00:00
|
|
|
const keyParam = decodeURIComponent(split[0]);
|
2016-12-12 22:37:49 +00:00
|
|
|
const value = split[1];
|
|
|
|
|
2017-02-15 22:13:53 +00:00
|
|
|
// Check if it matches edge conditions listed in this.filteredSearchTokenKeys
|
|
|
|
const condition = this.filteredSearchTokenKeys.searchByConditionUrl(p);
|
2016-12-12 22:37:49 +00:00
|
|
|
|
2016-12-13 04:15:31 +00:00
|
|
|
if (condition) {
|
2017-01-30 22:53:18 +00:00
|
|
|
hasFilteredSearch = true;
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken(condition.tokenKey, condition.value);
|
2016-12-12 22:37:49 +00:00
|
|
|
} else {
|
|
|
|
// Sanitize value since URL converts spaces into +
|
|
|
|
// Replace before decode so that we know what was originally + versus the encoded +
|
|
|
|
const sanitizedValue = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : value;
|
2017-02-15 22:13:53 +00:00
|
|
|
const match = this.filteredSearchTokenKeys.searchByKeyParam(keyParam);
|
2016-12-12 22:37:49 +00:00
|
|
|
|
|
|
|
if (match) {
|
2016-12-16 16:22:09 +00:00
|
|
|
const indexOf = keyParam.indexOf('_');
|
|
|
|
const sanitizedKey = indexOf !== -1 ? keyParam.slice(0, keyParam.indexOf('_')) : keyParam;
|
2016-12-12 22:37:49 +00:00
|
|
|
const symbol = match.symbol;
|
2016-12-13 04:15:31 +00:00
|
|
|
let quotationsToUse = '';
|
2016-12-12 22:37:49 +00:00
|
|
|
|
2016-12-13 04:15:31 +00:00
|
|
|
if (sanitizedValue.indexOf(' ') !== -1) {
|
2016-12-12 22:37:49 +00:00
|
|
|
// Prefer ", but use ' if required
|
|
|
|
quotationsToUse = sanitizedValue.indexOf('"') === -1 ? '"' : '\'';
|
|
|
|
}
|
|
|
|
|
2017-01-30 22:53:18 +00:00
|
|
|
hasFilteredSearch = true;
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken(sanitizedKey, `${symbol}${quotationsToUse}${sanitizedValue}${quotationsToUse}`);
|
2017-01-20 21:35:39 +00:00
|
|
|
} else if (!match && keyParam === 'assignee_id') {
|
|
|
|
const id = parseInt(value, 10);
|
|
|
|
if (usernameParams[id]) {
|
2017-01-30 22:53:18 +00:00
|
|
|
hasFilteredSearch = true;
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken('assignee', `@${usernameParams[id]}`);
|
2017-01-20 21:35:39 +00:00
|
|
|
}
|
|
|
|
} else if (!match && keyParam === 'author_id') {
|
|
|
|
const id = parseInt(value, 10);
|
|
|
|
if (usernameParams[id]) {
|
2017-01-30 22:53:18 +00:00
|
|
|
hasFilteredSearch = true;
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken('author', `@${usernameParams[id]}`);
|
2017-01-20 21:35:39 +00:00
|
|
|
}
|
2016-12-13 04:15:31 +00:00
|
|
|
} else if (!match && keyParam === 'search') {
|
2017-01-30 22:53:18 +00:00
|
|
|
hasFilteredSearch = true;
|
|
|
|
this.filteredSearchInput.value = sanitizedValue;
|
2016-12-12 22:37:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-01-30 22:53:18 +00:00
|
|
|
if (hasFilteredSearch) {
|
2016-12-12 22:37:49 +00:00
|
|
|
this.clearSearchButton.classList.remove('hidden');
|
2017-01-30 22:53:18 +00:00
|
|
|
this.handleInputPlaceholder();
|
2016-12-12 22:37:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-04 21:27:11 +00:00
|
|
|
search() {
|
2016-12-13 14:52:43 +00:00
|
|
|
const paths = [];
|
2017-01-30 22:53:18 +00:00
|
|
|
const { tokens, searchToken }
|
|
|
|
= this.tokenizer.processTokens(gl.DropdownUtils.getSearchQuery());
|
2016-12-13 03:15:50 +00:00
|
|
|
const currentState = gl.utils.getParameterByName('state') || 'opened';
|
2016-12-12 22:42:00 +00:00
|
|
|
paths.push(`state=${currentState}`);
|
2016-12-13 03:15:50 +00:00
|
|
|
|
2016-11-09 23:07:30 +00:00
|
|
|
tokens.forEach((token) => {
|
2017-02-15 22:13:53 +00:00
|
|
|
const condition = this.filteredSearchTokenKeys
|
2016-12-13 14:52:43 +00:00
|
|
|
.searchByConditionKeyValue(token.key, token.value.toLowerCase());
|
2017-02-15 22:13:53 +00:00
|
|
|
const { param } = this.filteredSearchTokenKeys.searchByKey(token.key) || {};
|
2016-12-17 19:22:00 +00:00
|
|
|
const keyParam = param ? `${token.key}_${param}` : token.key;
|
2016-11-14 19:22:32 +00:00
|
|
|
let tokenPath = '';
|
|
|
|
|
2016-12-17 19:22:00 +00:00
|
|
|
if (condition) {
|
2016-12-13 04:15:31 +00:00
|
|
|
tokenPath = condition.url;
|
2016-12-13 05:16:45 +00:00
|
|
|
} else {
|
2017-01-06 19:56:34 +00:00
|
|
|
let tokenValue = token.value;
|
|
|
|
|
|
|
|
if ((tokenValue[0] === '\'' && tokenValue[tokenValue.length - 1] === '\'') ||
|
|
|
|
(tokenValue[0] === '"' && tokenValue[tokenValue.length - 1] === '"')) {
|
|
|
|
tokenValue = tokenValue.slice(1, tokenValue.length - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
tokenPath = `${keyParam}=${encodeURIComponent(tokenValue)}`;
|
2016-11-14 19:22:32 +00:00
|
|
|
}
|
|
|
|
|
2016-12-12 22:42:00 +00:00
|
|
|
paths.push(tokenPath);
|
2016-11-04 21:27:11 +00:00
|
|
|
});
|
|
|
|
|
2016-11-09 23:07:30 +00:00
|
|
|
if (searchToken) {
|
2017-01-24 17:57:39 +00:00
|
|
|
const sanitized = searchToken.split(' ').map(t => encodeURIComponent(t)).join('+');
|
|
|
|
paths.push(`search=${sanitized}`);
|
2016-11-04 21:27:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 21:54:16 +00:00
|
|
|
const parameterizedUrl = `?scope=all&utf8=✓&${paths.join('&')}`;
|
|
|
|
|
2017-03-07 11:05:37 +00:00
|
|
|
if (this.updateObject) {
|
|
|
|
this.updateObject(parameterizedUrl);
|
|
|
|
} else {
|
|
|
|
gl.utils.visitUrl(parameterizedUrl);
|
|
|
|
}
|
2016-11-04 21:27:11 +00:00
|
|
|
}
|
2017-01-20 21:35:39 +00:00
|
|
|
|
|
|
|
getUsernameParams() {
|
|
|
|
const usernamesById = {};
|
|
|
|
try {
|
|
|
|
const attribute = this.filteredSearchInput.getAttribute('data-username-params');
|
|
|
|
JSON.parse(attribute).forEach((user) => {
|
|
|
|
usernamesById[user.id] = user.username;
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
return usernamesById;
|
|
|
|
}
|
2017-01-18 21:39:43 +00:00
|
|
|
|
2017-01-19 15:36:38 +00:00
|
|
|
tokenChange() {
|
2017-01-19 10:10:53 +00:00
|
|
|
const dropdown = this.dropdownManager.mapping[this.dropdownManager.currentDropdown];
|
2017-01-18 21:39:43 +00:00
|
|
|
|
2017-03-08 02:12:23 +00:00
|
|
|
if (dropdown) {
|
|
|
|
const currentDropdownRef = dropdown.reference;
|
|
|
|
|
|
|
|
this.setDropdownWrapper();
|
|
|
|
currentDropdownRef.dispatchInputEvent();
|
|
|
|
}
|
2017-01-18 21:39:43 +00:00
|
|
|
}
|
2016-11-04 21:27:11 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 14:52:43 +00:00
|
|
|
window.gl = window.gl || {};
|
|
|
|
gl.FilteredSearchManager = FilteredSearchManager;
|
|
|
|
})();
|