Skip to content

Commit

Permalink
Add scrollbar functionality for different rootElements than body
Browse files Browse the repository at this point in the history
  • Loading branch information
GeoSot committed Jul 7, 2021
1 parent f18ce54 commit 9d1c7b3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 73 deletions.
20 changes: 11 additions & 9 deletions js/src/util/scrollbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-to
const SELECTOR_STICKY_CONTENT = '.sticky-top'

class ScrollBarHelper {
constructor(rootElement) {
this._element = rootElement || document.body
constructor(element = document.body) {
this._isBody = [document.body, document.documentElement].includes(element)

this._element = this._isBody ? document.body : element
}

getWidth() {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
const documentWidth = document.documentElement.clientWidth
return Math.abs(window.innerWidth - documentWidth)
if (this._isBody) {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
const documentWidth = document.documentElement.clientWidth
return Math.abs(window.innerWidth - documentWidth)
}

return Math.abs(this._element.offsetWidth - this._element.clientWidth)
}

hide() {
Expand Down Expand Up @@ -88,10 +94,6 @@ class ScrollBarHelper {
SelectorEngine.find(selector, this._element).forEach(callBack)
}
}

isOverflowing() {
return this.getWidth() > 0
}
}

export default ScrollBarHelper
6 changes: 4 additions & 2 deletions js/tests/unit/modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -717,15 +717,17 @@ describe('Modal', () => {
describe('config rootElement', () => {
it('should append backdrop to root element', done => {
fixtureEl.innerHTML = [
'<div id="modal-root"></div>',
'<div class="modal"><div class="modal-dialog"></div></div>'
'<div id="modal-root">',
' <div class="modal"><div class="modal-dialog"></div></div>',
'</div>'
].join('')

const modalEl = fixtureEl.querySelector('.modal')
const rootElement = fixtureEl.querySelector('#modal-root')
const modal = new Modal(modalEl, { rootElement })

modalEl.addEventListener('shown.bs.modal', () => {
expect(fixtureEl.querySelector('.modal-open')).toEqual(rootElement)
expect(rootElement.querySelector('.modal-backdrop')).not.toBeNull()
done()
})
Expand Down
112 changes: 50 additions & 62 deletions js/tests/unit/util/scrollbar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,76 +48,64 @@ describe('ScrollBar', () => {
clearBodyAndDocument()
})

describe('isBodyOverflowing', () => {
it('should return true if body is overflowing', () => {
document.documentElement.style.overflowY = 'scroll'
document.body.style.overflowY = 'scroll'
fixtureEl.innerHTML = [
'<div style="height: 110vh; width: 100%"></div>'
].join('')
const result = new ScrollBarHelper().isOverflowing()

if (isScrollBarHidden()) {
expect(result).toEqual(false)
} else {
expect(result).toEqual(true)
}
})

it('should return false if body is not overflowing', () => {
doc.style.overflowY = 'hidden'
document.body.style.overflowY = 'hidden'
fixtureEl.innerHTML = [
'<div style="height: 110vh; width: 100%"></div>'
].join('')
const scrollBar = new ScrollBarHelper()
const result = scrollBar.isOverflowing()
describe('getWidth', () => {
describe('Body', () => {
it('should return an integer greater than zero, if body is overflowing', () => {
doc.style.overflowY = 'scroll'
document.body.style.overflowY = 'scroll'
fixtureEl.innerHTML = [
'<div style="height: 110vh; width: 100%"></div>'
].join('')
const result = new ScrollBarHelper().getWidth()

expect(result).toEqual(false)
})
if (isScrollBarHidden()) {
expect(result).toBe(0)
} else {
expect(result).toBeGreaterThan(1)
}
})

it('allows rootElement to be set', () => {
fixtureEl.innerHTML = [
'<div id="another-root" style="height: 100vh; width: 100%"><div style="height: 110vh; width: 100%"></div></div>'
].join('')
const anotherRootElement = document.querySelector('#another-root')
anotherRootElement.style.overflowY = 'scroll'
const result = new ScrollBarHelper(anotherRootElement).isOverflowing()

if (isScrollBarHidden()) {
expect(result).toEqual(false)
} else {
expect(result).toEqual(true)
}
})
})
it('should return 0 if body is not overflowing', () => {
document.documentElement.style.overflowY = 'hidden'
document.body.style.overflowY = 'hidden'
fixtureEl.innerHTML = [
'<div style="height: 110vh; width: 100%"></div>'
].join('')

describe('getWidth', () => {
it('should return an integer greater than zero, if body is overflowing', () => {
doc.style.overflowY = 'scroll'
document.body.style.overflowY = 'scroll'
fixtureEl.innerHTML = [
'<div style="height: 110vh; width: 100%"></div>'
].join('')
const result = new ScrollBarHelper().getWidth()
const result = new ScrollBarHelper().getWidth()

if (isScrollBarHidden()) {
expect(result).toBe(0)
} else {
expect(result).toBeGreaterThan(1)
}
expect(result).toEqual(0)
})
})

it('should return 0 if body is not overflowing', () => {
document.documentElement.style.overflowY = 'hidden'
document.body.style.overflowY = 'hidden'
fixtureEl.innerHTML = [
'<div style="height: 110vh; width: 100%"></div>'
].join('')
describe('Element', () => {
it('should return an integer greater than zero, if wrapper element is overflowing', () => {
fixtureEl.innerHTML = [
'<div class="wrapper" style="height: 100px; width: 100%; overflow: scroll">' +
' <div style="height: 120px; width: 100%"></div>' +
'</div>'
].join('')
const wrapper = fixtureEl.querySelector('.wrapper')
const result = new ScrollBarHelper(wrapper).getWidth()

if (isScrollBarHidden()) {
expect(result).toBe(0)
} else {
expect(result).toBeGreaterThan(1)
}
})

const result = new ScrollBarHelper().getWidth()
it('should return 0 if wrapper element is not overflowing', () => {
fixtureEl.innerHTML = [
'<div class="wrapper" style="height: 100px; width: 100%">' +
' <div style="height: 20px; width: 100%"></div>' +
'</div>'
].join('')
const wrapper = fixtureEl.querySelector('.wrapper')
const result = new ScrollBarHelper(wrapper).getWidth()

expect(result).toEqual(0)
expect(result).toEqual(0)
})
})
})

Expand Down

0 comments on commit 9d1c7b3

Please sign in to comment.