diff --git a/manipulation.go b/manipulation.go index 699aa79..152d9d0 100644 --- a/manipulation.go +++ b/manipulation.go @@ -79,6 +79,47 @@ func (s *Selection) manipulateNodes( return s } +// From the root document, apply the selector, and insert the matched elements +// after element in the set of matched elements. +// +// If one of the matched elements in the selection is not currently in the +// document, it's impossible to insert nodes after it, so it will be ignored. +// +// This follows the same rules as Selection.Append(). +func (s *Selection) After(selector string) *Selection { + return s.AfterSelector(cascadia.MustCompile(selector)) +} + +// From the root document, apply the cascadia selector, and insert the matched +// elements after each element in the set of matched elements. +// This follows the same rules as Selection.After(). +func (s *Selection) AfterSelector(cs cascadia.Selector) *Selection { + return s.AfterNodes(cs.MatchAll(s.document.rootNode)...) +} + +// Insert the elements in the selection after each element in the set of matched +// elements. +// This follows the same rules as Selection.After(). +func (s *Selection) AfterSelection(sel *Selection) *Selection { + return s.AfterNodes(sel.Nodes...) +} + +// Parse the html and insert it after the set of matched elements +// This follows the same rules as Selection.After(). +func (s *Selection) AfterHtml(html string) *Selection { + return s.AfterSelection(parseHtml(html)) +} + +// Insert the nodes after each element in the set of matched elements. +// This follows the same rules as Selection.After(). +func (s *Selection) AfterNodes(ns ...*html.Node) *Selection { + return s.manipulateNodes(ns, true, func(sn *html.Node, n *html.Node) { + if sn.Parent != nil { + sn.Parent.InsertBefore(n, sn.NextSibling) + } + }) +} + // Append the elements, specified by the selector, to the end of each element // in the set of matched elements. // diff --git a/manipulation_test.go b/manipulation_test.go index 85c34a6..227e3f4 100644 --- a/manipulation_test.go +++ b/manipulation_test.go @@ -4,6 +4,40 @@ import ( "testing" ) +func TestAfter(t *testing.T) { + doc := Doc2Clone() + doc.Find("#main").After("#nf6") + + AssertLength(t, doc.Find("#main #nf6").Nodes, 0) + AssertLength(t, doc.Find("#foot #nf6").Nodes, 0) + AssertLength(t, doc.Find("#main + #nf6").Nodes, 1) +} + +func TestAfterWithRemoved(t *testing.T) { + doc := Doc2Clone() + s := doc.Find("#main").Remove() + s.After("#nf6") + + AssertLength(t, s.Find("#nf6").Nodes, 0) + AssertLength(t, doc.Find("#nf6").Nodes, 0) +} + +func TestAfterSelection(t *testing.T) { + doc := Doc2Clone() + doc.Find("#main").AfterSelection(doc.Find("#nf1, #nf2")) + + AssertLength(t, doc.Find("#main #nf1, #main #nf2").Nodes, 0) + AssertLength(t, doc.Find("#foot #nf1, #foot #nf2").Nodes, 0) + AssertLength(t, doc.Find("#main + #nf1, #nf1 + #nf2").Nodes, 2) +} + +func TestAfterHtml(t *testing.T) { + doc := Doc2Clone() + doc.Find("#main").AfterHtml("new node") + + AssertLength(t, doc.Find("#main + strong").Nodes, 1) +} + func TestAppend(t *testing.T) { doc := Doc2Clone() doc.Find("#main").Append("#nf6")