From: GeoSot Date: Wed, 29 Jun 2022 23:10:34 +0000 (+0300) Subject: feat: add Hash/History helper to handle ref:#36647 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f793c30642d033587397b2048c8aafd7455204d4;p=thirdparty%2Fbootstrap.git feat: add Hash/History helper to handle ref:#36647 --- diff --git a/js/src/offcanvas.js b/js/src/offcanvas.js index 30a9a45136..795b41136e 100644 --- a/js/src/offcanvas.js +++ b/js/src/offcanvas.js @@ -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 index 0000000000..efc13dc7ec --- /dev/null +++ b/js/src/util/history.js @@ -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