diff options
| author | Troy Morehouse <[email protected]> | 2017-12-12 05:28:30 -0400 |
|---|---|---|
| committer | XhmikosR <[email protected]> | 2017-12-12 11:28:30 +0200 |
| commit | 8839c03865f02cf9c98443f4e07ac477985151ed (patch) | |
| tree | 6fb5b971ca225f392d9b051a9824517583767911 | |
| parent | a7e64c84aec65fe38b5a9323638e62d513b64ce8 (diff) | |
| download | bootstrap-8839c03865f02cf9c98443f4e07ac477985151ed.tar.xz bootstrap-8839c03865f02cf9c98443f4e07ac477985151ed.zip | |
dropdown: add boundary config option (#24976)
| -rw-r--r-- | docs/4.0/components/dropdowns.md | 8 | ||||
| -rw-r--r-- | js/src/dropdown.js | 18 | ||||
| -rw-r--r-- | js/tests/unit/dropdown.js | 44 |
3 files changed, 67 insertions, 3 deletions
diff --git a/docs/4.0/components/dropdowns.md b/docs/4.0/components/dropdowns.md index cde123b00..926729a3d 100644 --- a/docs/4.0/components/dropdowns.md +++ b/docs/4.0/components/dropdowns.md @@ -723,9 +723,17 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap <td>true</td> <td>Allow Dropdown to flip in case of an overlapping on the reference element. For more information refer to Popper.js's <a href="https://popper.js.org/popper-documentation.html#modifiers..flip.enabled">flip docs</a>.</td> </tr> + <tr> + <td>boundary</td> + <td>string | element</td> + <td>'scrollParent'</td> + <td>Overflow constraint boundary of the dropdown menu. Accepts the values of <code>'viewport'</code>, <code>'window'</code>, <code>'scrollParent'</code>, or an HTMLElement reference (JavaScript only). For more information refer to Popper.js's <a href="https://popper.js.org/popper-documentation.html#modifiers..preventOverflow.boundariesElement">preventOverflow docs</a>.</td> + </tr> </tbody> </table> +Note when `boundary` is set to any value other than `'scrollParent'`, the style `position: static` is applied to the `.dropdown` container. + ### Methods | Method | Description | diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 8affedc6c..56559b434 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -50,7 +50,8 @@ const Dropdown = (($) => { DROPRIGHT : 'dropright', DROPLEFT : 'dropleft', MENURIGHT : 'dropdown-menu-right', - MENULEFT : 'dropdown-menu-left' + MENULEFT : 'dropdown-menu-left', + POSITION_STATIC : 'position-static' } const Selector = { @@ -74,12 +75,14 @@ const Dropdown = (($) => { const Default = { offset : 0, - flip : true + flip : true, + boundary : 'scrollParent' } const DefaultType = { offset : '(number|string|function)', - flip : 'boolean' + flip : 'boolean', + boundary : '(string|element)' } @@ -159,6 +162,12 @@ const Dropdown = (($) => { element = parent } } + // If boundary is not `scrollParent`, then set position to `static` + // to allow the menu to "escape" the scroll parent's boundaries + // https://github.com/twbs/bootstrap/issues/24251 + if (this._config.boundary !== 'scrollParent') { + $(parent).addClass(ClassName.POSITION_STATIC) + } this._popper = new Popper(element, this._menu, this._getPopperConfig()) } @@ -276,6 +285,9 @@ const Dropdown = (($) => { offset : offsetConf, flip : { enabled : this._config.flip + }, + preventOverflow : { + boundariesElement : this._config.boundary } } } diff --git a/js/tests/unit/dropdown.js b/js/tests/unit/dropdown.js index c1202266b..41c53a98a 100644 --- a/js/tests/unit/dropdown.js +++ b/js/tests/unit/dropdown.js @@ -67,6 +67,50 @@ $(function () { $dropdown.trigger($.Event('click')) }) + QUnit.test('should not add class position-static to dropdown if boundary not set', function (assert) { + assert.expect(1) + var done = assert.async() + var dropdownHTML = '<div class="tabs">' + + '<div class="dropdown">' + + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' + + '<div class="dropdown-menu">' + + '<a class="dropdown-item" href="#">Secondary link</a>' + + '<a class="dropdown-item" href="#">Something else here</a>' + + '</div>' + + '</div>' + + '</div>' + var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown() + $dropdown + .parent('.dropdown') + .on('shown.bs.dropdown', function () { + assert.ok(!$dropdown.parent('.dropdown').hasClass('position-static'), '"position-static" class not added') + done() + }) + $dropdown.trigger('click') + }) + + QUnit.test('should add class position-static to dropdown if boundary not scrollParent', function (assert) { + assert.expect(1) + var done = assert.async() + var dropdownHTML = '<div class="tabs">' + + '<div class="dropdown">' + + '<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-boundary="viewport">Dropdown</a>' + + '<div class="dropdown-menu">' + + '<a class="dropdown-item" href="#">Secondary link</a>' + + '<a class="dropdown-item" href="#">Something else here</a>' + + '</div>' + + '</div>' + + '</div>' + var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown() + $dropdown + .parent('.dropdown') + .on('shown.bs.dropdown', function () { + assert.ok($dropdown.parent('.dropdown').hasClass('position-static'), '"position-static" class added') + done() + }) + $dropdown.trigger('click') + }) + QUnit.test('should set aria-expanded="true" on target when dropdown menu is shown', function (assert) { assert.expect(1) var done = assert.async() |
