aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/range.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/range.rs')
-rw-r--r--components/script/dom/range.rs95
1 files changed, 91 insertions, 4 deletions
diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs
index 78f1e9ba6ab..e94fd2d9e9f 100644
--- a/components/script/dom/range.rs
+++ b/components/script/dom/range.rs
@@ -4,17 +4,20 @@
use dom::bindings::codegen::Bindings::NodeBinding::NodeConstants;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
+use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::codegen::Bindings::RangeBinding::{self, RangeConstants};
use dom::bindings::codegen::Bindings::RangeBinding::RangeMethods;
+use dom::bindings::codegen::Bindings::TextBinding::TextMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use dom::bindings::codegen::InheritTypes::NodeCast;
+use dom::bindings::codegen::InheritTypes::{NodeCast, TextCast};
use dom::bindings::error::{Error, ErrorResult, Fallible};
+use dom::bindings::error::Error::HierarchyRequest;
use dom::bindings::global::GlobalRef;
-use dom::bindings::js::{JS, Root};
+use dom::bindings::js::{JS, Root, RootedReference};
use dom::bindings::utils::{Reflector, reflect_dom_object};
+use dom::characterdata::CharacterDataTypeId;
use dom::document::{Document, DocumentHelpers};
-use dom::node::{Node, NodeHelpers};
-
+use dom::node::{Node, NodeHelpers, NodeTypeId};
use std::cell::RefCell;
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
use std::rc::Rc;
@@ -288,6 +291,90 @@ impl<'a> RangeMethods for &'a Range {
fn Detach(self) {
// This method intentionally left blank.
}
+
+ // https://dom.spec.whatwg.org/#dom-range-insertnode
+ // https://dom.spec.whatwg.org/#concept-range-insert
+ fn InsertNode(self, node: &Node) -> ErrorResult {
+ let (start_node, start_offset) = {
+ let inner = self.inner().borrow();
+ let start = &inner.start;
+ (start.node(), start.offset())
+ };
+
+ // Step 1.
+ match start_node.type_id() {
+ // Handled under step 2.
+ NodeTypeId::CharacterData(CharacterDataTypeId::Text) => (),
+ NodeTypeId::CharacterData(_) => return Err(HierarchyRequest),
+ _ => ()
+ }
+
+ // Step 2.
+ let (reference_node, parent) =
+ if start_node.type_id() == NodeTypeId::CharacterData(CharacterDataTypeId::Text) {
+ // Step 3.
+ let parent = match start_node.GetParentNode() {
+ Some(parent) => parent,
+ // Step 1.
+ None => return Err(HierarchyRequest)
+ };
+ // Step 5.
+ (Some(Root::from_ref(start_node.r())), parent)
+ } else {
+ // Steps 4-5.
+ let child = start_node.ChildNodes().Item(start_offset);
+ (child, Root::from_ref(start_node.r()))
+ };
+
+ // Step 6.
+ try!(Node::ensure_pre_insertion_validity(node,
+ parent.r(),
+ reference_node.r()));
+
+ // Step 7.
+ let split_text;
+ let reference_node =
+ match TextCast::to_ref(start_node.r()) {
+ Some(text) => {
+ split_text = try!(text.SplitText(start_offset));
+ let new_reference = NodeCast::from_root(split_text);
+ assert!(new_reference.GetParentNode().r() == Some(parent.r()));
+ Some(new_reference)
+ },
+ _ => reference_node
+ };
+
+ // Step 8.
+ let reference_node = if Some(node) == reference_node.r() {
+ node.GetNextSibling()
+ } else {
+ reference_node
+ };
+
+ // Step 9.
+ node.remove_self();
+
+ // Step 10.
+ let new_offset =
+ reference_node.r().map_or(parent.len(), |node| node.index());
+
+ // Step 11
+ let new_offset = new_offset + if node.type_id() == NodeTypeId::DocumentFragment {
+ node.len()
+ } else {
+ 1
+ };
+
+ // Step 12.
+ try!(Node::pre_insert(node, parent.r(), reference_node.r()));
+
+ // Step 13.
+ if self.Collapsed() {
+ self.inner().borrow_mut().set_end(parent.r(), new_offset);
+ }
+
+ Ok(())
+ }
}
#[derive(JSTraceable)]