Skip to content

Commit

Permalink
Merge branch 'main' into patrickhlauke-carousel-indicators
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickhlauke committed Jan 28, 2021
2 parents be40c85 + e036e60 commit 6c0af73
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 2 deletions.
24 changes: 22 additions & 2 deletions js/src/dropdown.js
Expand Up @@ -72,7 +72,7 @@ const PLACEMENT_RIGHT = isRTL ? 'left-start' : 'right-start'
const PLACEMENT_LEFT = isRTL ? 'right-start' : 'left-start'

const Default = {
offset: 0,
offset: [0, 0],
flip: true,
boundary: 'clippingParents',
reference: 'toggle',
Expand All @@ -81,7 +81,7 @@ const Default = {
}

const DefaultType = {
offset: '(number|string|function)',
offset: '(array|string|function)',
flip: 'boolean',
boundary: '(string|element)',
reference: '(string|element|object)',
Expand Down Expand Up @@ -298,6 +298,20 @@ class Dropdown extends BaseComponent {
return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null
}

_getOffset() {
const { offset } = this._config

if (typeof offset === 'string') {
return offset.split(',').map(val => Number.parseInt(val, 10))
}

if (typeof offset === 'function') {
return popperData => offset(popperData, this._element)
}

return offset
}

_getPopperConfig() {
const popperConfig = {
placement: this._getPlacement(),
Expand All @@ -313,6 +327,12 @@ class Dropdown extends BaseComponent {
options: {
fallbackPlacements: ['top', 'right', 'bottom', 'left']
}
},
{
name: 'offset',
options: {
offset: this._getOffset()
}
}]
}

Expand Down
22 changes: 22 additions & 0 deletions js/src/tooltip.js
Expand Up @@ -50,6 +50,7 @@ const DefaultType = {
html: 'boolean',
selector: '(string|boolean)',
placement: '(string|function)',
offset: '(array|string|function)',
container: '(string|element|boolean)',
fallbackPlacements: 'array',
boundary: '(string|element)',
Expand Down Expand Up @@ -80,6 +81,7 @@ const Default = {
html: false,
selector: false,
placement: 'top',
offset: [0, 0],
container: false,
fallbackPlacements: ['top', 'right', 'bottom', 'left'],
boundary: 'clippingParents',
Expand Down Expand Up @@ -473,6 +475,20 @@ class Tooltip extends BaseComponent {
return context
}

_getOffset() {
const { offset } = this.config

if (typeof offset === 'string') {
return offset.split(',').map(val => Number.parseInt(val, 10))
}

if (typeof offset === 'function') {
return popperData => offset(popperData, this._element)
}

return offset
}

_getPopperConfig(attachment) {
const defaultBsConfig = {
placement: attachment,
Expand All @@ -484,6 +500,12 @@ class Tooltip extends BaseComponent {
fallbackPlacements: this.config.fallbackPlacements
}
},
{
name: 'offset',
options: {
offset: this._getOffset()
}
},
{
name: 'preventOverflow',
options: {
Expand Down
48 changes: 48 additions & 0 deletions js/tests/unit/dropdown.spec.js
Expand Up @@ -54,6 +54,54 @@ describe('Dropdown', () => {
expect(dropdown.toggle).toHaveBeenCalled()
})

it('should create offset modifier correctly when offset option is a function', done => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-bs-toggle="dropdown">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#">Secondary link</a>',
' </div>',
'</div>'
].join('')

const getOffset = jasmine.createSpy('getOffset').and.returnValue([10, 20])
const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown, {
offset: getOffset,
popperConfig: {
onFirstUpdate: state => {
expect(getOffset).toHaveBeenCalledWith({
popper: state.rects.popper,
reference: state.rects.reference,
placement: state.placement
}, btnDropdown)
done()
}
}
})
const offset = dropdown._getOffset()

expect(typeof offset).toEqual('function')

dropdown.show()
})

it('should create offset modifier correctly when offset option is a string into data attribute', () => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" data-bs-offset="10,20">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#">Secondary link</a>',
' </div>',
'</div>'
].join('')

const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown)

expect(dropdown._getOffset()).toEqual([10, 20])
})

it('should allow to pass config to Popper with `popperConfig`', () => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
Expand Down
35 changes: 35 additions & 0 deletions js/tests/unit/tooltip.spec.js
Expand Up @@ -107,6 +107,41 @@ describe('Tooltip', () => {
tooltipInContainerEl.click()
})

it('should create offset modifier when offset is passed as a function', done => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Offset from function">'

const getOffset = jasmine.createSpy('getOffset').and.returnValue([10, 20])
const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl, {
offset: getOffset,
popperConfig: {
onFirstUpdate: state => {
expect(getOffset).toHaveBeenCalledWith({
popper: state.rects.popper,
reference: state.rects.reference,
placement: state.placement
}, tooltipEl)
done()
}
}
})

const offset = tooltip._getOffset()

expect(typeof offset).toEqual('function')

tooltip.show()
})

it('should create offset modifier when offset option is passed in data attribute', () => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-offset="10,20" title="Another tooltip">'

const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl)

expect(tooltip._getOffset()).toEqual([10, 20])
})

it('should allow to pass config to Popper with `popperConfig`', () => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip">'

Expand Down
10 changes: 10 additions & 0 deletions site/content/docs/5.0/components/dropdowns.md
Expand Up @@ -896,6 +896,16 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
<td><code>'dynamic'</code></td>
<td>By default, we use Popper for dynamic positioning. Disable this with <code>static</code>.</td>
</tr>
<tr>
<td><code>offset</code></td>
<td>array | string | function</td>
<td><code>[0, 0]</code></td>
<td>
<p>Offset of the dropdown relative to its target. You can pass a string in data attributes with comma separated values like: <code>data-bs-offset="10,20"</code></p>
<p>When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: <code>[<a href="https://popper.js.org/docs/v2/modifiers/offset/#skidding-1">skidding</a>, <a href="https://popper.js.org/docs/v2/modifiers/offset/#distance-1">distance</a>]</code>.</p>
<p>For more information refer to Popper's <a href="https://popper.js.org/docs/v2/modifiers/offset/#options">offset docs</a>.</p>
</td>
</tr>
<tr>
<td><code>popperConfig</code></td>
<td>null | object</td>
Expand Down
10 changes: 10 additions & 0 deletions site/content/docs/5.0/components/popovers.md
Expand Up @@ -267,6 +267,16 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt
<td><code>null</code></td>
<td>Here you can supply your own sanitize function. This can be useful if you prefer to use a dedicated library to perform sanitization.</td>
</tr>
<tr>
<td><code>offset</code></td>
<td>array | string | function</td>
<td><code>[0, 0]</code></td>
<td>
<p>Offset of the popover relative to its target. You can pass a string in data attributes with comma separated values like: <code>data-bs-offset="10,20"</code></p>
<p>When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: <code>[<a href="https://popper.js.org/docs/v2/modifiers/offset/#skidding-1">skidding</a>, <a href="https://popper.js.org/docs/v2/modifiers/offset/#distance-1">distance</a>]</code>.</p>
<p>For more information refer to Popper's <a href="https://popper.js.org/docs/v2/modifiers/offset/#options">offset docs</a>.</p>
</td>
</tr>
<tr>
<td><code>popperConfig</code></td>
<td>null | object</td>
Expand Down
10 changes: 10 additions & 0 deletions site/content/docs/5.0/components/tooltips.md
Expand Up @@ -292,6 +292,16 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt
<td><code>null</code></td>
<td>Here you can supply your own sanitize function. This can be useful if you prefer to use a dedicated library to perform sanitization.</td>
</tr>
<tr>
<td><code>offset</code></td>
<td>array | string | function</td>
<td><code>[0, 0]</code></td>
<td>
<p>Offset of the tooltip relative to its target. You can pass a string in data attributes with comma separated values like: <code>data-bs-offset="10,20"</code></p>
<p>When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: <code>[<a href="https://popper.js.org/docs/v2/modifiers/offset/#skidding-1">skidding</a>, <a href="https://popper.js.org/docs/v2/modifiers/offset/#distance-1">distance</a>]</code>.</p>
<p>For more information refer to Popper's <a href="https://popper.js.org/docs/v2/modifiers/offset/#options">offset docs</a>.</p>
</td>
</tr>
<tr>
<td><code>popperConfig</code></td>
<td>null | object</td>
Expand Down
1 change: 1 addition & 0 deletions site/content/docs/5.0/migration.md
Expand Up @@ -20,6 +20,7 @@ toc: true

### JavaScript

- Restored `offset` option for Dropdown, Popover and Tooltip plugins.
- The default value for the `fallbackPlacements` is changed to `['top', 'right', 'bottom', 'left']` for better placement of popper elements.

## v5.0.0-beta1
Expand Down

0 comments on commit 6c0af73

Please sign in to comment.