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

8
9
10
import Polyfill from './polyfill'
import Util from '../util'

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

17
const findFn = Polyfill.find
18
const findOne = Polyfill.findOne
19
const NODE_TEXT = 3
Johann-S's avatar
Johann-S committed
20

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

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

31
    return findFn.call(element, selector)
32
33
34
35
36
37
  },

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

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

42
43
44
45
46
47
  children(element, selector) {
    if (typeof selector !== 'string') {
      return null
    }

    const children = Util.makeArray(element.children)
48

49
50
    return children.filter((child) => this.matches(child, selector))
  },
51

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

57
58
    const parents = []
    let ancestor = element.parentNode
59
60

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

65
66
      ancestor = ancestor.parentNode
    }
67

68
69
    return parents
  },
70

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

76
    return element.closest(selector)
77
  },
78

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

84
85
    const siblings = []
    let previous = element.previousSibling
86
87

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

92
      previous = previous.previousSibling
Johann-S's avatar
Johann-S committed
93
    }
94
95

    return siblings
Johann-S's avatar
Johann-S committed
96
  }
97
}
Johann-S's avatar
Johann-S committed
98
99

export default SelectorEngine