gitlab-org--gitlab-foss/app/assets/javascripts/droplab/drop_lab.js

161 lines
3.7 KiB
JavaScript
Raw Normal View History

import { DATA_TRIGGER } from './constants';
2017-04-07 09:57:03 -04:00
import HookButton from './hook_button';
import HookInput from './hook_input';
import Keyboard from './keyboard';
import utils from './utils';
2017-04-07 09:57:03 -04:00
class DropLab {
constructor() {
this.ready = false;
this.hooks = [];
this.queuedData = [];
this.config = {};
2017-04-07 09:57:03 -04:00
this.eventWrapper = {};
}
2017-04-07 09:57:03 -04:00
loadStatic() {
const dropdownTriggers = [].slice.apply(document.querySelectorAll(`[${DATA_TRIGGER}]`));
2017-04-07 09:57:03 -04:00
this.addHooks(dropdownTriggers);
}
2017-04-07 09:57:03 -04:00
addData(...args) {
this.applyArgs(args, 'processAddData');
}
2017-04-07 09:57:03 -04:00
setData(...args) {
this.applyArgs(args, 'processSetData');
}
2017-04-07 09:57:03 -04:00
destroy() {
this.hooks.forEach((hook) => hook.destroy());
2017-04-07 09:57:03 -04:00
this.hooks = [];
this.removeEvents();
}
2017-04-07 09:57:03 -04:00
applyArgs(args, methodName) {
if (this.ready) return this[methodName](...args);
2017-04-07 09:57:03 -04:00
this.queuedData = this.queuedData || [];
this.queuedData.push(args);
return this.ready;
}
processAddData(trigger, data) {
this.processData(trigger, data, 'addData');
}
2017-04-07 09:57:03 -04:00
processSetData(trigger, data) {
this.processData(trigger, data, 'setData');
}
2017-04-07 09:57:03 -04:00
processData(trigger, data, methodName) {
this.hooks.forEach((hook) => {
2017-04-07 09:57:03 -04:00
if (Array.isArray(trigger)) hook.list[methodName](trigger);
if (hook.trigger.id === trigger) hook.list[methodName](data);
});
}
2017-04-07 09:57:03 -04:00
addEvents() {
this.eventWrapper.documentClicked = this.documentClicked.bind(this);
document.addEventListener('click', this.eventWrapper.documentClicked);
}
2017-04-07 09:57:03 -04:00
documentClicked(e) {
if (e.defaultPrevented) return;
2017-04-07 09:57:03 -04:00
if (utils.isDropDownParts(e.target)) return;
if (e.target.tagName !== 'UL') {
const closestUl = utils.closest(e.target, 'UL');
if (utils.isDropDownParts(closestUl)) return;
}
2017-04-07 09:57:03 -04:00
this.hooks.forEach((hook) => hook.list.hide());
}
2017-04-07 09:57:03 -04:00
removeEvents() {
document.removeEventListener('click', this.eventWrapper.documentClicked);
}
2017-04-07 09:57:03 -04:00
changeHookList(trigger, list, plugins, config) {
const availableTrigger =
typeof trigger === 'string' ? document.getElementById(trigger) : trigger;
2017-04-07 09:57:03 -04:00
this.hooks.forEach((hook, i) => {
const aHook = hook;
aHook.list.list.dataset.dropdownActive = false;
2017-04-07 09:57:03 -04:00
if (aHook.trigger !== availableTrigger) return;
2017-04-07 09:57:03 -04:00
aHook.destroy();
2017-04-07 09:57:03 -04:00
this.hooks.splice(i, 1);
this.addHook(availableTrigger, list, plugins, config);
});
}
2017-04-07 09:57:03 -04:00
addHook(hook, list, plugins, config) {
2017-04-07 09:57:03 -04:00
const availableHook = typeof hook === 'string' ? document.querySelector(hook) : hook;
let availableList;
if (typeof list === 'string') {
availableList = document.querySelector(list);
} else if (list instanceof Element) {
availableList = list;
} else {
availableList = document.querySelector(hook.dataset[utils.toCamelCase(DATA_TRIGGER)]);
}
availableList.dataset.dropdownActive = true;
const HookObject = availableHook.tagName === 'INPUT' ? HookInput : HookButton;
this.hooks.push(new HookObject(availableHook, availableList, plugins, config));
return this;
}
2017-04-07 09:57:03 -04:00
addHooks(hooks, plugins, config) {
hooks.forEach((hook) => this.addHook(hook, null, plugins, config));
2017-04-07 09:57:03 -04:00
return this;
}
2017-04-07 09:57:03 -04:00
setConfig(obj) {
2017-04-07 09:57:03 -04:00
this.config = obj;
}
2017-04-07 09:57:03 -04:00
fireReady() {
2017-04-07 09:57:03 -04:00
const readyEvent = new CustomEvent('ready.dl', {
detail: {
dropdown: this,
},
});
document.dispatchEvent(readyEvent);
this.ready = true;
}
2017-04-07 09:57:03 -04:00
init(hook, list, plugins, config) {
if (hook) {
this.addHook(hook, list, plugins, config);
} else {
this.loadStatic();
}
2017-04-07 09:57:03 -04:00
this.addEvents();
Keyboard();
this.fireReady();
this.queuedData.forEach((data) => this.addData(data));
2017-04-07 09:57:03 -04:00
this.queuedData = [];
return this;
}
}
2017-04-07 09:57:03 -04:00
export default DropLab;