SprinklerD/web/index.html

470 lines
17 KiB
HTML

<!DOCTYPE html>
<html lang='en'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>
<title>Sprinkler</title>
<meta name='viewport' content='width=device-width'>
<meta name='apple-mobile-web-app-capable' content='yes'>
<meta name='apple-mobile-web-app-status-bar-style' content='black'>
<style>
:root {
--diameter: 30px;
}
html {
}
body {
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
font-weight: 300;
background-color: #f1f1f1;
color: #000000;
margin: 0 !important;
padding: 0 !important;
}
table,
th,
td {
border-collapse: collapse;
padding: 10px;
text-align: left;
border-bottom: 1px solid rgb(189, 189, 189);
width: 100%;
}
th {
width: 100vw;
padding: 15px;
text-align: center;
background-color: #f1f1f1;
}
tr {
background-color: white;
color: black;
}
.button {
background-color: white;
border-radius: 15px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
height: 30px
}
.opaque {
top: 0px;
left: 0px;
background-color: black;
filter: alpha(opacity=20);
opacity: 0.2;
}
.show {
top: 0px;
left: 0px;
}
.message {
position: fixed;
top: 0px;
left: 0px;
height: 100%;
z-index: 1000;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
}
.message-text {
background-color: black;
color: white;
height: auto;
padding: 15px;
font-size: 20px;
text-align: center;
position: relative;
border-radius: var(--diameter);
}
.option_button {
position: fixed;
top: 2px;
left: 2px;
z-index: 900;
}
.options {
top: 0px;
left: 0px;
z-index: 800;
display: none;
}
.input-text {
font-size: 16px;
}
.input-ios {
font-size: 16px;
}
.status {
font-size: 14px;
}
.small-note {
font-size: 12px;
}
.btn-toggle {
position: absolute;
margin-left: -9999px;
visibility: hidden;
}
.btn-toggle+label {
display: block;
position: relative;
cursor: pointer;
outline: none;
user-select: none;
}
input.btn-toggle-round+label {
padding: 2px;
width: calc(2 * var(--diameter));
height: var(--diameter);
background-color: #dddddd;
border-radius: var(--diameter);
}
input.btn-toggle-round+label:before,
input.btn-toggle-round+label:after {
display: block;
position: absolute;
top: 1px;
left: 1px;
bottom: 1px;
content: '';
}
input.btn-toggle-round+label:before {
right: 1px;
background-color: #f1f1f1;
border-radius: var(--diameter);
transition: background 0.4s;
}
input.btn-toggle-round+label:after {
width: var(--diameter);
background-color: #ffffff;
border-radius: 100%;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
transition: margin 0.4s;
}
input.btn-toggle-round:checked+label:before {
/*background-color: rgb(76, 217, 100);*/
background-color: #2196F3;
}
input.btn-toggle-round:checked+label:after {
margin-left: var(--diameter);
}
</style>
<script type='text/javascript'>
var _poller;
var _showingConfig=false;
var _width;
function setSizeSpecifics() {
_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
/*
Future change element sizes here if needed
*/
}
function addHeadIcon(rel) {
var image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJgAAACYCAMAAAAvHNATAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAABdUExURSLQQaPgq8PixOft54bll0Cu3mFhYf///wAAAAaX1Eyw2sXV2PP19Im8zpbAzo7knN3j5NHa3Nff4L7R1fr7+1my1cfW2WG01aqqqnJycsHBwWxsbGm01I2NjWa000nzYgoAAAL5SURBVHja7dlte4IgFAZgLMGZVVpWVmv//2fOKtUZ4NGdkO16zrexHXZfvIMi8jQEYIABBhhggAEGGGCAAQYYYIABBhgnbLlaLFZL/2CpjMuQqXewRXyPhW+wrXzA5NYz2C5+xg4t9sfHmL+z0tt1bIqVf5kkfC1BrY0AW8k4lisuF7U2QaqJT0aurRe2rBYolt6k19YLS6olPeGA0Wv7uzB648+TZO6wK6nDNd3fpts+dTb4iRP8UDXFwdlyQVoSc1kNHpk7W2ApsY7rWHu1V+4b2HEqWLbLjKcxw4lMm8IMW0sZS/nSXUdLixlSeGGfj0EuP+lj7OuZ8vVO2LqafN0GMM9KYworrP73saSuY+YURljW+i8ZbeW3pfDBds1I0twftXulPcVFi/Gl8I4xzhTOWcmawrmOWcLJOjZqGXey8o/b+FzslV7dxG1RXJQ2TsW0sJP6MIQ6TQkrjK5SVkwIu3xY4jQhTNlgCjBPYbpTzTAY5Q1hMGyrPQcOgRHfEHpg3ZfepDo5J2NhiebsbXtP1sO6b+OmuwYdpqvB+gKvh3W/JphuZ3SYrgbrNwst7OX7i+k+S4dp3hDsX3mE9dKx63kBoMM0Ndi/i/2uxehb0pGlxchjjL6J84wx8qykH3uYZqV5HTvoDoovKKUu3UOPbiUcvo4ZV/4tacdUQ2tg3yuHwN60Vw46YyiGSv817NqFXT2BZZ0mU5knsOj8Q6bOkS+wKG8aTWV55A+sNQEUU4WAAQYYYIAB9rt9nGcHZ4RF17tMXaO3wILurwN6yam55Abj6rHAws5fByG9JC2bTKVDs9olNlg4a/84C4Wgl5zVY4ANy2pKrDARti5Y8zJbDCgpijFZdYkdJjbNTxtxD3JJno/Jqkt6YE3XB+Ej3VVJD6zu+tkz21lJH+zZ9fM621VJL+zR9RvRCicl/bBb1wdhO91JST+s7PrZj2w3JQTYNAEYYIAB9q9hk8Z7bkncARhggAEGGGCAAQYYYIABBhhggAFWxjcZXFfjMfI84gAAAABJRU5ErkJggg==';
var link = document.createElement('link');
link.rel = rel;
link.type= 'image/png';
link.href = image;
document.head.appendChild(link);
}
function headIcons() {
addHeadIcon('shortcut icon');
addHeadIcon('apple-touch-icon');
addHeadIcon('apple-touch-startup-image');
}
function hidemessage() {
if (_showingConfig == false) {
document.getElementById('main').className = 'show';
} else {
document.getElementById('options').className = 'show';
}
document.getElementById('message').style.display = 'none';
}
function showmessage() {
if (_showingConfig == false) {
document.getElementById('main').className = 'opaque';
} else {
document.getElementById('options').className = 'opaque';
}
document.getElementById('message').style.display = 'flex';
}
function switchOptionsPane() {
if (_showingConfig == true) {
document.getElementById('options').style.display = 'none';
document.getElementById('main').style.display = 'flex';
_showingConfig = false;
} else {
document.getElementById('options').style.display = 'flex';
document.getElementById('main').style.display = 'none';
cleanupCalendar();
_showingConfig = true;
}
}
function calendarhtmlrow(title, daynum, zones) {
html = '</tr><tr><td>'+title+'</td> \
<td><input type="time" id="d'+daynum+'-starttime" class="input-ios" onchange="update(this);"></td>';
for (i=1; i<= zones; i++) {
html = html+'<td><input type="number" id="d'+daynum+'z'+i+'-runtime" class="input-ios" onchange="update(this);" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="0" max="30" step="1"></td>';
}
html = html+'</tr>';
return html;
}
function setzonehtml(zones) {
html = '';
for (i=1; i<= zones; i++) {
html = html+'<tr> \
<td>Zone&nbsp;'+i+'</td> \
<td><label id="z'+i+'-name" class="small-note"></label></td> \
<td>Runtime</td> \
<td><input type="number" id="z'+i+'-runtime" onchange="update(this);" class="input-ios" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="1" max="30" step="1"></td> \
<td> \
<div class="switch"> \
<input id="btn-toggle-z'+i+'" name="z'+i+'" class="btn-toggle btn-toggle-round" type="checkbox" onclick="update(this);"> \
<label for="btn-toggle-z'+i+'"></label> \
</div> \
</td> \
</tr>';
}
rnz = document.getElementById('main');
rnz.innerHTML = rnz.innerHTML.replace("<!-- AUTO HTML -->", html);
html = '<tr><th colspan="'+(zones+2)+'"> Configuration </th></tr> \
<tr> \
<td>&nbsp;</td> \
<td>Start Time</td>';
for (i=1; i<= zones; i++) {
html = html+'<td>Z'+i+'</td>';
}
html = html+calendarhtmlrow("Mon", 1, zones);
html = html+calendarhtmlrow("Tue", 2, zones);
html = html+calendarhtmlrow("Wed", 3, zones);
html = html+calendarhtmlrow("Thu", 4, zones);
html = html+calendarhtmlrow("Fri", 5, zones);
html = html+calendarhtmlrow("Sat", 6, zones);
html = html+calendarhtmlrow("Sun", 0, zones);
html = html + '<tr><td colspan="2">Delay if chance of rain is above</td><td colspan="'+zones+'" align="left"><input type="number" id="raindelaychance" class="input-ios" onchange="update(this);" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="0" max="100" step="1">percent</td></tr> \
<tr><td colspan="2">Delay 24 hours if rain total </td><td colspan="'+zones+'" align="left"><input type="number" id="raindelaytotal1" class="input-ios" onchange="update(this);" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="0" max="10" step="0.1">inches</td></tr> \
<tr><td colspan="2">Delay 48 hours if rain total </td><td colspan="'+zones+'" align="left"><input type="number" id="raindelaytotal2" class="input-ios" onchange="update(this);" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="0" max="10" step="0.1">inches</td></tr>' ;
rnz = document.getElementById('options');
rnz.innerHTML = rnz.innerHTML.replace("<!-- AUTO HTML -->", html);
}
function cleanupCalendar() {
for (i = 0; i < 7; i++) {
st = document.getElementById('d'+i+'-starttime')
if (st != null) {
if (st.value != ''){show=true}else{show=false}
for (j=1; null != (rt = document.getElementById('d'+i+'z'+j+'-runtime'));j++) {
if (show) {
rt.classList.remove("opaque");
if (rt.value == '')
rt.value = document.getElementById('z'+j+'-runtime').value;
} else {
rt.classList.add("opaque");
}
}
}
}
}
// Need to come back and make the better.
// if under 375 make sure only 20 character with a space after 10.
function resize(string) {
if (_width <= 375)
return string;
else
return "("+string.replace(" ", "&nbsp;")+")";
}
function update(type) {
var http = new XMLHttpRequest();
if (http) {
http.onreadystatechange = function () {
if (http.readyState === 4) {
if (http.status == 200 && http.status < 300) {
if (type == 'firstload') {
setzonehtml(JSON.parse(http.responseText)['zones']);
hidemessage();
}
var data = JSON.parse(http.responseText);
//console.log(data.ActTime);
for (var obj in data) {
if (obj == 'title') {
document.title = data[obj];
document.getElementById('title').innerHTML = data[obj];
} if (obj == 'status') {
if (data[obj].length > 0)
document.getElementById('status').innerHTML = data[obj].replace('/ /g', '&nbsp;');
else
document.getElementById('status').innerHTML = "Run now options";
} else if (obj == '24hdelay-offtime') {
if (data[obj] > 0) {
dt = new Date(data[obj] * 1000);
var options = { weekday: "short", hour: "2-digit", minute: "2-digit"};
document.getElementById('24hdelay-offtime').innerHTML = '(until '+dt.toLocaleTimeString("en-us", options)+')';
} else {
document.getElementById('24hdelay-offtime').innerHTML = '';
}
} else if ( (field = document.getElementById(obj)) != null){
if (obj.substr(-5,5) == '-name')
field.innerHTML = resize(data[obj]);
else {
if (field.id != document.activeElement.id) // Only update if not being edited
field.value = data[obj];
}
} else {
if ( (btn = document.getElementById('btn-toggle-' + obj)) != null){
if (data[obj] == 'on')
btn.checked = true;
else
btn.checked = false;
} else if ( (btn = document.getElementById('btn-' + obj)) != null){
btn.selectedIndex = data[obj];
}
}
}
}
else if(http.status >= 400 || http.status == 0) {
document.getElementById('message-text').innerHTML = 'Error connecting to server';
}
}
}
};
if (type == null ) {
http.open('GET', location.href + '?type=read', true);
http.send(null);
} else if (type == 'firstload') {
http.open('GET', location.href + '?type=firstload', true);
http.send(null);
} else if (type != null) {
clearTimeout(_poller);
// compare xx-starttime or xxx-runtime or xxxx-runtime
if (type.id.substr(-4,4) == 'time') {
// d1z10-runtime is a calendar config, z11-runtime is a zone default runtime
if (type.id.substr(0,1) == 'd') {
http.open('GET', location.href + '?type=calcfg&day='+type.id.substr(1,1)+'&zone='+type.id.substr(3,type.id.lastIndexOf("-")-3)+'&time='+type.value);
http.send(null);
cleanupCalendar();
} else if (type.id.substr(0,1) == 'z') {
http.open('GET', location.href + '?type=zrtcfg&zone='+type.id.substr(1,type.id.lastIndexOf("-")-1)+'&time='+type.value);
http.send(null);
cleanupCalendar();
}
} else if (type.id.substr(0,9) == 'raindelay'){ // rainChance, rainTotal1d, rainTotal2d
http.open('GET', location.href + '?type=config&option='+type.id+'&value='+type.value);
http.send(null);
} else if (type.id.substr(0,11) == 'btn-toggle-'){
// If there is a 'xx-runtime' id then it's a zone to start, else it's a cfg button
if ( (rto = document.getElementById(type.name + '-runtime')) != null){
http.open('GET', location.href + '?type=zone&zone=' + type.name.substring(1) + '&state=' + ((type.checked == true) ? 'on' : 'off') + '&runtime=' + rto.value, true);
} else {
http.open('GET', location.href + '?type=option&option=' + type.name + '&state=' + ((type.checked == true) ? 'on' : 'off'), true);
}
http.send(null);
}
}
_poller = setTimeout(update, 5000);
}
</script>
</head>
<body onload='setSizeSpecifics(); headIcons(); update("firstload");'>
<div id='message' class='message' onmousedown='hidemessage()'>
<div id='message-text' class='message-text'>
<b>Loading....</b>
</div>
</div>
<div id='option_button' class='option_button' onmousedown='switchOptionsPane()'>
<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAeUExURQAAADMzMjU1LjMzMjQ0NDMzMzAwMDMzMTIyMjMzMnuMncMAAAAJdFJOUwCAIOFAbRC/ouTmS5QAAACRSURBVDjL3ZTBDsMwCEMJJLT+/x8eblVtOzRhU9V288lCT4pMAJFNZj33lAK67z4DXakKVN1zTm5CQpPIjJRmAWz8tAEBlnGY8g3Ybfgb2NOvgcr+21pca0ajZ4AWiiGRRtM4VjR6Rurs0xe25/jUXkIMW2kq49P4rVIvm76dIn8p/OcWogwVkLTcIY3PbTnuAUNsEZOTrdGvAAAAAElFTkSuQmCC'>
</div>
<div id='main' class='opaque'>
<table>
<tbody>
<tr>
<th colspan='5'><label id='title'>Sprinkler</label></th>
</tr>
<tr>
<td colspan='4'>
Run on calendar schedule
</td>
<td>
<div class='switch'>
<input id='btn-toggle-calendar' name='calendar' class='btn-toggle btn-toggle-round' type='checkbox' onclick='update(this);'>
<label for='btn-toggle-calendar'></label>
</div>
</td>
</tr>
<tr>
<td colspan='4'>
24h Rain Delay&nbsp;<label id='24hdelay-offtime' class='small-note'></label>
</td>
<td>
<div class='switch'>
<input id='btn-toggle-24hdelay' name='24hdelay' class='btn-toggle btn-toggle-round' type='checkbox' onclick='update(this);'>
<label for='btn-toggle-24hdelay'></label>
</div>
</td>
</tr>
<tr>
<th colspan='5' class='status'>
<label id='status'>Run now option</label>
<!-- <font size='-1'>Run now option</font> -->
</th>
</tr>
<tr>
<td colspan='4'>Cycle all Zones</td>
<td>
<div class='switch'>
<input id='btn-toggle-allz' name='allz' class='btn-toggle btn-toggle-round' type='checkbox' onclick='update(this);'>
<label for='btn-toggle-allz'></label>
</div>
</td>
</tr>
<!-- AUTO HTML -->
</tbody>
</table>
</div>
<div id='options' class='options'>
<table>
<tbody>
<!-- AUTO HTML -->
</tbody>
</table>
</div>
</body>
</html>