<commit_before>import looseEqual from '../../utils/loose-equal'
import { addClass, removeAttr, removeClass, setAttr } from '../../utils/dom'
import { isBrowser } from '../../utils/env'
import { bindTargets, getTargets, unbindTargets } from '../../utils/target'

// Target listen types
const listenTypes = { click: true }

// Property key for handler storage
const BV_TOGGLE = '__BV_toggle__'
const BV_TOGGLE_STATE = '__BV_toggle_STATE__'
const BV_TOGGLE_CONTROLS = '__BV_toggle_CONTROLS__'
const BV_TOGGLE_TARGETS = '__BV_toggle_TARGETS__'

// Emitted control event for collapse (emitted to collapse)
const EVENT_TOGGLE = 'bv::toggle::collapse'

// Listen to event for toggle state update (emitted by collapse)
const EVENT_STATE = 'bv::collapse::state'

// Private event emitted on $root to ensure the toggle state is always synced.
// Gets emitted even if the state of b-collapse has not changed.
// This event is NOT to be documented as people should not be using it.
const EVENT_STATE_SYNC = 'bv::collapse::sync::state'
// Private event we send to collapse to request state update sync event
const EVENT_STATE_REQUEST = 'bv::request::collapse::state'

// Reset and remove a property from the provided element
const resetProp = (el, prop) => {
  el[prop] = null
  delete el[prop]
}

// Handle targets update
const handleTargets = ({ targets, vnode }) => {
  targets.forEach(target => {
    vnode.context.$root.$emit(EVENT_TOGGLE, target)
  })
}

// Handle directive updates
/* istanbul ignore next: not easy to test */
const handleUpdate = (el, binding, vnode) => {
  if (!isBrowser) {
    return
  }

  if (!looseEqual(getTargets(binding), el[BV_TOGGLE_TARGETS])) {
    // Targets have changed, so update accordingly
    unbindTargets(vnode, binding, listenTypes)
    const targets = bindTargets(vnode, binding, listenTypes, handleTargets)
    // Update targets array to element
    el[BV_TOGGLE_TARGETS] = targets
    // Add aria attributes to element
    el[BV_TOGGLE_CONTROLS] = targets.join(' ')
    // ensure aria-controls is up to date
    setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS])
    // Request a state update from targets so that we can ensure
    // expanded state is correct
    targets.forEach(target => {
      vnode.context.$root.$emit(EVENT_STATE_REQUEST, target)
    })
  }

  // Ensure the collapse class and aria-* attributes persist
  // after element is updated (either by parent re-rendering
  // or changes to this element or it's contents
  if (el[BV_TOGGLE_STATE] === true) {
    addClass(el, 'collapsed')
    setAttr(el, 'aria-expanded', 'true')
  } else if (el[BV_TOGGLE_STATE] === false) {
    removeClass(el, 'collapsed')
    setAttr(el, 'aria-expanded', 'false')
  }
  setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS])
}

/*
 * Export our directive
 */
export const VBToggle = {
  bind(el, binding, vnode) {
    const targets = bindTargets(vnode, binding, listenTypes, handleTargets)
    if (isBrowser && vnode.context && targets.length > 0) {
      // Add targets array to element
      el[BV_TOGGLE_TARGETS] = targets
      // Add aria attributes to element
      el[BV_TOGGLE_CONTROLS] = targets.join(' ')
      // State is initially collapsed until we receive a state event
      el[BV_TOGGLE_STATE] = false
      setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS])
      setAttr(el, 'aria-expanded', 'false')
      // If element is not a button, we add `role="button"` for accessibility
      if (el.tagName !== 'BUTTON') {
        setAttr(el, 'role', 'button')
      }

      // Toggle state handler
      const toggleDirectiveHandler = (id, state) => {
        const targets = el[BV_TOGGLE_TARGETS] || []
        if (targets.indexOf(id) !== -1) {
          // Set aria-expanded state
          setAttr(el, 'aria-expanded', state ? 'true' : 'false')
          // Set/Clear 'collapsed' class state
          el[BV_TOGGLE_STATE] = state
          if (state) {
            removeClass(el, 'collapsed')
          } else {<commit_msg>fix(v-b-toggle): don't override `role` if element has a `role` assigned (#3889)<commit_after>import looseEqual from '../../utils/loose-equal'
import { addClass, hasAttr, removeAttr, removeClass, setAttr } from '../../utils/dom'
import { isBrowser } from '../../utils/env'
import { bindTargets, getTargets, unbindTargets } from '../../utils/target'

// Target listen types
const listenTypes = { click: true }

// Property key for handler storage
const BV_TOGGLE = '__BV_toggle__'
const BV_TOGGLE_STATE = '__BV_toggle_STATE__'
const BV_TOGGLE_CONTROLS = '__BV_toggle_CONTROLS__'
const BV_TOGGLE_TARGETS = '__BV_toggle_TARGETS__'

// Emitted control event for collapse (emitted to collapse)
const EVENT_TOGGLE = 'bv::toggle::collapse'

// Listen to event for toggle state update (emitted by collapse)
const EVENT_STATE = 'bv::collapse::state'

// Private event emitted on $root to ensure the toggle state is always synced.
// Gets emitted even if the state of b-collapse has not changed.
// This event is NOT to be documented as people should not be using it.
const EVENT_STATE_SYNC = 'bv::collapse::sync::state'
// Private event we send to collapse to request state update sync event
const EVENT_STATE_REQUEST = 'bv::request::collapse::state'

// Reset and remove a property from the provided element
const resetProp = (el, prop) => {
  el[prop] = null
  delete el[prop]
}

// Handle targets update
const handleTargets = ({ targets, vnode }) => {
  targets.forEach(target => {
    vnode.context.$root.$emit(EVENT_TOGGLE, target)
  })
}

// Handle directive updates
/* istanbul ignore next: not easy to test */
const handleUpdate = (el, binding, vnode) => {
  if (!isBrowser) {
    return
  }

  if (!looseEqual(getTargets(binding), el[BV_TOGGLE_TARGETS])) {
    // Targets have changed, so update accordingly
    unbindTargets(vnode, binding, listenTypes)
    const targets = bindTargets(vnode, binding, listenTypes, handleTargets)
    // Update targets array to element
    el[BV_TOGGLE_TARGETS] = targets
    // Add aria attributes to element
    el[BV_TOGGLE_CONTROLS] = targets.join(' ')
    // ensure aria-controls is up to date
    setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS])
    // Request a state update from targets so that we can ensure
    // expanded state is correct
    targets.forEach(target => {
      vnode.context.$root.$emit(EVENT_STATE_REQUEST, target)
    })
  }

  // Ensure the collapse class and aria-* attributes persist
  // after element is updated (either by parent re-rendering
  // or changes to this element or it's contents
  if (el[BV_TOGGLE_STATE] === true) {
    addClass(el, 'collapsed')
    setAttr(el, 'aria-expanded', 'true')
  } else if (el[BV_TOGGLE_STATE] === false) {
    removeClass(el, 'collapsed')
    setAttr(el, 'aria-expanded', 'false')
  }
  setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS])
}

/*
 * Export our directive
 */
export const VBToggle = {
  bind(el, binding, vnode) {
    const targets = bindTargets(vnode, binding, listenTypes, handleTargets)
    if (isBrowser && vnode.context && targets.length > 0) {
      // Add targets array to element
      el[BV_TOGGLE_TARGETS] = targets
      // Add aria attributes to element
      el[BV_TOGGLE_CONTROLS] = targets.join(' ')
      // State is initially collapsed until we receive a state event
      el[BV_TOGGLE_STATE] = false
      setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS])
      setAttr(el, 'aria-expanded', 'false')
      // If element is not a button, we add `role="button"` for accessibility
      if (el.tagName !== 'BUTTON' && !hasAttr(el, 'role')) {
        setAttr(el, 'role', 'button')
      }

      // Toggle state handler
      const toggleDirectiveHandler = (id, state) => {
        const targets = el[BV_TOGGLE_TARGETS] || []
        if (targets.indexOf(id) !== -1) {
          // Set aria-expanded state
          setAttr(el, 'aria-expanded', state ? 'true' : 'false')
          // Set/Clear 'collapsed' class state
          el[BV_TOGGLE_STATE] = state
          if (state) {
            removeClass(el, 'collapsed')
          } else {
{'fraction_non_alphanumeric': 0.1207987101575096, 'fraction_numerical': 0.0009921865310678407, 'mean_word_length': 3.370731707317073, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6415547', 'n_tokens_mistral': 2569, 'n_tokens_neox': 2481, 'n_words': 761}