var pages
var parameters = {}
var daynames = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']
+var msgT
function toggleMenu(e) {
active = (document.getElementById('menuLink').className.indexOf('active') !== -1)
}
function getAnchor() {
- return window.location.hash;
+ return window.location.hash.slice(1);
}
-function DrawHeader(project) {
+function drawHeader(project) {
var menu_header = document.getElementById('_ui_menu_header')
menu_header.innerHTML = project.name
document.title = project.name + '/' + project.version
}
-function ParseJsonQ(url, callback) {
+function parseJsonQ(url, callback) {
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status != 200 && this.status != 500 && this.status != 404) {
- setTimeout(ParseJsonQ(url, callback),30000);
+ setTimeout(parseJsonQ(url, callback),30000);
return;
}
var json = JSON.parse(this.responseText)
}
-function UpdateElement(id, value) {
+function updateElement(id, value) {
var element = document.getElementById("_ui_element_"+id)
if (!element) return;
var ui_class = element.dataset.ui_class;
}
}
-function UpdateValues(json) {
+function updateValues(json) {
for (var key in json) {
var obj = document.getElementById("_ui_element_"+key)
if (obj) {
- UpdateElement(key, json[key])
+ updateElement(key, json[key])
}
parameters[key] = json[key]
}
var notification = document.getElementById('_ui_notification');
if (parameters['_changed']) {
- notification.innerHTML = '<input style="margin:1em .5em 0;" type="button" id="save" value="Сохранить внесенные изменения" class="pure-button pure-button-primary" onclick="sendAction(\'save\')">'
+ notification.innerHTML = '<input type="button" id="save" value="Сохранить" class="pure-button" onclick="sendAction(\'save\')">'
notification.removeAttribute('hidden')
} else {
notification.innerHTML = ''
case 'number':
case 'range':
if (input.checkValidity() && input.value != parameters[id]) {
- ParseJsonQ('/config/set?name=' + id + '&value=' + encodeURIComponent(input.value), function(json) {
- UpdateValues(json)
+ parseJsonQ('/config/set?name=' + id + '&value=' + encodeURIComponent(input.value), function(json) {
+ updateValues(json)
})
}
break
case 'select':
- ParseJsonQ('/config/set?name=' + id + '&value=' + encodeURIComponent(input.selectedOptions[0].value), function(json) {
- UpdateValues(json)
+ parseJsonQ('/config/set?name=' + id + '&value=' + encodeURIComponent(input.selectedOptions[0].value), function(json) {
+ updateValues(json)
})
break;
case 'checkbox':
- ParseJsonQ('/config/set?name=' + id + '&value=' + (input.checked?'true':'false'), function(json) {
- UpdateValues(json)
+ parseJsonQ('/config/set?name=' + id + '&value=' + (input.checked?'true':'false'), function(json) {
+ updateValues(json)
})
break;
case 'week':
- ParseJsonQ('/config/set?name=' + id + '&value=' + input.dataset.value, function(json) {
- UpdateValues(json)
+ parseJsonQ('/config/set?name=' + id + '&value=' + input.dataset.value, function(json) {
+ updateValues(json)
})
break;
}
}
-function sendAction(name) {
- ParseJsonQ('/action?name=' + name, function(json) {
+function sendAction(name, params = {}) {
+ var url = '/action?name=' + name
+ for (var param in params) {
+ url += '&'+param+'='+encodeURIComponent(params[param])
+ }
+ parseJsonQ(url, function(json) {
if (json.result == 'FAILED') {
alert(json.message)
if (json.page) {
- DrawPage(json.page)
+ drawPage(json.page)
}
} else {
location.reload()
})
}
-function ShowPwd(id) {
+function showPwd(id) {
var x = document.getElementById('_ui_element_' + id)
if (x.type === "password") {
x.type = "text";
}
}
-function OpenSelect(id) {
+function openSelect(id) {
var selector = document.getElementById('_ui_elemmodal_'+id);
selector.removeAttribute("hidden")
}
-function CloseSelect(id) {
+function closeSelect(id) {
var selector = document.getElementById('_ui_elemmodal_'+id);
selector.hidden = true
}
-function SelectWiFi(id, ssid) {
- CloseSelect(id);
+function closeMsg() {
+ document.getElementById("_ui_message").hidden = true;
+}
+
+function fadeMsg() {
+ var msg = document.getElementById('_ui_message');
+ msg.classList.add("fadeout")
+ msgT = setTimeout(()=> { closeMsg() }, 5000);
+}
+
+function openMsg(msgText) {
+ document.getElementById("_ui_message_text").innerText = msgText;
+ document.getElementById("_ui_message").classList.remove("fadeout");
+ document.getElementById("_ui_message").removeAttribute('hidden');
+
+ if (msgT) {
+ window.clearTimeout(msgT);
+ }
+ msgT = setTimeout(()=> { fadeMsg(); }, 5000);
+}
+
+function selectWiFi(id, ssid) {
+ closeSelect(id);
var x = document.getElementById('_ui_element_' + id)
- UpdateElement(x,ssid);
+ updateElement(x,ssid);
sendUpdate(id)
}
return;
}
var json = JSON.parse(this.responseText)
- var table = '<table cellpadding="5" border="0" align="center"><thead class="table-header"><tr><td style="padding: 1rem">SSID</td><td style="padding: 1rem">BSSID</td><td style="padding: 1rem">RSSI</td><td style="padding: 1rem">Канал</td><td style="padding: 1rem">Защита</td></tr></thead></tbody style="border-bottom: lightgrey 1px solid">'
+ var table = '<table align="center"><thead class="table-header"><tr><td>SSID</td><td>BSSID</td><td>RSSI</td><td>Канал</td><td>Защита</td></tr></thead><tbody>'
if (!json.length) {
setTimeout(getWiFi(id),5000);
}
for (idx in json) {
- var encryption = json[idx].secure == 2? "TKIP" : json[idx].secure == 5? "WEP" : json[idx].secure == 4? "CCMP" : json[idx].secure == 7? "нет" : json[idx].secure == 8? "Автоматически" : "Не определено";
- table += '<tr onclick="SelectWiFi(\''+id+'\',\''+json[idx].ssid+'\')"><td style="padding: 1rem">'+json[idx].ssid+'</td><td style="padding: 1rem">'+json[idx].bssid+'</td><td style="padding: 1rem">'+json[idx].rssi+'</td><td style="padding: 1rem">'+json[idx].channel+'</td><td style="padding: 1rem">'+encryption+'</td></tr>'
+ var encryption = json[idx].secure == 2? "TKIP" : json[idx].secure == 5? "WEP" : json[idx].secure == 4? "CCMP" : json[idx].secure == 7? "нет" : json[idx].secure == 8? "Авто" : "Неизв.";
+ table += '<tr onclick="selectWiFi(\''+id+'\',\''+json[idx].ssid+'\')"><td>'+json[idx].ssid+'</td><td>'+json[idx].bssid+'</td><td>'+json[idx].rssi+'</td><td>'+json[idx].channel+'</td><td>'+encryption+'</td></tr>'
}
table += '</tbody></table>'
req.open("GET", "/wifi/scan", true);
req.send()
-
}
-function ClickDay(id, day) {
+function clickDay(id, day) {
value = parameters[id].split('')
day_value = value[day]
day_value = (day_value=='0')?'1':'0'
sendUpdate(id);
}
-function ElementHTML(element) {
+function sendTime(id) {
+ var value = document.getElementById('_ui_element_' + id).value
+ if (value) {
+ var date = new Date(value)
+ var timestamp = Math.floor(date.getTime()/1000);
+ sendAction('time',{"timestamp":timestamp})
+ }
+}
+
+function downloadFile(url, name) {
+ const a = document.createElement('a')
+ a.href = url
+ a.download = name?name:url.split('/').pop()
+ document.body.appendChild(a)
+ a.click()
+ document.body.removeChild(a)
+}
+
+function uploadConfig() {
+ var elem = document.getElementById('_config_file')
+ if (elem.value) {
+ var data = elem.files[0]
+ console.log(data)
+ fetch('/config/put', {method:'PUT',body:data});
+ elem.value = null
+ }
+}
+
+function elementHTML(element) {
var value
if (parameters[element.id] || !isNaN(parameters[element.id])) {
value = parameters[element.id]
case 'hr':
return '<div class="pure-u-1 pure-u-md-1-3"><hr></div>'
case 'button':
- return '<div class="pure-u-1 pure-u-md-1-3"><div align="center"><input style="margin:1em .5em 0;" type="button" id="'
- + element.id + '" value="' + encode(element.label) + '" class="pure-button pure-button-primary" onclick="sendAction(\'' + element.id + '\')" /></div></div>'
+ return '<div class="pure-u-1 pure-u-md-1-3"><div align="center"><input type="button" id="'
+ + element.id + '" value="' + encode(element.label) + '" class="pure-button" onclick="sendAction(\'' + element.id + '\')" /></div></div>'
case 'password':
return '<div class="pure-u-1 pure-u-md-1-3"><label for="_ui_element_' + element.id + '">' + encode(element.label) + '</label>'
- + '<input data-ui_class="password" type="password" id="_ui_element_' + element.id + '" value="' + encode(value)
- + '" class="pure-u-1" style="display:inline-block" maxlength="99" oninput="sendUpdate(\'' + element.id + '\')" />'
- + '<div class="hint" onclick="ShowPwd(\'' + element.id + '\')">👁</div></div>'
+ + '<div class="hinted"><input data-ui_class="password" type="password" id="_ui_element_' + element.id + '" value="' + encode(value)
+ + '" class="pure-u-1" maxlength="99" oninput="sendUpdate(\'' + element.id + '\')" />'
+ + '<z class="hint" onclick="showPwd(\'' + element.id + '\')"></z></div></div>'
case 'input':
var pattern = ""
if (element.pattern) {
pattern = ' pattern="' + encode(element.pattern) + '"'
}
return '<div class="pure-u-1 pure-u-md-1-3"><label for="_ui_element_' + element.id + '">' + encode(element.label) + '</label>'
- + '<input data-ui_class="input" type="text" id="_ui_element_' + element.id + '" value="' + encode(value) +'"'+ pattern
- + ' class="pure-u-1" style="display:inline-block" maxlength="99" oninput="sendUpdate(\'' + element.id + '\')" />'
- + '<div class="hint" onclick="OpenSelect(\'' + element.id+ '\'); getWiFi(\'' + element.id + '\')">📶</div>'
+ + '<div class="hinted"><input data-ui_class="input" type="text" id="_ui_element_' + element.id + '" value="' + encode(value) +'"'+ pattern
+ + ' class="pure-u-1" maxlength="99" oninput="sendUpdate(\'' + element.id + '\')" />'
+ + '<z class="hint" onclick="openSelect(\'' + element.id+ '\'); getWiFi(\'' + element.id + '\')"></z></div>'
+ '<div class="modal" id="_ui_elemmodal_' + element.id + '" hidden>'
+ '<div class="modal-content">'
+ '<div id="_ui_elemselect_' + element.id + '"></div>'
- + '<div class="pure-u-1 pure-u-md-1-3"><div align="center"><input style="margin:1em .5em 0;" type="button" id="_ui_button_'
- + element.id + '" value="Закрыть" class="pure-button pure-button-primary" onclick="CloseSelect(\'' + element.id + '\')"></div>'
- + '</div></div></div>'
+ + '<div class="pure-u-1 pure-u-md-1-3"><div align="center"><input type="button" id="_ui_button_'
+ + element.id + '" value="Закрыть" class="pure-button" onclick="closeSelect(\'' + element.id + '\')"></div>'
+ + '</div></div></div></div>'
case 'checkbox':
return '<div class="pure-u-1 pure-u-md-1-3"><label class="switch socket" for="_ui_element_' + element.id + '">'
+ '<input class="switch" data-ui_class="checkbox" type="checkbox" id="_ui_element_' + element.id + '"' + (parameters[element.id]?' checked':'') + ' onchange="sendUpdate(\'' + element.id + '\')" />'
+ '<table data-ui_class="week" data-value="' + value + '" id="_ui_element_' + element.id + '" cellpadding="5" border="0" class="week"><tbody><tr>'
for (i=0; i<7; i++) {
a_enabled = (value[i] == "1")
- days = days + '<td><div class="weekday' + (a_enabled?"-selected":"") + '" id="_ui_elpart_'+i+'_'+element.id+'" onclick="ClickDay(\'' + element.id + '\', ' + i + ')">'+ daynames[i] + '</div></td>'
+ days = days + '<td><div class="weekday' + (a_enabled?"-selected":"") + '" id="_ui_elpart_'+i+'_'+element.id+'" onclick="clickDay(\'' + element.id + '\', ' + i + ')">'+ daynames[i] + '</div></td>'
}
days += '</tr></tbody></table></div>'
return days
+ case 'timeset':
+ var now = new Date()
+ now.setMinutes(now.getMinutes() - now.getTimezoneOffset())
+ value = now.toISOString().slice(0, -1);
+ return '<div class="pure-u-1 pure-u-md-1-3"><label for="_ui_element_' + element.id + '">' + encode(element.label) + '</label>'
+ +'<input id="_ui_element_'+element.id+'" data-ui_class="timeset" class="inline-input" type="datetime-local" value="'+value+'">'
+ + '<div class="send-button" onclick="sendTime(\''+element.id+'\')">→</div></div>'
case 'text':
return '<div class="pure-u-1 pure-u-md-1-3"><h2 id="_ui_element_'+ element.id +'" ' + (element.color?'style="color:'+ element.color+'" ':'')+ '>' + encode(value) + '</h2></div>'
case 'number':
+ '<input data-ui_class="range" type="range" '+ (!isNaN(element.min)?'min="'+element.min+'" ':'') + (!isNaN(element.max)?'max="'+element.max+'" ':'') + (!isNaN(element.step)?'step="'+element.step+'" ':'')
+ 'id="_ui_element_' + element.id + '" value="' + encode(value) +'"'+ pattern
+ ' class="pure-u-1" maxlength="99" oninput="sendUpdate(\'' + element.id + '\')" /></div>'
+ case 'config':
+ return '<div class="pure-u-1 pure-u-md-1-3"><label for="_ui_element_' + element.id + '">' + encode(element.label) + '</label>'
+ + '<div align="center"><input type="button" class="pure-button row-button" value="Сохранить..." onclick="downloadFile(\'/config/get\',\'config.json\')">'
+ + '<label for="_config_file" class="pure-button row-button">Восстановить...</label>'
+ + '<input type="button" class="pure-button row-button" value="Настройки по умолчанию" onclick="confirm(\'Вы точно хотите сбросить настройки?\')?sendAction(\'reset\'):console.log(\'Не надо так не надо...\')">'
+ + '<input type="file" id="_config_file" onchange="uploadConfig()" hidden>'
+ + '</div></div>'
case 'table':
default:
- return '<div class="pure-u-1 pure-u-md-1-3"><table cellpadding="5" border="0" align="center"><tbody><tr><td style="padding-right: 10px; width: 50%;" align="right"><pre>'
- + encode(element.label)+ '</pre></td><td style="padding-left: 10px;" id="cT"><pre id="_ui_element_'
- + element.id + '" data-ui_class="table" ' + (element.color?'style="color:'+ element.color+'" ':'')+ '>' + encode(value) + '</pre></td></tr></tbody></table></div>'
+ return '<div class="pure-u-1 pure-u-md-1-3"><table class="texttable" cellpadding="5" border="0" align="center"><tbody><tr><td class="value-name" align="right">'
+ + encode(element.label)+ '</td><td id="_ui_element_'
+ + element.id + '" data-ui_class="table" ' + (element.color?'style="color:'+ element.color+'" ':'')+ '>' + encode(value) + '</td></tr></tbody></table></div>'
}
}
-function DrawPage(id) {
+function drawPage(id) {
var idx =0, i=0
for (const page of pages) {
var menu_link = document.getElementById('_ui_pglink_' + page.id)
var page_content = document.getElementById("_ui_page_content");
var content = ''
for (const element of pages[idx].elements) {
- content = content + ElementHTML(element) + '\n'
+ content = content + elementHTML(element) + '\n'
}
page_content.innerHTML = content
window.location.hash = id
}
-function DrawNavigator(project, pages) {
+function drawNavigator(project, pages) {
var menu = document.getElementById('_ui_menu_list');
var list = ''
for (const page of pages) {
list = list + '<li id="_ui_pglink_' + page.id
- + '" class="pure-menu-item"><a class="pure-menu-link" onclick="DrawPage(\''+ page.id +'\')" href="#' + page.id + '">'
+ + '" class="pure-menu-item"><a class="pure-menu-link" onclick="drawPage(\''+ page.id +'\')" href="#' + page.id + '">'
+ + (page.icon?'<span class="icon">'+page.icon+'</span>':'')
+ page.title+'</a></li>'
}
menu.innerHTML = list
}
-function DrawContacts(contacts) {
+function drawContacts(contacts) {
if (!contacts) return;
var contact_list = '<hr><h4 class="pure-u1">Контакты</h4>'
- for (const contact of contacts) {
+ for (contact of contacts) {
const url = new URL(contact)
var ref
- console.log(url)
switch (url.protocol) {
case 'http':
case 'https:':
- ref = '⌂ '+url.hostname
+ ref = '<span class="icon"></span>'+url.hostname
break
case 'mailto:':
- ref = '✉ '+url.pathname
+ ref = '<span class="icon"></span>'+url.pathname
+ break
+ case 'tg:':
+ ref = '<span class="icon"></span>'+url.pathname
+ contact = 'tg://resolve?domain='+url.pathname
break
default:
- ref = '🖅 '+url.pathname
+ ref = '<span class="icon"></span>'+url.pathname
}
contact_list += '<a href="'+contact+'">'+ref+'</a>'
}
footer.innerHTML = contact_list
}
-function DrawUI(ui) {
- DrawHeader(ui.project)
+function drawUI(ui) {
+ drawHeader(ui.project)
pages = ui.pages
- DrawNavigator(ui.project, pages)
- DrawContacts(ui.project.contacts)
+ drawNavigator(ui.project, pages)
+ drawContacts(ui.project.contacts)
var anchor = getAnchor()
if (anchor) {
- DrawPage(anchor)
+ drawPage(anchor)
} else {
- DrawPage(pages[0].id)
+ drawPage(pages[0].id)
}
}
function GetUI() {
- ParseJsonQ("/ui", DrawUI);
+ parseJsonQ("/ui", drawUI);
}
GetUI()
function initES() {
if (!!window.EventSource) {
var source = new EventSource('/events');
+ openMsg('Соединение установлено')
source.onerror = function(e) {
if (source.readyState == 2) {
+ openMsg('Соединение прервано')
setTimeout(initES, 5000);
}
};
- source.addEventListener('keepalive', function(e) {
- UpdateValues(JSON.parse(e.data));
- }, false);
-
source.addEventListener('update', function(e) {
- UpdateValues(JSON.parse(e.data));
+ updateValues(JSON.parse(e.data));
+ }, false);
+ source.addEventListener('message', function(e) {
+ openMsg(e.data);
}, false);
}
}
initES();
-function DrawConfig(cfg) {
- UpdateValues(cfg)
+function drawConfig(cfg) {
+ updateValues(cfg)
}
function GetCfg() {
- ParseJsonQ("/config/get", DrawConfig);
+ parseJsonQ("/config/get", drawConfig);
}
GetCfg()