PageSourceSearch

https://artlofthotel.com/cdn/alertify/lib/alertify.js

js artlofthotel.com collected 2026-10-09 00:01:10 UTC 20,015 bytes, 636 lines download raw bytes

1/**
2 * alertify
3 * An unobtrusive customizable JavaScript notification system
4 *
5 * @author Fabien Doiron <[email protected]>
6 * @copyright Fabien Doiron 2013
7 * @license MIT <http://opensource.org/licenses/mit-license.php>
8 * @link http://fabien-d.github.com/alertify.js/
9 * @module alertify
10 * @version 0.3.11
11 */
12(function (global, undefined) {
13	"use strict";
14
15	var document = global.document,
16	    Alertify;
17
18	Alertify = function () {
19
20		var _alertify = {},
21		    dialogs   = {},
22		    isopen    = false,
23		    keys      = { ENTER: 13, ESC: 27, SPACE: 32 },
24		    queue     = [],
25		    $, btnCancel, btnOK, btnReset, btnResetBack, btnFocus, elCallee, elCover, elDialog, elLog, form, input, getTransitionEvent;
26
27		/**
28		 * Markup pieces
29		 * @type {Object}
30		 */
31		dialogs = {
32			buttons : {
33				holder : "<nav class=\"alertify-buttons\">{{buttons}}</nav>",
34				submit : "<button type=\"submit\" class=\"alertify-button alertify-button-ok\" id=\"alertify-ok\">{{ok}}</button>",
35				ok     : "<button class=\"alertify-button alertify-button-ok\" id=\"alertify-ok\">{{ok}}</button>",
36				cancel : "<button class=\"alertify-button alertify-button-cancel\" id=\"alertify-cancel\">{{cancel}}</button>"
37			},
38			input   : "<div class=\"alertify-text-wrapper\"><input type=\"text\" class=\"alertify-text\" id=\"alertify-text\"></div>",
39			message : "<p class=\"alertify-message\">{{message}}</p>",
40			log     : "<article class=\"alertify-log{{class}}\">{{message}}</article>"
41		};
42
43		/**
44		 * Return the proper transitionend event
45		 * @return {String}    Transition type string
46		 */
47		getTransitionEvent = function () {
48			var t,
49			    type,
50			    supported   = false,
51			    el          = document.createElement("fakeelement"),
52			    transitions = {
53				    "WebkitTransition" : "webkitTransitionEnd",
54				    "MozTransition"    : "transitionend",
55				    "OTransition"      : "otransitionend",
56				    "transition"       : "transitionend"
57			    };
58
59			for (t in transitions) {
60				if (el.style[t] !== undefined) {
61					type      = transitions[t];
62					supported = true;
63					break;
64				}
65			}
66
67			return {
68				type      : type,
69				supported : supported
70			};
71		};
72
73		/**
74		 * Shorthand for document.getElementById()
75		 *
76		 * @param  {String} id    A specific element ID
77		 * @return {Object}       HTML element
78		 */
79		$ = function (id) {
80			return document.getElementById(id);
81		};
82
83		/**
84		 * Alertify private object
85		 * @type {Object}
86		 */
87		_alertify = {
88
89			/**
90			 * Labels object
91			 * @type {Object}
92			 */
93			labels : {
94				ok     : "OK",
95				cancel : "Cancel"
96			},
97
98			/**
99			 * Delay number
100			 * @type {Number}
101			 */
102			delay : 5000,
103
104			/**
105			 * Whether buttons are reversed (default is secondary/primary)
106			 * @type {Boolean}
107			 */
108			buttonReverse : false,
109
110			/**
111			 * Which button should be focused by default
112			 * @type {String}	"ok" (default), "cancel", or "none"
113			 */
114			buttonFocus : "ok",
115
116			/**
117			 * Set the transition event on load
118			 * @type {[type]}
119			 */
120			transition : undefined,
121
122			/**
123			 * Set the proper button click events
124			 *
125			 * @param {Function} fn    [Optional] Callback function
126			 *
127			 * @return {undefined}
128			 */
129			addListeners : function (fn) {
130				var hasOK     = (typeof btnOK !== "undefined"),
131				    hasCancel = (typeof btnCancel !== "undefined"),
132				    hasInput  = (typeof input !== "undefined"),
133				    val       = "",
134				    self      = this,
135				    ok, cancel, common, key, reset;
136
137				// ok event handler
138				ok = function (event) {
139					if (typeof event.preventDefault !== "undefined") event.preventDefault();
140					common(event);
141					if (typeof input !== "undefined") val = input.value;
142					if (typeof fn === "function") {
143						if (typeof input !== "undefined") {
144							fn(true, val);
145						}
146						else fn(true);
147					}
148					return false;
149				};
150
151				// cancel event handler
152				cancel = function (event) {
153					if (typeof event.preventDefault !== "undefined") event.preventDefault();
154					common(event);
155					if (typeof fn === "function") fn(false);
156					return false;
157				};
158
159				// common event handler (keyup, ok and cancel)
160				common = function (event) {
161					self.hide();
162					self.unbind(document.body, "keyup", key);
163					self.unbind(btnReset, "focus", reset);
164					if (hasOK) self.unbind(btnOK, "click", ok);
165					if (hasCancel) self.unbind(btnCancel, "click", cancel);
166				};
167
168				// keyup handler
169				key = function (event) {
170					var keyCode = event.keyCode;
171					if ((keyCode === keys.SPACE && !hasInput) || (hasInput && keyCode === keys.ENTER)) ok(event);
172					if (keyCode === keys.ESC && hasCancel) cancel(event);
173				};
174
175				// reset focus to first item in the dialog
176				reset = function (event) {
177					if (hasInput) input.focus();
178					else if (!hasCancel || self.buttonReverse) btnOK.focus();
179					else btnCancel.focus();
180				};
181
182				// handle reset focus link
183				// this ensures that the keyboard focus does not
184				// ever leave the dialog box until an action has
185				// been taken
186				this.bind(btnReset, "focus", reset);
187				this.bind(btnResetBack, "focus", reset);
188				// handle OK click
189				if (hasOK) this.bind(btnOK, "click", ok);
190				// handle Cancel click
191				if (hasCancel) this.bind(btnCancel, "click", cancel);
192				// listen for keys, Cancel => ESC
193				this.bind(document.body, "keyup", key);
194				if (!this.transition.supported) {
195					this.setFocus();
196				}
197			},
198
199			/**
200			 * Bind events to elements
201			 *
202			 * @param  {Object}   el       HTML Object
203			 * @param  {Event}    event    Event to attach to element
204			 * @param  {Function} fn       Callback function
205			 *
206			 * @return {undefined}
207			 */
208			bind : function (el, event, fn) {
209				if (typeof el.addEventListener === "function") {
210					el.addEventListener(event, fn, false);
211				} else if (el.attachEvent) {
212					el.attachEvent("on" + event, fn);
213				}
214			},
215
216			/**
217			 * Use alertify as the global error handler (using window.onerror)
218			 *
219			 * @return {boolean} success
220			 */
221			handleErrors : function () {
222				if (typeof global.onerror !== "undefined") {
223					var self = this;
224					global.onerror = function (msg, url, line) {
225						self.error("[" + msg + " on line " + line + " of " + url + "]", 0);
226					};
227					return true;
228				} else {
229					return false;
230				}
231			},
232
233			/**
234			 * Append button HTML strings
235			 *
236			 * @param {String} secondary    The secondary button HTML string
237			 * @param {String} primary      The primary button HTML string
238			 *
239			 * @return {String}             The appended button HTML strings
240			 */
241			appendButtons : function (secondary, primary) {
242				return this.buttonReverse ? primary + secondary : secondary + primary;
243			},
244
245			/**
246			 * Build the proper message box
247			 *
248			 * @param  {Object} item    Current object in the queue
249			 *
250			 * @return {String}         An HTML string of the message box
251			 */
252			build : function (item) {
253				var html    = "",
254				    type    = item.type,
255				    message = item.message,
256				    css     = item.cssClass || "";
257
258				html += "<div class=\"alertify-dialog\">";
259				html += "<a id=\"alertify-resetFocusBack\" class=\"alertify-resetFocus\" href=\"#\">Reset Focus</a>";
260
261				if (_alertify.buttonFocus === "none") html += "<a href=\"#\" id=\"alertify-noneFocus\" class=\"alertify-hidden\"></a>";
262
263				// doens't require an actual form
264				if (type === "prompt") html += "<div id=\"alertify-form\">";
265
266				html += "<article class=\"alertify-inner\">";
267				html += dialogs.message.replace("{{message}}", message);
268
269				if (type === "prompt") html += dialogs.input;
270
271				html += dialogs.buttons.holder;
272				html += "</article>";
273
274				if (type === "prompt") html += "</div>";
275
276				html += "<a id=\"alertify-resetFocus\" class=\"alertify-resetFocus\" href=\"#\">Reset Focus</a>";
277				html += "</div>";
278
279				switch (type) {
280				case "confirm":
281					html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.ok));
282					html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel);
283					break;
284				case "prompt":
285					html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.submit));
286					html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel);
287					break;
288				case "alert":
289					html = html.replace("{{buttons}}", dialogs.buttons.ok);
290					html = html.replace("{{ok}}", this.labels.ok);
291					break;
292				default:
293					break;
294				}
295
296				elDialog.className = "alertify alertify-" + type + " " + css;
297				elCover.className  = "alertify-cover";
298				return html;
299			},
300
301			/**
302			 * Close the log messages
303			 *
304			 * @param  {Object} elem    HTML Element of log message to close
305			 * @param  {Number} wait    [optional] Time (in ms) to wait before automatically hiding the message, if 0 never hide
306			 *
307			 * @return {undefined}
308			 */
309			close : function (elem, wait) {
310				// Unary Plus: +"2" === 2
311				var timer = (wait && !isNaN(wait)) ? +wait : this.delay,
312				    self  = this,
313				    hideElement, transitionDone;
314
315				// set click event on log messages
316				this.bind(elem, "click", function () {
317					hideElement(elem);
318				});
319				// Hide the dialog box after transition
320				// This ensure it doens't block any element from being clicked
321				transitionDone = function (event) {
322					event.stopPropagation();
323					// unbind event so function only gets called once
324					self.unbind(this, self.transition.type, transitionDone);
325					// remove log message
326					elLog.removeChild(this);
327					if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden";
328				};
329				// this sets the hide class to transition out
330				// or removes the child if css transitions aren't supported
331				hideElement = function (el) {
332					// ensure element exists
333					if (typeof el !== "undefined" && el.parentNode === elLog) {
334						// whether CSS transition exists
335						if (self.transition.supported) {
336							self.bind(el, self.transition.type, transitionDone);
337							el.className += " alertify-log-hide";
338						} else {
339							elLog.removeChild(el);
340							if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden";
341						}
342					}
343				};
344				// never close (until click) if wait is set to 0
345				if (wait === 0) return;
346				// set timeout to auto close the log message
347				setTimeout(function () { hideElement(elem); }, timer);
348			},
349
350			/**
351			 * Create a dialog box
352			 *
353			 * @param  {String}   message        The message passed from the callee
354			 * @param  {String}   type           Type of dialog to create
355			 * @param  {Function} fn             [Optional] Callback function
356			 * @param  {String}   placeholder    [Optional] Default value for prompt input field
357			 * @param  {String}   cssClass       [Optional] Class(es) to append to dialog box
358			 *
359			 * @return {Object}
360			 */
361			dialog : function (message, type, fn, placeholder, cssClass) {
362				// set the current active element
363				// this allows the keyboard focus to be resetted
364				// after the dialog box is closed
365				elCallee = document.activeElement;
366				// check to ensure the alertify dialog element
367				// has been successfully created
368				var check = function () {
369					if ((elLog && elLog.scrollTop !== null) && (elCover && elCover.scrollTop !== null)) return;
370					else check();
371				};
372				// error catching
373				if (typeof message !== "string") throw new Error("message must be a string");
374				if (typeof type !== "string") throw new Error("type must be a string");
375				if (typeof fn !== "undefined" && typeof fn !== "function") throw new Error("fn must be a function");
376				// initialize alertify if it hasn't already been done
377				this.init();
378				check();
379
380				queue.push({ type: type, message: message, callback: fn, placeholder: placeholder, cssClass: cssClass });
381				if (!isopen) this.setup();
382
383				return this;
384			},
385
386			/**
387			 * Extend the log method to create custom methods
388			 *
389			 * @param  {String} type    Custom method name
390			 *
391			 * @return {Function}
392			 */
393			extend : function (type) {
394				if (typeof type !== "string") throw new Error("extend method must have exactly one paramter");
395				return function (message, wait) {
396					this.log(message, type, wait);
397					return this;
398				};
399			},
400
401			/**
402			 * Hide the dialog and rest to defaults
403			 *
404			 * @return {undefined}
405			 */
406			hide : function () {
407				var transitionDone,
408				    self = this;
409				// remove reference from queue
410				queue.splice(0,1);
411				// if items remaining in the queue
412				if (queue.length > 0) this.setup(true);
413				else {
414					isopen = false;
415					// Hide the dialog box after transition
416					// This ensure it doens't block any element from being clicked
417					transitionDone = function (event) {
418						event.stopPropagation();
419						// unbind event so function only gets called once
420						self.unbind(elDialog, self.transition.type, transitionDone);
421					};
422					// whether CSS transition exists
423					if (this.transition.supported) {
424						this.bind(elDialog, this.transition.type, transitionDone);
425						elDialog.className = "alertify alertify-hide alertify-hidden";
426					} else {
427						elDialog.className = "alertify alertify-hide alertify-hidden alertify-isHidden";
428					}
429					elCover.className  = "alertify-cover alertify-cover-hidden";
430					// set focus to the last element or body
431					// after the dialog is closed
432					elCallee.focus();
433				}
434			},
435
436			/**
437			 * Initialize Alertify
438			 * Create the 2 main elements
439			 *
440			 * @return {undefined}
441			 */
442			init : function () {
443				// ensure legacy browsers support html5 tags
444				document.createElement("nav");
445				document.createElement("article");
446				document.createElement("section");
447				// cover
448				if ($("alertify-cover") == null) {
449					elCover = document.createElement("div");
450					elCover.setAttribute("id", "alertify-cover");
451					elCover.className = "alertify-cover alertify-cover-hidden";
452					document.body.appendChild(elCover);
453				}
454				// main element
455				if ($("alertify") == null) {
456					isopen = false;
457					queue = [];
458					elDialog = document.createElement("section");
459					elDialog.setAttribute("id", "alertify");
460					elDialog.className = "alertify alertify-hidden";
461					document.body.appendChild(elDialog);
462				}
463				// log element
464				if ($("alertify-logs") == null) {
465					elLog = document.createElement("section");
466					elLog.setAttribute("id", "alertify-logs");
467					elLog.className = "alertify-logs alertify-logs-hidden";
468					document.body.appendChild(elLog);
469				}
470				// set tabindex attribute on body element
471				// this allows script to give it focus
472				// after the dialog is closed
473				document.body.setAttribute("tabindex", "0");
474				// set transition type
475				this.transition = getTransitionEvent();
476			},
477
478			/**
479			 * Show a new log message box
480			 *
481			 * @param  {String} message    The message passed from the callee
482			 * @param  {String} type       [Optional] Optional type of log message
483			 * @param  {Number} wait       [Optional] Time (in ms) to wait before auto-hiding the log
484			 *
485			 * @return {Object}
486			 */
487			log : function (message, type, wait) {
488				// check to ensure the alertify dialog element
489				// has been successfully created
490				var check = function () {
491					if (elLog && elLog.scrollTop !== null) return;
492					else check();
493				};
494				// initialize alertify if it hasn't already been done
495				this.init();
496				check();
497
498				elLog.className = "alertify-logs";
499				this.notify(message, type, wait);
500				return this;
501			},
502
503			/**
504			 * Add new log message
505			 * If a type is passed, a class name "alertify-log-{type}" will get added.
506			 * This allows for custom look and feel for various types of notifications.
507			 *
508			 * @param  {String} message    The message passed from the callee
509			 * @param  {String} type       [Optional] Type of log message
510			 * @param  {Number} wait       [Optional] Time (in ms) to wait before auto-hiding
511			 *
512			 * @return {undefined}
513			 */
514			notify : function (message, type, wait) {
515				var log = document.createElement("article");
516				log.className = "alertify-log" + ((typeof type === "string" && type !== "") ? " alertify-log-" + type : "");
517				log.innerHTML = message;
518				// append child
519				elLog.appendChild(log);
520				// triggers the CSS animation
521				setTimeout(function() { log.className = log.className + " alertify-log-show"; }, 50);
522				this.close(log, wait);
523			},
524
525			/**
526			 * Set properties
527			 *
528			 * @param {Object} args     Passing parameters
529			 *
530			 * @return {undefined}
531			 */
532			set : function (args) {
533				var k;
534				// error catching
535				if (typeof args !== "object" && args instanceof Array) throw new Error("args must be an object");
536				// set parameters
537				for (k in args) {
538					if (args.hasOwnProperty(k)) {
539						this[k] = args[k];
540					}
541				}
542			},
543
544			/**
545			 * Common place to set focus to proper element
546			 *
547			 * @return {undefined}
548			 */
549			setFocus : function () {
550				if (input) {
551					input.focus();
552					input.select();
553				}
554				else btnFocus.focus();
555			},
556
557			/**
558			 * Initiate all the required pieces for the dialog box
559			 *
560			 * @return {undefined}
561			 */
562			setup : function (fromQueue) {
563				var item = queue[0],
564				    self = this,
565				    transitionDone;
566
567				// dialog is open
568				isopen = true;
569				// Set button focus after transition
570				transitionDone = function (event) {
571					event.stopPropagation();
572					self.setFocus();
573					// unbind event so function only gets called once
574					self.unbind(elDialog, self.transition.type, transitionDone);
575				};
576				// whether CSS transition exists
577				if (this.transition.supported && !fromQueue) {
578					this.bind(elDialog, this.transition.type, transitionDone);
579				}
580				// build the proper dialog HTML
581				elDialog.innerHTML = this.build(item);
582				// assign all the common elements
583				btnReset  = $("alertify-resetFocus");
584				btnResetBack  = $("alertify-resetFocusBack");
585				btnOK     = $("alertify-ok")     || undefined;
586				btnCancel = $("alertify-cancel") || undefined;
587				btnFocus  = (_alertify.buttonFocus === "cancel") ? btnCancel : ((_alertify.buttonFocus === "none") ? $("alertify-noneFocus") : btnOK),
588				input     = $("alertify-text")   || undefined;
589				form      = $("alertify-form")   || undefined;
590				// add placeholder value to the input field
591				if (typeof item.placeholder === "string" && item.placeholder !== "") input.value = item.placeholder;
592				if (fromQueue) this.setFocus();
593				this.addListeners(item.callback);
594			},
595
596			/**
597			 * Unbind events to elements
598			 *
599			 * @param  {Object}   el       HTML Object
600			 * @param  {Event}    event    Event to detach to element
601			 * @param  {Function} fn       Callback function
602			 *
603			 * @return {undefined}
604			 */
605			unbind : function (el, event, fn) {
606				if (typeof el.removeEventListener === "function") {
607					el.removeEventListener(event, fn, false);
608				} else if (el.detachEvent) {
609					el.detachEvent("on" + event, fn);
610				}
611			}
612		};
613
614		return {
615			alert   : function (message, fn, cssClass) { _alertify.dialog(message, "alert", fn, "", cssClass); return this; },
616			confirm : function (message, fn, cssClass) { _alertify.dialog(message, "confirm", fn, "", cssClass); return this; },
617			extend  : _alertify.extend,
618			init    : _alertify.init,
619			log     : function (message, type, wait) { _alertify.log(message, type, wait); return this; },
620			prompt  : function (message, fn, placeholder, cssClass) { _alertify.dialog(message, "prompt", fn, placeholder, cssClass); return this; },
621			success : function (message, wait) { _alertify.log(message, "success", wait); return this; },
622			error   : function (message, wait) { _alertify.log(message, "error", wait); return this; },
623			set     : function (args) { _alertify.set(args); },
624			labels  : _alertify.labels,
625			debug   : _alertify.handleErrors
626		};
627	};
628
629	// AMD and window support
630	if (typeof define === "function") {
631		define([], function () { return new Alertify(); });
632	} else if (typeof global.alertify === "undefined") {
633		global.alertify = new Alertify();
634	}
635
636}(this));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.