diff --git a/README.md b/README.md index dffefc9..8108829 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker, * [Slider](#slider) * [Number Input](#number-input) * [Text Input](#text-input) + * [File Display](#filedisplay) * [Date, Time, Colour and Password Input](#date-time-colour-and-password-input) * [Select control](#select-control) * [Getting the Time](#getting-the-time) @@ -63,8 +64,9 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker, - Vertical controls by @iangray001 - Time/date/password/color input types by @pcbbc - Delayed response support @MartinMueller2003 -- Fragmented control transfer @ MartinMueller2003 +- Fragmented control transfer @MartinMueller2003 - Extended Callback @MartinMueller2003 +- Added a file display element @MartinMueller2003 ## Roadmap @@ -146,6 +148,7 @@ more program memory to work with. - Separator - Time - Graph (partial implementation) +- File Display ## Documentation @@ -354,6 +357,19 @@ However even with a type set, user input should still be validated because it is easy to bypass client-side checks. Never trust user input. +#### File Display + +![filedisplay](docs/ui_fileDisplay.png) + +The File Display control is used to upload a file from the ESP file system and display the contents on the UI. The content is Auto Scrolled +to the last line in the file. Syntax: + +`fileDisplayId = ESPUI.fileDisplay("Filetest", ControlColor::Turquoise, FullyQualified FilePath);` + +After updating the contents of the file, trigger a display update using: +`ESPUI.updateControl(fileDisplayId);` + + #### Select control ![option1](docs/ui_select1.png) diff --git a/data/js/controls.js b/data/js/controls.js index 84b001b..908dd1a 100644 --- a/data/js/controls.js +++ b/data/js/controls.js @@ -60,7 +60,10 @@ const UPDATE_SEPARATOR = 119; const UI_TIME = 20; const UPDATE_TIME = 120; -const UI_FRAGMENT = 21; +const UI_FILEDISPLAY = 21; +const UPDATE_FILEDISPLAY = 121; + +const UI_FRAGMENT = 98; const UP = 0; const DOWN = 1; @@ -80,7 +83,7 @@ const C_DARK = 7; const C_NONE = 255; var controlAssemblyArray = new Object(); -var FragmentAssemblyTimer = new Object(); +var FragmentAssemblyTimer = new Array(); var graphData = new Array(); var hasAccel = false; var sliderContinuous = false; @@ -197,8 +200,8 @@ function conStatusError() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); if (true === websockConnected) { websockConnected = false; @@ -222,7 +225,7 @@ function handleVisibilityChange() { function start() { let location = window.location.hostname; let port = window.location.port; -// let location = "192.168.10.229"; +// let location = "192.168.10.219"; // let port = ""; document.addEventListener("visibilitychange", handleVisibilityChange, false); @@ -257,8 +260,8 @@ function start() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); }; websock.onclose = function (evt) { @@ -270,8 +273,8 @@ function start() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); }; websock.onerror = function (evt) { @@ -283,8 +286,8 @@ function start() { FragmentAssemblyTimer.forEach(element => { clearInterval(element); }); - FragmentAssemblyTimer = new Object(); - controlAssemblyArray = new Object(); + FragmentAssemblyTimer = new Array(); + controlAssemblyArray = new Array(); }; var handleEvent = function (evt) { @@ -367,7 +370,7 @@ function start() { if (data.visible) addToHTML(data); break; - /* + /* These elements must call additional functions after being added to the DOM */ case UI_BUTTON: @@ -565,6 +568,14 @@ function start() { } break; + case UI_FILEDISPLAY: + if (data.visible) + { + addToHTML(data); + FileDisplayUploadFile(data); + } + break; + /* * Update messages change the value/style of a component without adding new HTML */ @@ -639,6 +650,10 @@ function start() { websock.send("time:" + rv + ":" + data.id); break; + case UPDATE_FILEDISPLAY: + FileDisplayUploadFile(data); + break; + case UI_FRAGMENT: let FragmentLen = data.length; let FragementOffset = data.offset; @@ -770,6 +785,40 @@ function start() { websock.onmessage = handleEvent; } +async function FileDisplayUploadFile(data) +{ + let text = await downloadFile(data.value); + let ItemToUpdateId = "fd" + data.id; + // console.info("ItemToUpdateId: " + ItemToUpdateId); + // console.info(" text: " + text); + // populate the text object + $("#" + ItemToUpdateId).val(text); + $("#" + ItemToUpdateId).css("textAlign", "left"); + $("#" + ItemToUpdateId).css("white-space", "nowrap"); + $("#" + ItemToUpdateId).css("overflow", "scroll"); + $("#" + ItemToUpdateId).css("overflow-y", "scroll"); + $("#" + ItemToUpdateId).css("overflow-x", "scroll"); + $("#" + ItemToUpdateId).scrollTop($("#" + ItemToUpdateId).val().length); + + // scroll the page to the updated control + // $("#" + ItemToUpdateId).focus(); + +} // FileDisplayUploadFile + +async function downloadFile(filename) +{ + let response = await fetch(filename); + + if(response.status != 200) { + throw new Error("File Read Server Error: '" + response.status + "'"); + } + + // read response stream as text + let text_data = await response.text(); + + return text_data; +} // downloadFile + function StartFragmentAssemblyTimer(Id) { StopFragmentAssemblyTimer(Id); @@ -930,11 +979,13 @@ var addToHTML = function (data) { case UI_GRAPH: case UI_GAUGE: case UI_ACCEL: + case UI_FILEDISPLAY: html = "
" + data.label + "

" + elementHTML(data) + "
"; break; + case UI_SEPARATOR: html = "
" + "
" + data.label + "

"; @@ -961,6 +1012,9 @@ var elementHTML = function (data) { case UI_LABEL: return "" + data.value + ""; + case UI_FILEDISPLAY: + return ""; case UI_BUTTON: return "";case UI_SWITCHER:return"