From 7ade39d986497244c60482a9bf18e6f6c241a831 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Tue, 26 May 2015 00:31:12 -0700 Subject: [PATCH] switch layout to purecss --- Makefile | 29 +++--- html/console.tpl | 25 +++-- html/head.tpl | 16 ++++ html/help.tpl | 40 +++++--- html/index.tpl | 27 +++--- html/log.tpl | 25 +++-- html/pure-min.css | 11 +++ html/style.css | 233 +++++++++++++++++++++++++++++++++++++++------ html/ui.js | 35 +++++++ html/wifi/wifi.tpl | 162 ++++++++++++++++--------------- user/cgi.c | 52 ++++++++-- user/cgi.h | 1 + user/cgiwifi.c | 5 +- user/console.c | 6 +- user/log.c | 6 +- 15 files changed, 486 insertions(+), 187 deletions(-) create mode 100644 html/head.tpl create mode 100755 html/pure-min.css create mode 100644 html/ui.js diff --git a/Makefile b/Makefile index 19300983..8c9c4501 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,33 @@ # --------------- esphttpd config options --------------- -# If GZIP_COMPRESSION is set to "yes" then the static css, js, and html files will be compressed with gzip before added to the espfs image -# and will be served with gzip Content-Encoding header. -# This could speed up the downloading of these files, but might break compatibility with older web browsers not supporting gzip encoding -# because Accept-Encoding is simply ignored. Enable this option if you have large static files to serve (for e.g. JQuery, Twitter bootstrap) -# By default only js, css and html files are compressed. -# If you have text based static files with different extensions what you want to serve compressed then you will need to add the extension to the following places: +# If GZIP_COMPRESSION is set to "yes" then the static css, js, and html files will be compressed +# with gzip before added to the espfs image and will be served with gzip Content-Encoding header. +# This could speed up the downloading of these files, but might break compatibility with older +# web browsers not supporting gzip encoding because Accept-Encoding is simply ignored. +# Enable this option if you have large static files to serve (for e.g. JQuery, Twitter bootstrap) +# By default only js, css and html files are compressed using heatshrink. +# If you have text based static files with different extensions what you want to serve compressed +# then you will need to add the extension to the following places: # - Add the extension to this Makefile at the webpages.espfs target to the find command # - Add the extension to the gzippedFileTypes array in the user/httpd.c file # -# Adding JPG or PNG files (and any other compressed formats) is not recommended, because GZIP compression does not works effectively on compressed files. +# Adding JPG or PNG files (and any other compressed formats) is not recommended, because GZIP +# compression does not work effectively on compressed files. #Static gzipping is disabled by default. -GZIP_COMPRESSION ?= no +GZIP_COMPRESSION ?= yes -# If COMPRESS_W_YUI is set to "yes" then the static css and js files will be compressed with yui-compressor -# This option works only when GZIP_COMPRESSION is set to "yes" +# If COMPRESS_W_YUI is set to "yes" then the static css and js files will be compressed with +# yui-compressor. This option works only when GZIP_COMPRESSION is set to "yes". # http://yui.github.io/yuicompressor/ #Disabled by default. COMPRESS_W_YUI ?= no YUI-COMPRESSOR ?= /usr/bin/yui-compressor -#If USE_HEATSHRINK is set to "yes" then the espfs files will be compressed with Heatshrink and decompressed -#on the fly while reading the file. Because the decompression is done in the esp8266, it does not require -#any support in the browser. +# If USE_HEATSHRINK is set to "yes" then the espfs files will be compressed with Heatshrink and +# decompressed on the fly while reading the file. +# Because the decompression is done in the esp8266, it does not require any support in the browser. USE_HEATSHRINK ?= yes # -------------- End of esphttpd config options ------------- diff --git a/html/console.tpl b/html/console.tpl index 57f8aa8b..029f8002 100644 --- a/html/console.tpl +++ b/html/console.tpl @@ -1,14 +1,19 @@ -MCU Console - ESP Link - - - -
-
%topnav%
-

esp link - Microcontroller Console

-

The Microcontroller console shows the last 1024 characters received from UART0, to which -a microcontroller is tpically attached.

-
+%head%
+
+  
+
+

esp link - Microcontroller Console

+
+ +
+

The Microcontroller console shows the last 1024 characters received from UART0, to which + a microcontroller is typically attached.

+
 %console%
 
+
+
+ + diff --git a/html/head.tpl b/html/head.tpl new file mode 100644 index 00000000..e781653a --- /dev/null +++ b/html/head.tpl @@ -0,0 +1,16 @@ + + ESP Link + + + + + +
+ + + diff --git a/html/help.tpl b/html/help.tpl index 6057e7a3..783fd460 100644 --- a/html/help.tpl +++ b/html/help.tpl @@ -1,13 +1,16 @@ - -Help - ESP Link - - - -
-
%topnav%
-

esp link - Help

+%head% -The ESP Link functions in two wifi modes: Station+AccessPoint (STA+AP) and Station (STA). +
+
+

esp link - Help

+
+ +
+ +

This text is somewhat out of date, please refer to +the online README +for the time being.

+

The ESP Link functions in two wifi modes: Station+AccessPoint (STA+AP) and Station (STA). In the STA+AP mode it presents a network called esp8266 that you can connect to using the password jeelabs8266. This mode is intended for initial configuration, but it is fully functional. Typically the easiest way to connect to the esp8266 network is using a phone, @@ -27,23 +30,25 @@ fresh IP the next time it starts up. On many Wifi routers you can enter a fixed the ESP Link's hardware MAC address to a static IP address so it always gets the same IP address. This is the recommended method of operation.

-

Using your ESP Serial Programmer

-The ESP Programmer can used in several distinct ways: +

Using your esp-link

+

+The esp-link can used in several distinct ways:

  • as a transparent bridge between TCP port 23 and the serial port
  • as a web console to see input from the serial port
  • as an Arduino, AVR, or ARM processor programmer using serial-over-TCP
  • as an Arduino, AVR, or ARM processor programmer by uploading HEX files (not yet functional)
+

-

Transparent bridge

+

Transparent bridge

The ESP accepts TCP connections to port 23 and "connects" through to the serial port. Up to 5 simultaneous TCP connections are supported and characters coming in on the serial port get passed through to all connections. Characters coming in on a connection get copied through to the serial port.

When using Linux a simple way to use this is nc esp8266 23

-

Programmer using serial-over-TCP

+

Programmer using serial-over-TCP

By hooking up the ESP's GPIO lines to the reset line of an Arduino (or AVR in general) that is preloaded with the Optiboot bootloader/flasher it is possible to reprogram these processors over Wifi. The way is works is that the ESP toggles the reset line each time a connection is established @@ -55,16 +60,21 @@ Serial Programmer (an IP address could have been used instead).

ARM's reset and ISP lines. The ESP Serial Programmer issues the correct reset/isp pulses to put the ARM chip into firmware programming mode.

-

Web Console

+

Web Console

The output of an attached Arduino/AVR/ARM can also be monitored via the console web page. When connecting, it shows the most recent 10KB of characters received on the serial port and then continues to print everything that comes in on the serial port. Eventually the page refreshes when it gets very long. (Yes, this could be improved with some javascript...)

-

Programmer using HEX upload

+

Programmer using HEX upload

(Not yet functional) Instead of using the wifi-to-serial bridge to program microcontrollers it is often faster to upload the HEX file to the ESP Serial Programmer and have it perform the actual programming protocol.

+ +
+
+ + diff --git a/html/index.tpl b/html/index.tpl index fc7b2c36..3d3c01c2 100644 --- a/html/index.tpl +++ b/html/index.tpl @@ -1,14 +1,17 @@ - -ESP Link - - - -
-
%topnav%
-

esp link

-

-The ESP Link connects the ESP's serial port to Wifi and it can -program microcontrollers over the serial port, in particular Arduinos, AVRs, and -NXP's LPC800-series ARM processors.

+%head% + +
+
+

esp link

+
+ +
+

The ESP Link connects the ESP's serial port to Wifi and it can + program microcontrollers over the serial port, in particular Arduinos, AVRs, and + NXP's LPC800-series ARM processors.

+
+
+ + diff --git a/html/log.tpl b/html/log.tpl index d5db1cf7..92ca4033 100644 --- a/html/log.tpl +++ b/html/log.tpl @@ -1,14 +1,19 @@ -Log - ESP Link - - - -
-
%topnav%
-

esp link - Debug Log

-

The debug log shows the 1024 last characters printed by the esp-link software itself to -its own debug log.

-
+%head%
+
+  
+
+

esp link - Debug Log

+
+ +
+

The debug log shows the 1024 last characters printed by the esp-link software itself to + its own debug log.

+
 %log%
 
+
+
+ + diff --git a/html/pure-min.css b/html/pure-min.css new file mode 100755 index 00000000..f0aa374f --- /dev/null +++ b/html/pure-min.css @@ -0,0 +1,11 @@ +/*! +Pure v0.6.0 +Copyright 2014 Yahoo! Inc. All rights reserved. +Licensed under the BSD License. +https://github.com/yahoo/pure/blob/master/LICENSE.md +*/ +/*! +normalize.css v^3.0 | MIT License | git.io/normalize +Copyright (c) Nicolas Gallagher and Jonathan Neal +*/ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-flex;-webkit-flex-flow:row wrap;display:-ms-flexbox;-ms-flex-flow:row wrap;-ms-align-content:flex-start;-webkit-align-content:flex-start;align-content:flex-start}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class *="pure-u"]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-5-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-2-24,.pure-u-3-24,.pure-u-4-24,.pure-u-5-24,.pure-u-6-24,.pure-u-7-24,.pure-u-8-24,.pure-u-9-24,.pure-u-10-24,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%;*width:4.1357%}.pure-u-1-12,.pure-u-2-24{width:8.3333%;*width:8.3023%}.pure-u-1-8,.pure-u-3-24{width:12.5%;*width:12.469%}.pure-u-1-6,.pure-u-4-24{width:16.6667%;*width:16.6357%}.pure-u-1-5{width:20%;*width:19.969%}.pure-u-5-24{width:20.8333%;*width:20.8023%}.pure-u-1-4,.pure-u-6-24{width:25%;*width:24.969%}.pure-u-7-24{width:29.1667%;*width:29.1357%}.pure-u-1-3,.pure-u-8-24{width:33.3333%;*width:33.3023%}.pure-u-3-8,.pure-u-9-24{width:37.5%;*width:37.469%}.pure-u-2-5{width:40%;*width:39.969%}.pure-u-5-12,.pure-u-10-24{width:41.6667%;*width:41.6357%}.pure-u-11-24{width:45.8333%;*width:45.8023%}.pure-u-1-2,.pure-u-12-24{width:50%;*width:49.969%}.pure-u-13-24{width:54.1667%;*width:54.1357%}.pure-u-7-12,.pure-u-14-24{width:58.3333%;*width:58.3023%}.pure-u-3-5{width:60%;*width:59.969%}.pure-u-5-8,.pure-u-15-24{width:62.5%;*width:62.469%}.pure-u-2-3,.pure-u-16-24{width:66.6667%;*width:66.6357%}.pure-u-17-24{width:70.8333%;*width:70.8023%}.pure-u-3-4,.pure-u-18-24{width:75%;*width:74.969%}.pure-u-19-24{width:79.1667%;*width:79.1357%}.pure-u-4-5{width:80%;*width:79.969%}.pure-u-5-6,.pure-u-20-24{width:83.3333%;*width:83.3023%}.pure-u-7-8,.pure-u-21-24{width:87.5%;*width:87.469%}.pure-u-11-12,.pure-u-22-24{width:91.6667%;*width:91.6357%}.pure-u-23-24{width:95.8333%;*width:95.8023%}.pure-u-1,.pure-u-1-1,.pure-u-5-5,.pure-u-24-24{width:100%}.pure-button{display:inline-block;zoom:1;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:#444;color:rgba(0,0,0,.8);border:1px solid #999;border:0 rgba(0,0,0,0);background-color:#E6E6E6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:hover,.pure-button:focus{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#1a000000', GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:-moz-linear-gradient(top,rgba(0,0,0,.05) 0,rgba(0,0,0,.1));background-image:-o-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000\9}.pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:focus,.pure-button-disabled:active{border:0;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);filter:alpha(opacity=40);-khtml-opacity:.4;-moz-opacity:.4;opacity:.4;cursor:not-allowed;box-shadow:none}.pure-button-hidden{display:none}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=text]:focus,.pure-form input[type=password]:focus,.pure-form input[type=email]:focus,.pure-form input[type=url]:focus,.pure-form input[type=date]:focus,.pure-form input[type=month]:focus,.pure-form input[type=time]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=week]:focus,.pure-form input[type=number]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=color]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129FEA}.pure-form input:not([type]):focus{outline:0;border-color:#129FEA}.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus,.pure-form input[type=checkbox]:focus{outline:thin solid #129FEA;outline:1px auto #129FEA}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=text][disabled],.pure-form input[type=password][disabled],.pure-form input[type=email][disabled],.pure-form input[type=url][disabled],.pure-form input[type=date][disabled],.pure-form input[type=month][disabled],.pure-form input[type=time][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=week][disabled],.pure-form input[type=number][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=color][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form textarea:focus:invalid,.pure-form select:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus,.pure-form input[type=checkbox]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=text],.pure-form-stacked input[type=password],.pure-form-stacked input[type=email],.pure-form-stacked input[type=url],.pure-form-stacked input[type=date],.pure-form-stacked input[type=month],.pure-form-stacked input[type=time],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=week],.pure-form-stacked input[type=number],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=color],.pure-form-stacked input[type=file],.pure-form-stacked select,.pure-form-stacked label,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned textarea,.pure-form-aligned select,.pure-form-aligned .pure-help-inline,.pure-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form input.pure-input-rounded,.pure-form .pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form .pure-help-inline,.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=text],.pure-group input[type=password],.pure-group input[type=email],.pure-group input[type=url],.pure-group input[type=date],.pure-group input[type=month],.pure-group input[type=time],.pure-group input[type=datetime],.pure-group input[type=datetime-local],.pure-group input[type=week],.pure-group input[type=number],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=color]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form .pure-help-inline,.pure-form-message-inline,.pure-form-message{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-list,.pure-menu-item{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-link,.pure-menu-heading{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-separator{display:inline-block;*display:inline;zoom:1;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-allow-hover:hover>.pure-menu-children,.pure-menu-active>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;padding:.5em 0}.pure-menu-horizontal.pure-menu-scrollable::-webkit-scrollbar{display:none}.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-link,.pure-menu-disabled,.pure-menu-heading{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:hover,.pure-menu-link:focus{background-color:#eee}.pure-menu-selected .pure-menu-link,.pure-menu-selected .pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table td:first-child,.pure-table th:first-child{border-left-width:0}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0} \ No newline at end of file diff --git a/html/style.css b/html/style.css index 9856261a..35917ac3 100644 --- a/html/style.css +++ b/html/style.css @@ -1,46 +1,74 @@ +/* All fonts */ +html, button, input, select, textarea, .pure-g [class *= "pure-u"] { + font-family: sans-serif; +} body { - background-color: #404040; - font-family: sans-serif; - font-color: #663300; + color: #777; } -#main { - background-color: #FFFFCC; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - border-radius: 10px; - border: 2px solid #000000; - width: 800px; - margin: 0 auto; - padding: 20px +/* make images size-up */ +.xx-pure-img-responsive { + max-width: 100%; + height: auto; } -h1 { - margin-top: 0; - font-size: 36pt; +/* Add transition to containers so they can push in and out */ +#layout, #menu, .menu-link { + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -ms-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; } -h1 .esp { - font-size: 48pt; + +/* This is the parent `
` that contains the menu and the content area */ +#layout { + position: relative; + padding-left: 0; +} +#layout.active #menu { + left: 150px; + width: 150px; } -#topnav { - background-color: #CC9966; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - border: 0px solid #000000; - padding: 10px; - margin-left: auto; - margin-right: auto; - color: #ffff99; +#layout.active .menu-link { + left: 150px; } -#topnav a { - color: #ffff99; - font-weight: bold; - font-stretch: expanded; + +/* The content `
` */ +.content { + margin: 0 auto; + padding: 0 2em; + max-width: 800px; + margin-bottom: 50px; + line-height: 1.6em; } +.header { + margin: 0; + color: #333; + text-align: center; + padding: 2.5em 2em 0; + border-bottom: 1px solid #eee; + background-color: #fc0; +} +.header h1 { + margin: 0.2em 0; + font-size: 3em; + font-weight: 300; +} +.header h1 .esp { + font-size: 1.25em; +} + +.content-subhead { + margin: 50px 0 20px 0; + font-weight: 300; + color: #888; +} + +/* Text console */ pre.console { background-color: #663300; -moz-border-radius: 5px; @@ -62,3 +90,146 @@ pre.console a { height: 32px; display: inline-block; } + +/* The `#menu` `
` is the parent `
` that contains the `.pure-menu` that + * appears on the left side of the page */ +#menu { + margin-left: -150px; /* "#menu" width */ + width: 150px; + position: fixed; + top: 0; + left: 0; + bottom: 0; + z-index: 1000; /* so the menu or its navicon stays above all content */ + background: #191818; + overflow-y: auto; + -webkit-overflow-scrolling: touch; +} + +/* All anchors inside the menu should be styled like this */ +#menu a { + color: #999; + border: none; + padding: 0.6em 0 0.6em 0.6em; +} + +/* Remove all background/borders, since we are applying them to #menu */ +#menu .pure-menu, #menu .pure-menu ul { + border: none; + background: transparent; +} + +/* Add that light border to separate items into groups */ +#menu .pure-menu ul, #menu .pure-menu .menu-item-divided { + border-top: 1px solid #333; +} + +/* Change color of the anchor links on hover/focus */ +#menu .pure-menu li a:hover, #menu .pure-menu li a:focus { + background: #333; +} + +/* This styles the selected menu item `
  • ` */ +#menu .pure-menu-selected, #menu .pure-menu-heading { + background: #c60; +} + +/* This styles a link within a selected menu item `
  • ` */ +#menu .pure-menu-selected a { + color: #fff; +} + +/* This styles the menu heading */ +#menu .pure-menu-heading { + font-size: 110%; + color: #fff; + margin: 0; +} + +#menu .pure-menu-item { + height:2em; +} + +/* -- Dynamic Button For Responsive Menu -------------------------------------*/ + +/* `.menu-link` represents the responsive menu toggle that shows/hides on small screens */ +.menu-link { + position: fixed; + display: block; /* show this only on small screens */ + top: 0; + left: 0; /* "#menu width" */ + background: #000; + background: rgba(0,0,0,0.7); + font-size: 10px; /* change this value to increase/decrease button size */ + z-index: 10; + width: 2em; + height: auto; + padding: 2.1em 1.6em; +} + +.menu-link:hover, .menu-link:focus { + background: #000; +} + +.menu-link span { + position: relative; + display: block; +} + +.menu-link span, .menu-link span:before, .menu-link span:after { + background-color: #fff; + width: 100%; + height: 0.2em; +} + +.menu-link span:before, .menu-link span:after { + position: absolute; + margin-top: -0.6em; + content: " "; +} + +.menu-link span:after { + margin-top: 0.6em; +} + +/* -- Responsive Styles (Media Queries) ------------------------------------- */ + +/* Hides the menu at `48em`, but modify this based on your app's needs */ +@media (min-width: 48em) { + .header, .content { + padding-left: 2em; + padding-right: 2em; + } + + #layout { + padding-left: 150px; /* left col width "#menu" */ + left: 0; + } + #menu { + left: 150px; + } + + .menu-link { + position: fixed; + left: 150px; + display: none; + } + + #layout.active .menu-link { + left: 150px; + } +} + +@media (max-width: 48em) { + /* Only apply this when the window is small. Otherwise, the following + case results in extra padding on the left: + * Make the window small. + * Tap the menu to trigger the active state. + * Make the window large again. + */ + #layout.active { + position: relative; + left: 150px; + } +} + diff --git a/html/ui.js b/html/ui.js new file mode 100644 index 00000000..acc38a0f --- /dev/null +++ b/html/ui.js @@ -0,0 +1,35 @@ +(function (window, document) { + + var layout = document.getElementById('layout'), + menu = document.getElementById('menu'), + menuLink = document.getElementById('menuLink'); + + function toggleClass(element, className) { + var classes = element.className.split(/\s+/), + length = classes.length, + i = 0; + + for(; i < length; i++) { + if (classes[i] === className) { + classes.splice(i, 1); + break; + } + } + // The className is not found + if (length === classes.length) { + classes.push(className); + } + + element.className = classes.join(' '); + } + + menuLink.onclick = function (e) { + var active = 'active'; + + e.preventDefault(); + toggleClass(layout, active); + toggleClass(menu, active); + toggleClass(menuLink, active); + }; + +}(this, this.document)); diff --git a/html/wifi/wifi.tpl b/html/wifi/wifi.tpl index a2303716..03fcb8b9 100644 --- a/html/wifi/wifi.tpl +++ b/html/wifi/wifi.tpl @@ -1,97 +1,103 @@ -WiFi connection - ESP Link - - +%head% + +
    +
    +

    esp link - Wifi Configuration

    +
    + +
    +

    Current Wifi State

    +

    + WiFi mode: %WiFiMode%
    + Configured network: %currSsid% Status: %currStatus% Phy:%currPhy% +

    +

    %WiFiapwarn%

    + +

    Change Wifi association

    +
    +

    To connect to a WiFi network, please select one of the detected networks, + enter the password, and hit the connect button...

    +

    Scanning...
    +

    WiFi password, if applicable:
    + + +

    +
    + +
    +
    +
  • + + + - - -
    -
    %topnav%
    -

    esp link - Wifi Configuration

    -

    -Current WiFi mode: %WiFiMode%
    -Current network: %currSsid% Status: %currStatus% Phy:%currPhy% -

    -

    -Note: %WiFiapwarn% -

    -
    -

    -To connect to a WiFi network, please select one of the detected networks...
    -

    Scanning...
    -
    -WiFi password, if applicable:
    -
    - -

    -
    - - + diff --git a/user/cgi.c b/user/cgi.c index 57b4f542..630cd7bb 100644 --- a/user/cgi.c +++ b/user/cgi.c @@ -15,6 +15,7 @@ flash as a binary. Also handles the hit counter on the main page. #include #include "cgi.h" +#include "espfs.h" //cause I can't be bothered to write an ioGetLed() @@ -44,7 +45,7 @@ int ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) { //Template code for the led page. int ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) { - char buff[128]; + char buff[512]; if (token==NULL) return HTTPD_CGI_DONE; os_strcpy(buff, "Unknown"); @@ -65,13 +66,14 @@ static long hitCounter=0; //Template code for the counter on the index page. int ICACHE_FLASH_ATTR tplCounter(HttpdConnData *connData, char *token, void **arg) { - char buff[256]; + char buff[64]; if (token==NULL) return HTTPD_CGI_DONE; if (printSysInfo(buff, token) > 0) { // awesome... - } else if (os_strcmp(token, "topnav")==0) { - printNav(buff); + } else if (os_strcmp(token, "head")==0) { + printHead(connData); + buff[0] = 0; } else if (os_strcmp(token, "counter")==0) { hitCounter++; os_sprintf(buff, "%ld", hitCounter); @@ -82,7 +84,7 @@ int ICACHE_FLASH_ATTR tplCounter(HttpdConnData *connData, char *token, void **ar static char *navLinks[][2] = { { "Home", "/index.tpl" }, { "Wifi", "/wifi/wifi.tpl" }, { "\xC2\xB5""C Console", "/console.tpl" }, - { "Esp log", "/log.tpl" }, { "Help", "/help.tpl" }, + { "Debug log", "/log.tpl" }, { "Help", "/help.tpl" }, { 0, 0 }, }; @@ -90,14 +92,48 @@ static char *navLinks[][2] = { int ICACHE_FLASH_ATTR printNav(char *buff) { int len = 0; for (uint8_t i=0; navLinks[i][0] != NULL; i++) { - if (i > 0) buff[len++] = '|'; //os_printf("nav %d: %s -> %s\n", i, navLinks[i][0], navLinks[i][1]); - len += os_sprintf(buff+len, " %s ", navLinks[i][1], navLinks[i][0]); + len += os_sprintf(buff+len, + "
  • %s
  • ", + navLinks[i][1], navLinks[i][0]); } - //os_printf("nav: %s\n", buff); + //os_printf("nav(%d): %s\n", len, buff); return len; } +void ICACHE_FLASH_ATTR printHead(HttpdConnData *connData) { + char buff[1024]; + + struct EspFsFile *file = espFsOpen("/head.tpl"); + if (file == NULL) { + espFsClose(file); + os_printf("Header file 'head.tpl' not found\n"); + return; + } + + int len = espFsRead(file, buff, 1024); + if (len == 1024) { + os_printf("Header file 'head.tpl' too large!\n"); + buff[1023] = 0; + } else { + buff[len] = 0; // ensure null termination + } + + if (len > 0) { + char *p = os_strstr(buff, "%topnav%"); + if (p != NULL) { + char navBuf[512]; + int n = p - buff; + httpdSend(connData, buff, n); + printNav(navBuf); + httpdSend(connData, navBuf, -1); + httpdSend(connData, buff+n+8, len-n-8); + } else { + httpdSend(connData, buff, len); + } + } +} + #define TOKEN(x) (os_strcmp(token, x) == 0) // Handle system information variables and print their value, returns the number of diff --git a/user/cgi.h b/user/cgi.h index 371e5255..2e1638c3 100644 --- a/user/cgi.h +++ b/user/cgi.h @@ -7,6 +7,7 @@ int cgiLed(HttpdConnData *connData); int tplLed(HttpdConnData *connData, char *token, void **arg); int tplCounter(HttpdConnData *connData, char *token, void **arg); int printNav(char *buff); +void ICACHE_FLASH_ATTR printHead(HttpdConnData *connData); int ICACHE_FLASH_ATTR printSysInfo(char *buff, char *token); #endif diff --git a/user/cgiwifi.c b/user/cgiwifi.c index feb677d9..eab2a91c 100644 --- a/user/cgiwifi.c +++ b/user/cgiwifi.c @@ -406,8 +406,9 @@ int ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) os_strcpy(buff, "Click here to go to STA mode."); break; } - } else if (os_strcmp(token, "topnav")==0) { - printNav(buff); + } else if (os_strcmp(token, "head")==0) { + printHead(connData); + buff[0] = 0; } httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; diff --git a/user/console.c b/user/console.c index 0e32c089..c04ccc5f 100644 --- a/user/console.c +++ b/user/console.c @@ -39,7 +39,6 @@ console_write_char(char c) { int ICACHE_FLASH_ATTR tplConsole(HttpdConnData *connData, char *token, void **arg) { if (token==NULL) return HTTPD_CGI_DONE; - char buff[256]; if (os_strcmp(token, "console") == 0) { if (console_wr > console_rd) { @@ -48,9 +47,8 @@ tplConsole(HttpdConnData *connData, char *token, void **arg) { httpdSend(connData, console_buf+console_rd, BUF_MAX-console_rd); httpdSend(connData, console_buf, console_wr); } - } else if (os_strcmp(token, "topnav")==0) { - printNav(buff); - httpdSend(connData, buff, -1); + } else if (os_strcmp(token, "head")==0) { + printHead(connData); } else { httpdSend(connData, "Unknown\n", -1); } diff --git a/user/log.c b/user/log.c index e638789d..d1fd59b2 100644 --- a/user/log.c +++ b/user/log.c @@ -67,7 +67,6 @@ log_write_char(char c) { int ICACHE_FLASH_ATTR tplLog(HttpdConnData *connData, char *token, void **arg) { if (token==NULL) return HTTPD_CGI_DONE; - char buff[256]; if (os_strcmp(token, "log") == 0) { if (log_wr > log_rd) { @@ -76,9 +75,8 @@ tplLog(HttpdConnData *connData, char *token, void **arg) { httpdSend(connData, log_buf+log_rd, BUF_MAX-log_rd); httpdSend(connData, log_buf, log_wr); } - } else if (os_strcmp(token, "topnav")==0) { - printNav(buff); - httpdSend(connData, buff, -1); + } else if (os_strcmp(token, "head")==0) { + printHead(connData); } else { httpdSend(connData, "Unknown\n", -1); }