mirror of https://github.com/twbs/bootstrap.git
Merge 9ee6617dfe
into 4c98145482
This commit is contained in:
commit
66f9445ed2
|
@ -34,7 +34,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "./dist/js/bootstrap.bundle.js",
|
"path": "./dist/js/bootstrap.bundle.js",
|
||||||
"maxSize": "43.0 kB"
|
"maxSize": "43.25 kB"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "./dist/js/bootstrap.bundle.min.js",
|
"path": "./dist/js/bootstrap.bundle.min.js",
|
||||||
|
|
|
@ -174,6 +174,12 @@ class Offcanvas extends BaseComponent {
|
||||||
this.hide()
|
this.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keydownCallback = event => {
|
||||||
|
if (event.key === ESCAPE_KEY) {
|
||||||
|
this.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 'static' option will be translated to true, and booleans will keep their value
|
// 'static' option will be translated to true, and booleans will keep their value
|
||||||
const isVisible = Boolean(this._config.backdrop)
|
const isVisible = Boolean(this._config.backdrop)
|
||||||
|
|
||||||
|
@ -182,7 +188,8 @@ class Offcanvas extends BaseComponent {
|
||||||
isVisible,
|
isVisible,
|
||||||
isAnimated: true,
|
isAnimated: true,
|
||||||
rootElement: this._element.parentNode,
|
rootElement: this._element.parentNode,
|
||||||
clickCallback: isVisible ? clickCallback : null
|
clickCallback: isVisible ? clickCallback : null,
|
||||||
|
keydownCallback: this._config.keyboard ? keydownCallback : null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ import {
|
||||||
const NAME = 'backdrop'
|
const NAME = 'backdrop'
|
||||||
const CLASS_NAME_FADE = 'fade'
|
const CLASS_NAME_FADE = 'fade'
|
||||||
const CLASS_NAME_SHOW = 'show'
|
const CLASS_NAME_SHOW = 'show'
|
||||||
|
const EVENT_KEY = `.bs.${NAME}`
|
||||||
|
const EVENT_KEYDOWN = `keydown.bs.${NAME}`
|
||||||
const EVENT_MOUSEDOWN = `mousedown.bs.${NAME}`
|
const EVENT_MOUSEDOWN = `mousedown.bs.${NAME}`
|
||||||
|
|
||||||
const Default = {
|
const Default = {
|
||||||
|
@ -25,6 +27,7 @@ const Default = {
|
||||||
clickCallback: null,
|
clickCallback: null,
|
||||||
isAnimated: false,
|
isAnimated: false,
|
||||||
isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
|
isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
|
||||||
|
keydownCallback: null,
|
||||||
rootElement: 'body' // give the choice to place backdrop under different elements
|
rootElement: 'body' // give the choice to place backdrop under different elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +36,7 @@ const DefaultType = {
|
||||||
clickCallback: '(function|null)',
|
clickCallback: '(function|null)',
|
||||||
isAnimated: 'boolean',
|
isAnimated: 'boolean',
|
||||||
isVisible: 'boolean',
|
isVisible: 'boolean',
|
||||||
|
keydownCallback: '(function|null)',
|
||||||
rootElement: '(element|string)'
|
rootElement: '(element|string)'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +105,7 @@ class Backdrop extends Config {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHandler.off(this._element, EVENT_MOUSEDOWN)
|
EventHandler.off(this._element, EVENT_KEY)
|
||||||
|
|
||||||
this._element.remove()
|
this._element.remove()
|
||||||
this._isAppended = false
|
this._isAppended = false
|
||||||
|
@ -140,6 +144,12 @@ class Backdrop extends Config {
|
||||||
execute(this._config.clickCallback)
|
execute(this._config.clickCallback)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (this._config.keydownCallback) {
|
||||||
|
EventHandler.on(document, EVENT_KEYDOWN, event => {
|
||||||
|
execute(this._config.keydownCallback, [event])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
this._isAppended = true
|
this._isAppended = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,74 @@ describe('Offcanvas', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should hide if backdrop is static and esc key is pressed on document', () => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
fixtureEl.innerHTML = '<div class="offcanvas"></div>'
|
||||||
|
|
||||||
|
const offCanvasEl = fixtureEl.querySelector('div')
|
||||||
|
const offCanvas = new Offcanvas(offCanvasEl, { backdrop: 'static' })
|
||||||
|
|
||||||
|
const keydownEscEvent = createEvent('keydown')
|
||||||
|
keydownEscEvent.key = 'Escape'
|
||||||
|
|
||||||
|
const spyHide = spyOn(offCanvas, 'hide')
|
||||||
|
|
||||||
|
offCanvasEl.addEventListener('shown.bs.offcanvas', () => {
|
||||||
|
document.dispatchEvent(keydownEscEvent)
|
||||||
|
expect(spyHide).toHaveBeenCalled()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
|
||||||
|
offCanvas.show()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not hide if backdrop is static and esc key is pressed on document but keyboard = false', () => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
fixtureEl.innerHTML = '<div class="offcanvas"></div>'
|
||||||
|
|
||||||
|
const offCanvasEl = fixtureEl.querySelector('div')
|
||||||
|
const offCanvas = new Offcanvas(offCanvasEl, { backdrop: 'static', keyboard: false })
|
||||||
|
|
||||||
|
const keydownEscEvent = createEvent('keydown')
|
||||||
|
keydownEscEvent.key = 'Escape'
|
||||||
|
|
||||||
|
const spyHide = spyOn(offCanvas, 'hide')
|
||||||
|
|
||||||
|
offCanvasEl.addEventListener('shown.bs.offcanvas', () => {
|
||||||
|
expect(offCanvas._config.keyboard).toBeFalse()
|
||||||
|
|
||||||
|
document.dispatchEvent(keydownEscEvent)
|
||||||
|
expect(spyHide).not.toHaveBeenCalled()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
|
||||||
|
offCanvas.show()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not hide if backdrop is static but key other than esc is pressed on document', () => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
fixtureEl.innerHTML = '<div class="offcanvas"></div>'
|
||||||
|
|
||||||
|
const offCanvasEl = fixtureEl.querySelector('div')
|
||||||
|
const offCanvas = new Offcanvas(offCanvasEl, { backdrop: 'static' })
|
||||||
|
|
||||||
|
const keydownEvent = createEvent('keydown')
|
||||||
|
keydownEvent.key = 'Tab'
|
||||||
|
|
||||||
|
const spyHide = spyOn(offCanvas, 'hide')
|
||||||
|
|
||||||
|
offCanvasEl.addEventListener('shown.bs.offcanvas', () => {
|
||||||
|
document.dispatchEvent(keydownEvent)
|
||||||
|
expect(spyHide).not.toHaveBeenCalled()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
|
||||||
|
offCanvas.show()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('should call `hide` on resize, if element\'s position is not fixed any more', () => {
|
it('should call `hide` on resize, if element\'s position is not fixed any more', () => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
fixtureEl.innerHTML = '<div class="offcanvas-lg"></div>'
|
fixtureEl.innerHTML = '<div class="offcanvas-lg"></div>'
|
||||||
|
|
|
@ -191,6 +191,32 @@ describe('Backdrop', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('keydown callback', () => {
|
||||||
|
it('should execute keydown callback on keydown event', () => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const spy = jasmine.createSpy('spy')
|
||||||
|
|
||||||
|
const instance = new Backdrop({
|
||||||
|
isVisible: true,
|
||||||
|
isAnimated: false,
|
||||||
|
keydownCallback: () => spy()
|
||||||
|
})
|
||||||
|
const endTest = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(spy).toHaveBeenCalled()
|
||||||
|
resolve()
|
||||||
|
}, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.show(() => {
|
||||||
|
const keydownEvent = new Event('keydown', { bubbles: true, cancelable: true })
|
||||||
|
document.querySelector(CLASS_BACKDROP).dispatchEvent(keydownEvent)
|
||||||
|
endTest()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('animation callbacks', () => {
|
describe('animation callbacks', () => {
|
||||||
it('should show and hide backdrop after counting transition duration if it is animated', () => {
|
it('should show and hide backdrop after counting transition duration if it is animated', () => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
|
Loading…
Reference in New Issue