Rename external directory to third-party.
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Lucas Reade
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/* Main context menu outer */
|
||||
.contextualMenu{
|
||||
font-size: 13px;
|
||||
position: absolute;
|
||||
padding: 8px 0;
|
||||
background: var(--contextualMenuBg);
|
||||
box-shadow: var(--contextualMenuShadow);
|
||||
border-radius: var(--contextualMenuRadius);
|
||||
margin:0;
|
||||
list-style: none;
|
||||
color: var(--contextualMenuText);
|
||||
}
|
||||
|
||||
/* Menu seperator item */
|
||||
.contextualMenuSeperator{
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: 5px 5px;
|
||||
}
|
||||
.contextualMenuSeperator span{
|
||||
display: block;
|
||||
width:100%;
|
||||
height:1px;
|
||||
background: var(--contextualSeperator);
|
||||
}
|
||||
|
||||
/* Default menu item */
|
||||
.contextualMenuItemOuter {
|
||||
position: relative;
|
||||
}
|
||||
.contextualMenuItem{
|
||||
display: block;
|
||||
padding: 5px 8px;
|
||||
cursor: default;
|
||||
}
|
||||
.contextualMenuItem:hover{
|
||||
background: var(--contextualHover);
|
||||
}
|
||||
.contextualMenuItemIcon{
|
||||
float: left;
|
||||
width:16px;
|
||||
height: 16px;
|
||||
}
|
||||
.contextualMenuItemTitle{
|
||||
text-align: left;
|
||||
line-height: 16px;
|
||||
display: inline-block;
|
||||
padding: 0px 0px 0px 7px;
|
||||
}
|
||||
.contextualMenuItemTip{
|
||||
float: right;
|
||||
padding: 0px 0px 0px 50px;
|
||||
text-align: right;
|
||||
line-height: 16px;
|
||||
}
|
||||
.contextualMenuItemOverflow{
|
||||
float: right;
|
||||
width:16px;
|
||||
height: 16px;
|
||||
padding: 1px 0px 0px 7px;
|
||||
}
|
||||
|
||||
.contextualMenuItemOverflow .contextualMenuItemOverflowLine{
|
||||
display: block;
|
||||
height: 1px;
|
||||
margin: 3px 2px;
|
||||
background: var(--contextualOverflowIcon);
|
||||
}
|
||||
.contextualMenuItemOverflow.hidden{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.contextualMenuItem.disabled{
|
||||
opacity: 0.4;
|
||||
}
|
||||
.contextualMenuItem.disabled:hover{
|
||||
background: none;
|
||||
}
|
||||
|
||||
/* Submenu item */
|
||||
.contextualSubMenu{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: var(--contextualSubMenuBg);
|
||||
border-radius: var(--contextualMenuRadius);
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 1000px;
|
||||
transition: max-height 0.5s;
|
||||
overflow: hidden;
|
||||
}
|
||||
.contextualSubMenu .contextualMenuItem:hover{
|
||||
background: var(--contextualHover);
|
||||
}
|
||||
|
||||
.contextualMenuHidden{
|
||||
max-height: 0;
|
||||
}
|
||||
|
||||
/* Multi item button */
|
||||
.contextualMultiItem{
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
.contextualMultiItem .contextualMenuItemOuter{
|
||||
flex: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Hover menu */
|
||||
.contextualHoverMenuOuter{
|
||||
position: relative;
|
||||
}
|
||||
.contextualHoverMenuItem{
|
||||
display: block;
|
||||
padding: 5px 8px;
|
||||
cursor: default;
|
||||
}
|
||||
.contextualHoverMenuItem.disabled{
|
||||
opacity: 0.4;
|
||||
}
|
||||
.contextualHoverMenuItem.disabled:hover{
|
||||
background: none;
|
||||
}
|
||||
.contextualHoverMenuItem:hover{
|
||||
background: var(--contextualHover);
|
||||
}
|
||||
|
||||
.contextualHoverMenuOuter > .contextualHoverMenu{
|
||||
display: none;
|
||||
}
|
||||
.contextualHoverMenuOuter:hover > .contextualHoverMenu{
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
top: 0;
|
||||
background: var(--contextualMenuBg);
|
||||
box-shadow: var(--contextualMenuShadow);
|
||||
border-radius: var(--contextualMenuRadius);
|
||||
padding: 8px 0;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
list-style: none;
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
class Contextual{
|
||||
/**
|
||||
* Creates a new contextual menu
|
||||
* @param {object} opts options which build the menu e.g. position and items
|
||||
* @param {number} opts.width sets the width of the menu including children
|
||||
* @param {boolean} opts.isSticky sets how the menu apears, follow the mouse or sticky
|
||||
* @param {Array<ContextualItem>} opts.items sets the default items in the menu
|
||||
*/
|
||||
constructor(opts){
|
||||
contextualCore.CloseMenu();
|
||||
|
||||
this.position = opts.isSticky != null ? opts.isSticky : false;
|
||||
this.menuControl = contextualCore.CreateEl(`<ul class='contextualJs contextualMenu'></ul>`);
|
||||
this.menuControl.style.width = opts.width != null ? opts.width : '200px';
|
||||
opts.items.forEach(i => {
|
||||
let item = new ContextualItem(i);
|
||||
this.menuControl.appendChild(item.element);
|
||||
});
|
||||
|
||||
if(event != undefined){
|
||||
event.stopPropagation()
|
||||
document.body.appendChild(this.menuControl);
|
||||
contextualCore.PositionMenu(this.position, event, this.menuControl);
|
||||
}
|
||||
|
||||
document.onclick = function(e){
|
||||
if(!e.target.classList.contains('contextualJs')){
|
||||
contextualCore.CloseMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Adds item to this contextual menu instance
|
||||
* @param {ContextualItem} item item to add to the contextual menu
|
||||
*/
|
||||
add(item){
|
||||
this.menuControl.appendChild(item.element);
|
||||
}
|
||||
/**
|
||||
* Makes this contextual menu visible
|
||||
*/
|
||||
show(){
|
||||
event.stopPropagation()
|
||||
document.body.appendChild(this.menuControl);
|
||||
contextualCore.PositionMenu(this.position, event, this.menuControl);
|
||||
}
|
||||
/**
|
||||
* Hides this contextual menu
|
||||
*/
|
||||
hide(){
|
||||
event.stopPropagation()
|
||||
contextualCore.CloseMenu();
|
||||
}
|
||||
/**
|
||||
* Toggle visibility of menu
|
||||
*/
|
||||
toggle(){
|
||||
event.stopPropagation()
|
||||
if(this.menuControl.parentElement != document.body){
|
||||
document.body.appendChild(this.menuControl);
|
||||
contextualCore.PositionMenu(this.position, event, this.menuControl);
|
||||
}else{
|
||||
contextualCore.CloseMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
class ContextualItem{
|
||||
element;
|
||||
/**
|
||||
*
|
||||
* @param {Object} opts
|
||||
* @param {string} [opts.label]
|
||||
* @param {string} [opts.type]
|
||||
* @param {string} [opts.markup]
|
||||
* @param {string} [opts.icon]
|
||||
* @param {string} [opts.cssIcon]
|
||||
* @param {string} [opts.shortcut]
|
||||
* @param {void} [opts.onClick]
|
||||
* @param {boolean} [opts.enabled]
|
||||
* @param {Array<ContextualItem>} [opts.items]
|
||||
*
|
||||
*/
|
||||
constructor(opts){
|
||||
switch(opts.type){
|
||||
case 'seperator':
|
||||
this.seperator();
|
||||
break;
|
||||
case 'custom':
|
||||
this.custom(opts.markup);
|
||||
break;
|
||||
case 'multi':
|
||||
this.multiButton(opts.items);
|
||||
break;
|
||||
case 'submenu':
|
||||
this.subMenu(opts.label, opts.items, (opts.icon !== undefined ? opts.icon : ''), (opts.cssIcon !== undefined ? opts.cssIcon : ''), (opts.enabled !== undefined ? opts.enabled : true));
|
||||
break;
|
||||
case 'hovermenu':
|
||||
this.hoverMenu(opts.label, opts.items, (opts.icon !== undefined ? opts.icon : ''), (opts.cssIcon !== undefined ? opts.cssIcon : ''), (opts.enabled !== undefined ? opts.enabled : true));
|
||||
break;
|
||||
case 'normal':
|
||||
default:
|
||||
this.button(opts.label, opts.onClick, (opts.shortcut !== undefined ? opts.shortcut : ''), (opts.icon !== undefined ? opts.icon : ''), (opts.cssIcon !== undefined ? opts.cssIcon : ''), (opts.enabled !== undefined ? opts.enabled : true));
|
||||
}
|
||||
}
|
||||
|
||||
button(label, onClick, shortcut = '', icon = '', cssIcon = '', enabled = true){
|
||||
this.element = contextualCore.CreateEl( `
|
||||
<li class='contextualJs contextualMenuItemOuter'>
|
||||
<div class='contextualJs contextualMenuItem ${enabled == true ? '' : 'disabled'}'>
|
||||
${icon != ''? `<img src='${icon}' class='contextualJs contextualMenuItemIcon'/>` : `<div class='contextualJs contextualMenuItemIcon ${cssIcon != '' ? cssIcon : ''}'></div>`}
|
||||
<span class='contextualJs contextualMenuItemTitle'>${label == undefined? 'No label' : label}</span>
|
||||
<span class='contextualJs contextualMenuItemTip'>${shortcut == ''? '' : shortcut}</span>
|
||||
</div>
|
||||
</li>`);
|
||||
|
||||
if(enabled == true){
|
||||
this.element.addEventListener('click', () => {
|
||||
event.stopPropagation();
|
||||
if(onClick !== undefined){ onClick(); }
|
||||
contextualCore.CloseMenu();
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
custom(markup){
|
||||
this.element = contextualCore.CreateEl(`<li class='contextualJs contextualCustomEl'>${markup}</li>`);
|
||||
}
|
||||
hoverMenu(label, items, icon = '', cssIcon = '', enabled = true){
|
||||
this.element = contextualCore.CreateEl(`
|
||||
<li class='contextualJs contextualHoverMenuOuter'>
|
||||
<div class='contextualJs contextualHoverMenuItem ${enabled == true ? '' : 'disabled'}'>
|
||||
${icon != ''? `<img src='${icon}' class='contextualJs contextualMenuItemIcon'/>` : `<div class='contextualJs contextualMenuItemIcon ${cssIcon != '' ? cssIcon : ''}'></div>`}
|
||||
<span class='contextualJs contextualMenuItemTitle'>${label == undefined? 'No label' : label}</span>
|
||||
<span class='contextualJs contextualMenuItemOverflow'>></span>
|
||||
</div>
|
||||
<ul class='contextualJs contextualHoverMenu'>
|
||||
</ul>
|
||||
</li>
|
||||
`);
|
||||
|
||||
let childMenu = this.element.querySelector('.contextualHoverMenu'),
|
||||
menuItem = this.element.querySelector('.contextualHoverMenuItem');
|
||||
|
||||
if(items !== undefined) {
|
||||
items.forEach(i => {
|
||||
let item = new ContextualItem(i);
|
||||
childMenu.appendChild(item.element);
|
||||
});
|
||||
}
|
||||
if(enabled == true){
|
||||
menuItem.addEventListener('mouseenter', () => {
|
||||
|
||||
});
|
||||
menuItem.addEventListener('mouseleave', () => {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
multiButton(buttons) {
|
||||
this.element = contextualCore.CreateEl(`
|
||||
<li class='contextualJs contextualMultiItem'>
|
||||
</li>
|
||||
`);
|
||||
buttons.forEach(i => {
|
||||
let item = new ContextualItem(i);
|
||||
this.element.appendChild(item.element);
|
||||
});
|
||||
}
|
||||
subMenu(label, items, icon = '', cssIcon = '', enabled = true){
|
||||
this.element = contextualCore.CreateEl( `
|
||||
<li class='contextualJs contextualMenuItemOuter'>
|
||||
<div class='contextualJs contextualMenuItem ${enabled == true ? '' : 'disabled'}'>
|
||||
${icon != ''? `<img src='${icon}' class='contextualJs contextualMenuItemIcon'/>` : `<div class='contextualJs contextualMenuItemIcon ${cssIcon != '' ? cssIcon : ''}'></div>`}
|
||||
<span class='contextualJs contextualMenuItemTitle'>${label == undefined? 'No label' : label}</span>
|
||||
<span class='contextualJs contextualMenuItemOverflow'>
|
||||
<span class='contextualJs contextualMenuItemOverflowLine'></span>
|
||||
<span class='contextualJs contextualMenuItemOverflowLine'></span>
|
||||
<span class='contextualJs contextualMenuItemOverflowLine'></span>
|
||||
</span>
|
||||
</div>
|
||||
<ul class='contextualJs contextualSubMenu contextualMenuHidden'>
|
||||
</ul>
|
||||
</li>`);
|
||||
|
||||
let childMenu = this.element.querySelector('.contextualSubMenu'),
|
||||
menuItem = this.element.querySelector('.contextualMenuItem');
|
||||
|
||||
if(items !== undefined) {
|
||||
items.forEach(i => {
|
||||
let item = new ContextualItem(i);
|
||||
childMenu.appendChild(item.element);
|
||||
});
|
||||
}
|
||||
if(enabled == true){
|
||||
menuItem.addEventListener('click',() => {
|
||||
menuItem.classList.toggle('SubMenuActive');
|
||||
childMenu.classList.toggle('contextualMenuHidden');
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
seperator(label, items) {
|
||||
this.element = contextualCore.CreateEl(`<li class='contextualJs contextualMenuSeperator'><span></span></li>`);
|
||||
}
|
||||
}
|
||||
|
||||
const contextualCore = {
|
||||
PositionMenu: (docked, el, menu) => {
|
||||
if(docked){
|
||||
menu.style.left = ((el.target.offsetLeft + menu.offsetWidth) >= window.innerWidth) ?
|
||||
((el.target.offsetLeft - menu.offsetWidth) + el.target.offsetWidth)+"px"
|
||||
: (el.target.offsetLeft)+"px";
|
||||
|
||||
menu.style.top = ((el.target.offsetTop + menu.offsetHeight) >= window.innerHeight) ?
|
||||
(el.target.offsetTop - menu.offsetHeight)+"px"
|
||||
: (el.target.offsetHeight + el.target.offsetTop)+"px";
|
||||
}else{
|
||||
menu.style.left = ((el.clientX + menu.offsetWidth) >= window.innerWidth) ?
|
||||
((el.clientX - menu.offsetWidth))+"px"
|
||||
: (el.clientX)+"px";
|
||||
|
||||
menu.style.top = ((el.clientY + menu.offsetHeight) >= window.innerHeight) ?
|
||||
(el.clientY - menu.offsetHeight)+"px"
|
||||
: (el.clientY)+"px";
|
||||
}
|
||||
},
|
||||
CloseMenu: () => {
|
||||
let openMenuItem = document.querySelector('.contextualMenu:not(.contextualMenuHidden)');
|
||||
if(openMenuItem != null){ document.body.removeChild(openMenuItem); }
|
||||
},
|
||||
CreateEl: (template) => {
|
||||
var el = document.createElement('div');
|
||||
el.innerHTML = template;
|
||||
return el.firstElementChild;
|
||||
}
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-family:"Font Awesome 6 Free";font-weight:400}
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-family:"Font Awesome 6 Free";font-weight:900}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f250,u+f252,u+f27a}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 apvarun
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*!
|
||||
* Toastify js 1.11.2
|
||||
* https://github.com/apvarun/toastify-js
|
||||
* @license MIT licensed
|
||||
*
|
||||
* Copyright (C) 2018 Varun A P
|
||||
*/
|
||||
|
||||
.toastify {
|
||||
padding: 12px 20px;
|
||||
color: #ffffff;
|
||||
display: inline-block;
|
||||
box-shadow: 0 3px 6px -1px rgba(0, 0, 0, 0.12), 0 10px 36px -4px rgba(77, 96, 232, 0.3);
|
||||
background: -webkit-linear-gradient(315deg, #73a5ff, #5477f5);
|
||||
background: linear-gradient(135deg, #73a5ff, #5477f5);
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
max-width: calc(50% - 20px);
|
||||
z-index: 2147483647;
|
||||
}
|
||||
|
||||
.toastify.on {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toast-close {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: 1em;
|
||||
opacity: 0.4;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.toastify-right {
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.toastify-left {
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
.toastify-top {
|
||||
top: -150px;
|
||||
}
|
||||
|
||||
.toastify-bottom {
|
||||
bottom: -150px;
|
||||
}
|
||||
|
||||
.toastify-rounded {
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.toastify-avatar {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
margin: -7px 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.toastify-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: fit-content;
|
||||
max-width: -moz-fit-content;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 360px) {
|
||||
.toastify-right, .toastify-left {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: fit-content;
|
||||
}
|
||||
}
|
||||
+438
@@ -0,0 +1,438 @@
|
||||
/*!
|
||||
* Toastify js 1.11.2
|
||||
* https://github.com/apvarun/toastify-js
|
||||
* @license MIT licensed
|
||||
*
|
||||
* Copyright (C) 2018 Varun A P
|
||||
*/
|
||||
(function(root, factory) {
|
||||
if (typeof module === "object" && module.exports) {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.Toastify = factory();
|
||||
}
|
||||
})(this, function(global) {
|
||||
// Object initialization
|
||||
var Toastify = function(options) {
|
||||
// Returning a new init object
|
||||
return new Toastify.lib.init(options);
|
||||
},
|
||||
// Library version
|
||||
version = "1.11.2";
|
||||
|
||||
// Set the default global options
|
||||
Toastify.defaults = {
|
||||
oldestFirst: true,
|
||||
text: "Toastify is awesome!",
|
||||
node: undefined,
|
||||
duration: 3000,
|
||||
selector: undefined,
|
||||
callback: function () {
|
||||
},
|
||||
destination: undefined,
|
||||
newWindow: false,
|
||||
close: false,
|
||||
gravity: "toastify-top",
|
||||
positionLeft: false,
|
||||
position: '',
|
||||
backgroundColor: '',
|
||||
avatar: "",
|
||||
className: "",
|
||||
stopOnFocus: true,
|
||||
onClick: function () {
|
||||
},
|
||||
offset: {x: 0, y: 0},
|
||||
escapeMarkup: true,
|
||||
style: {background: ''}
|
||||
};
|
||||
|
||||
// Defining the prototype of the object
|
||||
Toastify.lib = Toastify.prototype = {
|
||||
toastify: version,
|
||||
|
||||
constructor: Toastify,
|
||||
|
||||
// Initializing the object with required parameters
|
||||
init: function(options) {
|
||||
// Verifying and validating the input object
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
// Creating the options object
|
||||
this.options = {};
|
||||
|
||||
this.toastElement = null;
|
||||
|
||||
// Validating the options
|
||||
this.options.text = options.text || Toastify.defaults.text; // Display message
|
||||
this.options.node = options.node || Toastify.defaults.node; // Display content as node
|
||||
this.options.duration = options.duration === 0 ? 0 : options.duration || Toastify.defaults.duration; // Display duration
|
||||
this.options.selector = options.selector || Toastify.defaults.selector; // Parent selector
|
||||
this.options.callback = options.callback || Toastify.defaults.callback; // Callback after display
|
||||
this.options.destination = options.destination || Toastify.defaults.destination; // On-click destination
|
||||
this.options.newWindow = options.newWindow || Toastify.defaults.newWindow; // Open destination in new window
|
||||
this.options.close = options.close || Toastify.defaults.close; // Show toast close icon
|
||||
this.options.gravity = options.gravity === "bottom" ? "toastify-bottom" : Toastify.defaults.gravity; // toast position - top or bottom
|
||||
this.options.positionLeft = options.positionLeft || Toastify.defaults.positionLeft; // toast position - left or right
|
||||
this.options.position = options.position || Toastify.defaults.position; // toast position - left or right
|
||||
this.options.backgroundColor = options.backgroundColor || Toastify.defaults.backgroundColor; // toast background color
|
||||
this.options.avatar = options.avatar || Toastify.defaults.avatar; // img element src - url or a path
|
||||
this.options.className = options.className || Toastify.defaults.className; // additional class names for the toast
|
||||
this.options.stopOnFocus = options.stopOnFocus === undefined ? Toastify.defaults.stopOnFocus : options.stopOnFocus; // stop timeout on focus
|
||||
this.options.onClick = options.onClick || Toastify.defaults.onClick; // Callback after click
|
||||
this.options.offset = options.offset || Toastify.defaults.offset; // toast offset
|
||||
this.options.escapeMarkup = options.escapeMarkup !== undefined ? options.escapeMarkup : Toastify.defaults.escapeMarkup;
|
||||
this.options.style = options.style || Toastify.defaults.style;
|
||||
if(options.backgroundColor) {
|
||||
this.options.style.background = options.backgroundColor;
|
||||
}
|
||||
|
||||
// Returning the current object for chaining functions
|
||||
return this;
|
||||
},
|
||||
|
||||
// Building the DOM element
|
||||
buildToast: function() {
|
||||
// Validating if the options are defined
|
||||
if (!this.options) {
|
||||
throw "Toastify is not initialized";
|
||||
}
|
||||
|
||||
// Creating the DOM object
|
||||
var divElement = document.createElement("div");
|
||||
divElement.className = "toastify on " + this.options.className;
|
||||
|
||||
// Positioning toast to left or right or center
|
||||
if (!!this.options.position) {
|
||||
divElement.className += " toastify-" + this.options.position;
|
||||
} else {
|
||||
// To be depreciated in further versions
|
||||
if (this.options.positionLeft === true) {
|
||||
divElement.className += " toastify-left";
|
||||
console.warn('Property `positionLeft` will be depreciated in further versions. Please use `position` instead.')
|
||||
} else {
|
||||
// Default position
|
||||
divElement.className += " toastify-right";
|
||||
}
|
||||
}
|
||||
|
||||
// Assigning gravity of element
|
||||
divElement.className += " " + this.options.gravity;
|
||||
|
||||
if (this.options.backgroundColor) {
|
||||
// This is being deprecated in favor of using the style HTML DOM property
|
||||
console.warn('DEPRECATION NOTICE: "backgroundColor" is being deprecated. Please use the "style.background" property.');
|
||||
}
|
||||
|
||||
// Loop through our style object and apply styles to divElement
|
||||
for (var property in this.options.style) {
|
||||
divElement.style[property] = this.options.style[property];
|
||||
}
|
||||
|
||||
// Adding the toast message/node
|
||||
if (this.options.node && this.options.node.nodeType === Node.ELEMENT_NODE) {
|
||||
// If we have a valid node, we insert it
|
||||
divElement.appendChild(this.options.node)
|
||||
} else {
|
||||
if (this.options.escapeMarkup) {
|
||||
divElement.innerText = this.options.text;
|
||||
} else {
|
||||
divElement.innerHTML = this.options.text;
|
||||
}
|
||||
|
||||
if (this.options.avatar !== "") {
|
||||
var avatarElement = document.createElement("img");
|
||||
avatarElement.src = this.options.avatar;
|
||||
|
||||
avatarElement.className = "toastify-avatar";
|
||||
|
||||
if (this.options.position == "left" || this.options.positionLeft === true) {
|
||||
// Adding close icon on the left of content
|
||||
divElement.appendChild(avatarElement);
|
||||
} else {
|
||||
// Adding close icon on the right of content
|
||||
divElement.insertAdjacentElement("afterbegin", avatarElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adding a close icon to the toast
|
||||
if (this.options.close === true) {
|
||||
// Create a span for close element
|
||||
var closeElement = document.createElement("button");
|
||||
closeElement.type = "button";
|
||||
closeElement.setAttribute("aria-label", "Close");
|
||||
closeElement.className = "toast-close";
|
||||
closeElement.innerHTML = "✖";
|
||||
|
||||
// Triggering the removal of toast from DOM on close click
|
||||
closeElement.addEventListener(
|
||||
"click",
|
||||
function(event) {
|
||||
event.stopPropagation();
|
||||
this.removeElement(this.toastElement);
|
||||
window.clearTimeout(this.toastElement.timeOutValue);
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
//Calculating screen width
|
||||
var width = window.innerWidth > 0 ? window.innerWidth : screen.width;
|
||||
|
||||
// Adding the close icon to the toast element
|
||||
// Display on the right if screen width is less than or equal to 360px
|
||||
if ((this.options.position == "left" || this.options.positionLeft === true) && width > 360) {
|
||||
// Adding close icon on the left of content
|
||||
divElement.insertAdjacentElement("afterbegin", closeElement);
|
||||
} else {
|
||||
// Adding close icon on the right of content
|
||||
divElement.appendChild(closeElement);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear timeout while toast is focused
|
||||
if (this.options.stopOnFocus && this.options.duration > 0) {
|
||||
var self = this;
|
||||
// stop countdown
|
||||
divElement.addEventListener(
|
||||
"mouseover",
|
||||
function(event) {
|
||||
window.clearTimeout(divElement.timeOutValue);
|
||||
}
|
||||
)
|
||||
// add back the timeout
|
||||
divElement.addEventListener(
|
||||
"mouseleave",
|
||||
function() {
|
||||
divElement.timeOutValue = window.setTimeout(
|
||||
function() {
|
||||
// Remove the toast from DOM
|
||||
self.removeElement(divElement);
|
||||
},
|
||||
self.options.duration
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Adding an on-click destination path
|
||||
if (typeof this.options.destination !== "undefined") {
|
||||
divElement.addEventListener(
|
||||
"click",
|
||||
function(event) {
|
||||
event.stopPropagation();
|
||||
if (this.options.newWindow === true) {
|
||||
window.open(this.options.destination, "_blank");
|
||||
} else {
|
||||
window.location = this.options.destination;
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof this.options.onClick === "function" && typeof this.options.destination === "undefined") {
|
||||
divElement.addEventListener(
|
||||
"click",
|
||||
function(event) {
|
||||
event.stopPropagation();
|
||||
this.options.onClick();
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
// Adding offset
|
||||
if(typeof this.options.offset === "object") {
|
||||
|
||||
var x = getAxisOffsetAValue("x", this.options);
|
||||
var y = getAxisOffsetAValue("y", this.options);
|
||||
|
||||
var xOffset = this.options.position == "left" ? x : "-" + x;
|
||||
var yOffset = this.options.gravity == "toastify-top" ? y : "-" + y;
|
||||
|
||||
divElement.style.transform = "translate(" + xOffset + "," + yOffset + ")";
|
||||
|
||||
}
|
||||
|
||||
// Returning the generated element
|
||||
return divElement;
|
||||
},
|
||||
|
||||
// Displaying the toast
|
||||
showToast: function() {
|
||||
// Creating the DOM object for the toast
|
||||
this.toastElement = this.buildToast();
|
||||
|
||||
// Getting the root element to with the toast needs to be added
|
||||
var rootElement;
|
||||
if (typeof this.options.selector === "string") {
|
||||
rootElement = document.getElementById(this.options.selector);
|
||||
} else if (this.options.selector instanceof HTMLElement || (typeof ShadowRoot !== 'undefined' && this.options.selector instanceof ShadowRoot)) {
|
||||
rootElement = this.options.selector;
|
||||
} else {
|
||||
rootElement = document.body;
|
||||
}
|
||||
|
||||
// Validating if root element is present in DOM
|
||||
if (!rootElement) {
|
||||
throw "Root element is not defined";
|
||||
}
|
||||
|
||||
// Adding the DOM element
|
||||
var elementToInsert = Toastify.defaults.oldestFirst ? rootElement.firstChild : rootElement.lastChild;
|
||||
rootElement.insertBefore(this.toastElement, elementToInsert);
|
||||
|
||||
// Repositioning the toasts in case multiple toasts are present
|
||||
Toastify.reposition();
|
||||
|
||||
if (this.options.duration > 0) {
|
||||
this.toastElement.timeOutValue = window.setTimeout(
|
||||
function() {
|
||||
// Remove the toast from DOM
|
||||
this.removeElement(this.toastElement);
|
||||
}.bind(this),
|
||||
this.options.duration
|
||||
); // Binding `this` for function invocation
|
||||
}
|
||||
|
||||
// Supporting function chaining
|
||||
return this;
|
||||
},
|
||||
|
||||
hideToast: function() {
|
||||
if (this.toastElement.timeOutValue) {
|
||||
clearTimeout(this.toastElement.timeOutValue);
|
||||
}
|
||||
this.removeElement(this.toastElement);
|
||||
},
|
||||
|
||||
// Removing the element from the DOM
|
||||
removeElement: function(toastElement) {
|
||||
// Hiding the element
|
||||
// toastElement.classList.remove("on");
|
||||
toastElement.className = toastElement.className.replace(" on", "");
|
||||
|
||||
// Removing the element from DOM after transition end
|
||||
window.setTimeout(
|
||||
function() {
|
||||
// remove options node if any
|
||||
if (this.options.node && this.options.node.parentNode) {
|
||||
this.options.node.parentNode.removeChild(this.options.node);
|
||||
}
|
||||
|
||||
// Remove the element from the DOM, only when the parent node was not removed before.
|
||||
if (toastElement.parentNode) {
|
||||
toastElement.parentNode.removeChild(toastElement);
|
||||
}
|
||||
|
||||
// Calling the callback function
|
||||
this.options.callback.call(toastElement);
|
||||
|
||||
// Repositioning the toasts again
|
||||
Toastify.reposition();
|
||||
}.bind(this),
|
||||
400
|
||||
); // Binding `this` for function invocation
|
||||
},
|
||||
};
|
||||
|
||||
// Positioning the toasts on the DOM
|
||||
Toastify.reposition = function() {
|
||||
|
||||
// Top margins with gravity
|
||||
var topLeftOffsetSize = {
|
||||
top: 15,
|
||||
bottom: 15,
|
||||
};
|
||||
var topRightOffsetSize = {
|
||||
top: 15,
|
||||
bottom: 15,
|
||||
};
|
||||
var offsetSize = {
|
||||
top: 15,
|
||||
bottom: 15,
|
||||
};
|
||||
|
||||
// Get all toast messages on the DOM
|
||||
var allToasts = document.getElementsByClassName("toastify");
|
||||
|
||||
var classUsed;
|
||||
|
||||
// Modifying the position of each toast element
|
||||
for (var i = 0; i < allToasts.length; i++) {
|
||||
// Getting the applied gravity
|
||||
if (containsClass(allToasts[i], "toastify-top") === true) {
|
||||
classUsed = "toastify-top";
|
||||
} else {
|
||||
classUsed = "toastify-bottom";
|
||||
}
|
||||
|
||||
var height = allToasts[i].offsetHeight;
|
||||
classUsed = classUsed.substr(9, classUsed.length-1)
|
||||
// Spacing between toasts
|
||||
var offset = 15;
|
||||
|
||||
var width = window.innerWidth > 0 ? window.innerWidth : screen.width;
|
||||
|
||||
// Show toast in center if screen with less than or equal to 360px
|
||||
if (width <= 360) {
|
||||
// Setting the position
|
||||
allToasts[i].style[classUsed] = offsetSize[classUsed] + "px";
|
||||
|
||||
offsetSize[classUsed] += height + offset;
|
||||
} else {
|
||||
if (containsClass(allToasts[i], "toastify-left") === true) {
|
||||
// Setting the position
|
||||
allToasts[i].style[classUsed] = topLeftOffsetSize[classUsed] + "px";
|
||||
|
||||
topLeftOffsetSize[classUsed] += height + offset;
|
||||
} else {
|
||||
// Setting the position
|
||||
allToasts[i].style[classUsed] = topRightOffsetSize[classUsed] + "px";
|
||||
|
||||
topRightOffsetSize[classUsed] += height + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Supporting function chaining
|
||||
return this;
|
||||
};
|
||||
|
||||
// Helper function to get offset.
|
||||
function getAxisOffsetAValue(axis, options) {
|
||||
|
||||
if(options.offset[axis]) {
|
||||
if(isNaN(options.offset[axis])) {
|
||||
return options.offset[axis];
|
||||
}
|
||||
else {
|
||||
return options.offset[axis] + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
return '0px';
|
||||
|
||||
}
|
||||
|
||||
function containsClass(elem, yourClass) {
|
||||
if (!elem || typeof yourClass !== "string") {
|
||||
return false;
|
||||
} else if (
|
||||
elem.className &&
|
||||
elem.className
|
||||
.trim()
|
||||
.split(/\s+/gi)
|
||||
.indexOf(yourClass) > -1
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Setting up the prototype for the init object
|
||||
Toastify.lib.init.prototype = Toastify.lib;
|
||||
|
||||
// Returning the Toastify function to be assigned to the window object/module
|
||||
return Toastify;
|
||||
});
|
||||
Reference in New Issue
Block a user