]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
feat: add Hash/History helper to handle ref:#36647
authorGeoSot <geo.sotis@gmail.com>
Wed, 29 Jun 2022 23:10:34 +0000 (02:10 +0300)
committerGeoSot <geo.sotis@gmail.com>
Sat, 16 Jul 2022 22:17:20 +0000 (01:17 +0300)
js/src/offcanvas.js
js/src/util/history.js [new file with mode: 0644]

index 30a9a45136e4046c2b27fc5900d173d21ca150a1..795b41136e5fd33cb5d27e7fe0b745c233f77d73 100644 (file)
@@ -18,6 +18,7 @@ import SelectorEngine from './dom/selector-engine'
 import Backdrop from './util/backdrop'
 import FocusTrap from './util/focustrap'
 import { enableDismissTrigger } from './util/component-functions'
+import HistoryHelper from './util/history'
 
 /**
  * Constants
@@ -70,6 +71,7 @@ class Offcanvas extends BaseComponent {
     this._isShown = false
     this._backdrop = this._initializeBackDrop()
     this._focustrap = this._initializeFocusTrap()
+    this._historyHelper = new HistoryHelper(this._element, { prefix: this.constructor.NAME })
     this._addEventListeners()
   }
 
@@ -112,6 +114,7 @@ class Offcanvas extends BaseComponent {
     this._element.setAttribute('aria-modal', true)
     this._element.setAttribute('role', 'dialog')
     this._element.classList.add(CLASS_NAME_SHOWING)
+    this._historyHelper.add()
 
     const completeCallBack = () => {
       if (!this._config.scroll || this._config.backdrop) {
@@ -152,6 +155,7 @@ class Offcanvas extends BaseComponent {
         new ScrollBarHelper().reset()
       }
 
+      this._historyHelper.remove()
       EventHandler.trigger(this._element, EVENT_HIDDEN)
     }
 
@@ -272,6 +276,17 @@ EventHandler.on(window, EVENT_RESIZE, () => {
   }
 })
 
+HistoryHelper.onChange(Offcanvas, (newUrl, oldUrl) => {
+  if (oldUrl) {
+    Offcanvas.getOrCreateInstance(oldUrl).hide()
+    return
+  }
+
+  if (newUrl) {
+    Offcanvas.getOrCreateInstance(newUrl).show()
+  }
+})
+
 enableDismissTrigger(Offcanvas)
 
 /**
diff --git a/js/src/util/history.js b/js/src/util/history.js
new file mode 100644 (file)
index 0000000..efc13dc
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.2.0-beta1): util/history.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+import Config from './config'
+import EventHandler from '../dom/event-handler'
+
+/**
+ * Constants
+ */
+
+const NAME = 'history'
+
+const Default = {
+  prefix: null
+}
+
+const DefaultType = {
+  prefix: 'string'
+}
+
+/**
+ * Class definition
+ */
+
+class HistoryHelper extends Config {
+  constructor(element, config) {
+    super()
+    this._element = element
+    this._config = this._getConfig(config)
+  }
+
+  // Getters
+  static get Default() {
+    return Default
+  }
+
+  static get DefaultType() {
+    return DefaultType
+  }
+
+  static get NAME() {
+    return NAME
+  }
+
+  add() {
+    const url = new window.URL(window.location)
+    url.hash = this._getHash()
+    window.history.pushState({}, '', url)
+  }
+
+  remove() {
+    if (window.location.hash === `#${this._getHash()}`) {
+      const url = new window.URL(window.location)
+      url.hash = ''
+      window.history.replaceState({}, '', url)
+    }
+  }
+
+  static onChange(plugin, callback) {
+    const prefix = `bs-${plugin.NAME}-`
+    const getHash = url => new window.URL(url)?.hash
+    const sanitize = hash => hash.replace(prefix, '')
+
+    EventHandler.on(window, 'load', () => {
+      const hash = getHash(window.location)
+      if (hash.includes(prefix)) {
+        callback(sanitize(hash), '')
+      }
+    })
+
+    EventHandler.on(window, 'hashchange', ev => {
+      const oldHash = getHash(ev.oldURL)
+      const newHash = getHash(ev.newURL)
+
+      if (oldHash.includes(prefix) || newHash.includes(prefix)) {
+        callback(sanitize(newHash), sanitize(oldHash))
+      }
+    })
+  }
+
+  _getHash() {
+    return `bs-${this._config.prefix}-${this._element.id}`
+  }
+}
+
+export default HistoryHelper