aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmltableelement.rs
diff options
context:
space:
mode:
authorYoav Alon <yoava333@gmail.com>2016-03-13 21:47:35 +0200
committerYoav Alon <yoava333@gmail.com>2016-04-12 18:35:55 +0300
commit5e3dcae71f5a1cf9b08866ae278cadd4d295beaf (patch)
tree7fb477ddb623af00b1270b982c9d525051a477ad /components/script/dom/htmltableelement.rs
parentdfb482a2b7fdb570f34e9092384fa74a3e1b54e3 (diff)
downloadservo-5e3dcae71f5a1cf9b08866ae278cadd4d295beaf.tar.gz
servo-5e3dcae71f5a1cf9b08866ae278cadd4d295beaf.zip
Implement the table section IDL attributes for HTML tables
Diffstat (limited to 'components/script/dom/htmltableelement.rs')
-rw-r--r--components/script/dom/htmltableelement.rs147
1 files changed, 146 insertions, 1 deletions
diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs
index ab611716b90..4ea908675b1 100644
--- a/components/script/dom/htmltableelement.rs
+++ b/components/script/dom/htmltableelement.rs
@@ -7,13 +7,15 @@ use dom::attr::{Attr, AttrValue};
use dom::bindings::codegen::Bindings::HTMLTableElementBinding;
use dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
+use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::inheritance::Castable;
-use dom::bindings::js::{JS, LayoutJS, Root, RootedReference};
+use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root, RootedReference};
use dom::document::Document;
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
use dom::htmlelement::HTMLElement;
use dom::htmltablecaptionelement::HTMLTableCaptionElement;
+use dom::htmltablecolelement::HTMLTableColElement;
use dom::htmltablerowelement::HTMLTableRowElement;
use dom::htmltablesectionelement::HTMLTableSectionElement;
use dom::node::{Node, document_from_node, window_from_node};
@@ -28,6 +30,7 @@ pub struct HTMLTableElement {
htmlelement: HTMLElement,
border: Cell<Option<u32>>,
cellspacing: Cell<Option<u32>>,
+ tbodies: MutNullableHeap<JS<HTMLCollection>>,
}
impl HTMLTableElement {
@@ -37,6 +40,7 @@ impl HTMLTableElement {
htmlelement: HTMLElement::new_inherited(localName, prefix, document),
border: Cell::new(None),
cellspacing: Cell::new(None),
+ tbodies: Default::default(),
}
}
@@ -50,6 +54,70 @@ impl HTMLTableElement {
pub fn get_border(&self) -> Option<u32> {
self.border.get()
}
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-thead
+ // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
+ fn get_first_section_of_type(&self, atom: &Atom) -> Option<Root<HTMLTableSectionElement>> {
+ self.upcast::<Node>()
+ .child_elements()
+ .find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == atom)
+ .and_then(|n| n.downcast().map(Root::from_ref))
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-thead
+ // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
+ fn set_first_section_of_type<P>(&self,
+ atom: &Atom,
+ section: Option<&HTMLTableSectionElement>,
+ reference_predicate: P)
+ -> ErrorResult
+ where P: FnMut(&Root<Element>) -> bool {
+ if let Some(e) = section {
+ if e.upcast::<Element>().local_name() != atom {
+ return Err(Error::HierarchyRequest)
+ }
+ }
+
+ self.delete_first_section_of_type(atom);
+
+ let node = self.upcast::<Node>();
+
+ if let Some(section) = section {
+ let reference_element = node.child_elements().find(reference_predicate);
+ let reference_node = reference_element.r().map(|e| e.upcast());
+
+ try!(node.InsertBefore(section.upcast(), reference_node));
+ }
+
+ Ok(())
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-createthead
+ // https://html.spec.whatwg.org/multipage/#dom-table-createtfoot
+ fn create_section_of_type(&self, atom: &Atom) -> Root<HTMLTableSectionElement> {
+ if let Some(section) = self.get_first_section_of_type(atom) {
+ return section
+ }
+
+ let section = HTMLTableSectionElement::new(atom.clone(),
+ None,
+ document_from_node(self).r());
+ match atom {
+ &atom!("thead") => self.SetTHead(Some(&section)),
+ &atom!("tfoot") => self.SetTFoot(Some(&section)),
+ _ => unreachable!("unexpected section type")
+ }.expect("unexpected section type");
+
+ section
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-deletethead
+ // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot
+ fn delete_first_section_of_type(&self, atom: &Atom) {
+ if let Some(thead) = self.get_first_section_of_type(atom) {
+ thead.upcast::<Node>().remove_self();
+ }
+ }
}
impl HTMLTableElementMethods for HTMLTableElement {
@@ -119,6 +187,83 @@ impl HTMLTableElementMethods for HTMLTableElement {
}
}
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-thead
+ fn GetTHead(&self) -> Option<Root<HTMLTableSectionElement>> {
+ self.get_first_section_of_type(&atom!("thead"))
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-thead
+ fn SetTHead(&self, thead: Option<&HTMLTableSectionElement>) -> ErrorResult {
+ self.set_first_section_of_type(&atom!("thead"), thead, |n| {
+ !n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>()
+ })
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-createthead
+ fn CreateTHead(&self) -> Root<HTMLTableSectionElement> {
+ self.create_section_of_type(&atom!("thead"))
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-deletethead
+ fn DeleteTHead(&self) {
+ self.delete_first_section_of_type(&atom!("thead"))
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
+ fn GetTFoot(&self) -> Option<Root<HTMLTableSectionElement>> {
+ self.get_first_section_of_type(&atom!("tfoot"))
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
+ fn SetTFoot(&self, tfoot: Option<&HTMLTableSectionElement>) -> ErrorResult {
+ self.set_first_section_of_type(&atom!("tfoot"), tfoot, |n| {
+ if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() {
+ return false;
+ }
+
+ if n.is::<HTMLTableSectionElement>() {
+ let name = n.local_name();
+ if name == &atom!("thead") || name == &atom!("tbody") {
+ return false;
+ }
+
+ }
+
+ true
+ })
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-createtfoot
+ fn CreateTFoot(&self) -> Root<HTMLTableSectionElement> {
+ self.create_section_of_type(&atom!("tfoot"))
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot
+ fn DeleteTFoot(&self) {
+ self.delete_first_section_of_type(&atom!("tfoot"))
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-table-tbodies
+ fn TBodies(&self) -> Root<HTMLCollection> {
+ #[derive(JSTraceable)]
+ struct TBodiesFilter;
+ impl CollectionFilter for TBodiesFilter {
+ fn filter(&self, elem: &Element, root: &Node) -> bool {
+ elem.is::<HTMLTableSectionElement>()
+ && elem.local_name() == &atom!("tbody")
+ && elem.upcast::<Node>().GetParentNode().r() == Some(root)
+ }
+ }
+
+ self.tbodies.or_init(|| {
+ let window = window_from_node(self);
+ let filter = box TBodiesFilter;
+ HTMLCollection::create(window.r(), self.upcast(), filter)
+ })
+ }
+
+
// https://html.spec.whatwg.org/multipage/#dom-table-createtbody
fn CreateTBody(&self) -> Root<HTMLTableSectionElement> {
let tbody = HTMLTableSectionElement::new(atom!("tbody"),