Skip to content

Instantly share code, notes, and snippets.

@SidIcarus
Last active February 17, 2022 17:14
Show Gist options
  • Save SidIcarus/0d511b805df255e53a8142efa8e6035d to your computer and use it in GitHub Desktop.
Save SidIcarus/0d511b805df255e53a8142efa8e6035d to your computer and use it in GitHub Desktop.
angularjs-toast
/*!
* es-module implementation of anguljar-toast by sibiraj
* @module angularjs-toast
* @description A Simple toast notification service for AngularJS pages
* @version v4.0.2
* @link https://github.com/sibiraj-s/angularjs-toast#readme
* @licence MIT License, https://opensource.org/licenses/MIT
*/
/** @param {ng.ITemplateCacheService} $templateCache */
const $run = function $run ($templateCache) {
const containerHTML = `
<div class="angularjs-toast">
<ul class="toast-container" ng-class="::[position, containerClass]">
<toast-message
ng-repeat="data in toastMessages track by data.id"
data="data"
></toast-message>
</ul>
</div>
`
const messageHTML = `
<li class="animate-repeat">
<div class="alert alert-dismissible" ng-class="::data.toastClass">
<span ng-bind-html="::data.message"></span>
<span
class="close"
aria-label="close"
title="close"
ng-click="close(\$index)"
ng-if="::data.dismissible"
>×</span>
</div>
</li>
`
$templateCache.put('angularjs-toast/container.html', containerHTML)
$templateCache.put('angularjs-toast/message.html', messageHTML)
}
$run.$inject = ['$templateCache']
/** @typedef {{
dismissible: boolean
id: string
message: string
timeout: number
toastClass: string
}} ToastMessage */
/** @typedef {ReturnType<ReturnType<$toastProvider>['$get']>} Toast */
const $toastProvider = function $toastProvider () {
const defaultOptions = {
containerClass: '',
defaultToastClass: 'alert-success',
dismissible: true,
insertFromTop: true,
maxToast: 7,
position: 'right',
timeout: 5 * 1000,
}
let options = defaultOptions
/** @type {ToastMessage[]} */ const toastMessages = []
const getUniqId = function getUniqId () {
const s4 = function s4() {
return ((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1)
}
return ''.concat(new Date().getTime().toString(), '-')
.concat(s4(), '-')
.concat(s4(), '-')
.concat(s4())
}
return {
// setNotificationTimer(json, timeout)
configure (c) {
options = angular.extend({}, defaultOptions, c)
},
$get () {
return {
/**
* @param {string | {
* message: string
* timeout: number
* dismissible: boolean
* className: string
* }} args
*/
create (args) {
let message, timeout, dismissible, toastClass
if (typeof args === 'string') {
message = args
} else {
message = args.message
timeout = args.timeout || options.timeout
dismissible = args.dismissible ?? options.dismissible
toastClass = args.className || options.defaultToastClass
}
// append inputs to json variable
if (!message) throw new Error('Toast message is required...')
// this will be pushed to the -> scope.$toastMessages array
timeout || (timeout = options.timeout)
dismissible ?? (dismissible = options.dismissible)
toastClass || (toastClass = options.defaultToastClass)
const json = {
dismissible,
id: getUniqId(),
message,
timeout,
toastClass,
}
// remove last/ first element from -> scope.$toastMessages when the
// maxlength is reached
if (toastMessages.length === options.maxToast) {
!options.insertFromTop
? toastMessages.shift()
: toastMessages.pop()
} // push elements to array
options.insertFromTop
? toastMessages.unshift(json)
: toastMessages.push(json)
},
/** @param {number} index */
destroy (index) {
toastMessages.splice(index, 1)
},
options,
toastMessages
}
}
}
}
/**
* @param {Toast} toast
* @returns {ng.IDirective}
*/
const $toastContainerDirective = function $toastContainerDirective (toast) {
return {
replace: true,
restrict: 'EA',
scope: {},
css: '/path/to/toast.style.css',
templateUrl: 'angularjs-toast/container.html',
compile () {
const options = toast.options
return function ($scope) {
$scope.containerClass = options.containerClass
$scope.position = options.position
$scope.toastMessages = toast.toastMessages
}
}
}
}
$toastContainerDirective.$inject = ['toast']
/**
* @param {ng.ITimeoutService} $timeout
* @param {Toast} toast
* @returns {ng.IDirective}
*/
const $toastMessageDirective = function $toastMessageDirective ($timeout, toast) {
return {
replace: true,
restrict: 'E',
scope: { data: '=' },
templateUrl: 'angularjs-toast/message.html',
/**
* @param {ng.IScope & { data: ToastMessage, close: () => void }} $scope
*/ // @ts-ignore
link ($scope) {
const data = $scope.data
const options = toast.options
const timeout = data.timeout || options.timeout
const toastMessages = toast.toastMessages
const destroy = function destroy () {
toast.destroy(toastMessages.indexOf(data))
}
$scope.close = destroy
const timeoutPromise = $timeout(function () { destroy() }, timeout)
$scope.$on('$destroy', function () { $timeout.cancel(timeoutPromise) })
}
}
}
$toastMessageDirective.$inject = ['$timeout', 'toast']
angular.module('angularjsToast', ['ngSanitize', 'ngAnimate', 'angularCSS'])
.run($run)
.provider('toast', $toastProvider)
.directive('toast', $toastContainerDirective)
.directive('toastMessage', $toastMessageDirective)
/*!
* @module angularjs-toast
* @description A Simple toast notification service for AngularJS pages
* @version v4.0.1
* @link https://github.com/sibiraj-s/angularjs-toast#readme
* @licence MIT License, https://opensource.org/licenses/MIT
*/
.toast-alert .alert, .angularjs-toast .alert {
padding: 15px;
margin-bottom: 20px;
border: 1px solid transparent;
border-radius: 4px;
position: relative;
}
.toast-alert .alert h4, .angularjs-toast .alert h4 {
margin-top: 0;
color: inherit;
}
.toast-alert .alert .alert-link, .angularjs-toast .alert .alert-link {
font-weight: bold;
}
.toast-alert .alert > p, .angularjs-toast .alert > p,
.toast-alert .alert > ul,
.angularjs-toast .alert > ul {
margin-bottom: 0;
}
.toast-alert .alert > p + p, .angularjs-toast .alert > p + p {
margin-top: 5px;
}
.toast-alert .alert.alert-dismissible, .angularjs-toast .alert.alert-dismissible {
padding-right: 35px;
}
.toast-alert .alert.alert-dismissible .close, .angularjs-toast .alert.alert-dismissible .close {
position: absolute;
top: 0;
right: 0;
padding: 15px;
color: inherit;
}
.toast-alert .alert .close, .angularjs-toast .alert .close {
float: right;
font-size: 21px;
font-weight: bold;
line-height: 1;
color: #000;
text-shadow: 0 1px 0 #fff;
filter: alpha(opacity=20);
opacity: 0.2;
text-decoration: none;
}
.toast-alert .alert .close:focus, .angularjs-toast .alert .close:focus, .toast-alert .alert .close:hover, .angularjs-toast .alert .close:hover {
color: #000;
text-decoration: none;
cursor: pointer;
filter: alpha(opacity=50);
opacity: 0.5;
}
.toast-alert .alert.alert-success, .angularjs-toast .alert.alert-success {
color: #155724;
background-color: #d4edda;
border-color: #c3e6cb;
}
.toast-alert .alert.alert-info, .angularjs-toast .alert.alert-info {
color: #0c5460;
background-color: #d1ecf1;
border-color: #bee5eb;
}
.toast-alert .alert.alert-warning, .angularjs-toast .alert.alert-warning {
color: #856404;
background-color: #fff3cd;
border-color: #ffeeba;
}
.toast-alert .alert.alert-danger, .angularjs-toast .alert.alert-danger {
color: #721c24;
background-color: #f8d7da;
border-color: #f5c6cb;
}
.angularjs-toast {
position: fixed;
z-index: 10000;
width: 100%;
top: 0;
}
.angularjs-toast ul.toast-container {
padding: 0;
list-style: none;
position: absolute;
top: 20px;
}
.angularjs-toast ul.toast-container li {
transition: 1s ease;
}
.angularjs-toast ul.toast-container li .alert {
display: inline-block;
}
.angularjs-toast ul.toast-container li.ng-enter {
opacity: 0;
transition: 0.5s ease-in;
}
.angularjs-toast ul.toast-container li.ng-enter.ng-enter-active {
opacity: 1;
}
.angularjs-toast ul.toast-container li.ng-leave {
opacity: 1;
transition: 0.2s ease-in;
}
.angularjs-toast ul.toast-container li.ng-leave.ng-leave-active {
opacity: 0;
}
.angularjs-toast ul.toast-container.right {
right: 0;
margin-right: 20px;
}
.angularjs-toast ul.toast-container.right li {
text-align: right;
}
.angularjs-toast ul.toast-container.center {
left: 0;
left: 50%;
transform: translate(-50%, 0);
}
.angularjs-toast ul.toast-container.left {
left: 0;
margin-left: 20px;
}
.angularjs-toast ul.toast-container.left li {
text-align: left;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment