supla-device
Loading...
Searching...
No Matches
web_sender.h
1// SPDX-FileCopyrightText: AC SOFTWARE SP. Z O.O.
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#ifndef SRC_SUPLA_NETWORK_WEB_SENDER_H_
5#define SRC_SUPLA_NETWORK_WEB_SENDER_H_
6
7#include <stddef.h>
8#include <stdio.h>
9#include <stdint.h>
10#include <supla/network/html_generator.h>
11
12#if defined(ARDUINO_ARCH_ESP8266)
13#include <pgmspace.h>
14#define SUPLA_WEB_PROGMEM PROGMEM
15#define SUPLA_WEB_SNPRINTF(buffer, size, format, ...) \
16 snprintf_P(buffer, size, PSTR(format), ##__VA_ARGS__)
17#else
18#define SUPLA_WEB_PROGMEM
19#define SUPLA_WEB_SNPRINTF(buffer, size, format, ...) \
20 snprintf(buffer, size, format, ##__VA_ARGS__)
21#endif
22
23namespace Supla {
24
25class WebSender;
26
27struct FixedValue {
28 int raw = 0;
29 int precision = 0;
30
31 constexpr FixedValue() = default;
32 // NOLINTNEXTLINE(runtime/explicit)
33 constexpr FixedValue(int value) : raw(value), precision(0) {
34 }
35 constexpr FixedValue(int value, int prec) : raw(value), precision(prec) {
36 }
37};
38
39constexpr FixedValue fixed(int value, int precision) {
40 return FixedValue(value, precision);
41}
42
44 FixedValue min;
45 FixedValue max;
46 FixedValue value;
47 FixedValue step;
48};
49
73class HtmlTag {
74 public:
75 HtmlTag(WebSender* sender, const char* tagName, bool paired = true);
76 ~HtmlTag();
77
78 HtmlTag(const HtmlTag&) = delete;
79 HtmlTag& operator=(const HtmlTag&) = delete;
80
81 HtmlTag(HtmlTag&& other) noexcept;
82 HtmlTag& operator=(HtmlTag&& other) noexcept;
83
87 HtmlTag& attr(const char* name, const char* value);
88
89 // Static attribute value in SUPLA_WEB_PROGMEM, escaped as ordinary attr().
90 HtmlTag& attrStatic(const char* name,
91 const char* value,
92 size_t size = static_cast<size_t>(-1));
93
97 HtmlTag& attr(const char* name, int value);
98
105 HtmlTag& attr(const char* name, int value, int precision);
106
112 HtmlTag& attrIf(const char* name, bool enabled);
113
117 HtmlTag& close();
118
126 HtmlTag& finish();
127
134 template <typename Fn>
135 void body(Fn&& fn) {
136 close();
137 fn();
138 end();
139 }
140
144 void body(char* text);
145
149 template <size_t N>
150 void body(const char (&text)[N]) {
151 body(static_cast<const char*>(text));
152 }
153
157 void body(const char* text);
158
165 void end();
166
167 private:
168 void release();
169
170 WebSender* sender_ = nullptr;
171 const char* tagName_ = nullptr;
172 bool paired_ = true;
173 bool closed_ = false;
174 bool finished_ = false;
175};
176
178 public:
197 virtual ~WebSender();
198 virtual void send(const char*, int size = -1) = 0;
199
207 void sendStatic(const char* data,
208 size_t size = static_cast<size_t>(-1),
209 bool escape = false);
210
211 virtual void sendSafe(const char*, int size = -1);
212 virtual void send(int number);
213 virtual void send(int number, int precision);
214 virtual void sendNameAndId(const char* id);
215 virtual void sendLabelFor(const char* id, const char* label);
216 virtual void sendSelectItem(int value,
217 const char* label,
218 bool selected,
219 bool emptyValue = false);
220 virtual void sendCsrfField();
221 virtual void sendHidden(bool hidden);
222 virtual void sendReadonly(bool readonly);
223 virtual void sendDisabled(bool disabled);
224 virtual void sendTimestamp(uint32_t timestamp);
225
232 template <typename Fn>
233 void formField(Fn&& fn, const char* className = "form-field") {
234 auto field = tag("div");
235 field.attr("class", className);
236 field.body(fn);
237 }
238
245 template <typename Fn>
246 void labeledField(const char* id,
247 const char* text,
248 Fn&& fn,
249 const char* className = "form-field") {
250 formField(
251 [&]() {
252 labelFor(id, text);
253 fn();
254 },
255 className);
256 }
257
264 template <typename Fn>
265 void toggleBox(const char* id,
266 bool visible,
267 Fn&& fn,
268 const char* className = nullptr) {
269 auto box = tag("div");
270 if (id) {
271 box.attr("id", id);
272 }
273 if (className) {
274 box.attr("class", className);
275 }
276 box.attr("style", visible ? "display: block" : "display: none");
277 box.body(fn);
278 }
279
283 template <typename Fn>
284 void selectInput(const char* name, const char* id, Fn&& fn) {
285 selectTag(name, id).body(fn);
286 }
287
294 HtmlTag selectTag(const char* name, const char* id) {
295 auto select = tag("select");
296 if (name) {
297 select.attr("name", name);
298 }
299 if (id) {
300 select.attr("id", id);
301 }
302 return select;
303 }
304
308 void labelFor(const char* id, const char* text);
309
316 void textInput(const char* name,
317 const char* id,
318 const char* value = nullptr,
319 int maxLength = -1,
320 const char* listId = nullptr,
321 const char* onInput = nullptr,
322 const char* onChange = nullptr);
323
327 void passwordInput(const char* name, const char* id);
328
335 void checkboxInput(const char* name,
336 const char* id,
337 bool checked,
338 const char* value = "on");
339
346 void numberInput(const char* key,
347 const NumericInputSpec& spec,
348 const char* cssClass = nullptr);
349
356 void rangeInput(const char* key,
357 const NumericInputSpec& spec,
358 const char* cssClass = nullptr);
359
363 void numberInput(const char* name,
364 const char* id,
365 const NumericInputSpec& spec,
366 const char* cssClass = nullptr);
367
371 void rangeInput(const char* name,
372 const char* id,
373 const NumericInputSpec& spec,
374 const char* cssClass = nullptr);
375
379 void selectOption(int value, int text, bool selected = false);
380 void selectOption(int value, const char* text, bool selected = false);
381 void selectOption(const char* value, int text, bool selected = false);
382 void selectOption(const char* value, const char* text, bool selected = false);
383
390 HtmlTag tag(const char* tagName, bool paired = true) {
391 return HtmlTag(this, tagName, paired);
392 }
393
397 HtmlTag voidTag(const char* tagName) {
398 return HtmlTag(this, tagName, false);
399 }
400};
401}; // namespace Supla
402
403#endif // SRC_SUPLA_NETWORK_WEB_SENDER_H_
RAII helper for emitting a single HTML tag.
Definition web_sender.h:73
void body(const char(&text)[N])
Emit a text body using escaped content.
Definition web_sender.h:150
void body(Fn &&fn)
Emit a paired body using a callback.
Definition web_sender.h:135
HtmlTag & close()
Emit the closing > for the opening tag.
Definition web_sender.cpp:102
HtmlTag & attr(const char *name, const char *value)
Append a quoted HTML attribute with escaped value.
Definition web_sender.cpp:50
void end()
Explicitly finish the tag.
Definition web_sender.cpp:128
HtmlTag & attrIf(const char *name, bool enabled)
Append a boolean HTML attribute when enabled.
Definition web_sender.cpp:94
HtmlTag & finish()
Close the opening tag and mark it as finished.
Definition web_sender.cpp:110
Definition web_sender.h:177
void labeledField(const char *id, const char *text, Fn &&fn, const char *className="form-field")
Emit a labeled field wrapper.
Definition web_sender.h:246
void selectOption(int value, int text, bool selected=false)
Emit a single <option> element.
Definition web_sender.cpp:332
void formField(Fn &&fn, const char *className="form-field")
Emit a <div class="form-field">...</div> block.
Definition web_sender.h:233
HtmlTag voidTag(const char *tagName)
Start a builder for a void HTML tag such as <input>.
Definition web_sender.h:397
HtmlTag selectTag(const char *name, const char *id)
Start a <select> tag builder.
Definition web_sender.h:294
void labelFor(const char *id, const char *text)
Emit a <label for="...">...</label> pair.
Definition web_sender.cpp:184
void sendStatic(const char *data, size_t size=static_cast< size_t >(-1), bool escape=false)
Emit a static HTML asset stored in program memory.
Definition web_sender.cpp:149
void textInput(const char *name, const char *id, const char *value=nullptr, int maxLength=-1, const char *listId=nullptr, const char *onInput=nullptr, const char *onChange=nullptr)
Emit a text input control.
Definition web_sender.cpp:190
void toggleBox(const char *id, bool visible, Fn &&fn, const char *className=nullptr)
Emit a <div> whose visibility is controlled via display.
Definition web_sender.h:265
virtual ~WebSender()
Base interface for emitting generated HTML.
Definition web_sender.cpp:147
HtmlTag tag(const char *tagName, bool paired=true)
Start an HTML tag builder.
Definition web_sender.h:390
void selectInput(const char *name, const char *id, Fn &&fn)
Emit a <select> block with optional name and id.
Definition web_sender.h:284
void checkboxInput(const char *name, const char *id, bool checked, const char *value="on")
Emit a checkbox input control.
Definition web_sender.cpp:235
void numberInput(const char *key, const NumericInputSpec &spec, const char *cssClass=nullptr)
Emit a numeric input control.
Definition web_sender.cpp:252
void rangeInput(const char *key, const NumericInputSpec &spec, const char *cssClass=nullptr)
Emit a range input control.
Definition web_sender.cpp:258
void passwordInput(const char *name, const char *id)
Emit a password input control.
Definition web_sender.cpp:223
Definition web_sender.h:27
Definition web_sender.h:43