summaryrefslogtreecommitdiff
path: root/platformio/common/static/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'platformio/common/static/app.js')
-rw-r--r--platformio/common/static/app.js246
1 files changed, 246 insertions, 0 deletions
diff --git a/platformio/common/static/app.js b/platformio/common/static/app.js
new file mode 100644
index 0000000..299230c
--- /dev/null
+++ b/platformio/common/static/app.js
@@ -0,0 +1,246 @@
+function isObject(o) {
+ return Object.prototype.toString.call(o) === '[object Object]';
+}
+
+function ge(id) {
+ return document.getElementById(id)
+}
+
+function hide(el) {
+ el.style.display = 'none'
+}
+
+function cancelEvent(evt) {
+ if (evt.preventDefault) evt.preventDefault();
+ if (evt.stopPropagation) evt.stopPropagation();
+
+ evt.cancelBubble = true;
+ evt.returnValue = false;
+
+ return false;
+}
+
+function errorText(e) {
+ return e instanceof Error ? e.message : e+''
+}
+
+(function() {
+ function request(method, url, data, callback) {
+ data = data || null;
+
+ if (typeof callback != 'function') {
+ throw new Error('callback must be a function');
+ }
+
+ if (!url)
+ throw new Error('no url specified');
+
+ switch (method) {
+ case 'GET':
+ if (isObject(data)) {
+ for (var k in data) {
+ if (data.hasOwnProperty(k))
+ url += (url.indexOf('?') === -1 ? '?' : '&')+encodeURIComponent(k)+'='+encodeURIComponent(data[k])
+ }
+ }
+ break;
+
+ case 'POST':
+ if (isObject(data)) {
+ var sdata = [];
+ for (var k in data) {
+ if (data.hasOwnProperty(k))
+ sdata.push(encodeURIComponent(k)+'='+encodeURIComponent(data[k]));
+ }
+ data = sdata.join('&');
+ }
+ break;
+ }
+
+ var xhr = new XMLHttpRequest();
+ xhr.open(method, url);
+
+ if (method === 'POST')
+ xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ if ('status' in xhr && !/^2|1223/.test(xhr.status))
+ throw new Error('http code '+xhr.status)
+ callback(null, JSON.parse(xhr.responseText));
+ }
+ };
+ xhr.onerror = function(e) {
+ callback(e, null);
+ };
+
+ xhr.send(method === 'GET' ? null : data);
+ return xhr;
+ }
+
+ window.ajax = {
+ get: request.bind(request, 'GET'),
+ post: request.bind(request, 'POST')
+ }
+})();
+
+
+function lock(el) {
+ el.setAttribute('disabled', 'disabled');
+}
+
+function unlock(el) {
+ el.removeAttribute('disabled');
+}
+
+function initNetworkSettings() {
+ function setupField(el, value) {
+ if (value !== null)
+ el.value = value;
+ unlock(el);
+ }
+
+ var doneRequestsCount = 0;
+ function onRequestDone() {
+ doneRequestsCount++;
+ if (doneRequestsCount === 2) {
+ hide(ge('loading_label'))
+ }
+ }
+
+ var form = document.forms.network_settings;
+ form.addEventListener('submit', function(e) {
+ if (!form.hid.value.trim()) {
+ alert('Введите home id');
+ return cancelEvent(e);
+ }
+
+ if (form.psk.value.length < 8) {
+ alert('Неверный пароль (минимальная длина - 8 символов)');
+ return cancelEvent(e);
+ }
+
+ if (form.ssid.selectedIndex === -1) {
+ alert('Не выбрана точка доступа');
+ return cancelEvent(e);
+ }
+
+ lock(form.submit)
+ })
+ form.show_psk.addEventListener('change', function(e) {
+ form.psk.setAttribute('type', e.target.checked ? 'text' : 'password');
+ });
+ form.ssid.addEventListener('change', function(e) {
+ var i = e.target.selectedIndex;
+ if (i !== -1) {
+ var opt = e.target.options[i];
+ if (opt)
+ form.psk.value = '';
+ }
+ });
+
+ ajax.get('/status', {}, function(error, response) {
+ try {
+ if (error)
+ throw error;
+
+ setupField(form.hid, response.node_id || null);
+ setupField(form.psk, null);
+ setupField(form.submit, null);
+
+ onRequestDone();
+ } catch (error) {
+ alert(errorText(error));
+ }
+ });
+
+ ajax.get('/scan', {}, function(error, response) {
+ try {
+ if (error)
+ throw error;
+
+ form.ssid.innerHTML = '';
+ for (var i = 0; i < response.list.length; i++) {
+ var ssid = response.list[i][0];
+ var rssi = response.list[i][1];
+ form.ssid.append(new Option(ssid + ' (' + rssi + ' dBm)', ssid));
+ }
+ unlock(form.ssid);
+
+ onRequestDone();
+ } catch (error) {
+ alert(errorText(error));
+ }
+ });
+}
+
+function initUpdateForm() {
+ var form = document.forms.update_settings;
+ form.addEventListener('submit', function(e) {
+ cancelEvent(e);
+ if (!form.file.files.length) {
+ alert('Файл обновления не выбран');
+ return false;
+ }
+
+ lock(form.submit);
+
+ var xhr = new XMLHttpRequest();
+ var fd = new FormData();
+ fd.append('file', form.file.files[0]);
+
+ xhr.upload.addEventListener('progress', function (e) {
+ var total = form.file.files[0].size;
+ var progress;
+ if (e.loaded < total) {
+ progress = Math.round(e.loaded / total * 100).toFixed(2);
+ } else {
+ progress = 100;
+ }
+ form.submit.innerHTML = progress + '%';
+ });
+ xhr.onreadystatechange = function() {
+ var errorMessage = 'Ошибка обновления';
+ var successMessage = 'Обновление завершено, устройство перезагружается';
+ if (xhr.readyState === 4) {
+ try {
+ var response = JSON.parse(xhr.responseText);
+ if (response.result === 1) {
+ alert(successMessage);
+ } else {
+ alert(errorMessage);
+ }
+ } catch (e) {
+ alert(successMessage);
+ }
+ }
+ };
+ xhr.onerror = function(e) {
+ alert(errorText(e));
+ };
+
+ xhr.open('POST', e.target.action);
+ xhr.send(fd);
+
+ return false;
+ });
+ form.file.addEventListener('change', function(e) {
+ if (e.target.files.length) {
+ var reader = new FileReader();
+ reader.onload = function() {
+ var hash = window.md5(reader.result);
+ form.setAttribute('action', '/update?md5='+hash);
+ unlock(form.submit);
+ };
+ reader.onerror = function() {
+ alert('Ошибка чтения файла');
+ };
+ reader.readAsBinaryString(e.target.files[0]);
+ }
+ });
+}
+
+window.initApp = function() {
+ initNetworkSettings();
+ initUpdateForm();
+} \ No newline at end of file