traversal.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. package goquery
  2. import "golang.org/x/net/html"
  3. type siblingType int
  4. // Sibling type, used internally when iterating over children at the same
  5. // level (siblings) to specify which nodes are requested.
  6. const (
  7. siblingPrevUntil siblingType = iota - 3
  8. siblingPrevAll
  9. siblingPrev
  10. siblingAll
  11. siblingNext
  12. siblingNextAll
  13. siblingNextUntil
  14. siblingAllIncludingNonElements
  15. )
  16. // Find gets the descendants of each element in the current set of matched
  17. // elements, filtered by a selector. It returns a new Selection object
  18. // containing these matched elements.
  19. func (s *Selection) Find(selector string) *Selection {
  20. return pushStack(s, findWithMatcher(s.Nodes, compileMatcher(selector)))
  21. }
  22. // FindMatcher gets the descendants of each element in the current set of matched
  23. // elements, filtered by the matcher. It returns a new Selection object
  24. // containing these matched elements.
  25. func (s *Selection) FindMatcher(m Matcher) *Selection {
  26. return pushStack(s, findWithMatcher(s.Nodes, m))
  27. }
  28. // FindSelection gets the descendants of each element in the current
  29. // Selection, filtered by a Selection. It returns a new Selection object
  30. // containing these matched elements.
  31. func (s *Selection) FindSelection(sel *Selection) *Selection {
  32. if sel == nil {
  33. return pushStack(s, nil)
  34. }
  35. return s.FindNodes(sel.Nodes...)
  36. }
  37. // FindNodes gets the descendants of each element in the current
  38. // Selection, filtered by some nodes. It returns a new Selection object
  39. // containing these matched elements.
  40. func (s *Selection) FindNodes(nodes ...*html.Node) *Selection {
  41. return pushStack(s, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
  42. if sliceContains(s.Nodes, n) {
  43. return []*html.Node{n}
  44. }
  45. return nil
  46. }))
  47. }
  48. // Contents gets the children of each element in the Selection,
  49. // including text and comment nodes. It returns a new Selection object
  50. // containing these elements.
  51. func (s *Selection) Contents() *Selection {
  52. return pushStack(s, getChildrenNodes(s.Nodes, siblingAllIncludingNonElements))
  53. }
  54. // ContentsFiltered gets the children of each element in the Selection,
  55. // filtered by the specified selector. It returns a new Selection
  56. // object containing these elements. Since selectors only act on Element nodes,
  57. // this function is an alias to ChildrenFiltered unless the selector is empty,
  58. // in which case it is an alias to Contents.
  59. func (s *Selection) ContentsFiltered(selector string) *Selection {
  60. if selector != "" {
  61. return s.ChildrenFiltered(selector)
  62. }
  63. return s.Contents()
  64. }
  65. // ContentsMatcher gets the children of each element in the Selection,
  66. // filtered by the specified matcher. It returns a new Selection
  67. // object containing these elements. Since matchers only act on Element nodes,
  68. // this function is an alias to ChildrenMatcher.
  69. func (s *Selection) ContentsMatcher(m Matcher) *Selection {
  70. return s.ChildrenMatcher(m)
  71. }
  72. // Children gets the child elements of each element in the Selection.
  73. // It returns a new Selection object containing these elements.
  74. func (s *Selection) Children() *Selection {
  75. return pushStack(s, getChildrenNodes(s.Nodes, siblingAll))
  76. }
  77. // ChildrenFiltered gets the child elements of each element in the Selection,
  78. // filtered by the specified selector. It returns a new
  79. // Selection object containing these elements.
  80. func (s *Selection) ChildrenFiltered(selector string) *Selection {
  81. return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), compileMatcher(selector))
  82. }
  83. // ChildrenMatcher gets the child elements of each element in the Selection,
  84. // filtered by the specified matcher. It returns a new
  85. // Selection object containing these elements.
  86. func (s *Selection) ChildrenMatcher(m Matcher) *Selection {
  87. return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), m)
  88. }
  89. // Parent gets the parent of each element in the Selection. It returns a
  90. // new Selection object containing the matched elements.
  91. func (s *Selection) Parent() *Selection {
  92. return pushStack(s, getParentNodes(s.Nodes))
  93. }
  94. // ParentFiltered gets the parent of each element in the Selection filtered by a
  95. // selector. It returns a new Selection object containing the matched elements.
  96. func (s *Selection) ParentFiltered(selector string) *Selection {
  97. return filterAndPush(s, getParentNodes(s.Nodes), compileMatcher(selector))
  98. }
  99. // ParentMatcher gets the parent of each element in the Selection filtered by a
  100. // matcher. It returns a new Selection object containing the matched elements.
  101. func (s *Selection) ParentMatcher(m Matcher) *Selection {
  102. return filterAndPush(s, getParentNodes(s.Nodes), m)
  103. }
  104. // Closest gets the first element that matches the selector by testing the
  105. // element itself and traversing up through its ancestors in the DOM tree.
  106. func (s *Selection) Closest(selector string) *Selection {
  107. cs := compileMatcher(selector)
  108. return s.ClosestMatcher(cs)
  109. }
  110. // ClosestMatcher gets the first element that matches the matcher by testing the
  111. // element itself and traversing up through its ancestors in the DOM tree.
  112. func (s *Selection) ClosestMatcher(m Matcher) *Selection {
  113. return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
  114. // For each node in the selection, test the node itself, then each parent
  115. // until a match is found.
  116. for ; n != nil; n = n.Parent {
  117. if m.Match(n) {
  118. return []*html.Node{n}
  119. }
  120. }
  121. return nil
  122. }))
  123. }
  124. // ClosestNodes gets the first element that matches one of the nodes by testing the
  125. // element itself and traversing up through its ancestors in the DOM tree.
  126. func (s *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
  127. set := make(map[*html.Node]bool)
  128. for _, n := range nodes {
  129. set[n] = true
  130. }
  131. return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
  132. // For each node in the selection, test the node itself, then each parent
  133. // until a match is found.
  134. for ; n != nil; n = n.Parent {
  135. if set[n] {
  136. return []*html.Node{n}
  137. }
  138. }
  139. return nil
  140. }))
  141. }
  142. // ClosestSelection gets the first element that matches one of the nodes in the
  143. // Selection by testing the element itself and traversing up through its ancestors
  144. // in the DOM tree.
  145. func (s *Selection) ClosestSelection(sel *Selection) *Selection {
  146. if sel == nil {
  147. return pushStack(s, nil)
  148. }
  149. return s.ClosestNodes(sel.Nodes...)
  150. }
  151. // Parents gets the ancestors of each element in the current Selection. It
  152. // returns a new Selection object with the matched elements.
  153. func (s *Selection) Parents() *Selection {
  154. return pushStack(s, getParentsNodes(s.Nodes, nil, nil))
  155. }
  156. // ParentsFiltered gets the ancestors of each element in the current
  157. // Selection. It returns a new Selection object with the matched elements.
  158. func (s *Selection) ParentsFiltered(selector string) *Selection {
  159. return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), compileMatcher(selector))
  160. }
  161. // ParentsMatcher gets the ancestors of each element in the current
  162. // Selection. It returns a new Selection object with the matched elements.
  163. func (s *Selection) ParentsMatcher(m Matcher) *Selection {
  164. return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), m)
  165. }
  166. // ParentsUntil gets the ancestors of each element in the Selection, up to but
  167. // not including the element matched by the selector. It returns a new Selection
  168. // object containing the matched elements.
  169. func (s *Selection) ParentsUntil(selector string) *Selection {
  170. return pushStack(s, getParentsNodes(s.Nodes, compileMatcher(selector), nil))
  171. }
  172. // ParentsUntilMatcher gets the ancestors of each element in the Selection, up to but
  173. // not including the element matched by the matcher. It returns a new Selection
  174. // object containing the matched elements.
  175. func (s *Selection) ParentsUntilMatcher(m Matcher) *Selection {
  176. return pushStack(s, getParentsNodes(s.Nodes, m, nil))
  177. }
  178. // ParentsUntilSelection gets the ancestors of each element in the Selection,
  179. // up to but not including the elements in the specified Selection. It returns a
  180. // new Selection object containing the matched elements.
  181. func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
  182. if sel == nil {
  183. return s.Parents()
  184. }
  185. return s.ParentsUntilNodes(sel.Nodes...)
  186. }
  187. // ParentsUntilNodes gets the ancestors of each element in the Selection,
  188. // up to but not including the specified nodes. It returns a
  189. // new Selection object containing the matched elements.
  190. func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
  191. return pushStack(s, getParentsNodes(s.Nodes, nil, nodes))
  192. }
  193. // ParentsFilteredUntil is like ParentsUntil, with the option to filter the
  194. // results based on a selector string. It returns a new Selection
  195. // object containing the matched elements.
  196. func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
  197. return filterAndPush(s, getParentsNodes(s.Nodes, compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
  198. }
  199. // ParentsFilteredUntilMatcher is like ParentsUntilMatcher, with the option to filter the
  200. // results based on a matcher. It returns a new Selection object containing the matched elements.
  201. func (s *Selection) ParentsFilteredUntilMatcher(filter, until Matcher) *Selection {
  202. return filterAndPush(s, getParentsNodes(s.Nodes, until, nil), filter)
  203. }
  204. // ParentsFilteredUntilSelection is like ParentsUntilSelection, with the
  205. // option to filter the results based on a selector string. It returns a new
  206. // Selection object containing the matched elements.
  207. func (s *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
  208. return s.ParentsMatcherUntilSelection(compileMatcher(filterSelector), sel)
  209. }
  210. // ParentsMatcherUntilSelection is like ParentsUntilSelection, with the
  211. // option to filter the results based on a matcher. It returns a new
  212. // Selection object containing the matched elements.
  213. func (s *Selection) ParentsMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
  214. if sel == nil {
  215. return s.ParentsMatcher(filter)
  216. }
  217. return s.ParentsMatcherUntilNodes(filter, sel.Nodes...)
  218. }
  219. // ParentsFilteredUntilNodes is like ParentsUntilNodes, with the
  220. // option to filter the results based on a selector string. It returns a new
  221. // Selection object containing the matched elements.
  222. func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
  223. return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), compileMatcher(filterSelector))
  224. }
  225. // ParentsMatcherUntilNodes is like ParentsUntilNodes, with the
  226. // option to filter the results based on a matcher. It returns a new
  227. // Selection object containing the matched elements.
  228. func (s *Selection) ParentsMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
  229. return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), filter)
  230. }
  231. // Siblings gets the siblings of each element in the Selection. It returns
  232. // a new Selection object containing the matched elements.
  233. func (s *Selection) Siblings() *Selection {
  234. return pushStack(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil))
  235. }
  236. // SiblingsFiltered gets the siblings of each element in the Selection
  237. // filtered by a selector. It returns a new Selection object containing the
  238. // matched elements.
  239. func (s *Selection) SiblingsFiltered(selector string) *Selection {
  240. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), compileMatcher(selector))
  241. }
  242. // SiblingsMatcher gets the siblings of each element in the Selection
  243. // filtered by a matcher. It returns a new Selection object containing the
  244. // matched elements.
  245. func (s *Selection) SiblingsMatcher(m Matcher) *Selection {
  246. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), m)
  247. }
  248. // Next gets the immediately following sibling of each element in the
  249. // Selection. It returns a new Selection object containing the matched elements.
  250. func (s *Selection) Next() *Selection {
  251. return pushStack(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil))
  252. }
  253. // NextFiltered gets the immediately following sibling of each element in the
  254. // Selection filtered by a selector. It returns a new Selection object
  255. // containing the matched elements.
  256. func (s *Selection) NextFiltered(selector string) *Selection {
  257. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), compileMatcher(selector))
  258. }
  259. // NextMatcher gets the immediately following sibling of each element in the
  260. // Selection filtered by a matcher. It returns a new Selection object
  261. // containing the matched elements.
  262. func (s *Selection) NextMatcher(m Matcher) *Selection {
  263. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), m)
  264. }
  265. // NextAll gets all the following siblings of each element in the
  266. // Selection. It returns a new Selection object containing the matched elements.
  267. func (s *Selection) NextAll() *Selection {
  268. return pushStack(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil))
  269. }
  270. // NextAllFiltered gets all the following siblings of each element in the
  271. // Selection filtered by a selector. It returns a new Selection object
  272. // containing the matched elements.
  273. func (s *Selection) NextAllFiltered(selector string) *Selection {
  274. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), compileMatcher(selector))
  275. }
  276. // NextAllMatcher gets all the following siblings of each element in the
  277. // Selection filtered by a matcher. It returns a new Selection object
  278. // containing the matched elements.
  279. func (s *Selection) NextAllMatcher(m Matcher) *Selection {
  280. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), m)
  281. }
  282. // Prev gets the immediately preceding sibling of each element in the
  283. // Selection. It returns a new Selection object containing the matched elements.
  284. func (s *Selection) Prev() *Selection {
  285. return pushStack(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil))
  286. }
  287. // PrevFiltered gets the immediately preceding sibling of each element in the
  288. // Selection filtered by a selector. It returns a new Selection object
  289. // containing the matched elements.
  290. func (s *Selection) PrevFiltered(selector string) *Selection {
  291. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), compileMatcher(selector))
  292. }
  293. // PrevMatcher gets the immediately preceding sibling of each element in the
  294. // Selection filtered by a matcher. It returns a new Selection object
  295. // containing the matched elements.
  296. func (s *Selection) PrevMatcher(m Matcher) *Selection {
  297. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), m)
  298. }
  299. // PrevAll gets all the preceding siblings of each element in the
  300. // Selection. It returns a new Selection object containing the matched elements.
  301. func (s *Selection) PrevAll() *Selection {
  302. return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil))
  303. }
  304. // PrevAllFiltered gets all the preceding siblings of each element in the
  305. // Selection filtered by a selector. It returns a new Selection object
  306. // containing the matched elements.
  307. func (s *Selection) PrevAllFiltered(selector string) *Selection {
  308. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), compileMatcher(selector))
  309. }
  310. // PrevAllMatcher gets all the preceding siblings of each element in the
  311. // Selection filtered by a matcher. It returns a new Selection object
  312. // containing the matched elements.
  313. func (s *Selection) PrevAllMatcher(m Matcher) *Selection {
  314. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), m)
  315. }
  316. // NextUntil gets all following siblings of each element up to but not
  317. // including the element matched by the selector. It returns a new Selection
  318. // object containing the matched elements.
  319. func (s *Selection) NextUntil(selector string) *Selection {
  320. return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
  321. compileMatcher(selector), nil))
  322. }
  323. // NextUntilMatcher gets all following siblings of each element up to but not
  324. // including the element matched by the matcher. It returns a new Selection
  325. // object containing the matched elements.
  326. func (s *Selection) NextUntilMatcher(m Matcher) *Selection {
  327. return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
  328. m, nil))
  329. }
  330. // NextUntilSelection gets all following siblings of each element up to but not
  331. // including the element matched by the Selection. It returns a new Selection
  332. // object containing the matched elements.
  333. func (s *Selection) NextUntilSelection(sel *Selection) *Selection {
  334. if sel == nil {
  335. return s.NextAll()
  336. }
  337. return s.NextUntilNodes(sel.Nodes...)
  338. }
  339. // NextUntilNodes gets all following siblings of each element up to but not
  340. // including the element matched by the nodes. It returns a new Selection
  341. // object containing the matched elements.
  342. func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
  343. return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
  344. nil, nodes))
  345. }
  346. // PrevUntil gets all preceding siblings of each element up to but not
  347. // including the element matched by the selector. It returns a new Selection
  348. // object containing the matched elements.
  349. func (s *Selection) PrevUntil(selector string) *Selection {
  350. return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
  351. compileMatcher(selector), nil))
  352. }
  353. // PrevUntilMatcher gets all preceding siblings of each element up to but not
  354. // including the element matched by the matcher. It returns a new Selection
  355. // object containing the matched elements.
  356. func (s *Selection) PrevUntilMatcher(m Matcher) *Selection {
  357. return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
  358. m, nil))
  359. }
  360. // PrevUntilSelection gets all preceding siblings of each element up to but not
  361. // including the element matched by the Selection. It returns a new Selection
  362. // object containing the matched elements.
  363. func (s *Selection) PrevUntilSelection(sel *Selection) *Selection {
  364. if sel == nil {
  365. return s.PrevAll()
  366. }
  367. return s.PrevUntilNodes(sel.Nodes...)
  368. }
  369. // PrevUntilNodes gets all preceding siblings of each element up to but not
  370. // including the element matched by the nodes. It returns a new Selection
  371. // object containing the matched elements.
  372. func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
  373. return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
  374. nil, nodes))
  375. }
  376. // NextFilteredUntil is like NextUntil, with the option to filter
  377. // the results based on a selector string.
  378. // It returns a new Selection object containing the matched elements.
  379. func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
  380. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
  381. compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
  382. }
  383. // NextFilteredUntilMatcher is like NextUntilMatcher, with the option to filter
  384. // the results based on a matcher.
  385. // It returns a new Selection object containing the matched elements.
  386. func (s *Selection) NextFilteredUntilMatcher(filter, until Matcher) *Selection {
  387. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
  388. until, nil), filter)
  389. }
  390. // NextFilteredUntilSelection is like NextUntilSelection, with the
  391. // option to filter the results based on a selector string. It returns a new
  392. // Selection object containing the matched elements.
  393. func (s *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
  394. return s.NextMatcherUntilSelection(compileMatcher(filterSelector), sel)
  395. }
  396. // NextMatcherUntilSelection is like NextUntilSelection, with the
  397. // option to filter the results based on a matcher. It returns a new
  398. // Selection object containing the matched elements.
  399. func (s *Selection) NextMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
  400. if sel == nil {
  401. return s.NextMatcher(filter)
  402. }
  403. return s.NextMatcherUntilNodes(filter, sel.Nodes...)
  404. }
  405. // NextFilteredUntilNodes is like NextUntilNodes, with the
  406. // option to filter the results based on a selector string. It returns a new
  407. // Selection object containing the matched elements.
  408. func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
  409. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
  410. nil, nodes), compileMatcher(filterSelector))
  411. }
  412. // NextMatcherUntilNodes is like NextUntilNodes, with the
  413. // option to filter the results based on a matcher. It returns a new
  414. // Selection object containing the matched elements.
  415. func (s *Selection) NextMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
  416. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
  417. nil, nodes), filter)
  418. }
  419. // PrevFilteredUntil is like PrevUntil, with the option to filter
  420. // the results based on a selector string.
  421. // It returns a new Selection object containing the matched elements.
  422. func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
  423. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
  424. compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
  425. }
  426. // PrevFilteredUntilMatcher is like PrevUntilMatcher, with the option to filter
  427. // the results based on a matcher.
  428. // It returns a new Selection object containing the matched elements.
  429. func (s *Selection) PrevFilteredUntilMatcher(filter, until Matcher) *Selection {
  430. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
  431. until, nil), filter)
  432. }
  433. // PrevFilteredUntilSelection is like PrevUntilSelection, with the
  434. // option to filter the results based on a selector string. It returns a new
  435. // Selection object containing the matched elements.
  436. func (s *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
  437. return s.PrevMatcherUntilSelection(compileMatcher(filterSelector), sel)
  438. }
  439. // PrevMatcherUntilSelection is like PrevUntilSelection, with the
  440. // option to filter the results based on a matcher. It returns a new
  441. // Selection object containing the matched elements.
  442. func (s *Selection) PrevMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
  443. if sel == nil {
  444. return s.PrevMatcher(filter)
  445. }
  446. return s.PrevMatcherUntilNodes(filter, sel.Nodes...)
  447. }
  448. // PrevFilteredUntilNodes is like PrevUntilNodes, with the
  449. // option to filter the results based on a selector string. It returns a new
  450. // Selection object containing the matched elements.
  451. func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
  452. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
  453. nil, nodes), compileMatcher(filterSelector))
  454. }
  455. // PrevMatcherUntilNodes is like PrevUntilNodes, with the
  456. // option to filter the results based on a matcher. It returns a new
  457. // Selection object containing the matched elements.
  458. func (s *Selection) PrevMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
  459. return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
  460. nil, nodes), filter)
  461. }
  462. // Filter and push filters the nodes based on a matcher, and pushes the results
  463. // on the stack, with the srcSel as previous selection.
  464. func filterAndPush(srcSel *Selection, nodes []*html.Node, m Matcher) *Selection {
  465. // Create a temporary Selection with the specified nodes to filter using winnow
  466. sel := &Selection{nodes, srcSel.document, nil}
  467. // Filter based on matcher and push on stack
  468. return pushStack(srcSel, winnow(sel, m, true))
  469. }
  470. // Internal implementation of Find that return raw nodes.
  471. func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node {
  472. // Map nodes to find the matches within the children of each node
  473. return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
  474. // Go down one level, becausejQuery's Find selects only within descendants
  475. for c := n.FirstChild; c != nil; c = c.NextSibling {
  476. if c.Type == html.ElementNode {
  477. result = append(result, m.MatchAll(c)...)
  478. }
  479. }
  480. return
  481. })
  482. }
  483. // Internal implementation to get all parent nodes, stopping at the specified
  484. // node (or nil if no stop).
  485. func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node {
  486. return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
  487. for p := n.Parent; p != nil; p = p.Parent {
  488. sel := newSingleSelection(p, nil)
  489. if stopm != nil {
  490. if sel.IsMatcher(stopm) {
  491. break
  492. }
  493. } else if len(stopNodes) > 0 {
  494. if sel.IsNodes(stopNodes...) {
  495. break
  496. }
  497. }
  498. if p.Type == html.ElementNode {
  499. result = append(result, p)
  500. }
  501. }
  502. return
  503. })
  504. }
  505. // Internal implementation of sibling nodes that return a raw slice of matches.
  506. func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNodes []*html.Node) []*html.Node {
  507. var f func(*html.Node) bool
  508. // If the requested siblings are ...Until, create the test function to
  509. // determine if the until condition is reached (returns true if it is)
  510. if st == siblingNextUntil || st == siblingPrevUntil {
  511. f = func(n *html.Node) bool {
  512. if untilm != nil {
  513. // Matcher-based condition
  514. sel := newSingleSelection(n, nil)
  515. return sel.IsMatcher(untilm)
  516. } else if len(untilNodes) > 0 {
  517. // Nodes-based condition
  518. sel := newSingleSelection(n, nil)
  519. return sel.IsNodes(untilNodes...)
  520. }
  521. return false
  522. }
  523. }
  524. return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
  525. return getChildrenWithSiblingType(n.Parent, st, n, f)
  526. })
  527. }
  528. // Gets the children nodes of each node in the specified slice of nodes,
  529. // based on the sibling type request.
  530. func getChildrenNodes(nodes []*html.Node, st siblingType) []*html.Node {
  531. return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
  532. return getChildrenWithSiblingType(n, st, nil, nil)
  533. })
  534. }
  535. // Gets the children of the specified parent, based on the requested sibling
  536. // type, skipping a specified node if required.
  537. func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *html.Node,
  538. untilFunc func(*html.Node) bool) (result []*html.Node) {
  539. // Create the iterator function
  540. var iter = func(cur *html.Node) (ret *html.Node) {
  541. // Based on the sibling type requested, iterate the right way
  542. for {
  543. switch st {
  544. case siblingAll, siblingAllIncludingNonElements:
  545. if cur == nil {
  546. // First iteration, start with first child of parent
  547. // Skip node if required
  548. if ret = parent.FirstChild; ret == skipNode && skipNode != nil {
  549. ret = skipNode.NextSibling
  550. }
  551. } else {
  552. // Skip node if required
  553. if ret = cur.NextSibling; ret == skipNode && skipNode != nil {
  554. ret = skipNode.NextSibling
  555. }
  556. }
  557. case siblingPrev, siblingPrevAll, siblingPrevUntil:
  558. if cur == nil {
  559. // Start with previous sibling of the skip node
  560. ret = skipNode.PrevSibling
  561. } else {
  562. ret = cur.PrevSibling
  563. }
  564. case siblingNext, siblingNextAll, siblingNextUntil:
  565. if cur == nil {
  566. // Start with next sibling of the skip node
  567. ret = skipNode.NextSibling
  568. } else {
  569. ret = cur.NextSibling
  570. }
  571. default:
  572. panic("Invalid sibling type.")
  573. }
  574. if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
  575. return
  576. }
  577. // Not a valid node, try again from this one
  578. cur = ret
  579. }
  580. }
  581. for c := iter(nil); c != nil; c = iter(c) {
  582. // If this is an ...Until case, test before append (returns true
  583. // if the until condition is reached)
  584. if st == siblingNextUntil || st == siblingPrevUntil {
  585. if untilFunc(c) {
  586. return
  587. }
  588. }
  589. result = append(result, c)
  590. if st == siblingNext || st == siblingPrev {
  591. // Only one node was requested (immediate next or previous), so exit
  592. return
  593. }
  594. }
  595. return
  596. }
  597. // Internal implementation of parent nodes that return a raw slice of Nodes.
  598. func getParentNodes(nodes []*html.Node) []*html.Node {
  599. return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
  600. if n.Parent != nil && n.Parent.Type == html.ElementNode {
  601. return []*html.Node{n.Parent}
  602. }
  603. return nil
  604. })
  605. }
  606. // Internal map function used by many traversing methods. Takes the source nodes
  607. // to iterate on and the mapping function that returns an array of nodes.
  608. // Returns an array of nodes mapped by calling the callback function once for
  609. // each node in the source nodes.
  610. func mapNodes(nodes []*html.Node, f func(int, *html.Node) []*html.Node) (result []*html.Node) {
  611. set := make(map[*html.Node]bool)
  612. for i, n := range nodes {
  613. if vals := f(i, n); len(vals) > 0 {
  614. result = appendWithoutDuplicates(result, vals, set)
  615. }
  616. }
  617. return result
  618. }