Juice/static/juice.js

308 lines
9.2 KiB
JavaScript
Raw Normal View History

2019-11-15 10:35:56 -05:00
var socket;
2019-06-19 10:15:08 -04:00
function load() {
2019-11-15 10:35:56 -05:00
socket = init_websocket();
// initialize RelayOutlet SVG color
2019-11-20 11:00:37 -05:00
Object.entries(init_state).forEach(([device_id, sub_devices]) => {
2019-06-19 10:15:08 -04:00
let device = document.querySelector('#' + device_id);
2019-11-20 11:00:37 -05:00
Object.entries(sub_devices).forEach(([sub_device_id, state]) => {
let sub_device = device.querySelector('.' + sub_device_id);
let svg = sub_device.querySelector('object').getSVGDocument().firstElementChild;
2019-06-19 10:15:08 -04:00
if (state) {
svg.classList.remove('off');
svg.classList.add('on');
}
});
});
2019-07-02 13:09:31 -04:00
2019-11-18 13:05:37 -05:00
/*document.querySelectorAll('input[type=color]').forEach((led_input) => {
2019-07-02 13:09:31 -04:00
led_input.onchange = function(event) {
}
2019-11-18 13:05:37 -05:00
});*/
2019-06-19 10:15:08 -04:00
}
2019-11-15 10:35:56 -05:00
/* Websocket setup */
function init_websocket() {
2019-11-15 12:21:35 -05:00
let socket = new WebSocket('wss://' + window.location.hostname + ws_uri);
2019-11-15 10:35:56 -05:00
socket._send = socket.send;
socket.send = function(event_title, data) {
data = JSON.stringify({event: event_title, data: data});
if (socket.readyState == 0) {
console.log("Socket is still opening!");
2019-11-15 12:21:35 -05:00
return;
2019-06-18 12:49:01 -04:00
}
2019-11-15 10:35:56 -05:00
socket._send(data);
2019-06-18 12:49:01 -04:00
}
2019-11-15 10:35:56 -05:00
socket.onmessage = onmessage;
socket.onclose = onclose;
socket.onerror = onerror;
socket.events = {};
socket.events['toggle_outlet'] = toggle_outlet_recv;
2019-11-15 12:21:35 -05:00
socket.events['edit_field'] = edit_field_recv;
socket.events['new_device'] = new_device_recv;
socket.events['lock_device'] = lock_device_recv;
socket.events['delete_device'] = delete_device_recv;
2019-11-18 13:05:37 -05:00
socket.events['neopixel'] = neopixel_recv;
2019-11-15 10:35:56 -05:00
return socket;
2019-06-18 12:49:01 -04:00
}
2019-11-15 10:35:56 -05:00
function onmessage (e) {
let data = JSON.parse(e.data);
let event = data.event;
data = data.data;
2019-11-15 12:21:35 -05:00
if (!data.ok) {
2019-11-18 13:05:37 -05:00
throw new Error("Socket error: event = " + event + ", error = " + data.error);
2019-11-15 12:21:35 -05:00
}
if (socket.events[event] === undefined) {
console.log("Unknown socket event: " + event);
return;
}
2019-11-15 10:35:56 -05:00
socket.events[event](data);
}
async function onclose(e) {
2019-11-15 10:35:56 -05:00
if (e.wasClean) { return; } // no need to reconnect
console.log(e);
console.log('Websocket lost connection to server. Re-trying...');
socket = init_websocket();
await sleep(5000);
2019-11-15 10:35:56 -05:00
}
function onerror(e) {
console.log("Websocket error!")
console.log(e);
}
/* Websocket receive */
function toggle_outlet_recv(data) {
let device = document.querySelector('#' + data.device_id);
2019-11-15 12:21:35 -05:00
let sub_device = device.querySelector('.' + data.sub_device_id);
2019-11-15 10:35:56 -05:00
let svg = sub_device.querySelector('.outlet_image').getSVGDocument().firstChild;
if (data.state === true) {
svg.classList.remove('off');
svg.classList.add('on');
} else {
svg.classList.remove('on');
svg.classList.add('off');
}
}
2019-11-15 12:21:35 -05:00
function edit_field_recv(data) {
let device = document.querySelector('#' + data.device_id);
if (data.sub_device_id) {
device = device.querySelector('.' + data.sub_device_id);
}
let field = device.querySelector('.' + data.field);
let span = document.createElement('span');
span.innerText = data['value'];
span.className = 'field_value';
field.firstElementChild.replaceWith(span);
let edit = document.createElement('span');
edit.innerHTML = '';
edit.className = 'edit font-awesome';
edit.setAttribute('onclick', 'edit_field(this.parentElement)');
field.children[1].replaceWith(edit);
}
function new_device_recv(data) {
if (data.device_type == 'RelayDevice') {
var template = document.querySelector('#RelayDevice_template');
} else {
return;
}
let node = document.importNode(template.content, true);
node.querySelector('.id').querySelector('.field_value').textContent = data.device_id;
document.querySelector('#devices').appendChild(node);
let children = document.querySelector('#devices').children;
children[children.length - 1].id = data.device_id;
}
function lock_device_recv(data) {
let device = document.querySelector('#' + data.device_id);
let fields = device.querySelectorAll('.editable');
if (data.locked) {
fields.forEach(function(field) {
field.querySelector('.edit').remove();
});
device.querySelector('.id').querySelector('.lock').remove();
device.querySelector('.id').querySelector('.delete').remove();
let unlock = document.createElement('span');
unlock.innerHTML = '';
unlock.className = 'unlock font-awesome';
unlock.setAttribute('onclick', 'unlock_device(this.parentElement.parentElement)');
device.querySelector('.id').appendChild(unlock);
} else {
fields.forEach(function(field) {
let edit = document.createElement('span');
edit.innerHTML = '';
edit.className = 'edit font-awesome';
edit.setAttribute('onclick', 'edit_field(this.parentElement)');
field.appendChild(edit);
});
device.querySelector('.id').querySelector('.unlock').remove();
let delete_elem = document.createElement('span');
delete_elem.innerHTML = '';
delete_elem.className = 'delete font-awesome';
delete_elem.setAttribute('onclick', 'delete_device(this.parentElement.parentElement)');
device.querySelector('.id').appendChild(delete_elem);
let lock = document.createElement('span');
lock.innerHTML = '';
lock.className = 'lock font-awesome';
lock.setAttribute('onclick', 'lock_device(this.parentElement.parentElement)');
device.querySelector('.id').appendChild(lock);
}
}
function delete_device_recv(data) {
let device = document.querySelector('#' + data.device_id);
device.remove()
}
2019-11-18 13:05:37 -05:00
function neopixel_recv(data) {
let device = document.querySelector('#' + data.device_id);
let sub_device = device.querySelector('.' + data.sub_device_id);
sub_device.firstElementChild.style.backgroundColor = data.color;
}
2019-11-15 10:35:56 -05:00
/* Websocket send */
2019-06-06 13:16:59 -04:00
function toggle_outlet(svg) {
2019-06-18 12:49:01 -04:00
let sub_dev = get_object_from_svg(svg).parentElement;
2019-11-15 10:35:56 -05:00
let data = {
2019-06-06 13:16:59 -04:00
device_id: sub_dev.parentElement.parentElement.id,
2019-11-15 10:35:56 -05:00
sub_device_id: sub_dev.querySelector('.id').innerText,
2019-06-06 13:16:59 -04:00
};
2019-11-15 10:35:56 -05:00
socket.send('toggle_outlet', data);
2019-06-06 13:16:59 -04:00
}
2019-06-13 10:46:59 -04:00
function save_field(field) {
let value = field.firstElementChild.value;
let device_id = field.parentElement.id;
2019-11-15 13:25:39 -05:00
let sub_device_id;
2019-06-13 10:46:59 -04:00
if (field.parentElement.className.includes('sub_device')) {
2019-11-15 12:21:35 -05:00
sub_device_id = field.parentElement.children[0].textContent;
2019-06-13 10:46:59 -04:00
device_id = field.parentElement.parentElement.parentElement.id;
} else {
2019-11-15 12:21:35 -05:00
sub_device_id = '';
2019-06-13 10:46:59 -04:00
}
2019-11-15 12:21:35 -05:00
let data = {
2019-06-13 10:46:59 -04:00
device_id: device_id,
2019-11-15 13:25:39 -05:00
sub_device_id: sub_device_id,
2019-06-20 11:28:26 -04:00
field: field.classList[0],
2019-06-13 10:46:59 -04:00
value: value
};
2019-11-15 12:21:35 -05:00
socket.send('edit_field', data);
2019-06-13 10:46:59 -04:00
}
2019-06-20 07:49:29 -04:00
function new_device() {
2019-11-15 12:21:35 -05:00
let data = {
2019-06-20 07:49:29 -04:00
device_type: 'RelayDevice',
};
2019-11-15 12:21:35 -05:00
socket.send('new_device', data);
2019-06-20 07:49:29 -04:00
}
2019-06-20 11:19:31 -04:00
function lock_device(device) {
if (device.querySelector('.save')) { return; }
2019-11-15 12:21:35 -05:00
let data = {
2019-06-20 12:36:19 -04:00
device_id: device.id,
locked: true,
};
2019-11-15 12:21:35 -05:00
socket.send('lock_device', data);
2019-06-20 11:19:31 -04:00
}
function unlock_device(device) {
2019-11-15 12:21:35 -05:00
let data = {
2019-06-20 12:36:19 -04:00
device_id: device.id,
locked: false,
};
2019-11-15 12:21:35 -05:00
socket.send('lock_device', data);
2019-06-20 11:19:31 -04:00
}
2019-06-20 14:51:00 -04:00
function delete_device(device) {
if (!window.confirm("Are you sure you want to delete this device?")) { return; }
2019-11-15 12:21:35 -05:00
let data = {
2019-06-20 14:51:00 -04:00
device_id: device.id,
};
2019-11-15 12:21:35 -05:00
socket.send('delete_device', data);
2019-06-20 14:51:00 -04:00
}
2019-06-23 14:01:03 -04:00
2019-11-18 13:05:37 -05:00
function neopixel(device) {
let data = {
device_id: device.parentElement.parentElement.id,
sub_device_id: device.classList[2],
change_mode: 'state',
type: 'solid',
amount: 'single',
color: device.firstElementChild.firstElementChild.value
}
socket.send('neopixel', data);
}
2019-11-15 12:21:35 -05:00
/* DOM */
function edit_field(field) {
let value = field.firstElementChild.innerText;
let input = document.createElement('input');
input.value = value;
field.firstElementChild.replaceWith(input);
2019-06-23 14:01:03 -04:00
2019-11-15 12:21:35 -05:00
let save = document.createElement('span');
save.innerHTML = '';
save.className = 'save font-awesome';
save.setAttribute('onclick', 'save_field(this.parentElement)');
field.children[1].replaceWith(save);
2019-06-23 14:01:03 -04:00
}
2019-11-15 10:35:56 -05:00
/* Misc */
function get_object_from_svg(svg) {
let all_objects = document.getElementsByTagName("object");
for (let i=0; i < all_objects.length; i++) {
if (svg === all_objects[i].getSVGDocument().firstElementChild) {
return all_objects[i];
}
}
return null;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
2019-11-20 11:00:37 -05:00
function state_solid_amount(radio) {
let device = radio.parentElement.parentElement.parentElement.parentElement;
let sub_devices = device.querySelector('.sub_devices');
for (let sub_device of sub_devices.children) {
let input = sub_device.firstElementChild.firstElementChild;
if (radio.value === 'all') {
input.disabled = true;
} else if (radio.value === 'single') {
input.disabled = false;
}
}
if (radio.value === 'all') {
device.querySelector('#state_solid_all_color_' + device.id).disabled = false;
} else if (radio.value === 'single') {
device.querySelector('#state_solid_all_color_' + device.id).disabled = true;
}
}
function state_select(select) {
if (select.value === 'solid') {
select.parentElement.querySelector('.state_solid').style.display = 'block';
select.parentElement.querySelector('.state_rainbow').style.display = 'none';
select.parentElement.querySelector('.state_america').style.display = 'none';
} else if (select.value === 'rainbow') {
select.parentElement.querySelector('.state_solid').style.display = 'none';
select.parentElement.querySelector('.state_rainbow').style.display = 'block';
select.parentElement.querySelector('.state_america').style.display = 'none';
} else if (select.value === 'america') {
select.parentElement.querySelector('.state_solid').style.display = 'none';
select.parentElement.querySelector('.state_rainbow').style.display = 'none';
select.parentElement.querySelector('.state_america').style.display = 'block';
}
}