Lorolem upravena verze - LittleFS, FSBrowser pro offline, pouziti PROGMEM.

This commit is contained in:
2020-08-21 12:43:46 +02:00
parent 9db6f3d1ca
commit eeca8b9af6
117 changed files with 23138 additions and 2 deletions

View File

@ -0,0 +1,24 @@
export const partial = (fn, ...presetArgs) => (...laterArgs) => fn(...presetArgs, ...laterArgs);
export const append = (el, ...children) => children.forEach(child => el.appendChild(child));
export const isString = input => typeof input === 'string';
export const createElement = (elementType, ...classNames) => {
const element = document.createElement(elementType);
if(classNames.length) {
classNames.forEach(currentClass => element.classList.add(currentClass));
}
return element;
};
const setInnerText = (element, text) => {
element.innerText = text;
return element;
};
const createTextElement = (elementType, ...classNames) => partial(setInnerText, createElement(elementType, ...classNames));
export const createParagraph = (...classNames) => createTextElement('p', ...classNames);

View File

@ -0,0 +1,148 @@
'use strict';
// Polyfills
import './polyfills/classList';
import {
append,
createElement,
createParagraph,
isString
} from './helpers';
(function Notifications(window) {
// Default notification options
const defaultOptions = {
closeOnClick: true,
displayCloseButton: false,
positionClass: 'nfc-top-right',
onclick: false,
showDuration: 3500,
theme: 'success'
};
function configureOptions(options) {
// Create a copy of options and merge with defaults
options = Object.assign({}, defaultOptions, options);
// Validate position class
function validatePositionClass(className) {
const validPositions = [
'nfc-top-left',
'nfc-top-right',
'nfc-bottom-left',
'nfc-bottom-right'
];
return validPositions.indexOf(className) > -1;
}
// Verify position, if invalid reset to default
if (!validatePositionClass(options.positionClass)) {
console.warn('An invalid notification position class has been specified.');
options.positionClass = defaultOptions.positionClass;
}
// Verify onClick is a function
if (options.onclick && typeof options.onclick !== 'function') {
console.warn('Notification on click must be a function.');
options.onclick = defaultOptions.onclick;
}
// Verify show duration
if(typeof options.showDuration !== 'number') {
options.showDuration = defaultOptions.showDuration;
}
// Verify theme
if(!isString(options.theme) || options.theme.length === 0) {
console.warn('Notification theme must be a string with length');
options.theme = defaultOptions.theme;
}
return options;
}
// Create a new notification instance
function createNotification(options) {
// Validate options and set defaults
options = configureOptions(options);
// Return a notification function
return function notification({ title, message } = {}) {
const container = createNotificationContainer(options.positionClass);
if(!title && !message) {
return console.warn('Notification must contain a title or a message!');
}
// Create the notification wrapper
const notificationEl = createElement('div', 'ncf', options.theme);
// Close on click
if(options.closeOnClick === true) {
notificationEl.addEventListener('click', () => container.removeChild(notificationEl));
}
// Custom click callback
if(options.onclick) {
notificationEl.addEventListener('click', (e) => options.onclick(e));
}
// Display close button
if(options.displayCloseButton) {
const closeButton = createElement('button');
closeButton.innerText = 'X';
// Use the wrappers close on click to avoid useless event listeners
if(options.closeOnClick === false){
closeButton.addEventListener('click', () =>container.removeChild(notificationEl));
}
append(notificationEl, closeButton);
}
// Append title and message
isString(title) && title.length && append(notificationEl, createParagraph('ncf-title')(title));
isString(message) && message.length && append(notificationEl, createParagraph('nfc-message')(message));
// Append to container
append(container, notificationEl);
// Remove element after duration
if(options.showDuration && options.showDuration > 0) {
const timeout = setTimeout(() => {
container.removeChild(notificationEl);
// Remove container if empty
if(container.querySelectorAll('.ncf').length === 0) {
document.body.removeChild(container);
}
}, options.showDuration);
// If close on click is enabled and the user clicks, cancel timeout
if(options.closeOnClick || options.displayCloseButton) {
notificationEl.addEventListener('click', () => clearTimeout(timeout));
}
}
};
}
function createNotificationContainer(position) {
let container = document.querySelector(`.${position}`);
if(!container) {
container = createElement('div', 'ncf-container', position);
append(document.body, container);
}
return container;
}
// Add Notifications to window to make globally accessible
if (window.createNotification) {
console.warn('Window already contains a create notification function. Have you included the script twice?');
} else {
window.createNotification = createNotification;
}
})(window);

View File

@ -0,0 +1,68 @@
(function () {
if (typeof window.Element === 'undefined' || 'classList' in document.documentElement) return;
var prototype = Array.prototype,
push = prototype.push,
splice = prototype.splice,
join = prototype.join;
function DOMTokenList(el) {
this.el = el;
// The className needs to be trimmed and split on whitespace
// to retrieve a list of classes.
var classes = el.className.replace(/^\s+|\s+$/g,'').split(/\s+/);
for (var i = 0; i < classes.length; i++) {
push.call(this, classes[i]);
}
}
DOMTokenList.prototype = {
add: function(token) {
if(this.contains(token)) return;
push.call(this, token);
this.el.className = this.toString();
},
contains: function(token) {
return this.el.className.indexOf(token) != -1;
},
item: function(index) {
return this[index] || null;
},
remove: function(token) {
if (!this.contains(token)) return;
for (var i = 0; i < this.length; i++) {
if (this[i] == token) break;
}
splice.call(this, i, 1);
this.el.className = this.toString();
},
toString: function() {
return join.call(this, ' ');
},
toggle: function(token) {
if (!this.contains(token)) {
this.add(token);
} else {
this.remove(token);
}
return this.contains(token);
}
};
window.DOMTokenList = DOMTokenList;
function defineElementGetter (obj, prop, getter) {
if (Object.defineProperty) {
Object.defineProperty(obj, prop,{
get : getter
});
} else {
obj.__defineGetter__(prop, getter);
}
}
defineElementGetter(Element.prototype, 'classList', function () {
return new DOMTokenList(this);
});
})();

View File

@ -0,0 +1,134 @@
// Base colors
$success: #51A351;
$info: #2F96B4;
$warning: #f87400;
$error: #BD362F;
$grey: #999999;
.ncf-container {
font-size: 14px;
box-sizing: border-box;
position: fixed;
z-index: 999999;
&.nfc-top-left {
top: 12px;
left: 12px;
}
&.nfc-top-right {
top: 12px;
right: 12px;
}
&.nfc-bottom-right {
bottom: 12px;
right: 12px;
}
&.nfc-bottom-left {
bottom: 12px;
left: 12px;
}
@media (max-width: 767px) {
left: 0;
right: 0;
}
.ncf {
background: #ffffff;
transition: .3s ease;
position: relative;
pointer-events: auto;
overflow: hidden;
margin: 0 0 6px;
padding: 30px;
width: 300px;
border-radius: 3px 3px 3px 3px;
box-shadow: 0 0 12px $grey;
color: #000000;
opacity: 0.9;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=90);
filter: alpha(opacity=90);
background-position: 15px center !important;
background-repeat: no-repeat !important;
// Prevent annoying text selection
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
-ms-user-select: none; /* IE 10+ */
user-select: none; /* Likely future */
&:hover {
box-shadow: 0 0 12px #000000;
opacity: 1;
cursor: pointer;
}
.ncf-title {
font-weight: bold;
font-size: 16px;
text-align: left;
margin-top: 0;
margin-bottom: 6px;
word-wrap: break-word;
}
.nfc-message {
margin: 0;
text-align: left;
word-wrap: break-word;
}
}
// Themes
.success {
background: $success;
color: #ffffff;
padding: 15px 15px 15px 50px;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==");
}
.info {
background: $info;
color: #ffffff;
padding: 15px 15px 15px 50px;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=");
}
.warning {
background: $warning;
color: #ffffff;
padding: 15px 15px 15px 50px;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=");
}
.error {
background: $error;
color: #ffffff;
padding: 15px 15px 15px 50px;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important;
}
button {
position: relative;
right: -0.3em;
top: -0.3em;
float: right;
font-weight: bold;
color: #FFFFFF;
text-shadow: 0 1px 0 #ffffff;
opacity: 0.8;
line-height: 1;
font-size: 16px;
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
&:hover {
opacity: 1;
}
}
}