Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
/**
2
 * --------------------------------------------------------------------------
3
 * Bootstrap dom/selector-engine.js
4
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
 * --------------------------------------------------------------------------
6
 */
7
 
8
import { isDisabled, isVisible, parseSelector } from '../util/index'
9
 
10
const getSelector = element => {
11
  let selector = element.getAttribute('data-bs-target')
12
 
13
  if (!selector || selector === '#') {
14
    let hrefAttribute = element.getAttribute('href')
15
 
16
    // The only valid content that could double as a selector are IDs or classes,
17
    // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
18
    // `document.querySelector` will rightfully complain it is invalid.
19
    // See https://github.com/twbs/bootstrap/issues/32273
20
    if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
21
      return null
22
    }
23
 
24
    // Just in case some CMS puts out a full URL with the anchor appended
25
    if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
26
      hrefAttribute = `#${hrefAttribute.split('#')[1]}`
27
    }
28
 
29
    selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
30
  }
31
 
32
  return selector ? selector.split(',').map(sel => parseSelector(sel)).join(',') : null
33
}
34
 
35
const SelectorEngine = {
36
  find(selector, element = document.documentElement) {
37
    return [].concat(...Element.prototype.querySelectorAll.call(element, selector))
38
  },
39
 
40
  findOne(selector, element = document.documentElement) {
41
    return Element.prototype.querySelector.call(element, selector)
42
  },
43
 
44
  children(element, selector) {
45
    return [].concat(...element.children).filter(child => child.matches(selector))
46
  },
47
 
48
  parents(element, selector) {
49
    const parents = []
50
    let ancestor = element.parentNode.closest(selector)
51
 
52
    while (ancestor) {
53
      parents.push(ancestor)
54
      ancestor = ancestor.parentNode.closest(selector)
55
    }
56
 
57
    return parents
58
  },
59
 
60
  prev(element, selector) {
61
    let previous = element.previousElementSibling
62
 
63
    while (previous) {
64
      if (previous.matches(selector)) {
65
        return [previous]
66
      }
67
 
68
      previous = previous.previousElementSibling
69
    }
70
 
71
    return []
72
  },
73
  // TODO: this is now unused; remove later along with prev()
74
  next(element, selector) {
75
    let next = element.nextElementSibling
76
 
77
    while (next) {
78
      if (next.matches(selector)) {
79
        return [next]
80
      }
81
 
82
      next = next.nextElementSibling
83
    }
84
 
85
    return []
86
  },
87
 
88
  focusableChildren(element) {
89
    const focusables = [
90
      'a',
91
      'button',
92
      'input',
93
      'textarea',
94
      'select',
95
      'details',
96
      '[tabindex]',
97
      '[contenteditable="true"]'
98
    ].map(selector => `${selector}:not([tabindex^="-"])`).join(',')
99
 
100
    return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))
101
  },
102
 
103
  getSelectorFromElement(element) {
104
    const selector = getSelector(element)
105
 
106
    if (selector) {
107
      return SelectorEngine.findOne(selector) ? selector : null
108
    }
109
 
110
    return null
111
  },
112
 
113
  getElementFromSelector(element) {
114
    const selector = getSelector(element)
115
 
116
    return selector ? SelectorEngine.findOne(selector) : null
117
  },
118
 
119
  getMultipleElementsFromSelector(element) {
120
    const selector = getSelector(element)
121
 
122
    return selector ? SelectorEngine.find(selector) : []
123
  }
124
}
125
 
126
export default SelectorEngine