servo: Merge #10508 - Insert row (from g-k:insert-row); r=KiChjang
authorGreg Guthe <greg.guthe@gmail.com>
Tue, 19 Apr 2016 01:09:08 +0500
changeset 338559 4036fbc9a7134ae10955fb3aeaf2675d96f0cc18
parent 338558 e32a38b3ab57dc9d4923ec2dc6eabc7c3f626559
child 338560 e3a795622528b092c2af6a7e3c29e867d04e0382
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersKiChjang
servo: Merge #10508 - Insert row (from g-k:insert-row); r=KiChjang Fixes #9269 Source-Repo: https://github.com/servo/servo Source-Revision: 19a5a9ad081548b1ca03a1ce98857c32be5404b1
servo/components/script/dom/htmltableelement.rs
servo/components/script/dom/webidls/HTMLTableElement.webidl
--- a/servo/components/script/dom/htmltableelement.rs
+++ b/servo/components/script/dom/htmltableelement.rs
@@ -1,18 +1,19 @@
 /* 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 http://mozilla.org/MPL/2.0/. */
 
 use cssparser::RGBA;
 use dom::attr::{Attr, AttrValue};
+use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
 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::error::{Error, ErrorResult, Fallible};
 use dom::bindings::inheritance::Castable;
 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;
@@ -161,28 +162,27 @@ impl HTMLTableElementMethods for HTMLTab
         if let Some(caption) = new_caption {
             let node = self.upcast::<Node>();
             node.InsertBefore(caption.upcast(), node.GetFirstChild().r())
                 .expect("Insertion failed");
         }
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-table-createcaption
-    fn CreateCaption(&self) -> Root<HTMLElement> {
-        let caption = match self.GetCaption() {
+    fn CreateCaption(&self) -> Root<HTMLTableCaptionElement> {
+        match self.GetCaption() {
             Some(caption) => caption,
             None => {
                 let caption = HTMLTableCaptionElement::new(atom!("caption"),
                                                            None,
                                                            document_from_node(self).r());
                 self.SetCaption(Some(caption.r()));
                 caption
             }
-        };
-        Root::upcast(caption)
+        }
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-table-deletecaption
     fn DeleteCaption(&self) {
         if let Some(caption) = self.GetCaption() {
             caption.upcast::<Node>().remove_self();
         }
     }
@@ -277,16 +277,71 @@ impl HTMLTableElementMethods for HTMLTab
         let reference_element =
             last_tbody.and_then(|t| t.upcast::<Node>().GetNextSibling());
 
         node.InsertBefore(tbody.upcast(), reference_element.r())
             .expect("Insertion failed");
         tbody
     }
 
+    // https://html.spec.whatwg.org/multipage/#dom-table-insertrow
+    fn InsertRow(&self, index: i32) -> Fallible<Root<HTMLTableRowElement>> {
+        let rows = self.Rows();
+        let number_of_row_elements = rows.Length();
+
+        if index < -1 || index > number_of_row_elements as i32 {
+            return Err(Error::IndexSize);
+        }
+
+        let new_row = HTMLTableRowElement::new(atom!("tr"),
+                                               None,
+                                               document_from_node(self).r());
+        let node = self.upcast::<Node>();
+
+        if number_of_row_elements == 0 {
+            // append new row to last or new tbody in table
+            if let Some(last_tbody) = node.rev_children()
+                .filter_map(Root::downcast::<Element>)
+                .find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == &atom!("tbody")) {
+                    last_tbody.upcast::<Node>().AppendChild(new_row.upcast::<Node>())
+                                               .expect("InsertRow failed to append first row.");
+                } else {
+                    let tbody = self.CreateTBody();
+                    node.AppendChild(tbody.upcast())
+                        .expect("InsertRow failed to append new tbody.");
+
+                    tbody.upcast::<Node>().AppendChild(new_row.upcast::<Node>())
+                                          .expect("InsertRow failed to append first row.");
+                }
+        } else if index == number_of_row_elements as i32 || index == -1 {
+            // append new row to parent of last row in table
+            let last_row = rows.Item(number_of_row_elements - 1)
+                               .expect("InsertRow failed to find last row in table.");
+
+            let last_row_parent =
+                last_row.upcast::<Node>().GetParentNode()
+                        .expect("InsertRow failed to find parent of last row in table.");
+
+            last_row_parent.upcast::<Node>().AppendChild(new_row.upcast::<Node>())
+                                            .expect("InsertRow failed to append last row.");
+        } else {
+            // insert new row before the index-th row in rows using the same parent
+            let ith_row = rows.Item(index as u32)
+                              .expect("InsertRow failed to find a row in table.");
+
+            let ith_row_parent = ith_row.upcast::<Node>().GetParentNode()
+                                        .expect("InsertRow failed to find parent of a row in table.");
+
+            ith_row_parent.upcast::<Node>().InsertBefore(new_row.upcast::<Node>(), Some(ith_row.upcast::<Node>()))
+                                           .expect("InsertRow failed to append row");
+        }
+
+        Ok(new_row)
+    }
+
     // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
     make_getter!(BgColor, "bgcolor");
 
     // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
     make_legacy_color_setter!(SetBgColor, "bgcolor");
 
     // https://html.spec.whatwg.org/multipage/#dom-table-width
     make_getter!(Width, "width");
--- a/servo/components/script/dom/webidls/HTMLTableElement.webidl
+++ b/servo/components/script/dom/webidls/HTMLTableElement.webidl
@@ -1,33 +1,31 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 http://mozilla.org/MPL/2.0/. */
 
 // https://html.spec.whatwg.org/multipage/#htmltableelement
 interface HTMLTableElement : HTMLElement {
            attribute HTMLTableCaptionElement? caption;
-  HTMLElement createCaption();
+  HTMLTableCaptionElement createCaption();
   void deleteCaption();
   [SetterThrows]
            attribute HTMLTableSectionElement? tHead;
   HTMLTableSectionElement createTHead();
   void deleteTHead();
   [SetterThrows]
            attribute HTMLTableSectionElement? tFoot;
   HTMLTableSectionElement createTFoot();
   void deleteTFoot();
   readonly attribute HTMLCollection tBodies;
   HTMLTableSectionElement createTBody();
   readonly attribute HTMLCollection rows;
-  //HTMLElement insertRow(optional long index = -1);
+  [Throws] HTMLTableRowElement insertRow(optional long index = -1);
   //void deleteRow(long index);
-  //         attribute boolean sortable;
-  //void stopSorting();
 
   // also has obsolete members
 };
 
 // https://html.spec.whatwg.org/multipage/#HTMLTableElement-partial
 partial interface HTMLTableElement {
   //         attribute DOMString align;
   //         attribute DOMString border;