Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of libdom.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <stdlib.h>
  10.  
  11. #include <dom/html/html_option_element.h>
  12. #include <dom/html/html_options_collection.h>
  13.  
  14. #include "html/html_document.h"
  15. #include "html/html_select_element.h"
  16.  
  17. #include "core/node.h"
  18. #include "utils/utils.h"
  19.  
  20. static struct dom_element_protected_vtable _protect_vtable = {
  21.         {
  22.                 DOM_NODE_PROTECT_VTABLE_HTML_SELECT_ELEMENT
  23.         },
  24.         DOM_HTML_SELECT_ELEMENT_PROTECT_VTABLE
  25. };
  26.  
  27. static bool is_option(struct dom_node_internal *node, void *ctx);
  28.  
  29. /**
  30.  * Create a dom_html_select_element object
  31.  *
  32.  * \param doc  The document object
  33.  * \param ele  The returned element object
  34.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  35.  */
  36. dom_exception _dom_html_select_element_create(struct dom_html_document *doc,
  37.                 dom_string *namespace, dom_string *prefix,
  38.                 struct dom_html_select_element **ele)
  39. {
  40.         struct dom_node_internal *node;
  41.  
  42.         *ele = malloc(sizeof(dom_html_select_element));
  43.         if (*ele == NULL)
  44.                 return DOM_NO_MEM_ERR;
  45.        
  46.         /* Set up vtables */
  47.         node = (struct dom_node_internal *) *ele;
  48.         node->base.vtable = &_dom_html_element_vtable;
  49.         node->vtable = &_protect_vtable;
  50.  
  51.         return _dom_html_select_element_initialise(doc, namespace, prefix, *ele);
  52. }
  53.  
  54. /**
  55.  * Initialise a dom_html_select_element object
  56.  *
  57.  * \param doc  The document object
  58.  * \param ele  The dom_html_select_element object
  59.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  60.  */
  61. dom_exception _dom_html_select_element_initialise(struct dom_html_document *doc,
  62.                 dom_string *namespace, dom_string *prefix,
  63.                 struct dom_html_select_element *ele)
  64. {
  65.         ele->form = NULL;
  66.         ele->options = NULL;
  67.  
  68.         return _dom_html_element_initialise(doc, &ele->base,
  69.                                             doc->memoised[hds_SELECT],
  70.                                             namespace, prefix);
  71. }
  72.  
  73. /**
  74.  * Finalise a dom_html_select_element object
  75.  *
  76.  * \param ele  The dom_html_select_element object
  77.  */
  78. void _dom_html_select_element_finalise(struct dom_html_select_element *ele)
  79. {
  80.         if (ele->options != NULL)
  81.                 dom_html_options_collection_unref(ele->options);
  82.  
  83.         _dom_html_element_finalise(&ele->base);
  84. }
  85.  
  86. /**
  87.  * Destroy a dom_html_select_element object
  88.  *
  89.  * \param ele  The dom_html_select_element object
  90.  */
  91. void _dom_html_select_element_destroy(struct dom_html_select_element *ele)
  92. {
  93.         _dom_html_select_element_finalise(ele);
  94.         free(ele);
  95. }
  96.  
  97. /*------------------------------------------------------------------------*/
  98. /* The protected virtual functions */
  99.  
  100. /* The virtual function used to parse attribute value, see src/core/element.c
  101.  * for detail */
  102. dom_exception _dom_html_select_element_parse_attribute(dom_element *ele,
  103.                 dom_string *name, dom_string *value,
  104.                 dom_string **parsed)
  105. {
  106.         UNUSED(ele);
  107.         UNUSED(name);
  108.  
  109.         dom_string_ref(value);
  110.         *parsed = value;
  111.  
  112.         return DOM_NO_ERR;
  113. }
  114.  
  115. /* The virtual destroy function, see src/core/node.c for detail */
  116. void _dom_virtual_html_select_element_destroy(dom_node_internal *node)
  117. {
  118.         _dom_html_select_element_destroy((struct dom_html_select_element *) node);
  119. }
  120.  
  121. /* The virtual copy function, see src/core/node.c for detail */
  122. dom_exception _dom_html_select_element_copy(dom_node_internal *old,
  123.                 dom_node_internal **copy)
  124. {
  125.         return _dom_html_element_copy(old, copy);
  126. }
  127.  
  128. /*-----------------------------------------------------------------------*/
  129. /* Public APIs */
  130.  
  131. static dom_exception _dom_html_select_element_ensure_collection(
  132.                 dom_html_select_element *ele)
  133. {
  134.         dom_exception err;
  135.         dom_html_document *doc = (dom_html_document *) dom_node_get_owner(ele);
  136.  
  137.         assert(doc != NULL);
  138.  
  139.         if (ele->options == NULL) {
  140.                 err = _dom_html_options_collection_create(doc,
  141.                                 (dom_node_internal *) ele,
  142.                                 is_option, ele, &ele->options);
  143.                 if (err != DOM_NO_ERR)
  144.                         return err;
  145.         }
  146.  
  147.         return DOM_NO_ERR;
  148. }
  149.  
  150. /**
  151.  * Get the type of selection control
  152.  *
  153.  * \param ele   The Select element
  154.  * \param type  Pointer to location to receive type
  155.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  156.  */
  157. dom_exception dom_html_select_element_get_type(
  158.                 dom_html_select_element *ele, dom_string **type)
  159. {
  160.         dom_html_document *doc = (dom_html_document *) dom_node_get_owner(ele);
  161.         dom_exception err;
  162.         bool multiple;
  163.  
  164.         err = dom_html_select_element_get_multiple(ele, &multiple);
  165.         if (err != DOM_NO_ERR)
  166.                 return err;
  167.  
  168.         if (multiple)
  169.                 *type = dom_string_ref(doc->memoised[hds_select_multiple]);
  170.         else
  171.                 *type = dom_string_ref(doc->memoised[hds_select_one]);
  172.  
  173.         return DOM_NO_ERR;
  174. }
  175.  
  176. /**
  177.  * Get the ordinal index of the selected option
  178.  *
  179.  * \param ele    The element object
  180.  * \param index  The returned index
  181.  * \return DOM_NO_ERR on success.
  182.  */
  183. dom_exception dom_html_select_element_get_selected_index(
  184.                 dom_html_select_element *ele, int32_t *index)
  185. {
  186.         dom_exception err;
  187.         uint32_t idx, len;
  188.         dom_node *option;
  189.         bool selected;
  190.  
  191.         err = dom_html_select_element_get_length(ele, &len);
  192.         if (err != DOM_NO_ERR)
  193.                 return err;
  194.  
  195.         for (idx = 0; idx < len; idx++) {
  196.                 err = dom_html_options_collection_item(ele->options,
  197.                                 idx, &option);
  198.                 if (err != DOM_NO_ERR)
  199.                         return err;
  200.  
  201.                 err = dom_html_option_element_get_selected(
  202.                                 (dom_html_option_element *) option, &selected);
  203.  
  204.                 dom_node_unref(option);
  205.  
  206.                 if (err != DOM_NO_ERR)
  207.                         return err;
  208.  
  209.                 if (selected) {
  210.                         *index = idx;
  211.                         return DOM_NO_ERR;
  212.                 }
  213.         }
  214.  
  215.         *index = -1;
  216.  
  217.         return DOM_NO_ERR;
  218. }
  219.  
  220. /**
  221.  * Set the ordinal index of the selected option
  222.  *
  223.  * \param ele    The element object
  224.  * \param index  The new index
  225.  * \return DOM_NO_ERR on success.
  226.  */
  227. dom_exception dom_html_select_element_set_selected_index(
  228.                 dom_html_select_element *ele, int32_t index)
  229. {
  230.         UNUSED(ele);
  231.         UNUSED(index);
  232.  
  233.         /** \todo Implement */
  234.         return DOM_NOT_SUPPORTED_ERR;
  235. }
  236.  
  237. /**
  238.  * Get the value of this form control
  239.  *
  240.  * \param ele    The select element
  241.  * \param value  Pointer to location to receive value
  242.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  243.  */
  244. dom_exception dom_html_select_element_get_value(
  245.                 dom_html_select_element *ele, dom_string **value)
  246. {
  247.         dom_exception err;
  248.         uint32_t idx, len;
  249.         dom_node *option;
  250.         bool selected;
  251.  
  252.         err = dom_html_select_element_get_length(ele, &len);
  253.         if (err != DOM_NO_ERR)
  254.                 return err;
  255.  
  256.         for (idx = 0; idx < len; idx++) {
  257.                 err = dom_html_options_collection_item(ele->options,
  258.                                 idx, &option);
  259.                 if (err != DOM_NO_ERR)
  260.                         return err;
  261.  
  262.                 err = dom_html_option_element_get_selected(
  263.                                 (dom_html_option_element *) option, &selected);
  264.                 if (err != DOM_NO_ERR) {
  265.                         dom_node_unref(option);
  266.                         return err;
  267.                 }
  268.  
  269.                 if (selected) {
  270.                         err = dom_html_option_element_get_value(
  271.                                         (dom_html_option_element *) option,
  272.                                         value);
  273.  
  274.                         dom_node_unref(option);
  275.  
  276.                         return err;
  277.                 }
  278.         }
  279.  
  280.         *value = NULL;
  281.  
  282.         return DOM_NO_ERR;
  283. }
  284.  
  285. /**
  286.  * Set the value of this form control
  287.  *
  288.  * \param ele    The select element
  289.  * \param value  New value
  290.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  291.  */
  292. dom_exception dom_html_select_element_set_value(
  293.                 dom_html_select_element *ele, dom_string *value)
  294. {
  295.         UNUSED(ele);
  296.         UNUSED(value);
  297.  
  298.         /** \todo Implement */
  299.         return DOM_NOT_SUPPORTED_ERR;
  300. }
  301.  
  302. /**
  303.  * Get the number of options in this select element
  304.  *
  305.  * \param ele  The element object
  306.  * \param len  The returned len
  307.  * \return DOM_NO_ERR on success.
  308.  */
  309. dom_exception dom_html_select_element_get_length(
  310.                 dom_html_select_element *ele, uint32_t *len)
  311. {
  312.         dom_exception err;
  313.  
  314.         err = _dom_html_select_element_ensure_collection(ele);
  315.         if (err != DOM_NO_ERR)
  316.                 return err;
  317.  
  318.         return dom_html_options_collection_get_length(ele->options, len);
  319. }
  320.  
  321. /**
  322.  * Set the number of options in this select element
  323.  *
  324.  * \param ele  The element object
  325.  * \param len  The new len
  326.  * \return DOM_NOT_SUPPORTED_ERR.
  327.  *
  328.  * todo: how to deal with set the len of the children option objects?
  329.  */
  330. dom_exception dom_html_select_element_set_length(
  331.                 dom_html_select_element *ele, uint32_t len)
  332. {
  333.         UNUSED(ele);
  334.         UNUSED(len);
  335.  
  336.         return DOM_NOT_SUPPORTED_ERR;
  337. }
  338.  
  339. /**
  340.  * Get the form associated with a select
  341.  *
  342.  * \param select  The dom_html_select_element object
  343.  * \param form    Pointer to location to receive form
  344.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  345.  */
  346. dom_exception dom_html_select_element_get_form(
  347.         dom_html_select_element *select, dom_html_form_element **form)
  348. {
  349.         *form = select->form;
  350.  
  351.         if (*form != NULL)
  352.                 dom_node_ref(*form);
  353.  
  354.         return DOM_NO_ERR;
  355. }
  356.  
  357. /**
  358.  * The collection of OPTION elements of this element
  359.  *
  360.  * \param ele  The element object
  361.  * \param col  THe returned collection object
  362.  * \return DOM_NO_ERR on success.
  363.  */
  364. dom_exception dom__html_select_element_get_options(
  365.                 dom_html_select_element *ele,
  366.                 struct dom_html_options_collection **col)
  367. {
  368.         dom_exception err;
  369.  
  370.         err = _dom_html_select_element_ensure_collection(ele);
  371.         if (err != DOM_NO_ERR)
  372.                 return err;
  373.  
  374.         dom_html_options_collection_ref(ele->options);
  375.         *col = ele->options;
  376.  
  377.         return DOM_NO_ERR;
  378. }
  379.  
  380. /**
  381.  * Whether this element is disabled
  382.  *
  383.  * \param ele       The element object
  384.  * \param disabled  The returned status
  385.  * \return DOM_NO_ERR on success.
  386.  */
  387. dom_exception dom_html_select_element_get_disabled(
  388.                 dom_html_select_element *ele, bool *disabled)
  389. {
  390.         return dom_html_element_get_bool_property(&ele->base,
  391.                         "disabled", SLEN("disabled"), disabled);
  392. }
  393.  
  394. /**
  395.  * Set the disabled status of this element
  396.  *
  397.  * \param ele       The element object
  398.  * \param disabled  The disabled status
  399.  * \return DOM_NO_ERR on success.
  400.  */
  401. dom_exception dom_html_select_element_set_disabled(
  402.                 dom_html_select_element *ele, bool disabled)
  403. {
  404.         return dom_html_element_set_bool_property(&ele->base,
  405.                         "disabled", SLEN("disabled"), disabled);
  406. }
  407.  
  408. /**
  409.  * Whether this element can be multiple selected
  410.  *
  411.  * \param ele       The element object
  412.  * \param multiple  The returned status
  413.  * \return DOM_NO_ERR on success.
  414.  */
  415. dom_exception dom_html_select_element_get_multiple(
  416.                 dom_html_select_element *ele, bool *multiple)
  417. {
  418.         return dom_html_element_get_bool_property(&ele->base,
  419.                         "multiple", SLEN("multiple"), multiple);
  420. }
  421.  
  422. /**
  423.  * Set whether this element can be multiple selected
  424.  *
  425.  * \param ele       The element object
  426.  * \param multiple  The status
  427.  * \return DOM_NO_ERR on success.
  428.  */
  429. dom_exception dom_html_select_element_set_multiple(
  430.                 dom_html_select_element *ele, bool multiple)
  431. {
  432.         return dom_html_element_set_bool_property(&ele->base,
  433.                         "multiple", SLEN("multiple"), multiple);
  434. }
  435.  
  436. /**
  437.  * Get the name property
  438.  *
  439.  * \param ele   The select element
  440.  * \param name  Pointer to location to receive name
  441.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  442.  */
  443. dom_exception dom_html_select_element_get_name(
  444.                 dom_html_select_element *ele, dom_string **name)
  445. {
  446.         dom_html_document *doc = (dom_html_document *) dom_node_get_owner(ele);
  447.  
  448.         return dom_element_get_attribute(ele,
  449.                         doc->memoised[hds_name], name);
  450. }
  451.  
  452. /**
  453.  * Set the name property
  454.  *
  455.  * \param ele   The select element
  456.  * \param name  New name
  457.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  458.  */
  459. dom_exception dom_html_select_element_set_name(
  460.                 dom_html_select_element *ele, dom_string *name)
  461. {
  462.         dom_html_document *doc = (dom_html_document *) dom_node_get_owner(ele);
  463.  
  464.         return dom_element_set_attribute(ele,
  465.                         doc->memoised[hds_name], name);
  466.  
  467. }
  468.  
  469. /**
  470.  * Get the size property
  471.  *
  472.  * \param ele   The select element
  473.  * \param size  Pointer to location to receive size
  474.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  475.  */
  476. dom_exception dom_html_select_element_get_size(
  477.                 dom_html_select_element *ele, int32_t *size)
  478. {
  479.         return dom_html_element_get_int32_t_property(&ele->base, "size",
  480.                         SLEN("size"), size);
  481. }
  482.  
  483. /**
  484.  * Set the size property
  485.  *
  486.  * \param ele   The select element
  487.  * \param size  New size
  488.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  489.  */
  490. dom_exception dom_html_select_element_set_size(
  491.                 dom_html_select_element *ele, int32_t size)
  492. {
  493.         return dom_html_element_set_int32_t_property(&ele->base, "size",
  494.                         SLEN("size"), size);
  495. }
  496.  
  497. /**
  498.  * Get the tabindex property
  499.  *
  500.  * \param ele        The select element
  501.  * \param tab_index  Pointer to location to receive tab index
  502.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  503.  */
  504. dom_exception dom_html_select_element_get_tab_index(
  505.                 dom_html_select_element *ele, int32_t *tab_index)
  506. {
  507.         return dom_html_element_get_int32_t_property(&ele->base, "tabindex",
  508.                         SLEN("tabindex"), tab_index);
  509. }
  510.  
  511. /**
  512.  * Set the tabindex property
  513.  *
  514.  * \param ele        The select element
  515.  * \param tab_index  New tab index
  516.  * \return DOM_NO_ERR on success, appropriate error otherwise.
  517.  */
  518. dom_exception dom_html_select_element_set_tab_index(
  519.                 dom_html_select_element *ele, int32_t tab_index)
  520. {
  521.         return dom_html_element_set_int32_t_property(&ele->base, "tabindex",
  522.                         SLEN("tabindex"), tab_index);
  523. }
  524.  
  525.  
  526. /* Functions */
  527. dom_exception dom__html_select_element_add(dom_html_select_element *select,
  528.                 struct dom_html_element *ele, struct dom_html_element *before)
  529. {
  530.         UNUSED(select);
  531.         UNUSED(ele);
  532.         UNUSED(before);
  533.  
  534.         /** \todo Implement */
  535.         return DOM_NOT_SUPPORTED_ERR;
  536. }
  537.  
  538. dom_exception dom_html_select_element_remove(dom_html_select_element *ele,
  539.                 int32_t index)
  540. {
  541.         dom_exception err;
  542.         uint32_t len;
  543.         dom_node *option;
  544.  
  545.         err = dom_html_select_element_get_length(ele, &len);
  546.         if (err != DOM_NO_ERR)
  547.                 return err;
  548.  
  549.         /* Ensure index is in range */
  550.         if (index < 0 || (uint32_t)index >= len)
  551.                 return DOM_NO_ERR;
  552.  
  553.         err = dom_html_options_collection_item(ele->options, index, &option);
  554.         if (err != DOM_NO_ERR)
  555.                 return err;
  556.  
  557.         /** \todo What does remove mean? Remove option from tree and destroy it? */
  558.         return DOM_NOT_SUPPORTED_ERR;
  559. }
  560.  
  561. /**
  562.  * Blur this control
  563.  *
  564.  * \param ele  Element to blur
  565.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  566.  */
  567. dom_exception dom_html_select_element_blur(struct dom_html_select_element *ele)
  568. {
  569.         struct dom_html_document *doc =
  570.                 (dom_html_document *) dom_node_get_owner(ele);
  571.         bool success = false;
  572.         assert(doc != NULL);
  573.  
  574.         /** \todo Is this event (a) default (b) bubbling and (c) cancelable? */
  575.         return _dom_dispatch_generic_event((dom_document *) doc,
  576.                                            (dom_event_target *) ele,
  577.                                            doc->memoised[hds_blur], true,
  578.                                            true, &success);
  579. }
  580.  
  581. /**
  582.  * Focus this control
  583.  *
  584.  * \param ele  Element to focus
  585.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  586.  */
  587. dom_exception dom_html_select_element_focus(struct dom_html_select_element *ele)
  588. {
  589.         struct dom_html_document *doc =
  590.                 (dom_html_document *) dom_node_get_owner(ele);
  591.         bool success = false;
  592.         assert(doc != NULL);
  593.  
  594.         /** \todo Is this event (a) default (b) bubbling and (c) cancelable? */
  595.         return _dom_dispatch_generic_event((dom_document *) doc,
  596.                                            (dom_event_target *) ele,
  597.                                            doc->memoised[hds_focus], true,
  598.                                            true, &success);
  599. }
  600.  
  601.  
  602. /*-----------------------------------------------------------------------*/
  603. /* Helper functions */
  604.  
  605. /* Test whether certain node is an option node */
  606. bool is_option(struct dom_node_internal *node, void *ctx)
  607. {
  608.         dom_html_select_element *ele = ctx;
  609.         dom_html_document *doc = (dom_html_document *) dom_node_get_owner(ele);
  610.        
  611.         if (dom_string_isequal(node->name, doc->memoised[hds_OPTION]))
  612.                 return true;
  613.  
  614.         return false;
  615. }
  616.  
  617. dom_exception _dom_html_select_element_set_form(
  618.         dom_html_select_element *select, dom_html_form_element *form)
  619. {
  620.         select->form = form;
  621.  
  622.         return DOM_NO_ERR;
  623. }
  624.  
  625.