From 2970d14dd91bf1f5f236766c856e81c297fa1390 Mon Sep 17 00:00:00 2001
From: Johann-S <johann.servoire@gmail.com>
Date: Wed, 23 Aug 2017 12:03:50 +0200
Subject: [PATCH] Remove jQuery from alert.js and add .alert only if jQuery is
 available

---
 js/src/alert.js              | 27 ++++++++++-----------------
 js/src/dom/data.js           |  6 +++---
 js/src/dom/eventHandler.js   |  5 ++++-
 js/src/dom/selectorEngine.js | 11 ++++-------
 js/tests/unit/alert.js       | 18 +++++++++---------
 5 files changed, 30 insertions(+), 37 deletions(-)

diff --git a/js/src/alert.js b/js/src/alert.js
index 5e99f6d011..c530b2996b 100644
--- a/js/src/alert.js
+++ b/js/src/alert.js
@@ -85,8 +85,7 @@ class Alert {
     let parent     = false
 
     if (selector) {
-      const tmpSelected = SelectorEngine.find(selector)
-      parent = tmpSelected[0]
+      parent = SelectorEngine.find(selector)[0]
     }
 
     if (!parent) {
@@ -136,16 +135,6 @@ class Alert {
       }
     })
   }
-
-  static _handleDismiss(alertInstance) {
-    return function (event) {
-      if (event) {
-        event.preventDefault()
-      }
-
-      alertInstance.close(this)
-    }
-  }
 }
 
 /**
@@ -159,13 +148,17 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleD
  * ------------------------------------------------------------------------
  * jQuery
  * ------------------------------------------------------------------------
+ * add .alert to jQuery only if jQuery is present
  */
 
-$.fn[NAME]             = Alert._jQueryInterface
-$.fn[NAME].Constructor = Alert
-$.fn[NAME].noConflict  = () => {
-  $.fn[NAME] = JQUERY_NO_CONFLICT
-  return Alert._jQueryInterface
+if (typeof window.$ !== 'undefined' || typeof window.jQuery !== 'undefined') {
+  const $ = window.$ || window.jQuery
+  $.fn[NAME]             = Alert._jQueryInterface
+  $.fn[NAME].Constructor = Alert
+  $.fn[NAME].noConflict  = () => {
+    $.fn[NAME] = JQUERY_NO_CONFLICT
+    return Alert._jQueryInterface
+  }
 }
 
 export default Alert
diff --git a/js/src/dom/data.js b/js/src/dom/data.js
index bbe807aac1..51ebb8d3f3 100644
--- a/js/src/dom/data.js
+++ b/js/src/dom/data.js
@@ -10,7 +10,7 @@ const mapData = (() => {
   return {
     set(element, key, data) {
       let id
-      if (element.key === undefined) {
+      if (typeof element.key === 'undefined') {
         element.key = {
           key,
           id
@@ -20,14 +20,14 @@ const mapData = (() => {
       storeData[id] = data
     },
     get(element, key) {
-      if (element.key === undefined || element.key !== key) {
+      if (typeof element.key === 'undefined' || element.key !== key) {
         return null
       }
       const keyProperties = element.key
       return storeData[keyProperties.id]
     },
     delete(element, key) {
-      if (element.key === undefined || element.key !== key) {
+      if (typeof element.key === 'undefined' || element.key !== key) {
         return
       }
       const keyProperties = element.key
diff --git a/js/src/dom/eventHandler.js b/js/src/dom/eventHandler.js
index ae3ccafadb..bcaefd59ce 100644
--- a/js/src/dom/eventHandler.js
+++ b/js/src/dom/eventHandler.js
@@ -19,7 +19,8 @@ if (typeof window.CustomEvent !== 'function') {
   window.CustomEvent = (event, params) => {
     params = params || {
       bubbles: false,
-      cancelable: false
+      cancelable: false,
+      detail: null
     }
     const evt = document.createEvent('CustomEvent')
     evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
@@ -101,6 +102,8 @@ function bootstrapDelegationHandler(selector, fn) {
         }
       }
     }
+    // To please ESLint
+    return null
   }
 }
 
diff --git a/js/src/dom/selectorEngine.js b/js/src/dom/selectorEngine.js
index 1b33bf62d6..f6f3fe82f0 100644
--- a/js/src/dom/selectorEngine.js
+++ b/js/src/dom/selectorEngine.js
@@ -16,9 +16,8 @@ if (!Element.prototype.matches) {
 }
 
 // closest polyfill (see: https://mzl.la/2vXggaI)
-let fnClosest = null
 if (!Element.prototype.closest) {
-  fnClosest = (element, selector) => {
+  Element.prototype.closest = (element, selector) => {
     let ancestor = element
     if (!document.documentElement.contains(element)) {
       return null
@@ -34,12 +33,10 @@ if (!Element.prototype.closest) {
 
     return null
   }
-} else {
-  fnClosest = (element, selector) => {
-    return element.closest(selector)
-  }
 }
 
+const fnClosest = Element.prototype.closest
+
 const SelectorEngine = {
   matches(element, selector) {
     return fnMatches.call(element, selector)
@@ -59,7 +56,7 @@ const SelectorEngine = {
   },
 
   closest(element, selector) {
-    return fnClosest(element, selector)
+    return fnClosest.call(element, selector)
   }
 }
 
diff --git a/js/tests/unit/alert.js b/js/tests/unit/alert.js
index 32fcc6ceaf..588908d66e 100644
--- a/js/tests/unit/alert.js
+++ b/js/tests/unit/alert.js
@@ -42,8 +42,8 @@ $(function () {
 
     var $alert = $(alertHTML).bootstrapAlert().appendTo($('#qunit-fixture'))
 
-    $alert.find('.close').trigger('click')
-
+    var closeBtn = $alert.find('.close')[0]
+    EventHandler.trigger(closeBtn, 'click')
     assert.strictEqual($alert.hasClass('show'), false, 'remove .show class on .close click')
   })
 
@@ -58,13 +58,13 @@ $(function () {
 
     assert.notEqual($('#qunit-fixture').find('.alert').length, 0, 'element added to dom')
 
-    $alert
-      .one('closed.bs.alert', function () {
-        assert.strictEqual($('#qunit-fixture').find('.alert').length, 0, 'element removed from dom')
-        done()
-      })
-      .find('.close')
-      .trigger('click')
+    EventHandler.on($alert[0], 'closed.bs.alert', function () {
+      assert.strictEqual($('#qunit-fixture').find('.alert').length, 0, 'element removed from dom')
+      done()
+    })
+
+    var closeBtn = $alert.find('.close')[0]
+    EventHandler.trigger(closeBtn, 'click')
   })
 
   QUnit.test('should not fire closed when close is prevented', function (assert) {
-- 
GitLab