summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-09 18:02:30 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2022-05-09 18:09:24 -0700
commitc227fb7cc9e30d6a4330cdad34b0b2a53b014d93 (patch)
tree4d5f6f4bfcb15e67de4bb588334f3b7facf86aa4
parent9ba644fd849ef7664be009e00206bf5eb1b85762 (diff)
downloaddartboat-c227fb7cc9e30d6a4330cdad34b0b2a53b014d93.tar.gz
dartboat-c227fb7cc9e30d6a4330cdad34b0b2a53b014d93.tar.xz
web: add support for child DOM elements and text nodes
-rw-r--r--web/static/dartboat.js40
-rw-r--r--web/web_dom.c54
-rw-r--r--web/web_dom.h6
-rw-r--r--web/web_prompt.c11
4 files changed, 88 insertions, 23 deletions
diff --git a/web/static/dartboat.js b/web/static/dartboat.js
index eb1b8fa..e664a8d 100644
--- a/web/static/dartboat.js
+++ b/web/static/dartboat.js
@@ -55,18 +55,29 @@ function elemScrollToBottom(sel) {
e.scrollTop = e.scrollHeight;
}
-function elemAppendElemv(sel, elemc, elemv, off_ns, off_name, off_content,
- off_n_attrs, off_attr_names, off_attr_vals) {
- const target = $(UTF8ToString(sel));
-
+function targetAppendElemv(target, elemc, elemv,
+ off_type, off_ns, off_name, off_content,
+ off_n_attrs, off_attr_names, off_attr_vals,
+ off_n_children, off_children) {
for (let ptr = elemv; ptr < elemv + 4*elemc; ptr += 4) {
const struct = HEAP32[ptr>>2];
- const nsptr = HEAP32[(struct + off_ns)>>2];
- const name = UTF8ToString(HEAP32[(struct + off_name)>>2]);
- const e = nsptr ?
- document.createElementNS(UTF8ToString(nsptr), name) :
- document.createElement(name);
+ let e;
+ const type = UTF8ToString(HEAP32[(struct + off_type)>>2]);
+ const contentptr = HEAP32[(struct + off_content)>>2];
+ const content = contentptr && UTF8ToString(contentptr);
+ if (type === "text") {
+ e = document.createTextNode(content);
+ } else {
+ const nsptr = HEAP32[(struct + off_ns)>>2];
+ const name = UTF8ToString(
+ HEAP32[(struct + off_name)>>2]);
+ e = nsptr ?
+ document.createElementNS(
+ UTF8ToString(nsptr), name) :
+ document.createElement(name);
+ if (content) e.textContent = content;
+ }
const n_attrs = HEAP32[(struct + off_n_attrs)>>2];
if (n_attrs) {
@@ -81,13 +92,20 @@ function elemAppendElemv(sel, elemc, elemv, off_ns, off_name, off_content,
HEAP32[(attr_vals + i*4)>>2]));
}
- const content = HEAP32[(struct + off_content)>>2];
- if (content) e.textContent = UTF8ToString(content);
+ const n_children = HEAP32[(struct + off_n_children)>>2];
+ if (n_children)
+ targetAppendElemv(e, n_children,
+ HEAP32[(struct + off_children)>>2],
+ ...Array.prototype.slice.call(arguments, 3));
target.appendChild(e);
}
}
+function elemAppendElemv(sel, ...args) {
+ targetAppendElemv($(UTF8ToString(sel)), ...args);
+}
+
function promptHandle(command, data) {
const str_c = toCString(command);
const str_d = data && toCString(data);
diff --git a/web/web_dom.c b/web/web_dom.c
index eadca7f..cff0459 100644
--- a/web/web_dom.c
+++ b/web/web_dom.c
@@ -7,41 +7,60 @@
#include <emscripten/emscripten.h>
+static struct dom_elem *dom_node_init(char *type, int size_attrs)
+{
+ struct dom_elem *e = calloc(1, sizeof(*e));
+ e->type = type; // string literal, not freed
+
+ e->size_attrs = size_attrs;
+ e->attr_names = malloc(size_attrs * sizeof(*(e->attr_names)));
+ e->attr_vals = malloc(size_attrs * sizeof(*(e->attr_vals)));
+
+ return e;
+}
+
struct dom_elem *dom_elem_init(char *ns, char *name, int size_attrs)
{
- struct dom_elem *e = malloc(sizeof(*e));
+ struct dom_elem *e = dom_node_init("element", size_attrs);
e->ns = ns ? strdup(ns) : NULL;
e->name = strdup(name);
- e->content = NULL;
- e->n_attrs = 0;
- e->size_attrs = size_attrs;
- e->attr_names = malloc(size_attrs * sizeof(*(e->attr_names)));
- e->attr_vals = malloc(size_attrs * sizeof(*(e->attr_vals)));
+ return e;
+}
+
+struct dom_elem *dom_text_init(char *content)
+{
+ struct dom_elem *e = dom_node_init("text", 0);
+ e->content = strdup(content);
return e;
}
void dom_elem_free(struct dom_elem *e)
{
- for(int i = 0; i < e->n_attrs; ++i) {
+ for (int i = 0; i < e->n_attrs; ++i) {
free(e->attr_names[i]);
free(e->attr_vals[i]);
}
+ for (int i = 0; i < e->n_children; ++i) {
+ dom_elem_free(e->children[i]);
+ }
+
free(e->ns);
free(e->name);
free(e->content);
free(e->attr_names);
free(e->attr_vals);
+ free(e->children);
free(e);
}
void dom_elem_add_attr(struct dom_elem *e, char *name, char *val)
{
if (e->n_attrs == e->size_attrs) {
- e->size_attrs *= 2;
+ e->size_attrs += e->size_attrs ? e->size_attrs : 1;
e->attr_names = realloc(e->attr_names,
e->size_attrs * sizeof(*(e->attr_names)));
e->attr_vals = realloc(e->attr_vals,
@@ -59,16 +78,31 @@ void dom_elem_add_attrd(struct dom_elem *e, char *name, double val)
dom_elem_add_attr(e, name, str);
}
+void dom_elem_add_child(struct dom_elem *e, struct dom_elem *child)
+{
+ if (e->n_children == e->size_children) {
+ e->size_children += e->size_children ? e->size_children : 1;
+ e->children = realloc(e->children,
+ e->size_children * sizeof(*(e->children)));
+ }
+
+ e->children[e->n_children++] = child;
+}
+
inline void dom_append_elemv(char *sel, int elemc, struct dom_elem **elemv)
{
- EM_ASM({elemAppendElemv($0, $1, $2, $3, $4, $5, $6, $7, $8)},
+ EM_ASM({elemAppendElemv($0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10,
+ $11)},
sel, elemc, elemv,
+ offsetof(struct dom_elem, type),
offsetof(struct dom_elem, ns),
offsetof(struct dom_elem, name),
offsetof(struct dom_elem, content),
offsetof(struct dom_elem, n_attrs),
offsetof(struct dom_elem, attr_names),
- offsetof(struct dom_elem, attr_vals));
+ offsetof(struct dom_elem, attr_vals),
+ offsetof(struct dom_elem, n_children),
+ offsetof(struct dom_elem, children));
}
inline char *dom_get_content(char *sel)
diff --git a/web/web_dom.h b/web/web_dom.h
index 41ac46d..e89b5ba 100644
--- a/web/web_dom.h
+++ b/web/web_dom.h
@@ -4,15 +4,19 @@
#include <stdbool.h>
struct dom_elem {
- char *ns, *name, *content;
+ char *type, *ns, *name, *content;
int n_attrs, size_attrs;
char **attr_names, **attr_vals;
+ int n_children, size_children;
+ struct dom_elem **children;
};
struct dom_elem *dom_elem_init(char *ns, char *name, int size_attrs);
+struct dom_elem *dom_text_init(char *content);
void dom_elem_free(struct dom_elem *e);
void dom_elem_add_attr(struct dom_elem *e, char *name, char *val);
void dom_elem_add_attrd(struct dom_elem *e, char *name, double val);
+void dom_elem_add_child(struct dom_elem *e, struct dom_elem *child);
void dom_append_elemv(char *sel, int elemc, struct dom_elem **elemv);
diff --git a/web/web_prompt.c b/web/web_prompt.c
index 3b5bc68..3f5521a 100644
--- a/web/web_prompt.c
+++ b/web/web_prompt.c
@@ -89,13 +89,22 @@ static void flush_list_opts()
for (int i = 0; i < list_optc; ++i) {
struct dom_elem *e = dom_elem_init(NULL, "div", 2);
- asprintf(&e->content, "[%d] %s", i + 1, list_optv[i]);
dom_elem_add_attr(e, "class", "key");
char buf[64];
sprintf(buf, "append:%d;submit", i + 1);
dom_elem_add_attr(e, "data-command", buf);
+ struct dom_elem *child;
+ child = dom_elem_init(NULL, "span", 1);
+ asprintf(&child->content, "[%d]", i + 1);
+ dom_elem_add_attr(child, "class", "keyboard-val");
+ dom_elem_add_child(e, child);
+
+ sprintf(buf, "\u2002%s", list_optv[i]);
+ child = dom_text_init(buf);
+ dom_elem_add_child(e, child);
+
elemv[i] = e;
}