| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ |
| |
| use dom_struct::dom_struct; |
| use html5ever::{LocalName, Prefix, local_name}; |
| use js::rust::HandleObject; |
| |
| use crate::dom::attr::Attr; |
| use crate::dom::bindings::cell::DomRefCell; |
| use crate::dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods; |
| use crate::dom::bindings::inheritance::Castable; |
| use crate::dom::bindings::root::{DomRoot, MutNullableDom}; |
| use crate::dom::bindings::str::DOMString; |
| use crate::dom::document::Document; |
| use crate::dom::element::{AttributeMutation, Element}; |
| use crate::dom::html::htmlelement::HTMLElement; |
| use crate::dom::html::htmlformelement::{FormControl, HTMLFormElement}; |
| use crate::dom::node::{Node, NodeTraits}; |
| use crate::dom::nodelist::NodeList; |
| use crate::dom::validation::Validatable; |
| use crate::dom::validitystate::ValidityState; |
| use crate::dom::virtualmethods::VirtualMethods; |
| use crate::script_runtime::CanGc; |
| |
| #[dom_struct] |
| pub(crate) struct HTMLOutputElement { |
| htmlelement: HTMLElement, |
| form_owner: MutNullableDom<HTMLFormElement>, |
| labels_node_list: MutNullableDom<NodeList>, |
| default_value_override: DomRefCell<Option<DOMString>>, |
| validity_state: MutNullableDom<ValidityState>, |
| } |
| |
| impl HTMLOutputElement { |
| fn new_inherited( |
| local_name: LocalName, |
| prefix: Option<Prefix>, |
| document: &Document, |
| ) -> HTMLOutputElement { |
| HTMLOutputElement { |
| htmlelement: HTMLElement::new_inherited(local_name, prefix, document), |
| form_owner: Default::default(), |
| labels_node_list: Default::default(), |
| default_value_override: DomRefCell::new(None), |
| validity_state: Default::default(), |
| } |
| } |
| |
| #[cfg_attr(crown, allow(crown::unrooted_must_root))] |
| pub(crate) fn new( |
| local_name: LocalName, |
| prefix: Option<Prefix>, |
| document: &Document, |
| proto: Option<HandleObject>, |
| can_gc: CanGc, |
| ) -> DomRoot<HTMLOutputElement> { |
| Node::reflect_node_with_proto( |
| Box::new(HTMLOutputElement::new_inherited( |
| local_name, prefix, document, |
| )), |
| document, |
| proto, |
| can_gc, |
| ) |
| } |
| |
| pub(crate) fn reset(&self, can_gc: CanGc) { |
| Node::string_replace_all(self.DefaultValue(), self.upcast::<Node>(), can_gc); |
| *self.default_value_override.borrow_mut() = None; |
| } |
| } |
| |
| impl HTMLOutputElementMethods<crate::DomTypeHolder> for HTMLOutputElement { |
| // https://html.spec.whatwg.org/multipage/#dom-fae-form |
| fn GetForm(&self) -> Option<DomRoot<HTMLFormElement>> { |
| self.form_owner() |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-lfe-labels |
| make_labels_getter!(Labels, labels_node_list); |
| |
| // https://html.spec.whatwg.org/multipage/#dom-output-defaultvaleu |
| fn DefaultValue(&self) -> DOMString { |
| let dvo = self.default_value_override.borrow(); |
| if let Some(ref dv) = *dvo { |
| dv.clone() |
| } else { |
| self.upcast::<Node>().descendant_text_content() |
| } |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-output-defaultvalue |
| fn SetDefaultValue(&self, value: DOMString, can_gc: CanGc) { |
| if self.default_value_override.borrow().is_none() { |
| // Step 1 ("and return") |
| Node::string_replace_all(value.clone(), self.upcast::<Node>(), can_gc); |
| } else { |
| // Step 2, if not returned from step 1 |
| *self.default_value_override.borrow_mut() = Some(value); |
| } |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-output-value |
| fn Value(&self) -> DOMString { |
| self.upcast::<Node>().descendant_text_content() |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-output-value |
| fn SetValue(&self, value: DOMString, can_gc: CanGc) { |
| *self.default_value_override.borrow_mut() = Some(self.DefaultValue()); |
| Node::string_replace_all(value, self.upcast::<Node>(), can_gc); |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-output-type |
| fn Type(&self) -> DOMString { |
| DOMString::from("output") |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-fe-name |
| make_atomic_setter!(SetName, "name"); |
| |
| // https://html.spec.whatwg.org/multipage/#dom-fe-name |
| make_getter!(Name, "name"); |
| |
| // https://html.spec.whatwg.org/multipage/#dom-cva-willvalidate |
| fn WillValidate(&self) -> bool { |
| self.is_instance_validatable() |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-cva-validity |
| fn Validity(&self) -> DomRoot<ValidityState> { |
| self.validity_state() |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-cva-checkvalidity |
| fn CheckValidity(&self, can_gc: CanGc) -> bool { |
| self.check_validity(can_gc) |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity |
| fn ReportValidity(&self, can_gc: CanGc) -> bool { |
| self.report_validity(can_gc) |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage |
| fn ValidationMessage(&self) -> DOMString { |
| self.validation_message() |
| } |
| |
| // https://html.spec.whatwg.org/multipage/#dom-cva-setcustomvalidity |
| fn SetCustomValidity(&self, error: DOMString) { |
| self.validity_state().set_custom_error_message(error); |
| } |
| } |
| |
| impl VirtualMethods for HTMLOutputElement { |
| fn super_type(&self) -> Option<&dyn VirtualMethods> { |
| Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods) |
| } |
| |
| fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) { |
| self.super_type() |
| .unwrap() |
| .attribute_mutated(attr, mutation, can_gc); |
| if attr.local_name() == &local_name!("form") { |
| self.form_attribute_mutated(mutation, can_gc); |
| } |
| } |
| } |
| |
| impl FormControl for HTMLOutputElement { |
| fn form_owner(&self) -> Option<DomRoot<HTMLFormElement>> { |
| self.form_owner.get() |
| } |
| |
| fn set_form_owner(&self, form: Option<&HTMLFormElement>) { |
| self.form_owner.set(form); |
| } |
| |
| fn to_element(&self) -> &Element { |
| self.upcast::<Element>() |
| } |
| } |
| |
| impl Validatable for HTMLOutputElement { |
| fn as_element(&self) -> &Element { |
| self.upcast() |
| } |
| |
| fn validity_state(&self) -> DomRoot<ValidityState> { |
| self.validity_state |
| .or_init(|| ValidityState::new(&self.owner_window(), self.upcast(), CanGc::note())) |
| } |
| |
| fn is_instance_validatable(&self) -> bool { |
| // output is not a submittable element (https://html.spec.whatwg.org/multipage/#category-submit) |
| false |
| } |
| } |