8000 feat(v-b-toggle): check for target ID via `href` if a link by tmorehouse · Pull Request #5398 · bootstrap-vue/bootstrap-vue · GitHub
[go: up one dir, main page]

Skip to content
42 changes: 40 additions & 2 deletions src/directives/toggle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ details and caveats.

## Directive syntax and usage

The directive is applied to the element or component that triggers the visibility of hte target. The
The directive is applied to the element or component that triggers the visibility of the target. The
target component can be specified (via its ID) as either a directive modifier(s), the directive
argument, or as a string/array passed to as the directive value:

Expand All @@ -34,7 +34,7 @@ argument, or as a string/array passed to as the directive value:

Modifiers, argument, and the value can be used at the same time when targeting multiple components.

### Example usage
**Example usage:**

```html
<template>
Expand Down Expand Up @@ -62,6 +62,44 @@ Modifiers, argument, and the value can be used at the same time when targeting m
<!-- v-b-toggle-directive.vue -->
```

## Usage on links

<span class="badge badge-info small">2.15.0+</span>

If placing the directive on a link (or a component that renders a link), the target ID can
alternatively be specified via the `href` attribute.

Note that the browser URL will change and the page may scroll the target into view. To prevent the
URL from changing and the page from scrolling, add `@click.prevent` to the link.

**Example usage:**

```html
<template>
<div>
<div class="mb-3">
<a v-b-toggle href="#example-collapse" @click.prevent>Toggle Collapse</a>
<b-button v-b-toggle href="#example-sidebar" @click.prevent>Toggle Sidebar</b-button>
</div>

<b-collapse id="example-collapse">
<b-card title="Collapsible card">
Hello world!
</b-card>
</b-collapse>

<b-sidebar id="example-sidebar" title="Sidebar" shadow>
<div class="px-3 py-2">
Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis
in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
</div>
</b-sidebar>
</div>
</template>

<!-- v-b-toggle-links.vue -->
```

## Hiding and showing content in the toggle trigger element

When using the `v-b-toggle` directive, the class `collapsed` will automatically be placed on the
Expand Down
27 changes: 23 additions & 4 deletions src/directives/toggle/toggle.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import KeyCodes from '../../utils/key-codes'
import looseEqual from '../../utils/loose-equal'
import { arrayIncludes, concat } from '../../utils/array'
import { addClass, hasAttr, isDisabled, removeAttr, removeClass, setAttr } from '../../utils/dom'
import {
addClass,
getAttr,
hasAttr,
isDisabled,
isTag,
removeAttr,
removeClass,
setAttr
} from '../../utils/dom'
import { isBrowser } from '../../utils/env'
import { eventOn, eventOff } from '../../utils/events'
import { isString } from '../../utils/inspect'
Expand Down Expand Up @@ -51,19 +60,29 @@ export const EVENT_STATE_REQUEST = 'bv::request::collapse::state'

const KEYDOWN_KEY_CODES = [ENTER, SPACE]

const RX_HASH = /^#/
const RX_HASH_ID = /^#[A-Za-z]+[\w\-:.]*$/
const RX_SPLIT_SEPARATOR = /\s+/

// --- Helper methods ---

const isNonStandardTag = el => !arrayIncludes(['BUTTON', 'A'], el.tagName)
const isNonStandardTag = el => !arrayIncludes(['button', 'a'], el.tagName.toLowerCase())

const getTargets = ({ modifiers, arg, value }) => {
const getTargets = ({ modifiers, arg, value }, el) => {
// Any modifiers are considered target IDs
const targets = keys(modifiers || {})

// If value is a string, split out individual targets (if space delimited)
value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value

// Support target ID as link href (`href="#id"`)
if (isTag(el.tagName, 'a')) {
const href = getAttr(el, 'href') || ''
if (RX_HASH_ID.test(href)) {
targets.push(href.replace(RX_HASH, ''))
}
}

// Add ID from `arg` (if provided), and support value
// as a single string ID or an array of string IDs
// If `value` is not an array or string, then it gets filtered out
Expand Down Expand Up @@ -172,7 +191,7 @@ const handleUpdate = (el, binding, vnode) => {
setToggleState(el, el[BV_TOGGLE_STATE])

// Parse list of target IDs
const targets = getTargets(binding)
const targets = getTargets(binding, el)

/* istanbul ignore else */
// Ensure the `aria-controls` hasn't been overwritten
Expand Down
Loading
0