mirror of
				https://github.com/the-djmaze/snappymail.git
				synced 2025-10-25 21:46:26 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			231 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
 | |
| (w=>{
 | |
| 	Array.isNotEmpty = array => Array.isArray(array) && array.length;
 | |
| 	Array.prototype.unique = function() { return this.filter((v, i, a) => a.indexOf(v) === i); };
 | |
| 	Array.prototype.validUnique = function(fn) {
 | |
| 		return this.filter((v, i, a) => (fn ? fn(v) : v) && a.indexOf(v) === i);
 | |
| 	};
 | |
| 
 | |
| 	// Import momentjs locales function
 | |
| 	w.moment = {
 | |
| 		defineLocale: (name, config)=>{
 | |
| 			locale = config;
 | |
| 			const m = config.monthsShort;
 | |
| 			if (Array.isArray(m)) {
 | |
| 				Date.shortMonths = m;
 | |
| 			} else for (let i = 0; i < 12; ++i) {
 | |
| 				Date.shortMonths[i] = config.monthsShort({month:()=>i}, '-MMM-');
 | |
| 			}
 | |
| 			Date.longMonths = config.months,
 | |
| 			Date.longDays = config.weekdays;
 | |
| 			Date.shortDays = config.weekdaysMin;
 | |
| 		}
 | |
| 	};
 | |
| 
 | |
| 	let locale = {
 | |
| 		longDateFormat: {
 | |
| 			LT   : 'h:mm A', // 'g:i A',
 | |
| 			L    : 'MM/DD/YYYY', // 'Y-m-d',
 | |
| 			LL   : 'MMMM D, YYYY', // 'F j, Y'
 | |
| 			LLL  : 'MMMM D, YYYY h:mm A', // 'F j, Y g:i A'
 | |
| 			LLLL : 'dddd, MMMM D, YYYY h:mm A' // 'l, F j, Y g:i A'
 | |
| 		},
 | |
| 		relativeTime : {
 | |
| 			future : 'in %s',
 | |
| 			past : '%s ago',
 | |
| 			s : 'a few seconds',
 | |
| 			ss : '%d seconds',
 | |
| 			m : 'a minute',
 | |
| 			mm : '%d minutes',
 | |
| 			h : 'an hour',
 | |
| 			hh : '%d hours',
 | |
| 			d : 'a day',
 | |
| 			dd : '%d days',
 | |
| 			M : 'a month',
 | |
| 			MM : '%d months',
 | |
| 			y : 'a year',
 | |
| 			yy : '%d years'
 | |
| 		}
 | |
| 	},
 | |
| 	pad2 = v => 10 > v ? '0' + v : v,
 | |
| 	getISODay = x => x.getDay() || 7,
 | |
| 	getDayOfYear = x => Math.floor((Date.UTC(x.getFullYear(),x.getMonth(),x.getDate())
 | |
| 		- Date.UTC(x.getFullYear(),0,1)) / 86400000),
 | |
| 	getWeek = x => {
 | |
| 		let d = new Date(x.getFullYear(),0,1),
 | |
| 			wd = getISODay(d),
 | |
| 			w = Math.ceil((getDayOfYear(x)+wd) / 7);
 | |
| 		/* ISO 8601 states that week 1 is the week with january 4th in it */
 | |
| 		if (4 < wd) --w;
 | |
| 		return (1 > w
 | |
| 			? getWeek(new Date(x.getFullYear()-1,11,31)) /* previous year, last week */
 | |
| 			: (52 < w && 4 > getISODay(x) ? 1 /* next year, first week */ : w) );
 | |
| 	};
 | |
| 
 | |
| 	// Defining locale
 | |
| 	Date.shortMonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
 | |
| 	Date.longMonths = ['January', 'February', 'March', 'April', 'May', 'June',
 | |
| 		'July', 'August', 'September', 'October', 'November', 'December'];
 | |
| 	Date.shortDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
 | |
| 	Date.longDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
 | |
| 
 | |
| 	// Simulate PHP's date function
 | |
| 	Date.prototype.format = function (str, UTC) {
 | |
| 		if (locale.longDateFormat[str]) {
 | |
| 			str = locale.longDateFormat[str]
 | |
| 				.replace('YYYY', 'Y')
 | |
| 				.replace(/(^|[^M])M([^M]|$)/, '$1n$2')
 | |
| 				.replace('MMMM', 'F')
 | |
| 				.replace('MMM', 'M')
 | |
| 				.replace('MM', 'm')
 | |
| 				.replace(/(^|[^D])D([^D]|$)/, '$1j$2')
 | |
| 				.replace('DD', 'd')
 | |
| 				.replace('dddd', 'l')
 | |
| 				.replace('ddd', 'D')
 | |
| 				.replace('dd', 'D')
 | |
| 				.replace(/(^|[^H])H([^H]|$)/, '$1G$2')
 | |
| 				.replace('HH', 'H')
 | |
| 				.replace('h', 'g')
 | |
| 				.replace('hh', 'h')
 | |
| 				.replace('mm', 'i');
 | |
| 		}
 | |
| 		UTC = UTC || str.match(/\\Z$/);
 | |
| 		let x = this,
 | |
| 			d = UTC ? {
 | |
| 				D: x.getUTCDay(),
 | |
| 				Y: x.getUTCFullYear(),
 | |
| 				m: x.getUTCMonth(),
 | |
| 				d: x.getUTCDate(),
 | |
| 				H: x.getUTCHours(),
 | |
| 				Z: 0
 | |
| 			} : {
 | |
| 				D: x.getDay(),
 | |
| 				Y: x.getFullYear(),
 | |
| 				m: x.getMonth(),
 | |
| 				d: x.getDate(),
 | |
| 				H: x.getHours(),
 | |
| 				Z: -x.getTimezoneOffset()
 | |
| 			};
 | |
| 		return str
 | |
| 			? str.replace(/\\?[a-zA-Z]/g, m => {
 | |
| 				if (m[0] === '\\') { return m[1]; }
 | |
| 				switch (m) {
 | |
| 				// Day
 | |
| 				case 'd': return pad2(d.d);
 | |
| 				case 'D': return Date.shortDays[d.D];
 | |
| 				case 'j': return d.d;
 | |
| 				case 'l': return Date.longDays[d.D];
 | |
| 				case 'N': return getISODay(x);
 | |
| 				case 'w': return d.D;
 | |
| 				case 'z': return getDayOfYear(x);
 | |
| 				// Week
 | |
| 				case 'W': return pad2(getWeek(x));
 | |
| 				// Month
 | |
| 				case 'F': return Date.longMonths[d.m];
 | |
| 				case 'm': return pad2(d.m + 1);
 | |
| 				case 'M': return Date.shortMonths[d.m];
 | |
| 				case 'n': return d.m + 1;
 | |
| 				case 't': return 32 - new Date(x.getFullYear(), x.getMonth(), 32).getDate();
 | |
| 				// Year
 | |
| 				case 'L': return (((d.Y%4===0)&&(d.Y%100 !== 0)) || (d.Y%400===0)) ? '1' : '0';
 | |
| 				case 'o': return new Date(
 | |
| 						x.getFullYear(),
 | |
| 						x.getMonth(),
 | |
| 						x.getDate() - ((x.getDay() + 6) % 7) + 3
 | |
| 					).getFullYear();
 | |
| 				case 'Y': return d.Y;
 | |
| 				case 'y': return ('' + d.Y).substr(2);
 | |
| 				// Time
 | |
| 				case 'a': return d.H < 12 ? "am" : "pm";
 | |
| 				case 'A': return d.H < 12 ? "AM" : "PM";
 | |
| 				case 'g': return d.H % 12 || 12;
 | |
| 				case 'G': return d.H;
 | |
| 				case 'h': return pad2(d.H % 12 || 12);
 | |
| 				case 'H': return pad2(d.H);
 | |
| 				case 'i': return pad2(UTC?x.getUTCMinutes():x.getMinutes());
 | |
| 				case 's': return pad2(UTC?x.getUTCSeconds():x.getSeconds());
 | |
| 				case 'u': return (UTC?x.getUTCMilliseconds():x.getMilliseconds()).toString().padStart(3,'0');
 | |
| 				// Timezone
 | |
| 				case 'O': return UTC ? 'Z' : (d.Z > 0 ? '+' : '-') + pad2(Math.abs(d.Z / 60)) + '00';
 | |
| 				case 'P': return UTC ? 'Z' : (d.Z > 0 ? '+' : '-') + pad2(Math.abs(d.Z / 60)) + ':' + pad2(Math.abs(d.Z % 60));
 | |
| 				case 'T': return UTC ? 'UTC' : new Date(d.Y, 0, 1).toTimeString().replace(/^.+ \(?([^)]+)\)?$/, '$1');
 | |
| 				case 'Z': return d.Z * 60;
 | |
| 				// Full Date/Time
 | |
| 				case 'c': return x.format("Y-m-d\\TH:i:sO");
 | |
| 				case 'r': return x.format("D, d M Y H:i:s O");
 | |
| 				case 'U': return x.getTime() / 1000;
 | |
| 				}
 | |
| 				return m;
 | |
| 			})
 | |
| 			: x.toString();
 | |
| 	};
 | |
| 
 | |
| 	// Simulate momentjs fromNow function
 | |
| 	Date.prototype.fromNow = function() {
 | |
| 		let format = 's',
 | |
| 			seconds = (Date.now() - this.getTime()) / 1000,
 | |
| 			str = locale.relativeTime[0 < seconds ? 'past' : 'future'],
 | |
| 			t = [[60,'m'],[3600,'h'],[86400,'d'],[2628000,'M'],[31536000,'y']],
 | |
| 			i = 5;
 | |
| 		seconds = Math.abs(seconds);
 | |
| 		while (i--) {
 | |
| 			if (t[i][0] <= seconds) {
 | |
| 				seconds = seconds / t[i][0];
 | |
| 				format = t[i][1];
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 		seconds = Math.round(seconds);
 | |
| 		if (1 < seconds) {
 | |
| 			format += format;
 | |
| 		}
 | |
| 		return str.replace('%s', locale.relativeTime[format].replace('%d', seconds));
 | |
| 	};
 | |
| 
 | |
| 	Element.prototype.closestWithin = function(selector, parent) {
 | |
| 		const el = this.closest(selector);
 | |
| 		return (el && el !== parent && parent.contains(el)) ? el : null;
 | |
| 	};
 | |
| 
 | |
| 	Element.fromHTML = string => {
 | |
| 		const template = document.createElement('template');
 | |
| 		template.innerHTML = string.trim();
 | |
| 		return template.content.firstChild;
 | |
| 	};
 | |
| 
 | |
| 	/**
 | |
| 	 * Every time the function is executed,
 | |
| 	 * it will delay the execution with the given amount of milliseconds.
 | |
| 	 */
 | |
| 	if (!Function.prototype.debounce) {
 | |
| 		Function.prototype.debounce = function(ms) {
 | |
| 			let func = this, timer;
 | |
| 			return function(...args) {
 | |
| 				timer && clearTimeout(timer);
 | |
| 				timer = setTimeout(()=>{
 | |
| 					func.apply(this, args)
 | |
| 					timer = 0;
 | |
| 				}, ms);
 | |
| 			};
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * No matter how many times the event is executed,
 | |
| 	 * the function will be executed only once, after the given amount of milliseconds.
 | |
| 	 */
 | |
| 	if (!Function.prototype.throttle) {
 | |
| 		Function.prototype.throttle = function(ms) {
 | |
| 			let func = this, timer;
 | |
| 			return function(...args) {
 | |
| 				if (!timer) {
 | |
| 					timer = setTimeout(()=>{
 | |
| 						func.apply(this, args)
 | |
| 						timer = 0;
 | |
| 					}, ms);
 | |
| 				}
 | |
| 			};
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| })(this);
 |