import popper.js
Signed-off-by: Nico Schottelius <nico@nico-notebook.schottelius.org>
This commit is contained in:
parent
615dc56d16
commit
16fb2bb919
241 changed files with 34099 additions and 0 deletions
|
|
@ -0,0 +1,500 @@
|
|||
import Popper from '../../src/index.js';
|
||||
import getOppositePlacement from '../../src/utils/getOppositePlacement';
|
||||
|
||||
// Utils
|
||||
import appendNewPopper from '@popperjs/test-utils/utils/appendNewPopper';
|
||||
import appendNewRef from '@popperjs/test-utils/utils/appendNewRef';
|
||||
import simulateScroll from '@popperjs/test-utils/utils/simulateScroll';
|
||||
import getRect from '../utils/getRect';
|
||||
const jasmineWrapper = document.getElementById('jasmineWrapper');
|
||||
|
||||
const isIPHONE = window.navigator.userAgent.match(/iPhone/i);
|
||||
[true, false].forEach((positionFixed) => {
|
||||
|
||||
describe('[flipping]' + (positionFixed ? ' Fixed' : ''), () => {
|
||||
|
||||
beforeEach(function(){
|
||||
Popper.Defaults.positionFixed = positionFixed;
|
||||
});
|
||||
|
||||
it('should flip from top to bottom', done => {
|
||||
const ref = appendNewRef(1, 'ref', jasmineWrapper);
|
||||
ref.style.marginLeft = '100px';
|
||||
const popper = appendNewPopper(2, 'popper');
|
||||
new Popper(ref, popper, {
|
||||
placement: 'top',
|
||||
onCreate: data => {
|
||||
expect(data.placement).toBe('bottom');
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const flippingDefault = [
|
||||
'top',
|
||||
'top-start',
|
||||
'top-end',
|
||||
'bottom',
|
||||
'bottom-start',
|
||||
'bottom-end',
|
||||
'left',
|
||||
'left-start',
|
||||
'left-end',
|
||||
'right',
|
||||
'right-start',
|
||||
'right-end',
|
||||
];
|
||||
|
||||
const flippingVariations = {
|
||||
'top-start': 'top-end',
|
||||
'top-end': 'top-start',
|
||||
'bottom-start': 'bottom-end',
|
||||
'bottom-end': 'bottom-start',
|
||||
'left-start': 'left-end',
|
||||
'left-end': 'left-start',
|
||||
'right-start': 'right-end',
|
||||
'right-end': 'right-start',
|
||||
};
|
||||
|
||||
flippingDefault.forEach(val => {
|
||||
it(`should flip from ${val} to ${getOppositePlacement(
|
||||
val
|
||||
)} if boundariesElement is set`, done => {
|
||||
const relative = document.createElement('div');
|
||||
relative.style.margin = '100px 300px';
|
||||
relative.style.height = '100px';
|
||||
relative.style.width = '100px';
|
||||
relative.style.background = '#ffff00';
|
||||
jasmineWrapper.appendChild(relative);
|
||||
|
||||
const ref = appendNewRef(1, 'ref', relative);
|
||||
ref.style.width = '70px';
|
||||
ref.style.height = '70px';
|
||||
ref.style.background = 'green';
|
||||
// ref.style.marginTop = '100px';
|
||||
const popper = appendNewPopper(2, 'popper');
|
||||
|
||||
new Popper(ref, popper, {
|
||||
placement: val,
|
||||
modifiers: {
|
||||
flip: { boundariesElement: relative },
|
||||
},
|
||||
onCreate: data => {
|
||||
expect(data.flipped).toBe(true);
|
||||
expect(data.placement).toBe(getOppositePlacement(val));
|
||||
expect(data.originalPlacement).toBe(val);
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should NOT flip if there is no boundariesElement', done => {
|
||||
const relative = document.createElement('div');
|
||||
relative.style.margin = '100px 300px';
|
||||
relative.style.height = '100px';
|
||||
relative.style.width = '100px';
|
||||
relative.style.background = '#ffff00';
|
||||
jasmineWrapper.appendChild(relative);
|
||||
|
||||
const ref = appendNewRef(1, 'ref', relative);
|
||||
ref.style.width = '70px';
|
||||
ref.style.height = '70px';
|
||||
ref.style.background = 'green';
|
||||
// ref.style.marginTop = '100px';
|
||||
const popper = appendNewPopper(3, 'popper');
|
||||
|
||||
new Popper(ref, popper, {
|
||||
placement: val,
|
||||
onCreate: data => {
|
||||
expect(data.flipped).not.toBe(true);
|
||||
expect(data.placement).toBe(val);
|
||||
expect(data.originalPlacement).toBe(val);
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function getSecondaryMarginByReference(val) {
|
||||
return (val === 'start' ? '-' : '') + '100px';
|
||||
}
|
||||
|
||||
function getSecondaryMarginByContent(val) {
|
||||
return val === 'start' ? '200px' : '50px';
|
||||
}
|
||||
|
||||
Object.keys(flippingVariations).forEach(val => {
|
||||
it(`(variations)(by reference) should flip from ${val} to ${flippingVariations[
|
||||
val
|
||||
]} if boundariesElement is set`, done => {
|
||||
const relative = document.createElement('div');
|
||||
relative.style.margin = '100px 300px';
|
||||
relative.style.height = '300px';
|
||||
relative.style.width = '300px';
|
||||
relative.style.background = '#ffff00';
|
||||
relative.style.position = 'relative';
|
||||
jasmineWrapper.appendChild(relative);
|
||||
|
||||
const ref = appendNewRef(1, 'ref', relative);
|
||||
ref.style.width = '200px';
|
||||
ref.style.height = '200px';
|
||||
ref.style.background = 'green';
|
||||
ref.style.position = 'absolute';
|
||||
ref.style.zIndex = '10';
|
||||
const valElems = val.split('-');
|
||||
|
||||
switch (valElems[0]) {
|
||||
case 'top':
|
||||
ref.style.top = '100px';
|
||||
ref.style.left = getSecondaryMarginByReference(valElems[1]);
|
||||
break;
|
||||
case 'bottom':
|
||||
ref.style.bottom = '100px';
|
||||
ref.style.left = getSecondaryMarginByReference(valElems[1]);
|
||||
break;
|
||||
case 'left':
|
||||
ref.style.top = getSecondaryMarginByReference(valElems[1]);
|
||||
ref.style.left = '200px';
|
||||
break;
|
||||
case 'right':
|
||||
ref.style.top = getSecondaryMarginByReference(valElems[1]);
|
||||
ref.style.right = '200px';
|
||||
break;
|
||||
}
|
||||
|
||||
const popper = appendNewPopper(2, 'popper');
|
||||
|
||||
new Popper(ref, popper, {
|
||||
placement: val,
|
||||
modifiers: {
|
||||
preventOverflow: {
|
||||
enabled: true,
|
||||
escapeWithReference: true,
|
||||
},
|
||||
flip: {
|
||||
flipVariations: true,
|
||||
boundariesElement: relative,
|
||||
},
|
||||
},
|
||||
onCreate: data => {
|
||||
expect(data.flipped).toBe(true);
|
||||
expect(data.placement).toBe(flippingVariations[val]);
|
||||
expect(data.originalPlacement).toBe(val);
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(flippingVariations).forEach(val => {
|
||||
it(`(variations)(by content) should flip from ${val} to ${flippingVariations[
|
||||
val
|
||||
]} if boundariesElement is set`, done => {
|
||||
const relative = document.createElement('div');
|
||||
relative.style.margin = '100px 300px';
|
||||
relative.style.height = '300px';
|
||||
relative.style.width = '300px';
|
||||
relative.style.background = '#ffff00';
|
||||
relative.style.position = 'relative';
|
||||
jasmineWrapper.appendChild(relative);
|
||||
|
||||
const ref = appendNewRef(1, 'ref', relative);
|
||||
ref.style.width = '50px';
|
||||
ref.style.height = '50px';
|
||||
ref.style.background = 'green';
|
||||
ref.style.position = 'absolute';
|
||||
ref.style.zIndex = '10';
|
||||
const valElems = val.split('-');
|
||||
|
||||
switch (valElems[0]) {
|
||||
case 'top':
|
||||
ref.style.bottom = '20px';
|
||||
ref.style.left = getSecondaryMarginByContent(valElems[1]);
|
||||
break;
|
||||
case 'bottom':
|
||||
ref.style.top = '20px';
|
||||
ref.style.left = getSecondaryMarginByContent(valElems[1]);
|
||||
break;
|
||||
case 'left':
|
||||
ref.style.top = getSecondaryMarginByContent(valElems[1]);
|
||||
ref.style.left = '200px';
|
||||
break;
|
||||
case 'right':
|
||||
ref.style.top = getSecondaryMarginByContent(valElems[1]);
|
||||
ref.style.right = '200px';
|
||||
break;
|
||||
}
|
||||
|
||||
const large = document.createElement('div');
|
||||
large.style.width = '150px';
|
||||
large.style.height = '150px';
|
||||
large.style.backgroundColor = 'blue';
|
||||
|
||||
const popper = appendNewPopper(2, 'popper');
|
||||
popper.appendChild(large);
|
||||
|
||||
new Popper(ref, popper, {
|
||||
placement: val,
|
||||
modifiers: {
|
||||
preventOverflow: {
|
||||
enabled: true,
|
||||
escapeWithReference: true,
|
||||
},
|
||||
flip: {
|
||||
flipVariationsByContent: true,
|
||||
boundariesElement: relative,
|
||||
},
|
||||
},
|
||||
onCreate: data => {
|
||||
expect(data.flipped).toBe(true);
|
||||
expect(data.placement).toBe(flippingVariations[val]);
|
||||
expect(data.originalPlacement).toBe(val);
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('flips to opposite side when rendered inside a positioned parent', done => {
|
||||
const page = document.createElement('div');
|
||||
page.style.paddingTop = '110vh'; // Simulates page content
|
||||
page.style.background = 'lightskyblue';
|
||||
jasmineWrapper.appendChild(page);
|
||||
|
||||
const parent = document.createElement('div');
|
||||
parent.style.position = 'relative';
|
||||
parent.style.background = 'yellow';
|
||||
page.appendChild(parent);
|
||||
|
||||
const ref = appendNewRef(1, 'reference', parent);
|
||||
const popper = appendNewPopper(2, 'popper', parent);
|
||||
|
||||
new Popper(ref, popper, {
|
||||
onCreate: data => {
|
||||
simulateScroll(page, { scrollTop: '110vh', delay: 10 });
|
||||
|
||||
const popperRect = popper.getBoundingClientRect();
|
||||
const refRect = ref.getBoundingClientRect();
|
||||
const arrowSize = 5;
|
||||
|
||||
expect(data.flipped).toBe(true);
|
||||
expect(popperRect.bottom + arrowSize).toBeApprox(refRect.top);
|
||||
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('flips to bottom when hits top viewport edge', done => {
|
||||
if (isIPHONE) {
|
||||
pending();
|
||||
}
|
||||
|
||||
jasmineWrapper.innerHTML = `
|
||||
<div id="s1" style="height: 3000px; background: red;">
|
||||
<div id="reference" style="background: pink; margin-top: 200px">reference</div>
|
||||
<div id="popper" style="background: purple">popper</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
|
||||
new Popper(reference, popper, {
|
||||
placement: 'top',
|
||||
onCreate() {
|
||||
simulateScroll(document.body, { scrollTop: 200 });
|
||||
},
|
||||
onUpdate(data) {
|
||||
expect(getRect(popper).top).toBeApprox(getRect(reference).bottom);
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('flip properly with large popper width', done => {
|
||||
jasmineWrapper.innerHTML = `
|
||||
<style>body { margin: 0; }</style>
|
||||
<div style="background: grey; height: 100vh;">
|
||||
<div
|
||||
id="reference"
|
||||
style="background: yellow; width: 200px; height: 80vh;"
|
||||
>
|
||||
ref
|
||||
</div>
|
||||
<div
|
||||
id="popper"
|
||||
style="background: purple; width: 95vw; height: 30px;"
|
||||
>
|
||||
popper
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
|
||||
new Popper(reference, popper, {
|
||||
placement: 'auto',
|
||||
onCreate(data) {
|
||||
expect(data.placement).toBe('bottom');
|
||||
expect(getRect(reference).bottom).toBeApprox(getRect(popper).top);
|
||||
data.instance.destroy();
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('init popper on fixed reference aligned to left and flips to right', done => {
|
||||
jasmineWrapper.innerHTML = `
|
||||
<div id="reference" style="position: fixed; top: 50px; left: 1px; background: pink">reference</div>
|
||||
<div id="popper" style="background: purple; width: 5px">popper</div>
|
||||
`;
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
|
||||
new Popper(reference, popper, {
|
||||
placement: 'left-start',
|
||||
onCreate() {
|
||||
expect(popper.getBoundingClientRect().top).toBeApprox(
|
||||
reference.getBoundingClientRect().top
|
||||
);
|
||||
expect(popper.getBoundingClientRect().left).toBeApprox(
|
||||
reference.getBoundingClientRect().right
|
||||
);
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('init popper on fixed reference aligned to right and flips to left', done => {
|
||||
jasmineWrapper.innerHTML = `
|
||||
<div id="reference" style="position: fixed; top: 50px; right: 1px; background: pink">reference</div>
|
||||
<div id="popper" style="background: purple;">popper</div>
|
||||
`;
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
|
||||
new Popper(reference, popper, {
|
||||
placement: 'right-start',
|
||||
onCreate() {
|
||||
expect(popper.getBoundingClientRect().top).toBeApprox(
|
||||
reference.getBoundingClientRect().top
|
||||
);
|
||||
expect(popper.getBoundingClientRect().right).toBeApprox(
|
||||
reference.getBoundingClientRect().left
|
||||
);
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('init popper on fixed reference aligned to top and flips to bottom', done => {
|
||||
jasmineWrapper.innerHTML = `
|
||||
<div id="reference" style="position: fixed; top: 1px; left: 50px; background: pink">reference</div>
|
||||
<div id="popper" style="background: purple;">popper</div>
|
||||
`;
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
|
||||
new Popper(reference, popper, {
|
||||
placement: 'top-start',
|
||||
onCreate() {
|
||||
expect(popper.getBoundingClientRect().top).toBeApprox(
|
||||
reference.getBoundingClientRect().bottom
|
||||
);
|
||||
expect(popper.getBoundingClientRect().left).toBeApprox(
|
||||
reference.getBoundingClientRect().left
|
||||
);
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('init popper on fixed reference aligned to bottom and flips to top', done => {
|
||||
jasmineWrapper.innerHTML = `
|
||||
<div id="reference" style="position: fixed; bottom: 1px; right: 50px; background: pink">reference</div>
|
||||
<div id="popper" style="background: purple;">popper</div>
|
||||
`;
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
|
||||
new Popper(reference, popper, {
|
||||
placement: 'bottom-start',
|
||||
onCreate() {
|
||||
expect(popper.getBoundingClientRect().bottom).toBeApprox(
|
||||
reference.getBoundingClientRect().top
|
||||
);
|
||||
expect(popper.getBoundingClientRect().left).toBeApprox(
|
||||
reference.getBoundingClientRect().left
|
||||
);
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('init popper on transformed parent flips to top', done => {
|
||||
jasmineWrapper.innerHTML = `
|
||||
<div id="container" style="position: relative; margin-left: 100px; margin-top:100px; height: 100vh; transform: translateZ(0)">
|
||||
<div style="height:100%"></div>
|
||||
<div id="reference" style="background: pink">reference</div>
|
||||
<div id="popper" style="background: purple;">popper</div>
|
||||
<div style="height:200%"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
new Popper(reference, popper, {
|
||||
placement: 'bottom-start',
|
||||
onCreate() {
|
||||
expect(popper.getBoundingClientRect().bottom).toBeApprox(
|
||||
reference.getBoundingClientRect().top
|
||||
);
|
||||
expect(popper.getBoundingClientRect().left).toBeApprox(
|
||||
reference.getBoundingClientRect().left
|
||||
);
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// This one will fail on IE10 - See #211
|
||||
xit('properly positions a bottom popper inside very high body', done => {
|
||||
jasmineWrapper.innerHTML = `
|
||||
<div id="reference" style="background: pink; margin-top: 100vh; width: 100px; height: 100px;">reference</div>
|
||||
<div id="popper" style="background: purple; width: 100px; height: 100px;">popper</div>
|
||||
`;
|
||||
document.body.style.height = '200vh';
|
||||
|
||||
const reference = document.getElementById('reference');
|
||||
const popper = document.getElementById('popper');
|
||||
|
||||
new Popper(reference, popper, {
|
||||
onCreate() {
|
||||
simulateScroll(document.body, {
|
||||
scrollTop: getRect(document.body).height,
|
||||
delay: 50,
|
||||
});
|
||||
},
|
||||
onUpdate(data) {
|
||||
expect(getRect(popper).top).toBeApprox(getRect(reference).bottom);
|
||||
data.instance.destroy();
|
||||
document.body.style.cssText = null;
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue