123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- //===== Collection of small utilities
- /*
- * Bind/Unbind events
- *
- * Usage:
- * var el = document.getElementyById('#container');
- * bnd(el, 'click', function() {
- * console.log('clicked');
- * });
- */
- var bnd = function(
- d, // a DOM element
- e, // an event name such as "click"
- f // a handler function
- ){
- d.addEventListener(e, f, false);
- }
- /*
- * Create DOM element
- *
- * Usage:
- * var el = m('<h1>Hello</h1>');
- * document.body.appendChild(el);
- *
- * Copyright (C) 2011 Jed Schmidt <http://jed.is> - WTFPL
- * More: https://gist.github.com/966233
- */
- var m = function(
- a, // an HTML string
- b, // placeholder
- c // placeholder
- ){
- b = document; // get the document,
- c = b.createElement("p"); // create a container element,
- c.innerHTML = a; // write the HTML to it, and
- a = b.createDocumentFragment(); // create a fragment.
- while ( // while
- b = c.firstChild // the container element has a first child
- ) a.appendChild(b); // append the child to the fragment,
- return a // and then return the fragment.
- }
- /*
- * DOM selector
- *
- * Usage:
- * $('div');
- * $('#name');
- * $('.name');
- *
- * Copyright (C) 2011 Jed Schmidt <http://jed.is> - WTFPL
- * More: https://gist.github.com/991057
- */
- var $ = function(
- a, // take a simple selector like "name", "#name", or ".name", and
- b // an optional context, and
- ){
- a = a.match(/^(\W)?(.*)/); // split the selector into name and symbol.
- return( // return an element or list, from within the scope of
- b // the passed context
- || document // or document,
- )[
- "getElement" + ( // obtained by the appropriate method calculated by
- a[1]
- ? a[1] == "#"
- ? "ById" // the node by ID,
- : "sByClassName" // the nodes by class name, or
- : "sByTagName" // the nodes by tag name,
- )
- ](
- a[2] // called with the name.
- )
- }
- /*
- * Get cross browser xhr object
- *
- * Copyright (C) 2011 Jed Schmidt <http://jed.is>
- * More: https://gist.github.com/993585
- */
- var j = function(
- a // cursor placeholder
- ){
- for( // for all a
- a=0; // from 0
- a<4; // to 4,
- a++ // incrementing
- ) try { // try
- return a // returning
- ? new ActiveXObject( // a new ActiveXObject
- [ // reflecting
- , // (elided)
- "Msxml2", // the various
- "Msxml3", // working
- "Microsoft" // options
- ][a] + // for Microsoft implementations, and
- ".XMLHTTP" // the appropriate suffix,
- ) // but make sure to
- : new XMLHttpRequest // try the w3c standard first, and
- }
- catch(e){} // ignore when it fails.
- }
- // dom element iterator: domForEach($(".some-class"), function(el) { ... });
- function domForEach(els, fun) { return Array.prototype.forEach.call(els, fun); }
- // createElement short-hand
- e = function(a) { return document.createElement(a); }
- // chain onload handlers
- function onLoad(f) {
- var old = window.onload;
- if (typeof old != 'function') {
- window.onload = f;
- } else {
- window.onload = function() {
- old();
- f();
- }
- }
- }
- //===== helpers to add/remove/toggle HTML element classes
- function addClass(el, cl) {
- el.className += ' ' + cl;
- }
- function removeClass(el, cl) {
- var cls = el.className.split(/\s+/),
- l = cls.length;
- for (var i=0; i<l; i++) {
- if (cls[i] === cl) cls.splice(i, 1);
- }
- el.className = cls.join(' ');
- return cls.length != l
- }
- function toggleClass(el, cl) {
- if (!removeClass(el, cl)) addClass(el, cl);
- }
- //===== AJAX
- function ajaxReq(method, url, ok_cb, err_cb, data) {
- var xhr = j();
- xhr.open(method, url, true);
- var timeout = setTimeout(function() {
- xhr.abort();
- console.log("XHR abort:", method, url);
- xhr.status = 599;
- xhr.responseText = "request time-out";
- }, 9000);
- xhr.onreadystatechange = function() {
- if (xhr.readyState != 4) { return; }
- clearTimeout(timeout);
- if (xhr.status >= 200 && xhr.status < 300) {
- // console.log("XHR done:", method, url, "->", xhr.status);
- ok_cb(xhr.responseText);
- } else {
- console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText, xhr);
- err_cb(xhr.status, xhr.responseText);
- }
- }
- // console.log("XHR send:", method, url);
- try {
- xhr.send(data);
- } catch(err) {
- console.log("XHR EXC :", method, url, "->", err);
- err_cb(599, err);
- }
- }
- function dispatchJson(resp, ok_cb, err_cb) {
- var j;
- try { j = JSON.parse(resp); }
- catch(err) {
- console.log("JSON parse error: " + err + ". In: " + resp);
- err_cb(500, "JSON parse error: " + err);
- return;
- }
- ok_cb(j);
- }
- function ajaxJson(method, url, ok_cb, err_cb) {
- ajaxReq(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb);
- }
- function ajaxSpin(method, url, ok_cb, err_cb) {
- $("#spinner").removeAttribute('hidden');
- ajaxReq(method, url, function(resp) {
- $("#spinner").setAttribute('hidden', '');
- ok_cb(resp);
- }, function(status, statusText) {
- $("#spinner").setAttribute('hidden', '');
- //showWarning("Error: " + statusText);
- err_cb(status, statusText);
- });
- }
- function ajaxJsonSpin(method, url, ok_cb, err_cb) {
- ajaxSpin(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb);
- }
- //===== main menu, header spinner and notification boxes
- function hidePopup(el) {
- addClass(el, "popup-hidden");
- addClass(el.parentNode, "popup-target");
- }
- /*onLoad(function() {
- var l = $("#layout");
- var o = l.childNodes[0];
- // spinner
- l.insertBefore(m('<div id="spinner" class="spinner" hidden></div>'), o);
- // notification boxes
- l.insertBefore(m(
- '<div id="messages"><div id="warning" hidden></div><div id="notification" hidden></div></div>'), o);
- // menu hamburger button
- l.insertBefore(m('<a href="#menu" id="menuLink" class="menu-link"><span></span></a>'), o);
- // menu left-pane
- var mm = m(
- '<div id="menu">\
- <div class="pure-menu">\
- <a class="pure-menu-heading" href="https://github.com/jeelabs/meta-id">\
- <img src="/favicon.ico" height="32"> meta-id</a>\
- <div class="pure-menu-heading system-name" style="padding: 0px 0.6em"></div>\
- <ul id="menu-list" class="pure-menu-list"></ul>\
- </div>\
- </div>\
- ');
- l.insertBefore(mm, o);
- // make hamburger button pull out menu
- var ml = $('#menuLink'), mm = $('#menu');
- bnd(ml, 'click', function (e) {
- // console.log("hamburger time");
- var active = 'active';
- e.preventDefault();
- toggleClass(l, active);
- toggleClass(mm, active);
- toggleClass(ml, active);
- });
- // hide pop-ups
- domForEach($(".popup"), function(el) {
- hidePopup(el);
- });
- // populate menu via ajax call
- var getMenu = function() {
- ajaxJson("GET", "/menu", function(data) {
- var html = "", path = window.location.pathname;
- for (var i=0; i<data.menu.length; i+=2) {
- var href = data.menu[i+1];
- html = html.concat(" <li class=\"pure-menu-item" +
- (path === href ? " pure-menu-selected" : "") + "\">" +
- "<a href=\"" + href + "\" class=\"pure-menu-link\">" +
- data.menu[i] + "</a></li>");
- }
- $("#menu-list").innerHTML = html;
- var v = $("#version");
- if (v != null) { v.innerHTML = data.version; }
- $('title')[0].innerHTML = data["name"];
- setEditToClick("system-name", data["name"]);
- }, function() { setTimeout(getMenu, 1000); });
- };
- getMenu();
- });
- */
- //===== Wifi info
- function showWifiInfo(data) {
- Object.keys(data).forEach(function(v) {
- el = $("#wifi-" + v);
- if (el != null) {
- if (el.nodeName === "INPUT") el.value = data[v];
- else el.innerHTML = data[v];
- }
- });
- var dhcp = $('#dhcp-r'+data.dhcp);
- if (dhcp) dhcp.click();
- $("#wifi-table").removeAttribute("hidden");
- currAp = data.ssid;
- }
- function getWifiInfo() {
- ajaxJson('GET', "/wifi/info", showWifiInfo,
- function(s, st) { window.setTimeout(getWifiInfo, 1000); });
- }
- //===== System info
- function showSystemInfo(data) {
- Object.keys(data).forEach(function(v) {
- setEditToClick("system-"+v, data[v]);
- });
- $("#system-spinner").setAttribute("hidden", "");
- $("#system-table").removeAttribute("hidden");
- currAp = data.ssid;
- }
- function getSystemInfo() {
- ajaxJson('GET', "/system/info", showSystemInfo,
- function(s, st) { window.setTimeout(getSystemInfo, 1000); });
- }
- function makeAjaxInput(klass, field) {
- domForEach($("."+klass+"-"+field), function(div) {
- var eon = $(".edit-on", div);
- var eoff = $(".edit-off", div)[0];
- var url = "/"+klass+"/update?"+field;
- if (eoff === undefined || eon == undefined) return;
- var enableEditToClick = function() {
- eoff.setAttribute('hidden','');
- domForEach(eon, function(el){ el.removeAttribute('hidden'); });
- eon[0].select();
- return false;
- }
- var submitEditToClick = function(v) {
- // console.log("Submit POST "+url+"="+v);
- ajaxSpin("POST", url+"="+v, function() {
- domForEach(eon, function(el){ el.setAttribute('hidden',''); });
- eoff.removeAttribute('hidden');
- setEditToClick(klass+"-"+field, v)
- showNotification(field + " changed to " + v);
- }, function() {
- showWarning(field + " change failed");
- });
- return false;
- }
- bnd(eoff, "click", function(){return enableEditToClick();});
- bnd(eon[0], "blur", function(){return submitEditToClick(eon[0].value);});
- bnd(eon[0], "keyup", function(ev){
- if ((ev||window.event).keyCode==13) return submitEditToClick(eon[0].value);
- });
- });
- }
- function setEditToClick(klass, value) {
- domForEach($("."+klass), function(div) {
- if (div.children.length > 0) {
- domForEach(div.children, function(el) {
- if (el.nodeName === "INPUT") el.value = value;
- else if (el.nodeName !== "DIV") el.innerHTML = value;
- });
- } else {
- div.innerHTML = value;
- }
- });
- }
- //===== Notifications
- function showWarning(text) {
- var el = $("#notification");
- el.innerHTML = text;
- el.removeAttribute('hidden');
- window.scrollTo(0, 0);
- }
- function hideWarning() {
- el = $("#notification").setAttribute('hidden', '');
- }
- var notifTimeout = null;
- function showNotification(text) {
- if(text=='')return;
- var el = $("#notification");
- el.innerHTML = text;
- el.removeAttribute('hidden');
- if (notifTimeout != null) clearTimeout(notifTimeout);
- notifTimout = setTimeout(function() {
- el.setAttribute('hidden', '');
- notifTimout = null;
- }, 4000);
- }
- function loginNotification(text) {
- if(text=='')return;
- var el = $("#loginnotification");
- el.innerHTML = text;
- el.removeAttribute('hidden');
- if (notifTimeout != null) clearTimeout(notifTimeout);
- notifTimout = setTimeout(function() {
- el.setAttribute('hidden', '');
- notifTimout = null;
- }, 4000);
- }
- //===== GPIO Pin mux card
- var pinPresets = {
- // array: reset, isp, conn, ser, swap, rxpup, txen
- "esp-01": [ 0, -1, 2, -1, 0, 1, -1 ],
- "esp-12": [ 12, 14, 0, 2, 0, 1, -1 ],
- "esp-12 swap": [ 1, 3, 0, 2, 1, 1, -1 ],
- "esp-bridge": [ 12, 13, 0, 14, 0, 0, -1 ],
- "wifi-link-12": [ 1, 3, 0, 2, 1, 0, -1 ],
- };
- function createPresets(sel) {
- for (var p in pinPresets) {
- var opt = m('<option value="' + p + '">' + p + '</option>');
- sel.appendChild(opt);
- }
- function applyPreset(v) {
- var pp = pinPresets[v];
- if (pp === undefined) return pp;
- // console.log("apply preset:", v, pp);
- function setPP(k, v) { $("#pin-"+k).value = v; };
- setPP("reset", pp[0]);
- setPP("isp", pp[1]);
- setPP("conn", pp[2]);
- setPP("ser", pp[3]);
- setPP("swap", pp[4]);
- $("#pin-rxpup").checked = !!pp[5];
- setPP("txen", pp[6]);
- sel.value = 0;
- };
- bnd(sel, "change", function(ev) {
- ev.preventDefault();
- applyPreset(sel.value);
- });
- }
- function displayPins(resp) {
- function createSelectForPin(name, v) {
- var sel = $("#pin-"+name);
- addClass(sel, "pure-button");
- sel.innerHTML = "";
- [-1,0,1,2,3,4,5,12,13,14,15].forEach(function(i) {
- var opt = document.createElement("option");
- opt.value = i;
- if (i >= 0) opt.innerHTML = "gpio"+i;
- else opt.innerHTML = "disabled";
- if (i===1) opt.innerHTML += "/TX0";
- if (i===2) opt.innerHTML += "/TX1";
- if (i===3) opt.innerHTML += "/RX0";
- if (i==v) opt.selected = true;
- sel.appendChild(opt);
- });
- var pup = $(".popup", sel.parentNode);
- if (pup !== undefined) hidePopup(pup[0]);
- };
- createSelectForPin("reset", resp["reset"]);
- createSelectForPin("isp", resp["isp"]);
- createSelectForPin("conn", resp["conn"]);
- createSelectForPin("ser", resp["ser"]);
- $("#pin-swap").value = resp["swap"];
- $("#pin-rxpup").checked = !!resp["rxpup"];
- createSelectForPin("txen", resp["txen"]);
- createPresets($("#pin-preset"));
- $("#pin-spinner").setAttribute("hidden", "");
- $("#pin-table").removeAttribute("hidden");
- }
- function fetchPins() {
- ajaxJson("GET", "/pins", displayPins, function() {
- window.setTimeout(fetchPins, 1000);
- });
- }
- function setPins(ev) {
- ev.preventDefault();
- var url = "/pins";
- var sep = "?";
- ["reset", "isp", "conn", "ser", "swap", "txen"].forEach(function(p) {
- url += sep + p + "=" + $("#pin-"+p).value;
- sep = "&";
- });
- url += "&rxpup=" + ($("#pin-rxpup").checked ? "1" : "0");
- // console.log("set pins: " + url);
- ajaxSpin("POST", url, function() {
- showNotification("Pin assignment changed");
- }, function(status, errMsg) {
- showWarning(errMsg);
- window.setTimeout(fetchPins, 100);
- });
- }
- function loadWifiInfo(data){
- showWifiInfo(data);
- wifiInfo=data;
- if(data != null){
- if (data.status == "connecting") {
- curState=1;
- }
- else if(data.status == "got IP address"){
- showWifiInfo(data);
- curState=2;
- }
- else{
- curState=0;
- }
- }
- stateMachine();
- }
- /**
- * -1 : unknown, waiting for authentication
- * 0 : login box // if no wifi config and no auth
- * 1 : login success // if auth ok
- * 2 : wifi config // if no wifi connection and on request
- * 3 : connecting //
- * 4 : connected
- **/
- var curState=-1;
- var lastState=-2
- var wifiInfo=null;
- function resetWifiAp(e) {
- e.preventDefault();
- showNotification("Ressetting configuration...");
- var url = "/wifi/connect?essid=&passwd=";
- hideWarning();
- $("#reconnect").setAttribute("hidden", "");
- $("#wifi-passwd").value = "";
- var cb = $("#reset-button");
- var cn = cb.className;
- cb.className += ' pure-button-disabled';
- blockScan = 1;
- ajaxSpin("POST", url, function(resp) {
- $("#spinner").removeAttribute('hidden'); // hack
- showNotification("Waiting for network change...");
- window.scrollTo(0, 0);
- window.setTimeout(getStatus, 2000);
- }, function(s, st) {
- showWarning("Error resetting network: "+st);
- cb.className = cn;
- window.setTimeout(scanAPs, 1000);
- });
- }
- function toggle(a){
- del=document.getElementById(a);
- if(del.hasAttribute("hidden")){
- del.removeAttribute("hidden");
- }
- else{
- del.setAttribute("hidden","");}
- }
- function restartSM(resp){
- stateMachine(resp);
- }
- function stateMachine (resp) {
- try { jrep = JSON.parse(resp); }
- catch(err) {
- console.log("JSON parse error: " + err + ". In: " + resp);
- jrep['state']=-1;
- jrep['msg']="not initialized";
- }
- curState=jrep['state'];
- if(lastState!=curState){
- showNotification(jrep['msg']);
- if(jrep['auth'] == 0){
- curState=-1
- }
- for(i=-1;i<5;i++){
- del=$("#state-"+i);
- del.setAttribute('hidden','');
- }
- del=$("#state-"+curState);
- del.removeAttribute('hidden');
- }
- lastState=curState;
- if(curState== 1 || curState == 3){
- window.setTimeout(function (){ajaxReq('GET', "/meta/state", stateMachine)}, 2000);
- }
- }
- function loginSuccess(resp){
- loginNotification("Login success");
- document.location.href="wifi.html";
- }
- function loginFail(s,st){
- loginNotification("Login failed");
- stateMachine(st);
- }
- function submitPass(e){
- e.preventDefault();
- ajaxReq('GET', "/meta/auth?passwd="+$("#passwd").value,
- loginSuccess,loginFail);
- }
- function displayMeta(data) {
- Object.keys(data).forEach(function (v) {
- el = $("#" + v);
- if (el != null) {
- console.log("have "+v+" : "+data[v]);
- if (data[v]==1)el.checked=false;
- if (data[v]==2)el.checked=true;
-
- }});
- }
- function fetchMeta() {
- // console.log("fetchMeta !");
- ajaxJson("GET", "/meta/gpio", displayMeta, function () {
- window.setTimeout(fetchMeta, 1000);
- });
- }
- function changeMetaStatus(e) {
- e.preventDefault();
- var v = document.querySelector('input[name="meta-status-topic"]').value;
- ajaxSpin("POST", "/meta?meta-status-topic=" + v, function () {
- showNotification("meta status settings updated");
- }, function (s, st) {
- showWarning("Error: " + st);
- window.setTimeout(fetchMeta, 100);
- });
- }
- function setMeta(b,d){
- ajaxReq("POST","/meta/gpio?num="+b+"&v="+(d?"-1":"-2"),
- function(){fetchMeta();
- }, function () {
- fetchMeta();
- showWarning("Enable/disable failed");
- });
- }
- function ledControl05(e){
- setMeta("05",$('#meta-gpio-05').checked);
- }
- function ledControl12(e){
- setMeta("12",$('#meta-gpio-12').checked);
- }
- function ledControl13(e){
- setMeta("13",$('#meta-gpio-13').checked);
- }
- function sendServer(e){
- e.preventDefault();
- var v = document.querySelector('input[name="send-msg"]').value;
- ajaxSpin("GET", "/meta/sand?msg=" + v, function () {
- showNotification("Your message was sent !");
- }, function (s, st) {
- showWarning("Error: " + st);
- });
- }
-
|