UNPKG

bootstrap-vue

Version:

BootstrapVue, with over 40 plugins and more than 75 custom components, provides one of the most comprehensive implementations of Bootstrap v4 components and grid system for Vue.js. With extensive and automated WAI-ARIA accessibility markup.

360 lines (248 loc) 10.9 kB
"use strict"; exports.__esModule = true; exports.position = exports.offset = exports.getCS = exports.getBCR = exports.hasAttr = exports.getAttr = exports.removeAttr = exports.setAttr = exports.hasClass = exports.removeClass = exports.addClass = exports.getById = exports.contains = exports.closest = exports.matches = exports.select = exports.selectAll = exports.reflow = exports.isDisabled = exports.isVisible = exports.isElement = exports.eventOff = exports.eventOn = exports.parseEventOptions = exports.MutationObs = exports.requestAF = exports.closestEl = exports.matchesEl = void 0; var _array = require("./array"); var _env = require("./env"); var _inspect = require("../utils/inspect"); // --- Constants --- var w = _env.hasWindowSupport ? window : {}; var d = _env.hasDocumentSupport ? document : {}; var elProto = typeof Element !== 'undefined' ? Element.prototype : {}; // --- Normalization utils --- // See: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill /* istanbul ignore next */ var matchesEl = elProto.matches || elProto.msMatchesSelector || elProto.webkitMatchesSelector; // See: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest /* istanbul ignore next */ exports.matchesEl = matchesEl; var closestEl = elProto.closest || function (sel) /* istanbul ignore next */ { var el = this; do { // Use our "patched" matches function if (matches(el, sel)) { return el; } el = el.parentElement || el.parentNode; } while (!(0, _inspect.isNull)(el) && el.nodeType === Node.ELEMENT_NODE); return null; }; // `requestAnimationFrame()` convenience method // We don't have a version for cancelAnimationFrame, but we don't call it anywhere exports.closestEl = closestEl; var requestAF = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.mozRequestAnimationFrame || w.msRequestAnimationFrame || w.oRequestAnimationFrame || function (cb) { // Fallback, but not a true polyfill // All browsers we support (other than Opera Mini) support // `requestAnimationFrame()` without a polyfill /* istanbul ignore next */ return setTimeout(cb, 16); }; exports.requestAF = requestAF; var MutationObs = w.MutationObserver || w.WebKitMutationObserver || w.MozMutationObserver || null; // --- Utils --- // Normalize event options based on support of passive option // Exported only for testing purposes exports.MutationObs = MutationObs; var parseEventOptions = function parseEventOptions(options) { /* istanbul ignore else: can't test in JSDOM, as it supports passive */ if (_env.hasPassiveEventSupport) { return (0, _inspect.isObject)(options) ? options : { useCapture: Boolean(options || false) }; } else { // Need to translate to actual Boolean value return Boolean((0, _inspect.isObject)(options) ? options.useCapture : options); } }; // Attach an event listener to an element exports.parseEventOptions = parseEventOptions; var eventOn = function eventOn(el, evtName, handler, options) { if (el && el.addEventListener) { el.addEventListener(evtName, handler, parseEventOptions(options)); } }; // Remove an event listener from an element exports.eventOn = eventOn; var eventOff = function eventOff(el, evtName, handler, options) { if (el && el.removeEventListener) { el.removeEventListener(evtName, handler, parseEventOptions(options)); } }; // Determine if an element is an HTML Element exports.eventOff = eventOff; var isElement = function isElement(el) { return Boolean(el && el.nodeType === Node.ELEMENT_NODE); }; // Determine if an HTML element is visible - Faster than CSS check exports.isElement = isElement; var isVisible = function isVisible(el) { if (!isElement(el) || !contains(d.body, el)) { return false; } if (el.style.display === 'none') { // We do this check to help with vue-test-utils when using v-show /* istanbul ignore next */ return false; } // All browsers support getBoundingClientRect(), except JSDOM as it returns all 0's for values :( // So any tests that need isVisible will fail in JSDOM // Except when we override the getBCR prototype in some tests var bcr = getBCR(el); return Boolean(bcr && bcr.height > 0 && bcr.width > 0); }; // Determine if an element is disabled exports.isVisible = isVisible; var isDisabled = function isDisabled(el) { return !isElement(el) || el.disabled || Boolean(getAttr(el, 'disabled')) || hasClass(el, 'disabled'); }; // Cause/wait-for an element to reflow it's content (adjusting it's height/width) exports.isDisabled = isDisabled; var reflow = function reflow(el) { // Requesting an elements offsetHight will trigger a reflow of the element content /* istanbul ignore next: reflow doesn't happen in JSDOM */ return isElement(el) && el.offsetHeight; }; // Select all elements matching selector. Returns `[]` if none found exports.reflow = reflow; var selectAll = function selectAll(selector, root) { return (0, _array.from)((isElement(root) ? root : d).querySelectorAll(selector)); }; // Select a single element, returns `null` if not found exports.selectAll = selectAll; var select = function select(selector, root) { return (isElement(root) ? root : d).querySelector(selector) || null; }; // Determine if an element matches a selector exports.select = select; var matches = function matches(el, selector) { if (!isElement(el)) { return false; } return matchesEl.call(el, selector); }; // Finds closest element matching selector. Returns `null` if not found exports.matches = matches; var closest = function closest(selector, root) { if (!isElement(root)) { return null; } var el = closestEl.call(root, selector); // Emulate jQuery closest and return `null` if match is the passed in element (root) return el === root ? null : el; }; // Returns true if the parent element contains the child element exports.closest = closest; var contains = function contains(parent, child) { if (!parent || !(0, _inspect.isFunction)(parent.contains)) { return false; } return parent.contains(child); }; // Get an element given an ID exports.contains = contains; var getById = function getById(id) { return d.getElementById(/^#/.test(id) ? id.slice(1) : id) || null; }; // Add a class to an element exports.getById = getById; var addClass = function addClass(el, className) { // We are checking for `el.classList` existence here since IE 11 // returns `undefined` for some elements (e.g. SVG elements) // See https://github.com/bootstrap-vue/bootstrap-vue/issues/2713 if (className && isElement(el) && el.classList) { el.classList.add(className); } }; // Remove a class from an element exports.addClass = addClass; var removeClass = function removeClass(el, className) { // We are checking for `el.classList` existence here since IE 11 // returns `undefined` for some elements (e.g. SVG elements) // See https://github.com/bootstrap-vue/bootstrap-vue/issues/2713 if (className && isElement(el) && el.classList) { el.classList.remove(className); } }; // Test if an element has a class exports.removeClass = removeClass; var hasClass = function hasClass(el, className) { // We are checking for `el.classList` existence here since IE 11 // returns `undefined` for some elements (e.g. SVG elements) // See https://github.com/bootstrap-vue/bootstrap-vue/issues/2713 if (className && isElement(el) && el.classList) { return el.classList.contains(className); } return false; }; // Set an attribute on an element exports.hasClass = hasClass; var setAttr = function setAttr(el, attr, value) { if (attr && isElement(el)) { el.setAttribute(attr, value); } }; // Remove an attribute from an element exports.setAttr = setAttr; var removeAttr = function removeAttr(el, attr) { if (attr && isElement(el)) { el.removeAttribute(attr); } }; // Get an attribute value from an element // Returns `null` if not found exports.removeAttr = removeAttr; var getAttr = function getAttr(el, attr) { return attr && isElement(el) ? el.getAttribute(attr) : null; }; // Determine if an attribute exists on an element // Returns `true` or `false`, or `null` if element not found exports.getAttr = getAttr; var hasAttr = function hasAttr(el, attr) { return attr && isElement(el) ? el.hasAttribute(attr) : null; }; // Return the Bounding Client Rect of an element // Returns `null` if not an element /* istanbul ignore next: getBoundingClientRect() doesn't work in JSDOM */ exports.hasAttr = hasAttr; var getBCR = function getBCR(el) { return isElement(el) ? el.getBoundingClientRect() : null; }; // Get computed style object for an element /* istanbul ignore next: getComputedStyle() doesn't work in JSDOM */ exports.getBCR = getBCR; var getCS = function getCS(el) { return _env.hasWindowSupport && isElement(el) ? w.getComputedStyle(el) : {}; }; // Return an element's offset with respect to document element // https://j11y.io/jquery/#v=git&fn=jQuery.fn.offset exports.getCS = getCS; var offset = function offset(el) /* istanbul ignore next: getBoundingClientRect(), getClientRects() doesn't work in JSDOM */ { var _offset = { top: 0, left: 0 }; if (!isElement(el) || el.getClientRects().length === 0) { return _offset; } var bcr = getBCR(el); if (bcr) { var win = el.ownerDocument.defaultView; _offset.top = bcr.top + win.pageYOffset; _offset.left = bcr.left + win.pageXOffset; } return _offset; }; // Return an element's offset with respect to to it's offsetParent // https://j11y.io/jquery/#v=git&fn=jQuery.fn.position exports.offset = offset; var position = function position(el) /* istanbul ignore next: getBoundingClientRect() doesn't work in JSDOM */ { var _offset = { top: 0, left: 0 }; if (!isElement(el)) { return _offset; } var parentOffset = { top: 0, left: 0 }; var elStyles = getCS(el); if (elStyles.position === 'fixed') { _offset = getBCR(el) || _offset; } else { _offset = offset(el); var doc = el.ownerDocument; var offsetParent = el.offsetParent || doc.documentElement; while (offsetParent && (offsetParent === doc.body || offsetParent === doc.documentElement) && getCS(offsetParent).position === 'static') { offsetParent = offsetParent.parentNode; } if (offsetParent && offsetParent !== el && offsetParent.nodeType === Node.ELEMENT_NODE) { parentOffset = offset(offsetParent); var offsetParentStyles = getCS(offsetParent); parentOffset.top += parseFloat(offsetParentStyles.borderTopWidth); parentOffset.left += parseFloat(offsetParentStyles.borderLeftWidth); } } return { top: _offset.top - parentOffset.top - parseFloat(elStyles.marginTop), left: _offset.left - parentOffset.left - parseFloat(elStyles.marginLeft) }; }; exports.position = position;