Support custom date and time formats

master
Anton 2024-08-07 15:20:13 +02:00
parent 16d4911972
commit fce8ef2d12
1 changed files with 132 additions and 30 deletions

View File

@ -3,8 +3,9 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="../../css/spectre.min.css"> <link rel="stylesheet" href="../../css/spectre.min.css">
<style> <style>
table { width:100%;} table {width:100%;margin-top:3%;}
.table_t {font-weight:bold;width:40%;}; .table_t {font-weight:bold;width:40%;}
.form-group > * {display:block;}
</style> </style>
</head> </head>
<body> <body>
@ -15,13 +16,15 @@
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<input id="translations" type="checkbox" /> <label for="translations">Add common language translations like "Yes", "No", "On", "Off"<br/><i>(Not recommended. For translations use the option under <code>More...</code> in the app loader.</i></label> <label><input id="translations" type="checkbox" /> Add common language translations like "Yes", "No", "On", "Off"<br/><i>(Not recommended. For translations use the option under <code>More...</code> in the app loader.</i></label>
<label><input id="customize" type="checkbox" /> Advanced: Customize the date and time formats.</label>
</div> </div>
<p> <p>
<table id="examples"> <span id="customize-warning"></span>
<table id="examples-short-long"></table>
<table id="examples"></table>
</p> </p>
</table>
<p>Then click <button id="upload" class="btn btn-primary">Upload</button></p> <p>Then click <button id="upload" class="btn btn-primary">Upload</button></p>
<script src="../../core/lib/customize.js"></script> <script src="../../core/lib/customize.js"></script>
@ -125,15 +128,14 @@ exports = { name : "system", currencySym:"£",
}); });
function createLocaleModule(lang) { function createLocaleModule() {
console.log(`Language ${lang}`); console.log(`Language ${lang}`);
const translations = document.getElementById('translations').checked; const translations = document.getElementById('translations').checked;
console.log(`Translations: ${translations}`); console.log(`Translations: ${translations}`);
const locale = locales[lang];
if (!locale) { if (!locale) {
alert(`Language ${lang} not found!`); alert(`Locale not set for language ${lang}!`);
return; return;
} }
@ -185,16 +187,10 @@ exports = { name : "system", currencySym:"£",
"%P": `d.getHours()<12?${js(locale.ampm[0].toLowerCase())}:${js(locale.ampm[1].toLowerCase())}` "%P": `d.getHours()<12?${js(locale.ampm[0].toLowerCase())}:${js(locale.ampm[1].toLowerCase())}`
}; };
var timeN = locale.timePattern[0]; var timeN = patternToCode(locale.timePattern[0]);
var timeS = locale.timePattern[1]; var timeS = patternToCode(locale.timePattern[1]);
var dateN = locale.datePattern[0]; var dateN = patternToCode(locale.datePattern[0]);
var dateS = locale.datePattern[1]; var dateS = patternToCode(locale.datePattern[1]);
Object.keys(replaceList).forEach(e => {
timeN = timeN.replace(e,"${"+replaceList[e]+"}");
timeS = timeS.replace(e,"${"+replaceList[e]+"}");
dateN = dateN.replace(e,"${"+replaceList[e]+"}");
dateS = dateS.replace(e,"${"+replaceList[e]+"}");
});
var temperature = locale.temperature=='°F' ? '(t*9/5)+32' : 't'; var temperature = locale.temperature=='°F' ? '(t*9/5)+32' : 't';
function getLocaleModule(isLocal) { function getLocaleModule(isLocal) {
@ -246,22 +242,121 @@ exports = {
eval(getLocaleModule(true)); eval(getLocaleModule(true));
console.log("exports:",exports); console.log("exports:",exports);
function patternToCode(pattern){
for(const symbol of Object.keys(replaceList)){
pattern = pattern.replaceAll(symbol,"${"+replaceList[symbol]+"}");
}
return pattern;
}
function patternToOutput(pattern){
const code = patternToCode(pattern);
const result = eval(`let d = new Date();\`${code}\``);
return result;
}
function dataList(id, options, formatter){
let output = `<datalist id="${id}">`;
for(const option of options){
const formatted = formatter?.(option) || option;
output+=`\n<option value="${option}">${formatted}</option>`
}
output += "\n</datalist>";
return output;
}
var date = new Date(); var date = new Date();
document.getElementById("examples").innerHTML = ` // TODO: This warning should have a link to an article explaining how the formats work, and how long they are allowed to be
document.getElementById("customize-warning").innerText = customizeLocale ? "⚠️ If you make the formats too long, some apps will not work!" : "";
document.getElementById("examples-short-long").innerHTML = `
<tr><td class="table_t"></td><td style="font-weight:bold">Short</td><td style="font-weight:bold">Long</td></tr> <tr><td class="table_t"></td><td style="font-weight:bold">Short</td><td style="font-weight:bold">Long</td></tr>
<tr><td class="table_t">Day</td><td>${exports.dow(date,1)}</td><td>${exports.dow(date,0)}</td></tr> <tr><td class="table_t">Day</td><td>${exports.dow(date,1)}</td><td>${exports.dow(date,0)}</td></tr>
<tr><td class="table_t">Month</td><td>${exports.month(date,1)}</td><td>${exports.month(date,0)}</td></tr> <tr><td class="table_t">Month</td><td>${exports.month(date,1)}</td><td>${exports.month(date,0)}</td></tr>
<tr><td class="table_t">Date</td><td>${exports.date(date,1)}</td><td>${exports.date(date,0)}</td></tr> <tr><td class="table_t">Date</td>
<tr><td class="table_t">Time</td><td>${exports.time(date,1)}</td><td>${exports.time(date,0)}</td></tr> <td id="short-date-pattern-output">${exports.date(date,1)}</td>
<tr><td class="table_t">Number</td><td>${exports.number(12.3456789)}</td><td>${exports.number(12.3456789,4)}</td></tr> <td id="long-date-pattern-output">${exports.date(date,0)}</td>
<tr><td class="table_t">Distance</td><td>${exports.distance(12.34,0)}</td><td>${exports.distance(12345.6,1)}</td></tr> </tr>
<tr><td class="table_t">Speed</td><td></td><td>${exports.speed(123)}</td></tr> ${customizeLocale ? `<tr><td class="table_t">Date format</td>
<tr><td class="table_t">Temperature</td><td></td><td>${exports.temp(12,0)}</td></tr> <td>
<input type=text id="short-date-pattern" list="short-date-patterns" value="${locale?.datePattern["1"]}"/>
${dataList("short-date-patterns", [locale?.datePattern["1"], "%-d.%-m.%y", "%-d/%-m/%y", "%d/%m/%Y"], patternToOutput)}
</td>
<td>
<input type=text id="long-date-pattern" list="long-date-patterns" value="${locale?.datePattern["0"]}"/>
${dataList("long-date-patterns", [locale?.datePattern["0"], "%-d. %b %Y", "%b %d, %Y"], patternToOutput)}
</td>
</td>`
: ""}
<tr><td class="table_t">Time</td>
<td id="short-time-pattern-output">${exports.time(date,1)}</td>
<td id="long-time-pattern-output">${exports.time(date,0)}</td>
</tr>
${customizeLocale ? `<tr><td class="table_t">Time format</td>
<td>
<input type=text id="short-time-pattern" list="short-time-patterns" value="${locale?.timePattern["1"]}"/>
${dataList("short-time-patterns", [ "%HH.%MM", "%HH:%MM"], patternToOutput)}
</td>
<td>
<input type=text id="long-time-pattern" list="long-time-patterns" value="${locale?.timePattern["0"]}"/>
${dataList("long-time-patterns", [locale?.timePattern["0"], "%HH.%MM.%SS", "%HH:%MM:%SS"], patternToOutput)}
</td>
</td>`
: ""}
<tr><td class="table_t">Number</td><td>${exports.number(12.3456789)}</td><td>${exports.number(12.3456789,4)}</td></tr>
<tr><td class="table_t">Distance</td><td>${exports.distance(12.34,0)}</td><td>${exports.distance(12345.6,1)}</td></tr>
`; `;
document.getElementById("examples").innerHTML = `
<tr><td class="table_t">Meridian</td><td>
<span id="meridian-am-output">${exports.meridian(new Date(0))}</span> /
<span id="meridian-pm-output">${exports.meridian(new Date(43200000))}</span>
</td></tr>
${customizeLocale ? `<tr><td class="table_t">Meridian names</td>
<td>
<input type=text id="meridian-am" list="meridian-ams" value="${locale?.ampm["0"]}"/>
${dataList("meridian-ams", [locale?.ampm["0"], "AM"])}
</td>
<td>
<input type=text id="meridian-pm" list="meridian-pms" value="${locale?.ampm["1"]}"/>
${dataList("meridian-pms", [locale?.ampm["1"], "PM"])}
</td>
</tr>`
: ""}
<tr><td class="table_t">Speed</td><td>${exports.speed(123)}</td></tr>
<tr><td class="table_t">Temperature</td><td>${exports.temp(12,0)}</td></tr>
`;
if(customizeLocale){
document.querySelector("input#short-date-pattern").addEventListener("input", event => {
locale.datePattern["1"] = event.target.value;
document.querySelector("td#short-date-pattern-output").innerText = patternToOutput(event.target.value);
});
document.querySelector("input#long-date-pattern").addEventListener("input", event => {
locale.datePattern["0"] = event.target.value;
document.querySelector("td#long-date-pattern-output").innerText = patternToOutput(event.target.value);
});
document.querySelector("input#short-time-pattern").addEventListener("input", event => {
locale.timePattern["1"] = event.target.value;
document.querySelector("td#short-time-pattern-output").innerText = patternToOutput(event.target.value);
});
document.querySelector("input#long-time-pattern").addEventListener("input", event => {
locale.timePattern["0"] = event.target.value;
document.querySelector("td#long-time-pattern-output").innerText = patternToOutput(event.target.value);
});
document.querySelector("input#meridian-am").addEventListener("input", event => {
locale.ampm["0"] = event.target.value;
document.querySelector("span#meridian-am-output").innerText = event.target.value;
});
document.querySelector("input#meridian-pm").addEventListener("input", event => {
locale.ampm["1"] = event.target.value;
document.querySelector("span#meridian-pm-output").innerText = event.target.value;
});
}
return getLocaleModule(false); return getLocaleModule(false);
} }
var lang;
var locale;
var customizeLocale;
var languageSelector = document.getElementById("languages"); var languageSelector = document.getElementById("languages");
var customizeSelector = document.getElementById('customize');
languageSelector.innerHTML = Object.keys(locales).map(l=>{ languageSelector.innerHTML = Object.keys(locales).map(l=>{
var locale = locales[l]; var locale = locales[l];
var localeParts = l.split("_"); // en_GB -> ["en","GB"] var localeParts = l.split("_"); // en_GB -> ["en","GB"]
@ -274,18 +369,25 @@ exports = {
return `<option value="${l}">${icon}${l}${locale.notes?" - "+locale.notes:""}</option>` return `<option value="${l}">${icon}${l}${locale.notes?" - "+locale.notes:""}</option>`
}).join("\n"); }).join("\n");
languageSelector.addEventListener('change', function() { languageSelector.addEventListener('change', function() {
const lang = languageSelector.options[languageSelector.selectedIndex].value; lang = languageSelector.options[languageSelector.selectedIndex].value;
createLocaleModule(lang); locale = locales[lang]
createLocaleModule();
});
customizeSelector.addEventListener('change', function() {
customizeLocale = customizeSelector.checked;
createLocaleModule();
}); });
// initial value // initial value
createLocaleModule(languageSelector.options[languageSelector.selectedIndex].value); lang = languageSelector.options[languageSelector.selectedIndex].value;
locale = locales[lang];
customizeLocale = false;
createLocaleModule();
document.getElementById("upload").addEventListener("click", function() { document.getElementById("upload").addEventListener("click", function() {
const lang = languageSelector.options[languageSelector.selectedIndex].value; var localeModule = createLocaleModule();
var localeModule = createLocaleModule(lang);
console.log("Locale Module is:",localeModule); console.log("Locale Module is:",localeModule);
sendCustomizedApp({ sendCustomizedApp({