aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel García <[email protected]>2020-06-01 20:07:13 +0200
committerGitHub <[email protected]>2020-06-01 20:07:13 +0200
commit1aa5e0d4dc436befe880b714af2e33e7fb789bdb (patch)
tree34249cc1d49842efac92b35747e981983b594091
parent5e802f8aa3b269975cc286c9dd06435fcd599468 (diff)
parentb47cf97409acddffb71aa30f483b95fe9ba09ee4 (diff)
downloadvaultwarden-1aa5e0d4dc436befe880b714af2e33e7fb789bdb.tar.gz
vaultwarden-1aa5e0d4dc436befe880b714af2e33e7fb789bdb.zip
Merge pull request #1012 from BlackDex/admin-interface1.15.0
Updated js/css libraries and fixed smallscreen err
-rw-r--r--src/static/scripts/bootstrap-native-v4.js3485
-rw-r--r--src/static/scripts/bootstrap.css747
-rw-r--r--src/static/templates/admin/base.hbs98
-rw-r--r--src/static/templates/admin/users.hbs88
4 files changed, 2172 insertions, 2246 deletions
diff --git a/src/static/scripts/bootstrap-native-v4.js b/src/static/scripts/bootstrap-native-v4.js
index e0cdf3a5..b1cf682f 100644
--- a/src/static/scripts/bootstrap-native-v4.js
+++ b/src/static/scripts/bootstrap-native-v4.js
@@ -1,1999 +1,1689 @@
-// Native Javascript for Bootstrap 4 v2.0.27 | © dnp_theme | MIT-License
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD support:
- define([], factory);
- } else if (typeof module === 'object' && module.exports) {
- // CommonJS-like:
- module.exports = factory();
- } else {
- // Browser globals (root is window)
- var bsn = factory();
- root.Alert = bsn.Alert;
- root.Button = bsn.Button;
- root.Carousel = bsn.Carousel;
- root.Collapse = bsn.Collapse;
- root.Dropdown = bsn.Dropdown;
- root.Modal = bsn.Modal;
- root.Popover = bsn.Popover;
- root.ScrollSpy = bsn.ScrollSpy;
- root.Tab = bsn.Tab;
- root.Toast = bsn.Toast;
- root.Tooltip = bsn.Tooltip;
+/*!
+ * Native JavaScript for Bootstrap v3.0.1 (https://thednp.github.io/bootstrap.native/)
+ * Copyright 2015-2020 © dnp_theme
+ * Licensed under MIT (https://github.com/thednp/bootstrap.native/blob/master/LICENSE)
+ */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = global || self, global.BSN = factory());
+}(this, (function () { 'use strict';
+
+ function hasClass(element,classNAME) {
+ return element.classList.contains(classNAME)
}
-}(this, function () {
-
- /* Native Javascript for Bootstrap 4 | Internal Utility Functions
- ----------------------------------------------------------------*/
- "use strict";
-
- // globals
- var globalObject = typeof global !== 'undefined' ? global : this||window,
- DOC = document, HTML = DOC.documentElement, body = 'body', // allow the library to be used in <head>
-
- // Native Javascript for Bootstrap Global Object
- BSN = globalObject.BSN = {},
- supports = BSN.supports = [],
-
- // function toggle attributes
- dataToggle = 'data-toggle',
- dataDismiss = 'data-dismiss',
- dataSpy = 'data-spy',
- dataRide = 'data-ride',
-
- // components
- stringAlert = 'Alert',
- stringButton = 'Button',
- stringCarousel = 'Carousel',
- stringCollapse = 'Collapse',
- stringDropdown = 'Dropdown',
- stringModal = 'Modal',
- stringPopover = 'Popover',
- stringScrollSpy = 'ScrollSpy',
- stringTab = 'Tab',
- stringTooltip = 'Tooltip',
- stringToast = 'Toast',
-
- // options DATA API
- dataAutohide = 'data-autohide',
- databackdrop = 'data-backdrop',
- dataKeyboard = 'data-keyboard',
- dataTarget = 'data-target',
- dataInterval = 'data-interval',
- dataHeight = 'data-height',
- dataPause = 'data-pause',
- dataTitle = 'data-title',
- dataOriginalTitle = 'data-original-title',
- dataDismissible = 'data-dismissible',
- dataTrigger = 'data-trigger',
- dataAnimation = 'data-animation',
- dataContainer = 'data-container',
- dataPlacement = 'data-placement',
- dataDelay = 'data-delay',
-
- // option keys
- backdrop = 'backdrop', keyboard = 'keyboard', delay = 'delay',
- content = 'content', target = 'target', currentTarget = 'currentTarget',
- interval = 'interval', pause = 'pause', animation = 'animation',
- placement = 'placement', container = 'container',
-
- // box model
- offsetTop = 'offsetTop', offsetBottom = 'offsetBottom',
- offsetLeft = 'offsetLeft',
- scrollTop = 'scrollTop', scrollLeft = 'scrollLeft',
- clientWidth = 'clientWidth', clientHeight = 'clientHeight',
- offsetWidth = 'offsetWidth', offsetHeight = 'offsetHeight',
- innerWidth = 'innerWidth', innerHeight = 'innerHeight',
- scrollHeight = 'scrollHeight', scrollWidth = 'scrollWidth',
- height = 'height',
-
- // aria
- ariaExpanded = 'aria-expanded',
- ariaHidden = 'aria-hidden',
- ariaSelected = 'aria-selected',
-
- // event names
- clickEvent = 'click',
- focusEvent = 'focus',
- hoverEvent = 'hover',
- keydownEvent = 'keydown',
- keyupEvent = 'keyup',
- resizeEvent = 'resize', // passive
- scrollEvent = 'scroll', // passive
- mouseHover = ('onmouseleave' in DOC) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ],
- // touch since 2.0.26
- touchEvents = { start: 'touchstart', end: 'touchend', move:'touchmove' }, // passive
- // originalEvents
- showEvent = 'show',
- shownEvent = 'shown',
- hideEvent = 'hide',
- hiddenEvent = 'hidden',
- closeEvent = 'close',
- closedEvent = 'closed',
- slidEvent = 'slid',
- slideEvent = 'slide',
- changeEvent = 'change',
-
- // other
- getAttribute = 'getAttribute',
- setAttribute = 'setAttribute',
- hasAttribute = 'hasAttribute',
- createElement = 'createElement',
- appendChild = 'appendChild',
- innerHTML = 'innerHTML',
- getElementsByTagName = 'getElementsByTagName',
- preventDefault = 'preventDefault',
- getBoundingClientRect = 'getBoundingClientRect',
- querySelectorAll = 'querySelectorAll',
- getElementsByCLASSNAME = 'getElementsByClassName',
- getComputedStyle = 'getComputedStyle',
-
- indexOf = 'indexOf',
- parentNode = 'parentNode',
- length = 'length',
- toLowerCase = 'toLowerCase',
- Transition = 'Transition',
- Duration = 'Duration',
- Webkit = 'Webkit',
- style = 'style',
- push = 'push',
- tabindex = 'tabindex',
- contains = 'contains',
-
- active = 'active',
- showClass = 'show',
- collapsing = 'collapsing',
- disabled = 'disabled',
- loading = 'loading',
- left = 'left',
- right = 'right',
- top = 'top',
- bottom = 'bottom',
-
- // tooltip / popover
- tipPositions = /\b(top|bottom|left|right)+/,
-
- // modal
- modalOverlay = 0,
- fixedTop = 'fixed-top',
- fixedBottom = 'fixed-bottom',
-
- // transitionEnd since 2.0.4
- supportTransitions = Webkit+Transition in HTML[style] || Transition[toLowerCase]() in HTML[style],
- transitionEndEvent = Webkit+Transition in HTML[style] ? Webkit[toLowerCase]()+Transition+'End' : Transition[toLowerCase]()+'end',
- transitionDuration = Webkit+Duration in HTML[style] ? Webkit[toLowerCase]()+Transition+Duration : Transition[toLowerCase]()+Duration,
-
- // set new focus element since 2.0.3
- setFocus = function(element){
- element.focus ? element.focus() : element.setActive();
- },
-
- // class manipulation, since 2.0.0 requires polyfill.js
- addClass = function(element,classNAME) {
- element.classList.add(classNAME);
- },
- removeClass = function(element,classNAME) {
- element.classList.remove(classNAME);
- },
- hasClass = function(element,classNAME){ // since 2.0.0
- return element.classList[contains](classNAME);
- },
-
- // selection methods
- getElementsByClassName = function(element,classNAME) { // returns Array
- return [].slice.call(element[getElementsByCLASSNAME]( classNAME ));
- },
- queryElement = function (selector, parent) {
- var lookUp = parent ? parent : DOC;
- return typeof selector === 'object' ? selector : lookUp.querySelector(selector);
- },
- getClosest = function (element, selector) { //element is the element and selector is for the closest parent element to find
- // source http://gomakethings.com/climbing-up-and-down-the-dom-tree-with-vanilla-javascript/
- var firstChar = selector.charAt(0), selectorSubstring = selector.substr(1);
- if ( firstChar === '.' ) {// If selector is a class
- for ( ; element && element !== DOC; element = element[parentNode] ) { // Get closest match
- if ( queryElement(selector,element[parentNode]) !== null && hasClass(element,selectorSubstring) ) { return element; }
- }
- } else if ( firstChar === '#' ) { // If selector is an ID
- for ( ; element && element !== DOC; element = element[parentNode] ) { // Get closest match
- if ( element.id === selectorSubstring ) { return element; }
- }
- }
- return false;
- },
-
- // event attach jQuery style / trigger since 1.2.0
- on = function (element, event, handler, options) {
- options = options || false;
- element.addEventListener(event, handler, options);
- },
- off = function(element, event, handler, options) {
- options = options || false;
- element.removeEventListener(event, handler, options);
- },
- one = function (element, event, handler, options) { // one since 2.0.4
- on(element, event, function handlerWrapper(e){
+
+ function removeClass(element,classNAME) {
+ element.classList.remove(classNAME);
+ }
+
+ function on (element, event, handler, options) {
+ options = options || false;
+ element.addEventListener(event, handler, options);
+ }
+
+ function off (element, event, handler, options) {
+ options = options || false;
+ element.removeEventListener(event, handler, options);
+ }
+
+ function one (element, event, handler, options) {
+ on(element, event, function handlerWrapper(e){
+ if (e.target === element) {
handler(e);
off(element, event, handlerWrapper, options);
- }, options);
- },
- // determine support for passive events
- supportPassive = (function(){
- // Test via a getter in the options object to see if the passive property is accessed
- var result = false;
- try {
- var opts = Object.defineProperty({}, 'passive', {
- get: function() {
- result = true;
- }
- });
- one(globalObject, 'testPassive', null, opts);
- } catch (e) {}
-
- return result;
- }()),
- // event options
- // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
- passiveHandler = supportPassive ? { passive: true } : false,
- // transitions
- getTransitionDurationFromElement = function(element) {
- var duration = supportTransitions ? globalObject[getComputedStyle](element)[transitionDuration] : 0;
- duration = parseFloat(duration);
- duration = typeof duration === 'number' && !isNaN(duration) ? duration * 1000 : 0;
- return duration; // we take a short offset to make sure we fire on the next frame after animation
- },
- emulateTransitionEnd = function(element,handler){ // emulateTransitionEnd since 2.0.4
- var called = 0, duration = getTransitionDurationFromElement(element);
- duration ? one(element, transitionEndEvent, function(e){ !called && handler(e), called = 1; })
- : setTimeout(function() { !called && handler(), called = 1; }, 17);
- },
- bootstrapCustomEvent = function (eventName, componentName, related) {
- var OriginalCustomEvent = new CustomEvent( eventName + '.bs.' + componentName);
- OriginalCustomEvent.relatedTarget = related;
- this.dispatchEvent(OriginalCustomEvent);
- },
-
- // tooltip / popover stuff
- getScroll = function() { // also Affix and ScrollSpy uses it
- return {
- y : globalObject.pageYOffset || HTML[scrollTop],
- x : globalObject.pageXOffset || HTML[scrollLeft]
- }
- },
- styleTip = function(link,element,position,parent) { // both popovers and tooltips (target,tooltip,placement,elementToAppendTo)
- var elementDimensions = { w : element[offsetWidth], h: element[offsetHeight] },
- windowWidth = (HTML[clientWidth] || DOC[body][clientWidth]),
- windowHeight = (HTML[clientHeight] || DOC[body][clientHeight]),
- rect = link[getBoundingClientRect](),
- scroll = parent === DOC[body] ? getScroll() : { x: parent[offsetLeft] + parent[scrollLeft], y: parent[offsetTop] + parent[scrollTop] },
- linkDimensions = { w: rect[right] - rect[left], h: rect[bottom] - rect[top] },
- isPopover = hasClass(element,'popover'),
- topPosition, leftPosition,
-
- arrow = queryElement('.arrow',element),
- arrowTop, arrowLeft, arrowWidth, arrowHeight,
-
- halfTopExceed = rect[top] + linkDimensions.h/2 - elementDimensions.h/2 < 0,
- halfLeftExceed = rect[left] + linkDimensions.w/2 - elementDimensions.w/2 < 0,
- halfRightExceed = rect[left] + elementDimensions.w/2 + linkDimensions.w/2 >= windowWidth,
- halfBottomExceed = rect[top] + elementDimensions.h/2 + linkDimensions.h/2 >= windowHeight,
- topExceed = rect[top] - elementDimensions.h < 0,
- leftExceed = rect[left] - elementDimensions.w < 0,
- bottomExceed = rect[top] + elementDimensions.h + linkDimensions.h >= windowHeight,
- rightExceed = rect[left] + elementDimensions.w + linkDimensions.w >= windowWidth;
-
- // recompute position
- position = (position === left || position === right) && leftExceed && rightExceed ? top : position; // first, when both left and right limits are exceeded, we fall back to top|bottom
- position = position === top && topExceed ? bottom : position;
- position = position === bottom && bottomExceed ? top : position;
- position = position === left && leftExceed ? right : position;
- position = position === right && rightExceed ? left : position;
-
- // update tooltip/popover class
- element.className[indexOf](position) === -1 && (element.className = element.className.replace(tipPositions,position));
-
- // we check the computed width & height and update here
- arrowWidth = arrow[offsetWidth]; arrowHeight = arrow[offsetHeight];
-
- // apply styling to tooltip or popover
- if ( position === left || position === right ) { // secondary|side positions
- if ( position === left ) { // LEFT
- leftPosition = rect[left] + scroll.x - elementDimensions.w - ( isPopover ? arrowWidth : 0 );
- } else { // RIGHT
- leftPosition = rect[left] + scroll.x + linkDimensions.w;
- }
-
- // adjust top and arrow
- if (halfTopExceed) {
- topPosition = rect[top] + scroll.y;
- arrowTop = linkDimensions.h/2 - arrowWidth;
- } else if (halfBottomExceed) {
- topPosition = rect[top] + scroll.y - elementDimensions.h + linkDimensions.h;
- arrowTop = elementDimensions.h - linkDimensions.h/2 - arrowWidth;
+ }
+ }, options);
+ }
+
+ var transitionEndEvent = 'webkitTransition' in document.body.style ? 'webkitTransitionEnd' : 'transitionend';
+
+ var supportTransition = 'webkitTransition' in document.body.style || 'transition' in document.body.style;
+
+ var transitionDuration = 'webkitTransition' in document.body.style ? 'webkitTransitionDuration' : 'transitionDuration';
+
+ function getElementTransitionDuration (element) {
+ var duration = supportTransition ? window.getComputedStyle(element)[transitionDuration] : 0;
+ duration = parseFloat(duration);
+ duration = typeof duration === 'number' && !isNaN(duration) ? duration * 1000 : 0;
+ return duration;
+ }
+
+ function emulateTransitionEnd (element,handler){
+ var called = 0, duration = getElementTransitionDuration(element);
+ duration ? one(element, transitionEndEvent, function(e){ !called && handler(e), called = 1; })
+ : setTimeout(function() { !called && handler(), called = 1; }, 17);
+ }
+
+ function queryElement (selector, parent) {
+ var lookUp = parent && parent instanceof Element ? parent : document;
+ return selector instanceof Element ? selector : lookUp.querySelector(selector);
+ }
+
+ function tryWrapper (fn,origin){
+ try{ fn(); }
+ catch(e){
+ console.error((origin + ": " + e));
+ }
+ }
+
+ function bootstrapCustomEvent (eventName, componentName, related) {
+ var OriginalCustomEvent = new CustomEvent( eventName + '.bs.' + componentName, {cancelable: true});
+ OriginalCustomEvent.relatedTarget = related;
+ return OriginalCustomEvent;
+ }
+ function dispatchCustomEvent (customEvent){
+ this && this.dispatchEvent(customEvent);
+ }
+
+ function Alert(element) {
+ var self = this,
+ alert,
+ closeCustomEvent = bootstrapCustomEvent('close','alert'),
+ closedCustomEvent = bootstrapCustomEvent('closed','alert');
+ function triggerHandler() {
+ hasClass(alert,'fade') ? emulateTransitionEnd(alert,transitionEndHandler) : transitionEndHandler();
+ }
+ function clickHandler(e) {
+ alert = e && e.target.closest(".alert");
+ element = queryElement('[data-dismiss="alert"]',alert);
+ element && alert && (element === e.target || element.contains(e.target)) && self.close();
+ }
+ function transitionEndHandler() {
+ off(element, 'click', clickHandler);
+ alert.parentNode.removeChild(alert);
+ dispatchCustomEvent.call(alert,closedCustomEvent);
+ }
+ self.close = function () {
+ if ( alert && element && hasClass(alert,'show') ) {
+ dispatchCustomEvent.call(alert,closeCustomEvent);
+ if ( closeCustomEvent.defaultPrevented ) { return; }
+ self.dispose();
+ removeClass(alert,'show');
+ triggerHandler();
+ }
+ };
+ self.dispose = function () {
+ off(element, 'click', clickHandler);
+ delete element.Alert;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ alert = element.closest('.alert');
+ element.Alert && element.Alert.dispose();
+ if ( !element.Alert ) {
+ on(element, 'click', clickHandler);
+ }
+ self.element = element;
+ element.Alert = self;
+ },"BSN.Alert");
+ }
+
+ function addClass(element,classNAME) {
+ element.classList.add(classNAME);
+ }
+
+ function Button(element) {
+ var self = this, labels,
+ changeCustomEvent = bootstrapCustomEvent('change', 'button');
+ function toggle(e) {
+ var input,
+ label = e.target.tagName === 'LABEL' ? e.target
+ : e.target.closest('LABEL') ? e.target.closest('LABEL') : null;
+ input = label && label.getElementsByTagName('INPUT')[0];
+ if ( !input ) { return; }
+ dispatchCustomEvent.call(input, changeCustomEvent);
+ dispatchCustomEvent.call(element, changeCustomEvent);
+ if ( input.type === 'checkbox' ) {
+ if ( changeCustomEvent.defaultPrevented ) { return; }
+ if ( !input.checked ) {
+ addClass(label,'active');
+ input.getAttribute('checked');
+ input.setAttribute('checked','checked');
+ input.checked = true;
} else {
- topPosition = rect[top] + scroll.y - elementDimensions.h/2 + linkDimensions.h/2;
- arrowTop = elementDimensions.h/2 - (isPopover ? arrowHeight*0.9 : arrowHeight/2);
+ removeClass(label,'active');
+ input.getAttribute('checked');
+ input.removeAttribute('checked');
+ input.checked = false;
}
- } else if ( position === top || position === bottom ) { // primary|vertical positions
- if ( position === top) { // TOP
- topPosition = rect[top] + scroll.y - elementDimensions.h - ( isPopover ? arrowHeight : 0 );
- } else { // BOTTOM
- topPosition = rect[top] + scroll.y + linkDimensions.h;
+ if (!element.toggled) {
+ element.toggled = true;
}
- // adjust left | right and also the arrow
- if (halfLeftExceed) {
- leftPosition = 0;
- arrowLeft = rect[left] + linkDimensions.w/2 - arrowWidth;
- } else if (halfRightExceed) {
- leftPosition = windowWidth - elementDimensions.w*1.01;
- arrowLeft = elementDimensions.w - ( windowWidth - rect[left] ) + linkDimensions.w/2 - arrowWidth/2;
- } else {
- leftPosition = rect[left] + scroll.x - elementDimensions.w/2 + linkDimensions.w/2;
- arrowLeft = elementDimensions.w/2 - ( isPopover ? arrowWidth : arrowWidth/2 );
+ }
+ if ( input.type === 'radio' && !element.toggled ) {
+ if ( changeCustomEvent.defaultPrevented ) { return; }
+ if ( !input.checked || (e.screenX === 0 && e.screenY == 0) ) {
+ addClass(label,'active');
+ addClass(label,'focus');
+ input.setAttribute('checked','checked');
+ input.checked = true;
+ element.toggled = true;
+ Array.from(labels).map(function (otherLabel){
+ var otherInput = otherLabel.getElementsByTagName('INPUT')[0];
+ if ( otherLabel !== label && hasClass(otherLabel,'active') ) {
+ dispatchCustomEvent.call(otherInput, changeCustomEvent);
+ removeClass(otherLabel,'active');
+ otherInput.removeAttribute('checked');
+ otherInput.checked = false;
+ }
+ });
}
}
-
- // apply style to tooltip/popover and its arrow
- element[style][top] = topPosition + 'px';
- element[style][left] = leftPosition + 'px';
-
- arrowTop && (arrow[style][top] = arrowTop + 'px');
- arrowLeft && (arrow[style][left] = arrowLeft + 'px');
- };
-
- BSN.version = '2.0.27';
-
- /* Native Javascript for Bootstrap 4 | Alert
- -------------------------------------------*/
-
- // ALERT DEFINITION
- // ================
- var Alert = function( element ) {
-
- // initialization element
- element = queryElement(element);
-
- // bind, target alert, duration and stuff
- var self = this, component = 'alert',
- alert = getClosest(element,'.'+component),
- triggerHandler = function(){ hasClass(alert,'fade') ? emulateTransitionEnd(alert,transitionEndHandler) : transitionEndHandler(); },
- // handlers
- clickHandler = function(e){
- alert = getClosest(e[target],'.'+component);
- element = queryElement('['+dataDismiss+'="'+component+'"]',alert);
- element && alert && (element === e[target] || element[contains](e[target])) && self.close();
- },
- transitionEndHandler = function(){
- bootstrapCustomEvent.call(alert, closedEvent, component);
- off(element, clickEvent, clickHandler); // detach it's listener
- alert[parentNode].removeChild(alert);
- };
-
- // public method
- this.close = function() {
- if ( alert && element && hasClass(alert,showClass) ) {
- bootstrapCustomEvent.call(alert, closeEvent, component);
- removeClass(alert,showClass);
- alert && triggerHandler();
+ setTimeout( function () { element.toggled = false; }, 50 );
+ }
+ function keyHandler(e) {
+ var key = e.which || e.keyCode;
+ key === 32 && e.target === document.activeElement && toggle(e);
+ }
+ function preventScroll(e) {
+ var key = e.which || e.keyCode;
+ key === 32 && e.preventDefault();
+ }
+ function focusToggle(e) {
+ var action = e.type === 'focusin' ? addClass : removeClass;
+ if (e.target.tagName === 'INPUT' ) {
+ action(e.target.closest('.btn'),'focus');
}
- };
-
- // init
- if ( !(stringAlert in element ) ) { // prevent adding event handlers twice
- on(element, clickEvent, clickHandler);
}
- element[stringAlert] = self;
- };
-
- // ALERT DATA API
- // ==============
- supports[push]([stringAlert, Alert, '['+dataDismiss+'="alert"]']);
-
-
- /* Native Javascript for Bootstrap 4 | Button
- ---------------------------------------------*/
-
- // BUTTON DEFINITION
- // ===================
- var Button = function( element ) {
-
- // initialization element
- element = queryElement(element);
-
- // constant
- var toggled = false, // toggled makes sure to prevent triggering twice the change.bs.button events
-
- // strings
- component = 'button',
- checked = 'checked',
- LABEL = 'LABEL',
- INPUT = 'INPUT',
-
- // private methods
- keyHandler = function(e){
- var key = e.which || e.keyCode;
- key === 32 && e[target] === DOC.activeElement && toggle(e);
- },
- preventScroll = function(e){
- var key = e.which || e.keyCode;
- key === 32 && e[preventDefault]();
- },
- toggle = function(e) {
- var label = e[target].tagName === LABEL ? e[target] : e[target][parentNode].tagName === LABEL ? e[target][parentNode] : null; // the .btn label
-
- if ( !label ) return; //react if a label or its immediate child is clicked
-
- var labels = getElementsByClassName(label[parentNode],'btn'), // all the button group buttons
- input = label[getElementsByTagName](INPUT)[0];
-
- if ( !input ) return; // return if no input found
-
- // manage the dom manipulation
- if ( input.type === 'checkbox' ) { //checkboxes
- if ( !input[checked] ) {
- addClass(label,active);
- input[getAttribute](checked);
- input[setAttribute](checked,checked);
- input[checked] = true;
- } else {
- removeClass(label,active);
- input[getAttribute](checked);
- input.removeAttribute(checked);
- input[checked] = false;
- }
-
- if (!toggled) { // prevent triggering the event twice
- toggled = true;
- bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
- bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
- }
- }
-
- if ( input.type === 'radio' && !toggled ) { // radio buttons
- // don't trigger if already active (the OR condition is a hack to check if the buttons were selected with key press and NOT mouse click)
- if ( !input[checked] || (e.screenX === 0 && e.screenY == 0) ) {
- addClass(label,active);
- addClass(label,focusEvent);
- input[setAttribute](checked,checked);
- input[checked] = true;
- bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
- bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
-
- toggled = true;
- for (var i = 0, ll = labels[length]; i<ll; i++) {
- var otherLabel = labels[i], otherInput = otherLabel[getElementsByTagName](INPUT)[0];
- if ( otherLabel !== label && hasClass(otherLabel,active) ) {
- removeClass(otherLabel,active);
- otherInput.removeAttribute(checked);
- otherInput[checked] = false;
- bootstrapCustomEvent.call(otherInput, changeEvent, component); // trigger the change
- }
- }
- }
+ function toggleEvents(action) {
+ action( element, 'click', toggle );
+ action( element, 'keyup', keyHandler ), action( element, 'keydown', preventScroll );
+ action( element, 'focusin', focusToggle), action( element, 'focusout', focusToggle);
+ }
+ self.dispose = function () {
+ toggleEvents(off);
+ delete element.Button;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.Button && element.Button.dispose();
+ labels = element.getElementsByClassName('btn');
+ if (!labels.length) { return; }
+ if ( !element.Button ) {
+ toggleEvents(on);
+ }
+ element.toggled = false;
+ element.Button = self;
+ Array.from(labels).map(function (btn){
+ !hasClass(btn,'active')
+ && queryElement('input:checked',btn)
+ && addClass(btn,'active');
+ hasClass(btn,'active')
+ && !queryElement('input:checked',btn)
+ && removeClass(btn,'active');
+ });
+ },"BSN.Button");
+ }
+
+ var touchEvents = { start: 'touchstart', end: 'touchend', move:'touchmove', cancel:'touchcancel' };
+
+ var mouseHoverEvents = ('onmouseleave' in document) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
+
+ var supportPassive = (function () {
+ var result = false;
+ try {
+ var opts = Object.defineProperty({}, 'passive', {
+ get: function() {
+ result = true;
}
- setTimeout( function() { toggled = false; }, 50 );
- },
- focusHandler = function(e) {
- addClass(e[target][parentNode],focusEvent);
- },
- blurHandler = function(e) {
- removeClass(e[target][parentNode],focusEvent);
- };
-
- // init
- if ( !( stringButton in element ) ) { // prevent adding event handlers twice
- on( element, clickEvent, toggle );
- on( element, keyupEvent, keyHandler ), on( element, keydownEvent, preventScroll );
-
- var allBtns = getElementsByClassName(element, 'btn');
- for (var i=0; i<allBtns.length; i++) {
- var input = allBtns[i][getElementsByTagName](INPUT)[0];
- on( input, focusEvent, focusHandler), on( input, 'blur', blurHandler);
- }
- }
-
- // activate items on load
- var labelsToACtivate = getElementsByClassName(element, 'btn'), lbll = labelsToACtivate[length];
- for (var i=0; i<lbll; i++) {
- !hasClass(labelsToACtivate[i],active) && queryElement('input:checked',labelsToACtivate[i])
- && addClass(labelsToACtivate[i],active);
- }
- element[stringButton] = this;
- };
-
- // BUTTON DATA API
- // =================
- supports[push]( [ stringButton, Button, '['+dataToggle+'="buttons"]' ] );
-
-
- /* Native Javascript for Bootstrap 4 | Carousel
- ----------------------------------------------*/
-
- // CAROUSEL DEFINITION
- // ===================
- var Carousel = function( element, options ) {
-
- // initialization element
- element = queryElement( element );
-
- // set options
+ });
+ one(document, 'DOMContentLoaded', function (){}, opts);
+ } catch (e) {}
+ return result;
+ })();
+
+ var passiveHandler = supportPassive ? { passive: true } : false;
+
+ function isElementInScrollRange(element) {
+ var bcr = element.getBoundingClientRect(),
+ viewportHeight = window.innerHeight || document.documentElement.clientHeight;
+ return bcr.top <= viewportHeight && bcr.bottom >= 0;
+ }
+
+ function Carousel (element,options) {
options = options || {};
-
- // DATA API
- var intervalAttribute = element[getAttribute](dataInterval),
- intervalOption = options[interval],
- intervalData = intervalAttribute === 'false' ? 0 : parseInt(intervalAttribute),
- pauseData = element[getAttribute](dataPause) === hoverEvent || false,
- keyboardData = element[getAttribute](dataKeyboard) === 'true' || false,
-
- // strings
- component = 'carousel',
- paused = 'paused',
- direction = 'direction',
- carouselItem = 'carousel-item',
- dataSlideTo = 'data-slide-to';
-
- this[keyboard] = options[keyboard] === true || keyboardData;
- this[pause] = (options[pause] === hoverEvent || pauseData) ? hoverEvent : false; // false / hover
-
- this[interval] = typeof intervalOption === 'number' ? intervalOption
- : intervalOption === false || intervalData === 0 || intervalData === false ? 0
- : isNaN(intervalData) ? 5000 // bootstrap carousel default interval
- : intervalData;
-
- // bind, event targets
- var self = this, index = element.index = 0, timer = element.timer = 0,
- isSliding = false, // isSliding prevents click event handlers when animation is running
- isTouch = false, startXPosition = null, currentXPosition = null, endXPosition = null, // touch and event coordinates
- slides = getElementsByClassName(element,carouselItem), total = slides[length],
- slideDirection = this[direction] = left,
- leftArrow = getElementsByClassName(element,component+'-control-prev')[0],
- rightArrow = getElementsByClassName(element,component+'-control-next')[0],
- indicator = queryElement( '.'+component+'-indicators', element ),
- indicators = indicator && indicator[getElementsByTagName]( "LI" ) || [];
-
- // invalidate when not enough items
- if (total < 2) { return; }
-
- // handlers
- var pauseHandler = function () {
- if ( self[interval] !==false && !hasClass(element,paused) ) {
- addClass(element,paused);
- !isSliding && ( clearInterval(timer), timer = null );
- }
- },
- resumeHandler = function() {
- if ( self[interval] !== false && hasClass(element,paused) ) {
- removeClass(element,paused);
- !isSliding && ( clearInterval(timer), timer = null );
- !isSliding && self.cycle();
- }
- },
- indicatorHandler = function(e) {
- e[preventDefault]();
- if (isSliding) return;
-
- var eventTarget = e[target]; // event target | the current active item
-
- if ( eventTarget && !hasClass(eventTarget,active) && eventTarget[getAttribute](dataSlideTo) ) {
- index = parseInt( eventTarget[getAttribute](dataSlideTo), 10 );
- } else { return false; }
-
- self.slideTo( index ); //Do the slide
- },
- controlsHandler = function (e) {
- e[preventDefault]();
- if (isSliding) return;
-
- var eventTarget = e.currentTarget || e.srcElement;
-
- if ( eventTarget === rightArrow ) {
- index++;
- } else if ( eventTarget === leftArrow ) {
- index--;
- }
-
- self.slideTo( index ); //Do the slide
- },
- keyHandler = function (e) {
- if (isSliding) return;
- switch (e.which) {
- case 39:
- index++;
- break;
- case 37:
- index--;
- break;
- default: return;
- }
- self.slideTo( index ); //Do the slide
- },
- // touch events
- toggleTouchEvents = function(toggle){
- toggle( element, touchEvents.move, touchMoveHandler, passiveHandler );
- toggle( element, touchEvents.end, touchEndHandler, passiveHandler );
- },
- touchDownHandler = function(e) {
- if ( isTouch ) { return; }
-
- startXPosition = parseInt(e.touches[0].pageX);
-
- if ( element.contains(e[target]) ) {
- isTouch = true;
- toggleTouchEvents(on);
- }
- },
- touchMoveHandler = function(e) {
- if ( !isTouch ) { e.preventDefault(); return; }
-
- currentXPosition = parseInt(e.touches[0].pageX);
-
- //cancel touch if more than one touches detected
- if ( e.type === 'touchmove' && e.touches[length] > 1 ) {
- e.preventDefault();
+ var self = this,
+ vars, ops = {},
+ slideCustomEvent, slidCustomEvent,
+ slides, leftArrow, rightArrow, indicator, indicators;
+ function pauseHandler() {
+ if ( ops.interval !==false && !hasClass(element,'paused') ) {
+ addClass(element,'paused');
+ !vars.isSliding && ( clearInterval(vars.timer), vars.timer = null );
+ }
+ }
+ function resumeHandler() {
+ if ( ops.interval !== false && hasClass(element,'paused') ) {
+ removeClass(element,'paused');
+ !vars.isSliding && ( clearInterval(vars.timer), vars.timer = null );
+ !vars.isSliding && self.cycle();
+ }
+ }
+ function indicatorHandler(e) {
+ e.preventDefault();
+ if (vars.isSliding) { return; }
+ var eventTarget = e.target;
+ if ( eventTarget && !hasClass(eventTarget,'active') && eventTarget.getAttribute('data-slide-to') ) {
+ vars.index = parseInt( eventTarget.getAttribute('data-slide-to'), 10 );
+ } else { return false; }
+ self.slideTo( vars.index );
+ }
+ function controlsHandler(e) {
+ e.preventDefault();
+ if (vars.isSliding) { return; }
+ var eventTarget = e.currentTarget || e.srcElement;
+ if ( eventTarget === rightArrow ) {
+ vars.index++;
+ } else if ( eventTarget === leftArrow ) {
+ vars.index--;
+ }
+ self.slideTo( vars.index );
+ }
+ function keyHandler(ref) {
+ var which = ref.which;
+ if (vars.isSliding) { return; }
+ switch (which) {
+ case 39:
+ vars.index++;
+ break;
+ case 37:
+ vars.index--;
+ break;
+ default: return;
+ }
+ self.slideTo( vars.index );
+ }
+ function toggleEvents(action) {
+ if ( ops.pause && ops.interval ) {
+ action( element, mouseHoverEvents[0], pauseHandler );
+ action( element, mouseHoverEvents[1], resumeHandler );
+ action( element, touchEvents.start, pauseHandler, passiveHandler );
+ action( element, touchEvents.end, resumeHandler, passiveHandler );
+ }
+ slides.length > 1 && action( element, touchEvents.start, touchDownHandler, passiveHandler );
+ rightArrow && action( rightArrow, 'click', controlsHandler );
+ leftArrow && action( leftArrow, 'click', controlsHandler );
+ indicator && action( indicator, 'click', indicatorHandler );
+ ops.keyboard && action( window, 'keydown', keyHandler );
+ }
+ function toggleTouchEvents(action) {
+ action( element, touchEvents.move, touchMoveHandler, passiveHandler );
+ action( element, touchEvents.end, touchEndHandler, passiveHandler );
+ }
+ function touchDownHandler(e) {
+ if ( vars.isTouch ) { return; }
+ vars.touchPosition.startX = e.changedTouches[0].pageX;
+ if ( element.contains(e.target) ) {
+ vars.isTouch = true;
+ toggleTouchEvents(on);
+ }
+ }
+ function touchMoveHandler(e) {
+ if ( !vars.isTouch ) { e.preventDefault(); return; }
+ vars.touchPosition.currentX = e.changedTouches[0].pageX;
+ if ( e.type === 'touchmove' && e.changedTouches.length > 1 ) {
+ e.preventDefault();
+ return false;
+ }
+ }
+ function touchEndHandler (e) {
+ if ( !vars.isTouch || vars.isSliding ) { return }
+ vars.touchPosition.endX = vars.touchPosition.currentX || e.changedTouches[0].pageX;
+ if ( vars.isTouch ) {
+ if ( (!element.contains(e.target) || !element.contains(e.relatedTarget) )
+ && Math.abs(vars.touchPosition.startX - vars.touchPosition.endX) < 75 ) {
return false;
+ } else {
+ if ( vars.touchPosition.currentX < vars.touchPosition.startX ) {
+ vars.index++;
+ } else if ( vars.touchPosition.currentX > vars.touchPosition.startX ) {
+ vars.index--;
+ }
+ vars.isTouch = false;
+ self.slideTo(vars.index);
}
- },
- touchEndHandler = function(e) {
- if ( !isTouch || isSliding ) { return }
-
- endXPosition = currentXPosition || parseInt( e.touches[0].pageX );
-
- if ( isTouch ) {
- if ( (!element.contains(e[target]) || !element.contains(e.relatedTarget) ) && Math.abs(startXPosition - endXPosition) < 75 ) {
- return false;
- } else {
- if ( currentXPosition < startXPosition ) {
- index++;
- } else if ( currentXPosition > startXPosition ) {
- index--;
+ toggleTouchEvents(off);
+ }
+ }
+ function setActivePage(pageIndex) {
+ Array.from(indicators).map(function (x){removeClass(x,'active');});
+ indicators[pageIndex] && addClass(indicators[pageIndex], 'active');
+ }
+ function transitionEndHandler(e){
+ if (vars.touchPosition){
+ var next = vars.index,
+ timeout = e && e.target !== slides[next] ? e.elapsedTime*1000+100 : 20,
+ activeItem = self.getActiveIndex(),
+ orientation = vars.direction === 'left' ? 'next' : 'prev';
+ vars.isSliding && setTimeout(function () {
+ if (vars.touchPosition){
+ vars.isSliding = false;
+ addClass(slides[next],'active');
+ removeClass(slides[activeItem],'active');
+ removeClass(slides[next],("carousel-item-" + orientation));
+ removeClass(slides[next],("carousel-item-" + (vars.direction)));
+ removeClass(slides[activeItem],("carousel-item-" + (vars.direction)));
+ dispatchCustomEvent.call(element, slidCustomEvent);
+ if ( !document.hidden && ops.interval && !hasClass(element,'paused') ) {
+ self.cycle();
}
- isTouch = false;
- self.slideTo(index);
}
- toggleTouchEvents(off);
- }
- },
-
- // private methods
- isElementInScrollRange = function () {
- var rect = element[getBoundingClientRect](),
- viewportHeight = globalObject[innerHeight] || HTML[clientHeight]
- return rect[top] <= viewportHeight && rect[bottom] >= 0; // bottom && top
- },
- setActivePage = function( pageIndex ) { //indicators
- for ( var i = 0, icl = indicators[length]; i < icl; i++ ) {
- removeClass(indicators[i],active);
- }
- if (indicators[pageIndex]) addClass(indicators[pageIndex], active);
- };
-
-
- // public methods
- this.cycle = function() {
- if (timer) {
- clearInterval(timer);
- timer = null;
- }
-
- timer = setInterval(function() {
- isElementInScrollRange() && (index++, self.slideTo( index ) );
- }, this[interval]);
+ }, timeout);
+ }
+ }
+ self.cycle = function () {
+ if (vars.timer) {
+ clearInterval(vars.timer);
+ vars.timer = null;
+ }
+ vars.timer = setInterval(function () {
+ var idx = vars.index || self.getActiveIndex();
+ isElementInScrollRange(element) && (idx++, self.slideTo( idx ) );
+ }, ops.interval);
};
- this.slideTo = function( next ) {
- if (isSliding) return; // when controled via methods, make sure to check again
-
- var activeItem = this.getActiveIndex(), // the current active
- orientation;
-
- // first return if we're on the same item #227
+ self.slideTo = function (next) {
+ if (vars.isSliding) { return; }
+ var activeItem = self.getActiveIndex(), orientation;
if ( activeItem === next ) {
return;
- // or determine slideDirection
- } else if ( (activeItem < next ) || (activeItem === 0 && next === total -1 ) ) {
- slideDirection = self[direction] = left; // next
- } else if ( (activeItem > next) || (activeItem === total - 1 && next === 0 ) ) {
- slideDirection = self[direction] = right; // prev
- }
-
- // find the right next index
- if ( next < 0 ) { next = total - 1; }
- else if ( next >= total ){ next = 0; }
-
- // update index
- index = next;
-
- orientation = slideDirection === left ? 'next' : 'prev'; //determine type
- bootstrapCustomEvent.call(element, slideEvent, component, slides[next]); // here we go with the slide
-
- isSliding = true;
- clearInterval(timer);
- timer = null;
+ } else if ( (activeItem < next ) || (activeItem === 0 && next === slides.length -1 ) ) {
+ vars.direction = 'left';
+ } else if ( (activeItem > next) || (activeItem === slides.length - 1 && next === 0 ) ) {
+ vars.direction = 'right';
+ }
+ if ( next < 0 ) { next = slides.length - 1; }
+ else if ( next >= slides.length ){ next = 0; }
+ orientation = vars.direction === 'left' ? 'next' : 'prev';
+ slideCustomEvent = bootstrapCustomEvent('slide', 'carousel', slides[next]);
+ slidCustomEvent = bootstrapCustomEvent('slid', 'carousel', slides[next]);
+ dispatchCustomEvent.call(element, slideCustomEvent);
+ if (slideCustomEvent.defaultPrevented) { return; }
+ vars.index = next;
+ vars.isSliding = true;
+ clearInterval(vars.timer);
+ vars.timer = null;
setActivePage( next );
-
- if ( supportTransitions && hasClass(element,'slide') ) {
-
- addClass(slides[next],carouselItem +'-'+ orientation);
- slides[next][offsetWidth];
- addClass(slides[next],carouselItem +'-'+ slideDirection);
- addClass(slides[activeItem],carouselItem +'-'+ slideDirection);
-
- emulateTransitionEnd(slides[next], function(e) {
- var timeout = e && e[target] !== slides[next] ? e.elapsedTime*1000+100 : 20;
-
- isSliding && setTimeout(function(){
- isSliding = false;
-
- addClass(slides[next],active);
- removeClass(slides[activeItem],active);
-
- removeClass(slides[next],carouselItem +'-'+ orientation);
- removeClass(slides[next],carouselItem +'-'+ slideDirection);
- removeClass(slides[activeItem],carouselItem +'-'+ slideDirection);
-
- bootstrapCustomEvent.call(element, slidEvent, component, slides[next]);
-
- if ( !DOC.hidden && self[interval] && !hasClass(element,paused) ) {
- self.cycle();
- }
- }, timeout);
- });
-
+ if ( getElementTransitionDuration(slides[next]) && hasClass(element,'slide') ) {
+ addClass(slides[next],("carousel-item-" + orientation));
+ slides[next].offsetWidth;
+ addClass(slides[next],("carousel-item-" + (vars.direction)));
+ addClass(slides[activeItem],("carousel-item-" + (vars.direction)));
+ emulateTransitionEnd(slides[next], transitionEndHandler);
} else {
- addClass(slides[next],active);
- slides[next][offsetWidth];
- removeClass(slides[activeItem],active);
- setTimeout(function() {
- isSliding = false;
- if ( self[interval] && !hasClass(element,paused) ) {
+ addClass(slides[next],'active');
+ slides[next].offsetWidth;
+ removeClass(slides[activeItem],'active');
+ setTimeout(function () {
+ vars.isSliding = false;
+ if ( ops.interval && element && !hasClass(element,'paused') ) {
self.cycle();
}
- bootstrapCustomEvent.call(element, slidEvent, component, slides[next]);
+ dispatchCustomEvent.call(element, slidCustomEvent);
}, 100 );
}
};
- this.getActiveIndex = function () {
- return slides[indexOf](getElementsByClassName(element,carouselItem+' active')[0]) || 0;
+ self.getActiveIndex = function () { return Array.from(slides).indexOf(element.getElementsByClassName('carousel-item active')[0]) || 0; };
+ self.dispose = function () {
+ var itemClasses = ['left','right','prev','next'];
+ Array.from(slides).map(function (slide,idx) {
+ if (hasClass(slide,'active')){
+ setActivePage( idx );
+ }
+ itemClasses.map(function (cls) { return removeClass(slide,("carousel-item-" + cls)); });
+ });
+ clearInterval(vars.timer);
+ toggleEvents(off);
+ vars = {};
+ delete element.Carousel;
};
-
- // init
- if ( !(stringCarousel in element ) ) { // prevent adding event handlers twice
-
- if ( self[pause] && self[interval] ) {
- on( element, mouseHover[0], pauseHandler );
- on( element, mouseHover[1], resumeHandler );
- on( element, touchEvents.start, pauseHandler, passiveHandler );
- on( element, touchEvents.end, resumeHandler, passiveHandler );
- }
-
- slides[length] > 1 && on( element, touchEvents.start, touchDownHandler, passiveHandler );
-
- rightArrow && on( rightArrow, clickEvent, controlsHandler );
- leftArrow && on( leftArrow, clickEvent, controlsHandler );
-
- indicator && on( indicator, clickEvent, indicatorHandler );
- self[keyboard] && on( globalObject, keydownEvent, keyHandler );
-
- }
- if (self.getActiveIndex()<0) {
- slides[length] && addClass(slides[0],active);
- indicators[length] && setActivePage(0);
- }
-
- if ( self[interval] ){ self.cycle(); }
- element[stringCarousel] = self;
- };
-
- // CAROUSEL DATA API
- // =================
- supports[push]( [ stringCarousel, Carousel, '['+dataRide+'="carousel"]' ] );
-
-
- /* Native Javascript for Bootstrap 4 | Collapse
- -----------------------------------------------*/
-
- // COLLAPSE DEFINITION
- // ===================
- var Collapse = function( element, options ) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
+ vars = {};
+ vars.direction = 'left';
+ vars.index = 0;
+ vars.timer = null;
+ vars.isSliding = false;
+ vars.isTouch = false;
+ vars.touchPosition = {
+ startX : 0,
+ currentX : 0,
+ endX : 0
+ };
+ tryWrapper(function (){
+ element = queryElement( element );
+ element.Carousel && element.Carousel.dispose();
+ var
+ intervalAttribute = element.getAttribute('data-interval'),
+ intervalOption = options.interval,
+ intervalData = intervalAttribute === 'false' ? 0 : parseInt(intervalAttribute),
+ pauseData = element.getAttribute('data-pause') === 'hover' || false,
+ keyboardData = element.getAttribute('data-keyboard') === 'true' || false;
+ slides = element.getElementsByClassName('carousel-item');
+ leftArrow = element.getElementsByClassName('carousel-control-prev')[0];
+ rightArrow = element.getElementsByClassName('carousel-control-next')[0];
+ indicator = element.getElementsByClassName('carousel-indicators')[0];
+ indicators = indicator && indicator.getElementsByTagName( "LI" ) || [];
+ ops.keyboard = options.keyboard === true || keyboardData;
+ ops.pause = (options.pause === 'hover' || pauseData) ? 'hover' : false;
+ ops.interval = typeof intervalOption === 'number' ? intervalOption
+ : intervalOption === false || intervalData === 0 || intervalData === false ? 0
+ : isNaN(intervalData) ? 5000
+ : intervalData;
+ if (slides.length < 2) { return; }
+ if ( !element.Carousel ) {
+ toggleEvents(on);
+ }
+ if (self.getActiveIndex()<0) {
+ slides.length && addClass(slides[0],'active');
+ indicators.length && setActivePage(0);
+ }
+ if ( ops.interval ){ self.cycle(); }
+ element.Carousel = self;
+ },"BSN.Carousel");
+ }
+
+ function Collapse(element,options) {
options = options || {};
-
- // event targets and constants
- var accordion = null, collapse = null, self = this,
- accordionData = element[getAttribute]('data-parent'),
- activeCollapse, activeElement,
-
- // component strings
- component = 'collapse',
- collapsed = 'collapsed',
- isAnimating = 'isAnimating',
-
- // private methods
- openAction = function(collapseElement,toggle) {
- bootstrapCustomEvent.call(collapseElement, showEvent, component);
- collapseElement[isAnimating] = true;
- addClass(collapseElement,collapsing);
- removeClass(collapseElement,component);
- collapseElement[style][height] = collapseElement[scrollHeight] + 'px';
-
- emulateTransitionEnd(collapseElement, function() {
- collapseElement[isAnimating] = false;
- collapseElement[setAttribute](ariaExpanded,'true');
- toggle[setAttribute](ariaExpanded,'true');
- removeClass(collapseElement,collapsing);
- addClass(collapseElement, component);
- addClass(collapseElement,showClass);
- collapseElement[style][height] = '';
- bootstrapCustomEvent.call(collapseElement, shownEvent, component);
- });
- },
- closeAction = function(collapseElement,toggle) {
- bootstrapCustomEvent.call(collapseElement, hideEvent, component);
- collapseElement[isAnimating] = true;
- collapseElement[style][height] = collapseElement[scrollHeight] + 'px'; // set height first
- removeClass(collapseElement,component);
- removeClass(collapseElement,showClass);
- addClass(collapseElement,collapsing);
- collapseElement[offsetWidth]; // force reflow to enable transition
- collapseElement[style][height] = '0px';
-
- emulateTransitionEnd(collapseElement, function() {
- collapseElement[isAnimating] = false;
- collapseElement[setAttribute](ariaExpanded,'false');
- toggle[setAttribute](ariaExpanded,'false');
- removeClass(collapseElement,collapsing);
- addClass(collapseElement,component);
- collapseElement[style][height] = '';
- bootstrapCustomEvent.call(collapseElement, hiddenEvent, component);
- });
- },
- getTarget = function() {
- var href = element.href && element[getAttribute]('href'),
- parent = element[getAttribute](dataTarget),
- id = href || ( parent && parent.charAt(0) === '#' ) && parent;
- return id && queryElement(id);
- };
-
- // public methods
- this.toggle = function(e) {
- e[preventDefault]();
- if (!hasClass(collapse,showClass)) { self.show(); }
- else { self.hide(); }
+ var self = this;
+ var accordion = null,
+ collapse = null,
+ activeCollapse,
+ activeElement,
+ showCustomEvent,
+ shownCustomEvent,
+ hideCustomEvent,
+ hiddenCustomEvent;
+ function openAction(collapseElement, toggle) {
+ dispatchCustomEvent.call(collapseElement, showCustomEvent);
+ if ( showCustomEvent.defaultPrevented ) { return; }
+ collapseElement.isAnimating = true;
+ addClass(collapseElement,'collapsing');
+ removeClass(collapseElement,'collapse');
+ collapseElement.style.height = (collapseElement.scrollHeight) + "px";
+ emulateTransitionEnd(collapseElement, function () {
+ collapseElement.isAnimating = false;
+ collapseElement.setAttribute('aria-expanded','true');
+ toggle.setAttribute('aria-expanded','true');
+ removeClass(collapseElement,'collapsing');
+ addClass(collapseElement, 'collapse');
+ addClass(collapseElement,'show');
+ collapseElement.style.height = '';
+ dispatchCustomEvent.call(collapseElement, shownCustomEvent);
+ });
+ }
+ function closeAction(collapseElement, toggle) {
+ dispatchCustomEvent.call(collapseElement, hideCustomEvent);
+ if ( hideCustomEvent.defaultPrevented ) { return; }
+ collapseElement.isAnimating = true;
+ collapseElement.style.height = (collapseElement.scrollHeight) + "px";
+ removeClass(collapseElement,'collapse');
+ removeClass(collapseElement,'show');
+ addClass(collapseElement,'collapsing');
+ collapseElement.offsetWidth;
+ collapseElement.style.height = '0px';
+ emulateTransitionEnd(collapseElement, function () {
+ collapseElement.isAnimating = false;
+ collapseElement.setAttribute('aria-expanded','false');
+ toggle.setAttribute('aria-expanded','false');
+ removeClass(collapseElement,'collapsing');
+ addClass(collapseElement,'collapse');
+ collapseElement.style.height = '';
+ dispatchCustomEvent.call(collapseElement, hiddenCustomEvent);
+ });
+ }
+ self.toggle = function (e) {
+ if (e && e.target.tagName === 'A' || element.tagName === 'A') {e.preventDefault();}
+ if (element.contains(e.target) || e.target === element) {
+ if (!hasClass(collapse,'show')) { self.show(); }
+ else { self.hide(); }
+ }
};
- this.hide = function() {
- if ( collapse[isAnimating] ) return;
+ self.hide = function () {
+ if ( collapse.isAnimating ) { return; }
closeAction(collapse,element);
- addClass(element,collapsed);
+ addClass(element,'collapsed');
};
- this.show = function() {
+ self.show = function () {
if ( accordion ) {
- activeCollapse = queryElement('.'+component+'.'+showClass,accordion);
- activeElement = activeCollapse && (queryElement('['+dataTarget+'="#'+activeCollapse.id+'"]',accordion)
- || queryElement('[href="#'+activeCollapse.id+'"]',accordion) );
+ activeCollapse = accordion.getElementsByClassName("collapse show")[0];
+ activeElement = activeCollapse && (queryElement(("[data-target=\"#" + (activeCollapse.id) + "\"]"),accordion)
+ || queryElement(("[href=\"#" + (activeCollapse.id) + "\"]"),accordion) );
}
-
- if ( !collapse[isAnimating] || activeCollapse && !activeCollapse[isAnimating] ) {
+ if ( !collapse.isAnimating ) {
if ( activeElement && activeCollapse !== collapse ) {
- closeAction(activeCollapse,activeElement);
- addClass(activeElement,collapsed);
+ closeAction(activeCollapse,activeElement);
+ addClass(activeElement,'collapsed');
}
openAction(collapse,element);
- removeClass(element,collapsed);
+ removeClass(element,'collapsed');
}
};
-
- // init
- if ( !(stringCollapse in element ) ) { // prevent adding event handlers twice
- on(element, clickEvent, self.toggle);
- }
- collapse = getTarget();
- collapse[isAnimating] = false; // when true it will prevent click handlers
- accordion = queryElement(options.parent) || accordionData && getClosest(element, accordionData);
- element[stringCollapse] = self;
- };
-
- // COLLAPSE DATA API
- // =================
- supports[push]( [ stringCollapse, Collapse, '['+dataToggle+'="collapse"]' ] );
-
-
- /* Native Javascript for Bootstrap 4 | Dropdown
- ----------------------------------------------*/
-
- // DROPDOWN DEFINITION
- // ===================
- var Dropdown = function( element, option ) {
-
- // initialization element
- element = queryElement(element);
-
- // set option
- this.persist = option === true || element[getAttribute]('data-persist') === 'true' || false;
-
- // constants, event targets, strings
- var self = this, children = 'children',
- parent = element[parentNode],
- component = 'dropdown', open = 'open',
- relatedTarget = null,
- menu = queryElement('.dropdown-menu', parent),
- menuItems = (function(){
- var set = menu[children], newSet = [];
- for ( var i=0; i<set[length]; i++ ){
- set[i][children][length] && (set[i][children][0].tagName === 'A' && newSet[push](set[i][children][0]));
- set[i].tagName === 'A' && newSet[push](set[i]);
- }
- return newSet;
- })(),
-
- // preventDefault on empty anchor links
- preventEmptyAnchor = function(anchor){
- (anchor.href && anchor.href.slice(-1) === '#' || anchor[parentNode] && anchor[parentNode].href
- && anchor[parentNode].href.slice(-1) === '#') && this[preventDefault]();
- },
-
- // toggle dismissible events
- toggleDismiss = function(){
- var type = element[open] ? on : off;
- type(DOC, clickEvent, dismissHandler);
- type(DOC, keydownEvent, preventScroll);
- type(DOC, keyupEvent, keyHandler);
- type(DOC, focusEvent, dismissHandler, true);
- },
-
- // handlers
- dismissHandler = function(e) {
- var eventTarget = e[target], hasData = eventTarget && (eventTarget[getAttribute](dataToggle)
- || eventTarget[parentNode] && getAttribute in eventTarget[parentNode]
- && eventTarget[parentNode][getAttribute](dataToggle));
- if ( e.type === focusEvent && (eventTarget === element || eventTarget === menu || menu[contains](eventTarget) ) ) {
- return;
- }
- if ( (eventTarget === menu || menu[contains](eventTarget)) && (self.persist || hasData) ) { return; }
- else {
- relatedTarget = eventTarget === element || element[contains](eventTarget) ? element : null;
- hide();
- }
- preventEmptyAnchor.call(e,eventTarget);
- },
- clickHandler = function(e) {
- relatedTarget = element;
- show();
- preventEmptyAnchor.call(e,e[target]);
- },
- preventScroll = function(e){
- var key = e.which || e.keyCode;
- if( key === 38 || key === 40 ) { e[preventDefault](); }
- },
- keyHandler = function(e){
- var key = e.which || e.keyCode,
- activeItem = DOC.activeElement,
- idx = menuItems[indexOf](activeItem),
+ self.dispose = function () {
+ off(element, 'click', self.toggle);
+ delete element.Collapse;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.Collapse && element.Collapse.dispose();
+ var accordionData = element.getAttribute('data-parent');
+ showCustomEvent = bootstrapCustomEvent('show', 'collapse');
+ shownCustomEvent = bootstrapCustomEvent('shown', 'collapse');
+ hideCustomEvent = bootstrapCustomEvent('hide', 'collapse');
+ hiddenCustomEvent = bootstrapCustomEvent('hidden', 'collapse');
+ collapse = queryElement(options.target || element.getAttribute('data-target') || element.getAttribute('href'));
+ collapse.isAnimating = false;
+ accordion = element.closest(options.parent || accordionData);
+ if ( !element.Collapse ) {
+ on(element, 'click', self.toggle);
+ }
+ element.Collapse = self;
+ },"BSN.Collapse");
+ }
+
+ var mouseClickEvents = { down: 'mousedown', up: 'mouseup' };
+
+ var support3DTransform = 'webkitPerspective' in document.body.style || 'perspective' in document.body.style;
+
+ var supportTransform = 'webkitTransform' in document.body.style || 'transform' in document.body.style;
+
+ function setFocus (element){
+ element.focus ? element.focus() : element.setActive();
+ }
+ function getScroll () {
+ return {
+ y : window.pageYOffset || document.documentElement.scrollTop,
+ x : window.pageXOffset || document.documentElement.scrollLeft
+ }
+ }
+ function styleTip (link,element,position,parent) {
+ var tipPositions = /\b(top|bottom|left|right)+/,
+ elementDimensions = { w : element.offsetWidth, h: element.offsetHeight },
+ windowWidth = (document.documentElement.clientWidth || document.body.clientWidth),
+ windowHeight = (document.documentElement.clientHeight || document.body.clientHeight),
+ rect = link.getBoundingClientRect(),
+ scroll = parent === document.body ? getScroll() : { x: parent.offsetLeft + parent.scrollLeft, y: parent.offsetTop + parent.scrollTop },
+ linkDimensions = { w: rect.right - rect.left, h: rect.bottom - rect.top },
+ isPopover = hasClass(element,'popover'),
+ arrow = queryElement('.arrow',element),
+ halfTopExceed = rect.top + linkDimensions.h/2 - elementDimensions.h/2 < 0,
+ halfLeftExceed = rect.left + linkDimensions.w/2 - elementDimensions.w/2 < 0,
+ halfRightExceed = rect.left + elementDimensions.w/2 + linkDimensions.w/2 >= windowWidth,
+ halfBottomExceed = rect.top + elementDimensions.h/2 + linkDimensions.h/2 >= windowHeight,
+ topExceed = rect.top - elementDimensions.h < 0,
+ leftExceed = rect.left - elementDimensions.w < 0,
+ bottomExceed = rect.top + elementDimensions.h + linkDimensions.h >= windowHeight,
+ rightExceed = rect.left + elementDimensions.w + linkDimensions.w >= windowWidth;
+ position = (position === 'left' || position === 'right') && leftExceed && rightExceed ? 'top' : position;
+ position = position === 'top' && topExceed ? 'bottom' : position;
+ position = position === 'bottom' && bottomExceed ? 'top' : position;
+ position = position === 'left' && leftExceed ? 'right' : position;
+ position = position === 'right' && rightExceed ? 'left' : position;
+ var topPosition,
+ leftPosition,
+ arrowTop,
+ arrowLeft,
+ arrowWidth,
+ arrowHeight;
+ element.className.indexOf(position) === -1 && (element.className = element.className.replace(tipPositions,position));
+ arrowWidth = arrow.offsetWidth; arrowHeight = arrow.offsetHeight;
+ if ( position === 'left' || position === 'right' ) {
+ if ( position === 'left' ) {
+ leftPosition = rect.left + scroll.x - elementDimensions.w - ( isPopover ? arrowWidth : 0 );
+ } else {
+ leftPosition = rect.left + scroll.x + linkDimensions.w;
+ }
+ if (halfTopExceed) {
+ topPosition = rect.top + scroll.y;
+ arrowTop = linkDimensions.h/2 - arrowWidth;
+ } else if (halfBottomExceed) {
+ topPosition = rect.top + scroll.y - elementDimensions.h + linkDimensions.h;
+ arrowTop = elementDimensions.h - linkDimensions.h/2 - arrowWidth;
+ } else {
+ topPosition = rect.top + scroll.y - elementDimensions.h/2 + linkDimensions.h/2;
+ arrowTop = elementDimensions.h/2 - (isPopover ? arrowHeight*0.9 : arrowHeight/2);
+ }
+ } else if ( position === 'top' || position === 'bottom' ) {
+ if ( position === 'top') {
+ topPosition = rect.top + scroll.y - elementDimensions.h - ( isPopover ? arrowHeight : 0 );
+ } else {
+ topPosition = rect.top + scroll.y + linkDimensions.h;
+ }
+ if (halfLeftExceed) {
+ leftPosition = 0;
+ arrowLeft = rect.left + linkDimensions.w/2 - arrowWidth;
+ } else if (halfRightExceed) {
+ leftPosition = windowWidth - elementDimensions.w*1.01;
+ arrowLeft = elementDimensions.w - ( windowWidth - rect.left ) + linkDimensions.w/2 - arrowWidth/2;
+ } else {
+ leftPosition = rect.left + scroll.x - elementDimensions.w/2 + linkDimensions.w/2;
+ arrowLeft = elementDimensions.w/2 - ( isPopover ? arrowWidth : arrowWidth/2 );
+ }
+ }
+ element.style.top = topPosition + 'px';
+ element.style.left = leftPosition + 'px';
+ arrowTop && (arrow.style.top = arrowTop + 'px');
+ arrowLeft && (arrow.style.left = arrowLeft + 'px');
+ }
+
+ function Dropdown(element,option) {
+ var self = this,
+ showCustomEvent,
+ shownCustomEvent,
+ hideCustomEvent,
+ hiddenCustomEvent,
+ relatedTarget = null,
+ parent, menu, menuItems = [],
+ persist;
+ function preventEmptyAnchor(anchor) {
+ (anchor.href && anchor.href.slice(-1) === '#' || anchor.parentNode && anchor.parentNode.href
+ && anchor.parentNode.href.slice(-1) === '#') && this.preventDefault();
+ }
+ function toggleDismiss() {
+ var action = element.open ? on : off;
+ action(document, 'click', dismissHandler);
+ action(document, 'keydown', preventScroll);
+ action(document, 'keyup', keyHandler);
+ action(document, 'focus', dismissHandler, true);
+ }
+ function dismissHandler(e) {
+ var eventTarget = e.target,
+ hasData = eventTarget && (eventTarget.getAttribute('data-toggle')
+ || eventTarget.parentNode && eventTarget.parentNode.getAttribute
+ && eventTarget.parentNode.getAttribute('data-toggle'));
+ if ( e.type === 'focus' && (eventTarget === element || eventTarget === menu || menu.contains(eventTarget) ) ) {
+ return;
+ }
+ if ( (eventTarget === menu || menu.contains(eventTarget)) && (persist || hasData) ) { return; }
+ else {
+ relatedTarget = eventTarget === element || element.contains(eventTarget) ? element : null;
+ self.hide();
+ }
+ preventEmptyAnchor.call(e,eventTarget);
+ }
+ function clickHandler(e) {
+ relatedTarget = element;
+ self.show();
+ preventEmptyAnchor.call(e,e.target);
+ }
+ function preventScroll(e) {
+ var key = e.which || e.keyCode;
+ if( key === 38 || key === 40 ) { e.preventDefault(); }
+ }
+ function keyHandler(ref) {
+ var which = ref.which;
+ var keyCode = ref.keyCode;
+ var key = which || keyCode,
+ activeItem = document.activeElement,
isSameElement = activeItem === element,
- isInsideMenu = menu[contains](activeItem),
- isMenuItem = activeItem[parentNode] === menu || activeItem[parentNode][parentNode] === menu;
-
- if ( isMenuItem ) { // navigate up | down
- idx = isSameElement ? 0
- : key === 38 ? (idx>1?idx-1:0)
- : key === 40 ? (idx<menuItems[length]-1?idx+1:idx) : idx;
- menuItems[idx] && setFocus(menuItems[idx]);
- }
- if ( (menuItems[length] && isMenuItem // menu has items
- || !menuItems[length] && (isInsideMenu || isSameElement) // menu might be a form
- || !isInsideMenu ) // or the focused element is not in the menu at all
- && element[open] && key === 27 // menu must be open
- ) {
- self.toggle();
- relatedTarget = null;
- }
- },
-
- // private methods
- show = function() {
- bootstrapCustomEvent.call(parent, showEvent, component, relatedTarget);
- addClass(menu,showClass);
- addClass(parent,showClass);
- element[setAttribute](ariaExpanded,true);
- bootstrapCustomEvent.call(parent, shownEvent, component, relatedTarget);
- element[open] = true;
- off(element, clickEvent, clickHandler);
- setTimeout(function(){
- setFocus( menu[getElementsByTagName]('INPUT')[0] || element ); // focus the first input item | element
- toggleDismiss();
- },1);
- },
- hide = function() {
- bootstrapCustomEvent.call(parent, hideEvent, component, relatedTarget);
- removeClass(menu,showClass);
- removeClass(parent,showClass);
- element[setAttribute](ariaExpanded,false);
- bootstrapCustomEvent.call(parent, hiddenEvent, component, relatedTarget);
- element[open] = false;
+ isInsideMenu = menu.contains(activeItem),
+ isMenuItem = activeItem.parentNode === menu || activeItem.parentNode.parentNode === menu;
+ var idx = menuItems.indexOf(activeItem);
+ if ( isMenuItem ) {
+ idx = isSameElement ? 0
+ : key === 38 ? (idx>1?idx-1:0)
+ : key === 40 ? (idx<menuItems.length-1?idx+1:idx) : idx;
+ menuItems[idx] && setFocus(menuItems[idx]);
+ }
+ if ( (menuItems.length && isMenuItem
+ || !menuItems.length && (isInsideMenu || isSameElement)
+ || !isInsideMenu )
+ && element.open && key === 27
+ ) {
+ self.toggle();
+ relatedTarget = null;
+ }
+ }
+ self.show = function () {
+ showCustomEvent = bootstrapCustomEvent('show', 'dropdown', relatedTarget);
+ dispatchCustomEvent.call(parent, showCustomEvent);
+ if ( showCustomEvent.defaultPrevented ) { return; }
+ addClass(menu,'show');
+ addClass(parent,'show');
+ element.setAttribute('aria-expanded',true);
+ element.open = true;
+ off(element, 'click', clickHandler);
+ setTimeout(function () {
+ setFocus( menu.getElementsByTagName('INPUT')[0] || element );
toggleDismiss();
- setFocus(element);
- setTimeout(function(){ on(element, clickEvent, clickHandler); },1);
- };
-
- // set initial state to closed
- element[open] = false;
-
- // public methods
- this.toggle = function() {
- if (hasClass(parent,showClass) && element[open]) { hide(); }
- else { show(); }
+ shownCustomEvent = bootstrapCustomEvent( 'shown', 'dropdown', relatedTarget);
+ dispatchCustomEvent.call(parent, shownCustomEvent);
+ },1);
};
-
- // init
- if ( !(stringDropdown in element) ) { // prevent adding event handlers twice
- !tabindex in menu && menu[setAttribute](tabindex, '0'); // Fix onblur on Chrome | Safari
- on(element, clickEvent, clickHandler);
- }
-
- element[stringDropdown] = self;
- };
-
- // DROPDOWN DATA API
- // =================
- supports[push]( [stringDropdown, Dropdown, '['+dataToggle+'="dropdown"]'] );
-
-
- /* Native Javascript for Bootstrap 4 | Modal
- -------------------------------------------*/
-
- // MODAL DEFINITION
- // ===============
- var Modal = function(element, options) { // element can be the modal/triggering button
-
- // the modal (both JavaScript / DATA API init) / triggering button element (DATA API)
- element = queryElement(element);
-
- // strings
- var component = 'modal',
- staticString = 'static',
- modalTrigger = 'modalTrigger',
- paddingRight = 'paddingRight',
- modalBackdropString = 'modal-backdrop',
- isAnimating = 'isAnimating',
- // determine modal, triggering element
- btnCheck = element[getAttribute](dataTarget)||element[getAttribute]('href'),
- checkModal = queryElement( btnCheck ),
- modal = hasClass(element,component) ? element : checkModal;
-
- if ( hasClass(element, component) ) { element = null; } // modal is now independent of it's triggering element
-
- if ( !modal ) { return; } // invalidate
-
- // set options
+ self.hide = function () {
+ hideCustomEvent = bootstrapCustomEvent('hide', 'dropdown', relatedTarget);
+ dispatchCustomEvent.call(parent, hideCustomEvent);
+ if ( hideCustomEvent.defaultPrevented ) { return; }
+ removeClass(menu,'show');
+ removeClass(parent,'show');
+ element.setAttribute('aria-expanded',false);
+ element.open = false;
+ toggleDismiss();
+ setFocus(element);
+ setTimeout(function () {
+ element.Dropdown && on(element, 'click', clickHandler);
+ },1);
+ hiddenCustomEvent = bootstrapCustomEvent('hidden', 'dropdown', relatedTarget);
+ dispatchCustomEvent.call(parent, hiddenCustomEvent);
+ };
+ self.toggle = function () {
+ if (hasClass(parent,'show') && element.open) { self.hide(); }
+ else { self.show(); }
+ };
+ self.dispose = function () {
+ if (hasClass(parent,'show') && element.open) { self.hide(); }
+ off(element, 'click', clickHandler);
+ delete element.Dropdown;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.Dropdown && element.Dropdown.dispose();
+ parent = element.parentNode;
+ menu = queryElement('.dropdown-menu', parent);
+ Array.from(menu.children).map(function (child){
+ child.children.length && (child.children[0].tagName === 'A' && menuItems.push(child.children[0]));
+ child.tagName === 'A' && menuItems.push(child);
+ });
+ if ( !element.Dropdown ) {
+ !('tabindex' in menu) && menu.setAttribute('tabindex', '0');
+ on(element, 'click', clickHandler);
+ }
+ persist = option === true || element.getAttribute('data-persist') === 'true' || false;
+ element.open = false;
+ element.Dropdown = self;
+ },"BSN.Dropdown");
+ }
+
+ function Modal(element,options) {
options = options || {};
-
- this[keyboard] = options[keyboard] === false || modal[getAttribute](dataKeyboard) === 'false' ? false : true;
- this[backdrop] = options[backdrop] === staticString || modal[getAttribute](databackdrop) === staticString ? staticString : true;
- this[backdrop] = options[backdrop] === false || modal[getAttribute](databackdrop) === 'false' ? false : this[backdrop];
- this[animation] = hasClass(modal, 'fade') ? true : false;
- this[content] = options[content]; // JavaScript only
-
- // set an initial state of the modal
- modal[isAnimating] = false;
-
- // bind, constants, event targets and other vars
- var self = this, relatedTarget = null,
- bodyIsOverflowing, scrollBarWidth, overlay, overlayDelay, modalTimer,
-
- // also find fixed-top / fixed-bottom items
- fixedItems = getElementsByClassName(HTML,fixedTop).concat(getElementsByClassName(HTML,fixedBottom)),
-
- // private methods
- getWindowWidth = function() {
- var htmlRect = HTML[getBoundingClientRect]();
- return globalObject[innerWidth] || (htmlRect[right] - Math.abs(htmlRect[left]));
- },
- setScrollbar = function () {
- var bodyStyle = globalObject[getComputedStyle](DOC[body]),
- bodyPad = parseInt((bodyStyle[paddingRight]), 10), itemPad;
- if (bodyIsOverflowing) {
- DOC[body][style][paddingRight] = (bodyPad + scrollBarWidth) + 'px';
- modal[style][paddingRight] = scrollBarWidth+'px';
- if (fixedItems[length]){
- for (var i = 0; i < fixedItems[length]; i++) {
- itemPad = globalObject[getComputedStyle](fixedItems[i])[paddingRight];
- fixedItems[i][style][paddingRight] = ( parseInt(itemPad) + scrollBarWidth) + 'px';
- }
- }
- }
- },
- resetScrollbar = function () {
- DOC[body][style][paddingRight] = '';
- modal[style][paddingRight] = '';
- if (fixedItems[length]){
- for (var i = 0; i < fixedItems[length]; i++) {
- fixedItems[i][style][paddingRight] = '';
- }
- }
- },
- measureScrollbar = function () { // thx walsh
- var scrollDiv = DOC[createElement]('div'), widthValue;
- scrollDiv.className = component+'-scrollbar-measure'; // this is here to stay
- DOC[body][appendChild](scrollDiv);
- widthValue = scrollDiv[offsetWidth] - scrollDiv[clientWidth];
- DOC[body].removeChild(scrollDiv);
- return widthValue;
- },
- checkScrollbar = function () {
- bodyIsOverflowing = DOC[body][clientWidth] < getWindowWidth();
- scrollBarWidth = measureScrollbar();
- },
- createOverlay = function() {
- var newOverlay = DOC[createElement]('div');
- overlay = queryElement('.'+modalBackdropString);
-
- if ( overlay === null ) {
- newOverlay[setAttribute]('class', modalBackdropString + (self[animation] ? ' fade' : ''));
- overlay = newOverlay;
- DOC[body][appendChild](overlay);
- }
- modalOverlay = 1;
- },
- removeOverlay = function() {
- overlay = queryElement('.'+modalBackdropString);
- if ( overlay && overlay !== null && typeof overlay === 'object' ) {
- modalOverlay = 0;
- DOC[body].removeChild(overlay); overlay = null;
- }
- },
- // triggers
- triggerShow = function() {
- setFocus(modal);
- modal[isAnimating] = false;
- bootstrapCustomEvent.call(modal, shownEvent, component, relatedTarget);
-
- on(globalObject, resizeEvent, self.update, passiveHandler);
- on(modal, clickEvent, dismissHandler);
- on(DOC, keydownEvent, keyHandler);
- },
- triggerHide = function() {
- modal[style].display = '';
- element && (setFocus(element));
- bootstrapCustomEvent.call(modal, hiddenEvent, component);
-
- (function(){
- if (!getElementsByClassName(DOC,component+' '+showClass)[0]) {
- resetScrollbar();
- removeClass(DOC[body],component+'-open');
- overlay && hasClass(overlay,'fade') ? (removeClass(overlay,showClass), emulateTransitionEnd(overlay,removeOverlay))
- : removeOverlay();
-
- off(globalObject, resizeEvent, self.update, passiveHandler);
- off(modal, clickEvent, dismissHandler);
- off(DOC, keydownEvent, keyHandler);
- }
- }());
- modal[isAnimating] = false;
- },
- // handlers
- clickHandler = function(e) {
- if ( modal[isAnimating] ) return;
-
- var clickTarget = e[target];
- clickTarget = clickTarget[hasAttribute](dataTarget) || clickTarget[hasAttribute]('href') ? clickTarget : clickTarget[parentNode];
- if ( clickTarget === element && !hasClass(modal,showClass) ) {
- modal[modalTrigger] = element;
- relatedTarget = element;
- self.show();
- e[preventDefault]();
- }
- },
- keyHandler = function(e) {
- if ( modal[isAnimating] ) return;
-
- if (self[keyboard] && e.which == 27 && hasClass(modal,showClass) ) {
- self.hide();
- }
- },
- dismissHandler = function(e) {
- if ( modal[isAnimating] ) return;
- var clickTarget = e[target];
-
- if ( hasClass(modal,showClass) && ( clickTarget[parentNode][getAttribute](dataDismiss) === component
- || clickTarget[getAttribute](dataDismiss) === component
- || clickTarget === modal && self[backdrop] !== staticString ) ) {
- self.hide(); relatedTarget = null;
- e[preventDefault]();
- }
- };
-
- // public methods
- this.toggle = function() {
- if ( hasClass(modal,showClass) ) {this.hide();} else {this.show();}
+ var self = this, modal,
+ showCustomEvent,
+ shownCustomEvent,
+ hideCustomEvent,
+ hiddenCustomEvent,
+ relatedTarget = null,
+ scrollBarWidth,
+ overlay,
+ overlayDelay,
+ fixedItems,
+ ops = {};
+ function setScrollbar() {
+ var openModal = hasClass(document.body,'modal-open'),
+ bodyPad = parseInt(getComputedStyle(document.body).paddingRight),
+ modalOverflow = modal.clientHeight !== modal.scrollHeight,
+ itemPad;
+ modal.style.paddingRight = (!modalOverflow && scrollBarWidth?(scrollBarWidth + "px"):'');
+ document.body.style.paddingRight = (bodyPad + (openModal ?0:scrollBarWidth)) + "px";
+ fixedItems.length && fixedItems.map(function (fixed){
+ itemPad = getComputedStyle(fixed).paddingRight;
+ fixed.style.paddingRight = (parseInt(itemPad) + (openModal?0:scrollBarWidth)) + "px";
+ });
+ }
+ function resetScrollbar() {
+ document.body.style.paddingRight = '';
+ modal.style.paddingRight = '';
+ fixedItems.length && fixedItems.map(function (fixed){
+ fixed.style.paddingRight = '';
+ });
+ }
+ function measureScrollbar() {
+ var scrollDiv = document.createElement('div'), widthValue;
+ scrollDiv.className = 'modal-scrollbar-measure';
+ document.body.appendChild(scrollDiv);
+ widthValue = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+ document.body.removeChild(scrollDiv);
+ return widthValue;
+ }
+ function checkScrollbar() {
+ scrollBarWidth = measureScrollbar();
+ }
+ function createOverlay() {
+ var newOverlay = document.createElement('div');
+ overlay = queryElement('.modal-backdrop');
+ if ( overlay === null ) {
+ newOverlay.setAttribute('class', 'modal-backdrop' + (ops.animation ? ' fade' : ''));
+ overlay = newOverlay;
+ document.body.appendChild(overlay);
+ }
+ return overlay;
+ }
+ function removeOverlay () {
+ overlay = queryElement('.modal-backdrop');
+ if ( overlay && !document.getElementsByClassName('modal show')[0] ) {
+ document.body.removeChild(overlay); overlay = null;
+ }
+ overlay === null && (removeClass(document.body,'modal-open'), resetScrollbar());
+ }
+ function toggleEvents(action) {
+ action(window, 'resize', self.update, passiveHandler);
+ action(modal, 'click', dismissHandler);
+ action(document, 'keydown', keyHandler);
+ }
+ function beforeShow() {
+ modal.style.display = 'block';
+ checkScrollbar();
+ setScrollbar();
+ !document.getElementsByClassName('modal show')[0] && addClass(document.body,'modal-open');
+ addClass(modal,'show');
+ modal.setAttribute('aria-hidden', false);
+ hasClass(modal,'fade') ? emulateTransitionEnd(modal, triggerShow) : triggerShow();
+ }
+ function triggerShow() {
+ setFocus(modal);
+ modal.isAnimating = false;
+ toggleEvents(on);
+ shownCustomEvent = bootstrapCustomEvent('shown', 'modal', relatedTarget);
+ dispatchCustomEvent.call(modal, shownCustomEvent);
+ }
+ function triggerHide(force) {
+ modal.style.display = '';
+ element && (setFocus(element));
+ overlay = queryElement('.modal-backdrop');
+ if (force !== 1 && overlay && hasClass(overlay,'show') && !document.getElementsByClassName('modal show')[0]) {
+ removeClass(overlay,'show');
+ emulateTransitionEnd(overlay,removeOverlay);
+ } else {
+ removeOverlay();
+ }
+ toggleEvents(off);
+ modal.isAnimating = false;
+ hiddenCustomEvent = bootstrapCustomEvent('hidden', 'modal');
+ dispatchCustomEvent.call(modal, hiddenCustomEvent);
+ }
+ function clickHandler(e) {
+ if ( modal.isAnimating ) { return; }
+ var clickTarget = e.target,
+ modalID = "#" + (modal.getAttribute('id')),
+ targetAttrValue = clickTarget.getAttribute('data-target') || clickTarget.getAttribute('href'),
+ elemAttrValue = element.getAttribute('data-target') || element.getAttribute('href');
+ if ( !hasClass(modal,'show')
+ && (clickTarget === element && targetAttrValue === modalID
+ || element.contains(clickTarget) && elemAttrValue === modalID) ) {
+ modal.modalTrigger = element;
+ relatedTarget = element;
+ self.show();
+ e.preventDefault();
+ }
+ }
+ function keyHandler(ref) {
+ var which = ref.which;
+ if (!modal.isAnimating && ops.keyboard && which == 27 && hasClass(modal,'show') ) {
+ self.hide();
+ }
+ }
+ function dismissHandler(e) {
+ if ( modal.isAnimating ) { return; }
+ var clickTarget = e.target,
+ hasData = clickTarget.getAttribute('data-dismiss') === 'modal',
+ parentWithData = clickTarget.closest('[data-dismiss="modal"]');
+ if ( hasClass(modal,'show') && ( parentWithData || hasData
+ || clickTarget === modal && ops.backdrop !== 'static' ) ) {
+ self.hide(); relatedTarget = null;
+ e.preventDefault();
+ }
+ }
+ self.toggle = function () {
+ if ( hasClass(modal,'show') ) {self.hide();} else {self.show();}
};
- this.show = function() {
- if ( hasClass(modal,showClass) || modal[isAnimating] ) {return}
-
- clearTimeout(modalTimer);
- modalTimer = setTimeout(function(){
- modal[isAnimating] = true;
- bootstrapCustomEvent.call(modal, showEvent, component, relatedTarget);
-
- // we elegantly hide any opened modal
- var currentOpen = getElementsByClassName(DOC,component+' '+showClass)[0];
- if (currentOpen && currentOpen !== modal) {
- modalTrigger in currentOpen && currentOpen[modalTrigger][stringModal].hide();
- stringModal in currentOpen && currentOpen[stringModal].hide();
- }
-
- if ( self[backdrop] ) {
- !modalOverlay && !overlay && createOverlay();
- }
-
- if ( overlay && !hasClass(overlay,showClass) ) {
- overlay[offsetWidth]; // force reflow to enable trasition
- overlayDelay = getTransitionDurationFromElement(overlay);
- addClass(overlay, showClass);
- }
-
- setTimeout( function() {
- modal[style].display = 'block';
-
- checkScrollbar();
- setScrollbar();
-
- addClass(DOC[body],component+'-open');
- addClass(modal,showClass);
- modal[setAttribute](ariaHidden, false);
-
- hasClass(modal,'fade') ? emulateTransitionEnd(modal, triggerShow) : triggerShow();
- }, supportTransitions && overlay && overlayDelay ? overlayDelay : 1);
- },1);
+ self.show = function () {
+ if (hasClass(modal, 'show') && !!modal.isAnimating ) {return}
+ showCustomEvent = bootstrapCustomEvent('show', 'modal', relatedTarget);
+ dispatchCustomEvent.call(modal, showCustomEvent);
+ if ( showCustomEvent.defaultPrevented ) { return; }
+ modal.isAnimating = true;
+ var currentOpen = document.getElementsByClassName('modal show')[0];
+ if (currentOpen && currentOpen !== modal) {
+ currentOpen.modalTrigger && currentOpen.modalTrigger.Modal.hide();
+ currentOpen.Modal && currentOpen.Modal.hide();
+ }
+ if ( ops.backdrop ) {
+ overlay = createOverlay();
+ }
+ if ( overlay && !currentOpen && !hasClass(overlay,'show') ) {
+ overlay.offsetWidth;
+ overlayDelay = getElementTransitionDuration(overlay);
+ addClass(overlay, 'show');
+ }
+ !currentOpen ? setTimeout( beforeShow, overlay && overlayDelay ? overlayDelay:0 ) : beforeShow();
};
- this.hide = function() {
- if ( modal[isAnimating] || !hasClass(modal,showClass) ) {return}
-
- clearTimeout(modalTimer);
- modalTimer = setTimeout(function(){
- modal[isAnimating] = true;
- bootstrapCustomEvent.call(modal, hideEvent, component);
- overlay = queryElement('.'+modalBackdropString);
- overlayDelay = overlay && getTransitionDurationFromElement(overlay);
-
- removeClass(modal,showClass);
- modal[setAttribute](ariaHidden, true);
-
- setTimeout(function(){
- hasClass(modal,'fade') ? emulateTransitionEnd(modal, triggerHide) : triggerHide();
- }, supportTransitions && overlay && overlayDelay ? overlayDelay : 2);
- },2)
+ self.hide = function (force) {
+ if ( !hasClass(modal,'show') ) {return}
+ hideCustomEvent = bootstrapCustomEvent( 'hide', 'modal');
+ dispatchCustomEvent.call(modal, hideCustomEvent);
+ if ( hideCustomEvent.defaultPrevented ) { return; }
+ modal.isAnimating = true;
+ removeClass(modal,'show');
+ modal.setAttribute('aria-hidden', true);
+ hasClass(modal,'fade') && force !== 1 ? emulateTransitionEnd(modal, triggerHide) : triggerHide();
};
- this.setContent = function( content ) {
- queryElement('.'+component+'-content',modal)[innerHTML] = content;
+ self.setContent = function (content) {
+ queryElement('.modal-content',modal).innerHTML = content;
};
- this.update = function() {
- if (hasClass(modal,showClass)) {
+ self.update = function () {
+ if (hasClass(modal,'show')) {
checkScrollbar();
setScrollbar();
}
};
-
- // init
- // prevent adding event handlers over and over
- // modal is independent of a triggering element
- if ( !!element && !(stringModal in element) ) {
- on(element, clickEvent, clickHandler);
- }
- if ( !!self[content] ) { self.setContent( self[content] ); }
- if (element) { element[stringModal] = self; modal[modalTrigger] = element; }
- else { modal[stringModal] = self; }
- };
-
- // DATA API
- supports[push]( [ stringModal, Modal, '['+dataToggle+'="modal"]' ] );
-
- /* Native Javascript for Bootstrap 4 | Popover
- ----------------------------------------------*/
-
- // POPOVER DEFINITION
- // ==================
- var Popover = function( element, options ) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
+ self.dispose = function () {
+ self.hide(1);
+ if (element) {off(element, 'click', clickHandler); delete element.Modal; }
+ else {delete modal.Modal;}
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ var checkModal = queryElement( element.getAttribute('data-target') || element.getAttribute('href') );
+ modal = hasClass(element,'modal') ? element : checkModal;
+ fixedItems = Array.from(document.getElementsByClassName('fixed-top'))
+ .concat(Array.from(document.getElementsByClassName('fixed-bottom')));
+ if ( hasClass(element, 'modal') ) { element = null; }
+ element && element.Modal && element.Modal.dispose();
+ modal && modal.Modal && modal.Modal.dispose();
+ ops.keyboard = options.keyboard === false || modal.getAttribute('data-keyboard') === 'false' ? false : true;
+ ops.backdrop = options.backdrop === 'static' || modal.getAttribute('data-backdrop') === 'static' ? 'static' : true;
+ ops.backdrop = options.backdrop === false || modal.getAttribute('data-backdrop') === 'false' ? false : ops.backdrop;
+ ops.animation = hasClass(modal, 'fade') ? true : false;
+ ops.content = options.content;
+ modal.isAnimating = false;
+ if ( element && !element.Modal ) {
+ on(element, 'click', clickHandler);
+ }
+ if ( ops.content ) {
+ self.setContent( ops.content.trim() );
+ }
+ if (element) {
+ modal.modalTrigger = element;
+ element.Modal = self;
+ } else {
+ modal.Modal = self;
+ }
+ },"BSN.Modal");
+ }
+
+ function Popover(element,options) {
options = options || {};
-
- // DATA API
- var triggerData = element[getAttribute](dataTrigger), // click / hover / focus
- animationData = element[getAttribute](dataAnimation), // true / false
- placementData = element[getAttribute](dataPlacement),
- dismissibleData = element[getAttribute](dataDismissible),
- delayData = element[getAttribute](dataDelay),
- containerData = element[getAttribute](dataContainer),
-
- // internal strings
- component = 'popover',
- template = 'template',
- trigger = 'trigger',
- classString = 'class',
- div = 'div',
- fade = 'fade',
- dataContent = 'data-content',
- dismissible = 'dismissible',
- closeBtn = '<button type="button" class="close">×</button>',
-
- // check container
- containerElement = queryElement(options[container]),
- containerDataElement = queryElement(containerData),
-
- // maybe the element is inside a modal
- modal = getClosest(element,'.modal'),
-
- // maybe the element is inside a fixed navbar
- navbarFixedTop = getClosest(element,'.'+fixedTop),
- navbarFixedBottom = getClosest(element,'.'+fixedBottom);
-
- // set instance options
- this[template] = options[template] ? options[template] : null; // JavaScript only
- this[trigger] = options[trigger] ? options[trigger] : triggerData || hoverEvent;
- this[animation] = options[animation] && options[animation] !== fade ? options[animation] : animationData || fade;
- this[placement] = options[placement] ? options[placement] : placementData || top;
- this[delay] = parseInt(options[delay] || delayData) || 200;
- this[dismissible] = options[dismissible] || dismissibleData === 'true' ? true : false;
- this[container] = containerElement ? containerElement
- : containerDataElement ? containerDataElement
- : navbarFixedTop ? navbarFixedTop
- : navbarFixedBottom ? navbarFixedBottom
- : modal ? modal : DOC[body];
-
- // bind, content
- var self = this,
- titleString = options.title || element[getAttribute](dataTitle) || null,
- contentString = options.content || element[getAttribute](dataContent) || null;
-
- if ( !contentString && !this[template] ) return; // invalidate
-
- // constants, vars
- var popover = null, timer = 0, placementSetting = this[placement],
-
- // handlers
- dismissibleHandler = function(e) {
- if (popover !== null && e[target] === queryElement('.close',popover)) {
- self.hide();
- }
- },
-
- // private methods
- removePopover = function() {
- self[container].removeChild(popover);
- timer = null; popover = null;
- },
- createPopover = function() {
- titleString = options.title || element[getAttribute](dataTitle);
- contentString = options.content || element[getAttribute](dataContent);
- // fixing https://github.com/thednp/bootstrap.native/issues/233
- contentString = !!contentString ? contentString.trim() : null;
-
- popover = DOC[createElement](div);
-
- // popover arrow
- var popoverArrow = DOC[createElement](div);
- popoverArrow[setAttribute](classString,'arrow');
- popover[appendChild](popoverArrow);
-
- if ( contentString !== null && self[template] === null ) { //create the popover from data attributes
-
- popover[setAttribute]('role','tooltip');
-
- if (titleString !== null) {
- var popoverTitle = DOC[createElement]('h3');
- popoverTitle[setAttribute](classString,component+'-header');
-
- popoverTitle[innerHTML] = self[dismissible] ? titleString + closeBtn : titleString;
- popover[appendChild](popoverTitle);
- }
-
- //set popover content
- var popoverContent = DOC[createElement](div);
- popoverContent[setAttribute](classString,component+'-body');
- popoverContent[innerHTML] = self[dismissible] && titleString === null ? contentString + closeBtn : contentString;
- popover[appendChild](popoverContent);
-
- } else { // or create the popover from template
- var popoverTemplate = DOC[createElement](div);
- self[template] = self[template].trim();
- popoverTemplate[innerHTML] = self[template];
- popover[innerHTML] = popoverTemplate.firstChild[innerHTML];
- }
-
- //append to the container
- self[container][appendChild](popover);
- popover[style].display = 'block';
- popover[setAttribute](classString, component+ ' bs-' + component+'-'+placementSetting + ' ' + self[animation]);
- },
- showPopover = function () {
- !hasClass(popover,showClass) && ( addClass(popover,showClass) );
- },
- updatePopover = function() {
- styleTip(element, popover, placementSetting, self[container]);
- },
-
- // event toggle
- dismissHandlerToggle = function(type){
- if (clickEvent == self[trigger] || 'focus' == self[trigger]) {
- !self[dismissible] && type( element, 'blur', self.hide );
+ var self = this;
+ var popover = null,
+ timer = 0,
+ isIphone = /(iPhone|iPod|iPad)/.test(navigator.userAgent),
+ titleString,
+ contentString,
+ ops = {};
+ var triggerData,
+ animationData,
+ placementData,
+ dismissibleData,
+ delayData,
+ containerData,
+ closeBtn,
+ showCustomEvent,
+ shownCustomEvent,
+ hideCustomEvent,
+ hiddenCustomEvent,
+ containerElement,
+ containerDataElement,
+ modal,
+ navbarFixedTop,
+ navbarFixedBottom,
+ placementClass;
+ function dismissibleHandler(e) {
+ if (popover !== null && e.target === queryElement('.close',popover)) {
+ self.hide();
+ }
+ }
+ function getContents() {
+ return {
+ 0 : options.title || element.getAttribute('data-title') || null,
+ 1 : options.content || element.getAttribute('data-content') || null
+ }
+ }
+ function removePopover() {
+ ops.container.removeChild(popover);
+ timer = null; popover = null;
+ }
+ function createPopover() {
+ titleString = getContents()[0] || null;
+ contentString = getContents()[1];
+ contentString = !!contentString ? contentString.trim() : null;
+ popover = document.createElement('div');
+ var popoverArrow = document.createElement('div');
+ addClass(popoverArrow,'arrow');
+ popover.appendChild(popoverArrow);
+ if ( contentString !== null && ops.template === null ) {
+ popover.setAttribute('role','tooltip');
+ if (titleString !== null) {
+ var popoverTitle = document.createElement('h3');
+ addClass(popoverTitle,'popover-header');
+ popoverTitle.innerHTML = ops.dismissible ? titleString + closeBtn : titleString;
+ popover.appendChild(popoverTitle);
}
- self[dismissible] && type( DOC, clickEvent, dismissibleHandler );
- type( globalObject, resizeEvent, self.hide, passiveHandler );
- },
-
- // triggers
- showTrigger = function() {
- dismissHandlerToggle(on);
- bootstrapCustomEvent.call(element, shownEvent, component);
- },
- hideTrigger = function() {
- dismissHandlerToggle(off);
- removePopover();
- bootstrapCustomEvent.call(element, hiddenEvent, component);
- };
-
- // public methods / handlers
- this.toggle = function() {
- if (popover === null) { self.show(); }
+ var popoverBodyMarkup = document.createElement('div');
+ addClass(popoverBodyMarkup,'popover-body');
+ popoverBodyMarkup.innerHTML = ops.dismissible && titleString === null ? contentString + closeBtn : contentString;
+ popover.appendChild(popoverBodyMarkup);
+ } else {
+ var popoverTemplate = document.createElement('div');
+ popoverTemplate.innerHTML = ops.template.trim();
+ popover.className = popoverTemplate.firstChild.className;
+ popover.innerHTML = popoverTemplate.firstChild.innerHTML;
+ var popoverHeader = queryElement('.popover-header',popover),
+ popoverBody = queryElement('.popover-body',popover);
+ titleString && popoverHeader && (popoverHeader.innerHTML = titleString.trim());
+ contentString && popoverBody && (popoverBody.innerHTML = contentString.trim());
+ }
+ ops.container.appendChild(popover);
+ popover.style.display = 'block';
+ !hasClass(popover, 'popover') && addClass(popover, 'popover');
+ !hasClass(popover, ops.animation) && addClass(popover, ops.animation);
+ !hasClass(popover, placementClass) && addClass(popover, placementClass);
+ }
+ function showPopover() {
+ !hasClass(popover,'show') && ( addClass(popover,'show') );
+ }
+ function updatePopover() {
+ styleTip(element, popover, ops.placement, ops.container);
+ }
+ function provideFocus () {
+ if (popover === null) { element.focus(); }
+ }
+ function toggleEvents(action) {
+ if (ops.trigger === 'hover') {
+ action( element, mouseClickEvents.down, self.show );
+ action( element, mouseHoverEvents[0], self.show );
+ if (!ops.dismissible) { action( element, mouseHoverEvents[1], self.hide ); }
+ } else if ('click' == ops.trigger) {
+ action( element, ops.trigger, self.toggle );
+ } else if ('focus' == ops.trigger) {
+ isIphone && action( element, 'click', provideFocus );
+ action( element, ops.trigger, self.toggle );
+ }
+ }
+ function touchHandler(e){
+ if ( popover && popover.contains(e.target) || e.target === element || element.contains(e.target)) ; else {
+ self.hide();
+ }
+ }
+ function dismissHandlerToggle(action) {
+ if (ops.dismissible) {
+ action( document, 'click', dismissibleHandler );
+ } else {
+ 'focus' == ops.trigger && action( element, 'blur', self.hide );
+ 'hover' == ops.trigger && action( document, touchEvents.start, touchHandler, passiveHandler );
+ }
+ action( window, 'resize', self.hide, passiveHandler );
+ }
+ function showTrigger() {
+ dismissHandlerToggle(on);
+ dispatchCustomEvent.call(element, shownCustomEvent);
+ }
+ function hideTrigger() {
+ dismissHandlerToggle(off);
+ removePopover();
+ dispatchCustomEvent.call(element, hiddenCustomEvent);
+ }
+ self.toggle = function () {
+ if (popover === null) { self.show(); }
else { self.hide(); }
};
- this.show = function() {
+ self.show = function () {
clearTimeout(timer);
- timer = setTimeout( function() {
+ timer = setTimeout( function () {
if (popover === null) {
- placementSetting = self[placement]; // we reset placement in all cases
+ dispatchCustomEvent.call(element, showCustomEvent);
+ if ( showCustomEvent.defaultPrevented ) { return; }
createPopover();
updatePopover();
showPopover();
- bootstrapCustomEvent.call(element, showEvent, component);
- !!self[animation] ? emulateTransitionEnd(popover, showTrigger) : showTrigger();
+ !!ops.animation ? emulateTransitionEnd(popover, showTrigger) : showTrigger();
}
}, 20 );
};
- this.hide = function() {
+ self.hide = function () {
clearTimeout(timer);
- timer = setTimeout( function() {
- if (popover && popover !== null && hasClass(popover,showClass)) {
- bootstrapCustomEvent.call(element, hideEvent, component);
- removeClass(popover,showClass);
- !!self[animation] ? emulateTransitionEnd(popover, hideTrigger) : hideTrigger();
+ timer = setTimeout( function () {
+ if (popover && popover !== null && hasClass(popover,'show')) {
+ dispatchCustomEvent.call(element, hideCustomEvent);
+ if ( hideCustomEvent.defaultPrevented ) { return; }
+ removeClass(popover,'show');
+ !!ops.animation ? emulateTransitionEnd(popover, hideTrigger) : hideTrigger();
}
- }, self[delay] );
+ }, ops.delay );
};
-
- // init
- if ( !(stringPopover in element) ) { // prevent adding event handlers twice
- if (self[trigger] === hoverEvent) {
- on( element, mouseHover[0], self.show );
- if (!self[dismissible]) { on( element, mouseHover[1], self.hide ); }
- } else if (clickEvent == self[trigger] || 'focus' == self[trigger]) {
- on( element, self[trigger], self.toggle );
+ self.dispose = function () {
+ self.hide();
+ toggleEvents(off);
+ delete element.Popover;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.Popover && element.Popover.dispose();
+ triggerData = element.getAttribute('data-trigger');
+ animationData = element.getAttribute('data-animation');
+ placementData = element.getAttribute('data-placement');
+ dismissibleData = element.getAttribute('data-dismissible');
+ delayData = element.getAttribute('data-delay');
+ containerData = element.getAttribute('data-container');
+ closeBtn = '<button type="button" class="close">×</button>';
+ showCustomEvent = bootstrapCustomEvent('show', 'popover');
+ shownCustomEvent = bootstrapCustomEvent('shown', 'popover');
+ hideCustomEvent = bootstrapCustomEvent('hide', 'popover');
+ hiddenCustomEvent = bootstrapCustomEvent('hidden', 'popover');
+ containerElement = queryElement(options.container);
+ containerDataElement = queryElement(containerData);
+ modal = element.closest('.modal');
+ navbarFixedTop = element.closest('.fixed-top');
+ navbarFixedBottom = element.closest('.fixed-bottom');
+ ops.template = options.template ? options.template : null;
+ ops.trigger = options.trigger ? options.trigger : triggerData || 'hover';
+ ops.animation = options.animation && options.animation !== 'fade' ? options.animation : animationData || 'fade';
+ ops.placement = options.placement ? options.placement : placementData || 'top';
+ ops.delay = parseInt(options.delay || delayData) || 200;
+ ops.dismissible = options.dismissible || dismissibleData === 'true' ? true : false;
+ ops.container = containerElement ? containerElement
+ : containerDataElement ? containerDataElement
+ : navbarFixedTop ? navbarFixedTop
+ : navbarFixedBottom ? navbarFixedBottom
+ : modal ? modal : document.body;
+ placementClass = "bs-popover-" + (ops.placement);
+ var popoverContents = getContents();
+ titleString = popoverContents[0];
+ contentString = popoverContents[1];
+ if ( !contentString && !ops.template ) { return; }
+ if ( !element.Popover ) {
+ toggleEvents(on);
}
- }
- element[stringPopover] = self;
- };
-
- // POPOVER DATA API
- // ================
- supports[push]( [ stringPopover, Popover, '['+dataToggle+'="popover"]' ] );
-
-
- /* Native Javascript for Bootstrap 4 | ScrollSpy
- -----------------------------------------------*/
-
- // SCROLLSPY DEFINITION
- // ====================
- var ScrollSpy = function(element, options) {
-
- // initialization element, the element we spy on
- element = queryElement(element);
-
- // DATA API
- var targetData = queryElement(element[getAttribute](dataTarget)),
- offsetData = element[getAttribute]('data-offset');
-
- // set options
+ element.Popover = self;
+ },"BSN.Popover");
+ }
+
+ function ScrollSpy(element,options) {
options = options || {};
-
- // invalidate
- if ( !options[target] && !targetData ) { return; }
-
- // event targets, constants
- var self = this, spyTarget = options[target] && queryElement(options[target]) || targetData,
- links = spyTarget && spyTarget[getElementsByTagName]('A'),
- offset = parseInt(options['offset'] || offsetData) || 10,
- items = [], targetItems = [], scrollOffset,
- scrollTarget = element[offsetHeight] < element[scrollHeight] ? element : globalObject, // determine which is the real scrollTarget
- isWindow = scrollTarget === globalObject;
-
- // populate items and targets
- for (var i=0, il=links[length]; i<il; i++) {
- var href = links[i][getAttribute]('href'),
- targetItem = href && href.charAt(0) === '#' && href.slice(-1) !== '#' && queryElement(href);
- if ( !!targetItem ) {
- items[push](links[i]);
- targetItems[push](targetItem);
- }
- }
-
- // private methods
- var updateItem = function(index) {
- var item = items[index],
- targetItem = targetItems[index], // the menu item targets this element
- dropdown = item[parentNode][parentNode],
- dropdownLink = hasClass(dropdown,'dropdown') && dropdown[getElementsByTagName]('A')[0],
- targetRect = isWindow && targetItem[getBoundingClientRect](),
-
- isActive = hasClass(item,active) || false,
-
- topEdge = (isWindow ? targetRect[top] + scrollOffset : targetItem[offsetTop]) - offset,
- bottomEdge = isWindow ? targetRect[bottom] + scrollOffset - offset : targetItems[index+1] ? targetItems[index+1][offsetTop] - offset : element[scrollHeight],
-
- inside = scrollOffset >= topEdge && bottomEdge > scrollOffset;
-
- if ( !isActive && inside ) {
- if ( !hasClass(item,active) ) {
- addClass(item,active);
- if (dropdownLink && !hasClass(dropdownLink,active) ) {
- addClass(dropdownLink,active);
- }
- bootstrapCustomEvent.call(element, 'activate', 'scrollspy', items[index]);
- }
- } else if ( !inside ) {
- if ( hasClass(item,active) ) {
- removeClass(item,active);
- if (dropdownLink && hasClass(dropdownLink,active) && !getElementsByClassName(item[parentNode],active).length ) {
- removeClass(dropdownLink,active);
- }
+ var self = this,
+ vars,
+ targetData,
+ offsetData,
+ spyTarget,
+ scrollTarget,
+ ops = {};
+ function updateTargets(){
+ var links = spyTarget.getElementsByTagName('A');
+ if (vars.length !== links.length) {
+ vars.items = [];
+ vars.targets = [];
+ Array.from(links).map(function (link){
+ var href = link.getAttribute('href'),
+ targetItem = href && href.charAt(0) === '#' && href.slice(-1) !== '#' && queryElement(href);
+ if ( targetItem ) {
+ vars.items.push(link);
+ vars.targets.push(targetItem);
}
- } else if ( !inside && !isActive || isActive && inside ) {
- return;
+ });
+ vars.length = links.length;
+ }
+ }
+ function updateItem(index) {
+ var item = vars.items[index],
+ targetItem = vars.targets[index],
+ dropmenu = hasClass(item,'dropdown-item') && item.closest('.dropdown-menu'),
+ dropLink = dropmenu && dropmenu.previousElementSibling,
+ nextSibling = item.nextElementSibling,
+ activeSibling = nextSibling && nextSibling.getElementsByClassName('active').length,
+ targetRect = vars.isWindow && targetItem.getBoundingClientRect(),
+ isActive = hasClass(item,'active') || false,
+ topEdge = (vars.isWindow ? targetRect.top + vars.scrollOffset : targetItem.offsetTop) - ops.offset,
+ bottomEdge = vars.isWindow ? targetRect.bottom + vars.scrollOffset - ops.offset
+ : vars.targets[index+1] ? vars.targets[index+1].offsetTop - ops.offset
+ : element.scrollHeight,
+ inside = activeSibling || vars.scrollOffset >= topEdge && bottomEdge > vars.scrollOffset;
+ if ( !isActive && inside ) {
+ addClass(item,'active');
+ if (dropLink && !hasClass(dropLink,'active') ) {
+ addClass(dropLink,'active');
}
- },
- updateItems = function(){
- scrollOffset = isWindow ? getScroll().y : element[scrollTop];
- for (var index=0, itl=items[length]; index<itl; index++) {
- updateItem(index)
+ dispatchCustomEvent.call(element, bootstrapCustomEvent( 'activate', 'scrollspy', vars.items[index]));
+ } else if ( isActive && !inside ) {
+ removeClass(item,'active');
+ if (dropLink && hasClass(dropLink,'active') && !item.parentNode.getElementsByClassName('active').length ) {
+ removeClass(dropLink,'active');
}
- };
-
- // public method
- this.refresh = function () {
- updateItems();
+ } else if ( isActive && inside || !inside && !isActive ) {
+ return;
+ }
}
-
- // init
- if ( !(stringScrollSpy in element) ) { // prevent adding event handlers twice
- on( scrollTarget, scrollEvent, self.refresh, passiveHandler );
- on( globalObject, resizeEvent, self.refresh, passiveHandler );
+ function updateItems() {
+ updateTargets();
+ vars.scrollOffset = vars.isWindow ? getScroll().y : element.scrollTop;
+ vars.items.map(function (l,idx){ return updateItem(idx); });
}
- self.refresh();
- element[stringScrollSpy] = self;
- };
-
- // SCROLLSPY DATA API
- // ==================
- supports[push]( [ stringScrollSpy, ScrollSpy, '['+dataSpy+'="scroll"]' ] );
-
-
- /* Native Javascript for Bootstrap 4 | Tab
- -----------------------------------------*/
-
- // TAB DEFINITION
- // ==============
- var Tab = function( element, options ) {
-
- // initialization element
- element = queryElement(element);
-
- // DATA API
- var heightData = element[getAttribute](dataHeight),
-
- // strings
- component = 'tab', height = 'height', float = 'float', isAnimating = 'isAnimating';
-
- // set options
+ function toggleEvents(action) {
+ action( scrollTarget, 'scroll', self.refresh, passiveHandler );
+ action( window, 'resize', self.refresh, passiveHandler );
+ }
+ self.refresh = function () {
+ updateItems();
+ };
+ self.dispose = function () {
+ toggleEvents(off);
+ delete element.ScrollSpy;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.ScrollSpy && element.ScrollSpy.dispose();
+ targetData = element.getAttribute('data-target');
+ offsetData = element.getAttribute('data-offset');
+ spyTarget = queryElement(options.target || targetData);
+ scrollTarget = element.offsetHeight < element.scrollHeight ? element : window;
+ if (!spyTarget) { return }
+ ops.target = spyTarget;
+ ops.offset = parseInt(options.offset || offsetData) || 10;
+ vars = {};
+ vars.length = 0;
+ vars.items = [];
+ vars.targets = [];
+ vars.isWindow = scrollTarget === window;
+ if ( !element.ScrollSpy ) {
+ toggleEvents(on);
+ }
+ self.refresh();
+ element.ScrollSpy = self;
+ },"BSN.ScrollSpy");
+ }
+
+ function Tab(element,options) {
options = options || {};
- this[height] = supportTransitions ? (options[height] || heightData === 'true') : false;
-
- // bind, event targets
- var self = this, next,
- tabs = getClosest(element,'.nav'),
+ var self = this,
+ heightData,
+ tabs, dropdown,
+ showCustomEvent,
+ shownCustomEvent,
+ hideCustomEvent,
+ hiddenCustomEvent,
+ next,
tabsContentContainer = false,
- dropdown = tabs && queryElement('.dropdown-toggle',tabs),
- activeTab, activeContent, nextContent, containerHeight, equalContents, nextHeight,
-
- // trigger
- triggerEnd = function(){
- tabsContentContainer[style][height] = '';
- removeClass(tabsContentContainer,collapsing);
- tabs[isAnimating] = false;
- },
- triggerShow = function() {
- if (tabsContentContainer) { // height animation
- if ( equalContents ) {
- triggerEnd();
- } else {
- setTimeout(function(){ // enables height animation
- tabsContentContainer[style][height] = nextHeight + 'px'; // height animation
- tabsContentContainer[offsetWidth];
- emulateTransitionEnd(tabsContentContainer, triggerEnd);
- },50);
- }
+ activeTab,
+ activeContent,
+ nextContent,
+ containerHeight,
+ equalContents,
+ nextHeight,
+ animateHeight;
+ function triggerEnd() {
+ tabsContentContainer.style.height = '';
+ removeClass(tabsContentContainer,'collapsing');
+ tabs.isAnimating = false;
+ }
+ function triggerShow() {
+ if (tabsContentContainer) {
+ if ( equalContents ) {
+ triggerEnd();
} else {
- tabs[isAnimating] = false;
- }
- bootstrapCustomEvent.call(next, shownEvent, component, activeTab);
- },
- triggerHide = function() {
- if (tabsContentContainer) {
- activeContent[style][float] = left;
- nextContent[style][float] = left;
- containerHeight = activeContent[scrollHeight];
- }
-
- addClass(nextContent,active);
- bootstrapCustomEvent.call(next, showEvent, component, activeTab);
-
- removeClass(activeContent,active);
- bootstrapCustomEvent.call(activeTab, hiddenEvent, component, next);
-
- if (tabsContentContainer) {
- nextHeight = nextContent[scrollHeight];
- equalContents = nextHeight === containerHeight;
- addClass(tabsContentContainer,collapsing);
- tabsContentContainer[style][height] = containerHeight + 'px'; // height animation
- tabsContentContainer[offsetHeight];
- activeContent[style][float] = '';
- nextContent[style][float] = '';
+ setTimeout(function () {
+ tabsContentContainer.style.height = nextHeight + "px";
+ tabsContentContainer.offsetWidth;
+ emulateTransitionEnd(tabsContentContainer, triggerEnd);
+ },50);
}
-
- if ( hasClass(nextContent, 'fade') ) {
- setTimeout(function(){
- addClass(nextContent,showClass);
- emulateTransitionEnd(nextContent,triggerShow);
- },20);
- } else { triggerShow(); }
- };
-
- if (!tabs) return; // invalidate
-
- // set default animation state
- tabs[isAnimating] = false;
-
- // private methods
- var getActiveTab = function() {
- var activeTabs = getElementsByClassName(tabs,active), activeTab;
- if ( activeTabs[length] === 1 && !hasClass(activeTabs[0][parentNode],'dropdown') ) {
- activeTab = activeTabs[0];
- } else if ( activeTabs[length] > 1 ) {
- activeTab = activeTabs[activeTabs[length]-1];
- }
- return activeTab;
- },
- getActiveContent = function() {
- return queryElement(getActiveTab()[getAttribute]('href'));
- },
- // handler
- clickHandler = function(e) {
- e[preventDefault]();
- next = e[currentTarget];
- !tabs[isAnimating] && !hasClass(next,active) && self.show();
- };
-
- // public method
- this.show = function() { // the tab we clicked is now the next tab
+ } else {
+ tabs.isAnimating = false;
+ }
+ shownCustomEvent = bootstrapCustomEvent('shown', 'tab', activeTab);
+ dispatchCustomEvent.call(next, shownCustomEvent);
+ }
+ function triggerHide() {
+ if (tabsContentContainer) {
+ activeContent.style.float = 'left';
+ nextContent.style.float = 'left';
+ containerHeight = activeContent.scrollHeight;
+ }
+ showCustomEvent = bootstrapCustomEvent('show', 'tab', activeTab);
+ hiddenCustomEvent = bootstrapCustomEvent('hidden', 'tab', next);
+ dispatchCustomEvent.call(next, showCustomEvent);
+ if ( showCustomEvent.defaultPrevented ) { return; }
+ addClass(nextContent,'active');
+ removeClass(activeContent,'active');
+ if (tabsContentContainer) {
+ nextHeight = nextContent.scrollHeight;
+ equalContents = nextHeight === containerHeight;
+ addClass(tabsContentContainer,'collapsing');
+ tabsContentContainer.style.height = containerHeight + "px";
+ tabsContentContainer.offsetHeight;
+ activeContent.style.float = '';
+ nextContent.style.float = '';
+ }
+ if ( hasClass(nextContent, 'fade') ) {
+ setTimeout(function () {
+ addClass(nextContent,'show');
+ emulateTransitionEnd(nextContent,triggerShow);
+ },20);
+ } else { triggerShow(); }
+ dispatchCustomEvent.call(activeTab, hiddenCustomEvent);
+ }
+ function getActiveTab() {
+ var activeTabs = tabs.getElementsByClassName('active'), activeTab;
+ if ( activeTabs.length === 1 && !hasClass(activeTabs[0].parentNode,'dropdown') ) {
+ activeTab = activeTabs[0];
+ } else if ( activeTabs.length > 1 ) {
+ activeTab = activeTabs[activeTabs.length-1];
+ }
+ return activeTab;
+ }
+ function getActiveContent() { return queryElement(getActiveTab().getAttribute('href')) }
+ function clickHandler(e) {
+ e.preventDefault();
+ next = e.currentTarget;
+ !tabs.isAnimating && self.show();
+ }
+ self.show = function () {
next = next || element;
- nextContent = queryElement(next[getAttribute]('href')); //this is the actual object, the next tab content to activate
- activeTab = getActiveTab();
- activeContent = getActiveContent();
-
- tabs[isAnimating] = true;
- removeClass(activeTab,active);
- activeTab[setAttribute](ariaSelected,'false');
- addClass(next,active);
- next[setAttribute](ariaSelected,'true');
-
- if ( dropdown ) {
- if ( !hasClass(element[parentNode],'dropdown-menu') ) {
- if (hasClass(dropdown,active)) removeClass(dropdown,active);
- } else {
- if (!hasClass(dropdown,active)) addClass(dropdown,active);
+ if (!hasClass(next,'active')) {
+ nextContent = queryElement(next.getAttribute('href'));
+ activeTab = getActiveTab();
+ activeContent = getActiveContent();
+ hideCustomEvent = bootstrapCustomEvent( 'hide', 'tab', next);
+ dispatchCustomEvent.call(activeTab, hideCustomEvent);
+ if (hideCustomEvent.defaultPrevented) { return; }
+ tabs.isAnimating = true;
+ removeClass(activeTab,'active');
+ activeTab.setAttribute('aria-selected','false');
+ addClass(next,'active');
+ next.setAttribute('aria-selected','true');
+ if ( dropdown ) {
+ if ( !hasClass(element.parentNode,'dropdown-menu') ) {
+ if (hasClass(dropdown,'active')) { removeClass(dropdown,'active'); }
+ } else {
+ if (!hasClass(dropdown,'active')) { addClass(dropdown,'active'); }
+ }
}
+ if (hasClass(activeContent, 'fade')) {
+ removeClass(activeContent,'show');
+ emulateTransitionEnd(activeContent, triggerHide);
+ } else { triggerHide(); }
}
-
- bootstrapCustomEvent.call(activeTab, hideEvent, component, next);
-
- if (hasClass(activeContent, 'fade')) {
- removeClass(activeContent,showClass);
- emulateTransitionEnd(activeContent, triggerHide);
- } else { triggerHide(); }
};
-
- // init
- if ( !(stringTab in element) ) { // prevent adding event handlers twice
- on(element, clickEvent, clickHandler);
- }
- if (self[height]) { tabsContentContainer = getActiveContent()[parentNode]; }
- element[stringTab] = self;
- };
-
- // TAB DATA API
- // ============
- supports[push]( [ stringTab, Tab, '['+dataToggle+'="tab"]' ] );
-
-
- /* Native Javascript for Bootstrap 4 | Toast
- ---------------------------------------------*/
-
- // TOAST DEFINITION
- // ==================
- var Toast = function( element,options ) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
+ self.dispose = function () {
+ off(element, 'click', clickHandler);
+ delete element.Tab;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.Tab && element.Tab.dispose();
+ heightData = element.getAttribute('data-height');
+ tabs = element.closest('.nav');
+ dropdown = tabs && queryElement('.dropdown-toggle',tabs);
+ animateHeight = !supportTransition || (options.height === false || heightData === 'false') ? false : true;
+ tabs.isAnimating = false;
+ if ( !element.Tab ) {
+ on(element, 'click', clickHandler);
+ }
+ if (animateHeight) { tabsContentContainer = getActiveContent().parentNode; }
+ element.Tab = self;
+ },'BSN.Tab');
+ }
+
+ function Toast(element,options) {
options = options || {};
-
- // DATA API
- var animationData = element[getAttribute](dataAnimation),
- autohideData = element[getAttribute](dataAutohide),
- delayData = element[getAttribute](dataDelay),
-
- // strings
- component = 'toast',
- autohide = 'autohide',
- animation = 'animation',
- showing = 'showing',
- hide = 'hide',
- fade = 'fade';
-
- // set instance options
- this[animation] = options[animation] === false || animationData === 'false' ? 0 : 1; // true by default
- this[autohide] = options[autohide] === false || autohideData === 'false' ? 0 : 1; // true by default
- this[delay] = parseInt(options[delay] || delayData) || 500; // 500ms default
-
- // bind,toast and timer
- var self = this, timer = 0,
- // get the toast element
- toast = getClosest(element,'.toast');
-
- // private methods
- // animation complete
- var showComplete = function() {
- removeClass( toast, showing );
- addClass( toast, showClass );
- bootstrapCustomEvent.call(toast, shownEvent, component);
- if (self[autohide]) { self.hide(); }
- },
- hideComplete = function() {
- addClass( toast, hide );
- bootstrapCustomEvent.call(toast, hiddenEvent, component);
- },
- close = function() {
- removeClass( toast,showClass );
- self[animation] ? emulateTransitionEnd(toast, hideComplete) : hideComplete();
- },
- disposeComplete = function(){
- clearTimeout(timer); timer = null;
- addClass( toast, hide );
- off(element, clickEvent, self.hide);
- element[stringToast] = null;
- element = null;
- toast = null;
- };
-
- // public methods
- this.show = function() {
- if (toast) {
- bootstrapCustomEvent.call(toast, showEvent, component);
- self[animation] && addClass( toast,fade );
- removeClass( toast,hide );
- addClass( toast,showing );
-
- self[animation] ? emulateTransitionEnd(toast, showComplete) : showComplete();
+ var self = this,
+ toast, timer = 0,
+ animationData,
+ autohideData,
+ delayData,
+ showCustomEvent,
+ hideCustomEvent,
+ shownCustomEvent,
+ hiddenCustomEvent,
+ ops = {};
+ function showComplete() {
+ removeClass( toast, 'showing' );
+ addClass( toast, 'show' );
+ dispatchCustomEvent.call(toast,shownCustomEvent);
+ if (ops.autohide) { self.hide(); }
+ }
+ function hideComplete() {
+ addClass( toast, 'hide' );
+ dispatchCustomEvent.call(toast,hiddenCustomEvent);
+ }
+ function close () {
+ removeClass( toast,'show' );
+ ops.animation ? emulateTransitionEnd(toast, hideComplete) : hideComplete();
+ }
+ function disposeComplete() {
+ clearTimeout(timer);
+ off(element, 'click', self.hide);
+ delete element.Toast;
+ }
+ self.show = function () {
+ if (toast && !hasClass(toast,'show')) {
+ dispatchCustomEvent.call(toast,showCustomEvent);
+ if (showCustomEvent.defaultPrevented) { return; }
+ ops.animation && addClass( toast,'fade' );
+ removeClass( toast,'hide' );
+ toast.offsetWidth;
+ addClass( toast,'showing' );
+ ops.animation ? emulateTransitionEnd(toast, showComplete) : showComplete();
}
};
- this.hide = function(noTimer) {
- if (toast && hasClass(toast,showClass)) {
- bootstrapCustomEvent.call(toast, hideEvent, component);
-
- if (noTimer) {
- close();
- } else {
- timer = setTimeout( close, self[delay]);
- }
+ self.hide = function (noTimer) {
+ if (toast && hasClass(toast,'show')) {
+ dispatchCustomEvent.call(toast,hideCustomEvent);
+ if(hideCustomEvent.defaultPrevented) { return; }
+ noTimer ? close() : (timer = setTimeout( close, ops.delay));
}
};
- this.dispose = function() {
- if ( toast && hasClass(toast,showClass) ) {
- removeClass( toast,showClass );
- self[animation] ? emulateTransitionEnd(toast, disposeComplete) : disposeComplete();
- }
+ self.dispose = function () {
+ ops.animation ? emulateTransitionEnd(toast, disposeComplete) : disposeComplete();
};
-
- // init
- if ( !(stringToast in element) ) { // prevent adding event handlers twice
- on(element, clickEvent, self.hide);
- }
- element[stringToast] = self;
- };
-
- // TOAST DATA API
- // =================
- supports[push]( [ stringToast, Toast, '['+dataDismiss+'="toast"]' ] );
-
-
- /* Native Javascript for Bootstrap 4 | Tooltip
- ---------------------------------------------*/
-
- // TOOLTIP DEFINITION
- // ==================
- var Tooltip = function( element,options ) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.Toast && element.Toast.dispose();
+ toast = element.closest('.toast');
+ animationData = element.getAttribute('data-animation');
+ autohideData = element.getAttribute('data-autohide');
+ delayData = element.getAttribute('data-delay');
+ showCustomEvent = bootstrapCustomEvent('show', 'toast');
+ hideCustomEvent = bootstrapCustomEvent('hide', 'toast');
+ shownCustomEvent = bootstrapCustomEvent('shown', 'toast');
+ hiddenCustomEvent = bootstrapCustomEvent('hidden', 'toast');
+ ops.animation = options.animation === false || animationData === 'false' ? 0 : 1;
+ ops.autohide = options.autohide === false || autohideData === 'false' ? 0 : 1;
+ ops.delay = parseInt(options.delay || delayData) || 500;
+ if ( !element.Toast ) {
+ on(element, 'click', self.hide);
+ }
+ element.Toast = self;
+ },'BSN.Toast');
+ }
+
+ function Tooltip(element,options) {
options = options || {};
-
- // DATA API
- var animationData = element[getAttribute](dataAnimation),
- placementData = element[getAttribute](dataPlacement),
- delayData = element[getAttribute](dataDelay),
- containerData = element[getAttribute](dataContainer),
-
- // strings
- component = 'tooltip',
- classString = 'class',
- title = 'title',
- fade = 'fade',
- div = 'div',
-
- // check container
- containerElement = queryElement(options[container]),
- containerDataElement = queryElement(containerData),
-
- // maybe the element is inside a modal
- modal = getClosest(element,'.modal'),
-
- // maybe the element is inside a fixed navbar
- navbarFixedTop = getClosest(element,'.'+fixedTop),
- navbarFixedBottom = getClosest(element,'.'+fixedBottom);
-
- // set instance options
- this[animation] = options[animation] && options[animation] !== fade ? options[animation] : animationData || fade;
- this[placement] = options[placement] ? options[placement] : placementData || top;
- this[delay] = parseInt(options[delay] || delayData) || 200;
- this[container] = containerElement ? containerElement
- : containerDataElement ? containerDataElement
- : navbarFixedTop ? navbarFixedTop
- : navbarFixedBottom ? navbarFixedBottom
- : modal ? modal : DOC[body];
-
- // bind, event targets, title and constants
- var self = this, timer = 0, placementSetting = this[placement], tooltip = null,
- titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle);
-
- if ( !titleString || titleString == "" ) return; // invalidate
-
- // private methods
- var removeToolTip = function() {
- self[container].removeChild(tooltip);
- tooltip = null; timer = null;
- },
- createToolTip = function() {
- titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle); // read the title again
-
- if ( titleString && titleString !== "" ) { // invalidate, maybe markup changed
- tooltip = DOC[createElement](div);
- tooltip[setAttribute]('role',component);
- tooltip[style][left] = '0';
- tooltip[style][top] = '0';
-
- // tooltip arrow
- var tooltipArrow = DOC[createElement](div);
- tooltipArrow[setAttribute](classString,'arrow');
- tooltip[appendChild](tooltipArrow);
-
- var tooltipInner = DOC[createElement](div);
- tooltipInner[setAttribute](classString,component+'-inner');
- tooltip[appendChild](tooltipInner);
- tooltipInner[innerHTML] = titleString;
-
- self[container][appendChild](tooltip);
- tooltip[setAttribute](classString, component + ' bs-' + component+'-'+placementSetting + ' ' + self[animation]);
+ var self = this,
+ tooltip = null, timer = 0, titleString,
+ animationData,
+ placementData,
+ delayData,
+ containerData,
+ showCustomEvent,
+ shownCustomEvent,
+ hideCustomEvent,
+ hiddenCustomEvent,
+ containerElement,
+ containerDataElement,
+ modal,
+ navbarFixedTop,
+ navbarFixedBottom,
+ placementClass,
+ ops = {};
+ function getTitle() {
+ return element.getAttribute('title')
+ || element.getAttribute('data-title')
+ || element.getAttribute('data-original-title')
+ }
+ function removeToolTip() {
+ ops.container.removeChild(tooltip);
+ tooltip = null; timer = null;
+ }
+ function createToolTip() {
+ titleString = getTitle();
+ if ( titleString ) {
+ tooltip = document.createElement('div');
+ if (ops.template) {
+ var tooltipMarkup = document.createElement('div');
+ tooltipMarkup.innerHTML = ops.template.trim();
+ tooltip.className = tooltipMarkup.firstChild.className;
+ tooltip.innerHTML = tooltipMarkup.firstChild.innerHTML;
+ queryElement('.tooltip-inner',tooltip).innerHTML = titleString.trim();
+ } else {
+ var tooltipArrow = document.createElement('div');
+ addClass(tooltipArrow,'arrow');
+ tooltip.appendChild(tooltipArrow);
+ var tooltipInner = document.createElement('div');
+ addClass(tooltipInner,'tooltip-inner');
+ tooltip.appendChild(tooltipInner);
+ tooltipInner.innerHTML = titleString;
}
- },
- updateTooltip = function () {
- styleTip(element, tooltip, placementSetting, self[container]);
- },
- showTooltip = function () {
- !hasClass(tooltip,showClass) && ( addClass(tooltip,showClass) );
- },
- // triggers
- showTrigger = function() {
- on( globalObject, resizeEvent, self.hide, passiveHandler );
- bootstrapCustomEvent.call(element, shownEvent, component);
- },
- hideTrigger = function() {
- off( globalObject, resizeEvent, self.hide, passiveHandler );
- removeToolTip();
- bootstrapCustomEvent.call(element, hiddenEvent, component);
- };
-
- // public methods
- this.show = function() {
+ tooltip.style.left = '0';
+ tooltip.style.top = '0';
+ tooltip.setAttribute('role','tooltip');
+ !hasClass(tooltip, 'tooltip') && addClass(tooltip, 'tooltip');
+ !hasClass(tooltip, ops.animation) && addClass(tooltip, ops.animation);
+ !hasClass(tooltip, placementClass) && addClass(tooltip, placementClass);
+ ops.container.appendChild(tooltip);
+ }
+ }
+ function updateTooltip() {
+ styleTip(element, tooltip, ops.placement, ops.container);
+ }
+ function showTooltip() {
+ !hasClass(tooltip,'show') && ( addClass(tooltip,'show') );
+ }
+ function touchHandler(e){
+ if ( tooltip && tooltip.contains(e.target) || e.target === element || element.contains(e.target)) ; else {
+ self.hide();
+ }
+ }
+ function showAction() {
+ on( document, touchEvents.start, touchHandler, passiveHandler );
+ on( window, 'resize', self.hide, passiveHandler );
+ dispatchCustomEvent.call(element, shownCustomEvent);
+ }
+ function hideAction() {
+ off( document, touchEvents.start, touchHandler, passiveHandler );
+ off( window, 'resize', self.hide, passiveHandler );
+ removeToolTip();
+ dispatchCustomEvent.call(element, hiddenCustomEvent);
+ }
+ function toggleEvents(action) {
+ action(element, mouseClickEvents.down, self.show);
+ action(element, mouseHoverEvents[0], self.show);
+ action(element, mouseHoverEvents[1], self.hide);
+ }
+ self.show = function () {
clearTimeout(timer);
- timer = setTimeout( function() {
+ timer = setTimeout( function () {
if (tooltip === null) {
- placementSetting = self[placement]; // we reset placement in all cases
- // if(createToolTip() == false) return;
+ dispatchCustomEvent.call(element, showCustomEvent);
+ if (showCustomEvent.defaultPrevented) { return; }
if(createToolTip() !== false) {
updateTooltip();
showTooltip();
- bootstrapCustomEvent.call(element, showEvent, component);
- !!self[animation] ? emulateTransitionEnd(tooltip, showTrigger) : showTrigger();
+ !!ops.animation ? emulateTransitionEnd(tooltip, showAction) : showAction();
}
}
}, 20 );
};
- this.hide = function() {
+ self.hide = function () {
clearTimeout(timer);
- timer = setTimeout( function() {
- if (tooltip && hasClass(tooltip,showClass)) {
- bootstrapCustomEvent.call(element, hideEvent, component);
- removeClass(tooltip,showClass);
- !!self[animation] ? emulateTransitionEnd(tooltip, hideTrigger) : hideTrigger();
+ timer = setTimeout( function () {
+ if (tooltip && hasClass(tooltip,'show')) {
+ dispatchCustomEvent.call(element, hideCustomEvent);
+ if (hideCustomEvent.defaultPrevented) { return; }
+ removeClass(tooltip,'show');
+ !!ops.animation ? emulateTransitionEnd(tooltip, hideAction) : hideAction();
}
- }, self[delay]);
+ }, ops.delay);
};
- this.toggle = function() {
- if (!tooltip) { self.show(); }
+ self.toggle = function () {
+ if (!tooltip) { self.show(); }
else { self.hide(); }
};
-
- // init
- if ( !(stringTooltip in element) ) { // prevent adding event handlers twice
- element[setAttribute](dataOriginalTitle,titleString);
- element.removeAttribute(title);
- on(element, mouseHover[0], self.show);
- on(element, mouseHover[1], self.hide);
- }
- element[stringTooltip] = self;
- };
-
- // TOOLTIP DATA API
- // =================
- supports[push]( [ stringTooltip, Tooltip, '['+dataToggle+'="tooltip"]' ] );
-
-
-
- /* Native Javascript for Bootstrap | Initialize Data API
- --------------------------------------------------------*/
- var initializeDataAPI = function( constructor, collection ){
- for (var i=0, l=collection[length]; i<l; i++) {
- new constructor(collection[i]);
- }
- },
- initCallback = BSN.initCallback = function(lookUp){
- lookUp = lookUp || DOC;
- for (var i=0, l=supports[length]; i<l; i++) {
- initializeDataAPI( supports[i][1], lookUp[querySelectorAll] (supports[i][2]) );
+ self.dispose = function () {
+ toggleEvents(off);
+ self.hide();
+ element.setAttribute('title', element.getAttribute('data-original-title'));
+ element.removeAttribute('data-original-title');
+ delete element.Tooltip;
+ };
+ tryWrapper(function (){
+ element = queryElement(element);
+ element.Tooltip && element.Tooltip.dispose();
+ animationData = element.getAttribute('data-animation');
+ placementData = element.getAttribute('data-placement');
+ delayData = element.getAttribute('data-delay');
+ containerData = element.getAttribute('data-container');
+ showCustomEvent = bootstrapCustomEvent('show', 'tooltip');
+ shownCustomEvent = bootstrapCustomEvent('shown', 'tooltip');
+ hideCustomEvent = bootstrapCustomEvent('hide', 'tooltip');
+ hiddenCustomEvent = bootstrapCustomEvent('hidden', 'tooltip');
+ containerElement = queryElement(options.container);
+ containerDataElement = queryElement(containerData);
+ modal = element.closest('.modal');
+ navbarFixedTop = element.closest('.fixed-top');
+ navbarFixedBottom = element.closest('.fixed-bottom');
+ ops.animation = options.animation && options.animation !== 'fade' ? options.animation : animationData || 'fade';
+ ops.placement = options.placement ? options.placement : placementData || 'top';
+ ops.template = options.template ? options.template : null;
+ ops.delay = parseInt(options.delay || delayData) || 200;
+ ops.container = containerElement ? containerElement
+ : containerDataElement ? containerDataElement
+ : navbarFixedTop ? navbarFixedTop
+ : navbarFixedBottom ? navbarFixedBottom
+ : modal ? modal : document.body;
+ placementClass = "bs-tooltip-" + (ops.placement);
+ titleString = getTitle();
+ if ( !titleString ) { return; }
+ if (!element.Tooltip) {
+ element.setAttribute('data-original-title',titleString);
+ element.removeAttribute('title');
+ toggleEvents(on);
}
+ element.Tooltip = self;
+ },'BSN.Tooltip');
+ }
+
+ var componentsInit = {};
+
+ var initCallback = function (lookUp){
+ lookUp = lookUp || document;
+ var initializeDataAPI = function( Constructor, collection ){
+ Array.from(collection).map(function (x){ return new Constructor(x); });
+ };
+ for (var component in componentsInit) {
+ initializeDataAPI( componentsInit[component][0], lookUp.querySelectorAll (componentsInit[component][1]) );
+ }
+ };
+ var removeDataAPI = function (lookUp) {
+ lookUp = lookUp || document;
+ var removeElementDataAPI = function( ConstructorName, collection ){
+ Array.from(collection).map(function (x){ return x[ConstructorName].dispose(); });
};
-
- // bulk initialize all components
- DOC[body] ? initCallback() : on( DOC, 'DOMContentLoaded', function(){ initCallback(); } );
-
- return {
+ for (var component in componentsInit) {
+ removeElementDataAPI( component, lookUp.querySelectorAll (componentsInit[component][1]) );
+ }
+ };
+
+ componentsInit.Alert = [ Alert, '[data-dismiss="alert"]'];
+ componentsInit.Button = [ Button, '[data-toggle="buttons"]' ];
+ componentsInit.Carousel = [ Carousel, '[data-ride="carousel"]' ];
+ componentsInit.Collapse = [ Collapse, '[data-toggle="collapse"]' ];
+ componentsInit.Dropdown = [ Dropdown, '[data-toggle="dropdown"]'];
+ componentsInit.Modal = [ Modal, '[data-toggle="modal"]' ];
+ componentsInit.Popover = [ Popover, '[data-toggle="popover"],[data-tip="popover"]' ];
+ componentsInit.ScrollSpy = [ ScrollSpy, '[data-spy="scroll"]' ];
+ componentsInit.Tab = [ Tab, '[data-toggle="tab"]' ];
+ componentsInit.Toast = [ Toast, '[data-dismiss="toast"]' ];
+ componentsInit.Tooltip = [ Tooltip, '[data-toggle="tooltip"],[data-tip="tooltip"]' ];
+ document.body ? initCallback() : one( document, 'DOMContentLoaded', initCallback );
+
+ var version = "3.0.1";
+
+ var index = {
Alert: Alert,
Button: Button,
Carousel: Carousel,
@@ -2004,6 +1694,13 @@
ScrollSpy: ScrollSpy,
Tab: Tab,
Toast: Toast,
- Tooltip: Tooltip
+ Tooltip: Tooltip,
+ initCallback: initCallback,
+ removeDataAPI: removeDataAPI,
+ componentsInit: componentsInit,
+ Version: version
};
-}));
+
+ return index;
+
+})));
diff --git a/src/static/scripts/bootstrap.css b/src/static/scripts/bootstrap.css
index c46012c5..e461d3fb 100644
--- a/src/static/scripts/bootstrap.css
+++ b/src/static/scripts/bootstrap.css
@@ -1,7 +1,7 @@
/*!
- * Bootstrap v4.3.1 (https://getbootstrap.com/)
- * Copyright 2011-2019 The Bootstrap Authors
- * Copyright 2011-2019 Twitter, Inc.
+ * Bootstrap v4.5.0 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
:root {
@@ -63,7 +63,7 @@ body {
background-color: #fff;
}
-[tabindex="-1"]:focus {
+[tabindex="-1"]:focus:not(:focus-visible) {
outline: 0 !important;
}
@@ -163,20 +163,16 @@ a:hover {
text-decoration: underline;
}
-a:not([href]):not([tabindex]) {
+a:not([href]) {
color: inherit;
text-decoration: none;
}
-a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
+a:not([href]):hover {
color: inherit;
text-decoration: none;
}
-a:not([href]):not([tabindex]):focus {
- outline: 0;
-}
-
pre,
code,
kbd,
@@ -189,6 +185,7 @@ pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
+ -ms-overflow-style: scrollbar;
}
figure {
@@ -256,6 +253,10 @@ select {
text-transform: none;
}
+[role="button"] {
+ cursor: pointer;
+}
+
select {
word-wrap: normal;
}
@@ -288,13 +289,6 @@ input[type="checkbox"] {
padding: 0;
}
-input[type="date"],
-input[type="time"],
-input[type="datetime-local"],
-input[type="month"] {
- -webkit-appearance: listbox;
-}
-
textarea {
overflow: auto;
resize: vertical;
@@ -507,7 +501,7 @@ mark,
code {
font-size: 87.5%;
color: #e83e8c;
- word-break: break-word;
+ word-wrap: break-word;
}
a > code {
@@ -577,7 +571,7 @@ pre code {
}
}
-.container-fluid {
+.container-fluid, .container-sm, .container-md, .container-lg, .container-xl {
width: 100%;
padding-right: 15px;
padding-left: 15px;
@@ -585,6 +579,30 @@ pre code {
margin-left: auto;
}
+@media (min-width: 576px) {
+ .container, .container-sm {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container, .container-sm, .container-md {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container, .container-sm, .container-md, .container-lg {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container, .container-sm, .container-md, .container-lg, .container-xl {
+ max-width: 1140px;
+ }
+}
+
.row {
display: -ms-flexbox;
display: flex;
@@ -622,9 +640,46 @@ pre code {
flex-basis: 0;
-ms-flex-positive: 1;
flex-grow: 1;
+ min-width: 0;
max-width: 100%;
}
+.row-cols-1 > * {
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
+ max-width: 100%;
+}
+
+.row-cols-2 > * {
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%;
+}
+
+.row-cols-3 > * {
+ -ms-flex: 0 0 33.333333%;
+ flex: 0 0 33.333333%;
+ max-width: 33.333333%;
+}
+
+.row-cols-4 > * {
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%;
+}
+
+.row-cols-5 > * {
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%;
+ max-width: 20%;
+}
+
+.row-cols-6 > * {
+ -ms-flex: 0 0 16.666667%;
+ flex: 0 0 16.666667%;
+ max-width: 16.666667%;
+}
+
.col-auto {
-ms-flex: 0 0 auto;
flex: 0 0 auto;
@@ -829,8 +884,39 @@ pre code {
flex-basis: 0;
-ms-flex-positive: 1;
flex-grow: 1;
+ min-width: 0;
+ max-width: 100%;
+ }
+ .row-cols-sm-1 > * {
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
max-width: 100%;
}
+ .row-cols-sm-2 > * {
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+ .row-cols-sm-3 > * {
+ -ms-flex: 0 0 33.333333%;
+ flex: 0 0 33.333333%;
+ max-width: 33.333333%;
+ }
+ .row-cols-sm-4 > * {
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+ .row-cols-sm-5 > * {
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+ .row-cols-sm-6 > * {
+ -ms-flex: 0 0 16.666667%;
+ flex: 0 0 16.666667%;
+ max-width: 16.666667%;
+ }
.col-sm-auto {
-ms-flex: 0 0 auto;
flex: 0 0 auto;
@@ -1001,8 +1087,39 @@ pre code {
flex-basis: 0;
-ms-flex-positive: 1;
flex-grow: 1;
+ min-width: 0;
+ max-width: 100%;
+ }
+ .row-cols-md-1 > * {
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
max-width: 100%;
}
+ .row-cols-md-2 > * {
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+ .row-cols-md-3 > * {
+ -ms-flex: 0 0 33.333333%;
+ flex: 0 0 33.333333%;
+ max-width: 33.333333%;
+ }
+ .row-cols-md-4 > * {
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+ .row-cols-md-5 > * {
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+ .row-cols-md-6 > * {
+ -ms-flex: 0 0 16.666667%;
+ flex: 0 0 16.666667%;
+ max-width: 16.666667%;
+ }
.col-md-auto {
-ms-flex: 0 0 auto;
flex: 0 0 auto;
@@ -1173,8 +1290,39 @@ pre code {
flex-basis: 0;
-ms-flex-positive: 1;
flex-grow: 1;
+ min-width: 0;
+ max-width: 100%;
+ }
+ .row-cols-lg-1 > * {
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
max-width: 100%;
}
+ .row-cols-lg-2 > * {
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+ .row-cols-lg-3 > * {
+ -ms-flex: 0 0 33.333333%;
+ flex: 0 0 33.333333%;
+ max-width: 33.333333%;
+ }
+ .row-cols-lg-4 > * {
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+ .row-cols-lg-5 > * {
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+ .row-cols-lg-6 > * {
+ -ms-flex: 0 0 16.666667%;
+ flex: 0 0 16.666667%;
+ max-width: 16.666667%;
+ }
.col-lg-auto {
-ms-flex: 0 0 auto;
flex: 0 0 auto;
@@ -1345,8 +1493,39 @@ pre code {
flex-basis: 0;
-ms-flex-positive: 1;
flex-grow: 1;
+ min-width: 0;
+ max-width: 100%;
+ }
+ .row-cols-xl-1 > * {
+ -ms-flex: 0 0 100%;
+ flex: 0 0 100%;
max-width: 100%;
}
+ .row-cols-xl-2 > * {
+ -ms-flex: 0 0 50%;
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+ .row-cols-xl-3 > * {
+ -ms-flex: 0 0 33.333333%;
+ flex: 0 0 33.333333%;
+ max-width: 33.333333%;
+ }
+ .row-cols-xl-4 > * {
+ -ms-flex: 0 0 25%;
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+ .row-cols-xl-5 > * {
+ -ms-flex: 0 0 20%;
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+ .row-cols-xl-6 > * {
+ -ms-flex: 0 0 16.666667%;
+ flex: 0 0 16.666667%;
+ max-width: 16.666667%;
+ }
.col-xl-auto {
-ms-flex: 0 0 auto;
flex: 0 0 auto;
@@ -1881,6 +2060,11 @@ pre code {
border: 0;
}
+.form-control:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #495057;
+}
+
.form-control:focus {
color: #495057;
background-color: #fff;
@@ -1919,6 +2103,15 @@ pre code {
opacity: 1;
}
+input[type="date"].form-control,
+input[type="time"].form-control,
+input[type="datetime-local"].form-control,
+input[type="month"].form-control {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+}
+
select.form-control:focus::-ms-value {
color: #495057;
background-color: #fff;
@@ -1955,9 +2148,9 @@ select.form-control:focus::-ms-value {
.form-control-plaintext {
display: block;
width: 100%;
- padding-top: 0.375rem;
- padding-bottom: 0.375rem;
+ padding: 0.375rem 0;
margin-bottom: 0;
+ font-size: 1rem;
line-height: 1.5;
color: #212529;
background-color: transparent;
@@ -2030,6 +2223,7 @@ textarea.form-control {
margin-left: -1.25rem;
}
+.form-check-input[disabled] ~ .form-check-label,
.form-check-input:disabled ~ .form-check-label {
color: #6c757d;
}
@@ -2077,12 +2271,19 @@ textarea.form-control {
border-radius: 0.25rem;
}
+.was-validated :valid ~ .valid-feedback,
+.was-validated :valid ~ .valid-tooltip,
+.is-valid ~ .valid-feedback,
+.is-valid ~ .valid-tooltip {
+ display: block;
+}
+
.was-validated .form-control:valid, .form-control.is-valid {
border-color: #28a745;
padding-right: calc(1.5em + 0.75rem);
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");
background-repeat: no-repeat;
- background-position: center right calc(0.375em + 0.1875rem);
+ background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
}
@@ -2091,12 +2292,6 @@ textarea.form-control {
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
}
-.was-validated .form-control:valid ~ .valid-feedback,
-.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,
-.form-control.is-valid ~ .valid-tooltip {
- display: block;
-}
-
.was-validated textarea.form-control:valid, textarea.form-control.is-valid {
padding-right: calc(1.5em + 0.75rem);
background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);
@@ -2104,8 +2299,8 @@ textarea.form-control {
.was-validated .custom-select:valid, .custom-select.is-valid {
border-color: #28a745;
- padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem);
- background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+ padding-right: calc(0.75em + 2.3125rem);
+ background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
}
.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus {
@@ -2113,18 +2308,6 @@ textarea.form-control {
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
}
-.was-validated .custom-select:valid ~ .valid-feedback,
-.was-validated .custom-select:valid ~ .valid-tooltip, .custom-select.is-valid ~ .valid-feedback,
-.custom-select.is-valid ~ .valid-tooltip {
- display: block;
-}
-
-.was-validated .form-control-file:valid ~ .valid-feedback,
-.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback,
-.form-control-file.is-valid ~ .valid-tooltip {
- display: block;
-}
-
.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {
color: #28a745;
}
@@ -2143,12 +2326,6 @@ textarea.form-control {
border-color: #28a745;
}
-.was-validated .custom-control-input:valid ~ .valid-feedback,
-.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback,
-.custom-control-input.is-valid ~ .valid-tooltip {
- display: block;
-}
-
.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {
border-color: #34ce57;
background-color: #34ce57;
@@ -2166,12 +2343,6 @@ textarea.form-control {
border-color: #28a745;
}
-.was-validated .custom-file-input:valid ~ .valid-feedback,
-.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback,
-.custom-file-input.is-valid ~ .valid-tooltip {
- display: block;
-}
-
.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {
border-color: #28a745;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
@@ -2200,12 +2371,19 @@ textarea.form-control {
border-radius: 0.25rem;
}
+.was-validated :invalid ~ .invalid-feedback,
+.was-validated :invalid ~ .invalid-tooltip,
+.is-invalid ~ .invalid-feedback,
+.is-invalid ~ .invalid-tooltip {
+ display: block;
+}
+
.was-validated .form-control:invalid, .form-control.is-invalid {
border-color: #dc3545;
padding-right: calc(1.5em + 0.75rem);
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");
background-repeat: no-repeat;
- background-position: center right calc(0.375em + 0.1875rem);
+ background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
}
@@ -2214,12 +2392,6 @@ textarea.form-control {
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
-.was-validated .form-control:invalid ~ .invalid-feedback,
-.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,
-.form-control.is-invalid ~ .invalid-tooltip {
- display: block;
-}
-
.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
padding-right: calc(1.5em + 0.75rem);
background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);
@@ -2227,8 +2399,8 @@ textarea.form-control {
.was-validated .custom-select:invalid, .custom-select.is-invalid {
border-color: #dc3545;
- padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem);
- background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+ padding-right: calc(0.75em + 2.3125rem);
+ background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
}
.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus {
@@ -2236,18 +2408,6 @@ textarea.form-control {
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
-.was-validated .custom-select:invalid ~ .invalid-feedback,
-.was-validated .custom-select:invalid ~ .invalid-tooltip, .custom-select.is-invalid ~ .invalid-feedback,
-.custom-select.is-invalid ~ .invalid-tooltip {
- display: block;
-}
-
-.was-validated .form-control-file:invalid ~ .invalid-feedback,
-.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback,
-.form-control-file.is-invalid ~ .invalid-tooltip {
- display: block;
-}
-
.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {
color: #dc3545;
}
@@ -2266,12 +2426,6 @@ textarea.form-control {
border-color: #dc3545;
}
-.was-validated .custom-control-input:invalid ~ .invalid-feedback,
-.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback,
-.custom-control-input.is-invalid ~ .invalid-tooltip {
- display: block;
-}
-
.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {
border-color: #e4606d;
background-color: #e4606d;
@@ -2289,12 +2443,6 @@ textarea.form-control {
border-color: #dc3545;
}
-.was-validated .custom-file-input:invalid ~ .invalid-feedback,
-.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback,
-.custom-file-input.is-invalid ~ .invalid-tooltip {
- display: block;
-}
-
.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {
border-color: #dc3545;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
@@ -2414,6 +2562,10 @@ textarea.form-control {
opacity: 0.65;
}
+.btn:not(:disabled):not(.disabled) {
+ cursor: pointer;
+}
+
a.btn.disabled,
fieldset:disabled a.btn {
pointer-events: none;
@@ -2432,6 +2584,9 @@ fieldset:disabled a.btn {
}
.btn-primary:focus, .btn-primary.focus {
+ color: #fff;
+ background-color: #0069d9;
+ border-color: #0062cc;
box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);
}
@@ -2466,6 +2621,9 @@ fieldset:disabled a.btn {
}
.btn-secondary:focus, .btn-secondary.focus {
+ color: #fff;
+ background-color: #5a6268;
+ border-color: #545b62;
box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);
}
@@ -2500,6 +2658,9 @@ fieldset:disabled a.btn {
}
.btn-success:focus, .btn-success.focus {
+ color: #fff;
+ background-color: #218838;
+ border-color: #1e7e34;
box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);
}
@@ -2534,6 +2695,9 @@ fieldset:disabled a.btn {
}
.btn-info:focus, .btn-info.focus {
+ color: #fff;
+ background-color: #138496;
+ border-color: #117a8b;
box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);
}
@@ -2568,6 +2732,9 @@ fieldset:disabled a.btn {
}
.btn-warning:focus, .btn-warning.focus {
+ color: #212529;
+ background-color: #e0a800;
+ border-color: #d39e00;
box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);
}
@@ -2602,6 +2769,9 @@ fieldset:disabled a.btn {
}
.btn-danger:focus, .btn-danger.focus {
+ color: #fff;
+ background-color: #c82333;
+ border-color: #bd2130;
box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);
}
@@ -2636,6 +2806,9 @@ fieldset:disabled a.btn {
}
.btn-light:focus, .btn-light.focus {
+ color: #212529;
+ background-color: #e2e6ea;
+ border-color: #dae0e5;
box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);
}
@@ -2670,6 +2843,9 @@ fieldset:disabled a.btn {
}
.btn-dark:focus, .btn-dark.focus {
+ color: #fff;
+ background-color: #23272b;
+ border-color: #1d2124;
box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);
}
@@ -2960,7 +3136,6 @@ fieldset:disabled a.btn {
.btn-link:focus, .btn-link.focus {
text-decoration: underline;
- box-shadow: none;
}
.btn-link:disabled, .btn-link.disabled {
@@ -3422,6 +3597,7 @@ input[type="button"].btn-block {
-ms-flex: 1 1 auto;
flex: 1 1 auto;
width: 1%;
+ min-width: 0;
margin-bottom: 0;
}
@@ -3613,7 +3789,10 @@ input[type="button"].btn-block {
.custom-control-input {
position: absolute;
+ left: 0;
z-index: -1;
+ width: 1rem;
+ height: 1.25rem;
opacity: 0;
}
@@ -3637,11 +3816,11 @@ input[type="button"].btn-block {
border-color: #b3d7ff;
}
-.custom-control-input:disabled ~ .custom-control-label {
+.custom-control-input[disabled] ~ .custom-control-label, .custom-control-input:disabled ~ .custom-control-label {
color: #6c757d;
}
-.custom-control-input:disabled ~ .custom-control-label::before {
+.custom-control-input[disabled] ~ .custom-control-label::before, .custom-control-input:disabled ~ .custom-control-label::before {
background-color: #e9ecef;
}
@@ -3680,7 +3859,7 @@ input[type="button"].btn-block {
}
.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e");
}
.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {
@@ -3689,7 +3868,7 @@ input[type="button"].btn-block {
}
.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e");
}
.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {
@@ -3705,7 +3884,7 @@ input[type="button"].btn-block {
}
.custom-radio .custom-control-input:checked ~ .custom-control-label::after {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
}
.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {
@@ -3761,8 +3940,7 @@ input[type="button"].btn-block {
line-height: 1.5;
color: #495057;
vertical-align: middle;
- background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px;
- background-color: #fff;
+ background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px;
border: 1px solid #ced4da;
border-radius: 0.25rem;
-webkit-appearance: none;
@@ -3796,6 +3974,11 @@ input[type="button"].btn-block {
display: none;
}
+.custom-select:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #495057;
+}
+
.custom-select-sm {
height: calc(1.5em + 0.5rem + 2px);
padding-top: 0.25rem;
@@ -3834,6 +4017,7 @@ input[type="button"].btn-block {
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
+.custom-file-input[disabled] ~ .custom-file-label,
.custom-file-input:disabled ~ .custom-file-label {
background-color: #e9ecef;
}
@@ -3881,7 +4065,7 @@ input[type="button"].btn-block {
.custom-range {
width: 100%;
- height: calc(1rem + 0.4rem);
+ height: 1.4rem;
padding: 0;
background-color: transparent;
-webkit-appearance: none;
@@ -3916,6 +4100,7 @@ input[type="button"].btn-block {
background-color: #007bff;
border: 0;
border-radius: 1rem;
+ -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
-webkit-appearance: none;
appearance: none;
@@ -3923,6 +4108,7 @@ input[type="button"].btn-block {
@media (prefers-reduced-motion: reduce) {
.custom-range::-webkit-slider-thumb {
+ -webkit-transition: none;
transition: none;
}
}
@@ -3947,6 +4133,7 @@ input[type="button"].btn-block {
background-color: #007bff;
border: 0;
border-radius: 1rem;
+ -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
-moz-appearance: none;
appearance: none;
@@ -3954,6 +4141,7 @@ input[type="button"].btn-block {
@media (prefers-reduced-motion: reduce) {
.custom-range::-moz-range-thumb {
+ -moz-transition: none;
transition: none;
}
}
@@ -3981,12 +4169,14 @@ input[type="button"].btn-block {
background-color: #007bff;
border: 0;
border-radius: 1rem;
+ -ms-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
appearance: none;
}
@media (prefers-reduced-motion: reduce) {
.custom-range::-ms-thumb {
+ -ms-transition: none;
transition: none;
}
}
@@ -4157,8 +4347,8 @@ input[type="button"].btn-block {
padding: 0.5rem 1rem;
}
-.navbar > .container,
-.navbar > .container-fluid {
+.navbar .container,
+.navbar .container-fluid, .navbar .container-sm, .navbar .container-md, .navbar .container-lg, .navbar .container-xl {
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
@@ -4243,7 +4433,7 @@ input[type="button"].btn-block {
@media (max-width: 575.98px) {
.navbar-expand-sm > .container,
- .navbar-expand-sm > .container-fluid {
+ .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl {
padding-right: 0;
padding-left: 0;
}
@@ -4268,7 +4458,7 @@ input[type="button"].btn-block {
padding-left: 0.5rem;
}
.navbar-expand-sm > .container,
- .navbar-expand-sm > .container-fluid {
+ .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl {
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
}
@@ -4285,7 +4475,7 @@ input[type="button"].btn-block {
@media (max-width: 767.98px) {
.navbar-expand-md > .container,
- .navbar-expand-md > .container-fluid {
+ .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl {
padding-right: 0;
padding-left: 0;
}
@@ -4310,7 +4500,7 @@ input[type="button"].btn-block {
padding-left: 0.5rem;
}
.navbar-expand-md > .container,
- .navbar-expand-md > .container-fluid {
+ .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl {
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
}
@@ -4327,7 +4517,7 @@ input[type="button"].btn-block {
@media (max-width: 991.98px) {
.navbar-expand-lg > .container,
- .navbar-expand-lg > .container-fluid {
+ .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl {
padding-right: 0;
padding-left: 0;
}
@@ -4352,7 +4542,7 @@ input[type="button"].btn-block {
padding-left: 0.5rem;
}
.navbar-expand-lg > .container,
- .navbar-expand-lg > .container-fluid {
+ .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl {
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
}
@@ -4369,7 +4559,7 @@ input[type="button"].btn-block {
@media (max-width: 1199.98px) {
.navbar-expand-xl > .container,
- .navbar-expand-xl > .container-fluid {
+ .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl {
padding-right: 0;
padding-left: 0;
}
@@ -4394,7 +4584,7 @@ input[type="button"].btn-block {
padding-left: 0.5rem;
}
.navbar-expand-xl > .container,
- .navbar-expand-xl > .container-fluid {
+ .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl {
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
}
@@ -4417,7 +4607,7 @@ input[type="button"].btn-block {
}
.navbar-expand > .container,
-.navbar-expand > .container-fluid {
+.navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl {
padding-right: 0;
padding-left: 0;
}
@@ -4437,7 +4627,7 @@ input[type="button"].btn-block {
}
.navbar-expand > .container,
-.navbar-expand > .container-fluid {
+.navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl {
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
}
@@ -4486,7 +4676,7 @@ input[type="button"].btn-block {
}
.navbar-light .navbar-toggler-icon {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
.navbar-light .navbar-text {
@@ -4534,7 +4724,7 @@ input[type="button"].btn-block {
}
.navbar-dark .navbar-toggler-icon {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
.navbar-dark .navbar-text {
@@ -4568,19 +4758,27 @@ input[type="button"].btn-block {
margin-left: 0;
}
-.card > .list-group:first-child .list-group-item:first-child {
- border-top-left-radius: 0.25rem;
- border-top-right-radius: 0.25rem;
+.card > .list-group {
+ border-top: inherit;
+ border-bottom: inherit;
}
-.card > .list-group:last-child .list-group-item:last-child {
- border-bottom-right-radius: 0.25rem;
- border-bottom-left-radius: 0.25rem;
+.card > .list-group:first-child {
+ border-top-width: 0;
+ border-top-left-radius: calc(0.25rem - 1px);
+ border-top-right-radius: calc(0.25rem - 1px);
+}
+
+.card > .list-group:last-child {
+ border-bottom-width: 0;
+ border-bottom-right-radius: calc(0.25rem - 1px);
+ border-bottom-left-radius: calc(0.25rem - 1px);
}
.card-body {
-ms-flex: 1 1 auto;
flex: 1 1 auto;
+ min-height: 1px;
padding: 1.25rem;
}
@@ -4651,67 +4849,56 @@ input[type="button"].btn-block {
padding: 1.25rem;
}
-.card-img {
+.card-img,
+.card-img-top,
+.card-img-bottom {
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
width: 100%;
- border-radius: calc(0.25rem - 1px);
}
+.card-img,
.card-img-top {
- width: 100%;
border-top-left-radius: calc(0.25rem - 1px);
border-top-right-radius: calc(0.25rem - 1px);
}
+.card-img,
.card-img-bottom {
- width: 100%;
border-bottom-right-radius: calc(0.25rem - 1px);
border-bottom-left-radius: calc(0.25rem - 1px);
}
-.card-deck {
- display: -ms-flexbox;
- display: flex;
- -ms-flex-direction: column;
- flex-direction: column;
-}
-
.card-deck .card {
margin-bottom: 15px;
}
@media (min-width: 576px) {
.card-deck {
+ display: -ms-flexbox;
+ display: flex;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
margin-right: -15px;
margin-left: -15px;
}
.card-deck .card {
- display: -ms-flexbox;
- display: flex;
-ms-flex: 1 0 0%;
flex: 1 0 0%;
- -ms-flex-direction: column;
- flex-direction: column;
margin-right: 15px;
margin-bottom: 0;
margin-left: 15px;
}
}
-.card-group {
- display: -ms-flexbox;
- display: flex;
- -ms-flex-direction: column;
- flex-direction: column;
-}
-
.card-group > .card {
margin-bottom: 15px;
}
@media (min-width: 576px) {
.card-group {
+ display: -ms-flexbox;
+ display: flex;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
}
@@ -4775,27 +4962,19 @@ input[type="button"].btn-block {
overflow: hidden;
}
-.accordion > .card:not(:first-of-type) .card-header:first-child {
- border-radius: 0;
-}
-
-.accordion > .card:not(:first-of-type):not(:last-of-type) {
- border-bottom: 0;
- border-radius: 0;
-}
-
-.accordion > .card:first-of-type {
+.accordion > .card:not(:last-of-type) {
border-bottom: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
-.accordion > .card:last-of-type {
+.accordion > .card:not(:first-of-type) {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
-.accordion > .card .card-header {
+.accordion > .card > .card-header {
+ border-radius: 0;
margin-bottom: -1px;
}
@@ -4811,6 +4990,11 @@ input[type="button"].btn-block {
border-radius: 0.25rem;
}
+.breadcrumb-item {
+ display: -ms-flexbox;
+ display: flex;
+}
+
.breadcrumb-item + .breadcrumb-item {
padding-left: 0.5rem;
}
@@ -4862,7 +5046,7 @@ input[type="button"].btn-block {
}
.page-link:focus {
- z-index: 2;
+ z-index: 3;
outline: 0;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
@@ -4879,7 +5063,7 @@ input[type="button"].btn-block {
}
.page-item.active .page-link {
- z-index: 1;
+ z-index: 3;
color: #fff;
background-color: #007bff;
border-color: #007bff;
@@ -5265,6 +5449,7 @@ a.badge-dark:focus, a.badge-dark.focus {
display: flex;
height: 1rem;
overflow: hidden;
+ line-height: 0;
font-size: 0.75rem;
background-color: #e9ecef;
border-radius: 0.25rem;
@@ -5277,6 +5462,7 @@ a.badge-dark:focus, a.badge-dark.focus {
flex-direction: column;
-ms-flex-pack: center;
justify-content: center;
+ overflow: hidden;
color: #fff;
text-align: center;
white-space: nowrap;
@@ -5326,6 +5512,7 @@ a.badge-dark:focus, a.badge-dark.focus {
flex-direction: column;
padding-left: 0;
margin-bottom: 0;
+ border-radius: 0.25rem;
}
.list-group-item-action {
@@ -5350,20 +5537,18 @@ a.badge-dark:focus, a.badge-dark.focus {
position: relative;
display: block;
padding: 0.75rem 1.25rem;
- margin-bottom: -1px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125);
}
.list-group-item:first-child {
- border-top-left-radius: 0.25rem;
- border-top-right-radius: 0.25rem;
+ border-top-left-radius: inherit;
+ border-top-right-radius: inherit;
}
.list-group-item:last-child {
- margin-bottom: 0;
- border-bottom-right-radius: 0.25rem;
- border-bottom-left-radius: 0.25rem;
+ border-bottom-right-radius: inherit;
+ border-bottom-left-radius: inherit;
}
.list-group-item.disabled, .list-group-item:disabled {
@@ -5379,49 +5564,68 @@ a.badge-dark:focus, a.badge-dark.focus {
border-color: #007bff;
}
+.list-group-item + .list-group-item {
+ border-top-width: 0;
+}
+
+.list-group-item + .list-group-item.active {
+ margin-top: -1px;
+ border-top-width: 1px;
+}
+
.list-group-horizontal {
-ms-flex-direction: row;
flex-direction: row;
}
-.list-group-horizontal .list-group-item {
- margin-right: -1px;
- margin-bottom: 0;
-}
-
-.list-group-horizontal .list-group-item:first-child {
- border-top-left-radius: 0.25rem;
+.list-group-horizontal > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
-.list-group-horizontal .list-group-item:last-child {
- margin-right: 0;
+.list-group-horizontal > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
- border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
+.list-group-horizontal > .list-group-item.active {
+ margin-top: 0;
+}
+
+.list-group-horizontal > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+}
+
+.list-group-horizontal > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+}
+
@media (min-width: 576px) {
.list-group-horizontal-sm {
-ms-flex-direction: row;
flex-direction: row;
}
- .list-group-horizontal-sm .list-group-item {
- margin-right: -1px;
- margin-bottom: 0;
- }
- .list-group-horizontal-sm .list-group-item:first-child {
- border-top-left-radius: 0.25rem;
+ .list-group-horizontal-sm > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
- .list-group-horizontal-sm .list-group-item:last-child {
- margin-right: 0;
+ .list-group-horizontal-sm > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
- border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
+ .list-group-horizontal-sm > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-sm > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-sm > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
}
@media (min-width: 768px) {
@@ -5429,21 +5633,25 @@ a.badge-dark:focus, a.badge-dark.focus {
-ms-flex-direction: row;
flex-direction: row;
}
- .list-group-horizontal-md .list-group-item {
- margin-right: -1px;
- margin-bottom: 0;
- }
- .list-group-horizontal-md .list-group-item:first-child {
- border-top-left-radius: 0.25rem;
+ .list-group-horizontal-md > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
- .list-group-horizontal-md .list-group-item:last-child {
- margin-right: 0;
+ .list-group-horizontal-md > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
- border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
+ .list-group-horizontal-md > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-md > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-md > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
}
@media (min-width: 992px) {
@@ -5451,21 +5659,25 @@ a.badge-dark:focus, a.badge-dark.focus {
-ms-flex-direction: row;
flex-direction: row;
}
- .list-group-horizontal-lg .list-group-item {
- margin-right: -1px;
- margin-bottom: 0;
- }
- .list-group-horizontal-lg .list-group-item:first-child {
- border-top-left-radius: 0.25rem;
+ .list-group-horizontal-lg > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
- .list-group-horizontal-lg .list-group-item:last-child {
- margin-right: 0;
+ .list-group-horizontal-lg > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
- border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
+ .list-group-horizontal-lg > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-lg > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-lg > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
}
@media (min-width: 1200px) {
@@ -5473,40 +5685,37 @@ a.badge-dark:focus, a.badge-dark.focus {
-ms-flex-direction: row;
flex-direction: row;
}
- .list-group-horizontal-xl .list-group-item {
- margin-right: -1px;
- margin-bottom: 0;
- }
- .list-group-horizontal-xl .list-group-item:first-child {
- border-top-left-radius: 0.25rem;
+ .list-group-horizontal-xl > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
- .list-group-horizontal-xl .list-group-item:last-child {
- margin-right: 0;
+ .list-group-horizontal-xl > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
- border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
+ .list-group-horizontal-xl > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-xl > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-xl > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
}
-.list-group-flush .list-group-item {
- border-right: 0;
- border-left: 0;
+.list-group-flush {
border-radius: 0;
}
-.list-group-flush .list-group-item:last-child {
- margin-bottom: -1px;
+.list-group-flush > .list-group-item {
+ border-width: 0 0 1px;
}
-.list-group-flush:first-child .list-group-item:first-child {
- border-top: 0;
-}
-
-.list-group-flush:last-child .list-group-item:last-child {
- margin-bottom: 0;
- border-bottom: 0;
+.list-group-flush > .list-group-item:last-child {
+ border-bottom-width: 0;
}
.list-group-item-primary {
@@ -5660,9 +5869,6 @@ button.close {
padding: 0;
background-color: transparent;
border: 0;
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
}
a.close.disabled {
@@ -5763,6 +5969,11 @@ a.close.disabled {
transform: none;
}
+.modal.modal-static .modal-dialog {
+ -webkit-transform: scale(1.02);
+ transform: scale(1.02);
+}
+
.modal-dialog-scrollable {
display: -ms-flexbox;
display: flex;
@@ -5795,6 +6006,9 @@ a.close.disabled {
.modal-dialog-centered::before {
display: block;
height: calc(100vh - 1rem);
+ height: -webkit-min-content;
+ height: -moz-min-content;
+ height: min-content;
content: "";
}
@@ -5856,8 +6070,8 @@ a.close.disabled {
justify-content: space-between;
padding: 1rem 1rem;
border-bottom: 1px solid #dee2e6;
- border-top-left-radius: 0.3rem;
- border-top-right-radius: 0.3rem;
+ border-top-left-radius: calc(0.3rem - 1px);
+ border-top-right-radius: calc(0.3rem - 1px);
}
.modal-header .close {
@@ -5880,22 +6094,20 @@ a.close.disabled {
.modal-footer {
display: -ms-flexbox;
display: flex;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
-ms-flex-align: center;
align-items: center;
-ms-flex-pack: end;
justify-content: flex-end;
- padding: 1rem;
+ padding: 0.75rem;
border-top: 1px solid #dee2e6;
- border-bottom-right-radius: 0.3rem;
- border-bottom-left-radius: 0.3rem;
+ border-bottom-right-radius: calc(0.3rem - 1px);
+ border-bottom-left-radius: calc(0.3rem - 1px);
}
-.modal-footer > :not(:first-child) {
- margin-left: .25rem;
-}
-
-.modal-footer > :not(:last-child) {
- margin-right: .25rem;
+.modal-footer > * {
+ margin: 0.25rem;
}
.modal-scrollbar-measure {
@@ -5922,6 +6134,9 @@ a.close.disabled {
}
.modal-dialog-centered::before {
height: calc(100vh - 3.5rem);
+ height: -webkit-min-content;
+ height: -moz-min-content;
+ height: min-content;
}
.modal-sm {
max-width: 300px;
@@ -6102,7 +6317,7 @@ a.close.disabled {
}
.bs-popover-top > .arrow, .bs-popover-auto[x-placement^="top"] > .arrow {
- bottom: calc((0.5rem + 1px) * -1);
+ bottom: calc(-0.5rem - 1px);
}
.bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^="top"] > .arrow::before {
@@ -6122,7 +6337,7 @@ a.close.disabled {
}
.bs-popover-right > .arrow, .bs-popover-auto[x-placement^="right"] > .arrow {
- left: calc((0.5rem + 1px) * -1);
+ left: calc(-0.5rem - 1px);
width: 0.5rem;
height: 1rem;
margin: 0.3rem 0;
@@ -6145,7 +6360,7 @@ a.close.disabled {
}
.bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^="bottom"] > .arrow {
- top: calc((0.5rem + 1px) * -1);
+ top: calc(-0.5rem - 1px);
}
.bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^="bottom"] > .arrow::before {
@@ -6176,7 +6391,7 @@ a.close.disabled {
}
.bs-popover-left > .arrow, .bs-popover-auto[x-placement^="left"] > .arrow {
- right: calc((0.5rem + 1px) * -1);
+ right: calc(-0.5rem - 1px);
width: 0.5rem;
height: 1rem;
margin: 0.3rem 0;
@@ -6289,7 +6504,7 @@ a.close.disabled {
.carousel-fade .active.carousel-item-right {
z-index: 0;
opacity: 0;
- transition: 0s 0.6s opacity;
+ transition: opacity 0s 0.6s;
}
@media (prefers-reduced-motion: reduce) {
@@ -6351,11 +6566,11 @@ a.close.disabled {
}
.carousel-control-prev-icon {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e");
}
.carousel-control-next-icon {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e");
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e");
}
.carousel-indicators {
@@ -6453,6 +6668,8 @@ a.close.disabled {
}
50% {
opacity: 1;
+ -webkit-transform: none;
+ transform: none;
}
}
@@ -6463,6 +6680,8 @@ a.close.disabled {
}
50% {
opacity: 1;
+ -webkit-transform: none;
+ transform: none;
}
}
@@ -7748,6 +7967,27 @@ button.bg-dark:focus {
}
}
+.user-select-all {
+ -webkit-user-select: all !important;
+ -moz-user-select: all !important;
+ -ms-user-select: all !important;
+ user-select: all !important;
+}
+
+.user-select-auto {
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto !important;
+ -ms-user-select: auto !important;
+ user-select: auto !important;
+}
+
+.user-select-none {
+ -webkit-user-select: none !important;
+ -moz-user-select: none !important;
+ -ms-user-select: none !important;
+ user-select: none !important;
+}
+
.overflow-auto {
overflow: auto !important;
}
@@ -7807,6 +8047,7 @@ button.bg-dark:focus {
width: 1px;
height: 1px;
padding: 0;
+ margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
@@ -7902,18 +8143,6 @@ button.bg-dark:focus {
height: 100vh !important;
}
-.stretched-link::after {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1;
- pointer-events: auto;
- content: "";
- background-color: rgba(0, 0, 0, 0);
-}
-
.m-0 {
margin: 0 !important;
}
@@ -9726,6 +9955,18 @@ button.bg-dark:focus {
}
}
+.stretched-link::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: auto;
+ content: "";
+ background-color: rgba(0, 0, 0, 0);
+}
+
.text-monospace {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
}
@@ -9941,8 +10182,7 @@ a.text-dark:hover, a.text-dark:focus {
}
.text-break {
- word-break: break-word !important;
- overflow-wrap: break-word !important;
+ word-wrap: break-word !important;
}
.text-reset {
@@ -10035,3 +10275,4 @@ a.text-dark:hover, a.text-dark:focus {
border-color: #dee2e6;
}
}
+/*# sourceMappingURL=bootstrap.css.map */ \ No newline at end of file
diff --git a/src/static/templates/admin/base.hbs b/src/static/templates/admin/base.hbs
index a7270b9c..c9cd40dc 100644
--- a/src/static/templates/admin/base.hbs
+++ b/src/static/templates/admin/base.hbs
@@ -1,40 +1,26 @@
<!DOCTYPE html>
<html lang="en">
-
<head>
- <meta http-equiv="content-type" content="text/html; charset=UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
+ <meta name="robots" content="noindex,nofollow" />
<title>Bitwarden_rs Admin Panel</title>
-
<link rel="stylesheet" href="{{urlpath}}/bwrs_static/bootstrap.css" />
- <script src="{{urlpath}}/bwrs_static/bootstrap-native-v4.js"></script>
- <script src="{{urlpath}}/bwrs_static/md5.js"></script>
- <script src="{{urlpath}}/bwrs_static/identicon.js"></script>
<style>
body {
- padding-top: 70px;
- }
-
- @media (max-width:768px) {
- body {
- padding-top: 190px;
- }
-
- .container {
- max-width: 100%;
- }
+ padding-top: 75px;
}
-
img {
width: 48px;
height: 48px;
}
-
.navbar img {
height: 24px;
width: auto;
}
</style>
+ <script src="{{urlpath}}/bwrs_static/md5.js"></script>
+ <script src="{{urlpath}}/bwrs_static/identicon.js"></script>
<script>
function reload() { window.location.reload(); }
function msg(text, reload_page = true) {
@@ -86,47 +72,44 @@
</head>
<body class="bg-light">
- <nav class="navbar navbar-expand-sm navbar-dark bg-dark fixed-top shadow mb-4">
- <div class="container">
- <a class="navbar-brand" href="{{urlpath}}/admin"><img class="pr-1" src="{{urlpath}}/bwrs_static/shield-white.png">Bitwarden_rs Admin</a>
- <div class="navbar-collapse">
- <ul class="navbar-nav">
- <li class="nav-item">
- <a class="nav-link" href="{{urlpath}}/admin">Settings</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="{{urlpath}}/admin/users/overview">Users</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="{{urlpath}}/admin/organizations/overview">Organizations</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="{{urlpath}}/admin/diagnostics">Diagnostics</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="{{urlpath}}/">Vault</a>
- </li>
- </ul>
- </div>
+ <nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4 shadow fixed-top">
+ <div class="container">
+ <a class="navbar-brand" href="{{urlpath}}/admin"><img class="pr-1" src="{{urlpath}}/bwrs_static/shield-white.png">Bitwarden_rs Admin</a>
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse"
+ aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="navbarCollapse">
+ <ul class="navbar-nav mr-auto">
+ {{#if logged_in}}
+ <li class="nav-item">
+ <a class="nav-link" href="{{urlpath}}/admin">Settings</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="{{urlpath}}/admin/users/overview">Users</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="{{urlpath}}/admin/organizations/overview">Organizations</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="{{urlpath}}/admin/diagnostics">Diagnostics</a>
+ </li>
+ {{/if}}
+ <li class="nav-item">
+ <a class="nav-link" href="{{urlpath}}/">Vault</a>
+ </li>
+ </ul>
- <ul class="navbar-nav">
- {{#if version}}
- <li class="nav-item">
- <span class="navbar-text mr-2">Version: {{version}}</span>
- </li>
- {{/if}}
-
- {{#if logged_in}}
- <li class="nav-item rounded btn-secondary">
- <a class="nav-link" href="{{urlpath}}/admin/logout">Log Out</a>
- </li>
- {{/if}}
- </ul>
- </div>
+ {{#if logged_in}}
+ <a class="btn btn-sm btn-secondary" href="{{urlpath}}/admin/logout">Log Out</a>
+ {{/if}}
+ </div>
+ </div>
</nav>
{{> (page_content) }}
+ <!-- This script needs to be at the bottom, else it will fail! -->
<script>
// get current URL path and assign 'active' class to the correct nav-item
(function () {
@@ -138,6 +121,7 @@
}
})();
</script>
+ <!-- This script needs to be at the bottom, else it will fail! -->
+ <script src="{{urlpath}}/bwrs_static/bootstrap-native-v4.js"></script>
</body>
-
</html> \ No newline at end of file
diff --git a/src/static/templates/admin/users.hbs b/src/static/templates/admin/users.hbs
index d3e12f78..758031fc 100644
--- a/src/static/templates/admin/users.hbs
+++ b/src/static/templates/admin/users.hbs
@@ -2,57 +2,61 @@
<div id="users-block" class="my-3 p-3 bg-white rounded shadow">
<h6 class="border-bottom pb-2 mb-0">Registered Users</h6>
- <div id="users-list">
- {{#each users}}
- <div class="media pt-3">
- <img class="mr-2 rounded identicon" data-src="{{Email}}">
- <div class="media-body pb-3 mb-0 small border-bottom">
- <div class="row justify-content-between">
- <div class="col">
+
+
+ <div class="table-responsive-xl small">
+ <table class="table table-sm table-striped table-hover">
+ <thead>
+ <tr>
+ <th style="width: 24px;">User</th>
+ <th></th>
+ <th style="width:90px; min-width: 90px;">Items</th>
+ <th style="min-width: 140px;">Organizations</th>
+ <th style="width: 140px; min-width: 140px;">Actions</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#each users}}
+ <tr>
+ <td><img class="mr-2 rounded identicon" data-src="{{Email}}"></td>
+ <td>
<strong>{{Name}}</strong>
- {{#if TwoFactorEnabled}}
- <span class="badge badge-success ml-2">2FA</span>
- {{/if}}
- {{#case _Status 1}}
- <span class="badge badge-warning ml-2">Invited</span>
- {{/case}}
- <span class="d-block">{{Email}}
+ <span class="d-block">{{Email}}</span>
+ <span class="d-block">
+ {{#if TwoFactorEnabled}}
+ <span class="badge badge-success mr-2" title="2FA is enabled">2FA</span>
+ {{/if}}
+ {{#case _Status 1}}
+ <span class="badge badge-warning mr-2" title="User is invited">Invited</span>
+ {{/case}}
{{#if EmailVerified}}
- <span class="badge badge-success ml-2">Verified</span>
+ <span class="badge badge-success mr-2" title="Email has been verified">Verified</span>
{{/if}}
</span>
- </div>
- <div class="col">
- <strong> Personal Items: </strong>
- <span class="d-block">
- {{cipher_count}}
- </span>
- </div>
- <div class="col-4">
- <strong> Organizations: </strong>
- <span class="d-block">
- {{#each Organizations}}
- <span class="badge badge-primary" data-orgtype="{{Type}}">{{Name}}</span>
- {{/each}}
- </span>
- </div>
- <div class="col" style="font-size: 90%; text-align: right; padding-right: 15px">
+ </td>
+ <td>
+ <span class="d-block">{{cipher_count}}</span>
+ </td>
+ <td>
+ {{#each Organizations}}
+ <span class="badge badge-primary" data-orgtype="{{Type}}">{{Name}}</span>
+ {{/each}}
+ </td>
+ <td style="font-size: 90%; text-align: right; padding-right: 15px">
{{#if TwoFactorEnabled}}
- <a class="mr-2" href="#" onclick='remove2fa({{jsesc Id}})'>Remove all 2FA</a>
+ <a class="d-block" href="#" onclick='remove2fa({{jsesc Id}})'>Remove all 2FA</a>
{{/if}}
-
- <a class="mr-2" href="#" onclick='deauthUser({{jsesc Id}})'>Deauthorize sessions</a>
- <a class="mr-2" href="#" onclick='deleteUser({{jsesc Id}}, {{jsesc Email}})'>Delete User</a>
- </div>
- </div>
- </div>
- </div>
- {{/each}}
-
+ <a class="d-block" href="#" onclick='deauthUser({{jsesc Id}})'>Deauthorize sessions</a>
+ <a class="d-block" href="#" onclick='deleteUser({{jsesc Id}}, {{jsesc Email}})'>Delete User</a>
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
</div>
<div class="mt-3">
- <button type="button" class="btn btn-sm btn-link" onclick="updateRevisions();"
+ <button type="button" class="btn btn-sm btn-danger" onclick="updateRevisions();"
title="Force all clients to fetch new data next time they connect. Useful after restoring a backup to remove any stale data.">
Force clients to resync
</button>