selector-engine.js 2.22 KB
Newer Older
Johann-S's avatar
Johann-S committed
1
2
/**
 * --------------------------------------------------------------------------
3
 * Bootstrap (v4.3.1): dom/selector-engine.js
Johann-S's avatar
Johann-S committed
4
5
6
7
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

Johann-S's avatar
Johann-S committed
8
import { find as findFn, findOne, matches, closest } from './polyfill'
9
import { makeArray } from '../util/index'
10

11
12
13
14
15
/**
 * ------------------------------------------------------------------------
 * Constants
 * ------------------------------------------------------------------------
 */
Johann-S's avatar
Johann-S committed
16

17
const NODE_TEXT = 3
Johann-S's avatar
Johann-S committed
18

19
20
const SelectorEngine = {
  matches(element, selector) {
Johann-S's avatar
Johann-S committed
21
    return matches.call(element, selector)
22
  },
Johann-S's avatar
Johann-S committed
23

24
25
26
27
  find(selector, element = document.documentElement) {
    if (typeof selector !== 'string') {
      return null
    }
28

29
    return findFn.call(element, selector)
30
31
32
33
34
35
  },

  findOne(selector, element = document.documentElement) {
    if (typeof selector !== 'string') {
      return null
    }
Johann-S's avatar
Johann-S committed
36

37
38
    return findOne.call(element, selector)
  },
Johann-S's avatar
Johann-S committed
39

40
41
42
43
44
  children(element, selector) {
    if (typeof selector !== 'string') {
      return null
    }

45
    const children = makeArray(element.children)
46

XhmikosR's avatar
XhmikosR committed
47
    return children.filter(child => this.matches(child, selector))
48
  },
49

50
51
52
53
  parents(element, selector) {
    if (typeof selector !== 'string') {
      return null
    }
54

55
56
    const parents = []
    let ancestor = element.parentNode
57
58

    while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== NODE_TEXT) {
59
60
      if (this.matches(ancestor, selector)) {
        parents.push(ancestor)
61
62
      }

63
64
      ancestor = ancestor.parentNode
    }
65

66
67
    return parents
  },
68

69
70
71
72
  closest(element, selector) {
    if (typeof selector !== 'string') {
      return null
    }
73

Johann-S's avatar
Johann-S committed
74
    return closest.call(element, selector)
75
  },
76

77
78
79
80
  prev(element, selector) {
    if (typeof selector !== 'string') {
      return null
    }
81

82
83
    const siblings = []
    let previous = element.previousSibling
84
85

    while (previous && previous.nodeType === Node.ELEMENT_NODE && previous.nodeType !== NODE_TEXT) {
86
87
      if (this.matches(previous, selector)) {
        siblings.push(previous)
88
89
      }

90
      previous = previous.previousSibling
Johann-S's avatar
Johann-S committed
91
    }
92
93

    return siblings
Johann-S's avatar
Johann-S committed
94
  }
95
}
Johann-S's avatar
Johann-S committed
96
97

export default SelectorEngine