Added standard operations to layouts

This commit is contained in:
sairaj mote 2021-07-20 16:28:32 +05:30
parent e2e8a18a9f
commit b03fa10c7a
17 changed files with 38264 additions and 247 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
// Global variables
const appPages = ['dashboard', 'settings'];
const domRefs = {};
const appPages = ['dashboard', 'settings']
let timerId;
const currentYear = new Date().getFullYear();
//Checks for internet connection status
if (!navigator.onLine)
@ -10,6 +11,10 @@ if (!navigator.onLine)
"error",
{ sound: true }
);
window.addEventListener("online", () => {
getRef("notification_drawer").clearAll();
notify("We are back online.", "success");
});
window.addEventListener("offline", () => {
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
@ -17,10 +22,6 @@ window.addEventListener("offline", () => {
{ pinned: true, sound: true }
);
});
window.addEventListener("online", () => {
getRef("notification_drawer").clearAll();
notify("We are back online.", "success");
});
// Use instead of document.getElementById
function getRef(elementId) {
@ -43,8 +44,8 @@ function getRef(elementId) {
}
// returns dom with specified element
function createElement(tagName, obj) {
const { className, textContent, innerHTML, attributes = {} } = obj
function createElement(tagName, options) {
const { className, textContent, innerHTML, attributes = {} } = options
const elem = document.createElement(tagName)
for (let attribute in attributes) {
elem.setAttribute(attribute, attributes[attribute])
@ -70,7 +71,6 @@ const debounce = (callback, wait) => {
}
// Limits the rate of function execution
let timerId;
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
@ -87,7 +87,6 @@ function throttle(func, delay) {
}, delay);
}
// function required for popups or modals to appear
class Stack {
constructor() {
this.items = [];
@ -104,14 +103,13 @@ class Stack {
return this.items[this.items.length - 1];
}
}
let popupStack = new Stack(),
zIndex = 10;
async function showPopup(popup, pinned) {
// function required for popups or modals to appear
function showPopup(popupId, pinned) {
zIndex++
getRef(popup).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popup).show({ pinned, popupStack })
return getRef(popup);
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popupId).show({ pinned, popupStack })
return getRef(popupId);
}
// hides the popup or modal
@ -122,7 +120,7 @@ function hidePopup() {
}
// displays a popup for asking permission. Use this instead of JS confirm
let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
const getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
return new Promise(resolve => {
showPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title;
@ -143,19 +141,19 @@ let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK'
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', showText = true, trueBtn = "Ok", falseBtn = "Cancel") {
async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (showText)
if (isPassword)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = falseBtn;
buttons[1].textContent = trueBtn;
buttons[0].textContent = cancelText;
buttons[1].textContent = confirmText;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
@ -170,11 +168,10 @@ async function getPromptInput(title, message = '', showText = true, trueBtn = "O
}
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const { pinned = false, sound } = options
if (mode === "error") console.error(message);
function notify(message, type, options = {}) {
const { pinned = false, sound = false } = options
let icon
switch (mode) {
switch (type) {
case 'success':
icon = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>`
break;
@ -189,7 +186,6 @@ function notify(message, mode, options = {}) {
}
}
const currentYear = new Date().getFullYear();
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
@ -277,7 +273,7 @@ function showPage(targetPage, options = {}) {
else {
pageId = targetPage.includes('#') ? targetPage.split('#')[1] : targetPage
}
if(!appPages.includes(pageId)) return
if (!appPages.includes(pageId)) return
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active')
getRef(pageId).classList.remove('hide-completely')

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
// Global variables
const appPages = ['home'];
const domRefs = {};
const appPages = ['home']
let timerId;
const currentYear = new Date().getFullYear();
//Checks for internet connection status
if (!navigator.onLine)
@ -43,8 +44,8 @@ function getRef(elementId) {
}
// returns dom with specified element
function createElement(tagName, obj) {
const { className, textContent, innerHTML, attributes = {} } = obj
function createElement(tagName, options) {
const { className, textContent, innerHTML, attributes = {} } = options
const elem = document.createElement(tagName)
for (let attribute in attributes) {
elem.setAttribute(attribute, attributes[attribute])
@ -70,7 +71,6 @@ const debounce = (callback, wait) => {
}
// Limits the rate of function execution
let timerId;
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
@ -87,7 +87,6 @@ function throttle(func, delay) {
}, delay);
}
// function required for popups or modals to appear
class Stack {
constructor() {
this.items = [];
@ -97,21 +96,20 @@ class Stack {
}
pop() {
if (this.items.length == 0)
return "Underflow";
return "Underflow";
return this.items.pop();
}
peek() {
return this.items[this.items.length - 1];
}
}
let popupStack = new Stack(),
zIndex = 10;
async function showPopup(popup, pinned) {
// function required for popups or modals to appear
function showPopup(popupId, pinned) {
zIndex++
getRef(popup).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popup).show({ pinned, popupStack })
return getRef(popup);
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popupId).show({ pinned, popupStack })
return getRef(popupId);
}
// hides the popup or modal
@ -122,7 +120,7 @@ function hidePopup() {
}
// displays a popup for asking permission. Use this instead of JS confirm
let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
const getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
return new Promise(resolve => {
showPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title;
@ -143,19 +141,19 @@ let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK'
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', showText = true, trueBtn = "Ok", falseBtn = "Cancel") {
async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (showText)
if (isPassword)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = falseBtn;
buttons[1].textContent = trueBtn;
buttons[0].textContent = cancelText;
buttons[1].textContent = confirmText;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
@ -171,8 +169,7 @@ async function getPromptInput(title, message = '', showText = true, trueBtn = "O
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const { pinned = false, sound } = options
if (mode === "error") console.error(message);
const { pinned = false, sound = false } = options
let icon
switch (mode) {
case 'success':
@ -189,7 +186,6 @@ function notify(message, mode, options = {}) {
}
}
const currentYear = new Date().getFullYear();
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
@ -268,7 +264,8 @@ function createRipple(event, target) {
};
}
function showPage(targetPage) {
function showPage(targetPage, options = {}) {
const { firstLoad, hashChange } = options
let pageId
if (targetPage === '') {
pageId = 'overview_page'
@ -278,5 +275,31 @@ function showPage(targetPage) {
}
if(!appPages.includes(pageId)) return
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active')
getRef(pageId).classList.remove('hide-completely')
getRef(pageId).animate([
{
opacity: 0,
transform: 'translateX(-1rem)'
},
{
opacity: 1,
transform: 'none'
},
],
{
duration: 300,
easing: 'ease'
})
const targetListItem = document.querySelector(`.nav-list__item[href="#${pageId}"]`)
targetListItem.classList.add('nav-list__item--active')
if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height) {
getRef('side_nav').scrollTo({
top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),
behavior: 'smooth'
})
}
if (hashChange && window.innerWidth < 640) {
getRef('side_nav').close()
}
}

View File

@ -387,19 +387,19 @@ main {
padding-bottom: 3rem;
}
.list {
.nav-list {
list-style: none;
display: flex;
flex-direction: column;
margin-bottom: 0.8rem;
}
.list__item {
.nav-list__item {
display: flex;
padding: 0.8rem 1.5rem;
text-transform: capitalize;
}
.list__item--active {
.nav-list__item--active {
color: var(--accent-color);
background: rgba(var(--text-color), 0.06);
}
@ -469,7 +469,7 @@ main {
background: rgba(var(--text-color), 0.5);
}
.list__item:hover {
.nav-list__item:hover {
background: rgba(var(--text-color), 0.1);
cursor: pointer;
}

File diff suppressed because one or more lines are too long

View File

@ -321,13 +321,13 @@ main{
flex-direction: column;
padding-bottom: 3rem;
}
.list{
.nav-list{
list-style: none;
display: flex;
flex-direction: column;
margin-bottom: 0.8rem;
}
.list__item{
.nav-list__item{
display: flex;
padding: 0.8rem 1.5rem;
text-transform: capitalize;
@ -394,7 +394,7 @@ main{
background: rgba(var(--text-color), 0.5);
}
}
.list__item:hover{
.nav-list__item:hover{
background: rgba(var(--text-color), .1);
cursor: pointer;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
// Global variables
const appPages = ['dashboard', 'settings'];
const domRefs = {};
const appPages = ['dashboard', 'settings']
let timerId;
const currentYear = new Date().getFullYear();
//Checks for internet connection status
if (!navigator.onLine)
@ -43,8 +44,8 @@ function getRef(elementId) {
}
// returns dom with specified element
function createElement(tagName, obj) {
const { className, textContent, innerHTML, attributes = {} } = obj
function createElement(tagName, options) {
const { className, textContent, innerHTML, attributes = {} } = options
const elem = document.createElement(tagName)
for (let attribute in attributes) {
elem.setAttribute(attribute, attributes[attribute])
@ -70,7 +71,6 @@ const debounce = (callback, wait) => {
}
// Limits the rate of function execution
let timerId;
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
@ -87,7 +87,6 @@ function throttle(func, delay) {
}, delay);
}
// function required for popups or modals to appear
class Stack {
constructor() {
this.items = [];
@ -97,21 +96,20 @@ class Stack {
}
pop() {
if (this.items.length == 0)
return "Underflow";
return "Underflow";
return this.items.pop();
}
peek() {
return this.items[this.items.length - 1];
}
}
let popupStack = new Stack(),
zIndex = 10;
async function showPopup(popup, pinned) {
// function required for popups or modals to appear
function showPopup(popupId, pinned) {
zIndex++
getRef(popup).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popup).show({ pinned, popupStack })
return getRef(popup);
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popupId).show({ pinned, popupStack })
return getRef(popupId);
}
// hides the popup or modal
@ -122,7 +120,7 @@ function hidePopup() {
}
// displays a popup for asking permission. Use this instead of JS confirm
let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
const getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
return new Promise(resolve => {
showPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title;
@ -143,19 +141,19 @@ let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK'
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', showText = true, trueBtn = "Ok", falseBtn = "Cancel") {
async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (showText)
if (isPassword)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = falseBtn;
buttons[1].textContent = trueBtn;
buttons[0].textContent = cancelText;
buttons[1].textContent = confirmText;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
@ -171,8 +169,7 @@ async function getPromptInput(title, message = '', showText = true, trueBtn = "O
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const { pinned = false, sound } = options
if (mode === "error") console.error(message);
const { pinned = false, sound = false } = options
let icon
switch (mode) {
case 'success':
@ -189,7 +186,6 @@ function notify(message, mode, options = {}) {
}
}
const currentYear = new Date().getFullYear();
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
@ -279,7 +275,7 @@ function showPage(targetPage, options = {}) {
}
if(!appPages.includes(pageId)) return
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
document.querySelector('.list__item--active').classList.remove('list__item--active')
document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active')
getRef(pageId).classList.remove('hide-completely')
getRef(pageId).animate([
{
@ -295,8 +291,8 @@ function showPage(targetPage, options = {}) {
duration: 300,
easing: 'ease'
})
const targetListItem = document.querySelector(`.list__item[href="#${pageId}"]`)
targetListItem.classList.add('list__item--active')
const targetListItem = document.querySelector(`.nav-list__item[href="#${pageId}"]`)
targetListItem.classList.add('nav-list__item--active')
if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height) {
getRef('side_nav').scrollTo({
top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
// Global variables
const appPages = ['dashboard', 'settings'];
const domRefs = {};
const appPages = ['home']
let timerId;
const currentYear = new Date().getFullYear();
//Checks for internet connection status
if (!navigator.onLine)
@ -43,8 +44,8 @@ function getRef(elementId) {
}
// returns dom with specified element
function createElement(tagName, obj) {
const { className, textContent, innerHTML, attributes = {} } = obj
function createElement(tagName, options) {
const { className, textContent, innerHTML, attributes = {} } = options
const elem = document.createElement(tagName)
for (let attribute in attributes) {
elem.setAttribute(attribute, attributes[attribute])
@ -70,7 +71,6 @@ const debounce = (callback, wait) => {
}
// Limits the rate of function execution
let timerId;
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
@ -87,7 +87,6 @@ function throttle(func, delay) {
}, delay);
}
// function required for popups or modals to appear
class Stack {
constructor() {
this.items = [];
@ -97,21 +96,20 @@ class Stack {
}
pop() {
if (this.items.length == 0)
return "Underflow";
return "Underflow";
return this.items.pop();
}
peek() {
return this.items[this.items.length - 1];
}
}
let popupStack = new Stack(),
zIndex = 10;
async function showPopup(popup, pinned) {
// function required for popups or modals to appear
function showPopup(popupId, pinned) {
zIndex++
getRef(popup).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popup).show({ pinned, popupStack })
return getRef(popup);
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popupId).show({ pinned, popupStack })
return getRef(popupId);
}
// hides the popup or modal
@ -122,7 +120,7 @@ function hidePopup() {
}
// displays a popup for asking permission. Use this instead of JS confirm
let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
const getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
return new Promise(resolve => {
showPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title;
@ -143,19 +141,19 @@ let getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK'
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', showText = true, trueBtn = "Ok", falseBtn = "Cancel") {
async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (showText)
if (isPassword)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = falseBtn;
buttons[1].textContent = trueBtn;
buttons[0].textContent = cancelText;
buttons[1].textContent = confirmText;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
@ -171,8 +169,7 @@ async function getPromptInput(title, message = '', showText = true, trueBtn = "O
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const { pinned = false, sound } = options
if (mode === "error") console.error(message);
const { pinned = false, sound = false } = options
let icon
switch (mode) {
case 'success':
@ -189,7 +186,6 @@ function notify(message, mode, options = {}) {
}
}
const currentYear = new Date().getFullYear();
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
@ -268,7 +264,8 @@ function createRipple(event, target) {
};
}
function showPage(targetPage) {
function showPage(targetPage, options = {}) {
const { firstLoad, hashChange } = options
let pageId
if (targetPage === '') {
pageId = 'overview_page'
@ -278,5 +275,31 @@ function showPage(targetPage) {
}
if(!appPages.includes(pageId)) return
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active')
getRef(pageId).classList.remove('hide-completely')
getRef(pageId).animate([
{
opacity: 0,
transform: 'translateX(-1rem)'
},
{
opacity: 1,
transform: 'none'
},
],
{
duration: 300,
easing: 'ease'
})
const targetListItem = document.querySelector(`.nav-list__item[href="#${pageId}"]`)
targetListItem.classList.add('nav-list__item--active')
if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height) {
getRef('side_nav').scrollTo({
top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),
behavior: 'smooth'
})
}
if (hashChange && window.innerWidth < 640) {
getRef('side_nav').close()
}
}

View File

@ -1,133 +0,0 @@
if (!navigator.onLine)
notify('There seems to be a problem connecting to the internet.', 'error', 'fixed', true)
window.addEventListener('offline', () => {
notify('There seems to be a problem connecting to the internet.', 'error', 'fixed', true)
})
window.addEventListener('online', () => {
notify('We are back online.', '', '', true)
})
let themeToggler = document.getElementById("theme_toggle")
if (localStorage.theme === "dark") {
darkTheme()
themeToggler.checked = true;
} else {
lightTheme()
themeToggler.checked = false;
}
function lightTheme() {
document.body.setAttribute("data-theme", "light");
}
function darkTheme() {
document.body.setAttribute("data-theme", "dark");
}
themeToggler.addEventListener("change", () => {
if (themeToggler.checked) {
darkTheme()
localStorage.setItem("theme", "dark");
} else {
lightTheme()
localStorage.setItem("theme", "light");
}
})
// function required for popups or modals to appear
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length == 0)
return "Underflow";
return this.items.pop();
}
peek(index) {
let newIndex = index ? index : 1
return this.items[this.items.length - index];
}
}
let popupStack = new Stack(),
zIndex = 10;
function showPopup(popup, permission) {
let thisPopup = document.getElementById(popup);
document.body.setAttribute('style', `overflow: hidden; top: -${window.scrollY}px`)
popupStack.push({ thisPopup, permission })
thisPopup.show(permission, popupStack)
zIndex++;
thisPopup.setAttribute('style', `z-index: ${zIndex}`)
return thisPopup;
}
function setAttributes(el, attrs) {
for (var key in attrs) {
el.setAttribute(key, attrs[key]);
}
}
// displays a popup for asking permission. Use this instead of JS confirm
let confirmation = function (message) {
return new Promise(resolve => {
let popup = document.getElementById('confirmation');
showPopup('confirmation')
popup.querySelector('#confirm_message').textContent = message;
popup.querySelector('.submit-btn').onclick = () => {
hidePopup()
resolve(true);
}
popup.querySelector('.cancel-btn').onclick = () => {
hidePopup()
resolve(false);
}
})
}
// displays a popup for asking user input. Use this instead of JS prompt
let askPrompt = function (message, defaultVal) {
return new Promise(resolve => {
let popup = document.getElementById('prompt'),
input = popup.querySelector('input');
if (defaultVal)
input.value = defaultVal;
showPopup('prompt')
input.focus()
input.addEventListener('keyup', e => {
if (e.key === 'Enter') {
resolve(input.value);
hidePopup()
}
})
popup.querySelector('#prompt_message').textContent = message;
popup.querySelector('.submit-btn').onclick = () => {
hidePopup()
resolve(input.value);
}
popup.querySelector('.cancel-btn').onclick = () => {
hidePopup()
resolve(null);
}
})
}
function formatedTime(time) {
let timeFrag = new Date(parseInt(time)).toString().split(' '),
day = timeFrag[0],
month = timeFrag[1],
date = timeFrag[2],
year = timeFrag[3],
hours = timeFrag[4].slice(0, timeFrag[4].lastIndexOf(':')),
finalTime = '';
parseInt(hours.split(':')[0]) > 12 ? finalTime = 'PM' : finalTime = 'AM'
return `${hours} ${finalTime} ${day} ${date} ${month} ${year}`
}
function copyToClipboard(parent) {
let toast = document.getElementById('textCopied'),
textToCopy = parent.querySelector('.copy').textContent;
navigator.clipboard.writeText(textToCopy)
toast.classList.remove('hide');
setTimeout(() => {
toast.classList.add('hide');
}, 2000)
}

View File

@ -143,10 +143,10 @@ class ThemeToggle extends HTMLElement {
connectedCallback() {
this.setAttribute('role', 'switch')
this.setAttribute('aria-label', 'theme toggle')
if (localStorage.theme === "dark") {
if (localStorage.getItem(`${window.location.hostname}-theme`) === "dark") {
this.nightlight();
this.setAttribute('checked', '')
} else if (localStorage.theme === "light") {
} else if (localStorage.getItem(`${window.location.hostname}-theme`) === "light") {
this.daylight();
this.removeAttribute('checked')
}
@ -174,10 +174,10 @@ class ThemeToggle extends HTMLElement {
if (name === 'checked') {
if (this.hasAttribute('checked')) {
this.nightlight();
localStorage.setItem("theme", "dark");
localStorage.setItem(`${window.location.hostname}-theme`, "dark");
} else {
this.daylight();
localStorage.setItem("theme", "light");
localStorage.setItem(`${window.location.hostname}-theme`, "light");
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1911,7 +1911,28 @@
</sm-checkbox>
</template>
<script src="assets/prism.js"></script>
<script src="components.min.js"></script>
<script src="dist/button.js"></script>
<script src="dist/carousel.js"></script>
<script src="dist/checkbox.js"></script>
<script src="dist/copy.js"></script>
<script src="dist/file-input.js"></script>
<script src="dist/form.js"></script>
<script src="dist/hamburger-menu.js"></script>
<script src="dist/input.js"></script>
<script src="dist/menu.js"></script>
<script src="dist/notifications.js"></script>
<script src="dist/popup.js"></script>
<script src="dist/radio.js"></script>
<script src="dist/select.js"></script>
<script src="dist/spinner.js"></script>
<script src="dist/strip-select.js"></script>
<script src="dist/switch.js"></script>
<script src="dist/tabs.js"></script>
<script src="dist/tags-input.js"></script>
<script src="dist/text-field.js"></script>
<script src="dist/textarea.js"></script>
<script src="dist/theme-toggle.js"></script>
<script id="default_ui_library">
const domRefs = {};
const appPages = ["overview_page", "quick_start_page", "global_styling_page", "button_page", "carousel_page", "checkbox_page", "copy_page", "file_input_page", "form_page", "hamburger_menu_page", "input_page", "menu_page", "notifications_page", "popup_page", "radio_page", "select_page", "spinner_page", "switch_page", "strip_select_page", "tabs_page", "tags_input_page", "textarea_page", "text_field_page", "theme_toggle_page"]

View File

@ -326,7 +326,7 @@
})
&lt;/script&gt;
</code>
</pre></section></article></main><template id="nav_item_template"><li><a class="list__item interact"></a></li></template><template id="comp_checkbox_template"><sm-checkbox><span class="comp-checkbox__title"></span></sm-checkbox></template><script src="assets/prism.js"></script><script src="components.min.js"></script><script id="default_ui_library">const domRefs = {};
</pre></section></article></main><template id="nav_item_template"><li><a class="list__item interact"></a></li></template><template id="comp_checkbox_template"><sm-checkbox><span class="comp-checkbox__title"></span></sm-checkbox></template><script src="assets/prism.js"></script><script src="dist/button.js"></script><script src="dist/carousel.js"></script><script src="dist/checkbox.js"></script><script src="dist/copy.js"></script><script src="dist/file-input.js"></script><script src="dist/form.js"></script><script src="dist/hamburger-menu.js"></script><script src="dist/input.js"></script><script src="dist/menu.js"></script><script src="dist/notifications.js"></script><script src="dist/popup.js"></script><script src="dist/radio.js"></script><script src="dist/select.js"></script><script src="dist/spinner.js"></script><script src="dist/strip-select.js"></script><script src="dist/switch.js"></script><script src="dist/tabs.js"></script><script src="dist/tags-input.js"></script><script src="dist/text-field.js"></script><script src="dist/textarea.js"></script><script src="dist/theme-toggle.js"></script><script id="default_ui_library">const domRefs = {};
const appPages = ["overview_page", "quick_start_page", "global_styling_page", "button_page", "carousel_page", "checkbox_page", "copy_page", "file_input_page", "form_page", "hamburger_menu_page", "input_page", "menu_page", "notifications_page", "popup_page", "radio_page", "select_page", "spinner_page", "switch_page", "strip_select_page", "tabs_page", "tags_input_page", "textarea_page", "text_field_page", "theme_toggle_page"]
function getRef(elementId) {

305
main_UI.js Normal file
View File

@ -0,0 +1,305 @@
// Global variables
const appPages = ['dashboard', 'settings'];
const domRefs = {};
let timerId;
const currentYear = new Date().getFullYear();
//Checks for internet connection status
if (!navigator.onLine)
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
{ sound: true }
);
window.addEventListener("offline", () => {
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
{ pinned: true, sound: true }
);
});
window.addEventListener("online", () => {
getRef("notification_drawer").clearAll();
notify("We are back online.", "success");
});
// Use instead of document.getElementById
function getRef(elementId) {
if (!domRefs.hasOwnProperty(elementId)) {
domRefs[elementId] = {
count: 1,
ref: null,
};
return document.getElementById(elementId);
} else {
if (domRefs[elementId].count < 3) {
domRefs[elementId].count = domRefs[elementId].count + 1;
return document.getElementById(elementId);
} else {
if (!domRefs[elementId].ref)
domRefs[elementId].ref = document.getElementById(elementId);
return domRefs[elementId].ref;
}
}
}
// returns dom with specified element
function createElement(tagName, options) {
const { className, textContent, innerHTML, attributes = {} } = options
const elem = document.createElement(tagName)
for (let attribute in attributes) {
elem.setAttribute(attribute, attributes[attribute])
}
if (className)
elem.className = className
if (textContent)
elem.textContent = textContent
if (innerHTML)
elem.innerHTML = innerHTML
return elem
}
// Use when a function needs to be executed after user finishes changes
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback.apply(null, args);
}, wait);
};
}
// Limits the rate of function execution
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
return;
}
// Schedule a setTimeout after delay seconds
timerId = setTimeout(function () {
func();
// Once setTimeout function execution is finished, timerId = undefined so that in
// the next scroll event function execution can be scheduled by the setTimeout
timerId = undefined;
}, delay);
}
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length == 0)
return "Underflow";
return this.items.pop();
}
peek() {
return this.items[this.items.length - 1];
}
}
// function required for popups or modals to appear
function showPopup(popupId, pinned) {
zIndex++
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popupId).show({ pinned, popupStack })
return getRef(popupId);
}
// hides the popup or modal
function hidePopup() {
if (popupStack.peek() === undefined)
return;
popupStack.peek().popup.hide()
}
// displays a popup for asking permission. Use this instead of JS confirm
const getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
return new Promise(resolve => {
showPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title;
getRef('confirm_message').textContent = message;
let cancelButton = getRef('confirmation_popup').children[2].children[0],
submitButton = getRef('confirmation_popup').children[2].children[1]
submitButton.textContent = confirmText
cancelButton.textContent = cancelText
submitButton.onclick = () => {
hidePopup()
resolve(true);
}
cancelButton.onclick = () => {
hidePopup()
resolve(false);
}
})
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (isPassword)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = cancelText;
buttons[1].textContent = confirmText;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
return;
}
buttons[1].onclick = () => {
let value = input.value;
hidePopup()
resolve(value)
}
})
}
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const { pinned = false, sound = false } = options
let icon
switch (mode) {
case 'success':
icon = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>`
break;
case 'error':
icon = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-7v2h2v-2h-2zm0-8v6h2V7h-2z"/></svg>`
break;
}
getRef("notification_drawer").push(message, { pinned, icon });
if (navigator.onLine && sound) {
getRef("notification_sound").currentTime = 0;
getRef("notification_sound").play();
}
}
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
const intTime = parseInt(time);
if (String(intTime).length < 13) time *= 1000;
let timeFrag = new Date(intTime).toString().split(" "),
day = timeFrag[0],
month = timeFrag[1],
date = timeFrag[2],
year = timeFrag[3],
minutes = new Date(intTime).getMinutes(),
hours = new Date(intTime).getHours(),
currentTime = new Date().toString().split(" ");
minutes = minutes < 10 ? `0${minutes}` : minutes;
let finalHours = ``;
if (hours > 12) finalHours = `${hours - 12}:${minutes}`;
else if (hours === 0) finalHours = `12:${minutes}`;
else finalHours = `${hours}:${minutes}`;
finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`;
if (relative) {
return `${date} ${month} ${year}`;
} else return `${finalHours} ${month} ${date} ${year}`;
} catch (e) {
console.error(e);
return time;
}
}
window.addEventListener('hashchange', e => showPage(window.location.hash))
window.addEventListener("load", () => {
document.body.classList.remove('hide-completely')
showPage(window.location.hash)
// document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = validateAddr)
document.addEventListener('keyup', (e) => {
if (e.code === 'Escape') {
hidePopup()
}
})
document.addEventListener("pointerdown", (e) => {
if (e.target.closest("button, sm-button:not([disabled]), .interact")) {
createRipple(e, e.target.closest("button, sm-button, .interact"));
}
});
document.addEventListener('copy', () => {
notify('copied', 'success')
})
});
function createRipple(event, target) {
const circle = document.createElement("span");
const diameter = Math.max(target.clientWidth, target.clientHeight);
const radius = diameter / 2;
const targetDimensions = target.getBoundingClientRect();
circle.style.width = circle.style.height = `${diameter}px`;
circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`;
circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`;
circle.classList.add("ripple");
const rippleAnimation = circle.animate(
[
{
transform: "scale(3)",
opacity: 0,
},
],
{
duration: 1000,
fill: "forwards",
easing: "ease-out",
}
);
target.append(circle);
rippleAnimation.onfinish = () => {
circle.remove();
};
}
function showPage(targetPage, options = {}) {
const { firstLoad, hashChange } = options
let pageId
if (targetPage === '') {
pageId = 'overview_page'
}
else {
pageId = targetPage.includes('#') ? targetPage.split('#')[1] : targetPage
}
if(!appPages.includes(pageId)) return
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active')
getRef(pageId).classList.remove('hide-completely')
getRef(pageId).animate([
{
opacity: 0,
transform: 'translateX(-1rem)'
},
{
opacity: 1,
transform: 'none'
},
],
{
duration: 300,
easing: 'ease'
})
const targetListItem = document.querySelector(`.nav-list__item[href="#${pageId}"]`)
targetListItem.classList.add('nav-list__item--active')
if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height) {
getRef('side_nav').scrollTo({
top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),
behavior: 'smooth'
})
}
if (hashChange && window.innerWidth < 640) {
getRef('side_nav').close()
}
}