|
1 | 1 | import KeyCodes from '../../utils/key-codes'
|
2 | 2 | import looseEqual from '../../utils/loose-equal'
|
3 | 3 | import { arrayIncludes, concat } from '../../utils/array'
|
4 |
| -import { addClass, hasAttr, isDisabled, removeAttr, removeClass, setAttr } from '../../utils/dom' |
| 4 | +import { |
| 5 | + addClass, |
| 6 | + getAttr, |
| 7 | + hasAttr, |
| 8 | + isDisabled, |
| 9 | + isTag, |
| 10 | + removeAttr, |
| 11 | + removeClass, |
| 12 | + setAttr |
| 13 | +} from '../../utils/dom' |
5 | 14 | import { isBrowser } from '../../utils/env'
|
6 | 15 | import { eventOn, eventOff } from '../../utils/events'
|
7 | 16 | import { isString } from '../../utils/inspect'
|
@@ -51,19 +60,29 @@ export const EVENT_STATE_REQUEST = 'bv::request::collapse::state'
|
51 | 60 |
|
52 | 61 | const KEYDOWN_KEY_CODES = [ENTER, SPACE]
|
53 | 62 |
|
| 63 | +const RX_HASH = /^#/ |
| 64 | +const RX_HASH_ID = /^#[A-Za-z]+[\w\-:.]*$/ |
54 | 65 | const RX_SPLIT_SEPARATOR = /\s+/
|
55 | 66 |
|
56 | 67 | // --- Helper methods ---
|
57 | 68 |
|
58 |
| -const isNonStandardTag = el => !arrayIncludes(['BUTTON', 'A'], el.tagName) |
| 69 | +const isNonStandardTag = el => !arrayIncludes(['button', 'a'], el.tagName.toLowerCase()) |
59 | 70 |
|
60 |
| -const getTargets = ({ modifiers, arg, value }) => { |
| 71 | +const getTargets = ({ modifiers, arg, value }, el) => { |
61 | 72 | // Any modifiers are considered target IDs
|
62 | 73 | const targets = keys(modifiers || {})
|
63 | 74 |
|
64 | 75 | // If value is a string, split out individual targets (if space delimited)
|
65 | 76 | value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value
|
66 | 77 |
|
| 78 | + // Support target ID as link href (`href="#id"`) |
| 79 | + if (isTag(el.tagName, 'a')) { |
| 80 | + const href = getAttr(el, 'href') || '' |
| 81 | + if (RX_HASH_ID.test(href)) { |
| 82 | + targets.push(href.replace(RX_HASH, '')) |
| 83 | + } |
| 84 | + } |
| 85 | + |
67 | 86 | // Add ID from `arg` (if provided), and support value
|
68 | 87 | // as a single string ID or an array of string IDs
|
69 | 88 | // If `value` is not an array or string, then it gets filtered out
|
@@ -172,7 +191,7 @@ const handleUpdate = (el, binding, vnode) => {
|
172 | 191 | setToggleState(el, el[BV_TOGGLE_STATE])
|
173 | 192 |
|
174 | 193 | // Parse list of target IDs
|
175 |
| - const targets = getTargets(binding) |
| 194 | + const targets = getTargets(binding, el) |
176 | 195 |
|
177 | 196 | /* istanbul ignore else */
|
178 | 197 | // Ensure the `aria-controls` hasn't been overwritten
|
|
0 commit comments