Lorolem upravena verze - LittleFS, FSBrowser pro offline, pouziti PROGMEM.
This commit is contained in:
@ -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);
|
@ -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);
|
@ -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);
|
||||
});
|
||||
})();
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user