From 7c1d0a1097657fb604a69cd47375a7e94c0ced93 Mon Sep 17 00:00:00 2001
From: Johann-S <johann.servoire@gmail.com>
Date: Wed, 20 Sep 2017 14:19:10 +0200
Subject: [PATCH] Wrap our objects into IIFE

---
 js/src/dom/data.js           |  94 ++++---
 js/src/dom/eventHandler.js   | 532 ++++++++++++++++++-----------------
 js/src/dom/selectorEngine.js | 122 ++++----
 3 files changed, 395 insertions(+), 353 deletions(-)

diff --git a/js/src/dom/data.js b/js/src/dom/data.js
index 68908d8f22..f3e4386fcc 100644
--- a/js/src/dom/data.js
+++ b/js/src/dom/data.js
@@ -5,56 +5,66 @@
  * --------------------------------------------------------------------------
  */
 
-const mapData = (() => {
-  const storeData = {}
-  let id = 1
-  return {
-    set(element, key, data) {
-      if (typeof element.key === 'undefined') {
-        element.key = {
-          key,
-          id
+const Data = (() => {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+
+  const mapData = (() => {
+    const storeData = {}
+    let id = 1
+    return {
+      set(element, key, data) {
+        if (typeof element.key === 'undefined') {
+          element.key = {
+            key,
+            id
+          }
         }
-      }
 
-      storeData[id] = data
-      id++
-    },
-    get(element, key) {
-      if (typeof element === 'undefined' || typeof element.key === 'undefined') {
+        storeData[id] = data
+        id++
+      },
+      get(element, key) {
+        if (typeof element === 'undefined' || typeof element.key === 'undefined') {
+          return null
+        }
+
+        const keyProperties = element.key
+        if (keyProperties.key === key) {
+          return storeData[keyProperties.id]
+        }
         return null
-      }
+      },
+      delete(element, key) {
+        if (typeof element.key === 'undefined') {
+          return
+        }
 
-      const keyProperties = element.key
-      if (keyProperties.key === key) {
-        return storeData[keyProperties.id]
-      }
-      return null
-    },
-    delete(element, key) {
-      if (typeof element.key === 'undefined') {
-        return
+        const keyProperties = element.key
+        if (keyProperties.key === key) {
+          delete storeData[keyProperties.id]
+          delete element.key
+        }
       }
+    }
+  })()
 
-      const keyProperties = element.key
-      if (keyProperties.key === key) {
-        delete storeData[keyProperties.id]
-        delete element.key
-      }
+  return {
+    setData(instance, key, data) {
+      mapData.set(instance, key, data)
+    },
+    getData(instance, key) {
+      return mapData.get(instance, key)
+    },
+    removeData(instance, key) {
+      mapData.delete(instance, key)
     }
   }
 })()
 
-const Data = {
-  setData(instance, key, data) {
-    mapData.set(instance, key, data)
-  },
-  getData(instance, key) {
-    return mapData.get(instance, key)
-  },
-  removeData(instance, key) {
-    mapData.delete(instance, key)
-  }
-}
-
 export default Data
diff --git a/js/src/dom/eventHandler.js b/js/src/dom/eventHandler.js
index b72684f819..7854401c37 100644
--- a/js/src/dom/eventHandler.js
+++ b/js/src/dom/eventHandler.js
@@ -7,325 +7,347 @@ import Util from '../util'
  * --------------------------------------------------------------------------
  */
 
-// defaultPrevented is broken in IE.
-// https://connect.microsoft.com/IE/feedback/details/790389/event-defaultprevented-returns-false-after-preventdefault-was-called
-const workingDefaultPrevented = (() => {
-  const e = document.createEvent('CustomEvent')
-  e.initEvent('Bootstrap', true, true)
-  e.preventDefault()
-  return e.defaultPrevented
-})()
+const EventHandler = (() => {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Polyfills
+   * ------------------------------------------------------------------------
+   */
+
+  // defaultPrevented is broken in IE.
+  // https://connect.microsoft.com/IE/feedback/details/790389/event-defaultprevented-returns-false-after-preventdefault-was-called
+  const workingDefaultPrevented = (() => {
+    const e = document.createEvent('CustomEvent')
+    e.initEvent('Bootstrap', true, true)
+    e.preventDefault()
+    return e.defaultPrevented
+  })()
 
-let defaultPreventedPreservedOnDispatch = true
+  let defaultPreventedPreservedOnDispatch = true
 
-// CustomEvent polyfill for IE (see: https://mzl.la/2v76Zvn)
-if (typeof window.CustomEvent !== 'function') {
-  window.CustomEvent = (event, params) => {
-    params = params || {
-      bubbles: false,
-      cancelable: false,
-      detail: null
-    }
-    const evt = document.createEvent('CustomEvent')
-    evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
-    if (!workingDefaultPrevented) {
-      const origPreventDefault = Event.prototype.preventDefault
-      evt.preventDefault = () => {
-        if (!evt.cancelable) {
-          return
+  // CustomEvent polyfill for IE (see: https://mzl.la/2v76Zvn)
+  if (typeof window.CustomEvent !== 'function') {
+    window.CustomEvent = (event, params) => {
+      params = params || {
+        bubbles: false,
+        cancelable: false,
+        detail: null
+      }
+      const evt = document.createEvent('CustomEvent')
+      evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
+      if (!workingDefaultPrevented) {
+        const origPreventDefault = Event.prototype.preventDefault
+        evt.preventDefault = () => {
+          if (!evt.cancelable) {
+            return
+          }
+
+          origPreventDefault.call(evt)
+          Object.defineProperty(evt, 'defaultPrevented', {
+            get() {
+              return true
+            },
+            configurable: true
+          })
         }
-
-        origPreventDefault.call(evt)
-        Object.defineProperty(evt, 'defaultPrevented', {
-          get() {
-            return true
-          },
-          configurable: true
-        })
       }
+      return evt
     }
-    return evt
-  }
 
-  window.CustomEvent.prototype = window.Event.prototype
-} else {
-  // MSEdge resets defaultPrevented flag upon dispatchEvent call if at least one listener is attached
-  defaultPreventedPreservedOnDispatch = (() => {
-    const e = new CustomEvent('Bootstrap', {
-      cancelable: true
-    })
+    window.CustomEvent.prototype = window.Event.prototype
+  } else {
+    // MSEdge resets defaultPrevented flag upon dispatchEvent call if at least one listener is attached
+    defaultPreventedPreservedOnDispatch = (() => {
+      const e = new CustomEvent('Bootstrap', {
+        cancelable: true
+      })
 
-    const element = document.createElement('div')
-    element.addEventListener('Bootstrap', () => null)
+      const element = document.createElement('div')
+      element.addEventListener('Bootstrap', () => null)
 
-    e.preventDefault()
-    element.dispatchEvent(e)
-    return e.defaultPrevented
-  })()
-}
-
-// Event constructor shim
-if (!window.Event || typeof window.Event !== 'function') {
-  const origEvent = window.Event
-  window.Event = (inType, params) => {
-    params = params || {}
-    const e = document.createEvent('Event')
-    e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable))
-    return e
+      e.preventDefault()
+      element.dispatchEvent(e)
+      return e.defaultPrevented
+    })()
   }
-  window.Event.prototype = origEvent.prototype
-}
-
-const namespaceRegex = /[^.]*(?=\..*)\.|.*/
-const stripNameRegex = /\..*/
-const keyEventRegex  = /^key/
-const stripUidRegex  = /::\d+$/
 
-// Events storage
-const eventRegistry = {}
-let uidEvent = 1
+  // Event constructor shim
+  if (!window.Event || typeof window.Event !== 'function') {
+    const origEvent = window.Event
+    window.Event = (inType, params) => {
+      params = params || {}
+      const e = document.createEvent('Event')
+      e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable))
+      return e
+    }
+    window.Event.prototype = origEvent.prototype
+  }
 
-function getUidEvent(element, uid) {
-  return element.uidEvent = uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++
-}
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
 
-function getEvent(element) {
-  const uid = getUidEvent(element)
-  return eventRegistry[uid] = eventRegistry[uid] || {}
-}
+  const TransitionEndEvent = {
+    WebkitTransition : 'webkitTransitionEnd',
+    transition       : 'transitionend'
+  }
+  const namespaceRegex = /[^.]*(?=\..*)\.|.*/
+  const stripNameRegex = /\..*/
+  const keyEventRegex  = /^key/
+  const stripUidRegex  = /::\d+$/
+  const eventRegistry  = {}   // Events storage
+  let uidEvent         = 1
+  const customEvents   = {
+    mouseenter: 'mouseover',
+    mouseleave: 'mouseout'
+  }
+  const nativeEvents   = [
+    'click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu',
+    'mousewheel', 'DOMMouseScroll',
+    'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend',
+    'keydown', 'keypress', 'keyup',
+    'orientationchange',
+    'touchstart', 'touchmove', 'touchend', 'touchcancel',
+    'gesturestart', 'gesturechange', 'gestureend',
+    'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout',
+    'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange',
+    'error', 'abort', 'scroll'
+  ]
+
+  /**
+   * ------------------------------------------------------------------------
+   * Private methods
+   * ------------------------------------------------------------------------
+   */
+
+
+  function getUidEvent(element, uid) {
+    return element.uidEvent = uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++
+  }
 
-const nativeEvents = [
-  'click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu',
-  'mousewheel', 'DOMMouseScroll',
-  'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend',
-  'keydown', 'keypress', 'keyup',
-  'orientationchange',
-  'touchstart', 'touchmove', 'touchend', 'touchcancel',
-  'gesturestart', 'gesturechange', 'gestureend',
-  'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout',
-  'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange',
-  'error', 'abort', 'scroll'
-]
-
-const customEvents = {
-  mouseenter: 'mouseover',
-  mouseleave: 'mouseout'
-}
+  function getEvent(element) {
+    const uid = getUidEvent(element)
+    return eventRegistry[uid] = eventRegistry[uid] || {}
+  }
 
-function fixEvent(event) {
-  // Add which for key events
-  if (event.which === null && keyEventRegex.test(event.type)) {
-    event.which = event.charCode !== null ? event.charCode : event.keyCode
+  function fixEvent(event) {
+    // Add which for key events
+    if (event.which === null && keyEventRegex.test(event.type)) {
+      event.which = event.charCode !== null ? event.charCode : event.keyCode
+    }
+    return event
   }
-  return event
-}
 
-function bootstrapHandler(element, fn) {
-  return function (event) {
-    event = fixEvent(event)
-    return fn.apply(element, [event])
+  function bootstrapHandler(element, fn) {
+    return function (event) {
+      event = fixEvent(event)
+      return fn.apply(element, [event])
+    }
   }
-}
 
-function bootstrapDelegationHandler(element, selector, fn) {
-  return function (event) {
-    event = fixEvent(event)
-    const domElements = element.querySelectorAll(selector)
-    for (let target = event.target; target && target !== this; target = target.parentNode) {
-      for (let i = domElements.length; i--;) {
-        if (domElements[i] === target) {
-          return fn.apply(target, [event])
+  function bootstrapDelegationHandler(element, selector, fn) {
+    return function (event) {
+      event = fixEvent(event)
+      const domElements = element.querySelectorAll(selector)
+      for (let target = event.target; target && target !== this; target = target.parentNode) {
+        for (let i = domElements.length; i--;) {
+          if (domElements[i] === target) {
+            return fn.apply(target, [event])
+          }
         }
       }
+      // To please ESLint
+      return null
     }
-    // To please ESLint
-    return null
   }
-}
 
-function removeHandler(element, events, typeEvent, handler) {
-  const uidEvent = handler.uidEvent
-  const fn = events[typeEvent][uidEvent]
-  element.removeEventListener(typeEvent, fn, fn.delegation)
-  delete events[typeEvent][uidEvent]
-}
+  function removeHandler(element, events, typeEvent, handler) {
+    const uidEvent = handler.uidEvent
+    const fn = events[typeEvent][uidEvent]
+    element.removeEventListener(typeEvent, fn, fn.delegation)
+    delete events[typeEvent][uidEvent]
+  }
 
-function removeNamespacedHandlers(element, events, typeEvent, namespace) {
-  const storeElementEvent = events[typeEvent] || {}
-  for (const handlerKey in storeElementEvent) {
-    if (!Object.prototype.hasOwnProperty.call(storeElementEvent, handlerKey)) {
-      continue
-    }
+  function removeNamespacedHandlers(element, events, typeEvent, namespace) {
+    const storeElementEvent = events[typeEvent] || {}
+    for (const handlerKey in storeElementEvent) {
+      if (!Object.prototype.hasOwnProperty.call(storeElementEvent, handlerKey)) {
+        continue
+      }
 
-    if (handlerKey.indexOf(namespace) > -1) {
-      removeHandler(element, events, typeEvent, storeElementEvent[handlerKey].originalHandler)
+      if (handlerKey.indexOf(namespace) > -1) {
+        removeHandler(element, events, typeEvent, storeElementEvent[handlerKey].originalHandler)
+      }
     }
   }
-}
 
-const EventHandler = {
-  on(element, originalTypeEvent, handler, delegationFn) {
-    if (typeof originalTypeEvent !== 'string' ||
-        (typeof element === 'undefined' || element === null)) {
-      return
-    }
+  return {
+    on(element, originalTypeEvent, handler, delegationFn) {
+      if (typeof originalTypeEvent !== 'string' ||
+          (typeof element === 'undefined' || element === null)) {
+        return
+      }
 
-    const delegation      = typeof handler === 'string'
-    const originalHandler = delegation ? delegationFn : handler
+      const delegation      = typeof handler === 'string'
+      const originalHandler = delegation ? delegationFn : handler
 
-    // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
-    let typeEvent = originalTypeEvent.replace(stripNameRegex, '')
+      // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
+      let typeEvent = originalTypeEvent.replace(stripNameRegex, '')
 
-    const custom = customEvents[typeEvent]
-    if (custom) {
-      typeEvent = custom
-    }
+      const custom = customEvents[typeEvent]
+      if (custom) {
+        typeEvent = custom
+      }
 
-    const isNative = nativeEvents.indexOf(typeEvent) > -1
-    if (!isNative) {
-      typeEvent = originalTypeEvent
-    }
-    const events    = getEvent(element)
-    const handlers  = events[typeEvent] || (events[typeEvent] = {})
-    const uid       = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''))
-    if (handlers[uid]) {
-      return
-    }
+      const isNative = nativeEvents.indexOf(typeEvent) > -1
+      if (!isNative) {
+        typeEvent = originalTypeEvent
+      }
+      const events    = getEvent(element)
+      const handlers  = events[typeEvent] || (events[typeEvent] = {})
+      const uid       = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''))
+      if (handlers[uid]) {
+        return
+      }
 
-    const fn = !delegation ? bootstrapHandler(element, handler) : bootstrapDelegationHandler(element, handler, delegationFn)
-    fn.isDelegation = delegation
-    handlers[uid] = fn
-    originalHandler.uidEvent = uid
-    fn.originalHandler = originalHandler
-    element.addEventListener(typeEvent, fn, delegation)
-  },
-
-  one(element, event, handler) {
-    function complete(e) {
-      EventHandler.off(element, event, complete)
-      handler.apply(element, [e])
-    }
-    EventHandler.on(element, event, complete)
-  },
+      const fn = !delegation ? bootstrapHandler(element, handler) : bootstrapDelegationHandler(element, handler, delegationFn)
+      fn.isDelegation = delegation
+      handlers[uid] = fn
+      originalHandler.uidEvent = uid
+      fn.originalHandler = originalHandler
+      element.addEventListener(typeEvent, fn, delegation)
+    },
+
+    one(element, event, handler) {
+      function complete(e) {
+        EventHandler.off(element, event, complete)
+        handler.apply(element, [e])
+      }
+      EventHandler.on(element, event, complete)
+    },
 
-  off(element, originalTypeEvent, handler) {
-    if (typeof originalTypeEvent !== 'string' ||
-       (typeof element === 'undefined' || element === null)) {
-      return
-    }
+    off(element, originalTypeEvent, handler) {
+      if (typeof originalTypeEvent !== 'string' ||
+        (typeof element === 'undefined' || element === null)) {
+        return
+      }
 
-    const events      = getEvent(element)
-    let typeEvent     = originalTypeEvent.replace(stripNameRegex, '')
+      const events      = getEvent(element)
+      let typeEvent     = originalTypeEvent.replace(stripNameRegex, '')
 
-    const inNamespace = typeEvent !== originalTypeEvent
-    const custom      = customEvents[typeEvent]
-    if (custom) {
-      typeEvent = custom
-    }
+      const inNamespace = typeEvent !== originalTypeEvent
+      const custom      = customEvents[typeEvent]
+      if (custom) {
+        typeEvent = custom
+      }
 
-    const isNative = nativeEvents.indexOf(typeEvent) > -1
-    if (!isNative) {
-      typeEvent = originalTypeEvent
-    }
+      const isNative = nativeEvents.indexOf(typeEvent) > -1
+      if (!isNative) {
+        typeEvent = originalTypeEvent
+      }
+
+      if (typeof handler !== 'undefined') {
+        // Simplest case: handler is passed, remove that listener ONLY.
+        if (!events || !events[typeEvent]) {
+          return
+        }
 
-    if (typeof handler !== 'undefined') {
-      // Simplest case: handler is passed, remove that listener ONLY.
-      if (!events || !events[typeEvent]) {
+        removeHandler(element, events, typeEvent, handler)
         return
       }
 
-      removeHandler(element, events, typeEvent, handler)
-      return
-    }
+      const isNamespace = originalTypeEvent.charAt(0) === '.'
+      if (isNamespace) {
+        for (const elementEvent in events) {
+          if (!Object.prototype.hasOwnProperty.call(events, elementEvent)) {
+            continue
+          }
 
-    const isNamespace = originalTypeEvent.charAt(0) === '.'
-    if (isNamespace) {
-      for (const elementEvent in events) {
-        if (!Object.prototype.hasOwnProperty.call(events, elementEvent)) {
-          continue
+          removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.substr(1))
         }
-
-        removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.substr(1))
       }
-    }
 
-    const storeElementEvent = events[typeEvent] || {}
-    for (const keyHandlers in storeElementEvent) {
-      if (!Object.prototype.hasOwnProperty.call(storeElementEvent, keyHandlers)) {
-        continue
+      const storeElementEvent = events[typeEvent] || {}
+      for (const keyHandlers in storeElementEvent) {
+        if (!Object.prototype.hasOwnProperty.call(storeElementEvent, keyHandlers)) {
+          continue
+        }
+
+        const handlerKey = keyHandlers.replace(stripUidRegex, '')
+        if (!inNamespace || originalTypeEvent.indexOf(handlerKey) > -1) {
+          removeHandler(element, events, typeEvent, storeElementEvent[keyHandlers].originalHandler)
+        }
       }
+    },
 
-      const handlerKey = keyHandlers.replace(stripUidRegex, '')
-      if (!inNamespace || originalTypeEvent.indexOf(handlerKey) > -1) {
-        removeHandler(element, events, typeEvent, storeElementEvent[keyHandlers].originalHandler)
+    trigger(element, event, args) {
+      if (typeof event !== 'string' ||
+          (typeof element === 'undefined' || element === null)) {
+        return null
       }
-    }
-  },
 
-  trigger(element, event, args) {
-    if (typeof event !== 'string' ||
-        (typeof element === 'undefined' || element === null)) {
-      return null
-    }
+      const typeEvent   = event.replace(stripNameRegex, '')
+      const inNamespace = event !== typeEvent
+      const isNative    = nativeEvents.indexOf(typeEvent) > -1
 
-    const typeEvent   = event.replace(stripNameRegex, '')
-    const inNamespace = event !== typeEvent
-    const isNative    = nativeEvents.indexOf(typeEvent) > -1
+      const $ = Util.jQuery
+      let jQueryEvent
 
-    const $ = Util.jQuery
-    let jQueryEvent
+      let bubbles = true
+      let nativeDispatch = true
+      let defaultPrevented = false
 
-    let bubbles = true
-    let nativeDispatch = true
-    let defaultPrevented = false
+      if (inNamespace && typeof $ !== 'undefined') {
+        jQueryEvent = new $.Event(event, args)
 
-    if (inNamespace && typeof $ !== 'undefined') {
-      jQueryEvent = new $.Event(event, args)
+        $(element).trigger(jQueryEvent)
+        bubbles = !jQueryEvent.isPropagationStopped()
+        nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()
+        defaultPrevented = jQueryEvent.isDefaultPrevented()
+      }
 
-      $(element).trigger(jQueryEvent)
-      bubbles = !jQueryEvent.isPropagationStopped()
-      nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()
-      defaultPrevented = jQueryEvent.isDefaultPrevented()
-    }
+      let evt           = null
 
-    let evt           = null
+      if (isNative) {
+        evt = document.createEvent('HTMLEvents')
+        evt.initEvent(typeEvent, bubbles, true)
+      } else {
+        evt = new CustomEvent(event, {
+          bubbles,
+          cancelable: true
+        })
+      }
 
-    if (isNative) {
-      evt = document.createEvent('HTMLEvents')
-      evt.initEvent(typeEvent, bubbles, true)
-    } else {
-      evt = new CustomEvent(event, {
-        bubbles,
-        cancelable: true
-      })
-    }
+      // merge custom informations in our event
+      if (typeof args !== 'undefined') {
+        evt = Util.extend(evt, args)
+      }
 
-    // merge custom informations in our event
-    if (typeof args !== 'undefined') {
-      evt = Util.extend(evt, args)
-    }
+      if (defaultPrevented) {
+        evt.preventDefault()
 
-    if (defaultPrevented) {
-      evt.preventDefault()
+        if (!defaultPreventedPreservedOnDispatch) {
+          Object.defineProperty(evt, 'defaultPrevented', {
+            get: () => true
+          })
+        }
+      }
 
-      if (!defaultPreventedPreservedOnDispatch) {
-        Object.defineProperty(evt, 'defaultPrevented', {
-          get: () => true
-        })
+      if (nativeDispatch) {
+        element.dispatchEvent(evt)
       }
-    }
 
-    if (nativeDispatch) {
-      element.dispatchEvent(evt)
-    }
+      if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') {
+        jQueryEvent.preventDefault()
+      }
 
-    if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') {
-      jQueryEvent.preventDefault()
+      return evt
     }
-
-    return evt
   }
-}
+})()
 
 // focusin and focusout polyfill
 if (typeof window.onfocusin === 'undefined') {
diff --git a/js/src/dom/selectorEngine.js b/js/src/dom/selectorEngine.js
index 0cff83ef97..99dc26b797 100644
--- a/js/src/dom/selectorEngine.js
+++ b/js/src/dom/selectorEngine.js
@@ -5,76 +5,86 @@
  * --------------------------------------------------------------------------
  */
 
-// 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
-}
-
-// 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
-    }
+const SelectorEngine = (() => {
 
-    do {
-      if (fnMatches.call(ancestor, selector)) {
-        return ancestor
-      }
 
-      ancestor = ancestor.parentElement
-    } while (ancestor !== null)
+  /**
+   * ------------------------------------------------------------------------
+   * Polyfills
+   * ------------------------------------------------------------------------
+   */
 
-    return null
+  // 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
   }
-} else {
-  // eslint-disable-next-line arrow-body-style
-  fnClosest = (element, selector) => {
-    return element.closest(selector)
-  }
-}
 
-const SelectorEngine = {
-  matches(element, selector) {
-    return fnMatches.call(element, selector)
-  },
+  // 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)
 
-  find(selector, element = document) {
-    if (typeof selector !== 'string') {
       return null
     }
-
-    if (selector.indexOf('#') === 0) {
-      return SelectorEngine.findOne(selector, element)
+  } else {
+    // eslint-disable-next-line arrow-body-style
+    fnClosest = (element, selector) => {
+      return element.closest(selector)
     }
+  }
 
-    return element.querySelectorAll(selector)
-  },
+  return {
+    matches(element, selector) {
+      return fnMatches.call(element, selector)
+    },
 
-  findOne(selector, element = document) {
-    if (typeof selector !== 'string') {
-      return null
-    }
+    find(selector, element = document) {
+      if (typeof selector !== 'string') {
+        return null
+      }
 
-    let selectorType = 'querySelector'
-    if (selector.indexOf('#') === 0) {
-      selectorType = 'getElementById'
-      selector = selector.substr(1, selector.length)
-    }
+      if (selector.indexOf('#') === 0) {
+        return SelectorEngine.findOne(selector, element)
+      }
+
+      return element.querySelectorAll(selector)
+    },
 
-    return element[selectorType](selector)
-  },
+    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)
+      }
 
-  closest(element, selector) {
-    return fnClosest(element, selector)
+      return element[selectorType](selector)
+    },
+
+    closest(element, selector) {
+      return fnClosest(element, selector)
+    }
   }
-}
+})()
 
 export default SelectorEngine
-- 
GitLab