Improve click-to-edit fields

pull/69/head
Thorsten von Eicken 9 years ago
parent 6b3fb4e90b
commit e429c0bb1c
  1. 2
      Makefile
  2. 6
      esp-link/cgioptiboot.c
  3. 2
      esp-link/config.h
  4. 2
      esp-link/main.c
  5. 22
      html/home.html
  6. 30
      html/style.css
  7. 78
      html/ui.js

@ -370,7 +370,7 @@ ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(WIFI_PATH)*.html $(WIFI_PATH)*.html
$(Q) echo "Compression assets with yui-compressor. This may take a while..." $(Q) echo "Compression assets with yui-compressor. This may take a while..."
$(Q) for file in `find html_compressed -type f -name "*.js"`; do \ $(Q) for file in `find html_compressed -type f -name "*.js"`; do \
java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \ java -jar tools/$(YUI_COMPRESSOR) $$file --line-break 0 -o $$file; \
done done
$(Q) for file in `find html_compressed -type f -name "*.css"`; do \ $(Q) for file in `find html_compressed -type f -name "*.css"`; do \
java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \ java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \

@ -84,6 +84,8 @@ static void ICACHE_FLASH_ATTR optibootInit() {
DBG("OB init\n"); DBG("OB init\n");
} }
// append one string to another but visually escape non-printing characters in the second
// string using \x00 hex notation, max is the max chars in the concatenated string.
void ICACHE_FLASH_ATTR appendPretty(char *buf, char *raw, int max) { void ICACHE_FLASH_ATTR appendPretty(char *buf, char *raw, int max) {
int off = strlen(buf); int off = strlen(buf);
int i = 0; int i = 0;
@ -100,8 +102,8 @@ void ICACHE_FLASH_ATTR appendPretty(char *buf, char *raw, int max) {
} else { } else {
buf[off++] = '\\'; buf[off++] = '\\';
buf[off++] = 'x'; buf[off++] = 'x';
buf[off++] = '0'+(c>>4)+((c>>4)>9?7:0); buf[off++] = '0'+(unsigned char)((c>>4)+((c>>4)>9?7:0));
buf[off++] = '0'+(c&0xff)+((c&0xff)>9?7:0); buf[off++] = '0'+(unsigned char)((c&0xff)+((c&0xff)>9?7:0));
} }
} }
buf[off] = 0; buf[off] = 0;

@ -23,7 +23,7 @@ typedef struct {
uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer
char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32]; char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32];
char mqtt_status_topic[32]; char mqtt_status_topic[32];
char sys_name[12], sys_descr[128]; // informal system name and description char sys_name[13], sys_descr[129]; // informal system name and description
} FlashConfig; } FlashConfig;
extern FlashConfig flashConfig; extern FlashConfig flashConfig;

@ -171,7 +171,7 @@ void user_init(void) {
os_delay_us(10000L); os_delay_us(10000L);
os_printf("\n\n** %s\n", esp_link_version); os_printf("\n\n** %s\n", esp_link_version);
os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*"); os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*");
if (flashConfig.sys_name[0] == 0) os_strcpy(flashConfig.sys_name, "nameme"); if (flashConfig.sys_name[0] == 0) os_strcpy(flashConfig.sys_name, "name-me");
#if defined(STA_SSID) && defined(STA_PASS) #if defined(STA_SSID) && defined(STA_PASS)
int x = wifi_get_opmode() & 0x3; int x = wifi_get_opmode() & 0x3;

@ -42,15 +42,20 @@
<h1>Esp-link summary</h1> <h1>Esp-link summary</h1>
<div id="system-spinner" class="spinner spinner-small"></div> <div id="system-spinner" class="spinner spinner-small"></div>
<table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody> <table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>Name</td><td><input type=text maxlength=12 disabled id="system-name"></td></tr> <tr><td>Flash chip ID</td><td class="system-id"></td></tr>
<tr><td>Flash chip ID</td><td id="system-id"></td></tr> <tr><td>Flash size</td><td class="system-size"></td></tr>
<tr><td>Flash size</td><td id="system-size"></td></tr> <tr><td>Current partition</td><td class="system-partition"></td></tr>
<tr><td>Current partition</td><td id="system-partition"></td></tr> <tr><td>SLIP status</td><td class="system-slip"></td></tr>
<tr><td>SLIP status</td><td id="system-slip"></td></tr> <tr><td>MQTT status</td><td class="system-mqtt"></td></tr>
<tr><td>MQTT status</td><td id="system-mqtt"></td></tr> <tr><td>Serial baud</td><td class="system-baud"></td></tr>
<tr><td>Serial baud</td><td id="system-baud"></td></tr>
<tr><td colspan=2 >Description:<br> <tr><td colspan=2 >Description:<br>
<textarea rows=3 maxlength=127 disabled id="system-description"></textarea></td></tr> <div class="click-to-edit system-description">
<span class="edit-off"></span>
<textarea class="edit-on" rows=3 maxlength=127 hidden></textarea>
<div class="edit-on popup" hidden>A short description or memo for this esp-link
module, 128 chars max</div>
</div>
</td></tr>
</tbody></table> </tbody></table>
</div> </div>
</div> </div>
@ -70,7 +75,6 @@
<script type="text/javascript"> <script type="text/javascript">
onLoad(function() { onLoad(function() {
makeAjaxInput("system", "name");
makeAjaxInput("system", "description"); makeAjaxInput("system", "description");
fetchPins(); fetchPins();
getWifiInfo(); getWifiInfo();

@ -7,10 +7,6 @@ input[type="text"], input[type="password"], textarea {
width: 100%; width: 100%;
} }
input[type="text"]:disabled, textarea:disabled {
cursor: pointer;
}
input[type=checkbox] { input[type=checkbox] {
float: left; float: left;
margin: .35em 0.4em; margin: .35em 0.4em;
@ -36,6 +32,30 @@ a:hover {
border: 0px solid #000000; border: 0px solid #000000;
} }
/* click-to-edit fields */
.click-to-edit {
position: relative;
}
.edit-off {
cursor: pointer;
}
.click-to-edit input, .click-to-edit textarea {
color: black;
background-color: #eee;
width: 100%;
}
div.edit-on.popup {
position: absolute;
top: 100%;
left: 20px;
background-color: cornsilk;
color: #333;
font-size: 80%;
line-height: 110%;
z-index: 100;
padding: 3px;
}
/* wifi AP selection form */ /* wifi AP selection form */
#aps label div { #aps label div {
display: inline-block; display: inline-block;
@ -188,7 +208,7 @@ pre.console a {
bottom: 0; bottom: 0;
z-index: 1000; z-index: 1000;
background: #191818; background: #191818;
overflow-y: auto; overflow: visible;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }

@ -110,6 +110,9 @@ var j = function(
catch(e){} // ignore when it fails. 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 // createElement short-hand
e = function(a) { return document.createElement(a); } e = function(a) { return document.createElement(a); }
@ -226,7 +229,11 @@ onLoad(function() {
<div class="pure-menu">\ <div class="pure-menu">\
<a class="pure-menu-heading" href="https://github.com/jeelabs/esp-link">\ <a class="pure-menu-heading" href="https://github.com/jeelabs/esp-link">\
<img src="/favicon.ico" height="32">&nbsp;esp-link</a>\ <img src="/favicon.ico" height="32">&nbsp;esp-link</a>\
<div class="pure-menu-heading" id="sysname" style="padding: 0px 0.6em"></div>\ <div class="pure-menu-heading click-to-edit system-name" style="padding: 0px 0.6em">\
<span class="edit-off"></span>\
<input class="edit-on" maxlength=12 hidden>\
<div class="edit-on popup" hidden>Short name for this esp-link, 12 chars max</div>\
</div>\
<ul id="menu-list" class="pure-menu-list"></ul>\ <ul id="menu-list" class="pure-menu-list"></ul>\
</div>\ </div>\
</div>\ </div>\
@ -257,11 +264,11 @@ onLoad(function() {
} }
$("#menu-list").innerHTML = html; $("#menu-list").innerHTML = html;
v = $("#version"); var v = $("#version");
if (v != null) { v.innerHTML = data.version; } if (v != null) { v.innerHTML = data.version; }
n = $("#sysname"); setEditToClick("system-name", data.name);
if (n != null) { n.innerHTML = data.name; } makeAjaxInput("system", "name");
}, function() { setTimeout(getMenu, 1000); }); }, function() { setTimeout(getMenu, 1000); });
}; };
getMenu(); getMenu();
@ -291,13 +298,22 @@ function getWifiInfo() {
//===== System info //===== System info
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;
}
});
}
function showSystemInfo(data) { function showSystemInfo(data) {
Object.keys(data).forEach(function(v) { Object.keys(data).forEach(function(v) {
el = $("#system-" + v); setEditToClick("system-" + v, data[v]);
if (el != null) {
if (el.nodeName === "INPUT") el.value = data[v];
else el.innerHTML = data[v];
}
}); });
$("#system-spinner").setAttribute("hidden", ""); $("#system-spinner").setAttribute("hidden", "");
$("#system-table").removeAttribute("hidden"); $("#system-table").removeAttribute("hidden");
@ -309,27 +325,37 @@ function getSystemInfo() {
function(s, st) { window.setTimeout(getSystemInfo, 1000); }); function(s, st) { window.setTimeout(getSystemInfo, 1000); });
} }
function enableInput(el) { function makeAjaxInput(klass, field) {
el.disabled = false; domForEach($("."+klass+"-"+field), function(div) {
el.select(); var eon = $(".edit-on", div);
var eoff = $(".edit-off", div)[0];
var url = "/"+klass+"/update?"+field;
var enableEditToClick = function() {
eoff.setAttribute('hidden','');
domForEach(eon, function(el){ el.removeAttribute('hidden'); });
eon[0].select();
return false; return false;
} }
function submitInput(klass, id, v) {
console.log("Submit POST /"+klass+"/update?"+id+"="+v); var submitEditToClick = function(v) {
$("#"+klass+"-"+id).disabled = true; console.log("Submit POST "+url+"="+v);
ajaxSpin("POST", "/"+klass+"/update?"+id+"="+v, function() { ajaxSpin("POST", url+"="+v, function() {
showNotification(id + " changed to " + v); domForEach(eon, function(el){ el.setAttribute('hidden',''); });
eoff.removeAttribute('hidden');
setEditToClick(klass+"-"+field, v)
showNotification(field + " changed to " + v);
}, function() { }, function() {
showWarning(id + " change failed"); showWarning(field + " change failed");
}); });
return false; return false;
} }
function makeAjaxInput(klass, field) {
var el = $("#"+klass+"-"+field); bnd(eoff, "click", function(){return enableEditToClick();});
bnd(el.parentElement, "click", function(){return enableInput(el);}); bnd(eon[0], "blur", function(){return submitEditToClick(eon[0].value);});
bnd(el, "blur", function(){return submitInput(klass,field,el.value);}); bnd(eon[0], "keyup", function(ev){
bnd(el, "keyup", function(ev){ if ((ev||window.event).keyCode==13) return submitEditToClick(eon[0].value);
if ((ev||window.event).keyCode==13) return submitInput(klass,field,el.value); });
}); });
} }

Loading…
Cancel
Save