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