summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClement Ho <ClemMakesApps@gmail.com>2017-02-24 10:09:53 -0600
committerClement Ho <ClemMakesApps@gmail.com>2017-03-01 10:14:08 -0600
commit7f337c9ded66f1b90b689ee2f5563dbb091ca942 (patch)
tree91ffcef01930435c8b39ab1c9ce1435cd7e43d97
parent6d10767fb6bb5197f20260203264739bbb0e0e4a (diff)
downloadgitlab-ce-highlight-selected-tokens-deletable.tar.gz
Allow visual tokens to be deletable after selectionhighlight-selected-tokens-deletable
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js.es613
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js.es69
-rw-r--r--spec/javascripts/filtered_search/filtered_search_manager_spec.js.es682
-rw-r--r--spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js.es622
4 files changed, 111 insertions, 15 deletions
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
index d216fff07e3..935daf3199b 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
@@ -33,6 +33,7 @@
this.checkForEnterWrapper = this.checkForEnter.bind(this);
this.clearSearchWrapper = this.clearSearch.bind(this);
this.checkForBackspaceWrapper = this.checkForBackspace.bind(this);
+ this.removeSelectedTokenWrapper = this.removeSelectedToken.bind(this);
this.tokenChange = this.tokenChange.bind(this);
this.filteredSearchInput.form.addEventListener('submit', this.handleFormSubmit);
@@ -47,6 +48,7 @@
this.tokensContainer.addEventListener('click', FilteredSearchManager.selectToken);
this.clearSearchButton.addEventListener('click', this.clearSearchWrapper);
document.addEventListener('click', gl.FilteredSearchVisualTokens.unselectTokens);
+ document.addEventListener('keydown', this.removeSelectedTokenWrapper);
}
unbindEvents() {
@@ -62,6 +64,7 @@
this.tokensContainer.removeEventListener('click', FilteredSearchManager.selectToken);
this.clearSearchButton.removeEventListener('click', this.clearSearchWrapper);
document.removeEventListener('click', gl.FilteredSearchVisualTokens.unselectTokens);
+ document.removeEventListener('keydown', this.removeSelectedTokenWrapper);
}
checkForBackspace(e) {
@@ -138,6 +141,16 @@
}
}
+ removeSelectedToken(e) {
+ // 8 = Backspace Key
+ // 46 = Delete Key
+ if (e.keyCode === 8 || e.keyCode === 46) {
+ gl.FilteredSearchVisualTokens.removeSelectedToken();
+ this.handleInputPlaceholder();
+ this.toggleClearSearchButton();
+ }
+ }
+
clearSearch(e) {
e.preventDefault();
diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js.es6
index 3b04c6ef6fa..4f3efea8e16 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js.es6
@@ -23,6 +23,15 @@ class FilteredSearchVisualTokens {
}
}
+ static removeSelectedToken() {
+ const selected = document.querySelector('.js-visual-token .selected');
+
+ if (selected) {
+ const li = selected.closest('.js-visual-token');
+ li.parentElement.removeChild(li);
+ }
+ }
+
static addVisualTokenElement(name, value, isSearchTerm) {
const li = document.createElement('li');
li.classList.add('js-visual-token');
diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6
index 51582251cbe..8312928a8c5 100644
--- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6
+++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6
@@ -13,6 +13,20 @@ const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper
let tokensContainer;
const placeholder = 'Search or filter results...';
+ function dispatchBackspaceEvent(element, eventType) {
+ const backspaceKey = 8;
+ const event = new Event(eventType);
+ event.keyCode = backspaceKey;
+ element.dispatchEvent(event);
+ }
+
+ function dispatchDeleteEvent(element, eventType) {
+ const deleteKey = 46;
+ const event = new Event(eventType);
+ event.keyCode = deleteKey;
+ element.dispatchEvent(event);
+ }
+
beforeEach(() => {
setFixtures(`
<form>
@@ -99,9 +113,6 @@ const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper
});
describe('checkForBackspace', () => {
- const backspaceKey = 8;
- const deleteKey = 46;
-
describe('tokens and no input', () => {
beforeEach(() => {
tokensContainer.innerHTML = FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug');
@@ -109,20 +120,14 @@ const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper
it('removes last token', () => {
spyOn(gl.FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
-
- const event = new Event('keyup');
- event.keyCode = backspaceKey;
- input.dispatchEvent(event);
+ dispatchBackspaceEvent(input, 'keyup');
expect(gl.FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
});
it('sets the input', () => {
spyOn(gl.FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
-
- const event = new Event('keyup');
- event.keyCode = deleteKey;
- input.dispatchEvent(event);
+ dispatchDeleteEvent(input, 'keyup');
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial).toHaveBeenCalled();
expect(input.value).toEqual('~bug');
@@ -134,10 +139,7 @@ const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper
spyOn(gl.FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
input.value = 'text';
-
- const event = new Event('keyup');
- event.keyCode = deleteKey;
- input.dispatchEvent(event);
+ dispatchDeleteEvent(input, 'keyup');
expect(gl.FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled();
@@ -145,6 +147,56 @@ const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper
});
});
+ describe('removeSelectedToken', () => {
+ beforeEach(() => {
+ tokensContainer.innerHTML = FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', 'none', true);
+ });
+
+ it('removes selected token when the backspace key is pressed', () => {
+ expect(tokensContainer.children.length).toEqual(1);
+
+ dispatchBackspaceEvent(document, 'keydown');
+
+ expect(tokensContainer.children.length).toEqual(0);
+ });
+
+ it('removes selected token when the delete key is pressed', () => {
+ tokensContainer.innerHTML = FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', 'none', true);
+
+ expect(tokensContainer.children.length).toEqual(1);
+
+ dispatchDeleteEvent(document, 'keydown');
+
+ expect(tokensContainer.children.length).toEqual(0);
+ });
+
+ it('updates the input placeholder after removal', () => {
+ manager.handleInputPlaceholder();
+
+ expect(input.placeholder).toEqual('');
+ expect(tokensContainer.children.length).toEqual(1);
+
+ dispatchBackspaceEvent(document, 'keydown');
+
+ expect(input.placeholder).not.toEqual('');
+ expect(tokensContainer.children.length).toEqual(0);
+ });
+
+ it('updates the clear button after removal', () => {
+ manager.toggleClearSearchButton();
+
+ const clearButton = document.querySelector('.clear-search');
+
+ expect(clearButton.classList.contains('hidden')).toEqual(false);
+ expect(tokensContainer.children.length).toEqual(1);
+
+ dispatchBackspaceEvent(document, 'keydown');
+
+ expect(clearButton.classList.contains('hidden')).toEqual(true);
+ expect(tokensContainer.children.length).toEqual(0);
+ });
+ });
+
describe('unselects token', () => {
beforeEach(() => {
tokensContainer.innerHTML = `
diff --git a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js.es6
index ff21d096f9d..4d6eda83e79 100644
--- a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js.es6
+++ b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js.es6
@@ -138,6 +138,28 @@ const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper
});
});
+ describe('removeSelectedToken', () => {
+ it('does not remove when there are no selected tokens', () => {
+ tokensContainer.innerHTML = FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', 'none');
+
+ expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null);
+
+ gl.FilteredSearchVisualTokens.removeSelectedToken();
+
+ expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null);
+ });
+
+ it('removes selected token', () => {
+ tokensContainer.innerHTML = FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', 'none', true);
+
+ expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null);
+
+ gl.FilteredSearchVisualTokens.removeSelectedToken();
+
+ expect(tokensContainer.querySelector('.js-visual-token .selectable')).toEqual(null);
+ });
+ });
+
describe('addVisualTokenElement', () => {
it('renders search visual tokens', () => {
gl.FilteredSearchVisualTokens.addVisualTokenElement('search term', null, true);