Added source code, MZ6500 module still not complete

This commit is contained in:
Philip Smart
2022-09-04 14:51:38 +01:00
parent 8bba3b0e92
commit 96a69cc86d
74 changed files with 30544 additions and 69 deletions

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/css/bootstrap.min.css.gz

Binary file not shown.

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/css

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/css/jquery.edittable.min.css

18
webserver/css/jquery.edittable.min.css vendored Normal file
View File

@@ -0,0 +1,18 @@
table.inputtable{width:100%;border:1px solid #ddd;border-collapse:collapse;border-spacing:0;-moz-box-shadow:0 1px 3px rgba(0,0,0,.075);-webkit-box-shadow:0 1px 3px rgba(0,0,0,.075);box-shadow:0 1px 3px rgba(0,0,0,.075);margin:15px 0}
table.inputtable a.icon-button{background-color:#ccc;display:inline-block;width:18px;height:18px;text-decoration:none;color:#fff;font-weight:800;line-height:16px;text-align:center;font-size:14px;-moz-border-radius:1px;-webkit-border-radius:1px;border-radius:1px;-moz-box-shadow:0 0 1px rgba(0,0,0,0.2);-webkit-box-shadow:0 0 1px rgba(0,0,0,0.2);box-shadow:0 0 1px rgba(0,0,0,0.2)}
table.inputtable a.icon-button.addcol,table.inputtable a.icon-button.addrow{background-color:#81b71a}
table.inputtable a.icon-button.delcol,table.inputtable a.icon-button.delrow{background-color:#db4a39}
table.inputtable a.icon-button.disabled{background-color:#eee}
table.inputtable td:last-child,table.inputtable th:last-child{width:54px;border:1px solid #eee;border-right:thick;}
table.inputtable td,table.inputtable th{border:1px solid #eee;text-align:center;height:40px;vertical-align:middle;font-size:14px}
table.inputtable th{background-color:#f1f1f1;border-top:none;border-bottom:2px solid #ddd;border-color:#ddd}
table.inputtable td input[type=text]{border:0;width:90%;height:100%;text-align:center;padding:0 5%}
table.inputtable tr td input:focus{background-color:#fafafa}
table.inputtable.wh tbody tr:nth-child(1),table.inputtable.wh tbody tr:nth-child(1) input{background-color:#fdfdfd;font-weight:800}
table.inputtable th:first-child,table.inputtable td:first-child{border-left:none}
table.inputtable tr:last-child td{border-bottom:none}
@media only screen and max-width 480px {
table.inputtable td,table.inputtable th{min-width:40px;height:80px}
table.inputtable a.icon-button{width:40px;height:40px;font-size:18px;min-width:40px;line-height:40px;margin:3px 0}
table.inputtable td input{height:80px}
}

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/css/sb-admin.css

159
webserver/css/sb-admin.css Normal file
View File

@@ -0,0 +1,159 @@
/*
Author: Start Bootstrap - http://startbootstrap.com
'SB Admin' HTML Template by Start Bootstrap
All Start Bootstrap themes are licensed under Apache 2.0.
For more info and more free Bootstrap 3 HTML themes, visit http://startbootstrap.com!
*/
/* ATTN: This is mobile first CSS - to update 786px and up screen width use the media query near the bottom of the document! */
/* Global Styles */
body {
margin-top: 50px;
}
#wrapper {
padding-left: 0;
}
#page-wrapper {
width: 100%;
padding: 5px 15px;
}
/* Nav Messages */
.messages-dropdown .dropdown-menu .message-preview .avatar,
.messages-dropdown .dropdown-menu .message-preview .name,
.messages-dropdown .dropdown-menu .message-preview .message,
.messages-dropdown .dropdown-menu .message-preview .time {
display: block;
}
.messages-dropdown .dropdown-menu .message-preview .avatar {
float: left;
margin-right: 15px;
}
.messages-dropdown .dropdown-menu .message-preview .name {
font-weight: bold;
}
.messages-dropdown .dropdown-menu .message-preview .message {
font-size: 12px;
}
.messages-dropdown .dropdown-menu .message-preview .time {
font-size: 12px;
}
/* Nav Announcements */
.announcement-heading {
font-size: 50px;
margin: 0;
}
.announcement-text {
margin: 0;
}
/* Table Headers */
table.tablesorter thead {
cursor: pointer;
}
table.tablesorter thead tr th:hover {
background-color: #f5f5f5;
}
/* Flot Chart Containers */
.flot-chart {
display: block;
height: 400px;
}
.flot-chart-content {
width: 100%;
height: 100%;
}
/* Edit Below to Customize Widths > 768px */
@media (min-width:768px) {
/* Wrappers */
#wrapper {
padding-left: 225px;
}
#page-wrapper {
padding: 15px 25px;
}
/* Side Nav */
.side-nav {
margin-left: -225px;
left: 225px;
width: 225px;
position: fixed;
top: 50px;
height: 100%;
border-radius: 0;
border: none;
background-color: #222222;
overflow-y: auto;
}
/* Bootstrap Default Overrides - Customized Dropdowns for the Side Nav */
.side-nav>li.dropdown>ul.dropdown-menu {
position: relative;
min-width: 225px;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
background-color: transparent;
box-shadow: none;
-webkit-box-shadow: none;
}
.side-nav>li.dropdown>ul.dropdown-menu>li>a {
color: #999999;
padding: 15px 15px 15px 25px;
}
.side-nav>li.dropdown>ul.dropdown-menu>li>a:hover,
.side-nav>li.dropdown>ul.dropdown-menu>li>a.active,
.side-nav>li.dropdown>ul.dropdown-menu>li>a:focus {
color: #fff;
background-color: #080808;
}
.side-nav>li>a {
width: 225px;
}
.navbar-inverse .navbar-nav>li>a:hover,
.navbar-inverse .navbar-nav>li>a:focus {
background-color: #080808;
}
/* Nav Messages */
.messages-dropdown .dropdown-menu {
min-width: 300px;
}
.messages-dropdown .dropdown-menu li a {
white-space: normal;
}
}

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/css/sharpkey.css

266
webserver/css/sharpkey.css Normal file
View File

@@ -0,0 +1,266 @@
.wm-button {
width: 95px;
height: 25px;
background: blue;
border: none;
vertical-align: top;
margin-left: 25px;
cursor: pointer;
color: white;
transition: 2s;
border-radius: 12px;
}
.wm-button:disabled {
background: #999;
color: #555;
cursor: not-allowed;
}
.wm-button:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
input[type="file"] {
display: none;
}
.firmware-file-upload {
width: 95px;
height: 25px;
background: blue;
border: none;
vertical-align: middle;
text-align: center;
line-height: 25px;
margin-left: 35px;
margin-bottom: 0px;
cursor: pointer;
color: white;
transition: 2s;
border-radius: 12px;
}
.firmware-file-upload:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
.keymap-file-upload {
width: 95px;
height: 25px;
background: blue;
border: none;
vertical-align: middle;
text-align: center;
line-height: 25px;
margin-left: 35px;
margin-bottom: 0px;
cursor: pointer;
color: white;
transition: 2s;
border-radius: 12px;
}
.keymap-file-upload:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
input[type=file]::file-selector-button {
border: 2px solid #6c5ce7;
padding: .2em .4em;
border-radius: .2em;
background-color: #a29bfe;
transition: 1s;
}
input[type=file]::file-selector-button:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
.sk-modules-table {
border: none;
border-collapse: collapse;
}
.sk-modules-table caption {
padding-bottom: 0.5em;
}
.sk-modules-table th, .sk-modules-table td {
border: none;
padding: 0.2rem 2rem;
}
.sk-modules-table td {
white-space: nowrap;
}
.sk-modules-table th {
font-weight: normal;
}
.sk-modules-table td {
border-style: none;
vertical-align: top;
}
.sk-modules-table th {
padding: 0.2em;
vertical-align: middle;
text-align: center;
}
.sk-modules-table tbody td:first-child::after {
content: leader(". ");
}
.sk-client-wifi-config-table {
border: none;
border-collapse: collapse;
width: 1px !important;
table-layout: auto !important;
}
.sk-client-wifi-config-table caption {
padding-bottom: 0.5em;
}
.sk-client-wifi-config-table th, .sk-client-wifi-config-table td {
border: none;
padding: 0.2rem 2rem;
padding-left: 0;
padding-right: 4rem;
}
.sk-client-wifi-config-table td {
white-space: nowrap;
overflow: hidden;
border-style: none;
vertical-align: top;
width: auto !important;
}
.sk-client-wifi-config-table th {
font-weight: normal;
padding: 0.2em;
vertical-align: middle;
text-align: center;
width: auto !important;
}
#client-wifi-config-area {
overflow-x: scroll;
width: fit-content;
}
#firmware-revision-area {
overflow-x: scroll;
width: fit-content;
}
#esp32-partitions-area {
overflow-x: scroll;
width: fit-content;
}
.sk-partitions-table {
border: none;
border-collapse: collapse;
}
.sk-partitions-table caption {
padding-bottom: 0.5em;
}
.sk-partitions-table th, .sk-partitions-table td {
border: none;
padding: 0.2rem 2rem;
}
.sk-partitions-table td {
white-space: nowrap;
border-style: none;
vertical-align: top;
}
.sk-partitions-table th {
font-weight: normal;
padding: 0.2em;
vertical-align: middle;
text-align: center;
}
.sk-partitions-table tbody td:first-child::after {
content: leader(". ");
}
.sk-partitions-table tbody td:nth-child(4) {
text-align: right;
}
.sk-partitions-table tbody td:nth-child(5) {
text-align: right;
}
.sk-partitions-table tbody td:nth-child(6) {
text-align: center;
}
.sk-partitions-table tbody td:nth-child(8) {
text-align: center;
}
.table-condensed .progress {
margin-bottom: 0 !important;
width: 400px;
display: none;
}
.table-borderless > tbody > tr > td,
.table-borderless > thead > tr > td,
.table-borderless {
border-bottom: 0;
border-top: 0;
padding: 4px;
padding-top: 2px;
padding-bottom: 0;
white-space: nowrap;
}
.table-responsive {
border-bottom: 0;
border-top: 0;
border-left: 0;
border-right: 0;
padding: 4px;
padding-top: 2px;
padding-bottom: 0;
white-space: nowrap;
table-layout: auto;
}
.table {
margin-bottom: 10px;
}
.justify {
text-align: justify;
text-justify: inter-word;
}
.keymap {
max-height: 36.2em;
overflow: auto;
}
.hr_no_margin {
margin-top: 0.2em;
margin-bottom: 0.2em;
}
fieldset {
overflow: hidden;
}
.radio-mouse {
padding-right: 1em;
}
.radio-mouse label {
float: left;
clear: none;
display: block;
padding: 0px 1em 0px 8px;
}
input[type=radio] .radio-mouse,
input.radio .radio-mouse {
float: left;
clear: none;
margin: 2px 0 0 2px;
}

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/css/style.css

253
webserver/css/style.css Normal file
View File

@@ -0,0 +1,253 @@
/*
body {
margin: 0;
}
*/
/*
h1 {
text-align: center;
font-family: Tahoma, Arial, sans-serif;
color: #06D85F;
margin: 10px;
}
*/
.box {
width: 40%;
margin: 0 auto;
background: rgba(255,255,255,0.2);
padding: 35px;
border: 2px solid #fff;
border-radius: 20px/50px;
background-clip: padding-box;
text-align: center;
}
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
//transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 30%;
position: relative;
transition: all 5s ease-in-out;
}
.popup h2 {
margin-top: 0;
color: #333;
font-family: Tahoma, Arial, sans-serif;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.popup .close:hover {
color: #06D85F;
}
.popup .content {
max-height: 30%;
overflow: auto;
}
@media screen and (max-width: 700px){
.box{
width: 90%;
}
.popup{
width: 90%;
}
}
/*
html {
font-family: Arial, Helvetica, sans-serif;
display: inline-block;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
p {
font-size: 1.1rem;
}
*/
.topnav {
overflow: hidden;
background-color: #0A1128;
}
.content {
padding: 5%;
}
.card-grid {
max-width: 800px;
margin: 0 auto;
display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.card {
background-color: lightyellow;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
}
.card-title {
font-size: 1.1rem;
font-weight: bold;
color: #034078
}
/*
input[type=submit] {
border: none;
color: #FEFCFB;
background-color: #034078;
padding: 15px 15px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 18px;
width: 30%;
margin-right: 10px;
border-radius: 4px;
transition-duration: 0.4s;
}
input[type=submit]:hover {
background-color: #1282A2;
}
input[type=text], input[type=number], select {
width: 40%;
padding: 8px 10px;
margin: 12px;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=url], input[type=number], select {
width: 50%;
padding: 12px 20px;
margin: 18px;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
label {
font-size: 1rem;
}
*/
.value{
font-size: 1rem;
color: #1282A2;
}
.state {
font-size: 1rem;
color: #1282A2;
}
.button {
font-size: 2em;
padding: 3px;
color: #dbd75e;
border: 1px solid #000;
border-radius: 5px;
text-decoration: none;
cursor: pointer;
transition: all 1s ease-out;
background: #1b06d8;
}
.button:hover {
background: #06D85F;
}
/*
button {
//border: none;
// color: #FEFCFB;
// padding: 15px 32px;
// text-align: center;
// font-size: 30px;
// width: 100px;
// border-radius: 4px;
transition-duration: 0.4s;
}
.button-on {
// background-color: #034078;
}
.button-on:hover {
// background-color: #1282A2;
}
.button-off {
// background-color: #858585;
}
.button-off:hover {
// background-color: #252524;
}
*/
#sk-modules-table {
border: solid thin;
border-collapse: collapse;
}
#sk-modules-table caption {
padding-bottom: 0.5em;
}
#sk-modules-table th,
#sk-modules-table td {
border: solid thin;
padding: 0.5rem 2rem;
}
#sk-modules-table td {
white-space: nowrap;
}
#sk-modules-table th {
font-weight: normal;
}
#sk-modules-table td {
border-style: none solid;
vertical-align: top;
}
#sk-modules-table th {
padding: 0.2em;
vertical-align: middle;
text-align: center;
}
#sk-modules-table tbody td:first-child::after {
content: leader(". ");
}

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/css/styles.css

1
webserver/css/styles.css Normal file
View File

@@ -0,0 +1 @@
body { padding-bottom: 70px; }

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/favicon.ico

Before

Width:  |  Height:  |  Size: 36 B

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
webserver/favicon.ico Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 B

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1 +0,0 @@
../../../../sharpkey/webserver/font-awesome/css

View File

@@ -1 +0,0 @@
../../../../sharpkey/webserver/font-awesome/css/font-awesome.css

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
../../../../sharpkey/webserver/font-awesome/css/font-awesome.min.css

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
../../../../sharpkey/webserver/font-awesome/css/font-awesome.min.css.orig

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/font-awesome

View File

@@ -1 +0,0 @@
../../../../sharpkey/webserver/font-awesome/fonts/fontawesome-webfont.woff

Binary file not shown.

View File

@@ -1 +0,0 @@
../../../../sharpkey/webserver/font-awesome/fonts

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/images

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/index.html

166
webserver/index.html Normal file
View File

@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard - SharpKey Admin</title>
<!-- Bootstrap core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Add custom CSS here -->
<link href="css/sb-admin.css" rel="stylesheet">
<link href="css/sharpkey.css" rel="stylesheet">
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">
</head>
<body>
<div id="wrapper">
<!-- Sidebar -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">SharpKey Interface</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav side-nav">
<li class="active"><a href="index.html"><i class="fa fa-dashboard"></i> Status</a></li>
<li id="keyMapAvailable"><a href="keymap.html"><i class="fa fa-keyboard-o"></i> %SK_CURRENTIF%Keymap</a></li>
<li id="mouseCfgAvailable"><a href="mouse.html"><i class="fa fa-mouse-pointer"></i> Mouse Config</a></li>
<li><a href="ota.html"><i class="fa fa-file"></i> OTA Update</a></li>
<li><a href="wifimanager.html"><i class="fa fa-wifi"></i> WiFi Manager</a></li>
<li><a href="reboot"><i class="fa fa-power-off"></i> Reboot</a></li>
</ul>
<ul class="nav navbar-nav navbar-right navbar-user">
<li class="dropdown user-dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-gear"></i> Settings <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#"><i class="fa fa-gear"></i> Settings</a></li>
<li class="divider"></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<h1>Status </h1>
<ol class="breadcrumb">
<li class="active"><i class="fa fa-dashboard"></i> Status</li>
</ol>
<div class="alert alert-success alert-dismissable justify">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<p>Welcome to the SharpKey embedded browser based configuration App which enables keyboard map changes, mouse configuration, <u>O</u>ver <u>T</u>he <u>A</u>ir firmware updates and more.<br>No help text is available as NVRAM is at a premium, so please read the documentation if you need help.</p>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-wifi"></i> WiFi Configuration</h3>
</div>
<div class="panel-body">
<div class="table-responsive">
<div id="client-wifi-config-area">
<div id="wifiCfg%SK_WIFIMODEAP%">
<table class="table table-borderless table-sm">
<tbody>
<tr style="display: compact;">
<td>SSID:</td><td><span style="color: blue;">%SK_APSSID%</span></td>
</tr>
<tr style="display: compact;">
<td>Password:</td><td><span style="color: blue;">%SK_APPWD%</span></td>
</tr>
<tr>
<td>IP (AP):</td><td><span style="color: blue;">%SK_CURRENTIP%</span></td>
<td>NETMASK:</td><td><span style="color: blue;">%SK_CURRENTNM%</span></td>
<td>GATEWAY:</td><td><span style="color: blue;">%SK_CURRENTGW%</span></td>
</tr>
</tbody>
</table>
</div>
<div id="wifiCfg0%SK_WIFIMODECLIENT%">
<table class="table table-borderless table-sm">
<tbody>
<tr style="display: compact;">
<td>SSID:</td><td><span style="color: blue;">%SK_CLIENTSSID%</span></td>
</tr>
<tr style="display: compact;" id="wifiCfg1%SK_CLIENTDHCPON%">
<td>DHCP:</td><td><span style="color: blue;">Enabled</span></td>
</tr>
<tr id="wifiCfg3%SK_CLIENTDHCPON%">
<td>IP (assigned):</td><td><span style="color: blue;">%SK_CURRENTIP%</span></td>
<td>NETMASK:</td><td><span style="color: blue;">%SK_CURRENTNM%</span></td>
<td>GATEWAY:</td><td><span style="color: blue;">%SK_CURRENTGW%</span></td>
</tr>
<tr id="wifiCfg3%SK_CLIENTDHCPOFF%">
<td>IP (fixed):</td><td><span style="color: blue;">%SK_CURRENTIP%</span></td>
<td>NETMASK:</td><td><span style="color: blue;">%SK_CURRENTNM%</span></td>
<td>GATEWAY:</td><td><span style="color: blue;">%SK_CURRENTGW%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-file"></i> Version Information</h3>
</div>
<div class="panel-body">
<div class="table-responsive">
<div id="firmware-revision-area">
%SK_PRODNAME% v%SK_PRODVERSION% &copy; P.D. Smart, 2018-22<br><br>
<b>Modules</b><br>
%SK_MODULES%
<b>File Pack</b><br>
%SK_FILEPACK%
</div>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
</div><!-- /#page-wrapper -->
</div><!-- /#wrapper -->
<!-- JavaScript -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script>
// Store the name of the active and secondary interfaces.
const activeInterface = "%SK_CURRENTIF%";
const secondaryInterface = "%SK_SECONDIF%"
</script>
<script src="js/index.js"></script>
</body>
</html>

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/140medley.min.js

2
webserver/js/140medley.min.js vendored Normal file
View File

@@ -0,0 +1,2 @@
var t=function(a,b){return function(c,d){return a.replace(/#{([^}]*)}/g,function(a,f){return Function("x","with(x)return "+f).call(c,d||b||{})})}},s=function(a,b){return b?{get:function(c){return a[c]&&b.parse(a[c])},set:function(c,d){a[c]=b.stringify(d)}}:{}}(this.localStorage||{},JSON),p=function(a,b,c,d){c=c||document;d=c[b="on"+b];a=c[b]=function(e){d=d&&d(e=e||c.event);return(a=a&&b(e))?b:d};c=this},m=function(a,b,c){b=document;c=b.createElement("p");c.innerHTML=a;for(a=b.createDocumentFragment();b=
c.firstChild;)a.appendChild(b);return a},$=function(a,b){a=a.match(/^(\W)?(.*)/);return(b||document)["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2])},j=function(a){for(a=0;a<4;a++)try{return a?new ActiveXObject([,"Msxml2","Msxml3","Microsoft"][a]+".XMLHTTP"):new XMLHttpRequest}catch(b){}};

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/bootstrap.min.js.gz

Binary file not shown.

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/index.js

66
webserver/js/index.js Normal file
View File

@@ -0,0 +1,66 @@
function showIPConfig()
{
if(document.getElementById("wifiCfg0checked"))
{
document.getElementById("wifiCfg0checked").style.display = 'compact';
document.getElementById("wifiCfg").style.display = 'none';
if(document.getElementById("wifiCfg3checked"))
{
document.getElementById("wifiCfg3checked").style.display = 'compact';
document.getElementById("wifiCfg3").style.display = 'none';
} else
{
document.getElementById("wifiCfg3checked").style.display = 'none';
document.getElementById("wifiCfg3").style.display = 'compact';
}
if(document.getElementById("wifiCfg1checked"))
{
document.getElementById("wifiCfg1checked").style.display = 'compact';
} else
{
document.getElementById("wifiCfg1").style.display = 'none';
}
} else
{
document.getElementById("wifiCfg0").style.display = 'none';
document.getElementById("wifiCfgchecked").style.display = 'compact';
}
}
// Method to enable the correct side-bar menu for the underlying host interface.
function enableIfConfig()
{
// Disable keymap if no host is connected to the SharpKey. KeyInterface is the base class which exists when
// no host was detected to invoke a host specific sub-class.
if(activeInterface === "KeyInterface ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
}
// Mouse interface active?
else if(activeInterface === "Mouse ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("keyMapAvailable").style.display = 'compact';
// Secondary interface available?
if(secondaryInterface == "Mouse ")
{
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("mouseCfgAvailable").style.display = 'none';
}
}
}
// On document load, setup the items viewable on the page according to set values.
document.addEventListener("DOMContentLoaded", function setPageDefaults()
{
showIPConfig();
enableIfConfig();
});

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/jquery.edittable.js

View File

@@ -0,0 +1,340 @@
/*! editTable v0.2.0 by Alessandro Benoit */
(function ($, window, i) {
'use strict';
$.fn.editTable = function (options) {
// Settings
var s = $.extend({
data: [['']],
tableClass: 'inputtable',
jsonData: false,
headerCols: false,
maxRows: 999,
first_row: true,
row_template: false,
field_templates: false,
validate_field: function (col_id, value, col_type, $element) {
return true;
}
}, options),
$el = $(this),
defaultTableContent = '<thead><tr></tr></thead><tbody></tbody>',
$table = $('<table/>', {
class: s.tableClass + ((s.first_row) ? ' wh' : ''),
html: defaultTableContent
}),
addRowCallBack = null,
defaultth = '<th><a class="addcol fa fa-plus" style="color: green" href="#"></a> <a class="delcol fa fa-minus" style="color: red" href="#"></a></th>',
colnumber,
rownumber,
reset,
is_validated = true;
// Increment for IDs
i = i + 1;
// Build cell
function buildCell(content, type) {
content = (content === 0) ? "0" : (content || '');
// Custom type
if (type && 'text' !== type){
var field = s.field_templates[type];
return '<td>' + field.setValue(field.html, content)[0].outerHTML + '</td>';
}
// Default
return '<td><input type="text" value="' + content.toString().replace(/"/g, "&quot;") + '" /></td>';
}
// Build row
function buildRow(data, len) {
var rowcontent = '', b;
data = data || '';
if (!s.row_template) {
// Without row template
for (b = 0; b < (len || data.length); b += 1) {
rowcontent += buildCell(data[b]);
}
} else {
// With row template
for (b = 0; b < s.row_template.length; b += 1) {
// For each field in the row
rowcontent += buildCell(data[b], s.row_template[b]);
}
}
return $('<tr/>', {
html: rowcontent + '<td> <a class="addrow fa fa-plus" style="color: green" href="#"></a> / <a class="delrow fa fa-minus" style="color: red" href="#"></a></td>'
});
}
// Check button status (enable/disabled)
function checkButtons() {
if (colnumber < 2) {
$table.find('.delcol').addClass('disabled');
}
if (rownumber < 2) {
$table.find('.delrow').addClass('disabled');
}
if (s.maxRows && rownumber === s.maxRows) {
$table.find('.addrow').addClass('disabled');
}
}
// Extension method to change or set the table header. This method should be called before fillTableData.
function setTableHeader(header) {
s.headerCols = header;
}
// Extension method to change or set the table column types. This method should be called before fillTableData.
function setTableType(types) {
s.row_template = types;
}
// Fill table with data
function fillTableData(data) {
var a, crow = Math.min(s.maxRows, data.length);
// Clear table
$table.html(defaultTableContent);
// If headers or row_template are set
if (s.headerCols || s.row_template) {
// Fixed columns
var col = s.headerCols || s.row_template;
// Table headers
for (a = 0; a < col.length; a += 1) {
var col_title = s.headerCols[a] || '';
$table.find('thead tr').append('<th>' + col_title + '</th>');
}
$table.find('thead tr').append('<th><span class="fa fa-table"></span></th>');
// Table content
for (a = 0; a < crow; a += 1) {
// For each row in data
buildRow(data[a], col.length).appendTo($table.find('tbody'));
}
} else if ( data[0] ) {
// Variable columns
for (a = 0; a < data[0].length; a += 1) {
$table.find('thead tr').append(defaultth);
}
for (a = 0; a < crow; a += 1) {
buildRow(data[a]).appendTo($table.find('tbody'));
}
}
// Append missing th
//$table.find('thead tr').append('<th></th>');
// Count rows and columns
colnumber = $table.find('thead th').length - 1;
rownumber = $table.find('tbody tr').length;
checkButtons();
}
// Export data
function exportData() {
var row = 0, data = [], value;
is_validated = true;
$table.find('tbody tr').each(function () {
row += 1;
data[row] = [];
$(this).find('td:not(:last-child)').each(function (i, v) {
if ( s.row_template && 'text' !== s.row_template[i] ){
var field = s.field_templates[s.row_template[i]],
el = $(this).find($(field.html).prop('tagName'));
value = field.getValue(el);
if ( !s.validate_field(i, value, s.row_template[i], el) ){
is_validated = false;
}
data[row].push(value);
} else {
value = $(this).find('input[type="text"]').val();
if ( !s.validate_field(i, value, 'text', v) ){
is_validated = false;
}
data[row].push(value);
}
});
});
// Remove undefined
data.splice(0, 1);
return data;
}
// Fill the table with data from textarea or given properties
if ($el.is('textarea')) {
try {
reset = JSON.parse($el.val());
} catch (e) {
reset = s.data;
}
$el.after($table);
// If inside a form set the textarea content on submit
if ($table.parents('form').length > 0) {
$table.parents('form').submit(function () {
$el.val(JSON.stringify(exportData()));
});
}
} else {
reset = (JSON.parse(s.jsonData) || s.data);
$el.append($table);
}
fillTableData(reset);
// Add column
$table.on('click', '.addcol', function () {
var colid = parseInt($(this).closest('tr').children().index($(this).parent('th')), 10);
colnumber += 1;
$table.find('thead tr').find('th:eq(' + colid + ')').after(defaultth);
$table.find('tbody tr').each(function () {
$(this).find('td:eq(' + colid + ')').after(buildCell());
});
$table.find('.delcol').removeClass('disabled');
return false;
});
// Remove column
$table.on('click', '.delcol', function () {
if ($(this).hasClass('disabled')) {
return false;
}
var colid = parseInt($(this).closest('tr').children().index($(this).parent('th')), 10);
colnumber -= 1;
checkButtons();
$(this).parent('th').remove();
$table.find('tbody tr').each(function () {
$(this).find('td:eq(' + colid + ')').remove();
});
return false;
});
// Add row
$table.on('click', '.addrow', function () {
if ($(this).hasClass('disabled')) {
return false;
}
rownumber += 1;
$(this).closest('tr').after(buildRow(0, colnumber));
$table.find('.delrow').removeClass('disabled');
checkButtons();
// Addition, raise callback after row has been added.
if(addRowCallBack)
{
addRowCallBack(rownumber, $(this).closest('tr').next('tr'), $table);
}
return false;
});
// Delete row
$table.on('click', '.delrow', function () {
if ($(this).hasClass('disabled')) {
return false;
}
rownumber -= 1;
checkButtons();
$(this).closest('tr').remove();
$table.find('.addrow').removeClass('disabled');
return false;
});
// Select all content on click
$table.on('click', 'input', function () {
$(this).select();
});
// Return functions
return {
// Get an array of data
getData: function () {
return exportData();
},
// Get the JSON rappresentation of data
getJsonData: function () {
return JSON.stringify(exportData());
},
// Load an array of data
loadData: function (data) {
reset = data;
fillTableData(data);
},
// Load a JSON rappresentation of data
loadJsonData: function (data) {
reset = JSON.parse(data);
fillTableData(JSON.parse(data));
},
// Extension method to change or set the table header. This method should be called before fillTableData.
setHeaders: function (headers) {
setTableHeader(headers);
},
// Extension method to change or set the table column types. This method should be called before fillTableData.
setTypes: function (types) {
setTableType(types);
},
// Reset data to the first instance
reset: function () {
fillTableData(reset);
},
isValidated: function () {
return is_validated;
},
addRowCallBack: function (func) {
addRowCallBack = func;
}
};
};
})(jQuery, this, 0);

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/jquery.edittable.min.js

2
webserver/js/jquery.edittable.min.js vendored Normal file
View File

@@ -0,0 +1,2 @@
/*! editTable v0.2.0 by Alessandro Benoit */
(function(e,t,n){"use strict";e.fn.editTable=function(t){function p(e,t){e=e===0?"0":e||"";if(t&&"text"!==t){var n=r.field_templates[t];return"<td>"+n.setValue(n.html,e)[0].outerHTML+"</td>"}return'<td><input type="text" value="'+e.toString().replace(/"/g,"&quot;")+'" /></td>'}function d(t,n){var i="",s;t=t||"";if(!r.row_template){for(s=0;s<(n||t.length);s+=1){i+=p(t[s])}}else{for(s=0;s<r.row_template.length;s+=1){i+=p(t[s],r.row_template[s])}}return e("<tr/>",{html:i+'<td><a class="addrow icon-button" href="#">+</a> <a class="delrow icon-button" href="#">-</a></td>'})}function v(){if(f<2){u.find(".delcol").addClass("disabled")}if(l<2){u.find(".delrow").addClass("disabled")}if(r.maxRows&&l===r.maxRows){u.find(".addrow").addClass("disabled")}}function m(e){var t,n=Math.min(r.maxRows,e.length);u.html(o);if(r.headerCols||r.row_template){var i=r.headerCols||r.row_template;for(t=0;t<i.length;t+=1){var s=r.headerCols[t]||"";u.find("thead tr").append("<th>"+s+"</th>")}for(t=0;t<n;t+=1){d(e[t],i.length).appendTo(u.find("tbody"))}}else if(e[0]){for(t=0;t<e[0].length;t+=1){u.find("thead tr").append(a)}for(t=0;t<n;t+=1){d(e[t]).appendTo(u.find("tbody"))}}u.find("thead tr").append("<th></th>");f=u.find("thead th").length-1;l=u.find("tbody tr").length;v()}function g(){var t=0,n=[],i;h=true;u.find("tbody tr").each(function(){t+=1;n[t]=[];e(this).find("td:not(:last-child)").each(function(s,o){if(r.row_template&&"text"!==r.row_template[s]){var u=r.field_templates[r.row_template[s]],a=e(this).find(e(u.html).prop("tagName"));i=u.getValue(a);if(!r.validate_field(s,i,r.row_template[s],a)){h=false}n[t].push(i)}else{i=e(this).find('input[type="text"]').val();if(!r.validate_field(s,i,"text",o)){h=false}n[t].push(i)}})});n.splice(0,1);return n}var r=e.extend({data:[[""]],tableClass:"inputtable",jsonData:false,headerCols:false,maxRows:999,first_row:true,row_template:false,field_templates:false,validate_field:function(e,t,n,r){return true}},t),s=e(this),o="<thead><tr></tr></thead><tbody></tbody>",u=e("<table/>",{"class":r.tableClass+(r.first_row?" wh":""),html:o}),a='<th><a class="addcol icon-button" href="#">+</a> <a class="delcol icon-button" href="#">-</a></th>',f,l,c,h=true;n=n+1;if(s.is("textarea")){try{c=JSON.parse(s.val())}catch(y){c=r.data}s.after(u);if(u.parents("form").length>0){u.parents("form").submit(function(){s.val(JSON.stringify(g()))})}}else{c=JSON.parse(r.jsonData)||r.data;s.append(u)}m(c);u.on("click",".addcol",function(){var t=parseInt(e(this).closest("tr").children().index(e(this).parent("th")),10);f+=1;u.find("thead tr").find("th:eq("+t+")").after(a);u.find("tbody tr").each(function(){e(this).find("td:eq("+t+")").after(p())});u.find(".delcol").removeClass("disabled");return false});u.on("click",".delcol",function(){if(e(this).hasClass("disabled")){return false}var t=parseInt(e(this).closest("tr").children().index(e(this).parent("th")),10);f-=1;v();e(this).parent("th").remove();u.find("tbody tr").each(function(){e(this).find("td:eq("+t+")").remove()});return false});u.on("click",".addrow",function(){if(e(this).hasClass("disabled")){return false}l+=1;e(this).closest("tr").after(d(0,f));u.find(".delrow").removeClass("disabled");v();return false});u.on("click",".delrow",function(){if(e(this).hasClass("disabled")){return false}l-=1;v();e(this).closest("tr").remove();u.find(".addrow").removeClass("disabled");return false});u.on("click","input",function(){e(this).select()});return{getData:function(){return g()},getJsonData:function(){return JSON.stringify(g())},loadData:function(e){m(e)},loadJsonData:function(e){m(JSON.parse(e))},reset:function(){m(c)},isValidated:function(){return h}}}})(jQuery,this,0)

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/jquery.min.js.gz

Binary file not shown.

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/keymap.js

653
webserver/js/keymap.js Normal file
View File

@@ -0,0 +1,653 @@
// Method to display a message in a message field. The existing html is saved and replaced
// with the new html. After a timeout period the original html is restored.
//
$origMessage = null;
$origId = null;
$msgTimerId = null;
function showMessage(timeout, id, message)
{
// Is this a new message whilst one is active?
if($origMessage !== null)
{
// Cancel timer and restore original message.
clearTimeout($msgTimerId);
$('#' + $origId).html($origMessage);
}
// Store original message and Id so that on timer expiry it can be replaced..
$origMessage = $('#' + id).html();
$origId = id;
// Change HTML and set timer to restore it.
$('#' + id).html(message);
$msgTimerId = setTimeout(function(msgFieldId)
{
$('#' + msgFieldId).html($origMessage);
$origMessage = null;
}, timeout, id);
}
// Ajax download function, from user:leo on stackexchange, customised for this application.
//
function downloadFile()
{
var req = new XMLHttpRequest();
var downloadUrl = "/keymap";
req.open("GET", downloadUrl, true);
req.responseType = "blob";
req.onload = function (event)
{
var blob = req.response;
var fileName = null;
var contentType = req.getResponseHeader("content-type");
// IE/EDGE seems not returning some response header
if (req.getResponseHeader("content-disposition"))
{
var contentDisposition = req.getResponseHeader("content-disposition");
fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
} else
{
fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
}
if (window.navigator.msSaveOrOpenBlob)
{
// Internet Explorer
window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
} else
{
var el = document.getElementById("keymapDownloadLink");
el.href = window.URL.createObjectURL(blob);
el.download = fileName;
el.click();
}
};
showMessage(1000, 'keymapMsg', "<p style=\"color:orange;\">Downloading keymap file, please wait...</p>");
req.send();
}
// Listener for the Download button click. Once clicked commence download via ajax function.
//
document.getElementById('keymapDownload').onclick = function keymapFileDownload(e)
{
downloadFile();
}
// Listener for an event change on the INPUT file tag 'keymapUpload'. Once pressed and a filename available, this method
// commences transmission via a POST method to the SharpKey server.
document.getElementById('keymapUpload').onchange = function keymapFileUpload(e)
{
var fileInput = document.getElementById("keymapUpload").files;
// Reset the last status. Used to track state change.
lastStatus = 0;
// Client side checks, no point initiating an upload if the file isnt valid!
if (fileInput.length == 0)
{
alert("No file selected!");
// Sane size check, a keymap entry is 6-12 bytes long, so a 1000 rows should be the max size.
} else if (fileInput[0].size > 12*1024)
{
alert("File size must be less than 12KB!");
} else
{
var xhttp;
if(window.XMLHttpRequest)
{
xhttp = new XMLHttpRequest();
} else
{
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// Install listeners to handle state change.
xhttp.onreadystatechange = function()
{
if (xhttp.readyState == 4)
{
lastStatus = xhttp.status;
if (xhttp.status == 200)
{
showMessage(5000, 'keymapMsg', "<p style=\"color:green;\">Upload complete. Please press <b>Reboot</b> to activate new key map.</p>");
} else if (xhttp.status == 500)
{
showMessage(5000, 'keymapMsg', "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>");
}
else if (xhttp.status == 0)
{
showMessage(5000, 'keymapMsg', "<p style=\"color:red;\">Error: Server closed the connection abrubtly, status unknown! - Please retry or press Reboot</p>");
} else
{
showMessage(5000, 'keymapMsg', "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>");
}
}
};
showMessage(10000, 'keymapMsg', "<p style=\"color:orange;\">Uploading keymap file, please wait...</p>");
xhttp.open("POST", "/keymap", true);
xhttp.send(fileInput[0]);
}
}
// Method to enable the correct side-bar menu for the underlying host interface.
function enableIfConfig()
{
// Disable keymap if no host is connected to the SharpKey. KeyInterface is the base class which exists when
// no host was detected to invoke a host specific sub-class.
if(activeInterface === "KeyInterface ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
}
// Mouse interface active?
else if(activeInterface === "Mouse ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("keyMapAvailable").style.display = 'compact';
// Secondary interface available?
if(secondaryInterface == "Mouse ")
{
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("mouseCfgAvailable").style.display = 'none';
}
}
}
// Method to validate a hex input field. Basically call hexConvert and it will return a
// valid number, 0 if invalid or 255 if out of range.
function validateHexInput(event)
{
event.target.value=hexConvert(event.target.value, false);
return true;
};
// Use variables to remember last popover and value as the popover mechanism, probably due to race states, isnt uniform.
// Also use the shown/hidden events and toggle as hide doesnt trigger reliably.
var $currentPopover = null;
var $currentPopoverVal = -1;
var $currentClass = null;
var $currentSelectCount = 0;
var $currentTimerId = null;
var $currentDataSetModified = false;
function updateButtons()
{
if($currentSelectCount == 2)
{
$('#keymapSwap').removeAttr('disabled');
} else
{
$('#keymapSwap').attr('disabled', 'disabled');
}
if($currentSelectCount > 0)
{
$('#keymapDelete').removeAttr('disabled');
} else
{
$('#keymapDelete').attr('disabled', 'disabled');
}
if($currentDataSetModified == true)
{
$('#keymapSave').removeAttr('disabled');
$('#keymapReload').removeAttr('disabled');
} else
{
$('#keymapSave').attr('disabled', 'disabled');
$('#keymapReload').attr('disabled', 'disabled');
}
}
function addPopover(field, tableRow)
{
// Popover auto-hide timer alarm.
const popoverAlarm = {
setup: function(timerId, timeout) {
if (timerId != null) {
timerId = this.cancel(timerId);
}
timerId = setTimeout(function() {
if($currentPopover) {
$currentPopover.popover('toggle');
}
}, timeout);
return(timerId);
},
cancel: function(timerId) {
clearTimeout(timerId);
timerId = null;
return(timerId);
},
};
// Setup popover menus on each custom field to aid with conversion of a feature into a hex number.
$(field).popover({
html: true,
title: function () {
return $('#popover-' + field.className).find('.head').html();
},
content: function () {
return $('#popover-' + field.className).find('.content').html();
}
})
.on("show.bs.popover", function(e)
{
var className = this.getAttribute('class');
var $target = $(e.target);
// Detect a class change, user has gone from one column to another, need to close out current
// popover ready for initialisation of new.
if($currentClass != null && $currentClass != className)
{
if($currentPopover)
{
if($currentTimerId != 0)
{
$currentTimerId = popoverAlarm.cancel($currentTimerId);
}
if ($currentPopover && ($currentPopover.get(0) != $target.get(0))) {
$currentPopover.popover('toggle');
}
$currentPopover = null;
}
}
$currentClass = className;
if($currentPopover)
{
$currentPopoverVal = 0;
$('#popover-' + field.className).find('input').each( function( index ) {
if($(this).attr("checked") === "checked")
{
$currentPopoverVal += parseInt(this.getAttribute('data-value'), 10);
}
});
} else
{
$currentPopoverVal = -1;
}
// Go through all the checkboxes and setup the initial value.
$('#popover-' + field.className).find('input').each( function( index ) {
if((e.target.value & this.getAttribute('data-value')) == this.getAttribute('data-value'))
{
$(this).attr('checked', true);
} else
{
$(this).attr('checked', false);
}
});
})
.on("shown.bs.popover", function(e)
{
var $target = $(e.target);
if ($currentPopover && ($currentPopover.get(0) != $target.get(0))) {
$currentPopover.popover('toggle');
}
$currentPopover = $target;
// Setup an alarm to remove a visible popover if not clicked closed.
$currentTimerId = popoverAlarm.setup($currentTimerId, 5000);
})
.on("hidden.bs.popover", function(e)
{
var $target = $(e.target);
if ($currentPopover && ($currentPopover.get(0) == $target.get(0))) {
if($currentPopoverVal == -1)
{
$currentPopoverVal = 0;
$('#popover-' + field.className).find('input').each( function( index ) {
if($(this).attr("checked") === "checked")
{
$currentPopoverVal += parseInt(this.getAttribute('data-value'), 10);
}
});
}
if(e.target.value != hexConvert($currentPopoverVal, false))
{
e.target.value = hexConvert($currentPopoverVal, false);
$currentDataSetModified = true;
updateButtons();
}
$currentPopover = null;
// Cancel the alarm on the hidden popover.
$currentTimerId = popoverAlarm.cancel($currentTimerId);
}
$currentPopoverVal = -1;
})
.on("hide.bs.popover", function(e)
{
// $currentTimerId = popoverAlarm.cancel($currentTimerId);
})
.on("click", function(e)
{
console.log('click: ' + e.target.value);
})
.on("change", function(e)
{
if(e.target.className === 'checkbox')
{
if($(e.target).attr('checked') == 'checked')
{
$currentSelectCount += 1;
//$(e.target).attr("checked", true);
}
else if($(e.target).attr('checked') != 'checked')
{
$currentSelectCount -= 1;
//$(e.target).attr("checked", false);
}
} else
{
if(e.target.value != hexConvert($currentPopoverVal, false))
{
e.target.value = hexConvert(e.target.value, false);
$currentDataSetModified = true;
}
}
updateButtons();
})
.blur(function () {
});
// End popover definition
// Only attach popover handlers to classes in the first row, subsequent rows will use the same popover.
//
if(tableRow == 1)
{
var search = '#popover-' + field.className;
$(search + ' input').each(function () {
$('body').on('click', '#' + this.id, function(e) {
$currentTimerId = popoverAlarm.setup($currentTimerId, 5000);
$(search + ' input').each(function() {
if(this.id === e.target.id)
{
$(this).attr("checked", e.target.checked ? true : false);
}
});
});
});
}
}
// Method to convert a string/numeric into a hex number and range check it to be within and 8bit unsigned range.
function hexConvert(inVal, invert)
{
if(isNaN(inVal) == true && isNaN('0x' + inVal) == false)
{
inVal = parseInt(inVal, 16);
}
else if(isNaN(inVal) == false && typeof inVal == 'string' && inVal.length > 0)
{
if(inVal.toUpperCase().indexOf("0X") == 0)
{
inVal = parseInt(inVal, 16);
} else
{
inVal = parseInt(inVal, 10);
}
}
else if(isNaN(inVal) == true || inVal.length == 0)
{
inVal = 0;
}
if(inVal < 0)
{
inVal = 0;
}
else if(inVal > 255)
{
inVal = 255;
}
if(invert == true)
{
inVal = (~inVal) & 0xFF;
}
return('0x' + (inVal).toString(16).toUpperCase());
}
// Method to swap 2 tables rows. This is necessary as the keymap table has top down priority in mapping.
function swapKeyMapData()
{
// Locals.
var firstRow = null;
var secondRow = null;
// Get row numbers of the rows to be swapped.
var rowcnt = 1;
$('.inputtable tr .checkbox').each(function() {
if(firstRow == null && this.checked == true)
{
firstRow = rowcnt;
} else
if(firstRow != null && secondRow == null && this.checked == true)
{
secondRow = rowcnt;
}
rowcnt++;
});
// If rows were matched (should be due to count) then perform swap.
if(firstRow != null && secondRow != null)
{
$('.inputtable > tbody > tr:nth-child(' + firstRow + ')').replaceWith($('.inputtable > tbody > tr:nth-child(' + secondRow + ')').after($('.inputtable > tbody > tr:nth-child(' + firstRow + ')').clone(true)));
}
// Update the modified state and update button state.
$currentDataSetModified = true;
updateButtons();
return true;
}
// Method to delete 1 or multiple rows. An individual row can be deleted by the +/- buttons but multiple requires selection and then running through the table, deleting the selected rows.
function deleteKeyMapData()
{
// Locals.
var toDeleteRows = [];
// Get row numbers of the rows to be swapped.
var rowcnt = 1;
$('.inputtable tr .checkbox').each(function() {
if(this.checked == true)
{
toDeleteRows.push(rowcnt);
}
rowcnt++;
});
// Iterate through the array of rows to delete and actually perform the deletion.
// We work in reverse order, ie. deleting the last row first due to the index changing if we delete first to last.
for(var idx = toDeleteRows.length; idx > 0; idx--)
{
$('.inputtable > tbody > tr:nth-child(' + toDeleteRows[idx-1] + ')').remove();
}
// Reset the select counter and update button state.
$currentSelectCount = 0;
$currentDataSetModified = true;
updateButtons();
return true;
}
// Method to save the current keymap table data to the interface.
function saveKeyMapData()
{
var data = keymapTable.getData();
// Reset the last status. Used to track state change.
lastStatus = 0;
// Client side checks, no point initiating an upload if the file isnt valid!
if(data.length == 0)
{
alert("No data to save!!");
} else
{
var xhttp;
if(window.XMLHttpRequest)
{
xhttp = new XMLHttpRequest();
} else
{
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// Install listeners to handle state change.
xhttp.onreadystatechange = function()
{
if (xhttp.readyState == 4)
{
lastStatus = xhttp.status;
if (xhttp.status == 200)
{
showMessage(5000, 'keymapEditorMsg', "<p style=\"color:green;\">Upload complete. Please press <b>Reboot</b> to activate new key map.</p>");
// Reset the data modified flag and update button state.
$currentDataSetModified = false;
updateButtons();
} else if (xhttp.status == 500)
{
showMessage(5000, 'keymapEditorMsg', "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>");
}
else if (xhttp.status == 0)
{
showMessage(5000, 'keymapEditorMsg', "<p style=\"color:red;\">Error: Server closed the connection abrubtly, status unknown! - Please retry Save</p>");
} else
{
showMessage(5000, 'keymapEditorMsg', "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>");
}
}
};
showMessage(5000, 'keymapEditorMsg', "<p style=\"color:orange;\">Uploading keymap data, please wait...</p>");
xhttp.open("POST", "/keymap/table", true);
xhttp.send(JSON.stringify(data));
}
return true;
}
// Method to reload the initial table data set.
function reloadKeyMapData()
{
// Request reload of the initial data.
keymapTable.reset();
// Re-install the listeners as the old dataset was deleted.
setupTableListeners();
// Complete message.
showMessage(5000, 'keymapEditorMsg', "<p style=\"color:green;\">Reload complete, data reset to initial values.</p>");
// Reset the select counter and update button state.
$currentSelectCount = 0;
$currentDataSetModified = false;
updateButtons();
return true;
}
// Callback function triggered after a row has been added to the edittable. Use the event to add popover listeners to the new fields.
//
function tableRowAdded(row, rowHandle, tableHandle)
{
$(rowHandle).children().children().each(function() {
if(this.className !== "")
{
addPopover(this, 0);
}
});
}
// Method to install listeners on the table data for popover aids.
//
function setupTableListeners()
{
// Setup a popover on each input field where a modal exists.
$('.inputtable >tbody > tr').each(function (tridx) {
// We seperate out the Row from the input as we want to watch every input but only setup 1 popover per input type.
$(this).find('input').each(function (inpidx) {
if(this.className !== "")
{
addPopover(this, tridx);
}
});
});
//
// Setup a callback on new rows added to table.
keymapTable.addRowCallBack(tableRowAdded);
}
$(document).ready(function() {
// Load up the table headers, types and data. This is done with JQuery fetch as it is easier. The SharpKey is synchronous
// but fetch order can vary so we nest the requests to ensure all headers and types are in place before the data.
fetch('/data/keymap/table/headers')
.then((response) => {
return(response.json());
})
.then((headers) => {
keymapTable.setHeaders(headers);
fetch('/data/keymap/table/types')
.then((response) => {
return(response.json());
})
.then((types) => {
keymapTable.setTypes(types);
fetch('/data/keymap/table/data')
.then((response) => {
return(response.json());
})
.then((data) => {
keymapTable.loadData(data);
setupTableListeners();
});
});
});
// Disable buttons, enabled when user action requires them.
$('#keymapSwap').attr('disabled', 'disabled');
$('#keymapDelete').attr('disabled', 'disabled');
$('#keymapSave').attr('disabled', 'disabled');
$('#keymapReload').attr('disabled', 'disabled');
// Add listeners to the buttons.
$('#keymapSwap').on('click', function() { swapKeyMapData(); });
$('#keymapDelete').on('click', function() { deleteKeyMapData(); });
$('#keymapSave').on('click', function() { saveKeyMapData(); });
$('#keymapReload').on('click', function() { reloadKeyMapData(); });
// Setup the menu options according to underlying interface.
enableIfConfig();
});

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/mouse.js

141
webserver/js/mouse.js Normal file
View File

@@ -0,0 +1,141 @@
// Method to display a message in a message field. The existing html is saved and replaced
// with the new html. After a timeout period the original html is restored.
//
$origMessage = null;
$origId = null;
$msgTimerId = null;
function showMessage(timeout, id, message)
{
// Is this a new message whilst one is active?
if($origMessage !== null)
{
// Cancel timer and restore original message.
clearTimeout($msgTimerId);
$('#' + $origId).html($origMessage);
}
// Store original message and Id so that on timer expiry it can be replaced..
$origMessage = $('#' + id).html();
$origId = id;
// Change HTML and set timer to restore it.
$('#' + id).html(message);
$msgTimerId = setTimeout(function(msgFieldId)
{
$('#' + msgFieldId).html($origMessage);
$origMessage = null;
}, timeout, id);
}
// Method to enable the correct side-bar menu for the underlying host interface.
function enableIfConfig()
{
// Disable keymap if no host is connected to the SharpKey. KeyInterface is the base class which exists when
// no host was detected to invoke a host specific sub-class.
if(activeInterface === "KeyInterface ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
}
// Mouse interface active?
else if(activeInterface === "Mouse ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("keyMapAvailable").style.display = 'compact';
// Secondary interface available?
if(secondaryInterface == "Mouse ")
{
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("mouseCfgAvailable").style.display = 'none';
}
}
}
// Method to convert a string/numeric into a hex number and range check it to be within and 8bit unsigned range.
function hexConvert(inVal, invert)
{
if(isNaN(inVal) == true && isNaN('0x' + inVal) == false)
{
inVal = parseInt(inVal, 16);
}
else if(isNaN(inVal) == false && typeof inVal == 'string' && inVal.length > 0)
{
if(inVal.toUpperCase().indexOf("0X") == 0)
{
inVal = parseInt(inVal, 16);
} else
{
inVal = parseInt(inVal, 10);
}
}
else if(isNaN(inVal) == true || inVal.length == 0)
{
inVal = 0;
}
if(inVal < 0)
{
inVal = 0;
}
else if(inVal > 255)
{
inVal = 255;
}
if(invert == true)
{
inVal = (~inVal) & 0xFF;
}
return('0x' + (inVal).toString(16).toUpperCase());
}
$(document).ready(function() {
// Setup the menu options according to underlying interface.
enableIfConfig();
// AJAX code to post in a controlled manner so that we can receive back an error/success message to the commit.
$("#mouseHostCfgSave").submit( function(e)
{
var form = $(this);
var actionUrl = form.attr('action');
// Prevent default submit action, we want to manually submit and be able to receive a response for errors/success.
e.preventDefault();
$.ajax(
{
type: "POST",
url: actionUrl,
data: form.serialize(), // serializes the form's elements.
success: function(data)
{
// Show the message then revert back to original text.
showMessage(10000, "mouseHostCfgMsg", data);
}
});
});
$("#mousePS2CfgSave").submit( function(e)
{
var form = $(this);
var actionUrl = form.attr('action');
// Prevent default submit action, we want to manually submit and be able to receive a response for errors/success.
e.preventDefault();
$.ajax(
{
type: "POST",
url: actionUrl,
data: form.serialize(), // serializes the form's elements.
success: function(data)
{
// Show the message then revert back to original text.
showMessage(10000, "mousePS2CfgMsg", data);
}
});
});
});

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/ota.js

300
webserver/js/ota.js Normal file
View File

@@ -0,0 +1,300 @@
var lastStatus = 0;
// Method to display a message in a message field. The existing html is saved and replaced
// with the new html. After a timeout period the original html is restored.
//
$origMessage = null;
$origId = null;
$msgTimerId = null;
function showMessage(timeout, id, message)
{
// Is this a new message whilst one is active?
if($origMessage !== null)
{
// Cancel timer and restore original message.
clearTimeout($msgTimerId);
$('#' + $origId).html($origMessage);
}
// Store original message and Id so that on timer expiry it can be replaced..
$origMessage = $('#' + id).html();
$origId = id;
// Change HTML and set timer to restore it.
$('#' + id).html(message);
$msgTimerId = setTimeout(function(msgFieldId)
{
$('#' + msgFieldId).html($origMessage);
$origMessage = null;
}, timeout, id);
}
// Clear the file input array.
function clearFileInput(ctrl)
{
try {
ctrl.value = null;
} catch(ex) { }
if (ctrl.value) {
ctrl.parentNode.replaceChild(ctrl.cloneNode(true), ctrl);
}
}
// Firmware handlers.
document.getElementById('firmwareUpload').onchange = function getFirmwareFileName(e)
{
var default_path = document.getElementById("firmwareUpload").files[0].name;
// Put the name of the file into the table cell.
document.getElementById('firmwareName').innerHTML = "<b>&#61;&gt;</b>" + default_path;
document.getElementById('firmwareUpgrade').value = document.getElementById('firmwareUpload').files[0].name;
// Disable select and enable upgrade/cancel.
document.getElementById('firmwareUploadLabel').style.display = 'none';
document.getElementById('firmwareUpgrade').disabled = false;
document.getElementById('firmwareUpgrade').style.display = 'block';
document.getElementById('firmwareCancel').disabled = false;
document.getElementById('firmwareCancel').style.display = 'block';
document.getElementById('firmwareMsg').innerHTML = "Press <b>Upgrade</b> to upload and flash the firmware into the SharpKey or <b>Cancel</b> to cancel and re-select file.";
}
document.getElementById('firmwareCancel').onclick = function cancelFirmwareUpload(e)
{
var default_path = document.getElementById("firmwareUpload").files[0].name;
// Reset the selected filename.
document.getElementById('firmwareName').innerHTML = "";
document.getElementById('firmwareUpgrade').value = [];
clearFileInput(document.getElementById('firmwareUpload'));
// Enable select and disable upgrade/cancel.
document.getElementById('firmwareUploadLabel').style.display = 'block';
document.getElementById('firmwareUpgrade').disabled = true;
document.getElementById('firmwareUpgrade').style.display = 'none';
document.getElementById('firmwareCancel').disabled = true;
document.getElementById('firmwareCancel').style.display = 'none';
document.getElementById('firmwareMsg').innerHTML = "Select a firmware image file with which to upgrade the SharpKey Operating System.";
}
// Firmware upgrade handler.
function firmwareUpdateProgress(e)
{
if (e.lengthComputable)
{
var percentage = Math.round((e.loaded/e.total)*100);
document.getElementById('firmwareProgressBar').style.width = percentage + '%';
}
else
{
document.getElementById('firmwareProgressBar').innerHTML = "Unable to compute progress information since the total size is unknown";
}
}
document.getElementById('firmwareUpgrade').onclick = function firmwareUpload()
{
var fileInput = document.getElementById("firmwareUpload").files;
// Reset the last status. Used to track state change.
lastStatus = 0;
// Client side checks, no point initiating a firmware update if the file isnt valid!
if (fileInput.length == 0)
{
alert("No file selected!");
} else if (fileInput[0].size > 1664*1024)
{
alert("File size must be less than 1.6MB!");
} else
{
document.getElementById("firmwareUpload").disabled = true;
document.getElementById("firmwareUploadLabel").style.display = 'none';
document.getElementById("firmwareUpgrade").disabled = true;
document.getElementById("firmwareUpgrade").style.display = 'none';
document.getElementById("firmwareCancel").style.display = 'none';
document.getElementById("firmwareProgress").style.display = 'block';
var xhttp;
if(window.XMLHttpRequest)
{
xhttp = new XMLHttpRequest();
} else
{
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// Install listeners to
xhttp.upload.addEventListener("progress", firmwareUpdateProgress, false);
xhttp.onreadystatechange = function()
{
if (xhttp.readyState == 4)
{
lastStatus = xhttp.status;
if (xhttp.status == 200)
{
document.getElementById('firmwareMsg').innerHTML = "<p style=\"color:green;\">Transfer complete, firmware successfully flashed onto the SharpKey. Please press <b>Reboot</b> to activate.</p>";
document.getElementById("firmwareProgress").style.display = 'none';
document.getElementById('firmwareName').style.display = 'none';
} else if (xhttp.status == 500)
{
document.getElementById('firmwareMsg').innerHTML = "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>";
}
else if (xhttp.status == 0)
{
document.getElementById('firmwareMsg').innerHTML = "<p style=\"color:red;\">Error: Server closed the connection abrubtly, flash status unknown! - Press Reboot</p>";
} else
{
document.getElementById('firmwareMsg').innerHTML = "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>";
}
}
};
document.getElementById('firmwareMsg').innerHTML = "<p style=\"color:orange;\">Uploading and flashing the new firmware, please wait...</p>";
xhttp.open("POST", "/ota/firmware", true);
xhttp.send(fileInput[0]);
}
}
// Filepack handlers.
document.getElementById('filepackUpload').onchange = function getFilepackFileName(e)
{
var default_path = document.getElementById("filepackUpload").files[0].name;
// Put the name of the file into the table cell.
document.getElementById('filepackName').innerHTML = "<b>&#61;&gt;</b>" + default_path;
document.getElementById('filepackUpgrade').value = document.getElementById('filepackUpload').files[0].name;
// Disable select and enable upgrade/cancel.
document.getElementById('filepackUploadLabel').style.display = 'none';
document.getElementById('filepackUpgrade').disabled = false;
document.getElementById('filepackUpgrade').style.display = 'block';
document.getElementById('filepackCancel').disabled = false;
document.getElementById('filepackCancel').style.display = 'block';
document.getElementById('filepackWarning').style.display = 'block';
document.getElementById('filepackMsg').innerHTML = "Press <b>Upgrade</b> to upload and flash the filepack onto the SharpKey filesystem or <b>Cancel</b> to cancel and re-select file.";
}
document.getElementById('filepackCancel').onclick = function cancelFilepackUpload(e)
{
var default_path = document.getElementById("filepackUpload").files[0].name;
// Reset the selected filename.
document.getElementById('filepackName').innerHTML = "";
clearFileInput(document.getElementById('filepackUpload'));
// Enable select and disable upgrade/cancel.
document.getElementById('filepackUploadLabel').style.display = 'block';
document.getElementById('filepackUpgrade').disabled = true;
document.getElementById('filepackUpgrade').style.display = 'none';
document.getElementById('filepackCancel').disabled = true;
document.getElementById('filepackCancel').style.display = 'none';
document.getElementById('filepackWarning').style.display = 'none';
document.getElementById('filepackMsg').innerHTML = "Select a filepack image file with which to upgrade the SharpKey filesystem.";
}
// Filepack upgrade handler.
function filepackUpdateProgress(e)
{
if (e.lengthComputable)
{
var percentage = Math.round((e.loaded/e.total)*100);
document.getElementById('filepackProgressBar').style.width = percentage + '%';
}
else
{
document.getElementById('filepackProgressBar').innerHTML = "Unable to compute progress information since the total size is unknown";
}
}
document.getElementById('filepackUpgrade').onclick = function filepackUpload()
{
var fileInput = document.getElementById("filepackUpload").files;
// Reset the last status. Used to track state change.
lastStatus = 0;
// Client side checks, no point initiating a filepack update if the file isnt valid!
if (fileInput.length == 0)
{
alert("No file selected!");
} else if (fileInput[0].size > 640*1024)
{
alert("File size must be less than 640K!");
} else
{
document.getElementById("filepackUpload").disabled = true;
document.getElementById("filepackUploadLabel").style.display = 'none';
document.getElementById("filepackUpgrade").disabled = true;
document.getElementById("filepackUpgrade").style.display = 'none';
document.getElementById("filepackCancel").style.display = 'none';
document.getElementById("filepackProgress").style.display = 'block';
var xhttp;
if(window.XMLHttpRequest)
{
xhttp = new XMLHttpRequest();
} else
{
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// Install listeners to
xhttp.upload.addEventListener("progress", filepackUpdateProgress, false);
xhttp.onreadystatechange = function()
{
if (xhttp.readyState == 4)
{
lastStatus = xhttp.status;
if (xhttp.status == 200)
{
document.getElementById('filepackMsg').innerHTML = "<p style=\"color:green;\">Transfer complete, filepack successfully flashed onto SharpKey filesystem. Please press <b>Reboot</b> to activate.</p>";
document.getElementById("filepackProgress").style.display = 'none';
document.getElementById('filepackName').style.display = 'none';
} else if (xhttp.status == 500)
{
document.getElementById('filepackMsg').innerHTML = "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>";
}
else if (xhttp.status == 0)
{
document.getElementById('filepackMsg').innerHTML = "<p style=\"color:red;\">Error: Server closed the connection abrubtly, flash status unknown! - Press Reboot</p>";
} else
{
document.getElementById('filepackMsg').innerHTML = "<p style=\"color:red;\">Error: " + xhttp.responseText + " - Press Reboot</p>";
}
}
};
document.getElementById('filepackMsg').innerHTML = "<p style=\"color:orange;\">Uploading and flashing the new filepack, please wait...</p>";
xhttp.open("POST", "/ota/filepack", true);
xhttp.send(fileInput[0]);
}
}
// Method to enable the correct side-bar menu for the underlying host interface.
function enableIfConfig()
{
// Disable keymap if no host is connected to the SharpKey. KeyInterface is the base class which exists when
// no host was detected to invoke a host specific sub-class.
if(activeInterface === "KeyInterface ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
}
// Mouse interface active?
else if(activeInterface === "Mouse ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("keyMapAvailable").style.display = 'compact';
// Secondary interface available?
if(secondaryInterface == "Mouse ")
{
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("mouseCfgAvailable").style.display = 'none';
}
}
}
// On document load, setup the items viewable on the page according to set values.
document.addEventListener("DOMContentLoaded", function setPageDefaults()
{
enableIfConfig();
});

View File

@@ -1 +0,0 @@
../../../sharpkey/webserver/js/wifimanager.js

178
webserver/js/wifimanager.js Normal file
View File

@@ -0,0 +1,178 @@
// Method to display a message in a message field. The existing html is saved and replaced
// with the new html. After a timeout period the original html is restored.
//
$origMessage = null;
$origId = null;
$msgTimerId = null;
function showMessage(timeout, id, message)
{
// Is this a new message whilst one is active?
if($origMessage !== null)
{
// Cancel timer and restore original message.
clearTimeout($msgTimerId);
$('#' + $origId).html($origMessage);
}
// Store original message and Id so that on timer expiry it can be replaced..
$origMessage = $('#' + id).html();
$origId = id;
// Change HTML and set timer to restore it.
$('#' + id).html(message);
$msgTimerId = setTimeout(function(msgFieldId)
{
$('#' + msgFieldId).html($origMessage);
$origMessage = null;
}, timeout, id);
}
function showWiFiAPInput()
{
document.getElementById('inputWiFiClient').style.display = 'none';
document.getElementById('inputWiFiAP').style.display = 'block';
document.getElementById("errorMsgAP").innerHTML = "";
}
function showWiFiClientInput()
{
document.getElementById('inputWiFiClient').style.display = 'block';
document.getElementById('inputWiFiAP').style.display = 'none';
document.getElementById("errorMsgClient").innerHTML = "";
}
function hideFixedIPInput()
{
document.getElementById('rowClientIP').style.display = 'none';
document.getElementById('rowClientNETMASK').style.display = 'none';
document.getElementById('rowClientGATEWAY').style.display = 'none';
document.getElementById('dhcpInput').style.display = 'block';
document.getElementById("errorMsgClient").innerHTML = "";
}
function showFixedIPInput()
{
document.getElementById('rowClientIP').style.display = 'table-row';
document.getElementById('rowClientNETMASK').style.display = 'table-row';
document.getElementById('rowClientGATEWAY').style.display = 'table-row';
document.getElementById('dhcpInput').style.display = 'none';
document.getElementById("errorMsgClient").innerHTML = "";
}
function showIPConfig()
{
if(document.getElementById("wifiCfg0checked"))
{
document.getElementById("wifiCfg0checked").style.display = 'compact';
document.getElementById("wifiCfg").style.display = 'none';
if(document.getElementById("wifiCfg3checked"))
{
document.getElementById("wifiCfg3checked").style.display = 'compact';
document.getElementById("wifiCfg3").style.display = 'none';
} else
{
document.getElementById("wifiCfg3checked").style.display = 'none';
document.getElementById("wifiCfg3").style.display = 'compact';
}
if(document.getElementById("wifiCfg1checked"))
{
document.getElementById("wifiCfg1checked").style.display = 'compact';
} else
{
document.getElementById("wifiCfg1").style.display = 'none';
}
} else
{
document.getElementById("wifiCfg0").style.display = 'none';
document.getElementById("wifiCfgchecked").style.display = 'compact';
}
}
// Method to enable the correct side-bar menu for the underlying host interface.
function enableIfConfig()
{
// Disable keymap if no host is connected to the SharpKey. KeyInterface is the base class which exists when
// no host was detected to invoke a host specific sub-class.
if(activeInterface === "KeyInterface ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
}
// Mouse interface active?
else if(activeInterface === "Mouse ")
{
document.getElementById("keyMapAvailable").style.display = 'none';
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("keyMapAvailable").style.display = 'compact';
// Secondary interface available?
if(secondaryInterface == "Mouse ")
{
document.getElementById("mouseCfgAvailable").style.display = 'compact';
} else
{
document.getElementById("mouseCfgAvailable").style.display = 'none';
}
}
}
// On document load, setup the items viewable on the page according to set values.
document.addEventListener("DOMContentLoaded", function setPageDefaults()
{
document.getElementById('wifiModeAccessPoint').onclick = showWiFiAPInput;
document.getElementById('wifiModeClient').onclick = showWiFiClientInput;
document.getElementById('dhcpModeEnabled').onclick = hideFixedIPInput;
document.getElementById('dhcpModeDisabled').onclick = showFixedIPInput;
// Setup AP/Client display.
if(document.getElementById('wifiModeClient').checked)
{
showWiFiClientInput();
} else
{
showWiFiAPInput();
}
if(document.getElementById('dhcpModeEnabled').checked)
{
hideFixedIPInput();
} else
{
showFixedIPInput();
}
// AJAX code to post in a controlled manner so that we can receive back an error/success message to the commit.
$("#wifiman").submit( function(e)
{
var form = $(this);
var actionUrl = form.attr('action');
// Prevent default submit action, we want to manually submit and be able to receive a response for errors/success.
e.preventDefault();
// Clear message window before making a POST, allows for a new message if one is provided or blank if it isnt.
document.getElementById("errorMsgClient").innerHTML = "";
document.getElementById("errorMsgAP").innerHTML = "";
$.ajax(
{
type: "POST",
url: actionUrl,
data: form.serialize(), // serializes the form's elements.
success: function(data)
{
// JQuery not rendering HTML correcly so revert to DOM.
document.getElementById("errorMsgClient").innerHTML = data;
document.getElementById("errorMsgAP").innerHTML = data;
//form.find('#errorMsg').html(data);
}
});
});
showIPConfig();
enableIfConfig();
});

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/keymap.html

239
webserver/keymap.html Normal file
View File

@@ -0,0 +1,239 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard - SharpKey Admin</title>
<!-- Bootstrap core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Add custom CSS here -->
<link href="css/sb-admin.css" rel="stylesheet">
<link href="css/sharpkey.css" rel="stylesheet">
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="/css/jquery.edittable.min.css">
<link rel="stylesheet" type="text/css" href="/css/style.css">
</head>
<body>
<div id="wrapper">
<!-- Sidebar -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">SharpKey Interface</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav side-nav">
<li><a href="index.html"><i class="fa fa-dashboard"></i> Status</a></li>
<li class="active" id="keyMapAvailable"><a href="keymap.html"><i class="fa fa-keyboard-o"></i> %SK_CURRENTIF%Keymap</a></li>
<li id="mouseCfgAvailable"><a href="mouse.html"><i class="fa fa-mouse-pointer"></i> Mouse Config</a></li>
<li><a href="ota.html"><i class="fa fa-file"></i> OTA Update</a></li>
<li><a href="wifimanager.html"><i class="fa fa-wifi"></i> WiFi Manager</a></li>
<li><a href="reboot"><i class="fa fa-power-off"></i> Reboot</a></li>
</ul>
<ul class="nav navbar-nav navbar-right navbar-user">
<li class="dropdown user-dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-gear"></i> Settings <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#"><i class="fa fa-gear"></i> Settings</a></li>
<li class="divider"></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<h1>%SK_CURRENTIF%KeyMap </h1>
<ol class="breadcrumb">
<li class="active"><i class="fa fa-dashboard"></i> Status-&gt;%SK_CURRENTIF%KeyMap</li>
</ol>
<div class="alert alert-success alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<p>Configure the keyboard mapping of the interface from PS/2 to %SK_CURRENTIF% via the table below. The priority is top down and a copy can be saved or uploaded to/from your disk for backup or offline editting.</p>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-table"></i> KeyMap Editor</h3>
</div>
<div class="panel-body">
<div class="table-responsive" id="keymap-edit-area">
%SK_KEYMAPPOPOVER%
<div class="table-responsive keymap" id="edittable-area">
<div id="keymapTable"></div>
</div>
<p></p>
<p style="white-space: pre-wrap;" id="keymapEditorMsg">Directly edit the table, click <span class="fa fa-plus" style="color: green"></span> to add a row, <span class="fa fa-minus" style="color: red"></span> to delete, select (<i class="fa fa-check"></i>) 2 rows to Swap or select multiple rows for multi-row Delete.<br>Press Save to commit changes or Reload to discard changes and reload active i/f map.</p>
<div>
<table class="table-condensed">
<tbody>
<tr>
<td>
<button type="button" class="wm-button" name="keymapSwap" id="keymapSwap" value="">Swap</button>
</td>
<td>
<button type="button" class="wm-button" name="keymapDelete" id="keymapDelete" value="">Delete</button>
</td>
<td>
<button type="button" class="wm-button" name="keymapSave" id="keymapSave" value="">Save</button>
</td>
<td>
<button type="button" class="wm-button" name="keymapReload" id="keymapReload" value="">Reload</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-table"></i> Direct KeyMap Access</h3>
</div>
<div class="panel-body">
<div class="table-responsive" id="esp32-partitions-area">
<form action="/keymap/upload" method="POST" id="fwupgrade">
<p style="white-space: pre-wrap;">The KeyMap for the %SK_CURRENTIF% interface can be directly manipulated via the buttons below. You can download the file for backup or to modify locally then upload to restore or implement changes.</p>
<p id="keymapMsg">Select Upload file (to SharpKey) or Download (to your PC) via the buttons below.</p>
<table class="table-condensed">
<tbody>
<tr>
<td>
<label for="keymapUpload" class="keymap-file-upload" id="keymapUploadLabel">Upload<input type="file" id="keymapUpload"/>
</label>
</td>
<td>
<a id="keymapDownloadLink" style="display: none"></a>
<button type="button" class="wm-button" name="keymapDownload" id="keymapDownload" value="">Download</button>
</td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
</div><!-- /#page-wrapper -->
<!-- JavaScript -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery.edittable.js"></script>
<script>
// Initialize keymap editting table. The table is defined in the document because the custom types need to be added in by the server dynamically. There is no method to
// add custom fields in edittable and JSON is not recommended (and doesnt support it in the API) for serialization of functions hence this solution.
var keymapTable = $("#keymapTable").editTable({
field_templates: {
'checkbox' : {
html: '<input type="checkbox" class="checkbox"/>',
getValue: function (input) {
return $(input).is(':checked');
},
setValue: function (input, value) {
if ( value ){
return $(input).attr('checked', true);
}
return $(input).removeAttr('checked');
}
},
'textarea' : {
html: '<textarea/>',
getValue: function (input) {
return $(input).val();
},
setValue: function (input, value) {
return $(input).text(value);
}
},
'hex' : {
html: '<input type="text" class="hexInput" value="" data-placement="right"/>',
getValue: function (input) {
return $(input).val();
},
setValue: function (input, inVal) {
return $(input).attr("value", hexConvert(inVal, false));
}
},
'list' : {
html: '<select><option value="">None</option><option>All</option></select>',
getValue: function (input) {
return $(input).val();
},
setValue: function (input, value) {
var select = $(input);
select.find('option').filter(function() {
return $(this).val() == value;
}).attr('selected', true);
return select;
}
},
%SK_KEYMAPJSFIELDS%
},
row_template: false,
headerCols: false,
first_row: false,
data:[ ],
// Checkbox validation
validate_field: function (col_id, value, col_type, $element) {
if ( col_type === 'checkbox' ) {
$element.parent('td').animate({'background-color':'#fff'});
if ( value === false ){
$element.parent('td').animate({'background-color':'#DB4A39'});
return false;
}
}
if ( col_type === 'HEX' ) {
let regEx = "^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$";
let isHex = regEx.match(value);
console.log(isHex);
console.log(value);
}
return true;
},
tableClass: 'inputtable custom'
});
// Store the name of the active and secondary interfaces.
const activeInterface = "%SK_CURRENTIF%";
const secondaryInterface = "%SK_SECONDIF%"
</script>
<script src="js/keymap.js"></script>
</body>
</html>

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/mouse.html

167
webserver/mouse.html Normal file
View File

@@ -0,0 +1,167 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard - SharpKey Admin</title>
<!-- Bootstrap core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Add custom CSS here -->
<link href="css/sb-admin.css" rel="stylesheet">
<link href="css/sharpkey.css" rel="stylesheet">
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="/css/jquery.edittable.min.css">
<link rel="stylesheet" type="text/css" href="/css/style.css">
</head>
<body>
<div id="wrapper">
<!-- Sidebar -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">SharpKey Interface</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav side-nav">
<li><a href="index.html"><i class="fa fa-dashboard"></i> Status</a></li>
<li id="keyMapAvailable"><a href="keymap.html"><i class="fa fa-keyboard-o"></i> %SK_CURRENTIF%Keymap</a></li>
<li class="active" id="mouseCfgAvailable"><a href="mouse.html"><i class="fa fa-mouse-pointer"></i> Mouse Config</a></li>
<li><a href="ota.html"><i class="fa fa-file"></i> OTA Update</a></li>
<li><a href="wifimanager.html"><i class="fa fa-wifi"></i> WiFi Manager</a></li>
<li><a href="reboot"><i class="fa fa-power-off"></i> Reboot</a></li>
</ul>
<ul class="nav navbar-nav navbar-right navbar-user">
<li class="dropdown user-dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-gear"></i> Settings <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#"><i class="fa fa-gear"></i> Settings</a></li>
<li class="divider"></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<h1>Mouse Config </h1>
<ol class="breadcrumb">
<li class="active"><i class="fa fa-dashboard"></i> Status-&gt;Mouse Config</li>
</ol>
<div class="alert alert-success alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<p>Configure the Mouse settings in the panel below. Some of the mouse settings can be configured by the mouse wheel, please refer to the documentation for details.</p>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-server"></i> Mouse Host Configuration</h3>
</div>
<div class="panel-body">
<form action="/data/mouse" method="POST" id="mouseHostCfgSave">
<p><b>Host Scaling</b></p>
<div>
%SK_MOUSEHOSTSCALING%
</div>
<hr class="hr_no_margin">
<div>
<p style="white-space: pre-wrap;" id="mouseHostCfgMsg">Setup the host side mouse interface parameters. Commit changes by pressing <i>Save</i>.</p>
</div>
<hr class="hr_no_margin">
<div>
<table class="table-condensed">
<tbody>
<tr>
<td>
<button type="submit" class="wm-button" name="mouseHostSave" id="mouseHostSave" form="mouseHostCfgSave" value="">Save</button>
</td>
</tr>
</tbody>
</table>
</div>
</form>
</div>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-mouse-pointer"></i> Mouse Configuration</h3>
</div>
<div class="panel-body">
<form action="/data/mouse" method="POST" id="mousePS2CfgSave">
<p><b>Mouse Scaling</b></p>
<div>
%SK_MOUSEPS2SCALING%
</div>
<p><b>Mouse Resolution</b></p>
<div>
%SK_MOUSEPS2RESOLUTION%
<div>
<p><b>Mouse Sampling Rate</b></p>
<div>
%SK_MOUSEPS2SAMPLERATE%
</div>
<hr class="hr_no_margin">
<div>
<p style="white-space: pre-wrap;" id="mousePS2CfgMsg">Setup the mouse parameters which are PS/2 settings, Bluetooth mice will use these parameters via internal mapping.<br>Commit changes by pressing <i>Save</i>.</p>
</div>
<hr class="hr_no_margin">
<div>
<table class="table-condensed">
<tbody>
<tr>
<td>
<button type="submit" class="wm-button" name="mousePS2Save" id="mousePS2Save" form="mousePS2CfgSave" value="">Save</button>
</td>
</tr>
</tbody>
</table>
</div>
</form>
</div>
</div>
</div>
</div><!-- /.row -->
</div><!-- /#page-wrapper -->
<!-- JavaScript -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script>
// Store the name of the active and secondary interfaces.
const activeInterface = "%SK_CURRENTIF%";
const secondaryInterface = "%SK_SECONDIF%"
</script>
<script src="js/mouse.js"></script>
</body>
</html>

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/ota.html

238
webserver/ota.html Normal file
View File

@@ -0,0 +1,238 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard - SharpKey Admin</title>
<!-- Bootstrap core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Add custom CSS here -->
<link href="css/sb-admin.css" rel="stylesheet">
<link href="css/sharpkey.css" rel="stylesheet">
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">
</head>
<body>
<div id="wrapper">
<!-- Sidebar -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">SharpKey Interface</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav side-nav">
<li><a href="index.html"><i class="fa fa-dashboard"></i> Status</a></li>
<li id="keyMapAvailable"><a href="keymap.html"><i class="fa fa-keyboard-o"></i> %SK_CURRENTIF%Keymap</a></li>
<li id="mouseCfgAvailable"><a href="mouse.html"><i class="fa fa-mouse-pointer"></i> Mouse Config</a></li>
<li class="active"><a href="ota.html"><i class="fa fa-table"></i> OTA Update</a></li>
<li><a href="wifimanager.html"><i class="fa fa-wifi"></i> WiFi Manager</a></li>
<li><a href="reboot"><i class="fa fa-power-off"></i> Reboot</a></li>
</ul>
<ul class="nav navbar-nav navbar-right navbar-user">
<li class="dropdown user-dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-gear"></i> Settings <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#"><i class="fa fa-gear"></i> Settings</a></li>
<li class="divider"></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<h1><b>O</b>ver <b>T</b>he <b>A</b>ir Update </h1>
<ol class="breadcrumb">
<li class="active"><i class="fa fa-dashboard"></i> Status-&gt;OTA Update </li>
</ol>
<div class="alert alert-success alert-dismissable justify">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<p>Welcome to the SharpKey OTA Update page.</p><p>This page allows you to check current firmware/filepack version information and upgrade them as necessary. Please read the documentation if you need help.</p>
</div>
</div>
</div><!-- /.row -->
<div class="row">
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-file"></i> Version Information</h3>
</div>
<div class="panel-body">
<div class="table-responsive">
<div id="firmware-revision-area">
%SK_PRODNAME% v%SK_PRODVERSION% &copy; P.D. Smart, 2018-22<br><br>
<b>Modules</b><br>
%SK_MODULES%
<b>File Pack</b><br>
%SK_FILEPACK%
</div>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-table"></i> ESP32 Partitions</h3>
</div>
<div class="panel-body">
<div class="table-responsive">
<div id="esp32-partitions-area">
<table class="table table-borderless table-sm">
<thead>
<tr>
<th><b>Partition Name</b></th>
<th><b>Type</b></th>
<th><b>Sub-Type</b></th>
<th><b>Address</b></th>
<th><b>Size</b></th>
<th><b>Version</b></th>
<th><b>Timestamp</b></th>
<th><b>Active (Running)</b></th>
</tr>
</thead>
<tbody>
%SK_PARTITIONS%
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-file"></i> Firmware Upload</h3>
</div>
<div class="panel-body">
<div class="table-responsive" id="upload-firmware-area">
<form action="/data/wifi" method="POST" id="fwupgrade">
<p><i>Firmware</i> is a binary file containing the latest operating system for the SharpKey interface.</p>
<hr class="hr_no_margin">
<p id="firmwareMsg">Select a firmware image file with which to upgrade the SharpKey Operating System.</p>
<hr class="hr_no_margin">
<table class="table-condensed">
<tbody>
<tr>
<td>
<label for="firmwareUpload" class="firmware-file-upload" id="firmwareUploadLabel">Select file<input type="file" id="firmwareUpload"/>
</label>
</td>
<td>
<div id="firmwareName"></div>
</td>
<td>
<button type="button" class="wm-button" name="firmwareUpgrade" id="firmwareUpgrade" value="" style="display: none;" disabled>Upgrade</button>
</td>
<td>
<button type="button" class="wm-button" name="firmwareCancel" id="firmwareCancel" style="display: none;" disabled>Cancel</button>
</td>
<td>
<div class="progress progress-striped" id="firmwareProgress">
<div class="progress-bar progress-bar-striped active" id="firmwareProgressBar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
</div>
</div>
</td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-file"></i> File Pack Upload</h3>
</div>
<div class="panel-body">
<div class="table-responsive" id="upload-firmware-area">
<form action="/data/wifi" method="POST" id="fpupgrade">
<p style="white-space: pre-wrap;">A filepack is a SharpKey filesystem stored in a binary image file which contains static and template files for the webserver interface.</p>
<p id="filepackWarning" style="display: none; white-space: pre-wrap;"><b>WARNING!</b> There is no rollback for this update unlike the firmware upgrade, if the process is interrupted and the filesystem corrupted you will need to attach a serial cable to the SharpKey programming interface and upload the image via the command:
<br><span style="margin-left: 1em; display: block;"><i>esptool.py --chip esp32 --baud 921600 --before default_reset --after hard_reset write_flash --flash_freq 40m --flash_size detect 0x310000 &lt;filepack&gt;</i></span></p>
<hr class="hr_no_margin">
<p id="filepackMsg">Select a filepack image file with which to upgrade the SharpKey filesystem.</p>
<hr class="hr_no_margin">
<table class="table-condensed">
<tbody>
<tr>
<td>
<label for="filepackUpload" class="firmware-file-upload" id="filepackUploadLabel">Select file<input type="file" id="filepackUpload"/>
</label>
</td>
<td>
<div id="filepackName"></div>
</td>
<td>
<button type="button" class="wm-button" name="filepackUpgrade" id="filepackUpgrade" value="" style="display: none;" disabled>Upgrade</button>
</td>
<td>
<button type="button" class="wm-button" name="filepackCancel" id="filepackCancel" style="display: none;" disabled>Cancel</button>
</td>
<td>
<div class="progress progress-striped" id="filepackProgress">
<div class="progress-bar progress-bar-striped active" id="filepackProgressBar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
</div>
</div>
</td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
</div><!-- /#page-wrapper -->
</div><!-- /#wrapper -->
<!-- JavaScript -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script>
// Store the name of the active and secondary interfaces.
const activeInterface = "%SK_CURRENTIF%";
const secondaryInterface = "%SK_SECONDIF%"
</script>
<script src="js/ota.js"></script>
</body>
</html>

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/ptable.bin

1
webserver/ptable.bin Normal file
View File

@@ -0,0 +1 @@
hello philip˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙and another test here˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/version.txt

1
webserver/version.txt Normal file
View File

@@ -0,0 +1 @@
1.02

View File

@@ -1 +0,0 @@
../../sharpkey/webserver/wifimanager.html

312
webserver/wifimanager.html Normal file
View File

@@ -0,0 +1,312 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard - SharpKey Admin</title>
<!-- Bootstrap core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Add custom CSS here -->
<link href="css/sb-admin.css" rel="stylesheet">
<link href="css/sharpkey.css" rel="stylesheet">
<link href="font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/css/style.css">
</head>
<body>
<div id="wrapper">
<!-- Sidebar -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">SharpKey Interface</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav side-nav">
<li><a href="index.html"><i class="fa fa-dashboard"></i> Status</a></li>
<li id="keyMapAvailable"><a href="keymap.html"><i class="fa fa-keyboard-o"></i> %SK_CURRENTIF%Keymap</a></li>
<li id="mouseCfgAvailable"><a href="mouse.html"><i class="fa fa-mouse-pointer"></i> Mouse Config</a></li>
<li><a href="ota.html"><i class="fa fa-table"></i> OTA Update</a></li>
<li class="active"><a href="wifimanager.html"><i class="fa fa-wifi"></i> WiFi Manager</a></li>
<li><a href="reboot"><i class="fa fa-power-off"></i> Reboot</a></li>
</ul>
<ul class="nav navbar-nav navbar-right navbar-user">
<li class="dropdown user-dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-gear"></i> Settings <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#"><i class="fa fa-gear"></i> Settings</a></li>
<li class="divider"></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<h1>WiFi Manager </h1>
<ol class="breadcrumb">
<li class="active"><i class="fa fa-dashboard"></i> Status-&gt;WiFi Manager</li>
</ol>
<div class="alert alert-success alert-dismissable justify">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<p>Welcome to the SharpKey WiFi Manager page.</p><p>This page allows you to configure the SharpKey WiFi Access Point (you connect to the SharpKey) or
Client (SharpKey connects to your network) mode.</p>
</div>
</div>
</div><!-- /.row -->
<div class="row">
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-wifi"></i> WiFi Configuration</h3>
</div>
<div class="panel-body">
<div class="table-responsive">
<div id="client-wifi-config-area">
<div id="wifiCfg%SK_WIFIMODEAP%">
<table class="table table-borderless table-sm">
<tbody>
<tr style="display: compact;">
<td>SSID:</td><td><span style="color: blue;">%SK_APSSID%</span></td>
</tr>
<tr style="display: compact;">
<td>Password:</td><td><span style="color: blue;">%SK_APPWD%</span></td>
</tr>
<tr>
<td>IP (AP):</td><td><span style="color: blue;">%SK_CURRENTIP%</span></td>
<td>NETMASK:</td><td><span style="color: blue;">%SK_CURRENTNM%</span></td>
<td>GATEWAY:</td><td><span style="color: blue;">%SK_CURRENTGW%</span></td>
</tr>
</tbody>
</table>
</div>
<div id="wifiCfg0%SK_WIFIMODECLIENT%">
<table class="table table-borderless table-sm">
<tbody>
<tr style="display: compact;">
<td>SSID:</td><td><span style="color: blue;">%SK_CLIENTSSID%</span></td>
</tr>
<tr style="display: compact;" id="wifiCfg1%SK_CLIENTDHCPON%">
<td>DHCP:</td><td><span style="color: blue;">Enabled</span></td>
</tr>
<tr id="wifiCfg3%SK_CLIENTDHCPON%">
<td>IP (assigned):</td><td><span style="color: blue;">%SK_CURRENTIP%</span></td>
<td>NETMASK:</td><td><span style="color: blue;">%SK_CURRENTNM%</span></td>
<td>GATEWAY:</td><td><span style="color: blue;">%SK_CURRENTGW%</span></td>
</tr>
<tr id="wifiCfg3%SK_CLIENTDHCPOFF%">
<td>IP (fixed):</td><td><span style="color: blue;">%SK_CURRENTIP%</span></td>
<td>NETMASK:</td><td><span style="color: blue;">%SK_CURRENTNM%</span></td>
<td>GATEWAY:</td><td><span style="color: blue;">%SK_CURRENTGW%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-table"></i> Configure WiFi</h3>
</div>
<div class="panel-body">
<div class="table-responsive" id="wifi-configuration-area">
<form action="/data/wifi" method="POST" id="wifiman">
<div>
<table class="sk-client-wifi-config-table">
<tbody>
<tr>
<td><b>WiFi Mode:</b></td>
<td>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifiMode" id="wifiModeAccessPoint" value="ap" %SK_WIFIMODEAP%>
<label class="form-check-label" for="wifiModeAccessPoint">Access Point</label>
</div>
</td>
<td>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifiMode" id="wifiModeClient" value="client" %SK_WIFIMODECLIENT%>
<label class="form-check-label" for="wifiModeClient">Client</label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Client Mode -->
<div id="inputWiFiClient">
<div>
<table class="sk-client-wifi-config-table">
<tbody>
<tr>
<td><label for="clientSSID">SSID:</label></td>
<td><input type="text" id="clientSSID" name="clientSSID" value="%SK_CLIENTSSID%" autocapitalize="none"></td>
<td>Name of Wifi router to use.<td>
</tr>
<tr>
<td><label for="clientPWD">Password:</label></td>
<td><input type="text" id="clientPWD" name="clientPWD" value="%SK_CLIENTPWD%" autocapitalize="none"></td>
<td>Password of WiFi router.</td>
</tr>
<br>
<tr>
<td><b>DHCP Mode:</b></td>
<td>
<div class="form-check">
<input class="form-check-input" type="radio" name="dhcpMode" id="dhcpModeEnabled" value="on" %SK_CLIENTDHCPON%>
<label class="form-check-label" for="dhcpModeEnabled">
Enabled
</label>
</div>
</td>
<td style="width: 1px;">
<div class="form-check">
<input class="form-check-input" type="radio" name="dhcpMode" id="dhcpModeDisabled" value="off" %SK_CLIENTDHCPOFF%>
<label class="form-check-label" for="dhcpModeDisabled">
Disabled
</label>
</div>
</td>
</tr>
<tr id="rowClientIP">
<td><label for="clientIP">IP Address</label></td>
<td><input id="clientIP" name="clientIP" inputmode="decimal" placeholder="_._._._" value="%SK_CLIENTIP%"></td>
<td>Static IP address to assign to SharpKey</td>
</tr>
<tr id="rowClientNETMASK">
<td><label for "clientNETMASK">Netmask</label></td>
<td><input id="clientNETMASK" name="clientNETMASK" inputmode="decimal" placeholder="_._._._" value="%SK_CLIENTNM%"/></td>
<td>Netmask for Static IP</td>
</tr>
<tr id="rowClientGATEWAY">
<td><label for="clientGATEWAY">Gateway</label></td>
<td><input id="clientGATEWAY" name="clientGATEWAY" inputmode="decimal" placeholder="_._._._" value="%SK_CLIENTGW%"/></td>
<td>Gateway or router IP Address (if needed).</td>
</tr>
</tbody>
</table>
</div>
<div class="justify" id="dhcpInput">
<p style="white-space: initial;">DHCP Mode enabled.<br>The SharpKey will use the credentials specified above (SSID/Password) to connect to the router and obtain
an IP address, Netmask and Gateway. Use your router admin page to determine the IP address allocated and connect to the SharpKey via http://&lt;assigned IP&gt;</p>
</div>
<div>
<div id="errorMsgClient">
%SK_ERRMSG%
</div>
<hr class="hr_no_margin">
<div class="buttons" style="float: left; padding-left: 0px">
<table class="sk-client-wifi-config-table">
<tbody>
<tr>
<td><button type="submit" class="wm-button" name="save" id="save" form="wifiman">Save</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Access Point Mode -->
<div id="inputWiFiAP">
<div>
<br>
<table class="sk-client-wifi-config-table">
<tbody>
<tr>
<td><label for="apSSID">SSID</label></td>
<td><input type="text" id="apSSID" name="apSSID" value="%SK_APSSID%" autocapitalize="none"></td>
<td>Name of this WiFi Access Point.<td>
</tr>
<tr>
<td><label for="apPWD">Password</label></td>
<td><input type="text" id="apPWD" name="apPWD" value="%SK_APPWD%" autocapitalize="none"></td>
<td>Password required by this AP to authenticate clients.</td>
</tr>
<tr>
<td><label for="apIP">IP Address</label></td>
<td><input id="apIP" name="apIP" inputmode="decimal" placeholder="_._._._" value="%SK_APIP%"></td>
<td>IP address assigned to this Access Point. ie. 192.168.4.1</td>
</tr>
<tr>
<td><label for "apNETMASK">Netmask</label></td>
<td><input id="apNETMASK" name="apNETMASK" inputmode="decimal" placeholder="_._._._" value="%SK_APNM%"/></td>
<td>Netmask of this AP network.</td>
</tr>
<tr>
<td><label for="apGATEWAY">Gateway</label></td>
<td><input id="apGATEWAY" name="apGATEWAY" inputmode="decimal" placeholder="_._._._" value="%SK_APGW%"/></td>
<td>Gateway this AP will assign to a client. Normally same as IP.</td>
</tr>
</tbody>
</table>
</div>
<div>
<div id="errorMsgAP">
%SK_ERRMSG%
</div>
<hr class="hr_no_margin">
<div class="buttons" style="float: left; padding-left: 0px">
<table class="sk-client-wifi-config-table">
<tbody>
<tr>
<td><button type="submit" class="wm-button" name="save" id="save" form="wifiman">Save</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div><!-- /.row -->
</div><!-- /#page-wrapper -->
</div><!-- /#wrapper -->
<!-- JavaScript -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script>
// Store the name of the active and secondary interfaces.
const activeInterface = "%SK_CURRENTIF%";
const secondaryInterface = "%SK_SECONDIF%"
</script>
<script src="js/wifimanager.js"></script>
</body>
</html>