mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-01 21:49:21 +03:00
Cleanup bootstrap
This commit is contained in:
parent
1802dda136
commit
eb5fb5342e
34 changed files with 192 additions and 3044 deletions
340
vendors/bootstrap/js/bootstrap.native.js
vendored
340
vendors/bootstrap/js/bootstrap.native.js
vendored
|
|
@ -7,200 +7,160 @@
|
|||
window.BSN = (() => {
|
||||
'use strict';
|
||||
|
||||
const transitionEndEvent = 'transitionend',
|
||||
doc = document,
|
||||
const doc = document,
|
||||
body = doc.body,
|
||||
setFocus = element => element.focus ? element.focus() : element.setActive();
|
||||
|
||||
function emulateTransitionEnd(element,handler) {
|
||||
var called = 0, duration = parseFloat(getComputedStyle(element).transitionDuration),
|
||||
transitionEndWrapper = e => {
|
||||
!called && handler(e), called = 1;
|
||||
element.removeEventListener( transitionEndEvent, transitionEndWrapper);
|
||||
};
|
||||
(isFinite(duration) && duration)
|
||||
? element.addEventListener( transitionEndEvent, transitionEndWrapper )
|
||||
: setTimeout(() => { !called && handler(), called = 1; }, 17);
|
||||
}
|
||||
|
||||
function Dropdown(element) {
|
||||
var self = this,
|
||||
parent, menu, menuItems = [];
|
||||
function preventEmptyAnchor(ev, anchor) {
|
||||
const p = anchor.parentNode;
|
||||
((anchor.href && anchor.href.slice(-1) === '#') || (p && p.href && p.href.slice(-1) === '#'))
|
||||
&& ev.preventDefault();
|
||||
}
|
||||
function toggleEvents() {
|
||||
let action = element.open ? 'addEventListener' : 'removeEventListener';
|
||||
doc[action]('click',dismissHandler,false);
|
||||
doc[action]('keydown',preventScroll,false);
|
||||
doc[action]('keyup',keyHandler,false);
|
||||
doc[action]('focus',dismissHandler,false);
|
||||
}
|
||||
function dismissHandler(e) {
|
||||
let eventTarget = e.target,
|
||||
hasData = eventTarget && (eventTarget.getAttribute('data-toggle')
|
||||
|| (eventTarget.parentNode && eventTarget.parentNode.getAttribute('data-toggle')));
|
||||
if ( e.type === 'focus' && (eventTarget === element || eventTarget === menu || menu.contains(eventTarget) ) ) {
|
||||
return;
|
||||
}
|
||||
if ( hasData && (eventTarget === menu || menu.contains(eventTarget)) ) { return; }
|
||||
self.hide();
|
||||
preventEmptyAnchor(e,eventTarget);
|
||||
}
|
||||
function clickHandler(e) {
|
||||
self.show();
|
||||
preventEmptyAnchor(e,e.target);
|
||||
}
|
||||
function preventScroll(e) {
|
||||
( e.code === 'ArrowUp' || e.code === 'ArrowDown' ) && e.preventDefault();
|
||||
}
|
||||
function keyHandler(e) {
|
||||
var activeItem = doc.activeElement,
|
||||
isSameElement = activeItem === element,
|
||||
isInsideMenu = menu.contains(activeItem),
|
||||
isMenuItem = activeItem.parentNode === menu || activeItem.parentNode.parentNode === menu,
|
||||
idx = menuItems.indexOf(activeItem);
|
||||
if ( isMenuItem ) {
|
||||
idx = isSameElement ? 0
|
||||
: e.code === 'ArrowUp' ? (idx>1?idx-1:0)
|
||||
: e.code === 'ArrowDown' ? (idx<menuItems.length-1?idx+1:idx) : idx;
|
||||
menuItems[idx] && setFocus(menuItems[idx]);
|
||||
}
|
||||
if ( (menuItems.length && isMenuItem
|
||||
|| !menuItems.length && (isInsideMenu || isSameElement)
|
||||
|| !isInsideMenu )
|
||||
&& element.open && e.code === 'Escape'
|
||||
) {
|
||||
self.toggle();
|
||||
}
|
||||
}
|
||||
self.show = () => {
|
||||
menu = parent.querySelector('.dropdown-menu');
|
||||
menuItems = [];
|
||||
Array.from(menu.children).forEach(child => {
|
||||
child.children.length && (child.children[0].tagName === 'A' && menuItems.push(child.children[0]));
|
||||
child.tagName === 'A' && menuItems.push(child);
|
||||
});
|
||||
!('tabindex' in menu) && menu.setAttribute('tabindex', '0');
|
||||
menu.classList.add('show');
|
||||
parent.classList.add('show');
|
||||
element.setAttribute('aria-expanded',true);
|
||||
element.open = true;
|
||||
element.removeEventListener('click',clickHandler,false);
|
||||
setTimeout(() => {
|
||||
setFocus( menu.getElementsByTagName('INPUT')[0] || element );
|
||||
toggleEvents();
|
||||
},1);
|
||||
};
|
||||
self.hide = () => {
|
||||
menu.classList.remove('show');
|
||||
parent.classList.remove('show');
|
||||
element.setAttribute('aria-expanded',false);
|
||||
element.open = false;
|
||||
toggleEvents();
|
||||
setFocus(element);
|
||||
setTimeout(() => element.Dropdown && element.addEventListener('click',clickHandler,false), 1);
|
||||
};
|
||||
self.toggle = () => (parent.classList.contains('show') && element.open) ? self.hide() : self.show();
|
||||
parent = element.parentNode;
|
||||
element.addEventListener('click',clickHandler,false);
|
||||
element.open = false;
|
||||
element.Dropdown = self;
|
||||
}
|
||||
|
||||
function Modal(modal) {
|
||||
var scrollBarWidth;
|
||||
function setScrollbar() {
|
||||
var openModal = body.classList.contains('modal-open'),
|
||||
bodyPad = parseInt(getComputedStyle(body).paddingRight),
|
||||
bodyOverflow = doc.documentElement.clientHeight !== doc.documentElement.scrollHeight
|
||||
|| body.clientHeight !== body.scrollHeight,
|
||||
modalOverflow = modal.clientHeight !== modal.scrollHeight;
|
||||
scrollBarWidth = measureScrollbar();
|
||||
modal.style.paddingRight = !modalOverflow && scrollBarWidth ? scrollBarWidth + "px" : '';
|
||||
body.style.paddingRight = modalOverflow || bodyOverflow
|
||||
? (bodyPad + (openModal ? 0:scrollBarWidth)) + "px"
|
||||
: '';
|
||||
}
|
||||
function resetScrollbar() {
|
||||
body.style.paddingRight = '';
|
||||
modal.style.paddingRight = '';
|
||||
}
|
||||
function measureScrollbar() {
|
||||
var scrollDiv = doc.createElement('div'), widthValue;
|
||||
scrollDiv.className = 'modal-scrollbar-measure';
|
||||
body.appendChild(scrollDiv);
|
||||
widthValue = scrollDiv.offsetWidth - scrollDiv.clientWidth;
|
||||
body.removeChild(scrollDiv);
|
||||
return widthValue;
|
||||
}
|
||||
function toggleEvents(action) {
|
||||
window[action ? 'addEventListener' : 'removeEventListener']( 'resize',
|
||||
() => modal.classList.contains('show') && setScrollbar(), { passive: true });
|
||||
}
|
||||
function beforeShow() {
|
||||
modal.style.display = 'block';
|
||||
setScrollbar();
|
||||
!doc.getElementsByClassName('modal show')[0] && body.classList.add('modal-open');
|
||||
modal.classList.add('show');
|
||||
modal.setAttribute('aria-hidden', false);
|
||||
modal.classList.contains('fade') ? emulateTransitionEnd(modal, triggerShow) : triggerShow();
|
||||
}
|
||||
function triggerShow() {
|
||||
setFocus(modal);
|
||||
modal.isAnimating = false;
|
||||
toggleEvents(1);
|
||||
}
|
||||
function triggerHide() {
|
||||
modal.style.display = '';
|
||||
body.classList.remove('modal-open');
|
||||
resetScrollbar();
|
||||
toggleEvents();
|
||||
modal.isAnimating = false;
|
||||
}
|
||||
this.show = () => {
|
||||
if (!modal.classList.contains('show') || !modal.isAnimating) {
|
||||
modal.isAnimating = true;
|
||||
doc.getElementsByClassName('modal show')[0] ? beforeShow() : setTimeout( beforeShow, 0 );
|
||||
}
|
||||
};
|
||||
this.hide = () => {
|
||||
if (modal.classList.contains('show') ) {
|
||||
modal.isAnimating = true;
|
||||
modal.classList.remove('show');
|
||||
modal.setAttribute('aria-hidden', true);
|
||||
modal.classList.contains('fade') ? emulateTransitionEnd(modal, triggerHide) : triggerHide();
|
||||
}
|
||||
};
|
||||
modal.isAnimating = false;
|
||||
modal.Modal = this;
|
||||
}
|
||||
|
||||
class Tab {
|
||||
constructor(element) {
|
||||
this.element = element
|
||||
element.Tab = this;
|
||||
element.addEventListener('click', e => {e.preventDefault();this.show();});
|
||||
}
|
||||
|
||||
show() {
|
||||
const el = this.element, li = el.closest('li');
|
||||
if (!li.classList.contains('active')) {
|
||||
const previous = el.closest('ul').querySelector('.active a');
|
||||
previous.closest('li').classList.remove('active');
|
||||
doc.querySelector(previous.getAttribute('href')).classList.remove('active');
|
||||
li.classList.add('active');
|
||||
doc.querySelector(el.getAttribute('href')).classList.add('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Dropdown: Dropdown,
|
||||
Modal: Modal,
|
||||
Tab: Tab
|
||||
Dropdown: function(element) {
|
||||
let menu, menuItems = [];
|
||||
const self = this,
|
||||
parent = element.parentNode,
|
||||
preventEmptyAnchor = e => {
|
||||
const t = e.target, href = t.href || (t.parentNode && t.parentNode.href);
|
||||
(href && href.slice(-1) === '#') && e.preventDefault();
|
||||
},
|
||||
toggleEvents = () => {
|
||||
let action = element.open ? 'addEventListener' : 'removeEventListener';
|
||||
doc[action]('click',dismissHandler,false);
|
||||
doc[action]('keydown',preventScroll,false);
|
||||
doc[action]('keyup',keyHandler,false);
|
||||
doc[action]('focus',dismissHandler,false);
|
||||
},
|
||||
dismissHandler = e => {
|
||||
let eventTarget = e.target,
|
||||
inside = menu.contains(eventTarget),
|
||||
hasData = eventTarget && (eventTarget.getAttribute('data-toggle')
|
||||
|| (eventTarget.parentNode && eventTarget.parentNode.getAttribute('data-toggle')));
|
||||
if ((e.type === 'focus' && (eventTarget === element || inside))
|
||||
|| (hasData && inside)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
self.hide();
|
||||
preventEmptyAnchor(e);
|
||||
},
|
||||
clickHandler = e => {
|
||||
self.show();
|
||||
preventEmptyAnchor(e);
|
||||
},
|
||||
preventScroll = e => (e.code === 'ArrowUp' || e.code === 'ArrowDown') && e.preventDefault(),
|
||||
keyHandler = e => {
|
||||
let activeItem = doc.activeElement,
|
||||
isSameElement = activeItem === element,
|
||||
isInsideMenu = menu.contains(activeItem),
|
||||
isMenuItem = activeItem.parentNode === menu || activeItem.parentNode.parentNode === menu,
|
||||
idx = menuItems.indexOf(activeItem);
|
||||
if ( isMenuItem ) {
|
||||
idx = isSameElement ? 0
|
||||
: e.code === 'ArrowUp' ? (idx>1?idx-1:0)
|
||||
: e.code === 'ArrowDown' ? (idx<menuItems.length-1?idx+1:idx) : idx;
|
||||
menuItems[idx] && setFocus(menuItems[idx]);
|
||||
}
|
||||
if ( (menuItems.length && isMenuItem
|
||||
|| !menuItems.length && (isInsideMenu || isSameElement)
|
||||
|| !isInsideMenu )
|
||||
&& element.open && e.code === 'Escape'
|
||||
) {
|
||||
self.toggle();
|
||||
}
|
||||
};
|
||||
self.show = () => {
|
||||
menu = parent.querySelector('.dropdown-menu');
|
||||
menuItems = [];
|
||||
Array.from(menu.children).forEach(child => {
|
||||
child.children.length && (child.children[0].tagName === 'A' && menuItems.push(child.children[0]));
|
||||
child.tagName === 'A' && menuItems.push(child);
|
||||
});
|
||||
!('tabindex' in menu) && menu.setAttribute('tabindex', '0');
|
||||
menu.classList.add('show');
|
||||
parent.classList.add('show');
|
||||
element.setAttribute('aria-expanded',true);
|
||||
element.open = true;
|
||||
element.removeEventListener('click',clickHandler,false);
|
||||
setTimeout(() => {
|
||||
setFocus( menu.getElementsByTagName('INPUT')[0] || element );
|
||||
toggleEvents();
|
||||
},1);
|
||||
};
|
||||
self.hide = () => {
|
||||
menu.classList.remove('show');
|
||||
parent.classList.remove('show');
|
||||
element.setAttribute('aria-expanded',false);
|
||||
element.open = false;
|
||||
toggleEvents();
|
||||
setFocus(element);
|
||||
setTimeout(() => element.Dropdown && element.addEventListener('click',clickHandler,false), 1);
|
||||
};
|
||||
self.toggle = () => (parent.classList.contains('show') && element.open) ? self.hide() : self.show();
|
||||
element.addEventListener('click',clickHandler,false);
|
||||
element.open = false;
|
||||
element.Dropdown = self;
|
||||
},
|
||||
|
||||
Modal: function(modal) {
|
||||
let isAnimating = false;
|
||||
const mcl = modal.classList,
|
||||
emulateTransitionEnd = (element,handler) => {
|
||||
let transitionEndEvent = 'transitionend',
|
||||
duration = parseFloat(getComputedStyle(element).transitionDuration),
|
||||
transitionEndWrapper = e => {
|
||||
handler && handler(e), handler = 0;
|
||||
element.removeEventListener( transitionEndEvent, transitionEndWrapper);
|
||||
};
|
||||
(isFinite(duration) && duration)
|
||||
? element.addEventListener( transitionEndEvent, transitionEndWrapper )
|
||||
: setTimeout(() => { handler && handler(), handler = 0; }, 17);
|
||||
},
|
||||
beforeShow = () => {
|
||||
!doc.getElementsByClassName('modal show')[0] && body.classList.add('modal-open');
|
||||
mcl.add('show');
|
||||
modal.setAttribute('aria-hidden', false);
|
||||
mcl.contains('fade') ? emulateTransitionEnd(modal, triggerShow) : triggerShow();
|
||||
},
|
||||
triggerShow = () => {
|
||||
setFocus(modal);
|
||||
isAnimating = false;
|
||||
},
|
||||
triggerHide = () => {
|
||||
body.classList.remove('modal-open');
|
||||
isAnimating = false;
|
||||
};
|
||||
this.show = () => {
|
||||
if (!mcl.contains('show') || !isAnimating) {
|
||||
isAnimating = true;
|
||||
doc.getElementsByClassName('modal show')[0] ? beforeShow() : setTimeout( beforeShow, 0 );
|
||||
}
|
||||
};
|
||||
this.hide = () => {
|
||||
if (mcl.contains('show') ) {
|
||||
isAnimating = true;
|
||||
mcl.remove('show');
|
||||
modal.setAttribute('aria-hidden', true);
|
||||
mcl.contains('fade') ? emulateTransitionEnd(modal, triggerHide) : triggerHide();
|
||||
}
|
||||
};
|
||||
modal.Modal = this;
|
||||
},
|
||||
|
||||
Tab: class {
|
||||
constructor(element) {
|
||||
this.element = element
|
||||
element.Tab = this;
|
||||
element.addEventListener('click', e => {e.preventDefault();this.show();});
|
||||
}
|
||||
|
||||
show() {
|
||||
const el = this.element, li = el.closest('li');
|
||||
if (!li.classList.contains('active')) {
|
||||
const previous = el.closest('ul').querySelector('.active a');
|
||||
previous.closest('li').classList.remove('active');
|
||||
doc.querySelector(previous.getAttribute('href')).classList.remove('active');
|
||||
li.classList.add('active');
|
||||
doc.querySelector(el.getAttribute('href')).classList.add('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue