Notifications are very important when you want to inform something to the visitors. However, showing many notifications may lead to user angriness, since he must close all of them. The solution is to use auto hiding notification boxes. The following code shows success and error alerts which disappear automatically.
HTML
<!-- This script got from www.devanswer.com -->
<br />
<div class="row text-center">
<div>
<button class="button large round success">Success notification</button>
</div>
<div>
<button class="button large round alert">Error notification</button>
</div>
</div>
<link rel='stylesheet' href='http://devanswer.com/codes/files/foundation.css'>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='http://devanswer.com/codes/files/foundation.min.js'></script><div id="bcl"><a style="font-size:8pt;text-decoration:none;" href="http://www.devanswer.com">Developers Answer</a></div>
CSS
.alertify,
.alertify-show,
.alertify-log {
-webkit-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
-moz-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
-ms-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
-o-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
/* easeOutBack */
}
.alertify-hide {
-webkit-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
-moz-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
-ms-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
-o-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
/* easeInBack */
}
.alertify-log-hide {
-webkit-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
-moz-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
-ms-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
-o-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
/* easeInBack */
}
.alertify-cover {
position: fixed;
z-index: 99999;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: white;
filter: alpha(opacity=0);
opacity: 0;
}
.alertify-cover-hidden {
display: none;
}
.alertify {
position: fixed;
z-index: 99999;
top: 50px;
left: 50%;
width: 550px;
margin-left: -275px;
opacity: 1;
}
.alertify-hidden {
-webkit-transform: translate(0, -150px);
-moz-transform: translate(0, -150px);
-ms-transform: translate(0, -150px);
-o-transform: translate(0, -150px);
transform: translate(0, -150px);
opacity: 0;
display: none;
}
/* overwrite display: none; for everything except IE6-8 */
:root * > .alertify-hidden {
display: block;
visibility: hidden;
}
.alertify-logs {
position: fixed;
z-index: 5000;
bottom: 10px;
right: 10px;
width: 300px;
}
.alertify-logs-hidden {
display: none;
}
.alertify-log {
display: block;
margin-top: 10px;
position: relative;
right: -300px;
opacity: 0;
}
.alertify-log-show {
right: 0;
opacity: 1;
}
.alertify-log-hide {
-webkit-transform: translate(300px, 0);
-moz-transform: translate(300px, 0);
-ms-transform: translate(300px, 0);
-o-transform: translate(300px, 0);
transform: translate(300px, 0);
opacity: 0;
}
.alertify-dialog {
padding: 25px;
}
.alertify-resetFocus {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.alertify-inner {
text-align: center;
}
.alertify-text {
margin-bottom: 15px;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
font-size: 100%;
}
.alertify-button,
.alertify-button:hover,
.alertify-button:active,
.alertify-button:visited {
background: none;
text-decoration: none;
border: none;
/* line-height and font-size for input button */
line-height: 1.5;
font-size: 100%;
display: inline-block;
cursor: pointer;
margin-left: 5px;
}
@media only screen and (max-width: 680px) {
.alertify,
.alertify-logs {
width: 90%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.alertify {
left: 5%;
margin: 0;
}
}
/**
* Default Look and Feel
*/
.alertify,
.alertify-log {
font-family: sans-serif;
}
.alertify {
background: #FFF;
border: 10px solid #333;
/* browsers that don't support rgba */
border: 10px solid rgba(0, 0, 0, 0.7);
border-radius: 8px;
box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);
-webkit-background-clip: padding;
/* Safari 4? Chrome 6? */
-moz-background-clip: padding;
/* Firefox 3.6 */
background-clip: padding-box;
/* Firefox 4, Safari 5, Opera 10, IE 9 */
}
.alertify-text {
border: 1px solid #CCC;
padding: 10px;
border-radius: 4px;
}
.alertify-button {
border-radius: 4px;
color: #FFF;
font-weight: bold;
padding: 6px 15px;
text-decoration: none;
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.5);
background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
background-image: -ms-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
}
.alertify-button:hover,
.alertify-button:focus {
outline: none;
background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
background-image: -ms-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));
}
.alertify-button:focus {
box-shadow: 0 0 15px #2B72D5;
}
.alertify-button:active {
position: relative;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.alertify-button-cancel,
.alertify-button-cancel:hover,
.alertify-button-cancel:focus {
background-color: #FE1A00;
border: 1px solid #D83526;
}
.alertify-button-ok,
.alertify-button-ok:hover,
.alertify-button-ok:focus {
background-color: #5CB811;
border: 1px solid #3B7808;
}
.alertify-log {
background: #1F1F1F;
background: rgba(0, 0, 0, 0.9);
padding: 15px;
border-radius: 4px;
color: #FFF;
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
}
.alertify-log-error {
background: #FE1A00;
background: rgba(254, 26, 0, 0.9);
}
.alertify-log-success {
background: #5CB811;
background: rgba(92, 184, 17, 0.9);
}
button {
min-width: 300px;
outline: none;
}
Javascript
$(document).foundation();
/*global define*/
(function (global, undefined) {
"use strict";
var document = global.document,
Alertify;
Alertify = function () {
var _alertify = {},
dialogs = {},
isopen = false,
keys = { ENTER: 13, ESC: 27, SPACE: 32 },
queue = [],
$,btnCancel,btnOK,btnReset,btnResetBack,btnFocus,elCallee,elCover,elDialog,elLog,form,input,getTransitionEvent;
/**
* Markup pieces
* @type {Object}
*/
dialogs = {
buttons: {
holder: "<nav class=\"alertify-buttons\">{{buttons}}</nav>",
submit: "<button type=\"submit\" class=\"alertify-button alertify-button-ok\" id=\"alertify-ok\">{{ok}}</button>",
ok: "<button class=\"alertify-button alertify-button-ok\" id=\"alertify-ok\">{{ok}}</button>",
cancel: "<button class=\"alertify-button alertify-button-cancel\" id=\"alertify-cancel\">{{cancel}}</button>" },
input: "<div class=\"alertify-text-wrapper\"><input type=\"text\" class=\"alertify-text\" id=\"alertify-text\"></div>",
message: "<p class=\"alertify-message\">{{message}}</p>",
log: "<article class=\"alertify-log{{class}}\">{{message}}</article>" };
/**
* Return the proper transitionend event
* @return {String} Transition type string
*/
getTransitionEvent = function () {
var t,
type,
supported = false,
el = document.createElement("fakeelement"),
transitions = {
"WebkitTransition": "webkitTransitionEnd",
"MozTransition": "transitionend",
"OTransition": "otransitionend",
"transition": "transitionend" };
for (t in transitions) {
if (el.style[t] !== undefined) {
type = transitions[t];
supported = true;
break;
}
}
return {
type: type,
supported: supported };
};
/**
* Shorthand for document.getElementById()
*
* @param {String} id A specific element ID
* @return {Object} HTML element
*/
$ = function (id) {
return document.getElementById(id);
};
/**
* Alertify private object
* @type {Object}
*/
_alertify = {
/**
* Labels object
* @type {Object}
*/
labels: {
ok: "OK",
cancel: "Cancel" },
/**
* Delay number
* @type {Number}
*/
delay: 5000,
/**
* Whether buttons are reversed (default is secondary/primary)
* @type {Boolean}
*/
buttonReverse: false,
/**
* Which button should be focused by default
* @type {String} "ok" (default), "cancel", or "none"
*/
buttonFocus: "ok",
/**
* Set the transition event on load
* @type {[type]}
*/
transition: undefined,
/**
* Set the proper button click events
*
* @param {Function} fn [Optional] Callback function
*
* @return {undefined}
*/
addListeners: function (fn) {
var hasOK = typeof btnOK !== "undefined",
hasCancel = typeof btnCancel !== "undefined",
hasInput = typeof input !== "undefined",
val = "",
self = this,
ok,cancel,common,key,reset;
// ok event handler
ok = function (event) {
if (typeof event.preventDefault !== "undefined") event.preventDefault();
common(event);
if (typeof input !== "undefined") val = input.value;
if (typeof fn === "function") {
if (typeof input !== "undefined") {
fn(true, val);
} else
fn(true);
}
return false;
};
// cancel event handler
cancel = function (event) {
if (typeof event.preventDefault !== "undefined") event.preventDefault();
common(event);
if (typeof fn === "function") fn(false);
return false;
};
// common event handler (keyup, ok and cancel)
common = function (event) {
self.hide();
self.unbind(document.body, "keyup", key);
self.unbind(btnReset, "focus", reset);
if (hasOK) self.unbind(btnOK, "click", ok);
if (hasCancel) self.unbind(btnCancel, "click", cancel);
};
// keyup handler
key = function (event) {
var keyCode = event.keyCode;
if (keyCode === keys.SPACE && !hasInput || hasInput && keyCode === keys.ENTER) ok(event);
if (keyCode === keys.ESC && hasCancel) cancel(event);
};
// reset focus to first item in the dialog
reset = function (event) {
if (hasInput) input.focus();else
if (!hasCancel || self.buttonReverse) btnOK.focus();else
btnCancel.focus();
};
// handle reset focus link
// this ensures that the keyboard focus does not
// ever leave the dialog box until an action has
// been taken
this.bind(btnReset, "focus", reset);
this.bind(btnResetBack, "focus", reset);
// handle OK click
if (hasOK) this.bind(btnOK, "click", ok);
// handle Cancel click
if (hasCancel) this.bind(btnCancel, "click", cancel);
// listen for keys, Cancel => ESC
this.bind(document.body, "keyup", key);
if (!this.transition.supported) {
this.setFocus();
}
},
/**
* Bind events to elements
*
* @param {Object} el HTML Object
* @param {Event} event Event to attach to element
* @param {Function} fn Callback function
*
* @return {undefined}
*/
bind: function (el, event, fn) {
if (typeof el.addEventListener === "function") {
el.addEventListener(event, fn, false);
} else if (el.attachEvent) {
el.attachEvent("on" + event, fn);
}
},
/**
* Use alertify as the global error handler (using window.onerror)
*
* @return {boolean} success
*/
handleErrors: function () {
if (typeof global.onerror !== "undefined") {
var self = this;
global.onerror = function (msg, url, line) {
self.error("[" + msg + " on line " + line + " of " + url + "]", 0);
};
return true;
} else {
return false;
}
},
/**
* Append button HTML strings
*
* @param {String} secondary The secondary button HTML string
* @param {String} primary The primary button HTML string
*
* @return {String} The appended button HTML strings
*/
appendButtons: function (secondary, primary) {
return this.buttonReverse ? primary + secondary : secondary + primary;
},
/**
* Build the proper message box
*
* @param {Object} item Current object in the queue
*
* @return {String} An HTML string of the message box
*/
build: function (item) {
var html = "",
type = item.type,
message = item.message,
css = item.cssClass || "";
html += "<div class=\"alertify-dialog\">";
html += "<a id=\"alertify-resetFocusBack\" class=\"alertify-resetFocus\" href=\"#\">Reset Focus</a>";
if (_alertify.buttonFocus === "none") html += "<a href=\"#\" id=\"alertify-noneFocus\" class=\"alertify-hidden\"></a>";
// doens't require an actual form
if (type === "prompt") html += "<div id=\"alertify-form\">";
html += "<article class=\"alertify-inner\">";
html += dialogs.message.replace("{{message}}", message);
if (type === "prompt") html += dialogs.input;
html += dialogs.buttons.holder;
html += "</article>";
if (type === "prompt") html += "</div>";
html += "<a id=\"alertify-resetFocus\" class=\"alertify-resetFocus\" href=\"#\">Reset Focus</a>";
html += "</div>";
switch (type) {
case "confirm":
html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.ok));
html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel);
break;
case "prompt":
html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.submit));
html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel);
break;
case "alert":
html = html.replace("{{buttons}}", dialogs.buttons.ok);
html = html.replace("{{ok}}", this.labels.ok);
break;
default:
break;}
elDialog.className = "alertify alertify-" + type + " " + css;
elCover.className = "alertify-cover";
return html;
},
/**
* Close the log messages
*
* @param {Object} elem HTML Element of log message to close
* @param {Number} wait [optional] Time (in ms) to wait before automatically hiding the message, if 0 never hide
*
* @return {undefined}
*/
close: function (elem, wait) {
// Unary Plus: +"2" === 2
var timer = wait && !isNaN(wait) ? +wait : this.delay,
self = this,
hideElement,transitionDone;
// set click event on log messages
this.bind(elem, "click", function () {
hideElement(elem);
});
// Hide the dialog box after transition
// This ensure it doens't block any element from being clicked
transitionDone = function (event) {
event.stopPropagation();
// unbind event so function only gets called once
self.unbind(this, self.transition.type, transitionDone);
// remove log message
elLog.removeChild(this);
if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden";
};
// this sets the hide class to transition out
// or removes the child if css transitions aren't supported
hideElement = function (el) {
// ensure element exists
if (typeof el !== "undefined" && el.parentNode === elLog) {
// whether CSS transition exists
if (self.transition.supported) {
self.bind(el, self.transition.type, transitionDone);
el.className += " alertify-log-hide";
} else {
elLog.removeChild(el);
if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden";
}
}
};
// never close (until click) if wait is set to 0
if (wait === 0) return;
// set timeout to auto close the log message
setTimeout(function () {hideElement(elem);}, timer);
},
/**
* Create a dialog box
*
* @param {String} message The message passed from the callee
* @param {String} type Type of dialog to create
* @param {Function} fn [Optional] Callback function
* @param {String} placeholder [Optional] Default value for prompt input field
* @param {String} cssClass [Optional] Class(es) to append to dialog box
*
* @return {Object}
*/
dialog: function (message, type, fn, placeholder, cssClass) {
// set the current active element
// this allows the keyboard focus to be resetted
// after the dialog box is closed
elCallee = document.activeElement;
// check to ensure the alertify dialog element
// has been successfully created
var check = function () {
if (elLog && elLog.scrollTop !== null && elCover && elCover.scrollTop !== null) return;else
check();
};
// error catching
if (typeof message !== "string") throw new Error("message must be a string");
if (typeof type !== "string") throw new Error("type must be a string");
if (typeof fn !== "undefined" && typeof fn !== "function") throw new Error("fn must be a function");
// initialize alertify if it hasn't already been done
this.init();
check();
queue.push({ type: type, message: message, callback: fn, placeholder: placeholder, cssClass: cssClass });
if (!isopen) this.setup();
return this;
},
/**
* Extend the log method to create custom methods
*
* @param {String} type Custom method name
*
* @return {Function}
*/
extend: function (type) {
if (typeof type !== "string") throw new Error("extend method must have exactly one paramter");
return function (message, wait) {
this.log(message, type, wait);
return this;
};
},
/**
* Hide the dialog and rest to defaults
*
* @return {undefined}
*/
hide: function () {
var transitionDone,
self = this;
// remove reference from queue
queue.splice(0, 1);
// if items remaining in the queue
if (queue.length > 0) this.setup(true);else
{
isopen = false;
// Hide the dialog box after transition
// This ensure it doens't block any element from being clicked
transitionDone = function (event) {
event.stopPropagation();
// unbind event so function only gets called once
self.unbind(elDialog, self.transition.type, transitionDone);
};
// whether CSS transition exists
if (this.transition.supported) {
this.bind(elDialog, this.transition.type, transitionDone);
elDialog.className = "alertify alertify-hide alertify-hidden";
} else {
elDialog.className = "alertify alertify-hide alertify-hidden alertify-isHidden";
}
elCover.className = "alertify-cover alertify-cover-hidden";
// set focus to the last element or body
// after the dialog is closed
elCallee.focus();
}
},
/**
* Initialize Alertify
* Create the 2 main elements
*
* @return {undefined}
*/
init: function () {
// ensure legacy browsers support html5 tags
document.createElement("nav");
document.createElement("article");
document.createElement("section");
// cover
if ($("alertify-cover") == null) {
elCover = document.createElement("div");
elCover.setAttribute("id", "alertify-cover");
elCover.className = "alertify-cover alertify-cover-hidden";
document.body.appendChild(elCover);
}
// main element
if ($("alertify") == null) {
isopen = false;
queue = [];
elDialog = document.createElement("section");
elDialog.setAttribute("id", "alertify");
elDialog.className = "alertify alertify-hidden";
document.body.appendChild(elDialog);
}
// log element
if ($("alertify-logs") == null) {
elLog = document.createElement("section");
elLog.setAttribute("id", "alertify-logs");
elLog.className = "alertify-logs alertify-logs-hidden";
document.body.appendChild(elLog);
}
// set tabindex attribute on body element
// this allows script to give it focus
// after the dialog is closed
document.body.setAttribute("tabindex", "0");
// set transition type
this.transition = getTransitionEvent();
},
/**
* Show a new log message box
*
* @param {String} message The message passed from the callee
* @param {String} type [Optional] Optional type of log message
* @param {Number} wait [Optional] Time (in ms) to wait before auto-hiding the log
*
* @return {Object}
*/
log: function (message, type, wait) {
// check to ensure the alertify dialog element
// has been successfully created
var check = function () {
if (elLog && elLog.scrollTop !== null) return;else
check();
};
// initialize alertify if it hasn't already been done
this.init();
check();
elLog.className = "alertify-logs";
this.notify(message, type, wait);
return this;
},
/**
* Add new log message
* If a type is passed, a class name "alertify-log-{type}" will get added.
* This allows for custom look and feel for various types of notifications.
*
* @param {String} message The message passed from the callee
* @param {String} type [Optional] Type of log message
* @param {Number} wait [Optional] Time (in ms) to wait before auto-hiding
*
* @return {undefined}
*/
notify: function (message, type, wait) {
var log = document.createElement("article");
log.className = "alertify-log" + (typeof type === "string" && type !== "" ? " alertify-log-" + type : "");
log.innerHTML = message;
// append child
elLog.appendChild(log);
// triggers the CSS animation
setTimeout(function () {log.className = log.className + " alertify-log-show";}, 50);
this.close(log, wait);
},
/**
* Set properties
*
* @param {Object} args Passing parameters
*
* @return {undefined}
*/
set: function (args) {
var k;
// error catching
if (typeof args !== "object" && args instanceof Array) throw new Error("args must be an object");
// set parameters
for (k in args) {
if (args.hasOwnProperty(k)) {
this[k] = args[k];
}
}
},
/**
* Common place to set focus to proper element
*
* @return {undefined}
*/
setFocus: function () {
if (input) {
input.focus();
input.select();
} else
btnFocus.focus();
},
/**
* Initiate all the required pieces for the dialog box
*
* @return {undefined}
*/
setup: function (fromQueue) {
var item = queue[0],
self = this,
transitionDone;
// dialog is open
isopen = true;
// Set button focus after transition
transitionDone = function (event) {
event.stopPropagation();
self.setFocus();
// unbind event so function only gets called once
self.unbind(elDialog, self.transition.type, transitionDone);
};
// whether CSS transition exists
if (this.transition.supported && !fromQueue) {
this.bind(elDialog, this.transition.type, transitionDone);
}
// build the proper dialog HTML
elDialog.innerHTML = this.build(item);
// assign all the common elements
btnReset = $("alertify-resetFocus");
btnResetBack = $("alertify-resetFocusBack");
btnOK = $("alertify-ok") || undefined;
btnCancel = $("alertify-cancel") || undefined;
btnFocus = _alertify.buttonFocus === "cancel" ? btnCancel : _alertify.buttonFocus === "none" ? $("alertify-noneFocus") : btnOK,
input = $("alertify-text") || undefined;
form = $("alertify-form") || undefined;
// add placeholder value to the input field
if (typeof item.placeholder === "string" && item.placeholder !== "") input.value = item.placeholder;
if (fromQueue) this.setFocus();
this.addListeners(item.callback);
},
/**
* Unbind events to elements
*
* @param {Object} el HTML Object
* @param {Event} event Event to detach to element
* @param {Function} fn Callback function
*
* @return {undefined}
*/
unbind: function (el, event, fn) {
if (typeof el.removeEventListener === "function") {
el.removeEventListener(event, fn, false);
} else if (el.detachEvent) {
el.detachEvent("on" + event, fn);
}
} };
return {
alert: function (message, fn, cssClass) {_alertify.dialog(message, "alert", fn, "", cssClass);return this;},
confirm: function (message, fn, cssClass) {_alertify.dialog(message, "confirm", fn, "", cssClass);return this;},
extend: _alertify.extend,
init: _alertify.init,
log: function (message, type, wait) {_alertify.log(message, type, wait);return this;},
prompt: function (message, fn, placeholder, cssClass) {_alertify.dialog(message, "prompt", fn, placeholder, cssClass);return this;},
success: function (message, wait) {_alertify.log(message, "success", wait);return this;},
error: function (message, wait) {_alertify.log(message, "error", wait);return this;},
set: function (args) {_alertify.set(args);},
labels: _alertify.labels,
debug: _alertify.handleErrors };
};
// AMD and window support
if (typeof define === "function") {
define([], function () {return new Alertify();});
} else if (typeof global.alertify === "undefined") {
global.alertify = new Alertify();
}
})(this);
$('button.success').click(function () {
alertify.set({ delay: 1700 });
alertify.success("Success notification");
});
$('button.alert').click(function () {
alertify.set({ delay: 1700 });
alertify.error("Error notification");
});