bmsdave-ngalertify
Version:
Angular JS module for Alertify.js
560 lines (481 loc) • 24.1 kB
JavaScript
angular.module("ngAlertify", []).factory("alertify", function() {
"use strict";
// A quick hack to avoid exposing alertify to the window scope.
var module = { exports: true };
// Don't the line below as the alertif.js contents are
// automatically injected here based on the string contents.
(function() {
"use strict";
var TRANSITION_FALLBACK_DURATION = 500;
var hideElement = function(el) {
if (! el) {
return;
}
var removeThis = function() {
if (el && el.parentNode) {
el.parentNode.removeChild(el);
}
};
el.classList.remove("show");
el.classList.add("hide");
el.addEventListener("transitionend", removeThis);
// Fallback for no transitions.
setTimeout(removeThis, TRANSITION_FALLBACK_DURATION);
};
function Alertify() {
/**
* Alertify private object
* @type {Object}
*/
var _alertify = {
parent: document.body,
version: "1.0.11",
defaultOkLabel: "Ok",
okLabel: "Ok",
defaultCancelLabel: "Cancel",
cancelLabel: "Cancel",
defaultMaxLogItems: 2,
maxLogItems: 2,
promptValue: "",
promptPlaceholder: "",
closeLogOnClick: false,
closeLogOnClickDefault: false,
delay: 5000,
defaultDelay: 5000,
logContainerClass: "alertify-logs",
logContainerDefaultClass: "alertify-logs",
dialogs: {
buttons: {
holder: "<nav>{{buttons}}</nav>",
ok: "<button class='ok' tabindex='0'>{{ok}}</button>",
cancel: "<button class='cancel' tabindex='0'>{{cancel}}</button>"
},
input: "<input type='text'>",
message: "<p class='msg'>{{message}}</p>",
log: "<div class='{{class}}'>{{message}}</div>"
},
defaultDialogs: {
buttons: {
holder: "<nav>{{buttons}}</nav>",
ok: "<button class='ok' tabindex='0'>{{ok}}</button>",
cancel: "<button class='cancel' tabindex='0'>{{cancel}}</button>"
},
input: "<input type='text'>",
message: "<p class='msg'>{{message}}</p>",
log: "<div class='{{class}}'>{{message}}</div>"
},
/**
* 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 btnTxt = this.dialogs.buttons.ok;
var html = "<div class='dialog'>" + "<div onclick='event.stopPropagation()'>" + this.dialogs.message.replace("{{message}}", item.message);
if(item.type === "confirm" || item.type === "prompt") {
btnTxt = this.dialogs.buttons.ok + this.dialogs.buttons.cancel;
}
if (item.type === "prompt") {
html += this.dialogs.input;
}
html = (html + this.dialogs.buttons.holder + "</div>" + "</div>")
.replace("{{buttons}}", btnTxt)
.replace("{{ok}}", this.okLabel)
.replace("{{cancel}}", this.cancelLabel);
return html;
},
setCloseLogOnClick: function(bool) {
this.closeLogOnClick = !! bool;
},
/**
* 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) {
if (this.closeLogOnClick) {
elem.addEventListener("click", function() {
hideElement(elem);
});
}
wait = wait && !isNaN(+wait) ? +wait : this.delay;
if (wait < 0) {
hideElement(elem);
} else if(wait > 0) {
setTimeout(function() {
hideElement(elem);
}, wait);
}
},
/**
* Create a dialog box
*
* @param {String} message The message passed from the callee
* @param {String} type Type of dialog to create
* @param {Function} onOkay [Optional] Callback function when clicked okay.
* @param {Function} onCancel [Optional] Callback function when cancelled.
*
* @return {Object}
*/
dialog: function(message, type, onOkay, onCancel) {
return this.setup({
type: type,
message: message,
onOkay: onOkay,
onCancel: onCancel
});
},
/**
* 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, click) {
var existing = document.querySelectorAll(".alertify-logs > div");
if (existing) {
var diff = existing.length - this.maxLogItems;
if (diff >= 0) {
for (var i = 0, _i = diff + 1; i < _i; i++) {
this.close(existing[i], -1);
}
}
}
this.notify(message, type, click);
},
setLogPosition: function(str) {
this.logContainerClass = "alertify-logs " + str;
},
setupLogContainer: function() {
var elLog = document.querySelector(".alertify-logs");
var className = this.logContainerClass;
if (! elLog) {
elLog = document.createElement("div");
elLog.className = className;
this.parent.appendChild(elLog);
}
// Make sure it's positioned properly.
if (elLog.className !== className) {
elLog.className = className;
}
return elLog;
},
/**
* Add new log message
* If a type is passed, a class name "{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, click) {
var elLog = this.setupLogContainer();
var log = document.createElement("div");
log.className = (type || "default");
if (_alertify.logTemplateMethod) {
log.innerHTML = _alertify.logTemplateMethod(message);
} else {
log.innerHTML = message;
}
// Add the click handler, if specified.
if ("function" === typeof click) {
log.addEventListener("click", click);
}
elLog.appendChild(log);
setTimeout(function() {
log.className += " show";
}, 10);
this.close(log, this.delay);
},
/**
* Initiate all the required pieces for the dialog box
*
* @return {undefined}
*/
setup: function(item) {
var el = document.createElement("div");
el.className = "alertify hide";
el.innerHTML = this.build(item);
var btnOK = el.querySelector(".ok");
var btnCancel = el.querySelector(".cancel");
var input = el.querySelector("input");
var label = el.querySelector("label");
// Set default value/placeholder of input
if (input) {
if (typeof this.promptPlaceholder === "string") {
// Set the label, if available, for MDL, etc.
if (label) {
label.textContent = this.promptPlaceholder;
} else {
input.placeholder = this.promptPlaceholder;
}
}
if (typeof this.promptValue === "string") {
input.value = this.promptValue;
}
}
function setupHandlers(resolve) {
if ("function" !== typeof resolve) {
// promises are not available so resolve is a no-op
resolve = function () {};
}
function okHandler(ev) {
if (item.onOkay && "function" === typeof item.onOkay) {
if (input) {
item.onOkay(input.value, ev);
} else {
item.onOkay(ev);
}
}
if (input) {
resolve({
buttonClicked: "ok",
inputValue: input.value,
event: ev
});
} else {
resolve({
buttonClicked: "ok",
event: ev
});
}
hideElement(el);
}
function cancelHandler(ev) {
if (item.onCancel && "function" === typeof item.onCancel) {
item.onCancel(ev);
}
resolve({
buttonClicked: "cancel",
event: ev
});
hideElement(el);
}
if (btnOK) {
btnOK.addEventListener("click", okHandler);
}
if (btnCancel) {
btnCancel.addEventListener("click", cancelHandler);
el.addEventListener("click", cancelHandler);
} else {
el.addEventListener("click", okHandler);
}
if (input) {
input.addEventListener("keyup", function(ev) {
if (ev.currentTarget.value === "") {
btnOK.setAttribute("disabled", "true");
} else {
btnOK.removeAttribute("disabled");
}
if (ev.which === 13) {
btnOK.click();
}
});
}
}
var promise;
if (typeof Promise === "function") {
promise = new Promise(setupHandlers);
} else {
setupHandlers();
}
this.parent.appendChild(el);
setTimeout(function() {
el.classList.remove("hide");
if(input && item.type && item.type === "prompt") {
input.select();
input.focus();
} else {
if (btnOK) {
btnOK.focus();
}
}
}, 100);
return promise;
},
okBtn: function(label) {
this.okLabel = label;
return this;
},
setDelay: function(time) {
time = time || 0;
this.delay = isNaN(time) ? this.defaultDelay : parseInt(time, 10);
return this;
},
cancelBtn: function(str) {
this.cancelLabel = str;
return this;
},
setMaxLogItems: function(num) {
this.maxLogItems = parseInt(num || this.defaultMaxLogItems);
},
theme: function(themeStr) {
switch(themeStr.toLowerCase()) {
case "bootstrap":
this.dialogs.buttons.ok = "<button class='ok btn btn-primary' tabindex='0'>{{ok}}</button>";
this.dialogs.buttons.cancel = "<button class='cancel btn btn-default' tabindex='0'>{{cancel}}</button>";
this.dialogs.input = "<input type='text' class='form-control'>";
break;
case "purecss":
this.dialogs.buttons.ok = "<button class='ok pure-button' tabindex='0'>{{ok}}</button>";
this.dialogs.buttons.cancel = "<button class='cancel pure-button' tabindex='0'>{{cancel}}</button>";
break;
case "mdl":
case "material-design-light":
this.dialogs.buttons.ok = "<button class='ok mdl-button mdl-js-button mdl-js-ripple-effect' tabindex='0'>{{ok}}</button>";
this.dialogs.buttons.cancel = "<button class='cancel mdl-button mdl-js-button mdl-js-ripple-effect' tabindex='0'>{{cancel}}</button>";
this.dialogs.input = "<div class='mdl-textfield mdl-js-textfield'><input class='mdl-textfield__input'><label class='md-textfield__label'></label></div>";
break;
case "angular-material":
this.dialogs.buttons.ok = "<button class='ok md-primary md-button' tabindex='0'>{{ok}}</button>";
this.dialogs.buttons.cancel = "<button class='cancel md-button' tabindex='0'>{{cancel}}</button>";
this.dialogs.input = "<div layout='column'><md-input-container md-no-float><input type='text'></md-input-container></div>";
break;
case "default":
default:
this.dialogs.buttons.ok = this.defaultDialogs.buttons.ok;
this.dialogs.buttons.cancel = this.defaultDialogs.buttons.cancel;
this.dialogs.input = this.defaultDialogs.input;
break;
}
},
reset: function() {
this.parent = document.body;
this.theme("default");
this.okBtn(this.defaultOkLabel);
this.cancelBtn(this.defaultCancelLabel);
this.setMaxLogItems();
this.promptValue = "";
this.promptPlaceholder = "";
this.delay = this.defaultDelay;
this.setCloseLogOnClick(this.closeLogOnClickDefault);
this.setLogPosition("bottom left");
this.logTemplateMethod = null;
},
injectCSS: function() {
if (!document.querySelector("#alertifyCSS")) {
var head = document.getElementsByTagName("head")[0];
var css = document.createElement("style");
css.type = "text/css";
css.id = "alertifyCSS";
css.innerHTML = ".alertify-logs>*{padding:12px 24px;color:#fff;box-shadow:0 2px 5px 0 rgba(0,0,0,.2);border-radius:1px;transition:all .2s;display:block!important}.alertify-logs>*,.alertify-logs>.default{background:rgba(0,0,0,.8)}.alertify-logs>.error{background:rgba(244,67,54,.8)}.alertify-logs>.success{background:rgba(76,175,80,.9)}.alertify{position:fixed;background-color:rgba(0,0,0,.3);left:0;right:0;top:0;bottom:0;width:100%;height:100%;z-index:1}.alertify.hide{opacity:0;pointer-events:none}.alertify,.alertify.show{box-sizing:border-box;transition:all .33s cubic-bezier(.25,.8,.25,1)}.alertify,.alertify *{box-sizing:border-box}.alertify .dialog{padding:12px}.alertify .alert,.alertify .dialog{width:100%;margin:0 auto;position:relative;top:50%;transform:translateY(-50%)}.alertify .alert>*,.alertify .dialog>*{width:400px;max-width:95%;margin:0 auto;text-align:center;padding:12px;background:#fff;box-shadow:0 2px 4px -1px rgba(0,0,0,.14),0 4px 5px 0 rgba(0,0,0,.098),0 1px 10px 0 rgba(0,0,0,.084)}.alertify .alert .msg,.alertify .dialog .msg{padding:12px;margin-bottom:12px;margin:0;text-align:left}.alertify .alert input:not(.form-control),.alertify .dialog input:not(.form-control){margin-bottom:15px;width:100%;font-size:100%;padding:12px}.alertify .alert input:not(.form-control):focus,.alertify .dialog input:not(.form-control):focus{outline-offset:-2px}.alertify .alert nav,.alertify .dialog nav{height:40px;text-align:right}.alertify .alert nav button,.alertify .dialog nav button{float:right;background:transparent;box-sizing:border-box;color:rgba(0,0,0,.87);position:relative;outline:0;border:0;display:block;-ms-flex-align:center;align-items:center;padding:0 6px;margin:6px 8px;line-height:36px;min-height:36px;white-space:nowrap;min-width:88px;text-align:center;text-transform:uppercase;font-size:14px;text-decoration:none;cursor:pointer;border:1px solid transparent;border-radius:2px}.alertify .alert nav button:active,.alertify .alert nav button:hover,.alertify .dialog nav button:active,.alertify .dialog nav button:hover{background-color:rgba(0,0,0,.05)}.alertify .alert nav button:focus,.alertify .dialog nav button:focus{border:1px solid rgba(0,0,0,.1)}.alertify .alert nav button.btn,.alertify .dialog nav button.btn{margin:6px 4px}.alertify .alert nav button[disabled].ok,.alertify .dialog nav button[disabled].ok{color:grey!important}.alertify .alert nav button[disabled].ok:active,.alertify .alert nav button[disabled].ok:hover,.alertify .dialog nav button[disabled].ok:active,.alertify .dialog nav button[disabled].ok:hover{background-color:#fff!important}.alertify .alert nav button[disabled].ok:focus,.alertify .dialog nav button[disabled].ok:focus{border:1px solid #fff!important}.alertify-logs{position:fixed;z-index:1}.alertify-logs.bottom,.alertify-logs:not(.top){bottom:16px}.alertify-logs.left,.alertify-logs:not(.right){left:16px}.alertify-logs.left>*,.alertify-logs:not(.right)>*{float:left;transform:translateZ(0);height:auto}.alertify-logs.left>.show,.alertify-logs:not(.right)>.show{left:0}.alertify-logs.left>*,.alertify-logs.left>.hide,.alertify-logs:not(.right)>*,.alertify-logs:not(.right)>.hide{left:-110%}.alertify-logs.right{right:16px}.alertify-logs.right>*{float:right;transform:translateZ(0)}.alertify-logs.right>.show{right:0;opacity:1}.alertify-logs.right>*,.alertify-logs.right>.hide{right:-110%;opacity:0}.alertify-logs.top{top:0}.alertify-logs>*{box-sizing:border-box;transition:all .4s cubic-bezier(.25,.8,.25,1);position:relative;clear:both;-webkit-backface-visibility:hidden;backface-visibility:hidden;perspective:1000;max-height:0;margin:0;padding:0;overflow:hidden;opacity:0;pointer-events:none}.alertify-logs>.show{margin-top:12px;opacity:1;max-height:1000px;padding:12px;pointer-events:auto}";
head.insertBefore(css, head.firstChild);
}
},
removeCSS: function() {
var css = document.querySelector("#alertifyCSS");
if (css && css.parentNode) {
css.parentNode.removeChild(css);
}
}
};
_alertify.injectCSS();
return {
_$$alertify: _alertify,
parent: function(elem) {
_alertify.parent = elem;
},
reset: function() {
_alertify.reset();
return this;
},
alert: function(message, onOkay, onCancel) {
return _alertify.dialog(message, "alert", onOkay, onCancel) || this;
},
confirm: function(message, onOkay, onCancel) {
return _alertify.dialog(message, "confirm", onOkay, onCancel) || this;
},
prompt: function(message, onOkay, onCancel) {
return _alertify.dialog(message, "prompt", onOkay, onCancel) || this;
},
log: function(message, click) {
_alertify.log(message, "default", click);
return this;
},
theme: function(themeStr) {
_alertify.theme(themeStr);
return this;
},
success: function(message, click) {
_alertify.log(message, "success", click);
return this;
},
error: function(message, click) {
_alertify.log(message, "error", click);
return this;
},
cancelBtn: function(label) {
_alertify.cancelBtn(label);
return this;
},
okBtn: function(label) {
_alertify.okBtn(label);
return this;
},
delay: function(time) {
_alertify.setDelay(time);
return this;
},
placeholder: function(str) {
_alertify.promptPlaceholder = str;
return this;
},
defaultValue: function(str) {
_alertify.promptValue = str;
return this;
},
maxLogItems: function(num) {
_alertify.setMaxLogItems(num);
return this;
},
closeLogOnClick: function(bool) {
_alertify.setCloseLogOnClick(!! bool);
return this;
},
logPosition: function(str) {
_alertify.setLogPosition(str || "");
return this;
},
setLogTemplate: function(templateMethod) {
_alertify.logTemplateMethod = templateMethod;
return this;
},
clearLogs: function() {
_alertify.setupLogContainer().innerHTML = "";
return this;
},
version: _alertify.version
};
}
// AMD, window, and NPM support
if ("undefined" !== typeof module && !! module && !! module.exports) {
// Preserve backwards compatibility
module.exports = function() {
return new Alertify();
};
var obj = new Alertify();
for (var key in obj) {
module.exports[key] = obj[key];
}
} else if (typeof define === "function" && define.amd) {
define(function() {
return new Alertify();
});
} else {
window.alertify = new Alertify();
}
}());
var Alertify = module.exports;
return new Alertify();
});