New settings es6 (merge from pbolduc fork) (#3231)
* Initial new settings page test commit * quick poc to add chibi style helper and start to change files to es6 * add ready and loaded functions * added missing pageloaded variable to track if loaded already called. * More POC to dynamically add content, minimal DOM lib based on chibi * Add simple translation for any element that has class=l10n * simply self executing function --------- Co-authored-by: Phil Bolduc <philbolduc@gmail.com>
This commit is contained in:
parent
d383bc93c7
commit
59025e317e
122
tools/wled.js
Normal file
122
tools/wled.js
Normal file
@ -0,0 +1,122 @@
|
||||
|
||||
const express = require("express");
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||||
const path = require("path");
|
||||
const nopt = require("nopt");
|
||||
const app = express();
|
||||
|
||||
var knownOpts = {
|
||||
"help": Boolean,
|
||||
"port": Number,
|
||||
"settings": [path],
|
||||
"host": String,
|
||||
"verbose": Boolean
|
||||
};
|
||||
var shortHands = {
|
||||
"?":["--help"],
|
||||
"p":["--port"],
|
||||
"s":["--settings"],
|
||||
"h":["--host"],
|
||||
"v":["--verbose"]
|
||||
};
|
||||
|
||||
nopt.invalidHandler = function(k,v,t) {
|
||||
// TODO: console.log(k,v,t);
|
||||
}
|
||||
|
||||
var parsedArgs = nopt(knownOpts,shortHands,process.argv,2);
|
||||
|
||||
if (parsedArgs.help) {
|
||||
console.log("WLED Dev Server");
|
||||
console.log("Usage: wled [-v] [-?] [--settings settings.js] [--userDir DIR]");
|
||||
console.log(" [--port PORT] [--host HOST]");
|
||||
console.log("");
|
||||
console.log("Options:");
|
||||
console.log(" -p, --port PORT port to listen on");
|
||||
console.log(" -s, --settings FILE use specified settings file");
|
||||
console.log(" --host HOST WLED instance for dynamic content");
|
||||
console.log(" -v, --verbose enable verbose output");
|
||||
console.log(" -?, --help show this help");
|
||||
console.log("");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
// WLED_HOME - the root directory where the html files are
|
||||
process.env.WLED_HOME = process.env.WLED_HOME || path.resolve(__dirname,'..','wled00','data');
|
||||
|
||||
parsedArgs.port = parsedArgs.port || 8080;
|
||||
parsedArgs.host = parsedArgs.host || "0.0.0.0";
|
||||
|
||||
// get the static file reference
|
||||
function static(page) {
|
||||
return express.static(process.env.WLED_HOME, {index: page});
|
||||
}
|
||||
|
||||
// add routes for each setting page
|
||||
function useSettingsRoutes() {
|
||||
app.use(`/settings`, static(`settings.htm`));
|
||||
|
||||
const settings = ['wifi', 'leds', 'ui', 'sync','time','um', 'sec'];
|
||||
settings.forEach(function(setting) {
|
||||
app.use(`/settings/${setting}`, static(`settings_${setting}.htm`));
|
||||
});
|
||||
}
|
||||
|
||||
// dynamic content that is proxied to real WLED instance
|
||||
function useWebProxyRoutes(host) {
|
||||
const httpProxy = createProxyMiddleware({ target: `http://${host}`, changeOrigin: true, logLevel: 'warn' });
|
||||
const proxyRoutes = ['json', 'presets.json', 'skins.css', 'liveview'];
|
||||
proxyRoutes.forEach(function(route) {
|
||||
app.use(`/${route}`, httpProxy);
|
||||
});
|
||||
}
|
||||
|
||||
// proxy data to a real WLED instance
|
||||
function useWebSocketProxy(host, server) {
|
||||
const wsProxy = createProxyMiddleware(`ws://${host}`, { changeOrigin: true, logLevel: 'warn' });
|
||||
app.use(wsProxy);
|
||||
server.on('upgrade', wsProxy.upgrade);
|
||||
}
|
||||
|
||||
// first matching route
|
||||
app.use('/', static("index.htm"));
|
||||
useSettingsRoutes(); // map the setting pages
|
||||
useWebProxyRoutes(parsedArgs.host);
|
||||
|
||||
// use static files like style sheets etc
|
||||
app.use(express.static(process.env.WLED_HOME));
|
||||
|
||||
const server = app.listen(parsedArgs.port, () => {
|
||||
if (parsedArgs.verbose) {
|
||||
console.log(`WLED UI listening at http://localhost:${parsedArgs.port}`)
|
||||
}
|
||||
});
|
||||
|
||||
useWebSocketProxy(parsedArgs.host, server);
|
||||
|
||||
var stopping = false;
|
||||
function exitWhenStopped() {
|
||||
if (!stopping) {
|
||||
stopping = true;
|
||||
server.close(function() {
|
||||
console.log('WLED UI closed');
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
process.on('uncaughtException',function(err) {
|
||||
util.log('[WLED] Uncaught Exception:');
|
||||
if (err.stack) {
|
||||
console.log(err.stack);
|
||||
} else {
|
||||
console.log(err);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('SIGINT', exitWhenStopped);
|
||||
process.on('SIGTERM', exitWhenStopped);
|
||||
process.on('SIGHUP', exitWhenStopped);
|
||||
process.on('SIGUSR2', exitWhenStopped); // for nodemon restart
|
||||
process.on('SIGBREAK', exitWhenStopped); // for windows ctrl-break
|
129
wled00/data/cfg.css
Normal file
129
wled00/data/cfg.css
Normal file
@ -0,0 +1,129 @@
|
||||
@font-face {
|
||||
font-family: "CIcons";
|
||||
src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAApMAAsAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIGEWNtYXAAAAFoAAAAVAAAAFQXVtKTZ2FzcAAAAbwAAAAIAAAACAAAABBnbHlmAAABxAAABfwAAAX8iNRp/2hlYWQAAAfAAAAANgAAADYd+7tRaGhlYQAAB/gAAAAkAAAAJAeYA9JobXR4AAAIHAAAAEQAAABEOgAGTGxvY2EAAAhgAAAAJAAAACQItgqAbWF4cAAACIQAAAAgAAAAIAAWAExuYW1lAAAIpAAAAYYAAAGGmUoJ+3Bvc3QAAAosAAAAIAAAACAAAwAAAAMD2wGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA6QwDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADgAAAAKAAgAAgACAAEAIOkM//3//wAAAAAAIOkA//3//wAB/+MXBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQDWAIEDKgLVAAsAAAEhESMRITUhETMRIQMq/wBU/wABAFQBAAGB/wABAFQBAP8AAAAAAAIAgAArA7gDYwANABEAAAEXBzMRIREzJxUhESEVAREhEQLG8vK6/qqc8P6qAVb+qgFWA2Py8P6qAVbwnAFWuv26AVb+qgAAAAEAqgABA4ADVQAlAAABMxEhERQHBisBIicmNREhNSMVFAcGIyEiJyY9ATQ3NjMhMhcWFQMAgP6qDAwSVhIMDAGqKgwMEv4AEg0NDQ0SAgASDAwDAf6q/oASDAwMDBIB1qoqEg0NDQ0SqhIMDAwMEgABAQAAKwMqAysAEwAAASEVIxEjBgcGIyInJjU0NzYzMhcCAAEqqgIINjZKUDg4ODhQHCQDK4D+KkgxMTg4UFA4OAwAAAIAVgArA4ADKwALAB0AAAEWFRQHAScBNjMyFwEyFxYVFAcGIyInMjc2NTQ3NgN0DAz+gnYBfgwSEgz98DQmJjIyRmhCHhsbJiYC5QwSEgz+gnYBfgwM/jYmJjRGMjJWFxcmNCYmAAAAAQCSAIEDgAK9AAUAACUBFwEnNwGAAcQ8/gDuPPkBxDz+AO48AAAAAAIAqv/VA1YDgQAQACEAAAEWFRQHBiMVJzcVMjc2NTQnJyIHBhUUFwcmNTQ3NjM1FwcDIDZlZYyqqmpLSx7iaktLHj42ZWWMqqoCYVJkjGVlgKyqgEtLajw8iEtLakA4PlJkjGVlgKyqAAAAAAEAVgABA9YDgQA/AAABMhcWFRQHBisBFRQHBisBNTQnJiMiBwYdASMiJyY9ATMyNzY1NCcmKwE1NDc2OwE1NDc2MzIXFh0BMzIXFh0BA2osICAgICxAGRkioiIiMDAiIqIiGRlAMCEhISEwQBkZIqwfHywsHx+sIhkZAdUfHywsHx+sIhkZQDAhISEhMEAZGSKiIiIwMCIioiIZGUAsICAgICxAGRkirAAAAAACAFYAHQOqAysAIgA+AAAlNjc2NzY3NjU0JyYjIgcGByMmJyYjIgcGFRQXFhcWFxYfARMyFxYVFAcGBwYHBg8BJyYnJicmNTQ3NjMyFzYCBGAuLjY2FRUrK0AyKysQUBArKzJAKysVFTY2Li5gBMBkQ0MWFjs7MDBqPj6KPT00NENDZHRMTJNWLCw8PC4uLEAqKhwcLCwcHCoqQCwuLjw8LCxWBAKcRERiOjc3REQuLmA4Nnw+PlRUTmJERFpaAAAEAFYAAQOqA1UAAwATACMAJwAAATUzFQMyNzY1NCcmIyIHBhUUFxYTMhcWFRQHBiMiJyY1NDc2ExEzEQHWVCqMZWVlZYyMZWVlZYywfX19fbCwfX19fYZUAitWVv4qZWWMjGVlZWWMjGVlAwB9fbCwfX19fbCwfX39gAEA/wAAAAIAZAABA5wDVQAPAEkAAAEyNzY1NCcmIyIHBhUUFxYlFxYPAQYvAQYPAQYrASIvASYnBwYvASY/ASY1NDcnJj8BNh8BNj8BNjsBMh8BFhc3Nh8BFg8BFhUUAgA+LCwsLD4+LCwsLAF8Wg4KVggSaioeEAQQrBAEECYiahIIVgoOWgICWg4KVggSaioeEAQQrBAEECYiahIIVgoOWgIBFSwsPj4sLCwsPj4sLGxGChKUDgYqHgxwEhJwEBoqBg6UEgpGDhwcDkYKEpQOBioeDHASEnAQGioGDpQSCkYOHBwAAwAq/9UD1gOBAAcADwAXAAABPwEvAQ8BFwUnDwEfAT8BFw8BHwE/AScDKjZ2djY0dnb+9Gpq7OxqauxUNHZ2NDZ2dgIrdjQ2dnY2NIzs7Gpq7OxqgHY0NnZ2NjQAAAAAAwAqAFUD1gLtAA0AEwAdAAATNjMyFwcmJyYjIgcGBxc2MzIXBwE2ISAXByYjIgfWfK+velQkPz80ND8/JFY2Sko2gP4qxAETARPCVqDg4KABgXp6ViQaGhoaJFY2NoAB1sLCVp6eAAABAAAAAAAA3GG4ZV8PPPUACwQAAAAAAN2Du38AAAAA3YO7fwAA/9UD1gOBAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAPWAAEAAAAAAAAAAAAAAAAAAAARBAAAAAAAAAAAAAAAAgAAAAQAANYEAACABAAAqgQAAQAEAABWBAAAkgQAAKoEAABWBAAAVgQAAFYEAABkBAAAKgQAACoAAAAAAAoAFAAeADgAXACUALYA6gD+ATQBigHqAioCmgLKAv4AAQAAABEASgAEAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGljb21vb24AaQBjAG8AbQBvAG8AblZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGljb21vb24AaQBjAG8AbQBvAG8Abmljb21vb24AaQBjAG8AbQBvAG8AblJlZ3VsYXIAUgBlAGcAdQBsAGEAcmljb21vb24AaQBjAG8AbQBvAG8AbkZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('woff');
|
||||
}
|
||||
|
||||
:root {
|
||||
--c-1: #111;
|
||||
--c-f: #fff;
|
||||
--c-2: #222;
|
||||
--c-3: #333;
|
||||
--c-4: #444;
|
||||
--c-5: #555;
|
||||
--c-6: #666;
|
||||
--c-8: #888;
|
||||
--c-b: #bbb;
|
||||
--c-c: #ccc;
|
||||
--c-e: #eee;
|
||||
--c-d: #ddd;
|
||||
--c-r: #831;
|
||||
}
|
||||
|
||||
html {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: var(--c-2);
|
||||
font-family: Helvetica, Verdana, sans-serif;
|
||||
font-size: 17px;
|
||||
color: var(--c-f);
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
scrollbar-width: 6px;
|
||||
scrollbar-color: var(--c-sb) transparent;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
.icons {
|
||||
font-family: "CIcons";
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#header {
|
||||
width: 100%;
|
||||
background-color: var(--c-3);
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
#menu {
|
||||
height: calc(100% - 45px);
|
||||
background-color: var(--c-3);
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.entry {
|
||||
height: 45px;
|
||||
color: var(--c-b);
|
||||
}
|
||||
|
||||
.entry:hover {
|
||||
color: var(--c-f);
|
||||
background-color: var(--c-4);
|
||||
}
|
||||
|
||||
.e-icon {
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
width: 45px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.e-label {
|
||||
display: inline-block;
|
||||
height: 45px;
|
||||
vertical-align: top;
|
||||
padding: 14px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 9px;
|
||||
color: var(--c-b);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
color: var(--c-f);
|
||||
background-color: var(--c-4);
|
||||
}
|
||||
|
||||
.save {
|
||||
float: right;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.b-icon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.b-label {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
#menu {
|
||||
width: 45px;
|
||||
}
|
||||
.e-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
71
wled00/data/cfg.htm
Normal file
71
wled00/data/cfg.htm
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#222222">
|
||||
<link rel="stylesheet" href="cfg.css">
|
||||
<script src="cfg_lang.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="header">
|
||||
<div class="e-icon"><i class="icons"></i></div>
|
||||
<div class="l e-label l10n" id="h-cfg"></div>
|
||||
<div class="btn save">
|
||||
<div class="b-icon"><i class="icons"></i></div>
|
||||
<div class="l b-label l10n" id="b-save">Save</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="menu">
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-nw">Network</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-hw">Hardware</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-ui">Customization</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-if">Interfaces</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-tm">Schedules</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-dx">DMX Out</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-sr">Sound Reactive</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-um">Usermods</div></div>
|
||||
<div class="entry"><div class="e-icon"><i class="icons"></i></div><div class="l e-label l10n" id="e-ab">About</div></div>
|
||||
</div>
|
||||
<div id="content">
|
||||
<!-- simulate sections for each menu item -->
|
||||
<div id="nw">
|
||||
<h2 class="l10n">Network</h2>
|
||||
</div>
|
||||
<div id="hw">
|
||||
<h2 class="l10n">Hardware</h2>
|
||||
</div>
|
||||
<div id="ui">
|
||||
<h2 class="l10n">Customization</h2>
|
||||
</div>
|
||||
<div id="if">
|
||||
<h2 class="l10n">Interfaces</h2>
|
||||
</div>
|
||||
<div id="tm">
|
||||
<h2 class="l10n">Schedules</h2>
|
||||
</div>
|
||||
<div id="sr">
|
||||
<h2 class="l10n">Sound Reactive</h2>
|
||||
</div>
|
||||
<div id="um">
|
||||
<h2 class="l10n">Usermods</h2>
|
||||
</div>
|
||||
<div id="dx">
|
||||
<h2 class="l10n">DMX Out</h2>
|
||||
</div>
|
||||
<div id="ab">
|
||||
<h2 class="l10n">About</h2>
|
||||
</div>
|
||||
<div id="up">
|
||||
<h2 class="l10n">Update</h2>
|
||||
</div>
|
||||
<div id="rb">
|
||||
<h2 class="l10n">Reboot</h2>
|
||||
</div>
|
||||
</div>
|
||||
<script src="cfg.js" type="module"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
30
wled00/data/cfg.js
Normal file
30
wled00/data/cfg.js
Normal file
@ -0,0 +1,30 @@
|
||||
import $ from './dom.mjs'
|
||||
import translate from './translator.mjs'
|
||||
|
||||
/* Dynamically create the menu
|
||||
const menuItems = [
|
||||
{ "icon": "", "id": "e-nw", "text": "Network" },
|
||||
{ "icon": "", "id": "e-hw", "text": "Hardware" },
|
||||
{ "icon": "", "id": "e-ui", "text": "Customization" },
|
||||
{ "icon": "", "id": "e-if", "text": "Interfaces" },
|
||||
{ "icon": "", "id": "e-tm", "text": "Schedules" },
|
||||
{ "icon": "", "id": "e-dx", "text": "DMX Out" },
|
||||
{ "icon": "", "id": "e-sr", "text": "Sound Reactive" },
|
||||
{ "icon": "", "id": "e-um", "text": "Usermods" },
|
||||
{ "icon": "", "id": "e-ab", "text": "About" }
|
||||
];
|
||||
|
||||
$().ready(function() {
|
||||
const menu = $('#menu');
|
||||
menuItems.map(item =>
|
||||
menu.append(`<div class="entry"><div class="e-icon"><i class="icons">${item.icon}</i></div><div class="l e-label l10n" id="${item.id}">${item.text}</div></div>`)
|
||||
);
|
||||
});
|
||||
*/
|
||||
|
||||
// populate labels when to dom is ready but before it is rendered
|
||||
$().ready(function() {
|
||||
// https://www.w3.org/International/questions/qa-i18n
|
||||
// Localization is sometimes written in English as l10n
|
||||
translate('.l10n');
|
||||
});
|
10
wled00/data/cfg_lang.js
Normal file
10
wled00/data/cfg_lang.js
Normal file
@ -0,0 +1,10 @@
|
||||
(function() {
|
||||
// self executing function to ensure translations is set on page load
|
||||
// so we dont have to wait for fetch/xhr request
|
||||
window.translations = {
|
||||
"About": "Über",
|
||||
"Save": "Speichern",
|
||||
"Schedules": "Zeitpläne",
|
||||
"Sound Reactive": "Tonreaktiv"
|
||||
};
|
||||
}());
|
126
wled00/data/dom.mjs
Normal file
126
wled00/data/dom.mjs
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
** DOM module - base on https://github.com/kylebarrow/chibi with IE hacks removed
|
||||
**
|
||||
*/
|
||||
var readyfn = [],
|
||||
loadedfn = [],
|
||||
domready = false,
|
||||
pageloaded = false,
|
||||
d = document,
|
||||
w = window;
|
||||
|
||||
// Fire any function calls on ready event
|
||||
function fireReady() {
|
||||
var i;
|
||||
domready = true;
|
||||
for (i = 0; i < readyfn.length; i += 1) {
|
||||
readyfn[i]();
|
||||
}
|
||||
readyfn = [];
|
||||
}
|
||||
|
||||
// Fire any function calls on loaded event
|
||||
function fireLoaded() {
|
||||
var i;
|
||||
pageloaded = true;
|
||||
for (i = 0; i < loadedfn.length; i += 1) {
|
||||
loadedfn[i]();
|
||||
}
|
||||
loadedfn = [];
|
||||
}
|
||||
|
||||
// Check DOM ready, page loaded
|
||||
if (d.addEventListener) {
|
||||
// Standards
|
||||
d.addEventListener('DOMContentLoaded', fireReady, false);
|
||||
w.addEventListener('load', fireLoaded, false);
|
||||
}
|
||||
|
||||
// Loop through node array
|
||||
function nodeLoop(fn, nodes) {
|
||||
var i;
|
||||
// Good idea to walk up the DOM
|
||||
for (i = nodes.length - 1; i >= 0; i -= 1) {
|
||||
fn(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function dom(selector) {
|
||||
var self, nodes = [],
|
||||
json = false,
|
||||
nodelist;
|
||||
|
||||
if (selector) {
|
||||
|
||||
// Element node
|
||||
if (selector instanceof HTMLElement) {
|
||||
nodes = [selector]; // return element as node list
|
||||
} else if (selector instanceof NodeList) {
|
||||
// JSON, document object or node list
|
||||
json = (typeof selector.length !== 'number');
|
||||
nodes = selector;
|
||||
} else if (typeof selector === 'string') {
|
||||
nodelist = d.querySelectorAll(selector);
|
||||
nodes = Array.from(nodelist);
|
||||
}
|
||||
}
|
||||
|
||||
// Only attach nodes if not JSON
|
||||
self = json ? {} : nodes;
|
||||
|
||||
// Public functions
|
||||
|
||||
// Fire on DOM ready
|
||||
self.ready = function(fn) {
|
||||
if (fn) {
|
||||
if (domready) {
|
||||
fn();
|
||||
return self;
|
||||
} else {
|
||||
readyfn.push(fn);
|
||||
}
|
||||
}
|
||||
};
|
||||
// Fire on page loaded
|
||||
self.loaded = function(fn) {
|
||||
if (fn) {
|
||||
if (pageloaded) {
|
||||
fn();
|
||||
return self;
|
||||
} else {
|
||||
loadedfn.push(fn);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Executes a function on nodes
|
||||
self.each = function(fn) {
|
||||
if (typeof fn === 'function') {
|
||||
nodeLoop(fn, nodes);
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
self.first = function() {
|
||||
return dom(nodes.shift());
|
||||
};
|
||||
|
||||
// Find last
|
||||
self.last = function() {
|
||||
return dom(nodes.pop());
|
||||
};
|
||||
|
||||
// append html before end of the of the tag
|
||||
self.append = function(value) {
|
||||
if (value) {
|
||||
nodeLoop(function(elm) {
|
||||
elm.insertAdjacentHTML('beforeend', value);
|
||||
}, nodes);
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
export default dom;
|
27
wled00/data/translator.mjs
Normal file
27
wled00/data/translator.mjs
Normal file
@ -0,0 +1,27 @@
|
||||
import $ from './dom.mjs'
|
||||
|
||||
var w = window;
|
||||
|
||||
function getText(elm) {
|
||||
return elm.textContent; // or innerText ?
|
||||
}
|
||||
|
||||
function setText(elm, value) {
|
||||
if (value) {
|
||||
elm.textContent = value; // or innerText ?
|
||||
}
|
||||
}
|
||||
|
||||
// perform simple translation
|
||||
function translateElement(elm) {
|
||||
const text = getText(elm);
|
||||
setText(elm, w.translations[text]);
|
||||
}
|
||||
|
||||
export default function translate(selector) {
|
||||
if (w.translations) {
|
||||
$(selector).each(translateElement)
|
||||
} else {
|
||||
console.info("no translations");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user