<!DOCTYPE html>
<html ng-app="main">
<head>
<title></title>
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" />
<link href="toaster.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js" ></script>
</head>
<body>
<toaster-container toaster-options="{'time-out': 3000}"></toaster-container>
<div>
<div ng-controller="myController">
<button class="btn btn-primary" style="margin: 150px;" ng-click="pop()">Show toasts</button>
</div>
</div>
<script src="toaster.js"></script>
<script src="script.js"></script>
</body>
</html>
angular.module('main', ['toaster'])
.controller('myController', function($scope, toaster) {
$scope.pop = function(){
toaster.pop('success', "title", "text");
toaster.pop('error', "title", "text");
toaster.pop('warning', "title", "text");
toaster.pop('note', "title", "text");
};
});
'use strict';
/*
* AngularJS Toaster
*
* Copyright 2013 Jiri Kavulak.
* All Rights Reserved.
* Use, reproduction, distribution, and modification of this code is subject to the terms and
* conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
*
* Author: Jiri Kavulak
* Related to project of John Papa and Hans FjÀllemark
*/
angular.module('toaster', [])
.service('toaster', function ($rootScope) {
this.pop = function (type, title, body) {
this.toast = {
type: type,
title: title,
body: body
};
$rootScope.$broadcast('toaster-newToast');
};
})
.constant('toasterConfig', {
'tap-to-dismiss': true,
'newest-on-top': true,
//'fade-in': 1000, // done in css
//'on-fade-in': undefined, // not implemented
//'fade-out': 1000, // done in css
// 'on-fade-out': undefined, // not implemented
//'extended-time-out': 1000, // not implemented
'time-out': 5000, // Set timeOut and extendedTimeout to 0 to make it sticky
'icon-classes': {
error: 'toast-error',
info: 'toast-info',
success: 'toast-success',
warning: 'toast-warning'
},
'icon-class': 'toast-info',
'position-class': 'toast-top-right',
'title-class': 'toast-title',
'message-class': 'toast-message'
})
.directive('toasterContainer', ['$compile', '$timeout', 'toasterConfig', 'toaster',
function ($compile, $timeout, toasterConfig, toaster) {
return {
replace: true,
restrict: 'EA',
link: function (scope, elm, attrs){
var id = 0;
var mergedConfig = toasterConfig;
if (attrs.toasterOptions) {
angular.extend(mergedConfig, scope.$eval(attrs.toasterOptions));
}
scope.config = {
position: mergedConfig['position-class'],
title: mergedConfig['title-class'],
message: mergedConfig['message-class'],
tap: mergedConfig['tap-to-dismiss']
};
function addToast (toast){
toast.type = mergedConfig['icon-classes'][toast.type];
if (!toast.type)
toast.type = mergedConfig['icon-class'];
id++;
angular.extend(toast, { id: id });
if (mergedConfig['time-out'] > 0)
setTimeout(toast, mergedConfig['time-out']);
if (mergedConfig['newest-on-top'] === true)
scope.toasters.unshift(toast);
else
scope.toasters.push(toast);
}
function setTimeout(toast, time){
toast.timeout= $timeout(function (){
scope.removeToast(toast.id);
}, time);
}
scope.toasters = [];
scope.$on('toaster-newToast', function () {
addToast(toaster.toast);
});
},
controller: function($scope, $element, $attrs) {
$scope.stopTimer = function(toast){
if(toast.timeout)
$timeout.cancel(toast.timeout);
};
$scope.removeToast = function (id){
var i = 0;
for (i; i < $scope.toasters.length; i++){
if($scope.toasters[i].id === id)
break;
}
$scope.toasters.splice(i, 1);
};
$scope.remove = function(id){
if ($scope.config.tap === true){
$scope.removeToast(id);
}
};
},
template:
'<div id="toast-container" ng-class="config.position">' +
'<div ng-animate="\'animateToaster\'" ng-repeat="toaster in toasters">' +
'<div class="toast" ng-class="toaster.type" ng-click="remove(toaster.id)" ng-mouseover="stopTimer(toaster)">' +
'<div ng-class="config.title">{{toaster.title}}</div>' +
'<div ng-class="config.message">{{toaster.body}}' +
'</div>' +
'</div>' +
'</div>' +
'</div>'
};
}]);
.toast-title {
font-weight: bold;
}
.toast-message {
-ms-word-wrap: break-word;
word-wrap: break-word;
}
.toast-message a,
.toast-message label {
color: #ffffff;
}
.toast-message a:hover {
color: #cccccc;
text-decoration: none;
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%;
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%;
}
.toast-top-left {
top: 12px;
left: 12px;
}
.toast-top-right {
top: 12px;
right: 12px;
}
.toast-bottom-right {
right: 12px;
bottom: 12px;
}
.toast-bottom-left {
bottom: 12px;
left: 12px;
}
#toast-container {
position: fixed;
z-index: 999998;
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#toast-container > div > div {
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
-moz-border-radius: 3px 3px 3px 3px;
-webkit-border-radius: 3px 3px 3px 3px;
border-radius: 3px 3px 3px 3px;
background-position: 15px center;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999999;
-webkit-box-shadow: 0 0 12px #999999;
box-shadow: 0 0 12px #999999;
color: #ffffff;
/*opacity: 0.8;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
filter: alpha(opacity=80);*/
}
#toast-container > div > :hover {
-moz-box-shadow: 0 0 12px #000000;
-webkit-box-shadow: 0 0 12px #000000;
box-shadow: 0 0 12px #000000;
opacity: 1;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
filter: alpha(opacity=100);
cursor: pointer;
}
#toast-container > div > .toast-info {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important;
}
#toast-container > div > .toast-error {
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;
}
#toast-container > div > .toast-success {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important;
}
#toast-container > div > .toast-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important;
}
#toast-container.toast-top-full-width > div,
#toast-container.toast-bottom-full-width > div {
width: 96%;
margin: auto;
}
.toast {
background-color: #030303;
z-index: 999999;
}
.toast-success {
background-color: #51a351;
}
.toast-error {
background-color: #bd362f;
}
.toast-info {
background-color: #2f96b4;
}
.toast-warning {
background-color: #f89406;
}
/*Responsive Design*/
@media all and (max-width: 240px) {
#toast-container > div > div {
padding: 8px 8px 8px 50px;
width: 108px;
}
}
@media all and (min-width: 241px) and (max-width: 320px) {
#toast-container > div > div {
padding: 8px 8px 8px 50px;
width: 128px;
}
}
@media all and (min-width: 321px) and (max-width: 480px) {
#toast-container > div > div {
padding: 8px 8px 8px 50px;
width: 192px;
}
}
@media all and (min-width: 481px) and (max-width: 768px) {
#toast-container > div > div {
padding: 15px 15px 15px 50px;
width: 300px;
}
}
/*Animation CSS3*/
.animateToaster-enter,
.animateToaster-leave
{
-webkit-transition: 1000ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
-moz-transition: 1000ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
-ms-transition: 1000ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
-o-transition: 1000ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
transition: 1000ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all;
}
.animateToaster-enter.animateToaster-enter-active,
.animateToaster-leave {
opacity: 0.8;
}
.animateToaster-leave.animateToaster-leave-active,
.animateToaster-enter {
opacity: 0;
}