]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Remove jQuery support in plugins
authorMark Otto <markdotto@gmail.com>
Sat, 22 Feb 2025 05:06:51 +0000 (21:06 -0800)
committerMark Otto <markdotto@gmail.com>
Sat, 31 May 2025 03:30:55 +0000 (20:30 -0700)
15 files changed:
js/src/alert.js
js/src/button.js
js/src/carousel.js
js/src/collapse.js
js/src/dom/event-handler.js
js/src/dropdown.js
js/src/modal.js
js/src/offcanvas.js
js/src/popover.js
js/src/scrollspy.js
js/src/tab.js
js/src/toast.js
js/src/tooltip.js
js/src/util/index.js
site/src/content/docs/getting-started/javascript.mdx

index 88232bcebaae55cf9e0cf09db7bf9a451f2dc974..a0e6cab970777da21bfab27c03efd28bd580156d 100644 (file)
@@ -8,7 +8,6 @@
 import BaseComponent from './base-component.js'
 import EventHandler from './dom/event-handler.js'
 import { enableDismissTrigger } from './util/component-functions.js'
-import { defineJQueryPlugin } from './util/index.js'
 
 /**
  * Constants
@@ -53,23 +52,6 @@ class Alert extends BaseComponent {
     EventHandler.trigger(this._element, EVENT_CLOSED)
     this.dispose()
   }
-
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Alert.getOrCreateInstance(this)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config](this)
-    })
-  }
 }
 
 /**
@@ -78,10 +60,4 @@ class Alert extends BaseComponent {
 
 enableDismissTrigger(Alert, 'close')
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Alert)
-
 export default Alert
index a797f5050d405d6472182bbc41424d60129a54eb..7697edecf2235b96f1d2c96690fad8a6783bdd36 100644 (file)
@@ -7,7 +7,6 @@
 
 import BaseComponent from './base-component.js'
 import EventHandler from './dom/event-handler.js'
-import { defineJQueryPlugin } from './util/index.js'
 
 /**
  * Constants
@@ -37,17 +36,6 @@ class Button extends BaseComponent {
     // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
     this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))
   }
-
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Button.getOrCreateInstance(this)
-
-      if (config === 'toggle') {
-        data[config]()
-      }
-    })
-  }
 }
 
 /**
@@ -63,10 +51,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
   data.toggle()
 })
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Button)
-
 export default Button
index 68d11a32f2ab267d6d7eb8fb6389301fc2aaaa0e..a8df5f7b533fa1c43aff84680fcca315ae1e306f 100644 (file)
@@ -10,7 +10,6 @@ import EventHandler from './dom/event-handler.js'
 import Manipulator from './dom/manipulator.js'
 import SelectorEngine from './dom/selector-engine.js'
 import {
-  defineJQueryPlugin,
   getNextActiveElement,
   isRTL,
   isVisible,
@@ -404,25 +403,6 @@ class Carousel extends BaseComponent {
     return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT
   }
 
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Carousel.getOrCreateInstance(this, config)
-
-      if (typeof config === 'number') {
-        data.to(config)
-        return
-      }
-
-      if (typeof config === 'string') {
-        if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
-          throw new TypeError(`No method named "${config}"`)
-        }
-
-        data[config]()
-      }
-    })
-  }
 }
 
 /**
@@ -465,10 +445,4 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
   }
 })
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Carousel)
-
 export default Carousel
index b308863f468fb39597f096d49a28aedfae8521ad..6e3bfe9bcb194c6da43a96f5aca633fc33e2be7e 100644 (file)
@@ -9,7 +9,6 @@ import BaseComponent from './base-component.js'
 import EventHandler from './dom/event-handler.js'
 import SelectorEngine from './dom/selector-engine.js'
 import {
-  defineJQueryPlugin,
   getElement,
   reflow
 } from './util/index.js'
@@ -251,26 +250,6 @@ class Collapse extends BaseComponent {
       element.setAttribute('aria-expanded', isOpen)
     }
   }
-
-  // Static
-  static jQueryInterface(config) {
-    const _config = {}
-    if (typeof config === 'string' && /show|hide/.test(config)) {
-      _config.toggle = false
-    }
-
-    return this.each(function () {
-      const data = Collapse.getOrCreateInstance(this, _config)
-
-      if (typeof config === 'string') {
-        if (typeof data[config] === 'undefined') {
-          throw new TypeError(`No method named "${config}"`)
-        }
-
-        data[config]()
-      }
-    })
-  }
 }
 
 /**
@@ -288,10 +267,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
   }
 })
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Collapse)
-
 export default Collapse
index 561d8751d7ca9fa76a5a2ba1884adbe099269f28..5b2d4c1dd8c9ecfe3210c37aa1e0027986faf314 100644 (file)
@@ -5,8 +5,6 @@
  * --------------------------------------------------------------------------
  */
 
-import { getjQuery } from '../util/index.js'
-
 /**
  * Constants
  */
@@ -261,38 +259,8 @@ const EventHandler = {
       return null
     }
 
-    const $ = getjQuery()
-    const typeEvent = getTypeEvent(event)
-    const inNamespace = event !== typeEvent
-
-    let jQueryEvent = null
-    let bubbles = true
-    let nativeDispatch = true
-    let defaultPrevented = false
-
-    if (inNamespace && $) {
-      jQueryEvent = $.Event(event, args)
-
-      $(element).trigger(jQueryEvent)
-      bubbles = !jQueryEvent.isPropagationStopped()
-      nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()
-      defaultPrevented = jQueryEvent.isDefaultPrevented()
-    }
-
-    const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)
-
-    if (defaultPrevented) {
-      evt.preventDefault()
-    }
-
-    if (nativeDispatch) {
-      element.dispatchEvent(evt)
-    }
-
-    if (evt.defaultPrevented && jQueryEvent) {
-      jQueryEvent.preventDefault()
-    }
-
+    const evt = hydrateObj(new Event(event, { bubbles: true, cancelable: true }), args)
+    element.dispatchEvent(evt)
     return evt
   }
 }
index 88af932f76cbcfb39d698bc09a6cff22c311c33d..c9816d043a1874a8d212af96fc7c4bcfbf550805 100644 (file)
@@ -11,7 +11,6 @@ import EventHandler from './dom/event-handler.js'
 import Manipulator from './dom/manipulator.js'
 import SelectorEngine from './dom/selector-engine.js'
 import {
-  defineJQueryPlugin,
   execute,
   getElement,
   getNextActiveElement,
@@ -339,23 +338,6 @@ class Dropdown extends BaseComponent {
     getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()
   }
 
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Dropdown.getOrCreateInstance(this, config)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (typeof data[config] === 'undefined') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config]()
-    })
-  }
-
   static clearMenus(event) {
     if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) {
       return
@@ -449,10 +431,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
   Dropdown.getOrCreateInstance(this).toggle()
 })
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Dropdown)
-
 export default Dropdown
index dd61649ecce0e0752a1fded72942ef02003e9d4d..538d218653514a1ad01d5faa579dc04f18a23dc8 100644 (file)
@@ -12,7 +12,7 @@ import Backdrop from './util/backdrop.js'
 import { enableDismissTrigger } from './util/component-functions.js'
 import FocusTrap from './util/focustrap.js'
 import {
-  defineJQueryPlugin, isRTL, isVisible, reflow
+  isRTL, isVisible, reflow
 } from './util/index.js'
 import ScrollBarHelper from './util/scrollbar.js'
 
@@ -313,23 +313,6 @@ class Modal extends BaseComponent {
     this._element.style.paddingLeft = ''
     this._element.style.paddingRight = ''
   }
-
-  // Static
-  static jQueryInterface(config, relatedTarget) {
-    return this.each(function () {
-      const data = Modal.getOrCreateInstance(this, config)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (typeof data[config] === 'undefined') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config](relatedTarget)
-    })
-  }
 }
 
 /**
@@ -369,10 +352,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
 
 enableDismissTrigger(Modal)
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Modal)
-
 export default Modal
index 8d1feb13bb78b1281893714f31c7aac51cf0841a..decc156439cdedd0bf1009a0e825fe9611982efe 100644 (file)
@@ -12,7 +12,6 @@ import Backdrop from './util/backdrop.js'
 import { enableDismissTrigger } from './util/component-functions.js'
 import FocusTrap from './util/focustrap.js'
 import {
-  defineJQueryPlugin,
   isDisabled,
   isVisible
 } from './util/index.js'
@@ -207,22 +206,6 @@ class Offcanvas extends BaseComponent {
     })
   }
 
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Offcanvas.getOrCreateInstance(this, config)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config](this)
-    })
-  }
 }
 
 /**
@@ -273,10 +256,4 @@ EventHandler.on(window, EVENT_RESIZE, () => {
 
 enableDismissTrigger(Offcanvas)
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Offcanvas)
-
 export default Offcanvas
index 612c5218fc9c97a19594ac918428ed79c14688e0..b8383dc0d5b1558a5a28dcad31c27d2b51d164cd 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 import Tooltip from './tooltip.js'
-import { defineJQueryPlugin } from './util/index.js'
 
 /**
  * Constants
@@ -69,29 +68,6 @@ class Popover extends Tooltip {
   _getContent() {
     return this._resolvePossibleFunction(this._config.content)
   }
-
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Popover.getOrCreateInstance(this, config)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (typeof data[config] === 'undefined') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config]()
-    })
-  }
 }
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Popover)
-
 export default Popover
index 368092de45c94b2684a0a93808cea921c3593967..f3473ab2bdc93f6d89b0098e7aabb19e085cd9f2 100644 (file)
@@ -9,7 +9,7 @@ import BaseComponent from './base-component.js'
 import EventHandler from './dom/event-handler.js'
 import SelectorEngine from './dom/selector-engine.js'
 import {
-  defineJQueryPlugin, getElement, isDisabled, isVisible
+  getElement, isDisabled, isVisible
 } from './util/index.js'
 
 /**
@@ -259,22 +259,6 @@ class ScrollSpy extends BaseComponent {
     }
   }
 
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = ScrollSpy.getOrCreateInstance(this, config)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config]()
-    })
-  }
 }
 
 /**
@@ -287,10 +271,4 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
   }
 })
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(ScrollSpy)
-
 export default ScrollSpy
index dfaef0ffa2fa4baf590963912d35b48e2a295445..989a37a657f9a51fdf4078c0af3b1416b517402a 100644 (file)
@@ -8,7 +8,7 @@
 import BaseComponent from './base-component.js'
 import EventHandler from './dom/event-handler.js'
 import SelectorEngine from './dom/selector-engine.js'
-import { defineJQueryPlugin, getNextActiveElement, isDisabled } from './util/index.js'
+import { getNextActiveElement, isDisabled } from './util/index.js'
 
 /**
  * Constants
@@ -263,23 +263,6 @@ class Tab extends BaseComponent {
   _getOuterElement(elem) {
     return elem.closest(SELECTOR_OUTER) || elem
   }
-
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Tab.getOrCreateInstance(this)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config]()
-    })
-  }
 }
 
 /**
@@ -306,10 +289,5 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
     Tab.getOrCreateInstance(element)
   }
 })
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Tab)
 
 export default Tab
index 82369ebef40d8c5be9dcb10ce4eca8d750791156..4c3ea2f63ef3b2c4f3795cfc2b56b408d307da1e 100644 (file)
@@ -8,7 +8,7 @@
 import BaseComponent from './base-component.js'
 import EventHandler from './dom/event-handler.js'
 import { enableDismissTrigger } from './util/component-functions.js'
-import { defineJQueryPlugin, reflow } from './util/index.js'
+import { reflow } from './util/index.js'
 
 /**
  * Constants
@@ -192,21 +192,6 @@ class Toast extends BaseComponent {
     clearTimeout(this._timeout)
     this._timeout = null
   }
-
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Toast.getOrCreateInstance(this, config)
-
-      if (typeof config === 'string') {
-        if (typeof data[config] === 'undefined') {
-          throw new TypeError(`No method named "${config}"`)
-        }
-
-        data[config](this)
-      }
-    })
-  }
 }
 
 /**
@@ -215,10 +200,4 @@ class Toast extends BaseComponent {
 
 enableDismissTrigger(Toast)
 
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Toast)
-
 export default Toast
index 097477f7a1a813387caa92b33f585fb9cc3d07c7..9b7584e6393d4b35ac93cc6cf67416927b1d37b6 100644 (file)
@@ -10,7 +10,7 @@ import BaseComponent from './base-component.js'
 import EventHandler from './dom/event-handler.js'
 import Manipulator from './dom/manipulator.js'
 import {
-  defineJQueryPlugin, execute, findShadowRoot, getElement, getUID, isRTL, noop
+  execute, findShadowRoot, getElement, getUID, isRTL, noop
 } from './util/index.js'
 import { DefaultAllowlist } from './util/sanitizer.js'
 import TemplateFactory from './util/template-factory.js'
@@ -604,29 +604,5 @@ class Tooltip extends BaseComponent {
       this.tip = null
     }
   }
-
-  // Static
-  static jQueryInterface(config) {
-    return this.each(function () {
-      const data = Tooltip.getOrCreateInstance(this, config)
-
-      if (typeof config !== 'string') {
-        return
-      }
-
-      if (typeof data[config] === 'undefined') {
-        throw new TypeError(`No method named "${config}"`)
-      }
-
-      data[config]()
-    })
-  }
 }
-
-/**
- * jQuery
- */
-
-defineJQueryPlugin(Tooltip)
-
 export default Tooltip
index c271cc5368ca889a569eb6c26b6933f4b56c662c..4f35f31a5d6bf68fece9428cf6fbdf061a24c0a5 100644 (file)
@@ -176,14 +176,6 @@ const reflow = element => {
   element.offsetHeight // eslint-disable-line no-unused-expressions
 }
 
-const getjQuery = () => {
-  if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
-    return window.jQuery
-  }
-
-  return null
-}
-
 const DOMContentLoadedCallbacks = []
 
 const onDOMContentLoaded = callback => {
@@ -205,23 +197,6 @@ const onDOMContentLoaded = callback => {
 
 const isRTL = () => document.documentElement.dir === 'rtl'
 
-const defineJQueryPlugin = plugin => {
-  onDOMContentLoaded(() => {
-    const $ = getjQuery()
-    /* istanbul ignore if */
-    if ($) {
-      const name = plugin.NAME
-      const JQUERY_NO_CONFLICT = $.fn[name]
-      $.fn[name] = plugin.jQueryInterface
-      $.fn[name].Constructor = plugin
-      $.fn[name].noConflict = () => {
-        $.fn[name] = JQUERY_NO_CONFLICT
-        return plugin.jQueryInterface
-      }
-    }
-  })
-}
-
 const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
   return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue
 }
@@ -284,12 +259,10 @@ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed
 }
 
 export {
-  defineJQueryPlugin,
   execute,
   executeAfterTransition,
   findShadowRoot,
   getElement,
-  getjQuery,
   getNextActiveElement,
   getTransitionDurationFromElement,
   getUID,
index 5a54d290dcbe2ca8df184aa616fc327bc9463463..81177a074aee244f7db39cb83e99f9e0929b2681 100644 (file)
@@ -263,47 +263,6 @@ const tooltip = new bootstrap.Tooltip(yourTooltipEl, {
 })
 ```
 
-## Optionally using jQuery
-
-**You don’t need jQuery in Bootstrap 5**, but it’s still possible to use our components with jQuery. If Bootstrap detects `jQuery` in the `window` object, it'll add all of our components in jQuery’s plugin system. This allows you to do the following:
-
-```js
-// to enable tooltips with the default configuration
-$('[data-bs-toggle="tooltip"]').tooltip()
-
-// to initialize tooltips with given configuration
-$('[data-bs-toggle="tooltip"]').tooltip({
-  boundary: 'clippingParents',
-  customClass: 'myClass'
-})
-
-// to trigger the `show` method
-$('#myTooltip').tooltip('show')
-```
-
-The same goes for our other components.
-
-### No conflict
-
-Sometimes it is necessary to use Bootstrap plugins with other UI frameworks. In these circumstances, namespace collisions can occasionally occur. If this happens, you may call `.noConflict` on the plugin you wish to revert the value of.
-
-```js
-const bootstrapButton = $.fn.button.noConflict() // return $.fn.button to previously assigned value
-$.fn.bootstrapBtn = bootstrapButton // give $().bootstrapBtn the Bootstrap functionality
-```
-
-Bootstrap does not officially support third-party JavaScript libraries like Prototype or jQuery UI. Despite `.noConflict` and namespaced events, there may be compatibility problems that you need to fix on your own.
-
-### jQuery events
-
-Bootstrap will detect jQuery if `jQuery` is present in the `window` object and there is no `data-bs-no-jquery` attribute set on `<body>`. If jQuery is found, Bootstrap will emit events thanks to jQuery’s event system. So if you want to listen to Bootstrap’s events, you’ll have to use the jQuery methods (`.on`, `.one`) instead of `addEventListener`.
-
-```js
-$('#myTab a').on('shown.bs.tab', () => {
-  // do something...
-})
-```
-
 ## Disabled JavaScript
 
 Bootstrap’s plugins have no special fallback when JavaScript is disabled. If you care about the user experience in this case, use [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript) to explain the situation (and how to re-enable JavaScript) to your users, and/or add your own custom fallbacks.