mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Implement HTMLTableRowElement insertCell and deleteCell
This commit is contained in:
parent
e31ad01103
commit
1f58169263
8 changed files with 108 additions and 106 deletions
|
@ -8,11 +8,13 @@ use dom::bindings::codegen::Bindings::HTMLTableRowElementBinding::{self, HTMLTab
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTableDataCellElementDerived};
|
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTableDataCellElementDerived};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLTableHeaderCellElementDerived, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLTableHeaderCellElementDerived, NodeCast};
|
||||||
|
use dom::bindings::error::{ErrorResult, Fallible};
|
||||||
use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference};
|
use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
|
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
|
use dom::htmltabledatacellelement::HTMLTableDataCellElement;
|
||||||
use dom::node::{Node, window_from_node};
|
use dom::node::{Node, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -73,6 +75,24 @@ impl HTMLTableRowElementMethods for HTMLTableRowElement {
|
||||||
HTMLCollection::create(window.r(), NodeCast::from_ref(self), filter)
|
HTMLCollection::create(window.r(), NodeCast::from_ref(self), filter)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-tr-insertcell
|
||||||
|
fn InsertCell(&self, index: i32) -> Fallible<Root<HTMLElement>> {
|
||||||
|
let node = NodeCast::from_ref(self);
|
||||||
|
node.insert_cell_or_row(
|
||||||
|
index,
|
||||||
|
|| self.Cells(),
|
||||||
|
|| HTMLTableDataCellElement::new("td".to_owned(), None, node.owner_doc().r()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-tr-deletecell
|
||||||
|
fn DeleteCell(&self, index: i32) -> ErrorResult {
|
||||||
|
let node = NodeCast::from_ref(self);
|
||||||
|
node.delete_cell_or_row(
|
||||||
|
index,
|
||||||
|
|| self.Cells(),
|
||||||
|
|n| n.is_htmltabledatacellelement())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLTableRowElement {
|
impl VirtualMethods for HTMLTableRowElement {
|
||||||
|
|
|
@ -4,12 +4,9 @@
|
||||||
|
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
|
|
||||||
use dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding::{self, HTMLTableSectionElementMethods};
|
use dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding::{self, HTMLTableSectionElementMethods};
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTableRowElementDerived, NodeCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLTableRowElementDerived, NodeCast};
|
|
||||||
use dom::bindings::error::Error;
|
|
||||||
use dom::bindings::error::{ErrorResult, Fallible};
|
use dom::bindings::error::{ErrorResult, Fallible};
|
||||||
use dom::bindings::js::{Root, RootedReference};
|
use dom::bindings::js::{Root, RootedReference};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
|
@ -20,7 +17,6 @@ use dom::htmltablerowelement::HTMLTableRowElement;
|
||||||
use dom::node::{Node, window_from_node};
|
use dom::node::{Node, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::iter;
|
|
||||||
use util::str::{self, DOMString};
|
use util::str::{self, DOMString};
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -67,57 +63,20 @@ impl HTMLTableSectionElementMethods for HTMLTableSectionElement {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-tbody-insertrow
|
// https://html.spec.whatwg.org/multipage/#dom-tbody-insertrow
|
||||||
fn InsertRow(&self, index: i32) -> Fallible<Root<HTMLElement>> {
|
fn InsertRow(&self, index: i32) -> Fallible<Root<HTMLElement>> {
|
||||||
if index < -1 {
|
|
||||||
return Err(Error::IndexSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
let node = NodeCast::from_ref(self);
|
let node = NodeCast::from_ref(self);
|
||||||
let tr = HTMLTableRowElement::new("tr".to_owned(), None, node.owner_doc().r());
|
node.insert_cell_or_row(
|
||||||
|
index,
|
||||||
let after_node = if index == -1 {
|
|| self.Rows(),
|
||||||
None
|
|| HTMLTableRowElement::new("tr".to_owned(), None, node.owner_doc().r()))
|
||||||
} else {
|
|
||||||
match self.Rows()
|
|
||||||
.elements_iter()
|
|
||||||
.map(NodeCast::from_root)
|
|
||||||
.map(Some)
|
|
||||||
.chain(iter::once(None))
|
|
||||||
.nth(index as usize) {
|
|
||||||
None => return Err(Error::IndexSize),
|
|
||||||
Some(node) => node,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
{
|
|
||||||
let tr_node = NodeCast::from_ref(tr.r());
|
|
||||||
try!(node.InsertBefore(tr_node, after_node.r()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(HTMLElementCast::from_root(tr))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-tbody-deleterow
|
// https://html.spec.whatwg.org/multipage/#dom-tbody-deleterow
|
||||||
fn DeleteRow(&self, index: i32) -> ErrorResult {
|
fn DeleteRow(&self, index: i32) -> ErrorResult {
|
||||||
let element = match index {
|
let node = NodeCast::from_ref(self);
|
||||||
index if index < -1 => return Err(Error::IndexSize),
|
node.delete_cell_or_row(
|
||||||
-1 => {
|
index,
|
||||||
let last_child = NodeCast::from_ref(self).GetLastChild();
|
|| self.Rows(),
|
||||||
match last_child.and_then(|node| node.inclusively_preceding_siblings()
|
|n| n.is_htmltablerowelement())
|
||||||
.filter_map(ElementCast::to_root)
|
|
||||||
.filter(|n| n.is_htmltablerowelement())
|
|
||||||
.next()) {
|
|
||||||
Some(element) => element,
|
|
||||||
None => return Ok(()),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
index => match self.Rows().Item(index as u32) {
|
|
||||||
Some(element) => element,
|
|
||||||
None => return Err(Error::IndexSize),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
NodeCast::from_ref(element.r()).remove_self();
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,13 @@ use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||||
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
|
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
|
use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
|
||||||
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods};
|
use dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods};
|
||||||
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
|
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
|
||||||
use dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
|
use dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
|
||||||
|
use dom::bindings::codegen::InheritTypes::HTMLElementBase;
|
||||||
|
use dom::bindings::codegen::InheritTypes::HTMLElementCast;
|
||||||
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, CharacterDataTypeId};
|
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, CharacterDataTypeId};
|
||||||
use dom::bindings::codegen::InheritTypes::{DocumentCast, DocumentDerived, DocumentTypeCast};
|
use dom::bindings::codegen::InheritTypes::{DocumentCast, DocumentDerived, DocumentTypeCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, ElementTypeId};
|
use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, ElementTypeId};
|
||||||
|
@ -43,6 +46,8 @@ use dom::documentfragment::DocumentFragment;
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::element::{Element, ElementCreator};
|
use dom::element::{Element, ElementCreator};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
|
use dom::htmlcollection::HTMLCollection;
|
||||||
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::nodelist::NodeList;
|
use dom::nodelist::NodeList;
|
||||||
use dom::processinginstruction::ProcessingInstruction;
|
use dom::processinginstruction::ProcessingInstruction;
|
||||||
use dom::text::Text;
|
use dom::text::Text;
|
||||||
|
@ -60,7 +65,7 @@ use selectors::parser::parse_author_origin_selector_list_from_str;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, Ref, RefCell, RefMut};
|
use std::cell::{Cell, Ref, RefCell, RefMut};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::iter::{FilterMap, Peekable};
|
use std::iter::{self, FilterMap, Peekable};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::slice::ref_slice;
|
use std::slice::ref_slice;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -918,6 +923,66 @@ impl Node {
|
||||||
}
|
}
|
||||||
Ok(fragment)
|
Ok(fragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used by `HTMLTableSectionElement::InsertRow` and `HTMLTableRowElement::InsertCell`
|
||||||
|
pub fn insert_cell_or_row<F, G, I>(&self, index: i32, get_items: F, new_child: G) -> Fallible<Root<HTMLElement>>
|
||||||
|
where F: Fn() -> Root<HTMLCollection>,
|
||||||
|
G: Fn() -> Root<I>,
|
||||||
|
I: NodeBase + HTMLElementBase + Reflectable,
|
||||||
|
{
|
||||||
|
if index < -1 {
|
||||||
|
return Err(Error::IndexSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tr = new_child();
|
||||||
|
|
||||||
|
let after_node = if index == -1 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
match get_items().elements_iter()
|
||||||
|
.map(NodeCast::from_root)
|
||||||
|
.map(Some)
|
||||||
|
.chain(iter::once(None))
|
||||||
|
.nth(index as usize) {
|
||||||
|
None => return Err(Error::IndexSize),
|
||||||
|
Some(node) => node,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let tr_node = NodeCast::from_ref(tr.r());
|
||||||
|
try!(self.InsertBefore(tr_node, after_node.r()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(HTMLElementCast::from_root(tr))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used by `HTMLTableSectionElement::DeleteRow` and `HTMLTableRowElement::DeleteCell`
|
||||||
|
pub fn delete_cell_or_row<F, G>(&self, index: i32, get_items: F, is_delete_type: G) -> ErrorResult
|
||||||
|
where F: Fn() -> Root<HTMLCollection>,
|
||||||
|
G: Fn(&Element) -> bool
|
||||||
|
{
|
||||||
|
let element = match index {
|
||||||
|
index if index < -1 => return Err(Error::IndexSize),
|
||||||
|
-1 => {
|
||||||
|
let last_child = NodeCast::from_ref(self).GetLastChild();
|
||||||
|
match last_child.and_then(|node| node.inclusively_preceding_siblings()
|
||||||
|
.filter_map(ElementCast::to_root)
|
||||||
|
.filter(|elem| is_delete_type(elem))
|
||||||
|
.next()) {
|
||||||
|
Some(element) => element,
|
||||||
|
None => return Ok(()),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index => match get_items().Item(index as u32) {
|
||||||
|
Some(element) => element,
|
||||||
|
None => return Err(Error::IndexSize),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeCast::from_ref(element.r()).remove_self();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,10 @@ interface HTMLTableRowElement : HTMLElement {
|
||||||
//readonly attribute long rowIndex;
|
//readonly attribute long rowIndex;
|
||||||
//readonly attribute long sectionRowIndex;
|
//readonly attribute long sectionRowIndex;
|
||||||
readonly attribute HTMLCollection cells;
|
readonly attribute HTMLCollection cells;
|
||||||
//HTMLElement insertCell(optional long index = -1);
|
[Throws]
|
||||||
//void deleteCell(long index);
|
HTMLElement insertCell(optional long index = -1);
|
||||||
|
[Throws]
|
||||||
|
void deleteCell(long index);
|
||||||
|
|
||||||
// also has obsolete members
|
// also has obsolete members
|
||||||
};
|
};
|
||||||
|
|
|
@ -4707,12 +4707,6 @@
|
||||||
[HTMLTableRowElement interface: attribute sectionRowIndex]
|
[HTMLTableRowElement interface: attribute sectionRowIndex]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLTableRowElement interface: operation insertCell(long)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement interface: operation deleteCell(long)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement interface: attribute align]
|
[HTMLTableRowElement interface: attribute align]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -4731,18 +4725,6 @@
|
||||||
[HTMLTableRowElement interface: document.createElement("tr") must inherit property "sectionRowIndex" with the proper type (1)]
|
[HTMLTableRowElement interface: document.createElement("tr") must inherit property "sectionRowIndex" with the proper type (1)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLTableRowElement interface: document.createElement("tr") must inherit property "insertCell" with the proper type (3)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement interface: calling insertCell(long) on document.createElement("tr") with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement interface: document.createElement("tr") must inherit property "deleteCell" with the proper type (4)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement interface: calling deleteCell(long) on document.createElement("tr") with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement interface: document.createElement("tr") must inherit property "align" with the proper type (5)]
|
[HTMLTableRowElement interface: document.createElement("tr") must inherit property "align" with the proper type (5)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
[deleteCell.html]
|
|
||||||
type: testharness
|
|
||||||
[HTMLTableRowElement deleteCell(0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement deleteCell(-1)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement deleteCell(-2)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement deleteCell(cells.length)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
[insertCell.html]
|
|
||||||
type: testharness
|
|
||||||
[HTMLTableRowElement insertCell(0)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement insertCell(-1)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement insertCell(cells.length)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement insertCell()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement insertCell(-2)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableRowElement insertCell(cells.length + 1)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -43,4 +43,12 @@ test(function () {
|
||||||
});
|
});
|
||||||
}, "HTMLTableRowElement deleteCell(cells.length)");
|
}, "HTMLTableRowElement deleteCell(cells.length)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
assert_equals(tr.cells.length, 1);
|
||||||
|
tr.deleteCell(-1);
|
||||||
|
assert_equals(tr.cells.length, 0);
|
||||||
|
tr.deleteCell(-1);
|
||||||
|
assert_equals(tr.cells.length, 0);
|
||||||
|
}, "HTMLTableRowElement deleteCell(-1) with no cells");
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue