/* document binding for browser using duktape and libdom * * Copyright 2015 Vincent Sanders * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * Released under the terms of the MIT License, * http://www.opensource.org/licenses/mit-license */ class Element { prologue %{ #include #define LIST_PROXY_MAGIC MAGIC(LIST_PROXY) %}; }; init Element(struct dom_element *element::node); getter Element::firstElementChild() %{ dom_node *element; dom_exception exc; dom_node_type node_type; dom_node *next_node; exc = dom_node_get_first_child(((node_private_t*)priv)->node, &element); if (exc != DOM_NO_ERR) { return 0; } while (element != NULL) { exc = dom_node_get_node_type(element, &node_type); if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { /* found it */ break; } exc = dom_node_get_next_sibling(element, &next_node); dom_node_unref(element); if (exc == DOM_NO_ERR) { element = next_node; } else { element = NULL; } } if (dukky_push_node(ctx, (dom_node *)element) == false) { dom_node_unref(element); return 0; } dom_node_unref(element); return 1; %} getter Element::lastElementChild() %{ dom_node *element; dom_exception exc; dom_node_type node_type; dom_node *next_node; exc = dom_node_get_last_child(((node_private_t*)priv)->node, &element); if (exc != DOM_NO_ERR) { return 0; } while (element != NULL) { exc = dom_node_get_node_type(element, &node_type); if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { /* found it */ break; } exc = dom_node_get_previous_sibling(element, &next_node); dom_node_unref(element); if (exc == DOM_NO_ERR) { element = next_node; } else { element = NULL; } } if (dukky_push_node(ctx, (dom_node *)element) == false) { dom_node_unref(element); return 0; } dom_node_unref(element); return 1; %} getter Element::previousElementSibling() %{ dom_node *element; dom_exception exc; dom_node_type node_type; dom_node *sib_node; exc = dom_node_get_previous_sibling(((node_private_t *)priv)->node, &element); if (exc != DOM_NO_ERR) { return 0; } while (element != NULL) { exc = dom_node_get_node_type(element, &node_type); if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { /* found it */ break; } exc = dom_node_get_previous_sibling(element, &sib_node); dom_node_unref(element); if (exc == DOM_NO_ERR) { element = sib_node; } else { element = NULL; } } if (dukky_push_node(ctx, (dom_node *)element) == false) { dom_node_unref(element); return 0; } dom_node_unref(element); return 1; %} getter Element::nextElementSibling() %{ dom_node *element; dom_exception exc; dom_node_type node_type; dom_node *sib_node; exc = dom_node_get_next_sibling(((node_private_t *)priv)->node, &element); if (exc != DOM_NO_ERR) { return 0; } while (element != NULL) { exc = dom_node_get_node_type(element, &node_type); if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { /* found it */ break; } exc = dom_node_get_next_sibling(element, &sib_node); dom_node_unref(element); if (exc == DOM_NO_ERR) { element = sib_node; } else { element = NULL; } } if (dukky_push_node(ctx, (dom_node *)element) == false) { dom_node_unref(element); return 0; } dom_node_unref(element); return 1; %} getter Element::childElementCount() %{ dom_node *element; dom_exception exc; dom_node_type node_type; dom_node *next_node; duk_uint_t jsret = 0; exc = dom_node_get_first_child(((node_private_t *)priv)->node, &element); if (exc != DOM_NO_ERR) { return 0; } while (element != NULL) { exc = dom_node_get_node_type(element, &node_type); if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { jsret += 1; } exc = dom_node_get_next_sibling(element, &next_node); dom_node_unref(element); if (exc == DOM_NO_ERR) { element = next_node; } else { element = NULL; } } NSLOG(netsurf, INFO, "I found %u of them", jsret); duk_push_uint(ctx, jsret); return 1; %} method Element::getElementsByTagName () %{ dom_nodelist *nlist = NULL; dom_exception exc; dom_string *tagname; duk_size_t len; const char *str = duk_to_lstring(ctx, 0, &len); exc = dom_string_create((const uint8_t *)str, len, &tagname); if (exc != DOM_NO_ERR) return 0; exc = dom_element_get_elements_by_tag_name(priv->parent.node, tagname, &nlist); dom_string_unref(tagname); if (exc != DOM_NO_ERR) return 0; duk_get_global_string(ctx, LIST_PROXY_MAGIC); duk_push_pointer(ctx, nlist); dukky_create_object(ctx, PROTO_NAME(NODELIST), 1); dom_nodelist_unref(nlist); if (dukky_pcall(ctx, 1, false) != 0) { NSLOG(dukky, DEBUG, "Unable to construct nodelist?"); return 0; /* coerced to undefined */ } return 1; %} getter Element::id () %{ dom_string *idstr = NULL; dom_exception exc; exc = dom_element_get_attribute(priv->parent.node, corestring_dom_id, &idstr); if (exc != DOM_NO_ERR) return 0; if (idstr == NULL) { duk_push_lstring(ctx, "", 0); } else { duk_push_lstring(ctx, dom_string_data(idstr), dom_string_length(idstr)); dom_string_unref(idstr); } return 1; %} setter Element::id () %{ dom_string *idstr = NULL; dom_exception exc; duk_size_t slen; const char *s = duk_safe_to_lstring(ctx, 0, &slen); exc = dom_string_create((const uint8_t *)s, slen, &idstr); if (exc != DOM_NO_ERR) return 0; exc = dom_element_set_attribute(priv->parent.node, corestring_dom_id, idstr); dom_string_unref(idstr); if (exc != DOM_NO_ERR) return 0; return 0; %} method Element::removeAttribute() %{ dom_string *attr = NULL; dom_exception exc; duk_size_t slen; const char *s = duk_safe_to_lstring(ctx, 0, &slen); exc = dom_string_create((const uint8_t *)s, slen, &attr); if (exc != DOM_NO_ERR) return 0; exc = dom_element_remove_attribute(priv->parent.node, attr); dom_string_unref(attr); if (exc != DOM_NO_ERR) return 0; return 0; %} method Element::getAttribute() %{ dom_string *attr_name = NULL; dom_string *attr_value = NULL; dom_exception exc; duk_size_t slen; const char *s = duk_safe_to_lstring(ctx, 0, &slen); exc = dom_string_create((const uint8_t *)s, slen, &attr_name); duk_pop(ctx); exc = dom_element_get_attribute(priv->parent.node, attr_name, &attr_value); dom_string_unref(attr_name); if (exc != DOM_NO_ERR) { return 0; } if (attr_value == NULL) { duk_push_null(ctx); } else { duk_push_lstring(ctx, dom_string_data(attr_value), dom_string_length(attr_value)); dom_string_unref(attr_value); } return 1; %} method Element::setAttribute() %{ dom_exception exc; dom_string *attr_str, *value_str; duk_size_t attr_len, value_len; const char *attr = duk_safe_to_lstring(ctx, 0, &attr_len); const char *value = duk_safe_to_lstring(ctx, 1, &value_len); exc = dom_string_create((const uint8_t *)attr, attr_len, &attr_str); if (exc != DOM_NO_ERR) return 0; exc = dom_string_create((const uint8_t *)value, value_len, &value_str); if (exc != DOM_NO_ERR) { dom_string_unref(attr_str); return 0; } exc = dom_element_set_attribute(priv->parent.node, attr_str, value_str); dom_string_unref(attr_str); dom_string_unref(value_str); if (exc != DOM_NO_ERR) return 0; return 0; %} method Element::hasAttribute() %{ dom_string *attr_name = NULL; dom_exception exc; duk_size_t slen; bool res; const char *s = duk_safe_to_lstring(ctx, 0, &slen); exc = dom_string_create((const uint8_t *)s, slen, &attr_name); duk_pop(ctx); exc = dom_element_has_attribute(priv->parent.node, attr_name, &res); dom_string_unref(attr_name); if (exc != DOM_NO_ERR) { return 0; } duk_push_boolean(ctx, res); return 1; %} getter Element::className () %{ dom_string *classstr = NULL; dom_exception exc; exc = dom_element_get_attribute(priv->parent.node, corestring_dom_class, &classstr); if (exc != DOM_NO_ERR) return 0; if (classstr == NULL) { duk_push_lstring(ctx, "", 0); } else { duk_push_lstring(ctx, dom_string_data(classstr), dom_string_length(classstr)); dom_string_unref(classstr); } return 1; %} setter Element::className () %{ dom_string *classstr = NULL; dom_exception exc; duk_size_t slen; const char *s = duk_safe_to_lstring(ctx, 0, &slen); exc = dom_string_create((const uint8_t *)s, slen, &classstr); if (exc != DOM_NO_ERR) return 0; exc = dom_element_set_attribute(priv->parent.node, corestring_dom_class, classstr); dom_string_unref(classstr); if (exc != DOM_NO_ERR) return 0; return 0; %}