Commit 5589ab1e authored by Clement Ho's avatar Clement Ho

Refactor and add comments

parent 2bbc44cb
......@@ -23,7 +23,6 @@
class DropdownHint extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input) {
super(droplab, dropdown, input);
this.listId = dropdown.id;
this.config = {
droplabFilter: {
template: 'hint',
......@@ -66,7 +65,7 @@
return item;
}
configure() {
init() {
this.droplab.addHook(this.input, this.dropdown, [droplabFilter], this.config).init();
}
}
......
......@@ -5,7 +5,6 @@
class DropdownNonUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, endpoint, symbol) {
super(droplab, dropdown, input);
this.listId = dropdown.id;
this.symbol = symbol;
this.config = {
droplabAjax: {
......@@ -28,15 +27,17 @@
getEscapedText(text) {
let escapedText = text;
const hasSpace = text.indexOf(' ') !== -1;
const hasDoubleQuote = text.indexOf('"') !== -1;
const hasSingleQuote = text.indexOf('\'') !== -1;
// Encapsulate value with quotes if it has spaces
if (text.indexOf(' ') !== -1) {
if (text.indexOf('"') !== -1) {
// Use single quotes if value contains double quotes
escapedText = `'${text}'`;
} else {
// Known side effect: values's with both single and double quotes
// won't escape properly
if (hasSpace) {
if (hasDoubleQuote) {
escapedText = `'${text}'`;
} else if (hasSingleQuote) {
escapedText = `"${text}"`;
}
}
......@@ -65,7 +66,7 @@
super.renderContent(forceShowList);
}
configure() {
init() {
this.droplab.addHook(this.input, this.dropdown, [droplabAjax, droplabFilter], this.config).init();
}
}
......
......@@ -5,7 +5,6 @@
class DropdownUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input) {
super(droplab, dropdown, input);
this.listId = dropdown.id;
this.config = {
droplabAjaxFilter: {
endpoint: '/autocomplete/users.json',
......@@ -47,7 +46,7 @@
return hasPrefix ? valueWithoutPrefix : valueWithoutColon;
}
configure() {
init() {
this.droplab.addHook(this.input, this.dropdown, [droplabAjaxFilter], this.config).init();
}
}
......
......@@ -46,14 +46,8 @@
this.dismissDropdown();
}
renderContent(forceShowList = false) {
if (forceShowList && this.getCurrentHook().list.hidden) {
this.getCurrentHook().list.show();
}
}
setAsDropdown() {
this.input.setAttribute(DATA_DROPDOWN_TRIGGER, `#${this.listId}`);
this.input.setAttribute(DATA_DROPDOWN_TRIGGER, `#${this.dropdown.id}`);
}
setOffset(offset = 0) {
......@@ -67,17 +61,14 @@
gl.FilteredSearchDropdownManager.addWordToInput(dataValue);
}
// Return boolean based on whether it was set
return dataValue !== null;
}
dismissDropdown() {
this.input.focus();
renderContent(forceShowList = false) {
if (forceShowList && this.getCurrentHook().list.hidden) {
this.getCurrentHook().list.show();
}
dispatchInputEvent() {
// Propogate input change to FilteredSearchManager
// so that it can determine which dropdowns to open
this.input.dispatchEvent(new Event('input'));
}
render(forceRenderContent = false, forceShowList = false) {
......@@ -88,11 +79,23 @@
if (firstTimeInitialized || forceRenderContent) {
this.renderContent(forceShowList);
} else if(currentHook.list.list.id !== this.listId) {
} else if(currentHook.list.list.id !== this.dropdown.id) {
this.renderContent(forceShowList);
}
}
dismissDropdown() {
// Focusing on the input will dismiss dropdown
// (default droplab functionality)
this.input.focus();
}
dispatchInputEvent() {
// Propogate input change to FilteredSearchDropdownManager
// so that it can determine which dropdowns to open
this.input.dispatchEvent(new Event('input'));
}
hideDropdown() {
this.getCurrentHook().list.hide();
}
......@@ -100,9 +103,7 @@
resetFilters() {
const hook = this.getCurrentHook();
const data = hook.list.data;
const results = data.map(function(o) {
o.droplab_hidden = false;
});
const results = data.map(o => o.droplab_hidden = false);
hook.list.render(results);
}
}
......
......@@ -5,6 +5,8 @@
this.tokenizer = gl.FilteredSearchTokenizer;
this.filteredSearchInput = document.querySelector('.filtered-search');
this.setupMapping();
this.cleanupWrapper = this.cleanup.bind(this);
document.addEventListener('page:fetch', this.cleanupWrapper);
}
......@@ -52,21 +54,22 @@
}
}
static addWordToInput(word, addSpace) {
const filteredSearchInput = document.querySelector('.filtered-search')
const filteredSearchValue = filteredSearchInput.value;
const hasExistingValue = filteredSearchValue.length !== 0;
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(filteredSearchValue);
static addWordToInput(word, addSpace = false) {
const input = document.querySelector('.filtered-search')
const value = input.value;
const hasExistingValue = value.length !== 0;
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(value);
if (lastToken.hasOwnProperty('key')) {
console.log(lastToken);
// Spaces inside the token means that the token value will be escaped by quotes
const hasQuotes = lastToken.value.indexOf(' ') !== -1;
// Add 2 length to account for the length of the front and back quotes
const lengthToRemove = hasQuotes ? lastToken.value.length + 2 : lastToken.value.length;
filteredSearchInput.value = filteredSearchValue.slice(0, -1 * (lengthToRemove));
input.value = value.slice(0, -1 * (lengthToRemove));
}
filteredSearchInput.value += hasExistingValue && addSpace ? ` ${word}` : word;
input.value += hasExistingValue && addSpace ? ` ${word}` : word;
}
updateCurrentDropdownOffset() {
......@@ -74,6 +77,10 @@
}
updateDropdownOffset(key) {
if (!this.font) {
this.font = window.getComputedStyle(this.filteredSearchInput).font;
}
const filterIconPadding = 27;
const offset = gl.text.getTextWidth(this.filteredSearchInput.value, this.font) + filterIconPadding;
......@@ -87,19 +94,20 @@
let forceShowList = false;
if (!this.mapping[key].reference) {
var dl = this.droplab;
const dl = this.droplab;
const defaultArguments = [null, dl, element, this.filteredSearchInput];
const glArguments = defaultArguments.concat(this.mapping[key].extraArguments || []);
// Passing glArguments to `new gl[glClass](<arguments>)`
this.mapping[key].reference = new (Function.prototype.bind.apply(gl[glClass], glArguments));
}
if (firstLoad) {
this.mapping[key].reference.configure();
this.mapping[key].reference.init();
}
if (this.currentDropdown === 'hint') {
// Clicked from hint dropdown
// Force the dropdown to show if it was clicked from the hint dropdown
forceShowList = true;
}
......@@ -117,15 +125,12 @@
this.droplab = new DropLab();
}
if (!this.font) {
this.font = window.getComputedStyle(this.filteredSearchInput).font;
}
const match = gl.FilteredSearchTokenKeys.get().filter(value => value.key === dropdownName.toLowerCase())[0];
const shouldOpenFilterDropdown = match && this.currentDropdown !== match.key && this.mapping.hasOwnProperty(match.key);
const shouldOpenHintDropdown = !match && this.currentDropdown !== 'hint';
if (shouldOpenFilterDropdown || shouldOpenHintDropdown) {
// `hint` is not listed as a tokenKey (since it is not a real `filter`)
const key = match && match.hasOwnProperty('key') ? match.key : 'hint';
this.load(key, firstLoad);
}
......@@ -137,14 +142,12 @@
const { lastToken } = this.tokenizer.processTokens(this.filteredSearchInput.value);
if (typeof lastToken === 'string') {
// Token is not fully initialized yet
// because it has no value
// Token is not fully initialized yet because it has no value
// Eg. token = 'label:'
const { tokenKey } = this.tokenizer.parseToken(lastToken);
this.loadDropdown(tokenKey);
} else if (lastToken.hasOwnProperty('key')) {
// Token has been initialized into an object
// because it has a value
// Token has been initialized into an object because it has a value
this.loadDropdown(lastToken.key);
} else {
this.loadDropdown('hint');
......
/* eslint-disable no-param-reassign */
((global) => {
// TODO: Encapsulate inside class?
function toggleClearSearchButton(e) {
const clearSearchButton = document.querySelector('.clear-search');
......@@ -25,6 +26,7 @@
let conditionIndex = 0;
const validCondition = gl.FilteredSearchTokenKeys.get()
.filter(v => v.conditions && v.conditions.filter((c, index) => {
// TODO: Add comment here
if (c.url === p) {
conditionIndex = index;
}
......@@ -32,6 +34,7 @@
})[0])[0];
if (validCondition) {
// Parse params based on rules provided in the conditions key of gl.FilteredSearchTokenKeys.get()
inputValue += `${validCondition.key}:${validCondition.conditions[conditionIndex].keyword}`;
inputValue += ' ';
} else {
......@@ -77,7 +80,6 @@
this.clearSearchButton = document.querySelector('.clear-search');
this.dropdownManager = new gl.FilteredSearchDropdownManager();
this.dropdownManager.setupMapping();
this.bindEvents();
loadSearchParamsFromURL();
this.dropdownManager.setDropdown();
......@@ -130,7 +132,6 @@
}
checkForEnter(e) {
// Enter KeyCode
if (e.keyCode === 13) {
e.stopPropagation();
e.preventDefault();
......@@ -143,7 +144,6 @@
}
search() {
console.log('search');
let path = '?scope=all&utf8=✓';
// Check current state
......@@ -152,9 +152,10 @@
const defaultState = 'opened';
let currentState = defaultState;
const { tokens, searchToken } = this.tokenizer.processTokens(document.querySelector('.filtered-search').value);
const { tokens, searchToken } = this.tokenizer.processTokens(this.filteredSearchInput.value);
if (stateIndex !== -1) {
// TODO: Add comment here
const remaining = currentPath.slice(stateIndex + 6);
const separatorIndex = remaining.indexOf('&');
......
/* eslint-disable no-param-reassign */
((global) => {
class FilteredSearchTokenizer {
// TODO: Remove when going to pro
static printTokens(tokens, searchToken, lastToken) {
console.log('tokens:');
tokens.forEach(token => console.log(token));
console.log(`search: ${searchToken}`);
console.log('last token:');
console.log(lastToken);
}
static parseToken(input) {
const colonIndex = input.indexOf(':');
let tokenKey;
......@@ -163,9 +154,6 @@
searchToken = searchTerms.trim();
// TODO: Remove when going to PRO
gl.FilteredSearchTokenizer.printTokens(tokens, searchToken, lastToken);
return {
tokens,
searchToken,
......
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