CSS styles are removed when served by ESP8266 running an ESPAsyncWebServer - html

Tried to position text In an Image exactly like in the example from w3schools.
It works fine in my space at w3schools. When I look at the css in the browser:
.container {
position: relative;
}
.center {
position: absolute;
top: 50%;
width: 100%;
text-align: center;
font-size: 18px;
}
img {
width: 100%;
height: auto;
}
But when the exact same html + css code is running on the esp8266 nodeMCU, the positioning fails. Like Ben T stated, the width style is missing.
.container {
position: relative;
}
.center {
position: absolute;
top: 50;
text-align: center;
font-size: 18px;
}
img {
width: 100%;
height: auto;
}
So something goes wrong in the css-class "center".
This is the Code running on the esp8266.
The html file right now is in the same file.
The css-positioning also fails with the temperature string.
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include "LittleFS.h"
const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";
// hard coded current temperature & humidity
float t = 15.1;
float h = 55.5;
AsyncWebServer server(80);
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<style>
.container {
position: relative;
}
.center {
position: absolute;
top: 50%;
width: 100%;
text-align: center;
font-size: 18px;
}
img {
width: 100%;
height: auto;
}
</style>
</head>
<body>
<h2>Image Text</h2>
<p>Center text in image:</p>
<div class="container">
<img src="camper" alt="Cinque Terre" width="1000" height="300">
<div class="center">Centered</div>
</div>
</body>
</html>)rawliteral";
// Replaces placeholder with DHT values
String processor(const String& var){
//Serial.println(var);
if(var == "TEMPERATURE"){
return String(t);
}
else if(var == "HUMIDITY"){
return String(h);
}
return String();
}
//background-image: url(\"camper\")
void setup(){
Serial.begin(115200);
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
if(!LittleFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
File camper = LittleFS.open("/camper.png", "r");
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
server.on("/camper", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/camper.png", "image/png");
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(t).c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(h).c_str());
});
server.begin();
}
void loop(){
}
Has somebody experienced something like this before?
Thanks in advance for any kind of hints ;)

A template processor is used in:
request->send_P(200, "text/html", index_html, processor);
and from https://github.com/me-no-dev/ESPAsyncWebServer#template-processing
Placeholders are delimited with % symbols. Like this: %TEMPLATE_PLACEHOLDER%.
So all of the % characters in the index_html string literal need to be escaped. e.g.:
top: 50%%;
width: 100%%;
Otherwise the ESPAsyncWebServer template processing will treat the characters between % characters as a placeholder.
i.e. the text %;\n width: 100% is treated as a placeholder. Your processor() function only replaces the TEMPERATURE and HUMIDITY placeholders and any other placeholder is replaced by an empty string.
This means this CSS:
top: 50%;
width: 100%;
is replaced with:
top: 50;
This general problem is described in the issue https://github.com/me-no-dev/ESPAsyncWebServer/issues/644.

Related

Retriggering a switch in HTML and Arduino

I'm trying to set up a wifi switch to turn my computer on wirelessly. I'm using a program that has a web server and password. The issue I am having is I only want the button to be triggered for a 1 second then come off. I want the slider to turn on then off after the delay. I'm struggling with the HTML language to accomplish this.
I've tried adjusting the Arduino code but it has not worked. I believe the HTML code needs to be changed so that there's a delay and re-triggers the off switch.
Here is the code that I am using:
// Import required libraries
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#else
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
// Replace with your network credentials
const char* ssid = "";
const char* password = "";
const char* http_username = "admin";
const char* http_password = "admin";
const char* PARAM_INPUT_1 = "state";
const int output = 26;
int delaytime = 5000;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>Wifi Computer Switch</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 2.6rem;}
body {max-width: 600px; margin:0px auto; padding-bottom: 10px;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
input:checked+.slider {background-color: #2196F3}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
</style>
</head>
<body>
<h2>Wifi Computer Switch</h2>
<button onclick="logoutButton()">Logout</button>
<p>Ouput - GPIO 2 - State <span id="state">%STATE%</span></p>
%BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
if(element.checked){
xhr.open("GET", "/update?state=1", true);
document.getElementById("state").innerHTML = "ON";
}
else {
xhr.open("GET", "/update?state=0", true);
document.getElementById("state").innerHTML = "OFF";
}
xhr.send();
}
function logoutButton() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/logout", true);
xhr.send();
setTimeout(function(){ window.open("/logged-out","_self"); }, 1000);
}
function powerbutton() {
}
</script>
</body>
</html>
)rawliteral";
const char logout_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>Logged out or return to homepage.</p>
<p><strong>Note:</strong> close all web browser tabs to complete the logout process.</p>
</body>
</html>
)rawliteral";
// Replaces placeholder with button section in your web page
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons ="";
String outputStateValue = outputState();
buttons+= "<p><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label></p>";
return buttons;
}
if (var == "STATE"){
if(digitalRead(output)){
return "ON";
}
else {
return "OFF";
}
}
return String();
}
String outputState(){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
return "";
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
pinMode(output, OUTPUT);
digitalWrite(output, LOW);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
request->send_P(200, "text/html", index_html, processor);
});
server.on("/logout", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(401);
});
server.on("/logged-out", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", logout_html, processor);
});
// Send a GET request to <ESP_IP>/update?state=<inputMessage>
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
String inputMessage;
String inputParam;
// GET input1 value on <ESP_IP>/update?state=<inputMessage>
if (request->hasParam(PARAM_INPUT_1)) {
inputMessage = request->getParam(PARAM_INPUT_1)->value();
inputParam = PARAM_INPUT_1;
digitalWrite(output, inputMessage.toInt());
}
else {
inputMessage = "No message sent";
inputParam = "none";
}
Serial.println(inputMessage);
request->send(200, "text/plain", "OK");
});
// Start server
server.begin();
}
void loop() {
}
When I run the program, this is what the web page looks like
Web Page Display
The button slides but I would like it to turn off again after a certain amount of time.
[edit: added web page photo]

Extract link from html in flutter

I am trying to extract a link from an HTML body which is coming from a response . Then message looks like this "content":
{
"rendered":
"<div style=
"padding: 56.25% 0 0 0;
position: relative;">
<iframe style=
"position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;"
title="Shrewsberry"
src="https://player.vimeo.com/video/1000224?h=23334&badge=0&autopause=0&player_id=0&app_id=58479\"
frameborder="0"
allowfullscreen="allowfullscreen">
</iframe>
</div>"}
I want to get the content inside 'src="https://player.vimeo.com/video/1000224?' can anyone help .
This is my code which i use
final value = parse(html); // html is the value from response
String parsedString = parse(value.body!.text).documentElement!.text;
print(parsedString);
You can use this simple logic if your URL always ends with ?
void main(){
String x='"content": { "rendered": "<div style="padding: 56.25% 0 0 0; position: relative;"><iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" title="Shrewsberry" **src="https://player.vimeo.com/video/1000224?**h=23334&badge=0&autopause=0&player_id=0&app_id=58479" frameborder="0" allowfullscreen="allowfullscreen">\n"}';
int start= x.indexOf('src');
int end= x.indexOf('?');
print(x.substring(start,end+1));
}
You can use Regex to extract the string from your original string. Given the fact that it looks like HTML I ignored the ** you put in your answer.
In that case the regex (?<=src=").*?(?=") should work to retrieve the source. This will work for any source, not just Vimeo.
import 'dart:convert';
void main() {
String input = "\"content\": { \"rendered\": \"<div style=\"padding: 56.25% 0 0 0; position: relative;\"><iframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%;\" title=\"Shrewsberry\" **src=\"https://player.vimeo.com/video/1000224?\"h=23334&badge=0&autopause=0&player_id=0&app_id=58479\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\">\n\"}";
RegExp regex = new RegExp('(?<=src=").*?(?=")');
var match = regex.firstMatch(input);
if (match == null) {
print("No match found.");
return;
}
print("Result: " + match.group(0)!);
}
Output: Result: https://player.vimeo.com/video/1000224?

Can not convert html to png using phantomjs or wkhtmltoimage

I want to convert html to png.
Here is my html
<!DOCTYPE html>
<html>
<head>
<style type="text/css">* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
main {
width: 600px;
margin: 100px auto;
}
header {
width: 100%;
height: auto;
background-color: red;
background-size: cover;
background-repeat: no-repeat;
}
header .content {
width: 80%;
margin-left: 10%;
margin-right: 10%;
display: flex;
padding: 40px 0;
}
.content .column {
width: 25%;
margin: auto;
text-align: center;
}
.content .column.lfp-logo {
width: 30%;
}
.content .column img {
width: 80%;
height: auto;
}
</style>
</head>
<body>
<main>
<header>
<div class="content">
<div class="column"><img
src="https://cdn.shopify.com/s/files/1/1237/5652/products/spiderman_3_compression_shirt_3_small.jpg"></div>
<div class="column lfp-logo"><img
src="https://cdn.shopify.com/s/files/1/1237/5652/products/spiderman_3_compression_shirt_3_small.jpg"></div>
<div class="column"><img
src="https://cdn.shopify.com/s/files/1/1237/5652/products/spiderman_3_compression_shirt_3_small.jpg"></div>
</div>
</header>
</main>
</body>
</html>
Here is jsfiddle example. this is actually what i need to get in my png file jsfiddle
I tried to use wkhtmltoimage and I get this image
Also I tried to use phantomjs and get this image
I use phantomjs with nodejs module webshot.
Can anyone suggest me way I can render html to png image.
I dont need dynamic html. All I want to render is static.
UPDATE. Added code for generating images
const pug = require('pug');
const child_process = require('child_process');
const fs = require('fs');
const webshot = require('webshot');
const options = {
data: {
images: {
header: 'https://cdn.shopify.com/s/files/1/1237/5652/products/spiderman_3_compression_shirt_3_small.jpg',
team1: 'https://cdn.shopify.com/s/files/1/1237/5652/products/spiderman_3_compression_shirt_3_small.jpg',
team2: 'https://cdn.shopify.com/s/files/1/1237/5652/products/spiderman_3_compression_shirt_3_small.jpg',
competition: 'https://cdn.shopify.com/s/files/1/1237/5652/products/spiderman_3_compression_shirt_3_small.jpg'
}
}
};
const html = pug.renderFile('./template/next.pug', options);
console.log(html); // this is html
// webshot with wkhtmltoimage
child_process.exec(`echo "${html}" | wkhtmltoimage --width 600 --disable-smart-width - export/out.png`, (err) => {
console.log(err);
});
// webshot with phantomjs
webshot(html, 'hello_world.png', {siteType:'html'}, function(err) {
console.log(err);
});
I would say to make something like this. Working with html2canvas you can do it easy and fast.
convert_to_img = function (do_download) {
html2canvas(document.getElementById("contenedor_chimichangas"), {
//onrender devuelve el canvas para hacerle los retoques necesarios
onrendered: function (canvas) {//sombra aqui, sombra allí!!
var context = canvas.getContext('2d');//context from originalCanvas
var data_image = canvas.toDataURL("image/png"); //cogemos la url de la imagen sin tratar
//añadimos la url en una imagen para poder tratarla y redimensionarla
var image_edicion = $("<img/>", {
id: "image",
src: data_image
}).appendTo($("#show_img").empty());
//if we click download:
if(do_download === true){
Canvas2Image.saveAsPNG(new_canvas);
}
});
},
});
}
The js are documented line at line. ;D

GWT - Make CellTable Cell use HTML?

I have a CellTable where I want to put HTML-code in the cells.
The following code is not working, the blank spaces are removed from the output.
TextColumn<MyCell> column1 = new TextColumn<MyCell>()
{
#Override
public String getValue(MyCell myCell)
{
String result = " " +myCell.getValue();
return result;
}
};
table.addColumn(column1 , "Header1");
I know this could be done using css but I just want to know how to put HTML-code in the cells. Any help is appreciated!
AFAIK additional whitespace is ignored in HTML - you should use pre tag to maintain formatting.Anyway please find my column sample below. It generates nice progress bar from values contained in objects backed by data provider.
final SafeHtmlCell progressCell = new SafeHtmlCell();
Column<UiScheduledTask, SafeHtml> progressCol = new Column<UiScheduledTask, SafeHtml>(
progressCell) {
#Override
public SafeHtml getValue(UiScheduledTask value) {
SafeHtmlBuilder sb = new SafeHtmlBuilder();
float percent = new Float(value.getCompleted())
/ new Float(value.getAll());
int rounded = Math.round(percent * 100);
sb.appendHtmlConstant("<div style='width: 100px; height: 20px; position: relative;'>");
sb.appendHtmlConstant("<div style='z-index: 2; display: inline; width: 100px; position: absolute; left: 0px, top: 0px; text-align: center;'>"
+ value.getCompleted()
+ "/"
+ value.getAll()
+ "</div>");
sb.appendHtmlConstant("<div style='position: absolute; left: 0; top: 0; width: 100px; z-index: 1'><div style='display: inline; float: left; width: "
+ rounded
+ "%; height: 20px; background-color: #82cd80;'></div>");
sb.appendHtmlConstant("<div style='display: inline; float: right; width: "
+ (100 - rounded)
+ "%; height: 20px; background-color: #c54c4d;'></div></div>");
sb.appendHtmlConstant("</div>");
return sb.toSafeHtml();
}
};

HTML/CSS - Using a image for input type=file

How do use this image:
http://h899310.devhost.se/proxy/newProxy/uplfile.png
Instead of the regular:
<input type="file" />
Have a look at Styling an input type="file".
I'm not very sure on whether you want to style file upload fields, or whether you simply want to use a png file in a style.
Quirksmode.org has a section on styling file upload fields though, that you would want to refer to.
If you want to use the PNG file to use in a style inside a page, you should like at how to set backgrounds using images, although this may not work for all HTML elements.
I did something like this and it worked perfectly!
<script type="text/javascript">
var t = 0;
var IE = navigator.appName;
var OP = navigator.userAgent.indexOf('Opera');
var tmp = '';
function operaFix() {
if (OP != -1) {
document.getElementById('browser').style.left = -120 + 'px';
}
}
function startBrowse() {
tmp = document.getElementById('dummy_path').value;
getFile();
}
function getFile() {
// IF Netscape or Opera is used...
//////////////////////////////////////////////////////////////////////////////////////////////
if (OP != -1) {
displayPath();
if (tmp != document.getElementById('dummy_path').value && document.getElementById('dummy_path').value
!= '') {
clearTimeout(0);
return;
}
setTimeout("getFile()", 20);
// If IE is used...
//////////////////////////////////////////////////////////////////////////////////////////////
} else if (IE == "Microsoft Internet Explorer") {
if (t == 3) {
displayPath();
clearTimeout(0);
t = 0;
return;
}
t++;
setTimeout("getFile()", 20);
// Or if some other, better browser is used... like Firefox for example :)
//////////////////////////////////////////////////////////////////////////////////////////////
} else {
displayPath();
}
}
function displayPath() {
document.getElementById('dummy_path').value = document.getElementById('browser').value;
}
</script>
<style type="text/css">
#browser
{
position: absolute;
left: -132px;
opacity: 0;
filter: alpha(opacity=0);
}
#browser_box
{
width: 104px;
height: 22px;
position: relative;
overflow: hidden;
background: url(button1_off.jpg) no-repeat;
}
#browser_box:active
{
background: url(button1_on.jpg) no-repeat;
}
#dummy_path
{
width: 350px;
font-family: verdana;
font-size: 10px;
font-style: italic;
color: #3a3c48;
border: 1px solid #3a3c48;
padding-left: 2px;
background: #dcdce0;
}
</style>
<body onload="operaFix()">
<div id="browser_box">
<input type="file" name="my_file" id="browser" onclick="startBrowse()" />
</div>
</body>