Skip to content

Commit 47eb479

Browse files
Filip-rspectiveokonet
authored andcommitted
feat: Add scroll sync groups (#11)
* add groups to react-scroll-sync * update docs
1 parent dcd6cdc commit 47eb479

File tree

3 files changed

+99
-20
lines changed

3 files changed

+99
-20
lines changed

src/ScrollSync.js

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,41 +33,51 @@ export default class ScrollSync extends Component {
3333
}
3434
}
3535

36-
panes = []
36+
panes = {}
3737

38-
registerPane = (node) => {
39-
if (!this.findPane(node)) {
40-
this.addEvents(node)
41-
this.panes.push(node)
38+
registerPane = (node, group) => {
39+
if (!this.panes[group]) {
40+
this.panes[group] = []
41+
}
42+
43+
if (!this.findPane(node, group)) {
44+
this.addEvents(node, group)
45+
this.panes[group].push(node)
4246
}
4347
}
4448

45-
unregisterPane = (node) => {
46-
if (this.findPane(node)) {
49+
unregisterPane = (node, group) => {
50+
if (this.findPane(node, group)) {
4751
this.removeEvents(node)
48-
this.panes.splice(this.panes.indexOf(node), 1)
52+
this.panes[group].splice(this.panes[group].indexOf(node), 1)
4953
}
5054
}
5155

52-
addEvents = (node) => {
56+
addEvents = (node, group) => {
5357
/* For some reason element.addEventListener doesnt work with document.body */
54-
node.onscroll = this.handlePaneScroll.bind(this, node) // eslint-disable-line
58+
node.onscroll = this.handlePaneScroll.bind(this, node, group) // eslint-disable-line
5559
}
5660

5761
removeEvents = (node) => {
5862
/* For some reason element.removeEventListener doesnt work with document.body */
5963
node.onscroll = null // eslint-disable-line
6064
}
6165

62-
findPane = node => this.panes.find(pane => pane === node)
66+
findPane = (node, group) => {
67+
if (!this.panes[group]) {
68+
return false
69+
}
70+
71+
return this.panes[group].find(pane => pane === node)
72+
}
6373

64-
handlePaneScroll = (node) => {
74+
handlePaneScroll = (node, group) => {
6575
window.requestAnimationFrame(() => {
66-
this.syncScrollPositions(node)
76+
this.syncScrollPositions(node, group)
6777
})
6878
}
6979

70-
syncScrollPositions = (scrolledPane) => {
80+
syncScrollPositions = (scrolledPane, group) => {
7181
const {
7282
scrollTop,
7383
scrollHeight,
@@ -82,11 +92,11 @@ export default class ScrollSync extends Component {
8292

8393
const { proportional, vertical, horizontal } = this.props
8494

85-
this.panes.forEach((pane) => {
95+
this.panes[group].forEach((pane) => {
8696
/* For all panes beside the currently scrolling one */
8797
if (scrolledPane !== pane) {
8898
/* Remove event listeners from the node that we'll manipulate */
89-
this.removeEvents(pane)
99+
this.removeEvents(pane, group)
90100
/* Calculate the actual pane height */
91101
const paneHeight = pane.scrollHeight - clientHeight
92102
const paneWidth = pane.scrollWidth - clientWidth
@@ -99,7 +109,7 @@ export default class ScrollSync extends Component {
99109
}
100110
/* Re-attach event listeners after we're done scrolling */
101111
window.requestAnimationFrame(() => {
102-
this.addEvents(pane)
112+
this.addEvents(pane, group)
103113
})
104114
}
105115
})

src/ScrollSyncPane.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ export default class ScrollSyncPane extends Component {
1717

1818
static propTypes = {
1919
children: PropTypes.node.isRequired,
20-
attachTo: PropTypes.object
20+
attachTo: PropTypes.object,
21+
group: PropTypes.string
22+
}
23+
24+
static defaultProps = {
25+
group: 'default'
2126
}
2227

2328
static contextTypes = {
@@ -27,11 +32,18 @@ export default class ScrollSyncPane extends Component {
2732

2833
componentDidMount() {
2934
this.node = this.props.attachTo || ReactDOM.findDOMNode(this)
30-
this.context.registerPane(this.node)
35+
this.context.registerPane(this.node, this.props.group)
36+
}
37+
38+
componentWillReceiveProps(nextProps) {
39+
if (this.props.group !== nextProps.group) {
40+
this.context.unregisterPane(this.node, this.props.group)
41+
this.context.registerPane(this.node, nextProps.group)
42+
}
3143
}
3244

3345
componentWillUnmount() {
34-
this.context.unregisterPane(this.node)
46+
this.context.unregisterPane(this.node, this.props.group)
3547
}
3648

3749
render() {

src/example.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,60 @@ To use ScrollSync you have to wrap your scrollable content (ensure that you have
4545

4646
Sometimes it is useful to attach the `onScroll` event listener to a different node (for example
4747
to a `document.body`). Use `attachTo` prop for that.
48+
49+
Additionally sometimes there is need to use few independent scroll groups inside one ScrollSync.
50+
Provide an arbitrary group name in the `group` prop to ScrollSyncPane components to limit synchronization to panes with that group name.
51+
52+
```
53+
<ScrollSync>
54+
<div style={{ display: 'flex', position: 'relative', height: 300 }}>
55+
<ScrollSyncPane group="one">
56+
<div style={{overflow: 'auto'}}>
57+
<section style={{ height: 500 }}>
58+
<h1>Left Pane Content</h1>
59+
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aperiam doloribus
60+
dolorum
61+
est eum eveniet exercitationem iste labore minus, neque nobis odit officiis omnis
62+
possimus quasi rerum sed soluta veritatis.</p>
63+
</section>
64+
</div>
65+
</ScrollSyncPane>
66+
67+
<ScrollSyncPane group="two">
68+
<div style={{overflow: 'auto'}}>
69+
<section style={{ height: 1000 }}>
70+
<h1>Middle Pane Content</h1>
71+
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aperiam doloribus
72+
dolorum
73+
est eum eveniet exercitationem iste labore minus, neque nobis odit officiis omnis
74+
possimus quasi rerum sed soluta veritatis.</p>
75+
</section>
76+
</div>
77+
</ScrollSyncPane>
78+
79+
<ScrollSyncPane group="one">
80+
<div style={{overflow: 'auto'}}>
81+
<section style={{ height: 2000 }}>
82+
<h1>Right Pane Content</h1>
83+
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aperiam doloribus
84+
dolorum
85+
est eum eveniet exercitationem iste labore minus, neque nobis odit officiis omnis
86+
possimus quasi rerum sed soluta veritatis.</p>
87+
</section>
88+
</div>
89+
</ScrollSyncPane>
90+
91+
<ScrollSyncPane group="two">
92+
<div style={{overflow: 'auto'}}>
93+
<section style={{ height: 2000 }}>
94+
<h1>Right Pane Content</h1>
95+
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aperiam doloribus
96+
dolorum
97+
est eum eveniet exercitationem iste labore minus, neque nobis odit officiis omnis
98+
possimus quasi rerum sed soluta veritatis.</p>
99+
</section>
100+
</div>
101+
</ScrollSyncPane>
102+
</div>
103+
</ScrollSync>
104+
```

0 commit comments

Comments
 (0)