/public/assets-dev/js/2.alertify/alertify.js
https://github.com/lixiaokai2008/nested-sets-laravel-jquery · JavaScript · 636 lines · 351 code · 54 blank · 231 comment · 90 complexity · a968bbbb314368147fa922aae7b64de4 MD5 · raw file
- /**
- * alertify
- * An unobtrusive customizable JavaScript notification system
- *
- * @author Fabien Doiron <fabien.doiron@gmail.com>
- * @copyright Fabien Doiron 2013
- * @license MIT <http://opensource.org/licenses/mit-license.php>
- * @link http://fabien-d.github.com/alertify.js/
- * @module alertify
- * @version 0.3.11
- */
- (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));