source: imaps-frontend/node_modules/bootstrap/js/dist/tab.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 10.2 KB
RevLine 
[d565449]1/*!
2 * Bootstrap tab.js v5.3.3 (https://getbootstrap.com/)
3 * Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5 */
6(function (global, factory) {
7 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js'), require('./util/index.js')) :
8 typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './dom/selector-engine', './util/index'], factory) :
9 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tab = factory(global.BaseComponent, global.EventHandler, global.SelectorEngine, global.Index));
10})(this, (function (BaseComponent, EventHandler, SelectorEngine, index_js) { 'use strict';
11
12 /**
13 * --------------------------------------------------------------------------
14 * Bootstrap tab.js
15 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
16 * --------------------------------------------------------------------------
17 */
18
19
20 /**
21 * Constants
22 */
23
24 const NAME = 'tab';
25 const DATA_KEY = 'bs.tab';
26 const EVENT_KEY = `.${DATA_KEY}`;
27 const EVENT_HIDE = `hide${EVENT_KEY}`;
28 const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
29 const EVENT_SHOW = `show${EVENT_KEY}`;
30 const EVENT_SHOWN = `shown${EVENT_KEY}`;
31 const EVENT_CLICK_DATA_API = `click${EVENT_KEY}`;
32 const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
33 const EVENT_LOAD_DATA_API = `load${EVENT_KEY}`;
34 const ARROW_LEFT_KEY = 'ArrowLeft';
35 const ARROW_RIGHT_KEY = 'ArrowRight';
36 const ARROW_UP_KEY = 'ArrowUp';
37 const ARROW_DOWN_KEY = 'ArrowDown';
38 const HOME_KEY = 'Home';
39 const END_KEY = 'End';
40 const CLASS_NAME_ACTIVE = 'active';
41 const CLASS_NAME_FADE = 'fade';
42 const CLASS_NAME_SHOW = 'show';
43 const CLASS_DROPDOWN = 'dropdown';
44 const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
45 const SELECTOR_DROPDOWN_MENU = '.dropdown-menu';
46 const NOT_SELECTOR_DROPDOWN_TOGGLE = `:not(${SELECTOR_DROPDOWN_TOGGLE})`;
47 const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]';
48 const SELECTOR_OUTER = '.nav-item, .list-group-item';
49 const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`;
50 const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]'; // TODO: could only be `tab` in v6
51 const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`;
52 const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="pill"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="list"]`;
53
54 /**
55 * Class definition
56 */
57
58 class Tab extends BaseComponent {
59 constructor(element) {
60 super(element);
61 this._parent = this._element.closest(SELECTOR_TAB_PANEL);
62 if (!this._parent) {
63 return;
64 // TODO: should throw exception in v6
65 // throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`)
66 }
67
68 // Set up initial aria attributes
69 this._setInitialAttributes(this._parent, this._getChildren());
70 EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event));
71 }
72
73 // Getters
74 static get NAME() {
75 return NAME;
76 }
77
78 // Public
79 show() {
80 // Shows this elem and deactivate the active sibling if exists
81 const innerElem = this._element;
82 if (this._elemIsActive(innerElem)) {
83 return;
84 }
85
86 // Search for active tab on same parent to deactivate it
87 const active = this._getActiveElem();
88 const hideEvent = active ? EventHandler.trigger(active, EVENT_HIDE, {
89 relatedTarget: innerElem
90 }) : null;
91 const showEvent = EventHandler.trigger(innerElem, EVENT_SHOW, {
92 relatedTarget: active
93 });
94 if (showEvent.defaultPrevented || hideEvent && hideEvent.defaultPrevented) {
95 return;
96 }
97 this._deactivate(active, innerElem);
98 this._activate(innerElem, active);
99 }
100
101 // Private
102 _activate(element, relatedElem) {
103 if (!element) {
104 return;
105 }
106 element.classList.add(CLASS_NAME_ACTIVE);
107 this._activate(SelectorEngine.getElementFromSelector(element)); // Search and activate/show the proper section
108
109 const complete = () => {
110 if (element.getAttribute('role') !== 'tab') {
111 element.classList.add(CLASS_NAME_SHOW);
112 return;
113 }
114 element.removeAttribute('tabindex');
115 element.setAttribute('aria-selected', true);
116 this._toggleDropDown(element, true);
117 EventHandler.trigger(element, EVENT_SHOWN, {
118 relatedTarget: relatedElem
119 });
120 };
121 this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE));
122 }
123 _deactivate(element, relatedElem) {
124 if (!element) {
125 return;
126 }
127 element.classList.remove(CLASS_NAME_ACTIVE);
128 element.blur();
129 this._deactivate(SelectorEngine.getElementFromSelector(element)); // Search and deactivate the shown section too
130
131 const complete = () => {
132 if (element.getAttribute('role') !== 'tab') {
133 element.classList.remove(CLASS_NAME_SHOW);
134 return;
135 }
136 element.setAttribute('aria-selected', false);
137 element.setAttribute('tabindex', '-1');
138 this._toggleDropDown(element, false);
139 EventHandler.trigger(element, EVENT_HIDDEN, {
140 relatedTarget: relatedElem
141 });
142 };
143 this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE));
144 }
145 _keydown(event) {
146 if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY, HOME_KEY, END_KEY].includes(event.key)) {
147 return;
148 }
149 event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page
150 event.preventDefault();
151 const children = this._getChildren().filter(element => !index_js.isDisabled(element));
152 let nextActiveElement;
153 if ([HOME_KEY, END_KEY].includes(event.key)) {
154 nextActiveElement = children[event.key === HOME_KEY ? 0 : children.length - 1];
155 } else {
156 const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key);
157 nextActiveElement = index_js.getNextActiveElement(children, event.target, isNext, true);
158 }
159 if (nextActiveElement) {
160 nextActiveElement.focus({
161 preventScroll: true
162 });
163 Tab.getOrCreateInstance(nextActiveElement).show();
164 }
165 }
166 _getChildren() {
167 // collection of inner elements
168 return SelectorEngine.find(SELECTOR_INNER_ELEM, this._parent);
169 }
170 _getActiveElem() {
171 return this._getChildren().find(child => this._elemIsActive(child)) || null;
172 }
173 _setInitialAttributes(parent, children) {
174 this._setAttributeIfNotExists(parent, 'role', 'tablist');
175 for (const child of children) {
176 this._setInitialAttributesOnChild(child);
177 }
178 }
179 _setInitialAttributesOnChild(child) {
180 child = this._getInnerElement(child);
181 const isActive = this._elemIsActive(child);
182 const outerElem = this._getOuterElement(child);
183 child.setAttribute('aria-selected', isActive);
184 if (outerElem !== child) {
185 this._setAttributeIfNotExists(outerElem, 'role', 'presentation');
186 }
187 if (!isActive) {
188 child.setAttribute('tabindex', '-1');
189 }
190 this._setAttributeIfNotExists(child, 'role', 'tab');
191
192 // set attributes to the related panel too
193 this._setInitialAttributesOnTargetPanel(child);
194 }
195 _setInitialAttributesOnTargetPanel(child) {
196 const target = SelectorEngine.getElementFromSelector(child);
197 if (!target) {
198 return;
199 }
200 this._setAttributeIfNotExists(target, 'role', 'tabpanel');
201 if (child.id) {
202 this._setAttributeIfNotExists(target, 'aria-labelledby', `${child.id}`);
203 }
204 }
205 _toggleDropDown(element, open) {
206 const outerElem = this._getOuterElement(element);
207 if (!outerElem.classList.contains(CLASS_DROPDOWN)) {
208 return;
209 }
210 const toggle = (selector, className) => {
211 const element = SelectorEngine.findOne(selector, outerElem);
212 if (element) {
213 element.classList.toggle(className, open);
214 }
215 };
216 toggle(SELECTOR_DROPDOWN_TOGGLE, CLASS_NAME_ACTIVE);
217 toggle(SELECTOR_DROPDOWN_MENU, CLASS_NAME_SHOW);
218 outerElem.setAttribute('aria-expanded', open);
219 }
220 _setAttributeIfNotExists(element, attribute, value) {
221 if (!element.hasAttribute(attribute)) {
222 element.setAttribute(attribute, value);
223 }
224 }
225 _elemIsActive(elem) {
226 return elem.classList.contains(CLASS_NAME_ACTIVE);
227 }
228
229 // Try to get the inner element (usually the .nav-link)
230 _getInnerElement(elem) {
231 return elem.matches(SELECTOR_INNER_ELEM) ? elem : SelectorEngine.findOne(SELECTOR_INNER_ELEM, elem);
232 }
233
234 // Try to get the outer element (usually the .nav-item)
235 _getOuterElement(elem) {
236 return elem.closest(SELECTOR_OUTER) || elem;
237 }
238
239 // Static
240 static jQueryInterface(config) {
241 return this.each(function () {
242 const data = Tab.getOrCreateInstance(this);
243 if (typeof config !== 'string') {
244 return;
245 }
246 if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
247 throw new TypeError(`No method named "${config}"`);
248 }
249 data[config]();
250 });
251 }
252 }
253
254 /**
255 * Data API implementation
256 */
257
258 EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
259 if (['A', 'AREA'].includes(this.tagName)) {
260 event.preventDefault();
261 }
262 if (index_js.isDisabled(this)) {
263 return;
264 }
265 Tab.getOrCreateInstance(this).show();
266 });
267
268 /**
269 * Initialize on focus
270 */
271 EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
272 for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE_ACTIVE)) {
273 Tab.getOrCreateInstance(element);
274 }
275 });
276 /**
277 * jQuery
278 */
279
280 index_js.defineJQueryPlugin(Tab);
281
282 return Tab;
283
284}));
285//# sourceMappingURL=tab.js.map
Note: See TracBrowser for help on using the repository browser.