Proyectos de Subversion Moodle

Rev

Rev 1 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 1 Rev 1441
Línea 1... Línea 1...
1
/**
1
/**
2
 * --------------------------------------------------------------------------
2
 * --------------------------------------------------------------------------
3
 * Bootstrap (v4.6.2): tab.js
3
 * Bootstrap tab.js
4
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
4
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
 * --------------------------------------------------------------------------
5
 * --------------------------------------------------------------------------
6
 */
6
 */
Línea 7... Línea 7...
7
 
7
 
8
import $ from 'jquery'
8
import BaseComponent from './base-component'
-
 
9
import EventHandler from './dom/event-handler'
-
 
10
import SelectorEngine from './dom/selector-engine'
Línea 9... Línea 11...
9
import Util from './util'
11
import { defineJQueryPlugin, getNextActiveElement, isDisabled } from './util/index'
10
 
12
 
11
/**
13
/**
Línea 12... Línea 14...
12
 * Constants
14
 * Constants
13
 */
-
 
14
 
15
 */
15
const NAME = 'tab'
16
 
16
const VERSION = '4.6.2'
-
 
17
const DATA_KEY = 'bs.tab'
-
 
18
const EVENT_KEY = `.${DATA_KEY}`
-
 
19
const DATA_API_KEY = '.data-api'
-
 
20
const JQUERY_NO_CONFLICT = $.fn[NAME]
-
 
21
 
-
 
22
const CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu'
-
 
23
const CLASS_NAME_ACTIVE = 'active'
-
 
Línea 24... Línea 17...
24
const CLASS_NAME_DISABLED = 'disabled'
17
const NAME = 'tab'
25
const CLASS_NAME_FADE = 'fade'
18
const DATA_KEY = 'bs.tab'
26
const CLASS_NAME_SHOW = 'show'
19
const EVENT_KEY = `.${DATA_KEY}`
27
 
20
 
28
const EVENT_HIDE = `hide${EVENT_KEY}`
21
const EVENT_HIDE = `hide${EVENT_KEY}`
-
 
22
const EVENT_HIDDEN = `hidden${EVENT_KEY}`
-
 
23
const EVENT_SHOW = `show${EVENT_KEY}`
-
 
24
const EVENT_SHOWN = `shown${EVENT_KEY}`
-
 
25
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}`
-
 
26
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
-
 
27
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}`
-
 
28
 
-
 
29
const ARROW_LEFT_KEY = 'ArrowLeft'
-
 
30
const ARROW_RIGHT_KEY = 'ArrowRight'
-
 
31
const ARROW_UP_KEY = 'ArrowUp'
-
 
32
const ARROW_DOWN_KEY = 'ArrowDown'
-
 
33
const HOME_KEY = 'Home'
-
 
34
const END_KEY = 'End'
-
 
35
 
Línea 29... Línea -...
29
const EVENT_HIDDEN = `hidden${EVENT_KEY}`
-
 
30
const EVENT_SHOW = `show${EVENT_KEY}`
-
 
31
const EVENT_SHOWN = `shown${EVENT_KEY}`
-
 
32
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
-
 
33
 
-
 
34
const SELECTOR_DROPDOWN = '.dropdown'
36
const CLASS_NAME_ACTIVE = 'active'
35
const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'
37
const CLASS_NAME_FADE = 'fade'
-
 
38
const CLASS_NAME_SHOW = 'show'
-
 
39
const CLASS_DROPDOWN = 'dropdown'
-
 
40
 
-
 
41
const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'
-
 
42
const SELECTOR_DROPDOWN_MENU = '.dropdown-menu'
-
 
43
const NOT_SELECTOR_DROPDOWN_TOGGLE = `:not(${SELECTOR_DROPDOWN_TOGGLE})`
-
 
44
 
-
 
45
const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]'
-
 
46
const SELECTOR_OUTER = '.nav-item, .list-group-item'
Línea 36... Línea 47...
36
const SELECTOR_ACTIVE = '.active'
47
const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`
37
const SELECTOR_ACTIVE_UL = '> li > .active'
48
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]' // TODO: could only be `tab` in v6
38
const SELECTOR_DATA_TOGGLE = '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]'
49
const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`
Línea 39... Línea 50...
39
const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'
50
 
40
const SELECTOR_DROPDOWN_ACTIVE_CHILD = '> .dropdown-menu .active'
51
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"]`
41
 
52
 
-
 
53
/**
-
 
54
 * Class definition
-
 
55
 */
-
 
56
 
-
 
57
class Tab extends BaseComponent {
-
 
58
  constructor(element) {
-
 
59
    super(element)
-
 
60
    this._parent = this._element.closest(SELECTOR_TAB_PANEL)
-
 
61
 
-
 
62
    if (!this._parent) {
-
 
63
      return
-
 
64
      // TODO: should throw exception in v6
42
/**
65
      // throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`)
Línea 43... Línea 66...
43
 * Class definition
66
    }
44
 */
67
 
45
 
68
    // Set up initial aria attributes
46
class Tab {
69
    this._setInitialAttributes(this._parent, this._getChildren())
Línea 47... Línea 70...
47
  constructor(element) {
70
 
48
    this._element = element
-
 
49
  }
-
 
50
 
71
    EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event))
51
  // Getters
72
  }
52
  static get VERSION() {
-
 
53
    return VERSION
73
 
54
  }
74
  // Getters
55
 
75
  static get NAME() {
Línea 56... Línea 76...
56
  // Public
76
    return NAME
57
  show() {
77
  }
-
 
78
 
58
    if (this._element.parentNode &&
79
  // Public
59
        this._element.parentNode.nodeType === Node.ELEMENT_NODE &&
80
  show() { // Shows this elem and deactivate the active sibling if exists
-
 
81
    const innerElem = this._element
Línea 60... Línea -...
60
        $(this._element).hasClass(CLASS_NAME_ACTIVE) ||
-
 
61
        $(this._element).hasClass(CLASS_NAME_DISABLED) ||
82
    if (this._elemIsActive(innerElem)) {
-
 
83
      return
62
        this._element.hasAttribute('disabled')) {
84
    }
63
      return
85
 
64
    }
86
    // Search for active tab on same parent to deactivate it
Línea 65... Línea 87...
65
 
87
    const active = this._getActiveElem()
66
    let target
88
 
67
    let previous
89
    const hideEvent = active ?
Línea -... Línea 90...
-
 
90
      EventHandler.trigger(active, EVENT_HIDE, { relatedTarget: innerElem }) :
68
    const listElement = $(this._element).closest(SELECTOR_NAV_LIST_GROUP)[0]
91
      null
69
    const selector = Util.getSelectorFromElement(this._element)
92
 
-
 
93
    const showEvent = EventHandler.trigger(innerElem, EVENT_SHOW, { relatedTarget: active })
70
 
94
 
-
 
95
    if (showEvent.defaultPrevented || (hideEvent && hideEvent.defaultPrevented)) {
-
 
96
      return
-
 
97
    }
-
 
98
 
Línea -... Línea 99...
-
 
99
    this._deactivate(active, innerElem)
-
 
100
    this._activate(innerElem, active)
-
 
101
  }
71
    if (listElement) {
102
 
-
 
103
  // Private
-
 
104
  _activate(element, relatedElem) {
72
      const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE
105
    if (!element) {
-
 
106
      return
-
 
107
    }
-
 
108
 
-
 
109
    element.classList.add(CLASS_NAME_ACTIVE)
-
 
110
 
73
      previous = $.makeArray($(listElement).find(itemSelector))
111
    this._activate(SelectorEngine.getElementFromSelector(element)) // Search and activate/show the proper section
Línea 74... Línea 112...
74
      previous = previous[previous.length - 1]
112
 
-
 
113
    const complete = () => {
Línea 75... Línea 114...
75
    }
114
      if (element.getAttribute('role') !== 'tab') {
76
 
115
        element.classList.add(CLASS_NAME_SHOW)
77
    const hideEvent = $.Event(EVENT_HIDE, {
116
        return
78
      relatedTarget: this._element
117
      }
Línea 79... Línea -...
79
    })
-
 
80
 
118
 
81
    const showEvent = $.Event(EVENT_SHOW, {
119
      element.removeAttribute('tabindex')
Línea 82... Línea 120...
82
      relatedTarget: previous
120
      element.setAttribute('aria-selected', true)
83
    })
-
 
84
 
-
 
85
    if (previous) {
-
 
Línea 86... Línea 121...
86
      $(previous).trigger(hideEvent)
121
      this._toggleDropDown(element, true)
87
    }
122
      EventHandler.trigger(element, EVENT_SHOWN, {
88
 
123
        relatedTarget: relatedElem
-
 
124
      })
89
    $(this._element).trigger(showEvent)
125
    }
Línea 90... Línea 126...
90
 
126
 
91
    if (showEvent.isDefaultPrevented() ||
127
    this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE))
-
 
128
  }
-
 
129
 
92
        hideEvent.isDefaultPrevented()) {
130
  _deactivate(element, relatedElem) {
-
 
131
    if (!element) {
-
 
132
      return
-
 
133
    }
Línea 93... Línea 134...
93
      return
134
 
-
 
135
    element.classList.remove(CLASS_NAME_ACTIVE)
94
    }
136
    element.blur()
95
 
137
 
Línea -... Línea 138...
-
 
138
    this._deactivate(SelectorEngine.getElementFromSelector(element)) // Search and deactivate the shown section too
96
    if (selector) {
139
 
-
 
140
    const complete = () => {
97
      target = document.querySelector(selector)
141
      if (element.getAttribute('role') !== 'tab') {
-
 
142
        element.classList.remove(CLASS_NAME_SHOW)
-
 
143
        return
-
 
144
      }
-
 
145
 
98
    }
146
      element.setAttribute('aria-selected', false)
-
 
147
      element.setAttribute('tabindex', '-1')
-
 
148
      this._toggleDropDown(element, false)
-
 
149
      EventHandler.trigger(element, EVENT_HIDDEN, { relatedTarget: relatedElem })
-
 
150
    }
99
 
151
 
-
 
152
    this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE))
-
 
153
  }
100
    this._activate(
154
 
101
      this._element,
155
  _keydown(event) {
Línea 102... Línea -...
102
      listElement
-
 
103
    )
156
    if (!([ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY, HOME_KEY, END_KEY].includes(event.key))) {
104
 
157
      return
105
    const complete = () => {
158
    }
Línea 106... Línea -...
106
      const hiddenEvent = $.Event(EVENT_HIDDEN, {
-
 
107
        relatedTarget: this._element
-
 
108
      })
-
 
109
 
-
 
110
      const shownEvent = $.Event(EVENT_SHOWN, {
-
 
111
        relatedTarget: previous
-
 
112
      })
-
 
113
 
-
 
114
      $(previous).trigger(hiddenEvent)
-
 
115
      $(this._element).trigger(shownEvent)
-
 
116
    }
159
 
117
 
-
 
118
    if (target) {
-
 
119
      this._activate(target, target.parentNode, complete)
-
 
120
    } else {
-
 
121
      complete()
160
    event.stopPropagation()// stopPropagation/preventDefault both added to support up/down keys without scrolling the page
122
    }
-
 
123
  }
-
 
124
 
-
 
125
  dispose() {
-
 
126
    $.removeData(this._element, DATA_KEY)
-
 
127
    this._element = null
-
 
128
  }
-
 
129
 
-
 
130
  // Private
161
    event.preventDefault()
Línea 131... Línea 162...
131
  _activate(element, container, callback) {
162
 
132
    const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ?
-
 
133
      $(container).find(SELECTOR_ACTIVE_UL) :
163
    const children = this._getChildren().filter(element => !isDisabled(element))
Línea 134... Línea 164...
134
      $(container).children(SELECTOR_ACTIVE)
164
    let nextActiveElement
135
 
165
 
136
    const active = activeElements[0]
166
    if ([HOME_KEY, END_KEY].includes(event.key)) {
-
 
167
      nextActiveElement = children[event.key === HOME_KEY ? 0 : children.length - 1]
Línea 137... Línea 168...
137
    const isTransitioning = callback && (active && $(active).hasClass(CLASS_NAME_FADE))
168
    } else {
-
 
169
      const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key)
138
    const complete = () => this._transitionComplete(
170
      nextActiveElement = getNextActiveElement(children, event.target, isNext, true)
139
      element,
171
    }
-
 
172
 
Línea 140... Línea 173...
140
      active,
173
    if (nextActiveElement) {
141
      callback
174
      nextActiveElement.focus({ preventScroll: true })
142
    )
-
 
143
 
175
      Tab.getOrCreateInstance(nextActiveElement).show()
Línea 144... Línea -...
144
    if (active && isTransitioning) {
-
 
145
      const transitionDuration = Util.getTransitionDurationFromElement(active)
176
    }
146
 
177
  }
147
      $(active)
178
 
Línea 148... Línea 179...
148
        .removeClass(CLASS_NAME_SHOW)
179
  _getChildren() { // collection of inner elements
Línea 149... Línea 180...
149
        .one(Util.TRANSITION_END, complete)
180
    return SelectorEngine.find(SELECTOR_INNER_ELEM, this._parent)
150
        .emulateTransitionEnd(transitionDuration)
181
  }
151
    } else {
182
 
-
 
183
  _getActiveElem() {
-
 
184
    return this._getChildren().find(child => this._elemIsActive(child)) || null
-
 
185
  }
Línea 152... Línea -...
152
      complete()
-
 
153
    }
186
 
154
  }
187
  _setInitialAttributes(parent, children) {
155
 
188
    this._setAttributeIfNotExists(parent, 'role', 'tablist')
Línea 156... Línea 189...
156
  _transitionComplete(element, active, callback) {
189
 
157
    if (active) {
-
 
Línea 158... Línea 190...
158
      $(active).removeClass(CLASS_NAME_ACTIVE)
190
    for (const child of children) {
159
 
191
      this._setInitialAttributesOnChild(child)
-
 
192
    }
-
 
193
  }
Línea -... Línea 194...
-
 
194
 
-
 
195
  _setInitialAttributesOnChild(child) {
160
      const dropdownChild = $(active.parentNode).find(
196
    child = this._getInnerElement(child)
-
 
197
    const isActive = this._elemIsActive(child)
161
        SELECTOR_DROPDOWN_ACTIVE_CHILD
198
    const outerElem = this._getOuterElement(child)
Línea -... Línea 199...
-
 
199
    child.setAttribute('aria-selected', isActive)
-
 
200
 
-
 
201
    if (outerElem !== child) {
162
      )[0]
202
      this._setAttributeIfNotExists(outerElem, 'role', 'presentation')
-
 
203
    }
163
 
204
 
Línea -... Línea 205...
-
 
205
    if (!isActive) {
-
 
206
      child.setAttribute('tabindex', '-1')
-
 
207
    }
-
 
208
 
-
 
209
    this._setAttributeIfNotExists(child, 'role', 'tab')
-
 
210
 
164
      if (dropdownChild) {
211
    // set attributes to the related panel too
165
        $(dropdownChild).removeClass(CLASS_NAME_ACTIVE)
212
    this._setInitialAttributesOnTargetPanel(child)
166
      }
213
  }
167
 
214
 
Línea -... Línea 215...
-
 
215
  _setInitialAttributesOnTargetPanel(child) {
-
 
216
    const target = SelectorEngine.getElementFromSelector(child)
-
 
217
 
-
 
218
    if (!target) {
-
 
219
      return
-
 
220
    }
-
 
221
 
-
 
222
    this._setAttributeIfNotExists(target, 'role', 'tabpanel')
-
 
223
 
-
 
224
    if (child.id) {
-
 
225
      this._setAttributeIfNotExists(target, 'aria-labelledby', `${child.id}`)
-
 
226
    }
-
 
227
  }
-
 
228
 
168
      if (active.getAttribute('role') === 'tab') {
229
  _toggleDropDown(element, open) {
169
        active.setAttribute('aria-selected', false)
230
    const outerElem = this._getOuterElement(element)
170
      }
231
    if (!outerElem.classList.contains(CLASS_DROPDOWN)) {
171
    }
-
 
172
 
232
      return
Línea 173... Línea 233...
173
    $(element).addClass(CLASS_NAME_ACTIVE)
233
    }
174
    if (element.getAttribute('role') === 'tab') {
234
 
175
      element.setAttribute('aria-selected', true)
-
 
176
    }
235
    const toggle = (selector, className) => {
Línea 177... Línea -...
177
 
-
 
178
    Util.reflow(element)
236
      const element = SelectorEngine.findOne(selector, outerElem)
179
 
237
      if (element) {
180
    if (element.classList.contains(CLASS_NAME_FADE)) {
-
 
181
      element.classList.add(CLASS_NAME_SHOW)
-
 
182
    }
-
 
183
 
238
        element.classList.toggle(className, open)
-
 
239
      }
-
 
240
    }
184
    let parent = element.parentNode
241
 
185
    if (parent && parent.nodeName === 'LI') {
242
    toggle(SELECTOR_DROPDOWN_TOGGLE, CLASS_NAME_ACTIVE)
186
      parent = parent.parentNode
243
    toggle(SELECTOR_DROPDOWN_MENU, CLASS_NAME_SHOW)
Línea 187... Línea 244...
187
    }
244
    outerElem.setAttribute('aria-expanded', open)
188
 
245
  }
189
    if (parent && $(parent).hasClass(CLASS_NAME_DROPDOWN_MENU)) {
246
 
Línea 190... Línea -...
190
      const dropdownElement = $(element).closest(SELECTOR_DROPDOWN)[0]
-
 
191
 
247
  _setAttributeIfNotExists(element, attribute, value) {
-
 
248
    if (!element.hasAttribute(attribute)) {
192
      if (dropdownElement) {
249
      element.setAttribute(attribute, value)
-
 
250
    }
-
 
251
  }
-
 
252
 
-
 
253
  _elemIsActive(elem) {
-
 
254
    return elem.classList.contains(CLASS_NAME_ACTIVE)
-
 
255
  }
193
        const dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(SELECTOR_DROPDOWN_TOGGLE))
256
 
194
 
257
  // Try to get the inner element (usually the .nav-link)
Línea 195... Línea 258...
195
        $(dropdownToggleList).addClass(CLASS_NAME_ACTIVE)
258
  _getInnerElement(elem) {
-
 
259
    return elem.matches(SELECTOR_INNER_ELEM) ? elem : SelectorEngine.findOne(SELECTOR_INNER_ELEM, elem)
-
 
260
  }
-
 
261
 
-
 
262
  // Try to get the outer element (usually the .nav-item)
-
 
263
  _getOuterElement(elem) {
-
 
264
    return elem.closest(SELECTOR_OUTER) || elem
-
 
265
  }
-
 
266
 
196
      }
267
  // Static
197
 
268
  static jQueryInterface(config) {
Línea 198... Línea -...
198
      element.setAttribute('aria-expanded', true)
-
 
199
    }
-
 
200
 
-
 
201
    if (callback) {
-
 
202
      callback()
269
    return this.each(function () {
203
    }
-
 
Línea 204... Línea 270...
204
  }
270
      const data = Tab.getOrCreateInstance(this)