frontend with bootstrap

This commit is contained in:
Tropicananass 2021-10-18 19:56:35 +01:00
parent 2faa518b32
commit 64560b2662
32 changed files with 60493 additions and 176 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,481 @@
/*!
* Bootstrap Reboot v5.1.1 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,478 @@
/*!
* Bootstrap Reboot v5.1.1 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,17 @@
body {
/* min-width: 350px; */
overflow: scroll;
}
.IroColorPicker {
overflow: scroll;
white-space: nowrap;
width: max-content;
}
/* .IroColorPicker>.IroSlider, */
.IroColorPicker>.IroWheel {
margin-right: 12px;
}

View File

@ -0,0 +1,138 @@
<!doctype html>
<html>
<head>
<title>Config</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="description" content="Accueil">
<meta name="author" content="Tropicananass">
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" href="bootstrap-5.1.1-dist/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="index.css" type="text/css">
<script src="bootstrap-5.1.1-dist/js/bootstrap.min.js"></script>
<script src="iro.js"></script>
<script src="index_network_handler.js"></script>
<script src="index_ui_handler.js"></script>
</head>
<body class="bg-dark text-white">
<!-- Modal -->
<div class="modal fade text-black" id="reconnectBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="connectionLostLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="connectionLostLabel">Connection lost</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Try reconnecting in <span id="time-left">60s</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" onclick="{timeout=1;}">Reconnect now</button>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row py-4 text-center" id="header">
<h1> Tropicananass Leds </h1>
</div>
<div class="row pt-2 gy-2">
<div class="col d-flex justify-content-center">
<form id="mode-input" class="btn-group" role="group" aria-label="Select mode">
<input type="radio" class="btn-check" name="mode-selection" id="test-mode" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="mode-selection" id="artnet-mode" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="mode-selection" id="auto-mode" autocomplete="off" value="2">
<input type="radio" class="btn-check" name="mode-selection" id="manual-mode" autocomplete="off" value="3">
</form>
</div>
<div class="col d-flex justify-content-center">
<form id="pattern-input" class="btn-group" role="group" aria-label="Select pattern">
<input type="radio" class="btn-check" name="pattern-selection" id="pulse-pattern" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="pattern-selection" id="travel-pattern" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="pattern-selection" id="strobe-pattern" autocomplete="off" value="2">
</form>
</div>
</div>
<div class="row pt-2 gy-2">
<legend class="col-12 col-sm-auto">Channel</legend>
<!-- <div class="col d-flex justify-content-center">
<form id="channelGlobal-input" class="btn-group" role="group" aria-label="Select channel">
<input type="radio" class="btn-check" name="channelGlobal-selection" id="all-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channelGlobal-selection" id="none-channel" autocomplete="off">
</form>
</div> -->
<div class="col d-flex justify-content-center">
<form id="channel-input" class="btn-group" role="group" aria-label="Select channel">
<!-- todo: Change to checkbox -->
<input type="radio" class="btn-check" name="channel-selection" id="all-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="0-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="1-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="2-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="3-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="4-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="5-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="6-channel" autocomplete="off" checked>
<input type="radio" class="btn-check" name="channel-selection" id="7-channel" autocomplete="off" checked>
</form>
</div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Sensitivity</label>
<span class="col-3 col-sm-1 text-end">50</span>
<div class="col col-sm-9">
<input type="range" class="form-range" id="formControlRange" oninput="rangeCallback(this)">
</div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Gravity</label>
<span class="col-3 col-sm-1 text-end">50</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" oninput="rangeCallback(this)">
</div>
</div>
<div class="row pt-2 gy-2">
<div class="col">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="modulateColor" onclick="colorModulateCallback(this)">
<label class="form-check-label" for="modulateColor">Modulate color</label>
</div>
</div>
</div>
<div class="row pt-2 gy-2">
<div id="mainPicker" class="col d-flex justify-content-center"></div>
<div id="modulationPicker" class="col d-none d-flex justify-content-center"></div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Modulation speed</label>
<span class="col-3 col-sm-auto text-end" id="rangeval">50</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" oninput="rangeCallback(this)">
</div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Freq</label>
<span class="col-3 col-sm-auto text-end" id="rangeval">50</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" oninput="rangeCallback(this)">
</div>
</div>
</div>
</body>
</html>
<script src="index.js"></script>

View File

@ -0,0 +1,77 @@
var socket;
var timer;
var timeout;
var modal = new bootstrap.Modal(document.getElementById("reconnectBackdrop"));
var slectedChannel = 8;
function addLabelAndListener(name, callback) {
let rootElement = document.getElementById(name + "-input")
rootElement.addEventListener('click', callback);
let inputArray = rootElement.elements[name + "-selection"];
for (let inputIndex = 0; inputIndex < inputArray.length; inputIndex++) {
let element = inputArray[inputIndex]
let label = document.createElement("label");
label.classList.add("btn");
label.classList.add("btn-outline-primary");
label.classList.add("text-capitalize");
label.setAttribute("for", element.id);
labelText = element.id.split('-')[0];
label.innerHTML = labelText;
element.insertAdjacentElement("afterend", label);
}
}
addLabelAndListener("mode", modeSelectCallback);
addLabelAndListener("pattern", patternSelectCallback);
addLabelAndListener("channel", channelSelectCallback);
// addLabelAndListener("channelGlobal", channelSelectCallback);
var colorPicker = new iro.ColorPicker('#mainPicker', {
colors: [
'hsl(0, 100, 50)', // pure red
'hsl(180, 50, 100)' // pure green
],
layout: [{
component: iro.ui.Wheel,
options: {
wheelLightness: false
}
}, {
component: iro.ui.Slider,
options: {
sliderType: 'value'
}
}],
layoutDirection: 'horizontal',
// display: "flex",
width: 250,
margin: 0,
handleRadius: 14
});
var modulationPicker = new iro.ColorPicker('#modulationPicker', {
colors: [
'hsl(0, 100, 50)', // pure red
],
layout: [{
component: iro.ui.Wheel,
options: {
wheelLightness: false
}
}, {
component: iro.ui.Slider,
options: {
sliderType: 'value'
}
}],
layoutDirection: 'horizontal',
// display: "flex",
width: 250,
margin: 0,
handleRadius: 14
});
reconnect();
colorPicker.on("color:change", colorChangeCallback);
modulationPicker.on("color:change", colorChangeCallback);

View File

@ -0,0 +1,51 @@
function wait_reconnection() {
--timeout;
document.getElementById("time-left").innerHTML = timeout + "s";
if (timeout == 0) {
clearInterval(timer);
reconnect();
}
}
function reconnect() {
socket = new WebSocket("ws://tropicananass.ovh:8080");
timeout = 60;
socket.onopen = function(e) {
console.log("[open] ws: Connection established");
clearInterval(timer);
modal.hide();
};
socket.onmessage = function(event) {
console.log(`[message] ws: Data received from server: ${event.data}`);
let message = event.data.split(":");
let command = message[0];
let payload = message[1];
console.log(command + ", " + payload);
switch (command) {
case 'm':
document.getElementById("mode-input").elements["mode-selection"][payload].checked = true;
break;
default:
break;
}
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
console.log('[close] ws: Connection died');
timer = setInterval(wait_reconnection, 1000);
modal.show();
}
};
socket.onerror = function(error) {
console.log(`[error] ws: ${error.message}`);
};
}

View File

@ -0,0 +1,69 @@
function modeSelectCallback(event) {
// todo: disable form on this != auto
if (event.target.nodeName == 'INPUT') {
console.log("m:" + event.target.value);
if (socket.readyState == WebSocket.OPEN) {
socket.send("m:" + event.target.value);
}
}
}
function patternSelectCallback(event) {
// todo: disable form on this != auto
if (event.target.nodeName == 'INPUT') {
console.log("p:" + event.target.value);
if (socket.readyState == WebSocket.OPEN) {
socket.send("p:" + event.target.value);
}
}
}
function channelSelectCallback(event) {
if (event.target.nodeName == 'INPUT') {
channel = event.target.id.split("-")[0];
if (channel == "all") {
// inputArray = document.getElementById("channel-input").elements[name + "channel-selection"]
// for (let inputIndex = 0; inputIndex < inputArray.length; inputIndex++) {
// inputArray[inputIndex].checked = false;
// }
selectedChannel = 8;
} else if (channel == "none") {
inputArray = document.getElementById("channel-input").elements[name + "channel-selection"]
for (let inputIndex = 0; inputIndex < inputArray.length; inputIndex++) {
inputArray[inputIndex].checked = false;
}
selectedChannel = -1;
} else {
inputArray = document.getElementById("channelGlobal-input").elements[name + "channelGlobal-selection"]
for (let inputIndex = 0; inputIndex < inputArray.length; inputIndex++) {
inputArray[inputIndex].checked = false;
}
selectedChannel = channel;
}
console.log("channel:" + selectedChannel);
}
}
var eventd;
function colorModulateCallback(element) {
eventd = element;
if (element.checked) {
document.getElementById("modulationPicker").classList.remove("d-none");
} else {
document.getElementById("modulationPicker").classList.add("d-none");
}
console.log("s: " + element.checked);
}
function colorChangeCallback(color) {
console.log("c: " + color.index + ", h: " + color.hsl.h + ", s: " + color.hsl.s + ", l: " + color.hsl.l + "}");
if (socket.readyState == WebSocket.OPEN) {
socket.send("c:" + color.index + "," + color.hsl.h + "," + color.hsl.s + "," + color.hsl.l);
}
}
function rangeCallback(element) {
eventd = this
element.parentNode.parentElement.getElementsByTagName('span')[0].innerText = element.value;
}

View File

@ -1,80 +0,0 @@
html,
body,
.page {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
background: #434d5a;
font-family: "Roboto";
}
.page {
top: 0px;
left: 0px;
}
.window {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 1);
padding: 1em;
}
h1 {
color: #7e8c9f;
font-size: 50px;
margin: 2em 0px;
padding: 0px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: default;
text-align: center;
}
h1 {
text-align: center;
}
h1 #enc {
font-size: 80px;
font-weight: bold;
}
#picker {
display: flex;
justify-content: space-around;
}
.IroColorPicker {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: center;
justify-content: space-around;
}
#reconnect {
position: fixed;
visibility: hidden;
background: rgba(0, 0, 0, .5);
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
}
#reconnect .window div {
color: rgb(165, 165, 165);
font-family: monospace;
font-size: 2em;
font-weight: bold;
margin-bottom: .5em;
}

View File

@ -1,34 +0,0 @@
<!doctype html>
<html>
<head>
<title>Config</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="description" content="Accueil">
<meta name="author" content="Tropicananass">
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" href="index.css" type="text/css">
<script src="iro.js"></script>
<script src="index.js"></script>
</head>
<body>
<div id="reconnect" class="page">
<div class="window">
<div>Disconnected from server</div>
<button type="button" onclick="reconnect(this)">Reconnect</button>
</div>
</div>
<div class="page">
<div>
<h1> Tropicananass Leds </h1>
</div>
<div id="picker"></div>
</div>
</body>
</html>

View File

@ -1,62 +0,0 @@
let socket;
function reconnect() {
socket = new WebSocket("ws://192.168.1.130:8080");
socket.onopen = function(e) {
console.log("[open] ws: Connection established");
document.getElementById("reconnect").style.visibility = 'hidden';
};
socket.onmessage = function(event) {
console.log(`[message] ws: Data received from server: ${event.data}`);
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
console.log('[close] ws: Connection died');
document.getElementById("reconnect").style.visibility = 'visible';
}
};
socket.onerror = function(error) {
console.log(`[error] ws: ${error.message}`);
};
}
var colorPicker = new iro.ColorPicker('#picker', {
colors: [
'hsl(0, 100, 50)', // pure red
'hsl(180, 50, 100)' // pure green
],
layout: [{
component: iro.ui.Wheel,
options: {}
}, {
component: iro.ui.Box,
options: {}
},
{
component: iro.ui.Slider,
options: {
// can also be 'saturation', 'value', 'red', 'green', 'blue', 'alpha' or 'kelvin'
sliderType: 'value'
}
}
],
display: "flex",
handleRadius: 14,
});
// make a handler function
function colorChangeCallback(color) {
console.log("{index: " + color.index + ", h: " + color.hsl.h + ", s: " + color.hsl.s + ", l: " + color.hsl.l + "}");
socket.send("{" + color.index + "," + color.hsl.h + "," + color.hsl.s + "," + color.hsl.l + "}");
}
reconnect();
colorPicker.on("color:change", colorChangeCallback);