Under the work of v0.9.7 documentation

pull/41/head
Hieromon Ikasamo 5 years ago
parent a7f3c3ba10
commit d42c36ca33
  1. 2
      mkdocs.yml
  2. 63
      mkdocs/achandling.md
  3. 105
      mkdocs/datatips.md
  4. BIN
      mkdocs/images/aux_fsbrowser.gif
  5. BIN
      mkdocs/images/aux_pattern.gif
  6. 2
      mkdocs/js/gifffer.min.js
  7. 2
      mkdocs/menuize.md

@ -27,7 +27,7 @@ nav:
- 'Something extra': apiextra.md
- 'Examples' :
- 'How to embed': howtoembed.md
- 'Tips for data retrieval': datatips.md
- 'Tips for data conversion': datatips.md
- 'Constucting menu': menuize.md
- 'FAQ' : faq.md
- 'Change log' : changelog.md

@ -496,10 +496,67 @@ The [AutoConnectAux::loadElement](apiaux.md#loadelement) function overwrites its
### <i class="fa fa-check-square"></i> Check data against on submission
By giving a [pattern](apielements.md#pattern) to [AutoConnectInput](apielements.md#autoconenctinput), you can find errors in data styles while typing in custom Web pages. The pattern is specified by [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).[^2] If the value during input of AutoConnectInput does not match the regular expression specified in the pattern, its background color changes to pink. The following example shows the behavior when checking the IP address in the AutoConnectInput field.
[^2]: The pattern of AutoConnectInput conforms to javascript specification.
<span style="display:block;margin-left:auto;margin-right:auto;width:306px;height:136px;border:1px solid lightgrey;"><img data-gifffer="./images/aux_pattern.gif" data-gifffer-height="134" data-gifffer-width="304" /></span>
```json hl_lines="10"
{
"title" : "Page-1",
"uri" : "/page1",
"menu" : true,
"element" : [
{
"name" : "Server",
"type" : "ACInput",
"label": "Server address",
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
}
]
}
```
### <i class="fa fa-exchange"></i> Convert data to actually type
## Transitions of the custom Web pages
### Scope &amp; Lifetime of AutoConnectAux
The lifetime of AutoConnectAux and AutoConnectElements must remain in the period when the custom Web page can be manipulated. The implementation of the custom Web page inherits from requestHandler driven from ESP8266WebServer (WebServer for ESP32), so the instance of AutoConnectAux and AutoConnectElements must exist for the duration of effect of handleClient. The following example is incorrect for manipulating custom Web pages. Its AutoConnectAux instance will be destructed at the exit of the setup().
```cpp hl_lines="20"
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <AutoConnect.h>
static const auxPage[] PROGMEM = R"raw(
{
"title": "Page-1",
"uri": "/page1",
"menu": true,
"element": [
{ "name":"Server", "type":"ACText", "label":"Server address" }
]
}
)raw";
AutoConnect portal;
void setup() {
// This declaration is wrong.
AutoConnectAux aux;
aux.load(auxPage);
portal.join(aux);
portal.begin();
}
void loop() {
portal.handleClient();
}
```
### The URI of the custom Web pages
The transition of the custom Web page follows the URI of the page, but the ESP8266WebServer class does not know the URI of an AutoConnectAux page. (Registering a custom Web page does not use the *ESP8266WebServer::on*/*WebServer::on* function.) Therefore ESP8266WebServer class does not detect its URI access. If you want to detect an http request to AutoConnectAux's custom Web page, you need to register its URI with the [AutoConnectAux::on](apiaux.md#on) function.
@ -528,3 +585,9 @@ The custom Web pages handler has the following restrictions.
!!! hint "302 Redirect Alternatives"
To transition from a custom Web page to a sketch owned page, execute the link function of JavaScript with the AutoConnectElement element.
<script>
window.onload = function() {
Gifffer();
};
</script>

@ -0,0 +1,105 @@
## Convert AutoConnectElements value to actual data type
The value of the AutoConnectElements field of the custom Web pages consists of String type for all. Sketches will need to convert them to the actual data type. And then if the data type required for processing in the sketch is not a String type, it is necessary to convert to String type when storing to the AutoConenctElements value.
AutoConnect library does not provide the data conversion utility, and its function depends on Arduino language functions or functions of the type class. However, commonly used data conversion methods are generally similar.
Here, represent examples the typical method for the data type conversion for the AutoConnectElements value of custom Web pages.
### <i class="fa fa-exchange"></i> Integer
Use [int()](https://www.arduino.cc/reference/en/language/variables/conversion/intcast/) or [toInt() of String](https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/toint/).
```cpp
AutoConnectInput& input = aux.getElement<AutoConnectInput>("INPUT");
int value = input.value.toInt();
```
### <i class="fa fa-exchange"></i> Float
Use [float()](https://www.arduino.cc/reference/en/language/variables/conversion/floatcast/) or [toFloat() of String](https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/tofloat/).
```cpp
AutoConnectInput& input = aux.getElement<AutoConnectInput>("INPUT");
float value = input.value.toFloat();
```
### <i class="fa fa-exchange"></i> Date &amp; Time
The easiest way is to use the [Arduino Time Library](https://www.pjrc.com/teensy/td_libs_Time.html). Sketches must accommodate differences in date and time formats depending on the time zone. You can absorb the difference in DateTime format by using `sscanf` function.[^1]
[^1]:It can not be used with the old Arduino core.
```cpp
#include <TimeLib.h>
time_t tm;
int Year, Month, Day, Hour, Minute, Second;
AutoConnectInput& input = aux.getElement<AutoConnectInput>("INPUT");
sscanf(input.value.c_str(), "%d-%d-%d %d:%d:%d", &Year, &Month, &Day, &Hour, &Minute, &Second);
tm.Year = CalendarYrToTm(Year);
tm.Month = Month;
tm.Day = Day;
tm.Hour = Hour;
tm.Minute = Minute;
tm.Second = Second;
```
### <i class="fa fa-exchange"></i> IP adderss
To convert a String to an IP address, use **IPAddress::fromString**. To stringize an instance of an IP address, use **IPAddress::toString**.
```cpp
IPAddress ip;
AutoConnectInput& input aux.getElement<AutoConnectInput>("INPUT");
ip.fromString(input.value);
input.value = ip.toString();
```
## Validation for the value
In order for data to be correctly converted from a string, the input data must be consistent with the format. How to implement strict validation in sketches depends on various perspectives and the power of tiny devices is not enough to implement a complete lexical analysis. But you can reduce the burden for data verification using the **pattern** of AutoConnectInput.
By giving a [**pattern**](achandling.md#check-data-against-on-submission) to [AutoConnectInput](apielements.md#pattern), you can find errors in data styles while typing in custom Web pages. The pattern is specified by [**regular expression**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions). If the value during input of AutoConnectInput does not match the regular expression specified in the pattern, its background color changes to pink. Refer to [Handling the custom Web pages](achandling.md#check-data-against-on-submission) section.
!!! caution "Regular Expressions for JavaScript"
Regular expressions specified in the AutoConnectInput pattern conforms to the [JavaScript specification](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).
Here, represent examples the typical regular expression for the input validation.
### <i class="fa fa-check-square"></i> URL
```
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
```
### <i class="fa fa-check-square"></i> DNS hostname
```
^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$
```
### <i class="fa fa-check-square"></i> email address [^1]
```
^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$
```
### <i class="fa fa-check-square"></i> IP Address
```
^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
```
### <i class="fa fa-check-square"></i> Date as MM/DD/YYYY [^2]
```
^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$
```
!!! caution "Contain with backquote"
If that regular expression contains a backquote it must be escaped by backquote duplication.
[^1]: This regular expression does not fully support the format of the e-mail address requested in [RFC5322](https://tools.ietf.org/html/rfc5322).
[^2]: This regular expression does not consider semantic constraints. It is not possible to detect errors that do not exist as actual dates.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -1 +1 @@
(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory();else if(typeof define==="function"&&define.amd)define("Gifffer",[],factory);else if(typeof exports==="object")exports["Gifffer"]=factory();else root["Gifffer"]=factory()})(this,function(){var d=document;var playSize=60;var Gifffer=function(options){var images,i=0,gifs=[];images=d.querySelectorAll("[data-gifffer]");for(;i<images.length;++i)process(images[i],gifs,options);return gifs};function formatUnit(v){return v+(v.toString().indexOf("%")>0?"":"px")}function parseStyles(styles){var stylesStr="";for(prop in styles)stylesStr+=prop+":"+styles[prop]+";";return stylesStr}function createContainer(w,h,el,altText,opts){var alt;var con=d.createElement("BUTTON");var cls=el.getAttribute("class");var id=el.getAttribute("id");var playButtonStyles=opts&&opts.playButtonStyles?parseStyles(opts.playButtonStyles):["width:"+playSize+"px","height:"+playSize+"px","border-radius:"+playSize/2+"px","background:rgba(0, 0, 0, 0.3)","position:absolute","top:50%","left:50%","margin:-"+playSize/2+"px"].join(";");var playButtonIconStyles=opts&&opts.playButtonIconStyles?parseStyles(opts.playButtonIconStyles):["width: 0","height: 0","border-top: 14px solid transparent","border-bottom: 14px solid transparent","border-left: 14px solid rgba(0, 0, 0, 0.5)","position: absolute","left: 26px","top: 16px"].join(";");cls?con.setAttribute("class",el.getAttribute("class")):null;id?con.setAttribute("id",el.getAttribute("id")):null;con.setAttribute("style","position:relative;cursor:pointer;background:none;border:none;padding:0;");con.setAttribute("aria-hidden","true");var play=d.createElement("DIV");play.setAttribute("class","gifffer-play-button");play.setAttribute("style",playButtonStyles);var trngl=d.createElement("DIV");trngl.setAttribute("style",playButtonIconStyles);play.appendChild(trngl);if(altText){alt=d.createElement("p");alt.setAttribute("class","gifffer-alt");alt.setAttribute("style","border:0;clip:rect(0 0 0 0);height:1px;overflow:hidden;padding:0;position:absolute;width:1px;");alt.innerText=altText+", image"}con.appendChild(play);el.parentNode.replaceChild(con,el);altText?con.parentNode.insertBefore(alt,con.nextSibling):null;return{c:con,p:play}}function calculatePercentageDim(el,w,h,wOrig,hOrig){var parentDimW=el.parentNode.offsetWidth;var parentDimH=el.parentNode.offsetHeight;var ratio=wOrig/hOrig;if(w.toString().indexOf("%")>0){w=parseInt(w.toString().replace("%",""));w=w/100*parentDimW;h=w/ratio}else if(h.toString().indexOf("%")>0){h=parseInt(h.toString().replace("%",""));h=h/100*parentDimW;w=h*ratio}return{w:w,h:h}}function process(el,gifs,options){var url,con,c,w,h,duration,play,gif,playing=false,cc,isC,durationTimeout,dims,altText;url=el.getAttribute("data-gifffer");w=el.getAttribute("data-gifffer-width");h=el.getAttribute("data-gifffer-height");duration=el.getAttribute("data-gifffer-duration");altText=el.getAttribute("data-gifffer-alt");el.style.display="block";c=document.createElement("canvas");isC=!!(c.getContext&&c.getContext("2d"));if(w&&h&&isC)cc=createContainer(w,h,el,altText,options);el.onload=function(){if(!isC)return;w=w||el.width;h=h||el.height;if(!cc)cc=createContainer(w,h,el,altText,options);con=cc.c;play=cc.p;dims=calculatePercentageDim(con,w,h,el.width,el.height);gifs.push(con);con.addEventListener("click",function(){clearTimeout(durationTimeout);if(!playing){playing=true;gif=document.createElement("IMG");gif.setAttribute("style","width:100%;height:100%;");gif.setAttribute("data-uri",Math.floor(Math.random()*1e5)+1);setTimeout(function(){gif.src=url},0);con.removeChild(play);con.removeChild(c);con.appendChild(gif);if(parseInt(duration)>0){durationTimeout=setTimeout(function(){playing=false;con.appendChild(play);con.removeChild(gif);con.appendChild(c);gif=null},duration)}}else{playing=false;con.appendChild(play);con.removeChild(gif);con.appendChild(c);gif=null}});c.width=dims.w;c.height=dims.h;c.getContext("2d").drawImage(el,0,0,dims.w,dims.h);con.appendChild(c);con.setAttribute("style","position:relative;cursor:pointer;width:"+dims.w+"px;height:"+dims.h+"px;background:none;border:none;padding:0;");c.style.width="100%";c.style.height="100%";if(w.toString().indexOf("%")>0&&h.toString().indexOf("%")>0){con.style.width=w;con.style.height=h}else if(w.toString().indexOf("%")>0){con.style.width=w;con.style.height="inherit"}else if(h.toString().indexOf("%")>0){con.style.width="inherit";con.style.height=h}else{con.style.width=dims.w+"px";con.style.height=dims.h+"px"}};el.src=url}return Gifffer});
(function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory();else if(typeof define==="function"&&define.amd)define("Gifffer",[],factory);else if(typeof exports==="object")exports["Gifffer"]=factory();else root["Gifffer"]=factory()})(this,function(){if(typeof window==="undefined"||typeof document==="undefined"){return}var d=document;var playSize=60;var Gifffer=function(options){var images,i=0,gifs=[];images=d.querySelectorAll("[data-gifffer]");for(;i<images.length;++i)process(images[i],gifs,options);return gifs};function formatUnit(v){return v+(v.toString().indexOf("%")>0?"":"px")}function parseStyles(styles){var stylesStr="";for(prop in styles)stylesStr+=prop+":"+styles[prop]+";";return stylesStr}function createContainer(w,h,el,altText,opts){var alt;var con=d.createElement("BUTTON");var cls=el.getAttribute("class");var id=el.getAttribute("id");var playButtonStyles=opts&&opts.playButtonStyles?parseStyles(opts.playButtonStyles):["width:"+playSize+"px","height:"+playSize+"px","border-radius:"+playSize/2+"px","background:rgba(0, 0, 0, 0.3)","position:absolute","top:50%","left:50%","margin:-"+playSize/2+"px"].join(";");var playButtonIconStyles=opts&&opts.playButtonIconStyles?parseStyles(opts.playButtonIconStyles):["width: 0","height: 0","border-top: 14px solid transparent","border-bottom: 14px solid transparent","border-left: 14px solid rgba(0, 0, 0, 0.5)","position: absolute","left: 26px","top: 16px"].join(";");cls?con.setAttribute("class",el.getAttribute("class")):null;id?con.setAttribute("id",el.getAttribute("id")):null;con.setAttribute("style","position:relative;cursor:pointer;background:none;border:none;padding:0;");con.setAttribute("aria-hidden","true");var play=d.createElement("DIV");play.setAttribute("class","gifffer-play-button");play.setAttribute("style",playButtonStyles);var trngl=d.createElement("DIV");trngl.setAttribute("style",playButtonIconStyles);play.appendChild(trngl);if(altText){alt=d.createElement("p");alt.setAttribute("class","gifffer-alt");alt.setAttribute("style","border:0;clip:rect(0 0 0 0);height:1px;overflow:hidden;padding:0;position:absolute;width:1px;");alt.innerText=altText+", image"}con.appendChild(play);el.parentNode.replaceChild(con,el);altText?con.parentNode.insertBefore(alt,con.nextSibling):null;return{c:con,p:play}}function calculatePercentageDim(el,w,h,wOrig,hOrig){var parentDimW=el.parentNode.offsetWidth;var parentDimH=el.parentNode.offsetHeight;var ratio=wOrig/hOrig;if(w.toString().indexOf("%")>0){w=parseInt(w.toString().replace("%",""));w=w/100*parentDimW;h=w/ratio}else if(h.toString().indexOf("%")>0){h=parseInt(h.toString().replace("%",""));h=h/100*parentDimW;w=h*ratio}return{w:w,h:h}}function process(el,gifs,options){var url,con,c,w,h,duration,play,gif,playing=false,cc,isC,durationTimeout,dims,altText;url=el.getAttribute("data-gifffer");w=el.getAttribute("data-gifffer-width");h=el.getAttribute("data-gifffer-height");duration=el.getAttribute("data-gifffer-duration");altText=el.getAttribute("data-gifffer-alt");el.style.display="block";c=document.createElement("canvas");isC=!!(c.getContext&&c.getContext("2d"));if(w&&h&&isC)cc=createContainer(w,h,el,altText,options);el.onload=function(){if(!isC)return;w=w||el.width;h=h||el.height;if(!cc)cc=createContainer(w,h,el,altText,options);con=cc.c;play=cc.p;dims=calculatePercentageDim(con,w,h,el.width,el.height);gifs.push(con);con.addEventListener("click",function(){clearTimeout(durationTimeout);if(!playing){playing=true;gif=document.createElement("IMG");gif.setAttribute("style","width:100%;height:100%;");gif.setAttribute("data-uri",Math.floor(Math.random()*1e5)+1);setTimeout(function(){gif.src=url},0);con.removeChild(play);con.removeChild(c);con.appendChild(gif);if(parseInt(duration)>0){durationTimeout=setTimeout(function(){playing=false;con.appendChild(play);con.removeChild(gif);con.appendChild(c);gif=null},duration)}}else{playing=false;con.appendChild(play);con.removeChild(gif);con.appendChild(c);gif=null}});c.width=dims.w;c.height=dims.h;c.getContext("2d").drawImage(el,0,0,dims.w,dims.h);con.appendChild(c);con.setAttribute("style","position:relative;cursor:pointer;width:"+dims.w+"px;height:"+dims.h+"px;background:none;border:none;padding:0;");c.style.width="100%";c.style.height="100%";if(w.toString().indexOf("%")>0&&h.toString().indexOf("%")>0){con.style.width=w;con.style.height=h}else if(w.toString().indexOf("%")>0){con.style.width=w;con.style.height="inherit"}else if(h.toString().indexOf("%")>0){con.style.width="inherit";con.style.height=h}else{con.style.width=dims.w+"px";con.style.height=dims.h+"px"}};el.src=url}return Gifffer});

@ -23,7 +23,7 @@ To implement this with your sketch, use only the [AutoConnectAux](apiaux.md#auto
The AutoConnect library package contains an example sketch for ESP8266WebServer known as FSBrowser. Its example is a sample implementation that supports AutoConnect without changing the structure of the original FSBrowser and has the menu item for **Edit** and **List**.
<div style="display:block;margin-left:auto;margin-right:auto;width:284px;height:491px;border:1px solid lightgrey;"><img data-gifffer="./images/aux_fsbrowser.gif" data-gifffer-width="280" data-gifffer-height="490" /></div>
<span style="display:block;margin-left:auto;margin-right:auto;width:282px;height:492px;border:1px solid lightgrey;"><img data-gifffer="./images/aux_fsbrowser.gif" data-gifffer-height="490" data-gifffer-width="280" /></span>
The changes I made to adapt the FSBrowser to the AutoConnect menu are slight as follows.

Loading…
Cancel
Save