From c227fb7cc9e30d6a4330cdad34b0b2a53b014d93 Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Mon, 9 May 2022 18:02:30 -0700 Subject: web: add support for child DOM elements and text nodes --- web/static/dartboat.js | 40 +++++++++++++++++++++++++++---------- web/web_dom.c | 54 ++++++++++++++++++++++++++++++++++++++++---------- web/web_dom.h | 6 +++++- web/web_prompt.c | 11 +++++++++- 4 files changed, 88 insertions(+), 23 deletions(-) (limited to 'web') 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 +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 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; } -- cgit v1.2.3-70-g09d2