Commit 14789225 authored by Mike Greiling's avatar Mike Greiling

Merge branch 'leipert-split-gl-dropdown' into 'master'

Split gl_dropdown prototypes into multiple files

See merge request gitlab-org/gitlab!40437
parents d55ed486 ec9f617f
/* eslint-disable consistent-return */
import $ from 'jquery';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import { isObject } from '~/lib/utils/type_utility';
const BLUR_KEYCODES = [27, 40];
const HAS_VALUE_CLASS = 'has-value';
export class GitLabDropdownFilter {
constructor(input, options) {
let ref;
let 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');
$clearButton.on('click', e => {
// Clear click
e.preventDefault();
e.stopPropagation();
return this.input
.val('')
.trigger('input')
.focus();
});
// Key events
timeout = '';
this.input
.on('keydown', e => {
const keyCode = e.which;
if (keyCode === 13 && !options.elIsInput) {
e.preventDefault();
}
})
.on('input', () => {
if (this.input.val() !== '' && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.addClass(HAS_VALUE_CLASS);
} else if (this.input.val() === '' && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.removeClass(HAS_VALUE_CLASS);
}
// 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');
return this.options.query(this.input.val(), data => {
$inputContainer.parent().removeClass('is-loading');
return this.options.callback(data);
});
}, 250));
}
return this.filter(this.input.val());
});
}
static shouldBlur(keyCode) {
return BLUR_KEYCODES.indexOf(keyCode) !== -1;
}
filter(searchText) {
let group;
let results;
let tmp;
if (this.options.onFilter) {
this.options.onFilter(searchText);
}
const data = this.options.data();
if (data != null && !this.options.filterByText) {
results = data;
if (searchText !== '') {
// When data is an array of objects therefore [object Array] e.g.
// [
// { prop: 'foo' },
// { prop: 'baz' }
// ]
if (Array.isArray(data)) {
results = fuzzaldrinPlus.filter(data, searchText, {
key: this.options.keys,
});
}
// If data is grouped therefore an [object Object]. e.g.
// {
// groupName1: [
// { prop: 'foo' },
// { prop: 'baz' }
// ],
// groupName2: [
// { prop: 'abc' },
// { prop: 'def' }
// ]
// }
else if (isObject(data)) {
results = {};
Object.keys(data).forEach(key => {
group = data[key];
tmp = fuzzaldrinPlus.filter(group, searchText, {
key: this.options.keys,
});
if (tmp.length) {
results[key] = tmp.map(item => item);
}
});
}
}
return this.options.callback(results);
}
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(), searchText);
if (!$el.is('.dropdown-header')) {
if (matches.length) {
return $el.show().removeClass('option-hidden');
}
return $el.hide().addClass('option-hidden');
}
});
} else {
elements.show().removeClass('option-hidden');
}
elements
.parent()
.find('.dropdown-menu-empty-item')
.toggleClass('hidden', elements.is(':visible'));
}
}
export class GitLabDropdownInput {
constructor(input, options) {
this.input = input;
this.options = options;
this.fieldName = this.options.fieldName || 'field-name';
const $inputContainer = this.input.parent();
const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
$clearButton.on('click', e => {
// Clear click
e.preventDefault();
e.stopPropagation();
return this.input
.val('')
.trigger('input')
.focus();
});
this.input
.on('keydown', e => {
const keyCode = e.which;
if (keyCode === 13 && !options.elIsInput) {
e.preventDefault();
}
})
.on('input', e => {
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
.closest('.dropdown')
.find('.dropdown-toggle-text')
.text(val);
});
}
onInput(cb) {
this.cb = cb;
}
}
/* eslint-disable consistent-return */
import axios from '../lib/utils/axios_utils';
export class GitLabDropdownRemote {
constructor(dataEndpoint, options) {
this.dataEndpoint = dataEndpoint;
this.options = options;
}
execute() {
if (typeof this.dataEndpoint === 'string') {
return this.fetchData();
} else if (typeof this.dataEndpoint === 'function') {
if (this.options.beforeSend) {
this.options.beforeSend();
}
return this.dataEndpoint('', data => {
// Fetch the data by calling the data function
if (this.options.success) {
this.options.success(data);
}
if (this.options.beforeSend) {
return this.options.beforeSend();
}
});
}
}
fetchData() {
if (this.options.beforeSend) {
this.options.beforeSend();
}
// Fetch the data through ajax if the data is a string
return axios.get(this.dataEndpoint).then(({ data }) => {
if (this.options.success) {
return this.options.success(data);
}
});
}
}
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