mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	
		
			
	
	
		
			266 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			266 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /*********************************************** | ||
|  | 
 | ||
|  |  "toast.js" | ||
|  | 
 | ||
|  |  Created by Michael Cheng on 05/31/2015 22:34 | ||
|  |  http://michaelcheng.us/
 | ||
|  |  michael@michaelcheng.us | ||
|  |  --All Rights Reserved-- | ||
|  | 
 | ||
|  |  ***********************************************/ | ||
|  | 
 | ||
|  | 'use strict'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * The Toast animation speed; how long the Toast takes to move to and from the screen | ||
|  |  * @type {Number} | ||
|  |  */ | ||
|  | const TOAST_ANIMATION_SPEED = 400; | ||
|  | 
 | ||
|  | const Transitions = { | ||
|  |     SHOW: { | ||
|  |         '-webkit-transition': 'opacity ' + TOAST_ANIMATION_SPEED + 'ms, -webkit-transform ' + TOAST_ANIMATION_SPEED + 'ms', | ||
|  |         'transition': 'opacity ' + TOAST_ANIMATION_SPEED + 'ms, transform ' + TOAST_ANIMATION_SPEED + 'ms', | ||
|  |         'opacity': '1', | ||
|  |         '-webkit-transform': 'translateY(-100%) translateZ(0)', | ||
|  |         'transform': 'translateY(-100%) translateZ(0)' | ||
|  |     }, | ||
|  | 
 | ||
|  |     HIDE: { | ||
|  |         'opacity': '0', | ||
|  |         '-webkit-transform': 'translateY(150%) translateZ(0)', | ||
|  |         'transform': 'translateY(150%) translateZ(0)' | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * The main Toast object | ||
|  |  * @param {String} text    The text to put inside the Toast | ||
|  |  * @param {Object} options Optional; the Toast options. See Toast.prototype.DEFAULT_SETTINGS for more information | ||
|  |  * @param {Object} transitions Optional; the Transitions object. This should not be used unless you know what you're doing | ||
|  |  */ | ||
|  | function Toast(text, options, transitions) { | ||
|  |     if(getToastStage() !== null) { | ||
|  |         // If there is already a Toast being shown, put this Toast in the queue to show later
 | ||
|  |         Toast.prototype.toastQueue.push({ | ||
|  |             text: text, | ||
|  |             options: options, | ||
|  |             transitions: transitions | ||
|  |         }); | ||
|  |     } else { | ||
|  |         Toast.prototype.Transitions = transitions || Transitions; | ||
|  |         var _options = options || {}; | ||
|  |         _options = Toast.prototype.mergeOptions(Toast.prototype.DEFAULT_SETTINGS, _options); | ||
|  | 
 | ||
|  |         Toast.prototype.show(text, _options); | ||
|  | 
 | ||
|  |         _options = null; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * The toastStage. This is the HTML element in which the toast resides | ||
|  |  * Getter and setter methods are available privately | ||
|  |  * @type {Element} | ||
|  |  */ | ||
|  | var _toastStage = null; | ||
|  | function getToastStage() { | ||
|  |     return _toastStage; | ||
|  | } | ||
|  | function setToastStage(toastStage) { | ||
|  |     _toastStage = toastStage; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | // define some Toast constants
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * The default Toast settings | ||
|  |  * @type {Object} | ||
|  |  */ | ||
|  | Toast.prototype.DEFAULT_SETTINGS = { | ||
|  |     style: { | ||
|  |         main: { | ||
|  |             'background': 'rgba(0, 0, 0, .8)', | ||
|  |             'box-shadow': '0 0 10px rgba(0, 0, 0, .8)', | ||
|  | 
 | ||
|  |             'border-radius': '3px', | ||
|  | 
 | ||
|  |             'z-index': '99999', | ||
|  | 
 | ||
|  |             'color': 'rgba(255, 255, 255, .9)', | ||
|  | 
 | ||
|  |             'padding': '10px 15px', | ||
|  |             'max-width': '60%', | ||
|  |             'width': '100%', | ||
|  |             'word-break': 'keep-all', | ||
|  |             'margin': '0 auto', | ||
|  |             'text-align': 'center', | ||
|  | 
 | ||
|  |             'position': 'fixed', | ||
|  |             'left': '0', | ||
|  |             'right': '0', | ||
|  |             'bottom': '0', | ||
|  | 
 | ||
|  |             '-webkit-transform': 'translateY(150%) translateZ(0)', | ||
|  |             'transform': 'translateY(150%) translateZ(0)', | ||
|  |             '-webkit-filter': 'blur(0)', | ||
|  |             'opacity': '0' | ||
|  |         } | ||
|  |     }, | ||
|  | 
 | ||
|  |     settings: { | ||
|  |         duration: 4000 | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | Toast.prototype.Transitions = {}; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * The queue of Toasts waiting to be shown | ||
|  |  * @type {Array} | ||
|  |  */ | ||
|  | Toast.prototype.toastQueue = []; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * The Timeout object for animations. | ||
|  |  * This should be shared among the Toasts, because timeouts may be cancelled e.g. on explicit call of hide() | ||
|  |  * @type {Object} | ||
|  |  */ | ||
|  | Toast.prototype.timeout = null; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Merge the DEFAULT_SETTINGS with the user defined options if specified | ||
|  |  * @param  {Object} options The user defined options | ||
|  |  */ | ||
|  | Toast.prototype.mergeOptions = function(initialOptions, customOptions) { | ||
|  |     var merged = customOptions; | ||
|  |     for(var prop in initialOptions) { | ||
|  |         if(merged.hasOwnProperty(prop)) { | ||
|  |             if(initialOptions[prop] !== null && initialOptions[prop].constructor === Object) { | ||
|  |                 merged[prop] = Toast.prototype.mergeOptions(initialOptions[prop], merged[prop]); | ||
|  |             } | ||
|  |         } else { | ||
|  |             merged[prop] = initialOptions[prop]; | ||
|  |         } | ||
|  |     } | ||
|  |     return merged; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Generate the Toast with the specified text. | ||
|  |  * @param  {String|Object} text    The text to show inside the Toast, can be an HTML element or plain text | ||
|  |  * @param  {Object} style   The style to set for the Toast | ||
|  |  */ | ||
|  | Toast.prototype.generate = function(text, style) { | ||
|  |     var toastStage = document.createElement('div'); | ||
|  | 
 | ||
|  | 
 | ||
|  |     /** | ||
|  |      * If the text is a String, create a textNode for appending | ||
|  |      */ | ||
|  |     if(typeof text === 'string') { | ||
|  |         text = document.createTextNode(text); | ||
|  |     } | ||
|  |     toastStage.appendChild(text); | ||
|  | 
 | ||
|  | 
 | ||
|  |     setToastStage(toastStage); | ||
|  |     toastStage = null; | ||
|  | 
 | ||
|  |     Toast.prototype.stylize(getToastStage(), style); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Stylize the Toast. | ||
|  |  * @param  {Element} element The HTML element to stylize | ||
|  |  * @param  {Object}  styles  An object containing the style to apply | ||
|  |  * @return                   Returns nothing | ||
|  |  */ | ||
|  | Toast.prototype.stylize = function(element, styles) { | ||
|  |     Object.keys(styles).forEach(function(style) { | ||
|  |         element.style[style] = styles[style]; | ||
|  |     }); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Show the Toast | ||
|  |  * @param  {String} text    The text to show inside the Toast | ||
|  |  * @param  {Object} options The object containing the options for the Toast | ||
|  |  */ | ||
|  | Toast.prototype.show = function(text, options) { | ||
|  |     this.generate(text, options.style.main); | ||
|  | 
 | ||
|  |     var toastStage = getToastStage(); | ||
|  |     document.body.insertBefore(toastStage, document.body.firstChild); | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  |     // This is a hack to get animations started. Apparently without explicitly redrawing, it'll just attach the class and no animations would be done
 | ||
|  |     toastStage.offsetHeight; | ||
|  | 
 | ||
|  | 
 | ||
|  |     Toast.prototype.stylize(toastStage, Toast.prototype.Transitions.SHOW); | ||
|  | 
 | ||
|  | 
 | ||
|  |     toastStage = null; | ||
|  | 
 | ||
|  | 
 | ||
|  |     // Hide the Toast after the specified time
 | ||
|  |     clearTimeout(Toast.prototype.timeout); | ||
|  |     Toast.prototype.timeout = setTimeout(Toast.prototype.hide, options.settings.duration); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Hide the Toast that's currently shown | ||
|  |  */ | ||
|  | Toast.prototype.hide = function() { | ||
|  |     var toastStage = getToastStage(); | ||
|  |     Toast.prototype.stylize(toastStage, Toast.prototype.Transitions.HIDE); | ||
|  | 
 | ||
|  |     // Destroy the Toast element after animations end
 | ||
|  |     clearTimeout(Toast.prototype.timeout); | ||
|  |     toastStage.addEventListener('transitionend', Toast.prototype.animationListener); | ||
|  |     toastStage = null; | ||
|  | }; | ||
|  | 
 | ||
|  | Toast.prototype.animationListener = function() { | ||
|  |     getToastStage().removeEventListener('transitionend', Toast.prototype.animationListener); | ||
|  |     Toast.prototype.destroy.call(this); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Clean up after the Toast slides away. Namely, removing the Toast from the DOM. After the Toast is cleaned up, display the next Toast in the queue if any exists | ||
|  |  */ | ||
|  | Toast.prototype.destroy = function() { | ||
|  |     var toastStage = getToastStage(); | ||
|  |     document.body.removeChild(toastStage); | ||
|  | 
 | ||
|  |     toastStage = null; | ||
|  |     setToastStage(null); | ||
|  | 
 | ||
|  | 
 | ||
|  |     if(Toast.prototype.toastQueue.length > 0) { | ||
|  |         // Show the rest of the Toasts in the queue if they exist
 | ||
|  | 
 | ||
|  |         var toast = Toast.prototype.toastQueue.shift(); | ||
|  |         Toast(toast.text, toast.options, toast.transitions); | ||
|  | 
 | ||
|  |         // clean up
 | ||
|  |         toast = null; | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | window.showToast = Toast; | ||
|  | 
 | ||
|  | "END OF FILE"; // to avoid "result is non-structured-clonable data"
 |