Commit 79f0044d authored by Marvin Karegyeya's avatar Marvin Karegyeya Committed by Kushal Pandya

Refactor gl dropdown.js

parent b4a2ba41
/* eslint-disable func-names, no-underscore-dangle, one-var, no-cond-assign, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, no-param-reassign, no-loop-func */
/* eslint-disable one-var, consistent-return */
import $ from 'jquery';
import _ from 'underscore';
......@@ -32,8 +32,8 @@ const FILTER_INPUT = '.dropdown-input .dropdown-input-field:not(.dropdown-no-fil
const NO_FILTER_INPUT = '.dropdown-input .dropdown-input-field.dropdown-no-filter';
function GitLabDropdownInput(input, options) {
const _this = this;
class GitLabDropdownInput {
constructor(input, options) {
this.input = input;
this.options = options;
this.fieldName = this.options.fieldName || 'field-name';
......@@ -57,29 +57,32 @@ function GitLabDropdownInput(input, options) {
}
})
.on('input', e => {
let val = e.currentTarget.value || _this.options.inputFieldName;
let val = e.currentTarget.value || this.options.inputFieldName;
val = val
.split(' ')
.join('-') // replaces space with dash
.replace(/[^a-zA-Z0-9 -]/g, '')
.toLowerCase() // replace non alphanumeric
.replace(/(-)\1+/g, '-'); // replace repeated dashes
_this.cb(_this.options.fieldName, val, {}, true);
_this.input
this.cb(this.options.fieldName, val, {}, true);
this.input
.closest('.dropdown')
.find('.dropdown-toggle-text')
.text(val);
});
}
}
GitLabDropdownInput.prototype.onInput = function(cb) {
onInput(cb) {
this.cb = cb;
};
}
}
function GitLabDropdownFilter(input, options) {
class GitLabDropdownFilter {
constructor(input, options) {
let ref, timeout;
this.input = input;
this.options = options;
// eslint-disable-next-line no-cond-assign
this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true;
const $inputContainer = this.input.parent();
const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
......@@ -110,6 +113,7 @@ function GitLabDropdownFilter(input, options) {
// Only filter asynchronously only if option remote is set
if (this.options.remote) {
clearTimeout(timeout);
// eslint-disable-next-line no-return-assign
return (timeout = setTimeout(() => {
$inputContainer.parent().addClass('is-loading');
......@@ -118,35 +122,34 @@ function GitLabDropdownFilter(input, options) {
return this.options.callback(data);
});
}, 250));
} else {
return this.filter(this.input.val());
}
return this.filter(this.input.val());
});
}
}
GitLabDropdownFilter.prototype.shouldBlur = function(keyCode) {
static shouldBlur(keyCode) {
return BLUR_KEYCODES.indexOf(keyCode) !== -1;
};
}
GitLabDropdownFilter.prototype.filter = function(search_text) {
let elements, group, key, results, tmp;
filter(searchText) {
let group, results, tmp;
if (this.options.onFilter) {
this.options.onFilter(search_text);
this.options.onFilter(searchText);
}
const data = this.options.data();
if (data != null && !this.options.filterByText) {
results = data;
if (search_text !== '') {
if (searchText !== '') {
// When data is an array of objects therefore [object Array] e.g.
// [
// { prop: 'foo' },
// { prop: 'baz' }
// ]
if (_.isArray(data)) {
results = fuzzaldrinPlus.filter(data, search_text, {
results = fuzzaldrinPlus.filter(data, searchText, {
key: this.options.keys,
});
} else {
}
// If data is grouped therefore an [object Object]. e.g.
// {
// groupName1: [
......@@ -158,33 +161,32 @@ GitLabDropdownFilter.prototype.filter = function(search_text) {
// { prop: 'def' }
// ]
// }
if (isObject(data)) {
else if (isObject(data)) {
results = {};
for (key in data) {
Object.keys(data).forEach(key => {
group = data[key];
tmp = fuzzaldrinPlus.filter(group, search_text, {
tmp = fuzzaldrinPlus.filter(group, searchText, {
key: this.options.keys,
});
if (tmp.length) {
results[key] = tmp.map(item => item);
}
}
}
});
}
}
return this.options.callback(results);
} else {
elements = this.options.elements();
if (search_text) {
}
const elements = this.options.elements();
if (searchText) {
// eslint-disable-next-line func-names
elements.each(function() {
const $el = $(this);
const matches = fuzzaldrinPlus.match($el.text().trim(), search_text);
const matches = fuzzaldrinPlus.match($el.text().trim(), searchText);
if (!$el.is('.dropdown-header')) {
if (matches.length) {
return $el.show().removeClass('option-hidden');
} else {
return $el.hide().addClass('option-hidden');
}
return $el.hide().addClass('option-hidden');
}
});
} else {
......@@ -196,14 +198,15 @@ GitLabDropdownFilter.prototype.filter = function(search_text) {
.find('.dropdown-menu-empty-item')
.toggleClass('hidden', elements.is(':visible'));
}
};
}
function GitLabDropdownRemote(dataEndpoint, options) {
class GitLabDropdownRemote {
constructor(dataEndpoint, options) {
this.dataEndpoint = dataEndpoint;
this.options = options;
}
}
GitLabDropdownRemote.prototype.execute = function() {
execute() {
if (typeof this.dataEndpoint === 'string') {
return this.fetchData();
} else if (typeof this.dataEndpoint === 'function') {
......@@ -220,9 +223,9 @@ GitLabDropdownRemote.prototype.execute = function() {
}
});
}
};
}
GitLabDropdownRemote.prototype.fetchData = function() {
fetchData() {
if (this.options.beforeSend) {
this.options.beforeSend();
}
......@@ -233,9 +236,11 @@ GitLabDropdownRemote.prototype.fetchData = function() {
return this.options.success(data);
}
});
};
}
}
function GitLabDropdown(el1, options) {
class GitLabDropdown {
constructor(el1, options) {
let selector, self;
this.el = el1;
this.options = options;
......@@ -251,7 +256,8 @@ function GitLabDropdown(el1, options) {
this.noFilterInput = this.options.noFilterInput || this.getElement(NO_FILTER_INPUT);
this.highlight = Boolean(this.options.highlight);
this.icon = Boolean(this.options.icon);
this.filterInputBlur = this.options.filterInputBlur != null ? this.options.filterInputBlur : true;
this.filterInputBlur =
this.options.filterInputBlur != null ? this.options.filterInputBlur : true;
// If no input is passed create a default one
self = this;
// If selector was passed
......@@ -391,18 +397,18 @@ function GitLabDropdown(el1, options) {
$el.trigger('blur');
});
}
}
}
// Finds an element inside wrapper element
GitLabDropdown.prototype.getElement = function(selector) {
// Finds an element inside wrapper element
getElement(selector) {
return this.dropdown.find(selector);
};
}
GitLabDropdown.prototype.toggleLoading = function() {
toggleLoading() {
return $('.dropdown-menu', this.dropdown).toggleClass(LOADING_CLASS);
};
}
GitLabDropdown.prototype.togglePage = function() {
togglePage() {
const menu = $('.dropdown-menu', this.dropdown);
if (menu.hasClass(PAGE_TWO_CLASS)) {
if (this.remote) {
......@@ -412,19 +418,20 @@ GitLabDropdown.prototype.togglePage = function() {
menu.toggleClass(PAGE_TWO_CLASS);
// Focus first visible input on active page
return this.dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus();
};
}
GitLabDropdown.prototype.parseData = function(data) {
let groupData, html, name;
parseData(data) {
let groupData, html;
this.renderedData = data;
if (this.options.filterable && data.length === 0) {
// render no matching results
html = [this.noResults()];
} else {
}
// Handle array groups
if (isObject(data)) {
else if (isObject(data)) {
html = [];
for (name in data) {
Object.keys(data).forEach(name => {
groupData = data[name];
html.push(
this.renderItem(
......@@ -436,22 +443,21 @@ GitLabDropdown.prototype.parseData = function(data) {
),
);
this.renderData(groupData, name).map(item => html.push(item));
}
});
} else {
// Render each row
html = this.renderData(data);
}
}
// Render the full menu
const full_html = this.renderMenu(html);
return this.appendMenu(full_html);
};
const fullHtml = this.renderMenu(html);
return this.appendMenu(fullHtml);
}
GitLabDropdown.prototype.renderData = function(data, group) {
renderData(data, group) {
return data.map((obj, index) => this.renderItem(obj, group || false, index));
};
}
GitLabDropdown.prototype.shouldPropagate = function(e) {
shouldPropagate(e) {
let $target;
if (this.options.multiSelect || this.options.shouldPropagate === false) {
$target = $(e.target);
......@@ -471,18 +477,18 @@ GitLabDropdown.prototype.shouldPropagate = function(e) {
return true;
}
};
}
GitLabDropdown.prototype.filteredFullData = function() {
filteredFullData() {
return this.fullData.filter(
r =>
typeof r === 'object' &&
!Object.prototype.hasOwnProperty.call(r, 'beforeDivider') &&
!Object.prototype.hasOwnProperty.call(r, 'header'),
);
};
}
GitLabDropdown.prototype.opened = function(e) {
opened(e) {
this.resetRows();
this.addArrowKeyEvent();
......@@ -528,17 +534,17 @@ GitLabDropdown.prototype.opened = function(e) {
}
return this.dropdown.trigger('shown.gl.dropdown');
};
}
GitLabDropdown.prototype.positionMenuAbove = function() {
positionMenuAbove() {
const $menu = this.dropdown.find('.dropdown-menu');
$menu.addClass('dropdown-open-top');
$menu.css('top', 'initial');
$menu.css('bottom', '100%');
};
}
GitLabDropdown.prototype.hidden = function(e) {
hidden(e) {
this.resetRows();
this.removeArrowKeyEvent();
const $input = this.dropdown.find('.dropdown-input-field');
......@@ -552,25 +558,23 @@ GitLabDropdown.prototype.hidden = function(e) {
this.options.hidden.call(this, e);
}
return this.dropdown.trigger('hidden.gl.dropdown');
};
}
// Render the full menu
GitLabDropdown.prototype.renderMenu = function(html) {
// Render the full menu
renderMenu(html) {
if (this.options.renderMenu) {
return this.options.renderMenu(html);
} else {
}
return $('<ul>').append(html);
}
};
// Append the menu into the dropdown
GitLabDropdown.prototype.appendMenu = function(html) {
// Append the menu into the dropdown
appendMenu(html) {
return this.clearMenu().append(html);
};
}
GitLabDropdown.prototype.clearMenu = function() {
let selector;
selector = '.dropdown-content';
clearMenu() {
let selector = '.dropdown-content';
if (this.dropdown.find('.dropdown-toggle-page').length) {
if (this.options.containerSelector) {
selector = this.options.containerSelector;
......@@ -580,9 +584,9 @@ GitLabDropdown.prototype.clearMenu = function() {
}
return $(selector, this.dropdown).empty();
};
}
GitLabDropdown.prototype.renderItem = function(data, group, index) {
renderItem(data, group, index) {
let parent;
if (this.dropdown && this.dropdown[0]) {
......@@ -602,13 +606,15 @@ GitLabDropdown.prototype.renderItem = function(data, group, index) {
group,
index,
});
};
}
GitLabDropdown.prototype.highlightTemplate = function(text, template) {
// eslint-disable-next-line class-methods-use-this
highlightTemplate(text, template) {
return `"<b>${_.escape(text)}</b>" ${template}`;
};
}
GitLabDropdown.prototype.highlightTextMatches = function(text, term) {
// eslint-disable-next-line class-methods-use-this
highlightTextMatches(text, term) {
const occurrences = fuzzaldrinPlus.match(text, term);
const { indexOf } = [];
......@@ -617,18 +623,18 @@ GitLabDropdown.prototype.highlightTextMatches = function(text, term) {
.map((character, i) => {
if (indexOf.call(occurrences, i) !== -1) {
return `<b>${character}</b>`;
} else {
return character;
}
return character;
})
.join('');
};
}
GitLabDropdown.prototype.noResults = function() {
// eslint-disable-next-line class-methods-use-this
noResults() {
return '<li class="dropdown-menu-empty-item"><a>No matching results</a></li>';
};
}
GitLabDropdown.prototype.rowClicked = function(el) {
rowClicked(el) {
let field, groupName, selectedIndex, selectedObject, isMarking;
const { fieldName } = this.options;
const isInput = $(this.el).is('input');
......@@ -710,9 +716,9 @@ GitLabDropdown.prototype.rowClicked = function(el) {
}
return [selectedObject, isMarking];
};
}
GitLabDropdown.prototype.focusTextInput = function() {
focusTextInput() {
if (this.options.filterable) {
const initialScrollTop = $(window).scrollTop();
......@@ -724,9 +730,9 @@ GitLabDropdown.prototype.focusTextInput = function() {
$(window).scrollTop(initialScrollTop);
}
}
};
}
GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject, single) {
addInput(fieldName, value, selectedObject, single) {
// Create hidden input for form
if (single) {
$(`input[name="${fieldName}"]`).remove();
......@@ -751,11 +757,11 @@ GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject, s
}
this.dropdown.before($input).trigger('change');
};
}
GitLabDropdown.prototype.selectRowAtIndex = function(index) {
let selector;
selectRowAtIndex(index) {
// If we pass an option index
let selector;
if (typeof index !== 'undefined') {
selector = `${SELECTABLE_CLASSES}:eq(${index}) a`;
} else {
......@@ -774,12 +780,11 @@ GitLabDropdown.prototype.selectRowAtIndex = function(index) {
$el.trigger('click');
}
}
};
}
GitLabDropdown.prototype.addArrowKeyEvent = function() {
let selector;
addArrowKeyEvent() {
const ARROW_KEY_CODES = [38, 40];
selector = SELECTABLE_CLASSES;
let selector = SELECTABLE_CLASSES;
if (this.dropdown.find('.dropdown-toggle-page').length) {
selector = `.dropdown-page-one ${selector}`;
}
......@@ -814,19 +819,21 @@ GitLabDropdown.prototype.addArrowKeyEvent = function() {
this.selectRowAtIndex();
}
});
};
}
GitLabDropdown.prototype.removeArrowKeyEvent = function() {
// eslint-disable-next-line class-methods-use-this
removeArrowKeyEvent() {
return $('body').off('keydown');
};
}
GitLabDropdown.prototype.resetRows = function resetRows() {
resetRows() {
currentIndex = -1;
$('.is-focused', this.dropdown).removeClass('is-focused');
};
}
GitLabDropdown.prototype.highlightRowAtIndex = function($listItems, index) {
highlightRowAtIndex($listItems, index) {
if (!$listItems) {
// eslint-disable-next-line no-param-reassign
$listItems = $(SELECTABLE_CLASSES, this.dropdown);
}
......@@ -862,19 +869,9 @@ GitLabDropdown.prototype.highlightRowAtIndex = function($listItems, index) {
listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING,
);
}
};
GitLabDropdown.prototype.updateLabel = function(selected, el, instance) {
if (selected == null) {
selected = null;
}
if (el == null) {
el = null;
}
if (instance == null) {
instance = null;
}
updateLabel(selected = null, el = null, instance = null) {
let toggleText = this.options.toggleLabel(selected, el, instance);
if (this.options.updateLabel) {
// Option to override the dropdown label text
......@@ -884,13 +881,17 @@ GitLabDropdown.prototype.updateLabel = function(selected, el, instance) {
return $(this.el)
.find('.dropdown-toggle-text')
.text(toggleText);
};
}
GitLabDropdown.prototype.clearField = function(field, isInput) {
// eslint-disable-next-line class-methods-use-this
clearField(field, isInput) {
return isInput ? field.val('') : field.remove();
};
}
}
// eslint-disable-next-line func-names
$.fn.glDropdown = function(opts) {
// eslint-disable-next-line func-names
return this.each(function() {
if (!$.data(this, 'glDropdown')) {
return $.data(this, 'glDropdown', new GitLabDropdown(this, opts));
......
---
title: refactoring gl_dropdown.js to use ES6 classes instead of constructor functions
merge_request: 20488
author: nuwe1
type: other
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