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

Johann-S's avatar
Johann-S committed
8
9
10
11
12
13
const SelectorEngine = (() => {
  /**
   * ------------------------------------------------------------------------
   * Polyfills
   * ------------------------------------------------------------------------
   */
14

Johann-S's avatar
Johann-S committed
15
16
17
18
19
20
21
22
  // matches polyfill (see: https://mzl.la/2ikXneG)
  let fnMatches = null
  if (!Element.prototype.matches) {
    fnMatches =
      Element.prototype.msMatchesSelector ||
      Element.prototype.webkitMatchesSelector
  } else {
    fnMatches = Element.prototype.matches
23
24
  }

Johann-S's avatar
Johann-S committed
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  // closest polyfill (see: https://mzl.la/2vXggaI)
  let fnClosest = null
  if (!Element.prototype.closest) {
    fnClosest = (element, selector) => {
      let ancestor = element
      if (!document.documentElement.contains(element)) {
        return null
      }

      do {
        if (fnMatches.call(ancestor, selector)) {
          return ancestor
        }

        ancestor = ancestor.parentElement
      } while (ancestor !== null)
Johann-S's avatar
Johann-S committed
41
42
43

      return null
    }
Johann-S's avatar
Johann-S committed
44
45
46
47
  } else {
    // eslint-disable-next-line arrow-body-style
    fnClosest = (element, selector) => {
      return element.closest(selector)
Johann-S's avatar
Johann-S committed
48
    }
Johann-S's avatar
Johann-S committed
49
  }
Johann-S's avatar
Johann-S committed
50

Johann-S's avatar
Johann-S committed
51
52
53
54
  return {
    matches(element, selector) {
      return fnMatches.call(element, selector)
    },
Johann-S's avatar
Johann-S committed
55

Johann-S's avatar
Johann-S committed
56
57
58
59
    find(selector, element = document) {
      if (typeof selector !== 'string') {
        return null
      }
Johann-S's avatar
Johann-S committed
60

Johann-S's avatar
Johann-S committed
61
62
63
64
65
66
      if (selector.indexOf('#') === 0) {
        return SelectorEngine.findOne(selector, element)
      }

      return element.querySelectorAll(selector)
    },
Johann-S's avatar
Johann-S committed
67

Johann-S's avatar
Johann-S committed
68
69
70
71
72
73
74
75
76
77
    findOne(selector, element = document) {
      if (typeof selector !== 'string') {
        return null
      }

      let selectorType = 'querySelector'
      if (selector.indexOf('#') === 0) {
        selectorType = 'getElementById'
        selector = selector.substr(1, selector.length)
      }
Johann-S's avatar
Johann-S committed
78

Johann-S's avatar
Johann-S committed
79
80
81
82
83
84
      return element[selectorType](selector)
    },

    closest(element, selector) {
      return fnClosest(element, selector)
    }
Johann-S's avatar
Johann-S committed
85
  }
Johann-S's avatar
Johann-S committed
86
})()
Johann-S's avatar
Johann-S committed
87
88

export default SelectorEngine