use rdom_core::NodeId;
use crate::TuiDom;
pub fn selected_options(dom: &TuiDom, select: NodeId) -> Vec<NodeId> {
let mut out = Vec::new();
for opt in options(dom, select) {
if dom.node(opt).has_attribute("selected") {
out.push(opt);
}
}
out
}
pub fn value(dom: &TuiDom, select: NodeId) -> String {
let selected = selected_options(dom, select);
if selected.is_empty() {
return String::new();
}
if is_multi(dom, select) {
selected
.iter()
.map(|&id| option_value(dom, id))
.collect::<Vec<_>>()
.join(" ")
} else {
option_value(dom, selected[0])
}
}
pub fn option_value(dom: &TuiDom, option: NodeId) -> String {
if let Some(v) = dom.node(option).get_attribute("value") {
return v.to_string();
}
option_label(dom, option)
}
pub fn option_label(dom: &TuiDom, option: NodeId) -> String {
if let Some(v) = dom.node(option).get_attribute("label") {
return v.to_string();
}
crate::node::child_text(dom, option)
}
pub(crate) fn is_multi(dom: &TuiDom, select: NodeId) -> bool {
dom.node(select).has_attribute("multiple")
}
pub(crate) fn display_size(dom: &TuiDom, select: NodeId) -> u32 {
dom.node(select)
.get_attribute("size")
.and_then(|s| s.trim().parse::<u32>().ok())
.filter(|n| *n > 0)
.unwrap_or(1)
}
pub fn options(dom: &TuiDom, select: NodeId) -> Vec<NodeId> {
let mut out = Vec::new();
walk_options(dom, select, &mut out);
out
}
fn walk_options(dom: &TuiDom, id: NodeId, out: &mut Vec<NodeId>) {
for child in dom.node(id).child_nodes() {
match child.tag_name() {
Some("option") => out.push(child.id()),
Some("optgroup") => walk_options(dom, child.id(), out),
_ => {}
}
}
}
pub(crate) fn option_disabled(dom: &TuiDom, option: NodeId) -> bool {
dom.is_actually_disabled(option)
}
pub(super) fn closest_option(dom: &TuiDom, id: NodeId) -> Option<NodeId> {
let mut cur = Some(id);
while let Some(n) = cur {
if dom.node(n).tag_name() == Some("option") {
return Some(n);
}
cur = dom.node(n).parent_node().map(|p| p.id());
}
None
}
pub(super) fn closest_select(dom: &TuiDom, id: NodeId) -> Option<NodeId> {
enclosing_select(dom, id)
}
pub(super) fn enclosing_select(dom: &TuiDom, id: NodeId) -> Option<NodeId> {
let mut cur = Some(id);
while let Some(n) = cur {
if dom.node(n).tag_name() == Some("select") {
return Some(n);
}
cur = dom.node(n).parent_node().map(|p| p.id());
}
None
}