diff --git a/README.md b/README.md index 8108829..263b83e 100644 --- a/README.md +++ b/README.md @@ -667,6 +667,25 @@ All the example sketches include the DNS related code and will work as captive p ESPUI.captivePortal = false; ``` +### User-defined JavaScript + +You can add your own custom JavaScript to the UI. This allows you to create custom controls, handle events, or otherwise extend the functionality of the UI. + +To add custom JavaScript, call `ESPUI.setCustomJS()` before `ESPUI.begin()`. The argument to `setCustomJS()` is a C-string containing the JavaScript code. This string must remain valid for the lifetime of the ESPUIClass instance. + +```cpp +const char* myCustomJS = "alert('Hello from custom JS!');"; + +void setup() { + // ... + ESPUI.setCustomJS(myCustomJS); + ESPUI.begin("ESPUI Control"); + // ... +} +``` + +The custom JavaScript is served at `/js/custom.js` and is automatically included in the `index.htm` file. + # Notes for Development diff --git a/data/index.htm b/data/index.htm index dbb5e84..e072e3e 100644 --- a/data/index.htm +++ b/data/index.htm @@ -16,6 +16,7 @@ + diff --git a/data/index.min.htm b/data/index.min.htm index c4fb287..0967c55 100644 --- a/data/index.min.htm +++ b/data/index.min.htm @@ -1 +1 @@ -Control

Control
Offline


\ No newline at end of file + Control

Control
Offline


diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index 68b1fef..8f06276 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -17,6 +17,18 @@ #include #endif +// Optional user-defined JavaScript to be included in the UI. +// Served at /js/custom.js, which is automatically included in index.htm. +// js: JavaScript code as a C-string. Must remain valid for the lifetime of the ESPUIClass instance. +static const char* customJS = nullptr; + +// Set custom JavaScript to be included in the UI. +// js: JavaScript code as a C-string. Must remain valid for the lifetime of the ESPUIClass instance. +void ESPUIClass::setCustomJS(const char* js) +{ + customJS = js; +} + static String heapInfo(const __FlashStringHelper* mode) { String result; @@ -1272,6 +1284,15 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas yield(); }); + server->on("/js/custom.js", HTTP_GET, [](AsyncWebServerRequest* request) { + if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) + { + return request->requestAuthentication(); + } + + request->send(200, "application/javascript", customJS ? customJS : ""); + }); + server->begin(); #if defined(DEBUG_ESPUI) diff --git a/src/ESPUI.h b/src/ESPUI.h index 0e7bcc4..970daa1 100644 --- a/src/ESPUI.h +++ b/src/ESPUI.h @@ -201,6 +201,11 @@ public: void updateVisibility(uint16_t id, bool visibility, int clientId = -1); + // Set optional user-defined JavaScript to be included in the UI. + // js: JavaScript code as a C-string. Must remain valid for the lifetime of the ESPUIClass instance. + // This is intentionally not a String to avoid dynamic memory allocation. + void setCustomJS(const char* js); + // Variables const char* ui_title = "ESPUI"; // Store UI Title and Header Name Control* controls = nullptr; diff --git a/src/dataIndexHTML.h b/src/dataIndexHTML.h index 8686f3a..df4c8f6 100644 --- a/src/dataIndexHTML.h +++ b/src/dataIndexHTML.h @@ -1,5 +1,5 @@ const char HTML_INDEX[] PROGMEM = R"=====( -Control

Control
Offline


+ Control

Control
Offline


)====="; -const uint8_t HTML_INDEX_GZIP[896] PROGMEM = { 31,139,8,0,198,61,36,105,2,255,125,84,109,115,162,58,20,254,43,92,63,221,59,187,45,34,214,182,187,226,76,80,208,170,168,128,224,203,183,0,169,4,195,75,73,16,245,215,223,4,219,217,233,116,167,204,36,57,121,206,115,158,115,56,132,244,255,137,242,144,93,10,36,197,44,37,131,126,138,24,148,194,24,150,20,49,173,98,175,119,79,131,62,195,140,160,193,48,207,88,153,147,190,124,219,190,51,57,136,50,166,181,106,28,177,88,139,208,9,135,232,174,217,252,196,25,102,24,146,59,26,66,130,52,165,37,101,48,69,218,9,163,186,200,75,54,232,19,156,29,165,18,17,173,69,99,14,132,21,147,48,215,107,73,113,137,94,181,8,50,248,11,167,240,128,228,34,59,252,14,32,69,189,238,79,236,235,75,167,110,207,198,135,28,240,103,225,122,177,225,29,184,165,139,45,176,135,192,18,107,62,183,159,215,194,208,199,145,190,246,12,0,230,227,213,80,62,199,186,205,193,161,158,184,230,116,193,189,189,41,143,61,188,112,112,37,244,134,160,199,231,72,68,46,11,161,218,75,249,100,170,195,176,34,198,147,208,91,153,186,229,27,94,195,85,252,141,211,81,222,236,14,193,142,106,190,137,225,170,126,229,168,62,183,111,235,178,163,164,110,71,169,220,198,199,7,183,167,157,241,204,230,113,156,207,57,166,200,171,203,234,184,122,20,250,70,230,184,107,98,1,61,7,234,113,165,215,215,39,252,48,187,226,252,124,232,46,252,208,83,43,99,58,105,222,116,51,157,59,109,27,96,224,69,110,3,144,218,53,201,85,244,68,169,1,24,69,161,110,99,28,160,198,23,181,93,79,49,245,31,134,105,196,161,97,253,152,20,187,90,52,66,223,185,158,163,251,122,178,142,119,242,116,68,193,97,104,184,172,75,138,173,124,122,78,230,246,126,218,123,51,159,153,122,140,193,37,81,206,91,111,22,216,93,221,207,235,81,253,182,220,29,140,243,241,184,233,226,93,143,172,160,217,238,57,111,214,211,238,133,45,43,39,176,224,181,119,78,2,90,209,17,216,200,81,89,16,253,208,125,76,86,189,231,94,184,53,158,130,21,80,144,55,66,179,142,168,110,186,117,204,205,196,57,238,182,14,89,166,139,203,126,99,182,247,54,184,88,35,67,157,175,129,50,95,27,93,127,244,114,93,38,160,189,76,188,243,236,10,46,220,174,207,198,195,51,170,197,167,240,219,142,31,183,247,99,30,183,46,88,208,113,138,125,118,4,86,2,206,139,75,187,94,184,237,243,210,180,47,214,53,175,23,163,92,177,92,90,91,73,94,91,115,111,125,14,67,81,194,62,50,252,93,100,46,78,251,204,81,119,219,41,1,147,72,141,46,15,69,144,178,235,174,99,214,123,247,225,20,166,40,120,76,106,216,180,212,32,230,250,232,86,118,58,28,190,159,228,230,212,202,33,165,114,150,151,41,36,248,138,238,249,174,57,225,148,93,8,162,49,66,236,11,185,113,253,149,72,195,18,23,76,162,101,168,201,9,149,175,168,96,249,125,138,179,251,132,14,250,242,205,251,133,69,9,142,80,249,45,229,80,194,34,254,150,17,222,126,117,250,45,137,193,32,64,209,251,5,240,153,25,228,209,69,202,51,146,195,72,75,224,9,222,240,95,148,193,146,253,251,223,239,65,63,194,167,65,63,238,54,134,132,35,45,133,56,155,32,200,43,255,115,205,8,142,212,167,5,204,164,144,64,74,53,2,3,68,4,155,231,116,25,100,21,29,44,95,95,121,59,17,207,204,105,188,0,33,41,223,196,203,155,248,45,84,84,201,83,160,79,96,171,204,107,169,186,123,173,8,185,221,88,45,33,206,193,15,141,138,124,48,51,120,194,7,200,112,158,73,127,204,59,222,1,250,85,64,160,156,196,69,42,242,41,157,112,188,183,235,239,81,239,206,143,244,205,252,63,223,19,75,188,160,5,0,0 }; +const uint8_t HTML_INDEX_GZIP[923] PROGMEM = { 31,139,8,0,111,41,29,105,2,255,133,148,109,115,162,58,20,199,191,10,215,87,247,206,110,139,138,181,237,174,58,19,20,108,85,84,64,240,225,93,128,20,130,225,161,36,136,250,233,55,1,59,221,59,123,167,215,25,146,147,156,223,249,159,228,8,103,240,215,100,53,222,236,215,154,20,177,132,140,6,245,40,13,34,4,131,209,32,65,12,74,126,4,11,138,216,176,100,111,119,79,163,1,195,140,160,209,56,75,89,145,145,129,220,44,27,50,133,9,26,158,48,170,242,172,96,146,207,17,148,178,97,171,194,1,139,134,1,58,97,31,221,213,139,239,18,78,49,195,144,220,81,31,18,52,236,180,70,3,130,211,163,84,32,50,108,209,136,135,251,37,147,48,151,104,73,81,129,222,134,1,100,240,7,78,96,136,228,60,13,127,122,144,162,126,239,59,118,213,149,85,181,231,211,48,3,252,183,180,157,72,115,66,110,169,98,9,204,49,48,196,156,45,204,231,141,48,212,105,160,110,28,13,128,197,116,61,150,207,145,106,242,205,177,26,219,250,108,201,189,253,25,143,13,95,249,230,90,232,141,65,159,143,129,136,92,229,66,181,159,240,65,87,198,126,73,180,39,161,183,214,85,195,213,156,154,237,184,91,171,219,121,55,187,4,91,138,254,46,30,91,113,75,75,113,185,221,204,171,110,39,177,187,157,210,174,125,252,225,246,172,59,157,155,60,142,243,156,209,69,94,85,86,166,229,163,208,215,82,203,222,16,3,168,25,80,142,107,181,186,62,225,135,249,21,103,231,176,183,116,125,71,41,181,217,75,125,211,237,108,97,181,77,128,129,19,216,245,6,169,108,157,92,69,77,58,21,0,147,192,87,77,140,61,84,251,130,182,237,116,116,245,155,166,107,145,175,25,223,94,242,125,37,10,161,238,109,199,82,93,53,222,68,123,121,54,161,32,28,107,54,235,145,124,39,159,158,227,133,121,152,245,223,245,103,166,28,35,112,137,59,231,157,51,247,204,158,234,102,213,164,122,95,237,67,237,124,60,110,123,120,223,39,107,168,183,251,214,187,241,180,127,101,171,210,242,12,120,237,159,99,143,150,116,2,182,114,80,228,68,13,123,143,241,186,255,220,247,119,218,147,183,6,29,228,76,208,188,43,78,55,219,89,250,246,197,58,238,119,22,89,37,203,203,97,171,183,15,38,184,24,19,77,89,108,64,103,177,209,122,238,228,245,186,138,65,123,21,59,231,249,21,92,184,93,157,181,135,103,84,137,191,194,109,91,110,212,62,76,121,220,38,103,94,215,202,15,233,17,24,49,56,47,47,237,106,105,183,207,43,221,188,24,215,172,90,78,178,142,97,211,202,136,179,202,88,56,155,179,239,139,35,28,2,205,221,7,250,242,116,72,45,101,191,155,17,240,18,40,193,229,33,247,18,118,221,119,245,234,96,63,156,252,4,121,143,113,5,235,146,106,68,223,28,237,210,76,198,227,223,222,100,202,46,4,209,8,33,214,188,196,178,79,169,156,102,69,2,9,190,162,123,190,250,63,184,222,108,64,234,23,56,103,18,45,252,161,28,83,249,138,114,150,221,39,56,189,143,185,83,110,188,127,80,148,224,0,21,95,34,97,1,243,232,75,194,111,190,117,250,37,196,160,231,161,224,246,205,127,45,87,82,150,37,255,70,228,186,223,72,3,47,11,46,82,150,146,12,6,195,24,158,96,227,255,65,25,44,216,223,255,252,228,68,128,79,162,61,245,26,83,194,193,48,129,56,125,225,225,168,248,236,74,13,69,115,152,10,130,159,202,102,144,149,84,242,9,164,116,72,160,135,200,104,245,246,198,139,143,248,33,56,198,105,185,22,189,133,70,197,45,65,19,33,238,197,211,160,226,51,109,145,85,55,103,75,152,229,221,91,73,72,211,222,120,55,187,201,148,68,160,188,54,52,133,31,90,45,110,226,16,50,156,165,210,167,121,39,160,63,84,74,242,153,80,0,183,250,126,40,253,190,245,223,7,248,152,68,97,235,59,214,237,253,23,75,224,118,101,245,5,0,0 };