You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.9 KiB
121 lines
3.9 KiB
import { EVENT_OPTIONS_PASSIVE } from '../../constants/events';
|
|
import { CODE_ENTER, CODE_SPACE } from '../../constants/key-codes';
|
|
import { getAttr, hasAttr, isDisabled, matches, select, setAttr } from '../../utils/dom';
|
|
import { eventOn, eventOff } from '../../utils/events';
|
|
import { isString } from '../../utils/inspect';
|
|
import { keys } from '../../utils/object'; // Emitted show event for modal
|
|
|
|
var EVENT_SHOW = 'bv::show::modal'; // Prop name we use to store info on root element
|
|
|
|
var PROPERTY = '__bv_modal_directive__';
|
|
|
|
var getTarget = function getTarget(_ref) {
|
|
var _ref$modifiers = _ref.modifiers,
|
|
modifiers = _ref$modifiers === void 0 ? {} : _ref$modifiers,
|
|
arg = _ref.arg,
|
|
value = _ref.value;
|
|
// Try value, then arg, otherwise pick last modifier
|
|
return isString(value) ? value : isString(arg) ? arg : keys(modifiers).reverse()[0];
|
|
};
|
|
|
|
var getTriggerElement = function getTriggerElement(el) {
|
|
// If root element is a dropdown-item or nav-item, we
|
|
// need to target the inner link or button instead
|
|
return el && matches(el, '.dropdown-menu > li, li.nav-item') ? select('a, button', el) || el : el;
|
|
};
|
|
|
|
var setRole = function setRole(trigger) {
|
|
// Ensure accessibility on non button elements
|
|
if (trigger && trigger.tagName !== 'BUTTON') {
|
|
// Only set a role if the trigger element doesn't have one
|
|
if (!hasAttr(trigger, 'role')) {
|
|
setAttr(trigger, 'role', 'button');
|
|
} // Add a tabindex is not a button or link, and tabindex is not provided
|
|
|
|
|
|
if (trigger.tagName !== 'A' && !hasAttr(trigger, 'tabindex')) {
|
|
setAttr(trigger, 'tabindex', '0');
|
|
}
|
|
}
|
|
};
|
|
|
|
var bind = function bind(el, binding, vnode) {
|
|
var target = getTarget(binding);
|
|
var trigger = getTriggerElement(el);
|
|
|
|
if (target && trigger) {
|
|
var handler = function handler(evt) {
|
|
// `currentTarget` is the element with the listener on it
|
|
var currentTarget = evt.currentTarget;
|
|
|
|
if (!isDisabled(currentTarget)) {
|
|
var type = evt.type;
|
|
var key = evt.keyCode; // Open modal only if trigger is not disabled
|
|
|
|
if (type === 'click' || type === 'keydown' && (key === CODE_ENTER || key === CODE_SPACE)) {
|
|
vnode.context.$root.$emit(EVENT_SHOW, target, currentTarget);
|
|
}
|
|
}
|
|
};
|
|
|
|
el[PROPERTY] = {
|
|
handler: handler,
|
|
target: target,
|
|
trigger: trigger
|
|
}; // If element is not a button, we add `role="button"` for accessibility
|
|
|
|
setRole(trigger); // Listen for click events
|
|
|
|
eventOn(trigger, 'click', handler, EVENT_OPTIONS_PASSIVE);
|
|
|
|
if (trigger.tagName !== 'BUTTON' && getAttr(trigger, 'role') === 'button') {
|
|
// If trigger isn't a button but has role button,
|
|
// we also listen for `keydown.space` && `keydown.enter`
|
|
eventOn(trigger, 'keydown', handler, EVENT_OPTIONS_PASSIVE);
|
|
}
|
|
}
|
|
};
|
|
|
|
var unbind = function unbind(el) {
|
|
var oldProp = el[PROPERTY] || {};
|
|
var trigger = oldProp.trigger;
|
|
var handler = oldProp.handler;
|
|
|
|
if (trigger && handler) {
|
|
eventOff(trigger, 'click', handler, EVENT_OPTIONS_PASSIVE);
|
|
eventOff(trigger, 'keydown', handler, EVENT_OPTIONS_PASSIVE);
|
|
eventOff(el, 'click', handler, EVENT_OPTIONS_PASSIVE);
|
|
eventOff(el, 'keydown', handler, EVENT_OPTIONS_PASSIVE);
|
|
}
|
|
|
|
delete el[PROPERTY];
|
|
};
|
|
|
|
var componentUpdated = function componentUpdated(el, binding, vnode) {
|
|
var oldProp = el[PROPERTY] || {};
|
|
var target = getTarget(binding);
|
|
var trigger = getTriggerElement(el);
|
|
|
|
if (target !== oldProp.target || trigger !== oldProp.trigger) {
|
|
// We bind and rebind if the target or trigger changes
|
|
unbind(el, binding, vnode);
|
|
bind(el, binding, vnode);
|
|
} // If trigger element is not a button, ensure `role="button"`
|
|
// is still set for accessibility
|
|
|
|
|
|
setRole(trigger);
|
|
};
|
|
|
|
var updated = function updated() {};
|
|
/*
|
|
* Export our directive
|
|
*/
|
|
|
|
|
|
export var VBModal = {
|
|
inserted: componentUpdated,
|
|
updated: updated,
|
|
componentUpdated: componentUpdated,
|
|
unbind: unbind
|
|
};
|