codekingpro/portable-devtools
114k
1/**2 * --------------------------------------------------------------------------3 * Bootstrap (v4.6.2): tab.js4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)5 * --------------------------------------------------------------------------6 */7 8import $ from 'jquery'9import Util from './util'10 11/**12 * Constants13 */14 15const NAME = 'tab'16const VERSION = '4.6.2'17const DATA_KEY = 'bs.tab'18const EVENT_KEY = `.${DATA_KEY}`19const DATA_API_KEY = '.data-api'20const JQUERY_NO_CONFLICT = $.fn[NAME]21 22const CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu'23const CLASS_NAME_ACTIVE = 'active'24const CLASS_NAME_DISABLED = 'disabled'25const CLASS_NAME_FADE = 'fade'26const CLASS_NAME_SHOW = 'show'27 28const EVENT_HIDE = `hide${EVENT_KEY}`29const EVENT_HIDDEN = `hidden${EVENT_KEY}`30const EVENT_SHOW = `show${EVENT_KEY}`31const EVENT_SHOWN = `shown${EVENT_KEY}`32const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`33 34const SELECTOR_DROPDOWN = '.dropdown'35const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'36const SELECTOR_ACTIVE = '.active'37const SELECTOR_ACTIVE_UL = '> li > .active'38const SELECTOR_DATA_TOGGLE = '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]'39const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'40const SELECTOR_DROPDOWN_ACTIVE_CHILD = '> .dropdown-menu .active'41 42/**43 * Class definition44 */45 46class Tab {47 constructor(element) {48 this._element = element49 }50 51 // Getters52 static get VERSION() {53 return VERSION54 }55 56 // Public57 show() {58 if (this._element.parentNode &&59 this._element.parentNode.nodeType === Node.ELEMENT_NODE &&60 $(this._element).hasClass(CLASS_NAME_ACTIVE) ||61 $(this._element).hasClass(CLASS_NAME_DISABLED) ||62 this._element.hasAttribute('disabled')) {63 return64 }65 66 let target67 let previous68 const listElement = $(this._element).closest(SELECTOR_NAV_LIST_GROUP)[0]69 const selector = Util.getSelectorFromElement(this._element)70 71 if (listElement) {72 const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE73 previous = $.makeArray($(listElement).find(itemSelector))74 previous = previous[previous.length - 1]75 }76 77 const hideEvent = $.Event(EVENT_HIDE, {78 relatedTarget: this._element79 })80 81 const showEvent = $.Event(EVENT_SHOW, {82 relatedTarget: previous83 })84 85 if (previous) {86 $(previous).trigger(hideEvent)87 }88 89 $(this._element).trigger(showEvent)90 91 if (showEvent.isDefaultPrevented() ||92 hideEvent.isDefaultPrevented()) {93 return94 }95 96 if (selector) {97 target = document.querySelector(selector)98 }99 100 this._activate(101 this._element,102 listElement103 )104 105 const complete = () => {106 const hiddenEvent = $.Event(EVENT_HIDDEN, {107 relatedTarget: this._element108 })109 110 const shownEvent = $.Event(EVENT_SHOWN, {111 relatedTarget: previous112 })113 114 $(previous).trigger(hiddenEvent)115 $(this._element).trigger(shownEvent)116 }117 118 if (target) {119 this._activate(target, target.parentNode, complete)120 } else {121 complete()122 }123 }124 125 dispose() {126 $.removeData(this._element, DATA_KEY)127 this._element = null128 }129 130 // Private131 _activate(element, container, callback) {132 const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ?133 $(container).find(SELECTOR_ACTIVE_UL) :134 $(container).children(SELECTOR_ACTIVE)135 136 const active = activeElements[0]137 const isTransitioning = callback && (active && $(active).hasClass(CLASS_NAME_FADE))138 const complete = () => this._transitionComplete(139 element,140 active,141 callback142 )143 144 if (active && isTransitioning) {145 const transitionDuration = Util.getTransitionDurationFromElement(active)146 147 $(active)148 .removeClass(CLASS_NAME_SHOW)149 .one(Util.TRANSITION_END, complete)150 .emulateTransitionEnd(transitionDuration)151 } else {152 complete()153 }154 }155 156 _transitionComplete(element, active, callback) {157 if (active) {158 $(active).removeClass(CLASS_NAME_ACTIVE)159 160 const dropdownChild = $(active.parentNode).find(161 SELECTOR_DROPDOWN_ACTIVE_CHILD162 )[0]163 164 if (dropdownChild) {165 $(dropdownChild).removeClass(CLASS_NAME_ACTIVE)166 }167 168 if (active.getAttribute('role') === 'tab') {169 active.setAttribute('aria-selected', false)170 }171 }172 173 $(element).addClass(CLASS_NAME_ACTIVE)174 if (element.getAttribute('role') === 'tab') {175 element.setAttribute('aria-selected', true)176 }177 178 Util.reflow(element)179 180 if (element.classList.contains(CLASS_NAME_FADE)) {181 element.classList.add(CLASS_NAME_SHOW)182 }183 184 let parent = element.parentNode185 if (parent && parent.nodeName === 'LI') {186 parent = parent.parentNode187 }188 189 if (parent && $(parent).hasClass(CLASS_NAME_DROPDOWN_MENU)) {190 const dropdownElement = $(element).closest(SELECTOR_DROPDOWN)[0]191 192 if (dropdownElement) {193 const dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(SELECTOR_DROPDOWN_TOGGLE))194 195 $(dropdownToggleList).addClass(CLASS_NAME_ACTIVE)196 }197 198 element.setAttribute('aria-expanded', true)199 }200 201 if (callback) {202 callback()203 }204 }205 206 // Static207 static _jQueryInterface(config) {208 return this.each(function () {209 const $this = $(this)210 let data = $this.data(DATA_KEY)211 212 if (!data) {213 data = new Tab(this)214 $this.data(DATA_KEY, data)215 }216 217 if (typeof config === 'string') {218 if (typeof data[config] === 'undefined') {219 throw new TypeError(`No method named "${config}"`)220 }221 222 data[config]()223 }224 })225 }226}227 228/**229 * Data API implementation230 */231 232$(document)233 .on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {234 event.preventDefault()235 Tab._jQueryInterface.call($(this), 'show')236 })237 238/**239 * jQuery240 */241 242$.fn[NAME] = Tab._jQueryInterface243$.fn[NAME].Constructor = Tab244$.fn[NAME].noConflict = () => {245 $.fn[NAME] = JQUERY_NO_CONFLICT246 return Tab._jQueryInterface247}248 249export default Tab250 