PageSourceSearch

https://africanlit.org/wordpress/wp-content/plugins/file-away/lib/js/filertify.js?ver=0.3.11

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