minimal example
This commit is contained in:
parent
af9d2bbaa5
commit
b2b262c715
78
classless-tiny.css
Normal file
78
classless-tiny.css
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* Classless.css v1.0 (Tiny Inline Version)*/
|
||||
|
||||
/* Tiny Reset for block elements */
|
||||
* {box-sizing: border-box; border-spacing: 0;}
|
||||
header, footer, figure, table, video, details, blockquote,
|
||||
ul, ol, dl, fieldset, pre, pre > code, caption, nav {
|
||||
display: block;
|
||||
margin: 0.5rem 0rem 1rem;
|
||||
width: 100%;
|
||||
overflow: auto hidden;
|
||||
text-align: left;
|
||||
}
|
||||
video, summary, input, select { outline:none; }
|
||||
html { font: 12pt/1.6 'Open Sans', Helvetica, sans-serif; }
|
||||
body {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
max-width: 50rem;
|
||||
color: #433;
|
||||
padding: 3.1rem 0.6rem 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
body > footer { margin: 10rem 0rem 0rem; }
|
||||
|
||||
/* clickable stuff */
|
||||
a, summary, button, select { color: #07c; cursor: pointer; }
|
||||
a { text-decoration: underline solid #d1d1d1; text-underline-position: under; }
|
||||
a:hover { color: #088; border-color: #088; }
|
||||
|
||||
/* common */
|
||||
td, th, pre > code { padding: 0.5rem 0.8rem; }
|
||||
.card, details { padding: 0 .6rem; }
|
||||
code, kbd, samp { padding: 0.2rem; font: .9em/1.4 monospace; }
|
||||
code, kbd, samp, nav, .card { background: #f4f5f6; border-radius: 0.3em; }
|
||||
kbd, .card, details[open] { border: 1px solid #d1d1d1; }
|
||||
td, th, figcaption, caption, .card { font-size: 95%; }
|
||||
td, th, hr { border: 0; border-bottom: 0.1rem solid #d1d1d1; }
|
||||
|
||||
/* lists */
|
||||
ul, ol { padding-top: 0.5rem; }
|
||||
li, dd { margin-bottom: 0.5rem; }
|
||||
dt { font-weight: bold; }
|
||||
|
||||
/* headings */
|
||||
h1, h2, h3, h4, h5 { margin: 1.5em 0 0em; line-height: 1.2em; }
|
||||
h1+h2, h2+h3, h3+h4, h4+h5 { margin-top: .5em; }
|
||||
h1 { font-size: 2.2em; font-weight: 300; }
|
||||
h2 { font-size: 2.0em; font-weight: 300; font-variant-caps: small-caps; }
|
||||
h3 { font-size: 1.5em; font-weight: 400; }
|
||||
h4 { font-size: 1.1em; font-weight: 700; }
|
||||
h5 { font-size: 1.2em; font-weight: 400; color: #888; }
|
||||
h6 { font-size: 1.0em; font-weight: 600; display: inline; }
|
||||
h6 + p { display: inline; }
|
||||
|
||||
/* tables */
|
||||
td, th { text-align: right; white-space: nowrap; }
|
||||
td:first-child, th:first-child { text-align: left; }
|
||||
tr:hover{ background-color: #f4f5f6; }
|
||||
|
||||
/* figures */
|
||||
img, svg { max-width: 100%; vertical-align: text-top; }
|
||||
p>img:not(:only-child) { float: right; margin: 0 0 .5em .5em; }
|
||||
figure > img { display: block; margin: 0.5em auto; }
|
||||
figcaption, caption { color: #888; margin-bottom: 1rem; }
|
||||
figure > *:not(:last-child) { margin: 0 0 0.4rem; }
|
||||
|
||||
/*code*/
|
||||
pre > code { margin: 0; border-left: 0.4rem solid #088; }
|
||||
|
||||
/* misc */
|
||||
blockquote{ border-left: 0.3rem solid #d1d1d1; padding: 1rem 1.5rem; font-style: italic; }
|
||||
input { font-size: 1em; }
|
||||
p>cite:before { content: ' ('; } p>cite:after {content: ') '}
|
||||
|
||||
/* grid */
|
||||
.row { display: flex; margin: 0.5rem -0.5rem; align-items: stretch; }
|
||||
.row [class*="col"] { padding: 0 0.5rem; flex: 1 1 100%; }
|
||||
@media (max-width: 40em) { .row { flex-direction: column !important; } }
|
381
classless.css
Normal file
381
classless.css
Normal file
|
@ -0,0 +1,381 @@
|
|||
/* Classless.css v1.0
|
||||
|
||||
Table of Contents:
|
||||
1. Theme Settings
|
||||
2. Reset
|
||||
3. Base Style
|
||||
4. Extras (remove unwanted)
|
||||
5. Classes (remove unwanted)
|
||||
*/
|
||||
|
||||
/* 1. Theme Settings ––––––––––––––––––––-–––––––––––––– */
|
||||
|
||||
|
||||
:root, html[data-theme='light'] {
|
||||
--rem: 12pt;
|
||||
--width: 50rem;
|
||||
--navpos: absolute; /* fixed | absolute */
|
||||
--font-p: 1em/1.7 'Open Sans', 'DejaVu Sans', FreeSans, Helvetica, sans-serif;
|
||||
--font-h: .9em/1.5 'Open Sans', 'DejaVu Sans', FreeSans, Helvetica, sans-serif;
|
||||
--font-c: .9em/1.4 'DejaVu Sans Mono', monospace;
|
||||
--border: 1px solid var(--cmed);
|
||||
--ornament: "‹‹‹ ›››";
|
||||
/* foreground | background color */
|
||||
--cfg: #433; --cbg: #fff;
|
||||
--cdark: #888; --clight: #f5f6f7;
|
||||
--cmed: #d1d1d1;
|
||||
--clink: #07c;
|
||||
--cemph: #088; --cemphbg: #0881;
|
||||
}
|
||||
|
||||
|
||||
/* 2. Reset –––––––––––––––––––––––––––––––––––––––––––– */
|
||||
|
||||
/* reset block elements */
|
||||
* { box-sizing: border-box; border-spacing: 0; margin: 0; padding: 0;}
|
||||
header, footer, figure, table, video, details, blockquote,
|
||||
ul, ol, dl, fieldset, pre, pre > code, caption {
|
||||
display: block;
|
||||
margin: 0.5rem 0rem 1rem;
|
||||
width: 100%;
|
||||
overflow: auto hidden;
|
||||
text-align: left;
|
||||
}
|
||||
video, summary, input, select { outline:none; }
|
||||
|
||||
/* reset clickable things (FF Bug: select:hover prevents usage) */
|
||||
a, button, select, summary { color: var(--clink); cursor: pointer; }
|
||||
|
||||
|
||||
/* 3. Base Style ––––––––––––––––––––––––––––––––––––––– */
|
||||
html { font-size: var(--rem); background: var(--cbg); }
|
||||
body {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
max-width: var(--width);
|
||||
font: var(--font-p);
|
||||
color: var(--cfg);
|
||||
padding: 3.0rem 0.6rem 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
body > footer { margin: 10rem 0rem 0rem; font-size: 90%; }
|
||||
p { margin: .6em 0; }
|
||||
|
||||
/* links */
|
||||
a[href]{ text-decoration: underline solid var(--cmed); text-underline-position: under; }
|
||||
a[href^="#"] {text-decoration: none; }
|
||||
a:hover, button:not([disabled]):hover, summary:hover {
|
||||
filter: brightness(92%); color: var(--cemph); border-color: var(--cemph);
|
||||
}
|
||||
|
||||
/* lists */
|
||||
ul, ol, dl { margin: 1rem 0; padding: 0 0 0 2em; }
|
||||
li:not(:last-child), dd:not(:last-child) { margin-bottom: 0.5rem; }
|
||||
dt { font-weight: bold; }
|
||||
|
||||
/* headings */
|
||||
h1, h2, h3, h4, h5 { margin: 1.5em 0 .5rem; font: var(--font-h); line-height: 1.2em; clear: both; }
|
||||
h1+h2, h2+h3, h3+h4, h4+h5 { margin-top: .5em; padding-top: 0; } /* non-clashing headings */
|
||||
h1 { font-size: 2.2em; font-weight: 300; }
|
||||
h2 { font-size: 2.0em; font-weight: 300; font-variant: small-caps; }
|
||||
h3 { font-size: 1.5em; font-weight: 400; }
|
||||
h4 { font-size: 1.1em; font-weight: 700; }
|
||||
h5 { font-size: 1.2em; font-weight: 400; color: var(--cfg); }
|
||||
h6 { font-size: 1.0em; font-weight: 700; font-style: italic; display: inline; }
|
||||
h6 + p { display: inline; }
|
||||
|
||||
/* tables */
|
||||
td, th {
|
||||
padding: 0.5em 0.8em;
|
||||
text-align: right;
|
||||
border-bottom: 0.1rem solid var(--cmed);
|
||||
white-space: nowrap;
|
||||
font-size: 95%;
|
||||
}
|
||||
thead th[colspan] { padding: .2em 0.8em; text-align: center; }
|
||||
thead tr:not(:only-child) td { padding: .2em 0.8em; }
|
||||
thead+tbody tr:first-child td { border-top: 0.1rem solid var(--cdark); }
|
||||
td:first-child, th:first-child { text-align: left; }
|
||||
tr:hover{ background-color: var(--clight); }
|
||||
table img { display: block; }
|
||||
|
||||
/* figures */
|
||||
img, svg { max-width: 100%; vertical-align: text-top; object-fit: cover; }
|
||||
p>img:not(:only-child) { float: right; margin: 0 0 .5em .5em; }
|
||||
figure > img { display: inline-block; width: auto; }
|
||||
figure > img:only-of-type, figure > svg:only-of-type { max-width: 100%; display: block; margin: 0 auto 0.4em; }
|
||||
figcaption, caption { font: var(--font-h); color: var(--cdark); width: 100%; }
|
||||
figcaption > *:first-child, caption > *:first-child { display: inline-block; margin: 0; }
|
||||
figure > *:not(:last-child) { margin-bottom: 0.4rem; }
|
||||
|
||||
/* code */
|
||||
pre > code {
|
||||
margin: 0;
|
||||
position: relative;
|
||||
padding: 0.8em;
|
||||
border-left: .4rem solid var(--cemph);
|
||||
}
|
||||
code, kbd, samp {
|
||||
padding: 0.2em;
|
||||
font: var(--font-c);
|
||||
background: var(--clight);
|
||||
border-radius: 4px;
|
||||
}
|
||||
kbd { border: 1px solid var(--cmed); }
|
||||
|
||||
/* misc */
|
||||
blockquote { border-left: 0.4rem solid var(--cmed); padding: 0 0 0 1rem; }
|
||||
time{ color: var(--cdark); }
|
||||
hr { border: 0; border-top: 0.1rem solid var(--cmed); }
|
||||
nav { width: 100%; background-color: var(--clight); }
|
||||
::selection, mark { background: var(--clink); color: var(--cbg); }
|
||||
|
||||
|
||||
/* 4. Extra Style –––––––––––––––––––––––––––––––––––––– */
|
||||
|
||||
/* Auto Numbering: figure/tables/headings/cite */
|
||||
article { counter-reset: h2 0 h3 0 tab 0 fig 0 lst 0 ref 0 eq 0; }
|
||||
article figure figcaption:before {
|
||||
color: var(--cemph);
|
||||
counter-increment: fig;
|
||||
content: "Figure " counter(fig) ": ";
|
||||
}
|
||||
|
||||
/* subfigures */
|
||||
figure { counter-reset: subfig 0 }
|
||||
article figure figure { counter-reset: none; }
|
||||
article figure > figure { display: inline-grid; width: auto; }
|
||||
figure > figure:not(:last-of-type) { padding-right: 1rem; }
|
||||
article figure figure figcaption:before {
|
||||
counter-increment: subfig 1;
|
||||
content: counter(subfig, lower-alpha) ": ";
|
||||
}
|
||||
|
||||
/* listings */
|
||||
article figure pre + figcaption:before {
|
||||
counter-increment: lst 1;
|
||||
content: "Listing " counter(lst) ": ";
|
||||
}
|
||||
|
||||
/* tables */
|
||||
figure > table:only-of-type { display: table; margin: 0.5em auto !important; width: fit-content; }
|
||||
article figure > table caption { display: table-caption; caption-side: bottom; }
|
||||
article figure > table + figcaption:before,
|
||||
article table caption:before {
|
||||
color: var(--cemph);
|
||||
counter-increment: tab 1;
|
||||
content: "Table " counter(tab) ": ";
|
||||
}
|
||||
|
||||
/* headings */
|
||||
article h2, h3 { position: relative; }
|
||||
article h2:before,
|
||||
article h3:before {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
font-size: 0.6em;
|
||||
text-align: right;
|
||||
vertical-align: baseline;
|
||||
left: -1rem;
|
||||
width: 2.5em;
|
||||
margin-left: -2.5em;
|
||||
}
|
||||
article h1 { counter-set: h2; }
|
||||
article h2:before { counter-increment: h2; content: counter(h2) ". "; counter-set: h3; }
|
||||
article h3:before { counter-increment: h3; content: counter(h2) "." counter(h3) ". ";}
|
||||
@media (max-width: 60rem) { h2:before, h3:before { display: none; } }
|
||||
|
||||
/* tooltip + citation */
|
||||
article p>cite:before {
|
||||
padding: 0 .5em 0 0;
|
||||
counter-increment: ref; content: " [" counter(ref) "] ";
|
||||
vertical-align: super; font-size: .6em;
|
||||
}
|
||||
article p>cite > *:only-child { display: none; }
|
||||
article p>cite:hover > *:only-child,
|
||||
[data-tooltip]:hover:before {
|
||||
display: inline-block; z-index: 40;
|
||||
white-space: pre-wrap;
|
||||
position: absolute; left: 1rem; right: 1rem;
|
||||
padding: 1em 2em;
|
||||
text-align: center;
|
||||
transform:translateY( calc(-100%) );
|
||||
content: attr(data-tooltip);
|
||||
color: var(--cbg);
|
||||
background-color: var(--cemph);
|
||||
box-shadow: 0 2px 10px 0 black;
|
||||
}
|
||||
[data-tooltip], article p>cite:before {
|
||||
color: var(--clink);
|
||||
border: .8rem solid transparent; margin: -.8rem;
|
||||
}
|
||||
abbr[title], [data-tooltip] { cursor: help; }
|
||||
|
||||
/* navbar */
|
||||
nav+* { margin-top: 3rem; }
|
||||
body>nav, header nav {
|
||||
position: var(--navpos);
|
||||
top: 0; left: 0; right: 0;
|
||||
z-index: 41;
|
||||
box-shadow: 0vw -50vw 0 50vw var(--clight), 0 calc(-50vw + 2px) 4px 50vw var(--cdark);
|
||||
}
|
||||
nav ul { list-style-type: none; }
|
||||
nav ul:first-child { margin: 0; padding: 0; overflow: visible; }
|
||||
nav ul:first-child > li {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0.8rem .6rem;
|
||||
}
|
||||
nav ul > li > ul {
|
||||
display: none;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
margin: 0.5rem 0;
|
||||
padding: 1rem 2rem;
|
||||
background-color: var(--clight);
|
||||
border: var(--border);
|
||||
border-radius: 4px;
|
||||
z-index: 42;
|
||||
}
|
||||
nav ul > li > ul > li { white-space: nowrap; }
|
||||
nav ul > li:hover > ul { display: block; }
|
||||
@media (max-width: 40rem) {
|
||||
nav ul:first-child > li:first-child:after { content: " \25BE"; }
|
||||
nav ul:first-child > li:not(:first-child):not(.sticky) { display: none; }
|
||||
nav ul:first-child:hover > li:not(:first-child):not(.sticky) { display: block; float: none !important; }
|
||||
}
|
||||
|
||||
/* details/cards */
|
||||
summary>* { display: inline; }
|
||||
.card, details {
|
||||
display: block;
|
||||
margin: 0.5rem 0rem 1rem;
|
||||
padding: 0 .6rem;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.card, details[open] { outline: 1px solid var(--cmed); }
|
||||
.card>img:first-child { margin: -3px -.6rem; max-width: calc(100% + 1.2rem); }
|
||||
summary:hover, details[open] summary, .card>p:first-child {
|
||||
box-shadow: inset 0 0 0 2em var(--clight), 0 -.8rem 0 .8rem var(--clight);
|
||||
}
|
||||
.hint { --cmed: var(--cemph); --clight: var(--cemphbg); background-color: var(--clight); }
|
||||
.warn { --cmed: #c11; --clight: #e221; background-color: var(--clight); }
|
||||
|
||||
/* big first letter */
|
||||
article > section:first-of-type > h2:first-of-type + p:first-letter,
|
||||
article > h2:first-of-type + p:first-letter, .lettrine {
|
||||
float: left;
|
||||
font-size: 3.5em;
|
||||
padding: 0.1em 0.1em 0 0;
|
||||
line-height: 0.68em;
|
||||
color: var(--cemph);
|
||||
}
|
||||
|
||||
/* ornaments */
|
||||
section:after {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
color: var(--cmed);
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
content: var(--ornament);
|
||||
}
|
||||
|
||||
/* side menu (aside is not intended for use in a paragraph!) */
|
||||
main aside {
|
||||
position: absolute;
|
||||
width: 8rem; right: -8.6rem;
|
||||
font-size: 0.8em; line-height: 1.4em;
|
||||
}
|
||||
@media (max-width: 70rem) { main aside { display: none; } }
|
||||
|
||||
/* forms and inputs */
|
||||
textarea, input:not([type=range]), button, select {
|
||||
font: var(--font-h);
|
||||
border-radius: 4px;
|
||||
border: 1.5px solid var(--cmed);
|
||||
padding: 0.4em 0.8em;
|
||||
}
|
||||
fieldset select, input:not([type=checkbox]):not([type=radio]) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
button, select {
|
||||
font-weight: bold;
|
||||
background-color: var(--clight);
|
||||
margin: .5em;
|
||||
border: 1.5px solid var(--clink);
|
||||
}
|
||||
button { padding: 0.4em 1em; font-size: 85%; letter-spacing: 0.1em; }
|
||||
button[disabled]{ color: var(--cdark); border-color: var(--cmed); }
|
||||
fieldset { border-radius: 4px; border: var(--border); padding: .5em 1em;}
|
||||
textarea:hover, input:not([type=checkbox]):not([type*='ra']):hover, select:hover{
|
||||
border: 1.5px solid var(--cemph);
|
||||
}
|
||||
textarea:focus, input:not([type=checkbox]):not([type*='ra']):focus{
|
||||
border: 1.5px solid var(--clink);
|
||||
box-shadow: 0 0 5px var(--clink);
|
||||
}
|
||||
p>button { padding: 0 .5em; margin: 0 .5em; }
|
||||
p>select { padding: 0; margin: 0 .5em; }
|
||||
|
||||
|
||||
/* 5. Bootstrap-compatible classes ––––––––––––––––––––– */
|
||||
|
||||
/* grid */
|
||||
.row { display: flex; margin: 0.5rem -0.6rem; align-items: stretch; }
|
||||
.row [class*="col"] { padding: 0 0.6rem; }
|
||||
.row .col { flex: 1 1 100%; }
|
||||
.row .col-2 { flex: 0 0 16.66%; max-width: 16.66%;}
|
||||
.row .col-3 { flex: 0 0 25%; max-width: 25%;}
|
||||
.row .col-4 { flex: 0 0 33.33%; max-width: 33.33%; }
|
||||
.row .col-5 { flex: 0 0 41.66%; max-width: 41.66%; }
|
||||
.row .col-6 { flex: 0 0 50%; max-width: 50%; }
|
||||
@media (max-width: 40rem) { .row { flex-direction: column; } }
|
||||
|
||||
/* align */
|
||||
.text-left { text-align: left; }
|
||||
.text-right { text-align: right; }
|
||||
.text-center { text-align: center; }
|
||||
.float-left { float: left !important; }
|
||||
.float-right { float: right !important; }
|
||||
.clearfix { clear: both; }
|
||||
|
||||
/* colors */
|
||||
.text-black { color: #000; }
|
||||
.text-white { color: #fff; }
|
||||
.text-primary { color: var(--cemph); }
|
||||
.text-secondary{ color: var(--cdark); }
|
||||
.bg-white { background-color: #fff; }
|
||||
.bg-light { background-color: var(--clight); }
|
||||
.bg-primary { background-color: var(--cemph); }
|
||||
.bg-secondary{ background-color: var(--cmed); }
|
||||
|
||||
/* margins */
|
||||
.mx-auto { margin-left: auto; margin-right: auto; }
|
||||
.m-0 { margin: 0 !important; }
|
||||
.m-1, .mx-1, .mr-1 { margin-right: 1.0rem !important; }
|
||||
.m-1, .mx-1, .ml-1 { margin-left: 1.0rem !important; }
|
||||
.m-1, .my-1, .mt-1 { margin-top: 1.0rem !important; }
|
||||
.m-1, .my-1, .mb-1 { margin-bottom: 1.0rem !important; }
|
||||
|
||||
/* pading */
|
||||
.p-0 { padding: 0 !important; }
|
||||
.p-1, .px-1, .pr-1 { padding-right: 1.0rem !important; }
|
||||
.p-1, .px-1, .pl-1 { padding-left: 1.0rem !important; }
|
||||
.p-1, .py-1, .pt-1 { padding-top: 1.0rem !important; }
|
||||
.p-1, .py-1, .pb-1 { padding-bottom: 1.0rem !important; }
|
||||
|
||||
/* be print-friendly */
|
||||
@media print {
|
||||
@page { margin: 1.5cm 2cm; }
|
||||
html {font-size: 9pt!important; }
|
||||
body { max-width: 27cm; }
|
||||
p { orphans: 2; widows: 2; }
|
||||
caption, figcaption { page-break-before: avoid; }
|
||||
h2, h3, h4, h5 { page-break-after: avoid;}
|
||||
.noprint, body>nav, section:after { display: none; }
|
||||
.row { flex-direction: row; }
|
||||
}
|
17
l3config.html
Normal file
17
l3config.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="classless.css">
|
||||
<script src="l3config.js" defer=""></script>
|
||||
<title>l3config</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>l3config</h1>
|
||||
<div id="l3configinput">
|
||||
</div>
|
||||
<div id="l3configoutput">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
198
l3config.js
Normal file
198
l3config.js
Normal file
|
@ -0,0 +1,198 @@
|
|||
"use strict";
|
||||
|
||||
function makeFieldset(legend) {
|
||||
let fieldset = document.createElement('fieldset');
|
||||
let fieldsetlegend = document.createElement('legend');
|
||||
fieldsetlegend.innerHTML = legend;
|
||||
fieldset.appendChild(fieldsetlegend);
|
||||
return fieldset;
|
||||
}
|
||||
|
||||
class L3Section {
|
||||
constructor(legend, ...inputs) {
|
||||
this.legend = legend;
|
||||
this.inputs = inputs;
|
||||
}
|
||||
node() {
|
||||
let fs = makeFieldset(this.legend);
|
||||
let sep = undefined;
|
||||
for (const input of this.inputs) {
|
||||
let div = document.createElement('div');
|
||||
div.append(...input.node());
|
||||
fs.append(div);
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
values() {
|
||||
this.inputs.map((input) => {input.id = input.value;})
|
||||
}
|
||||
render() {
|
||||
const options = this.inputs
|
||||
.map(input => input.option())
|
||||
.filter(option => !!option);
|
||||
|
||||
if (options.length == 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
console.log("options:", options)
|
||||
|
||||
var compiledopts = {};
|
||||
for (const option of options) {
|
||||
if (!compiledopts[option.optionName]) {
|
||||
compiledopts[option.optionName] = [];
|
||||
}
|
||||
compiledopts[option.optionName].push(option.value)
|
||||
}
|
||||
console.log("compiledopts:", compiledopts)
|
||||
|
||||
let optstrs = [];
|
||||
for (const opt in compiledopts) {
|
||||
const values = compiledopts[opt];
|
||||
console.log("values:", values);
|
||||
if (values.length == 1) {
|
||||
optstrs.push(`option ${opt} '${values[0]}'`);
|
||||
} else {
|
||||
for (const value of values) {
|
||||
optstrs.push(`list ${opt} '${value}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return `config ${this.legend}\n\t` + optstrs.join('\n\t')
|
||||
}
|
||||
}
|
||||
|
||||
class L3Input {
|
||||
constructor(label, id, optionName, attrs, datalist) {
|
||||
this.label = label;
|
||||
this.id = id;
|
||||
this.optionName = optionName;
|
||||
this.attrs = attrs;
|
||||
this.datalist = datalist
|
||||
this.input = undefined;
|
||||
}
|
||||
node() {
|
||||
let newLabel = document.createElement('label');
|
||||
newLabel.setAttribute('for', this.id);
|
||||
newLabel.innerHTML = this.label;
|
||||
|
||||
this.input = document.createElement('input');
|
||||
this.input.setAttribute('id', this.id);
|
||||
for (const attr in this.attrs) {
|
||||
this.input.setAttribute(attr, this.attrs[attr]);
|
||||
}
|
||||
|
||||
|
||||
let ret = (this.input.type === 'radio') ? [this.input, newLabel] : [newLabel, this.input];
|
||||
|
||||
if (this.datalist) {
|
||||
let datalist = document.createElement('datalist');
|
||||
let datalistid = this.id + '-datalist';
|
||||
datalist.setAttribute('id', datalistid);
|
||||
this.input.setAttribute('list', datalistid);
|
||||
|
||||
for (const value of this.datalist) {
|
||||
let option = document.createElement('option');
|
||||
option.setAttribute('value', value);
|
||||
datalist.append(option);
|
||||
}
|
||||
|
||||
ret.push(datalist);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
id() {
|
||||
return this.id;
|
||||
}
|
||||
value() {
|
||||
return this.input.value;
|
||||
}
|
||||
option() {
|
||||
switch (this.input.type) {
|
||||
case 'radio':
|
||||
if (!this.input.checked || this.input.value == 'undefined') return undefined;
|
||||
break;
|
||||
default:
|
||||
if (!this.input.value) return undefined;
|
||||
break;
|
||||
}
|
||||
|
||||
const ret = {
|
||||
optionName: this.optionName,
|
||||
value: this.input.value,
|
||||
};
|
||||
|
||||
console.log("option:", ret, this.optionName, this.input.value);
|
||||
return ret;
|
||||
}
|
||||
render() {
|
||||
switch (this.input.type) {
|
||||
case 'radio':
|
||||
if (!this.input.checked || this.input.value == 'undefined') return undefined;
|
||||
break;
|
||||
default:
|
||||
if (!this.input.value) return undefined;
|
||||
break;
|
||||
}
|
||||
|
||||
return `option ${this.optionName} '${this.input.value}'`
|
||||
}
|
||||
}
|
||||
|
||||
function initForm() {
|
||||
let l3configinput = document.getElementById('l3configinput');
|
||||
let form = document.createElement('form');
|
||||
l3configinput.appendChild(form);
|
||||
|
||||
const L3Config = [
|
||||
new L3Section('gateway',
|
||||
new L3Input('name','gatewayName', 'name', {type: 'search', required: '', placeholder: 'Router Name'}),
|
||||
new L3Input('router_ip','gatewayRouterIP', 'router_ip', {type: 'text'}),
|
||||
new L3Input('router_ip6','gatewayRouterIP6', 'router_ip6', {type: 'text'}),
|
||||
),
|
||||
new L3Section('dns',
|
||||
new L3Input('Anycast DNS','dnsAnycast', 'server', {type: 'radio', name: 'anycast', value: 'fd43:5602:29bd:ffff:1:1:1:1', checked: ''}),
|
||||
new L3Input('Anycast DNS64','dnsAnycast64', 'server', {type: 'radio', name: 'anycast', value: 'fd43:5602:29bd:ffff:1:1:1:64'}),
|
||||
new L3Input('Disable','dnsAnycastNone', 'server', {type: 'radio', name: 'anycast', value: undefined}),
|
||||
new L3Input('server','dnsOther', 'server', {type: 'text', placeholder: 'Custom DNS Server'}),
|
||||
),
|
||||
new L3Section('babelpeer',
|
||||
new L3Input('vlan','babelpeerVLAN', 'vlan', {type: 'number', min: 1, max: 4094}),
|
||||
new L3Input('iface','babelpeerIFACE', 'iface', {type: 'text', placeholder: 'eth0, eth0.4, ...'}),
|
||||
new L3Input('type','babelpeerType', 'type', {type: 'search', placeholder: 'wired, wireless, ...'}, ['wired', 'wireless'] ),
|
||||
new L3Input('rxcost','babelpeerRXCOST', 'rxcost', {type: 'number', min: 96, max: 65535, placeholder: 'LAN: 96, Tunnel: 4096, ...'}),
|
||||
),
|
||||
|
||||
];
|
||||
|
||||
form.replaceChildren(...L3Config.map((section) => section.node()));
|
||||
|
||||
function handleUpdate() {
|
||||
console.log(L3Config);
|
||||
renderConfig(L3Config.map(section => section.render()).filter(section => !!section));
|
||||
}
|
||||
|
||||
for (let input of form.getElementsByTagName('input')) {
|
||||
input.addEventListener('input', handleUpdate);
|
||||
}
|
||||
|
||||
renderConfig(L3Config.map(section => section.render()).filter(section => !!section));
|
||||
}
|
||||
|
||||
function renderConfigOption(name, value) {
|
||||
return value ? `\toption ${name} '${value}'\n` : ""
|
||||
}
|
||||
function renderConfig(sections) {
|
||||
let l3configoutput = document.getElementById('l3configoutput');
|
||||
let l3configoutputpre = document.createElement('pre');
|
||||
let code = document.createElement('code');
|
||||
l3configoutputpre.appendChild(code);
|
||||
|
||||
code.innerHTML += sections.join('\n\n');
|
||||
|
||||
l3configoutput.replaceChildren(l3configoutputpre);
|
||||
}
|
||||
|
||||
initForm();
|
Loading…
Reference in New Issue
Block a user