Commit c349bb15 authored by Clement Ho's avatar Clement Ho

Refactor addWordToInput

parent 8f77b317
......@@ -4,8 +4,8 @@
(() => {
class DropdownHint extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input) {
super(droplab, dropdown, input);
constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input, filter);
this.config = {
droplabFilter: {
template: 'hint',
......@@ -25,7 +25,7 @@
const tag = selected.querySelector('.js-filter-tag').innerText.trim();
if (tag.length) {
gl.FilteredSearchDropdownManager.addWordToInput(token);
gl.FilteredSearchDropdownManager.addWordToInput(token.replace(':', ''));
}
this.dismissDropdown();
this.dispatchInputEvent();
......
......@@ -5,8 +5,8 @@
(() => {
class DropdownNonUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, endpoint, symbol) {
super(droplab, dropdown, input);
constructor(droplab, dropdown, input, filter, endpoint, symbol) {
super(droplab, dropdown, input, filter);
this.symbol = symbol;
this.config = {
droplabAjax: {
......
......@@ -4,8 +4,8 @@
(() => {
class DropdownUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input) {
super(droplab, dropdown, input);
constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input, filter);
this.config = {
droplabAjaxFilter: {
endpoint: '/autocomplete/users.json',
......
......@@ -58,11 +58,11 @@
return updatedItem;
}
static setDataValueIfSelected(selected) {
static setDataValueIfSelected(filter, selected) {
const dataValue = selected.getAttribute('data-value');
if (dataValue) {
gl.FilteredSearchDropdownManager.addWordToInput(dataValue);
gl.FilteredSearchDropdownManager.addWordToInput(filter, dataValue);
}
// Return boolean based on whether it was set
......
......@@ -2,10 +2,11 @@
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
class FilteredSearchDropdown {
constructor(droplab, dropdown, input) {
constructor(droplab, dropdown, input, filter) {
this.droplab = droplab;
this.hookId = input.getAttribute('data-id');
this.input = input;
this.filter = filter;
this.dropdown = dropdown;
this.loadingTemplate = `<div class="filter-dropdown-loading">
<i class="fa fa-spinner fa-spin"></i>
......@@ -30,11 +31,11 @@
const { selected } = e.detail;
if (selected.tagName === 'LI' && selected.innerHTML) {
const dataValueSet = gl.DropdownUtils.setDataValueIfSelected(selected);
const dataValueSet = gl.DropdownUtils.setDataValueIfSelected(this.filter, selected);
if (!dataValueSet) {
const value = getValueFunction(selected);
gl.FilteredSearchDropdownManager.addWordToInput(value);
gl.FilteredSearchDropdownManager.addWordToInput(this.filter, value);
}
this.dismissDropdown();
......
......@@ -55,31 +55,30 @@
};
}
static addWordToInput(word, addSpace = false) {
static addWordToInput(tokenName, tokenValue = '') {
const input = document.querySelector('.filtered-search');
input.value = input.value.trim();
const word = `${tokenName}:${tokenValue}`;
const value = input.value;
const hasExistingValue = value.length !== 0;
const { lastToken, searchToken } = gl.FilteredSearchTokenizer.processTokens(value);
const { lastToken, searchToken } = gl.FilteredSearchTokenizer.processTokens(input.value);
const lastSearchToken = searchToken.split(' ').last();
// Find out what part of the token value the user has typed
// and remove it from input before appending the selected token value
if (lastToken !== searchToken) {
const lastTokenString = `${lastToken.symbol}${lastToken.value}`;
// Spaces inside the token means that the token value will be escaped by quotes
const hasQuotes = lastTokenString.indexOf(' ') !== -1;
// Add 2 length to account for the length of the front and back quotes
const lengthToRemove = hasQuotes ? lastTokenString.length + 2 : lastTokenString.length;
input.value = value.slice(0, -1 * (lengthToRemove));
} else if (searchToken !== '' && word.indexOf(lastSearchToken) !== -1) {
input.value = value.slice(0, -1 * lastSearchToken.length);
const lastInputCharacter = input.value[input.value.length - 1];
const lastInputTrimmedCharacter = input.value.trim()[input.value.trim().length - 1];
// Remove the typed tokenName
if (word.indexOf(lastSearchToken) === 0 && searchToken !== '') {
// Remove spaces after the colon
if (lastInputCharacter === ' ' && lastInputTrimmedCharacter === ':') {
input.value = input.value.trim();
}
input.value = input.value.slice(0, -1 * lastSearchToken.length);
} else if (lastInputCharacter !== ' ') {
// Remove the existing tokenValue
const lastTokenString = `${lastToken.key}:${lastToken.symbol}${lastToken.value}`;
input.value = input.value.slice(0, -1 * lastTokenString.length);
}
input.value += hasExistingValue && addSpace ? ` ${word}` : word;
input.value += word;
}
updateCurrentDropdownOffset() {
......@@ -106,7 +105,7 @@
if (!mappingKey.reference) {
const dl = this.droplab;
const defaultArguments = [null, dl, element, this.filteredSearchInput];
const defaultArguments = [null, dl, element, this.filteredSearchInput, key];
const glArguments = defaultArguments.concat(mappingKey.extraArguments || []);
// Passing glArguments to `new gl[glClass](<arguments>)`
......
//= require extensions/array
//= require filtered_search/filtered_search_tokenizer
//= require filtered_search/filtered_search_dropdown_manager
......@@ -8,6 +9,10 @@
return document.querySelector('.filtered-search').value;
}
function setInputValue(value) {
document.querySelector('.filtered-search').value = value;
}
beforeEach(() => {
const input = document.createElement('input');
input.classList.add('filtered-search');
......@@ -19,47 +24,33 @@
});
describe('input has no existing value', () => {
it('should add word', () => {
gl.FilteredSearchDropdownManager.addWordToInput('firstWord');
expect(getInputValue()).toBe('firstWord');
});
it('should not add space before first word', () => {
gl.FilteredSearchDropdownManager.addWordToInput('firstWord', true);
expect(getInputValue()).toBe('firstWord');
it('should add just tokenName', () => {
gl.FilteredSearchDropdownManager.addWordToInput('milestone');
expect(getInputValue()).toBe('milestone:');
});
it('should not add space before second word by default', () => {
gl.FilteredSearchDropdownManager.addWordToInput('firstWord');
expect(getInputValue()).toBe('firstWord');
gl.FilteredSearchDropdownManager.addWordToInput('secondWord');
expect(getInputValue()).toBe('firstWordsecondWord');
});
it('should add space before new word when addSpace is passed', () => {
expect(getInputValue()).toBe('');
gl.FilteredSearchDropdownManager.addWordToInput('firstWord');
expect(getInputValue()).toBe('firstWord');
gl.FilteredSearchDropdownManager.addWordToInput('secondWord', true);
expect(getInputValue()).toBe('firstWord secondWord');
it('should add tokenName and tokenValue', () => {
gl.FilteredSearchDropdownManager.addWordToInput('label', 'none');
expect(getInputValue()).toBe('label:none');
});
});
describe('input has exsting value', () => {
it('should only add the remaining characters of the word', () => {
const lastToken = {
key: 'author',
value: 'roo',
};
describe('input has existing value', () => {
it('should be able to just add tokenName', () => {
setInputValue('a');
gl.FilteredSearchDropdownManager.addWordToInput('author');
expect(getInputValue()).toBe('author:');
});
document.querySelector('.filtered-search').value = `${lastToken.key}:${lastToken.value}`;
gl.FilteredSearchDropdownManager.addWordToInput('root');
expect(getInputValue()).toBe('author:root');
it('should replace tokenValue', () => {
setInputValue('author:roo');
gl.FilteredSearchDropdownManager.addWordToInput('author', '@root');
expect(getInputValue()).toBe('author:@root');
});
it('should only add the remaining characters of the word (contains space)', () => {
document.querySelector('.filtered-search').value = 'label:~"test';
gl.FilteredSearchDropdownManager.addWordToInput('~\'"test me"\'');
it('should add tokenValues containing spaces', () => {
setInputValue('label:~"test');
gl.FilteredSearchDropdownManager.addWordToInput('label', '~\'"test me"\'');
expect(getInputValue()).toBe('label:~\'"test me"\'');
});
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment