snappymail/dev/prototype.js
djmaze 6f585e1f1d Use Intl.DateTimeFormat instead of momentjs where we can
Need to solve the Intl.RelativeTimeFormat to drop momentjs
2020-10-15 00:26:40 +02:00

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);