Open slimninja opened 3 years ago
Made some very quick edits to work for me, hopefully a little helpful. Added the ability to use opt.img, opt.svg or default svg defined
toast.js
/**
* @author Script47 (https://github.com/Script47/Toast)
* @description Toast - A Bootstrap 4.2+ jQuery plugin for the toast component
* @version 1.1.0
**/
(function ($) {
const TOAST_CONTAINER_HTML = `<div id="toast-container" class="toast-container" aria-live="polite" aria-atomic="true"></div>`;
$.toastDefaults = {
position: 'bottom-right',
dismissible: true,
stackable: true,
pauseDelayOnHover: true,
style: {
toast: '',
info: '',
success: '',
warning: '',
error: '',
}
};
$('body').on('hidden.bs.toast', '.toast', function () {
$(this).remove();
});
let toastRunningCount = 1;
function render(opts) {
/** No container, create our own **/
if (!$('#toast-container').length) {
const position = ['top-right', 'top-left', 'top-center', 'bottom-right', 'bottom-left', 'bottom-center'].includes($.toastDefaults.position) ? $.toastDefaults.position : 'top-right';
$('body').prepend(TOAST_CONTAINER_HTML);
$('#toast-container').addClass(position);
}
let toastContainer = $('#toast-container');
let html = '';
let classes = {
header: {
fg: '',
bg: '',
icon: ''
},
subtitle: 'text-white',
dismiss: 'text-white'
};
let id = `toast-${toastRunningCount}`;
let type = opts.type;
let title = opts.title;
let subtitle = opts.subtitle;
let content = opts.content;
let img = opts.img;
let svg = opts.svg;
let delayOrAutohide = opts.delay ? `data-delay="${opts.delay}"` : `data-autohide="false"`;
let hideAfter = ``;
let dismissible = $.toastDefaults.dismissible;
let globalToastStyles = $.toastDefaults.style.toast;
let paused = false;
if (typeof opts.dismissible !== 'undefined') {
dismissible = opts.dismissible;
}
switch (type) {
case 'info':
classes.header.bg = $.toastDefaults.style.info || 'bg-info';
classes.header.fg = $.toastDefaults.style.info || 'text-white';
classes.header.icon = `<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-info-circle-fill mr-2" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412l-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM8 5.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
</svg>`;
break;
case 'success':
classes.header.bg = $.toastDefaults.style.success || 'bg-success';
classes.header.fg = $.toastDefaults.style.info || 'text-white';
classes.header.icon = `<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-check-circle-fill mr-2" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
</svg>`;
break;
case 'warning':
classes.header.bg = $.toastDefaults.style.warning || 'bg-warning';
classes.header.fg = $.toastDefaults.style.warning || 'text-white';
classes.header.icon = `<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-exclamation-circle-fill mr-2" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/>
</svg>`;
break;
case 'error':
classes.header.bg = $.toastDefaults.style.error || 'bg-danger';
classes.header.fg = $.toastDefaults.style.error || 'text-white';
classes.header.icon = `<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-exclamation-circle-fill mr-2" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/>
</svg>`;
break;
}
if ($.toastDefaults.pauseDelayOnHover && opts.delay) {
delayOrAutohide = `data-autohide="false"`;
hideAfter = `data-hide-after="${Math.floor(Date.now() / 1000) + (opts.delay / 1000)}"`;
}
html = `<div id="${id}" class="toast ${globalToastStyles}" role="alert" aria-live="assertive" aria-atomic="true" ${delayOrAutohide} ${hideAfter}>`;
html += `<div class="toast-header ${classes.header.bg} ${classes.header.fg}">`;
if (img) {
html += `<img src="${img.src}" class="mr-2 ${img.class || ''}" alt="${img.alt || 'Image'}">`;
} else if (svg) {
html += svg
} else {
html += classes.header.icon;
}
html += `<strong class="mr-auto">${title}</strong>`;
if (subtitle) {
html += `<small class="${classes.subtitle}">${subtitle}</small>`;
}
if (dismissible) {
html += `<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true" class="${classes.dismiss}">×</span>
</button>`;
}
html += `</div>`;
if (content) {
html += `<div class="toast-body">
${content}
</div>`;
}
html += `</div>`;
if (!$.toastDefaults.stackable) {
toastContainer.find('.toast').each(function () {
$(this).remove();
});
toastContainer.append(html);
toastContainer.find('.toast:last').toast('show');
} else {
toastContainer.append(html);
toastContainer.find('.toast:last').toast('show');
}
if ($.toastDefaults.pauseDelayOnHover) {
setTimeout(function () {
if (!paused) {
$(`#${id}`).toast('hide');
}
}, opts.delay);
$('body').on('mouseover', `#${id}`, function () {
paused = true;
});
$(document).on('mouseleave', '#' + id, function () {
const current = Math.floor(Date.now() / 1000),
future = parseInt($(this).data('hideAfter'));
paused = false;
if (current >= future) {
$(this).toast('hide');
}
});
}
toastRunningCount++;
}
/**
* Show a snack
* @param type
* @param title
* @param delay
*/
$.snack = function (type, title, delay) {
return render({
type,
title,
delay
});
}
/**
* Show a toast
* @param opts
*/
$.toast = function (opts) {
return render(opts);
}
}(jQuery));
and then I updated the toast.css to be a bit more friendly on notify:
/**
* @author Script47 (https://github.com/Script47/Toast)
* @description Toast - A Bootstrap 4.2+ jQuery plugin for the toast component
* @version 1.1.0
**/
.toast-container {
position: fixed;
z-index: 1055;
margin: 1em;
}
.toast-container.top-right {
top: 0;
right: 0;
}
.toast-container.top-left {
top: 0;
left: 0;
}
.toast-container.top-center {
transform: translateX(-50%);
top: 0;
left: 50%;
}
.toast-container.bottom-right {
right: 0;
bottom: 0;
}
.toast-container.bottom-left {
left: 0;
bottom: 0;
}
.toast-container.bottom-center {
transform: translateX(-50%);
bottom: 0;
left: 50%;
}
.toast-container > .toast {
min-width: 150px;
background: transparent;
border: none;
}
.toast-container > .toast > .toast-header {
border: none;
}
.toast-container > .toast > .toast-header strong {
padding-right: 20px;
}
.toast-container > .toast > .toast-body {
background: white;
}
@slimjim91
Thanks for taking the time out to draft some code.
I'll look further into your request/changes sometime this week and have a think about how best to implement this.
I envisage this to be v1.3.0.
Allow the option of switching from img to svg icons, maybe define defaults using bootstrap-icons?