mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 15:45:55 +08:00
6f585e1f1d
Need to solve the Intl.RelativeTimeFormat to drop momentjs
178 lines
4.7 KiB
JavaScript
178 lines
4.7 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
|
|
};
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
|
|
let formats = {
|
|
LT : {hour: 'numeric', minute: 'numeric'},
|
|
L : {},
|
|
LL : {year: 'numeric', month: 'short', day: 'numeric'},
|
|
LLL : {year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'},
|
|
LLLL : {weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'},
|
|
'd M': {day: '2-digit', month: 'short'}
|
|
},
|
|
phpFormats = {
|
|
// Day
|
|
d: {day: '2-digit'},
|
|
D: {weekday: 'short'},
|
|
j: {day: 'numeric'},
|
|
l: {weekday: 'long'},
|
|
// N: {},
|
|
// w: {},
|
|
// z: {},
|
|
// Week
|
|
// W: {},
|
|
// Month
|
|
F: {month: 'long'},
|
|
m: {month: '2-digit'},
|
|
M: {month: 'short'},
|
|
n: {month: 'numeric'},
|
|
// t: {},
|
|
// Year
|
|
// L: {},
|
|
// o: {},
|
|
Y: {year: 'numeric'},
|
|
y: {year: '2-digit'},
|
|
// Time
|
|
a: {hour12: true},
|
|
A: {hour12: true},
|
|
g: {hour: 'numeric', hourCycle: 'h12'},
|
|
G: {hour: 'numeric'},
|
|
h: {hour: '2-digit', hourCycle: 'h12'},
|
|
H: {hour: '2-digit'},
|
|
i: {minute: '2-digit'},
|
|
s: {second: '2-digit'},
|
|
u: {fractionalSecondDigits: 3},
|
|
// Timezone
|
|
// O: return UTC ? 'Z' : (d.Z > 0 ? '+' : '-') + pad2(Math.abs(d.Z / 60)) + '00';
|
|
// P: return UTC ? 'Z' : (d.Z > 0 ? '+' : '-') + pad2(Math.abs(d.Z / 60)) + :' + pad2(Math.abs(d.Z % 60));
|
|
// T: return UTC ? 'UTC' : new Date(d.Y, 0, 1).toTimeString().replace(/^.+ \(?([^)]+)\)?$/, '$1');
|
|
Z: {timeZone: 'UTC'}
|
|
// Full Date/Time
|
|
// c: {},
|
|
// r: {},
|
|
// U: {},
|
|
// options.timeZoneName = 'short';
|
|
},
|
|
locale = {
|
|
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;
|
|
|
|
// Simulate PHP's date function
|
|
Date.prototype.format = function (str, UTC) {
|
|
if ('Y-m-d\\TH:i:s' == str) {
|
|
return this.getFullYear() + '-' + pad2(1 + this.getMonth()) + '-' + pad2(this.getDate())
|
|
+ 'T' + pad2(this.getHours()) + ':' + pad2(this.getMinutes()) + ':' + pad2(this.getSeconds());
|
|
}
|
|
let options = {};
|
|
if (formats[str]) {
|
|
options = formats[str];
|
|
} else {
|
|
console.log('Date.format('+str+', '+(UTC?'true':'false')+')');
|
|
if (UTC) {
|
|
str += 'Z';
|
|
}
|
|
let i = str.length;
|
|
while (i--) {
|
|
phpFormats[str[i]] && Object.entries(phpFormats[str[i]]).forEach(([k,v])=>options[k]=v);
|
|
}
|
|
formats[str] = options;
|
|
}
|
|
return new Intl.DateTimeFormat(document.documentElement.lang, options).format(this);
|
|
};
|
|
|
|
// 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);
|