Skip to content

Commit

Permalink
Fix popup position when window body is scrolled (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryank109 committed Mar 3, 2018
1 parent 8812276 commit 5dfb647
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 11 deletions.
16 changes: 11 additions & 5 deletions example-app/app/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@ class App extends Component {
constructor(props) {
super(props);
this.openModal = () => this.props.openPopup('modal1');
this.scroll = () => this.props.refreshPopupPosition();
}

componentDidMount() {
window.addEventListener('scroll', this.scroll);
}

componentWillUnmount() {
window.removeEventListener('scroll', this.scroll);
}

render() {
return (
<div
style={{overflow:'auto', height:'400px'}}
onScroll={this.scroll.bind(this)}
onScroll={this.scroll}
ref={div => { this.containerElement = div; }}>
<button onClick={this.openModal}>Open Modal</button>
<div className="abc" style={{height:'1000px'}}>
Expand All @@ -25,10 +35,6 @@ class App extends Component {
</div>
);
}

scroll(event) {
this.props.refreshPopupPosition();
}
}

export default connect(null, { closePopup, openPopup, refreshPopupPosition })(App);
1 change: 1 addition & 0 deletions example-app/app/components/popup-menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ PopupMenu.propTypes = {

export default props => (
<Popup
anchor={props.anchor}
className="popup-menu"
getRect={props.getRect}
id={props.id}
Expand Down
2 changes: 2 additions & 0 deletions example-app/app/menus.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Menus extends Component {
constructor(props) {
super(props);
this.state = {
anchors: [ 'top', 'bottom', 'left', 'right' ],
menus: [ menu1, menu2, menu3, menu4 ]
};
this.menu = {};
Expand All @@ -57,6 +58,7 @@ class Menus extends Component {
return this.state.menus.map(
(menu, index) => (
<PopupMenu
anchor={this.state.anchors[index]}
getRect={() => this.menu[index].getBoundingClientRect()}
id={`${index}`}
key={index}
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-redux-popup",
"version": "3.0.1",
"version": "3.0.2",
"description": "React redux popup",
"license": "MIT",
"main": "lib/react-redux-popup",
Expand Down
109 changes: 109 additions & 0 deletions src/__tests__/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { getPopupPosition } from 'rrp/utils';

describe('utils', () => {
afterEach(() => {
window.scrollX = 0;
window.scrollY = 0;
});

it('should anchor to bottom when enough space below', () => {
const anchor = 'bottom';
const rect = { bottom: 50, left: 10, right: 50, top: 10 };
Expand Down Expand Up @@ -460,4 +465,108 @@ describe('utils', () => {
top: 70,
});
});

it('should anchor to bottom when enough space below and window has scrolled', () => {
window.scrollX = 20;
window.scrollY = 30;

const anchor = 'bottom';
const rect = { bottom: 50, left: 10, right: 50, top: 10 };
const popupWidth = 100;
const popupHeight = 100;
const windowWidth = 300;
const windowHeight = 300;
const offset = 10;

expect(getPopupPosition(
anchor,
rect,
popupWidth,
popupHeight,
windowWidth,
windowHeight,
offset
)).toEqual({
left: 30,
top: 90,
});
});

it('should anchor to top when enough space above and window has scrolled', () => {
window.scrollX = 20;
window.scrollY = 30;

const anchor = 'top';
const rect = { bottom: 290, left: 10, right: 50, top: 250 };
const popupWidth = 100;
const popupHeight = 100;
const windowWidth = 300;
const windowHeight = 300;
const offset = 10;

expect(getPopupPosition(
anchor,
rect,
popupWidth,
popupHeight,
windowWidth,
windowHeight,
offset
)).toEqual({
left: 30,
top: 170,
});
});

it('should anchor to right when enough space on the right and window has scrolled', () => {
window.scrollX = 20;
window.scrollY = 30;

const anchor = 'right';
const rect = { bottom: 50, left: 10, right: 50, top: 10 };
const popupWidth = 100;
const popupHeight = 100;
const windowWidth = 300;
const windowHeight = 300;
const offset = 10;

expect(getPopupPosition(
anchor,
rect,
popupWidth,
popupHeight,
windowWidth,
windowHeight,
offset
)).toEqual({
left: 80,
top: 40,
});
});

it('should anchor to left when enough space on the left and window has scrolled', () => {
window.scrollX = 20;
window.scrollY = 30;

const anchor = 'left';
const rect = { bottom: 50, left: 250, right: 290, top: 10 };
const popupWidth = 100;
const popupHeight = 100;
const windowWidth = 300;
const windowHeight = 300;
const offset = 10;

expect(getPopupPosition(
anchor,
rect,
popupWidth,
popupHeight,
windowWidth,
windowHeight,
offset
)).toEqual({
left: 160,
top: 40,
});
});
});
8 changes: 4 additions & 4 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ export function getPopupPosition(
windowWidth,
popupWidth,
rect.left,
rect.right),
rect.right) + window.scrollX,
top: calculatePosition(
windowHeight,
popupHeight,
rect.top,
rect.bottom,
offset,
anchor === 'bottom'),
anchor === 'bottom') + window.scrollY,
};
default: // left and right
return {
Expand All @@ -64,12 +64,12 @@ export function getPopupPosition(
rect.left,
rect.right,
offset,
anchor === 'right'),
anchor === 'right') + window.scrollX,
top: adjustPosition(
windowHeight,
popupHeight,
rect.top,
rect.bottom),
rect.bottom) + window.scrollY,
};
}
}

0 comments on commit 5dfb647

Please sign in to comment.