Implement insertBefore and reimplement appendChild.

This commit is contained in:
Ms2ger 2013-10-25 20:04:05 +02:00
parent 2c3d5ec79f
commit 2ca1eede9a
5 changed files with 175 additions and 52 deletions

View file

@ -455,6 +455,12 @@ impl<'self, View> AbstractNode<View> {
}
}
impl AbstractNode<ScriptView> {
pub fn AppendChild(self, node: AbstractNode<ScriptView>) -> Fallible<AbstractNode<ScriptView>> {
self.node().AppendChild(self, node)
}
}
impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
fn next(&mut self) -> Option<AbstractNode<View>> {
let node = self.current_node;
@ -691,6 +697,129 @@ impl Node<ScriptView> {
}
}
// http://dom.spec.whatwg.org/#concept-node-adopt
pub fn adopt(node: AbstractNode<ScriptView>,
document: AbstractDocument) {
// Step 1.
match node.parent_node() {
Some(parent) => parent.remove_child(node),
None => (),
}
// Step 2.
if node.node().owner_doc() != document {
for descendant in node.traverse_preorder() {
descendant.mut_node().set_owner_doc(document);
}
}
// Step 3.
// If node is an element, it is _affected by a base URL change_.
}
// http://dom.spec.whatwg.org/#concept-node-pre-insert
pub fn pre_insert(node: AbstractNode<ScriptView>,
parent: AbstractNode<ScriptView>,
child: Option<AbstractNode<ScriptView>>) -> Fallible<AbstractNode<ScriptView>> {
fn is_inclusive_ancestor_of(node: AbstractNode<ScriptView>,
parent: AbstractNode<ScriptView>) -> bool {
node == parent || parent.ancestors().any(|ancestor| ancestor == node)
}
// Step 1.
match parent.type_id() {
// DocumentNodeTypeId |
DocumentFragmentNodeTypeId |
ElementNodeTypeId(*) => (),
_ => {
return Err(HierarchyRequest);
},
}
// Step 2.
if is_inclusive_ancestor_of(node, parent) {
return Err(HierarchyRequest);
}
// Step 3.
match child {
Some(child) => {
if child.parent_node() != Some(parent) {
return Err(NotFound);
}
},
None => (),
}
// Step 4.
match node.type_id() {
DocumentFragmentNodeTypeId |
DoctypeNodeTypeId |
ElementNodeTypeId(_) |
TextNodeTypeId |
// ProcessingInstructionNodeTypeId |
CommentNodeTypeId => (),
/*_ => { XXX #838
return Err(HierarchyRequest);
},*/
}
// Step 5.
match node.type_id() {
TextNodeTypeId => {
if false { // XXX #838
return Err(HierarchyRequest);
}
},
DoctypeNodeTypeId => {
if true { // XXX #838
return Err(HierarchyRequest);
}
},
_ => (),
}
// Step 6.
// XXX #838
// Step 7-8.
let referenceChild = if child != Some(node) {
child
} else {
node.next_sibling()
};
// Step 9.
Node::adopt(node, parent.node().owner_doc());
// Step 10.
Node::insert(node, parent, referenceChild, false);
// Step 11.
return Ok(node)
}
pub fn insert(node: AbstractNode<ScriptView>,
parent: AbstractNode<ScriptView>,
child: Option<AbstractNode<ScriptView>>,
_suppressObserversFlag: bool) {
// Step 1-3: ranges.
// Step 4.
let nodes = match node.type_id() {
DocumentFragmentNodeTypeId => node.children().collect(),
_ => ~[node],
};
// Step 5: DocumentFragment, mutation records.
// Step 6: DocumentFragment.
// Step 7: mutation records.
// Step 8.
for node in nodes.iter() {
parent.add_child(*node, child);
}
// Step 9: _node is inserted_.
}
// http://dom.spec.whatwg.org/#concept-node-replace-all
pub fn replace_all(&mut self,
abstract_self: AbstractNode<ScriptView>,
@ -740,8 +869,11 @@ impl Node<ScriptView> {
Ok(())
}
pub fn InsertBefore(&mut self, _node: AbstractNode<ScriptView>, _child: Option<AbstractNode<ScriptView>>) -> Fallible<AbstractNode<ScriptView>> {
fail!("stub")
pub fn InsertBefore(&self,
node: AbstractNode<ScriptView>,
child: Option<AbstractNode<ScriptView>>) -> Fallible<AbstractNode<ScriptView>> {
self.wait_until_safe_to_modify_dom();
return Node::pre_insert(node, node, child);
}
fn wait_until_safe_to_modify_dom(&self) {
@ -749,43 +881,11 @@ impl Node<ScriptView> {
document.document().wait_until_safe_to_modify_dom();
}
pub fn AppendChild(&mut self,
pub fn AppendChild(&self,
abstract_self: AbstractNode<ScriptView>,
node: AbstractNode<ScriptView>) -> Fallible<AbstractNode<ScriptView>> {
fn is_hierarchy_request_err(this_node: AbstractNode<ScriptView>,
new_child: AbstractNode<ScriptView>) -> bool {
if new_child.is_doctype() {
return true;
}
if !this_node.is_element() {
// FIXME: This should also work for Document and DocumentFragments when they inherit from node.
// per jgraham
return true;
}
if this_node == new_child {
return true;
}
for ancestor in this_node.ancestors() {
if ancestor == new_child {
return true;
}
}
false
}
if is_hierarchy_request_err(abstract_self, node) {
return Err(HierarchyRequest);
}
// TODO: Should we handle WRONG_DOCUMENT_ERR here?
self.wait_until_safe_to_modify_dom();
// If the node already exists it is removed from current parent node.
node.parent_node().map(|parent| parent.remove_child(node));
abstract_self.add_child(node);
node.mut_node().add_to_doc(node, self.owner_doc());
Ok(node)
return Node::pre_insert(node, abstract_self, None);
}
pub fn ReplaceChild(&mut self, _node: AbstractNode<ScriptView>, _child: AbstractNode<ScriptView>) -> Fallible<AbstractNode<ScriptView>> {