121 lines
3.8 KiB
JavaScript
121 lines
3.8 KiB
JavaScript
(() => {
|
|
class DropdownUtils {
|
|
static getEscapedText(text) {
|
|
let escapedText = text;
|
|
const hasSpace = text.indexOf(' ') !== -1;
|
|
const hasDoubleQuote = text.indexOf('"') !== -1;
|
|
|
|
// Encapsulate value with quotes if it has spaces
|
|
// Known side effect: values's with both single and double quotes
|
|
// won't escape properly
|
|
if (hasSpace) {
|
|
if (hasDoubleQuote) {
|
|
escapedText = `'${text}'`;
|
|
} else {
|
|
// Encapsulate singleQuotes or if it hasSpace
|
|
escapedText = `"${text}"`;
|
|
}
|
|
}
|
|
|
|
return escapedText;
|
|
}
|
|
|
|
static filterWithSymbol(filterSymbol, input, item) {
|
|
const updatedItem = item;
|
|
const query = gl.DropdownUtils.getSearchInput(input);
|
|
const { lastToken, searchToken } = gl.FilteredSearchTokenizer.processTokens(query);
|
|
|
|
if (lastToken !== searchToken) {
|
|
const title = updatedItem.title.toLowerCase();
|
|
let value = lastToken.value.toLowerCase();
|
|
value = value.replace(/"(.*?)"/g, str => str.slice(1).slice(0, -1));
|
|
|
|
// Eg. filterSymbol = ~ for labels
|
|
const matchWithoutSymbol = lastToken.symbol === filterSymbol && title.indexOf(value) !== -1;
|
|
const match = title.indexOf(`${lastToken.symbol}${value}`) !== -1;
|
|
|
|
updatedItem.droplab_hidden = !match && !matchWithoutSymbol;
|
|
} else {
|
|
updatedItem.droplab_hidden = false;
|
|
}
|
|
|
|
return updatedItem;
|
|
}
|
|
|
|
static filterHint(input, item) {
|
|
const updatedItem = item;
|
|
const query = gl.DropdownUtils.getSearchInput(input);
|
|
let { lastToken } = gl.FilteredSearchTokenizer.processTokens(query);
|
|
lastToken = lastToken.key || lastToken || '';
|
|
|
|
if (!lastToken || query.split('').last() === ' ') {
|
|
updatedItem.droplab_hidden = false;
|
|
} else if (lastToken) {
|
|
const split = lastToken.split(':');
|
|
const tokenName = split[0].split(' ').last();
|
|
|
|
const match = updatedItem.hint.indexOf(tokenName.toLowerCase()) === -1;
|
|
updatedItem.droplab_hidden = tokenName ? match : false;
|
|
}
|
|
|
|
return updatedItem;
|
|
}
|
|
|
|
static setDataValueIfSelected(filter, selected) {
|
|
const dataValue = selected.getAttribute('data-value');
|
|
|
|
if (dataValue) {
|
|
gl.FilteredSearchDropdownManager.addWordToInput(filter, dataValue);
|
|
}
|
|
|
|
// Return boolean based on whether it was set
|
|
return dataValue !== null;
|
|
}
|
|
|
|
static getSearchInput(filteredSearchInput) {
|
|
const inputValue = filteredSearchInput.value;
|
|
const { right } = gl.DropdownUtils.getInputSelectionPosition(filteredSearchInput);
|
|
|
|
return inputValue.slice(0, right);
|
|
}
|
|
|
|
static getInputSelectionPosition(input) {
|
|
const selectionStart = input.selectionStart;
|
|
let inputValue = input.value;
|
|
// Replace all spaces inside quote marks with underscores
|
|
// This helps with matching the beginning & end of a token:key
|
|
inputValue = inputValue.replace(/"(.*?)"/g, str => str.replace(/\s/g, '_'));
|
|
|
|
// Get the right position for the word selected
|
|
// Regex matches first space
|
|
let right = inputValue.slice(selectionStart).search(/\s/);
|
|
|
|
if (right >= 0) {
|
|
right += selectionStart;
|
|
} else if (right < 0) {
|
|
right = inputValue.length;
|
|
}
|
|
|
|
// Get the left position for the word selected
|
|
// Regex matches last non-whitespace character
|
|
let left = inputValue.slice(0, right).search(/\S+$/);
|
|
|
|
if (selectionStart === 0) {
|
|
left = 0;
|
|
} else if (selectionStart === inputValue.length && left < 0) {
|
|
left = inputValue.length;
|
|
} else if (left < 0) {
|
|
left = selectionStart;
|
|
}
|
|
|
|
return {
|
|
left,
|
|
right,
|
|
};
|
|
}
|
|
}
|
|
|
|
window.gl = window.gl || {};
|
|
gl.DropdownUtils = DropdownUtils;
|
|
})();
|