diff --git a/property.go b/property.go index 98e895e..beabc5d 100644 --- a/property.go +++ b/property.go @@ -1,13 +1,12 @@ package goquery import ( - "regexp" "strings" "golang.org/x/net/html" ) -var rxClassTrim = regexp.MustCompile("[\t\r\n]") +var classTrimReplacer = strings.NewReplacer("\t", " ", "\r", " ", "\n", " ") // Attr gets the specified attribute's value for the first element in the // Selection. To get the value for each element individually, use a looping @@ -140,9 +139,14 @@ func (s *Selection) AddClass(class ...string) *Selection { func (s *Selection) HasClass(class string) bool { class = " " + class + " " for _, n := range s.Nodes { - classes, _ := getClassesAndAttr(n, false) - if strings.Contains(classes, class) { - return true + if n.Type != html.ElementNode { + continue + } + if attr := getAttributePtr("class", n); attr != nil { + val := classTrimReplacer.Replace(attr.Val) + if strings.Contains(" "+val+" ", class) { + return true + } } } return false @@ -243,10 +247,8 @@ func getClassesAndAttr(n *html.Node, create bool) (classes string, attr *html.At if attr == nil { classes = " " - } else if strings.ContainsAny(attr.Val, "\t\r\n") { - classes = rxClassTrim.ReplaceAllString(" "+attr.Val+" ", " ") } else { - classes = " " + attr.Val + " " + classes = classTrimReplacer.Replace(" " + attr.Val + " ") } return diff --git a/query.go b/query.go index fe86bf0..293afeb 100644 --- a/query.go +++ b/query.go @@ -24,19 +24,32 @@ func (s *Selection) IsMatcher(m Matcher) bool { // IsFunction checks the current matched set of elements against a predicate and // returns true if at least one of these elements matches. func (s *Selection) IsFunction(f func(int, *Selection) bool) bool { - return s.FilterFunction(f).Length() > 0 + for i, n := range s.Nodes { + if f(i, newSingleSelection(n, s.document)) { + return true + } + } + return false } // IsSelection checks the current matched set of elements against a Selection object // and returns true if at least one of these elements matches. func (s *Selection) IsSelection(sel *Selection) bool { - return s.FilterSelection(sel).Length() > 0 + if sel == nil { + return false + } + return s.IsNodes(sel.Nodes...) } // IsNodes checks the current matched set of elements against the specified nodes // and returns true if at least one of these elements matches. func (s *Selection) IsNodes(nodes ...*html.Node) bool { - return s.FilterNodes(nodes...).Length() > 0 + for _, n := range s.Nodes { + if isInSlice(nodes, n) { + return true + } + } + return false } // Contains returns true if the specified Node is within, diff --git a/traversal.go b/traversal.go index c45fa5d..46bac05 100644 --- a/traversal.go +++ b/traversal.go @@ -562,13 +562,12 @@ func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node { func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node { return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) { for p := n.Parent; p != nil; p = p.Parent { - sel := newSingleSelection(p, nil) if stopm != nil { - if sel.IsMatcher(stopm) { + if stopm.Match(p) { break } } else if len(stopNodes) > 0 { - if sel.IsNodes(stopNodes...) { + if isInSlice(stopNodes, p) { break } } @@ -589,13 +588,9 @@ func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNo if st == siblingNextUntil || st == siblingPrevUntil { f = func(n *html.Node) bool { if untilm != nil { - // Matcher-based condition - sel := newSingleSelection(n, nil) - return sel.IsMatcher(untilm) + return untilm.Match(n) } else if len(untilNodes) > 0 { - // Nodes-based condition - sel := newSingleSelection(n, nil) - return sel.IsNodes(untilNodes...) + return isInSlice(untilNodes, n) } return false }