Skip to content

Commit 7e5230c

Browse files
committed
feat: method to disable the Parallax Controller #13
1 parent 3b101ab commit 7e5230c

File tree

7 files changed

+148
-11
lines changed

7 files changed

+148
-11
lines changed

documentation/docs/api/parallax-controller/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ See the options for creating a new controller tied to a view: [`ParallaxControll
2222
- [`removeElementById()`](./methods#removeelementbyid)
2323
- [`resetElementStyles()`](./methods#resetelementstyles)
2424
- [`updateScrollContainer()`](./methods#updatescrollcontainer)
25-
- [`disableAllElements()`](./methods#disableallelements)
26-
- [`enableAllElements()`](./methods#enableallelements)
25+
- [`disableParallaxController()`](./methods#disableParallaxController)
26+
- [`enableParallaxController()`](./methods#enableParallaxController)
2727
- [`update()`](./methods#update)
2828
- [`destroy()`](./methods#destroy)

documentation/docs/api/parallax-controller/init.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ The following option can be passed to `ParallaxController.init(...)`.
2525
| Option | Default | Description |
2626
| ----------------- | :----------: | -------------------------------------------------------------------------- |
2727
| `scrollAxis` | `'vertical'` | Direction of scroll for the element. One of `'vertical'` or `'horizontal'` |
28+
| `disabled` | false | Initial disabled state of the Parallax Controller |
2829
| `scrollContainer` | `window` | HTMLElement that will contain scroll elements. |

documentation/docs/api/parallax-controller/methods.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,20 @@ const el = document.getElementById('your-scroll-container');
5656
parallaxController.updateScrollContainer(el);
5757
```
5858

59-
## disableAllElements()
59+
## disableParallaxController()
6060

61-
Disables all parallax elements in the controller.
61+
Disables the Parallax Controller.
6262

6363
```ts
64-
parallaxController.disableAllElements();
64+
parallaxController.disableParallaxController();
6565
```
6666

67-
## enableAllElements()
67+
## enableParallaxController()
6868

69-
Enables all parallax elements in the controller.
69+
Enables the Parallax Controller.
7070

7171
```ts
72-
parallaxController.enableAllElements();
72+
parallaxController.enableParallaxController();
7373
```
7474

7575
## update()

src/classes/Element.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,18 @@ import { scaleTranslateEffectsForSlowerScroll } from '../helpers/scaleTranslateE
2727
import { getShouldScaleTranslateEffects } from '../helpers/getShouldScaleTranslateEffects';
2828
import { clamp } from '../helpers/clamp';
2929

30-
type ElementConstructorOptions = CreateElementOptions & {
30+
type ParallaxControllerConstructorOptions = {
3131
scrollAxis: ValidScrollAxis;
32+
disabledParallaxController?: boolean;
3233
};
34+
type ElementConstructorOptions = CreateElementOptions &
35+
ParallaxControllerConstructorOptions;
3336

3437
export class Element {
3538
el: HTMLElement;
3639
props: ParallaxElementConfig;
3740
scrollAxis: ValidScrollAxis;
41+
disabledParallaxController: boolean;
3842
id: number;
3943
effects: ParallaxStartEndEffects;
4044
isInView: boolean | null;
@@ -49,6 +53,8 @@ export class Element {
4953
this.el = options.el;
5054
this.props = options.props;
5155
this.scrollAxis = options.scrollAxis;
56+
this.disabledParallaxController =
57+
options.disabledParallaxController || false;
5258
this.id = createId();
5359
this.effects = parseElementTransitionEffects(this.props, this.scrollAxis);
5460
this.isInView = null;
@@ -150,7 +156,7 @@ export class Element {
150156
}
151157

152158
_setElementStyles() {
153-
if (this.props.disabled) return;
159+
if (this.props.disabled || this.disabledParallaxController) return;
154160
const effects = this.scaledEffects || this.effects;
155161
setElementStyles(effects, this.progress, this.el);
156162
}
@@ -165,6 +171,12 @@ export class Element {
165171
this.easing = createEasingFunction(easing);
166172
}
167173

174+
updateElementOptions(options: ParallaxControllerConstructorOptions) {
175+
this.scrollAxis = options.scrollAxis;
176+
this.disabledParallaxController =
177+
options.disabledParallaxController || false;
178+
}
179+
168180
updatePosition(scroll: Scroll): Element {
169181
if (!this.limits) return this;
170182

src/classes/ParallaxController.test.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Element } from './Element';
33
import { Rect } from './Rect';
44
import { Limits } from './Limits';
55
import { CSSEffect, ScrollAxis } from '../types';
6+
import * as elementStyles from '../helpers/elementStyles';
67

78
const addEventListener = window.addEventListener;
89
const removeEventListener = window.removeEventListener;
@@ -18,10 +19,45 @@ const OPTIONS = {
1819

1920
describe('Expect the ParallaxController', () => {
2021
afterEach(() => {
22+
jest.restoreAllMocks();
2123
window.addEventListener = addEventListener;
2224
window.removeEventListener = removeEventListener;
2325
});
2426

27+
describe('when init with disabled configuration', () => {
28+
it('to not add listeners when init', () => {
29+
window.addEventListener = jest.fn();
30+
const controller = ParallaxController.init({
31+
scrollAxis: ScrollAxis.vertical,
32+
disabled: true,
33+
});
34+
// @ts-expect-error
35+
expect(window.addEventListener.mock.calls[0]).toEqual(
36+
expect.arrayContaining(['test', null, expect.any(Object)])
37+
);
38+
// @ts-expect-error
39+
expect(window.addEventListener.mock.calls[1]).toBeUndefined();
40+
// @ts-expect-error
41+
expect(window.addEventListener.mock.calls[2]).toBeUndefined();
42+
// @ts-expect-error
43+
expect(window.addEventListener.mock.calls[3]).toBeUndefined();
44+
// @ts-expect-error
45+
expect(window.addEventListener.mock.calls[4]).toBeUndefined();
46+
// @ts-expect-error
47+
expect(window.addEventListener.mock.calls[5]).toBeUndefined();
48+
controller.destroy();
49+
});
50+
it('to create an element with the disabledParallaxController property', () => {
51+
const controller = ParallaxController.init({
52+
scrollAxis: ScrollAxis.vertical,
53+
disabled: true,
54+
});
55+
const element = controller.createElement(OPTIONS);
56+
expect(element.disabledParallaxController).toBe(true);
57+
controller.destroy();
58+
});
59+
});
60+
2561
it('to return an instance on init', () => {
2662
const controller = ParallaxController.init({
2763
scrollAxis: ScrollAxis.vertical,
@@ -62,6 +98,49 @@ describe('Expect the ParallaxController', () => {
6298
controller.destroy();
6399
});
64100

101+
describe('when disabling the controller', () => {
102+
it('to update the disabled property', () => {
103+
const controller = ParallaxController.init({
104+
scrollAxis: ScrollAxis.vertical,
105+
});
106+
controller.disableParallaxController();
107+
expect(controller.disabled).toBe(true);
108+
controller.destroy();
109+
});
110+
111+
it('to reset element styles', () => {
112+
const controller = ParallaxController.init({
113+
scrollAxis: ScrollAxis.vertical,
114+
});
115+
const element = controller.createElement(OPTIONS);
116+
jest.spyOn(elementStyles, 'resetStyles');
117+
controller.disableParallaxController();
118+
expect(elementStyles.resetStyles).toHaveBeenCalledWith(element);
119+
controller.destroy();
120+
});
121+
122+
it('to remove listeners', () => {
123+
window.removeEventListener = jest.fn();
124+
const controller = ParallaxController.init({
125+
scrollAxis: ScrollAxis.vertical,
126+
});
127+
controller.disableParallaxController();
128+
// @ts-expect-error
129+
expect(window.removeEventListener.mock.calls[0]).toEqual(
130+
expect.arrayContaining(['test', null, expect.any(Object)])
131+
);
132+
// @ts-expect-error
133+
expect(window.removeEventListener.mock.calls[1]).toEqual(
134+
expect.arrayContaining(['scroll', expect.any(Function), false])
135+
);
136+
// @ts-expect-error
137+
expect(window.removeEventListener.mock.calls[2]).toEqual(
138+
expect.arrayContaining(['resize', expect.any(Function), false])
139+
);
140+
controller.destroy();
141+
});
142+
});
143+
65144
it('to add a resize observer', () => {
66145
const controller = ParallaxController.init({
67146
scrollAxis: ScrollAxis.vertical,
@@ -129,6 +208,7 @@ describe('Expect the ParallaxController', () => {
129208
});
130209

131210
it('to disable all elements when calling disableAllElements()', () => {
211+
jest.spyOn(console, 'warn').mockImplementation(() => {});
132212
const controller = ParallaxController.init({
133213
scrollAxis: ScrollAxis.vertical,
134214
});
@@ -142,9 +222,13 @@ describe('Expect the ParallaxController', () => {
142222
elements.forEach(element => {
143223
expect(element.props.disabled).toBe(true);
144224
});
225+
expect(console.warn).toHaveBeenCalledWith(
226+
'deprecated: use disableParallaxController() instead'
227+
);
145228
});
146229

147230
it('to enable all elements when calling enableAllElements()', () => {
231+
jest.spyOn(console, 'warn').mockImplementation(() => {});
148232
const controller = ParallaxController.init({
149233
scrollAxis: ScrollAxis.vertical,
150234
});
@@ -158,6 +242,9 @@ describe('Expect the ParallaxController', () => {
158242
elements.forEach(element => {
159243
expect(element.props.disabled).toBe(false);
160244
});
245+
expect(console.warn).toHaveBeenCalledWith(
246+
'deprecated: use enableParallaxController() instead'
247+
);
161248
});
162249

163250
it('to remove listeners when destroyed', () => {

src/classes/ParallaxController.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
*/
2323

2424
export class ParallaxController {
25+
disabled: boolean;
2526
elements: Element[];
2627
scrollAxis: ValidScrollAxis;
2728
viewEl: ViewElement;
@@ -51,7 +52,9 @@ export class ParallaxController {
5152
constructor({
5253
scrollAxis = ScrollAxis.vertical,
5354
scrollContainer,
55+
disabled = false,
5456
}: ParallaxControllerOptions) {
57+
this.disabled = disabled;
5558
this.scrollAxis = scrollAxis;
5659
// All parallax elements to be updated
5760
this.elements = [];
@@ -79,6 +82,10 @@ export class ParallaxController {
7982

8083
// Bind methods to class
8184
this._bindAllMethods();
85+
86+
// If this is initialized disabled, don't do anything below.
87+
if (this.disabled) return;
88+
8289
this._addListeners(this.viewEl);
8390
this._addResizeObserver();
8491
this._setViewSize();
@@ -211,7 +218,7 @@ export class ParallaxController {
211218
* attributes, if so set the elements parallax styles.
212219
*/
213220
_updateElementPosition(element: Element) {
214-
if (element.props.disabled) return;
221+
if (element.props.disabled || this.disabled) return;
215222
element.updatePosition(this.scroll);
216223
}
217224

@@ -285,6 +292,7 @@ export class ParallaxController {
285292
const newElement = new Element({
286293
...options,
287294
scrollAxis: this.scrollAxis,
295+
disabledParallaxController: this.disabled,
288296
});
289297
newElement.setCachedAttributes(this.view, this.scroll);
290298
this.elements = this.elements
@@ -365,10 +373,37 @@ export class ParallaxController {
365373
this._updateAllElements({ updateCache: true });
366374
}
367375

376+
disableParallaxController() {
377+
this.disabled = true;
378+
// remove listeners
379+
this._removeListeners(this.viewEl);
380+
// reset all styles
381+
if (this.elements) {
382+
this.elements.forEach(element => resetStyles(element));
383+
}
384+
}
385+
386+
enableParallaxController() {
387+
this.disabled = false;
388+
if (this.elements) {
389+
this.elements.forEach(element =>
390+
element.updateElementOptions({
391+
disabledParallaxController: false,
392+
scrollAxis: this.scrollAxis,
393+
})
394+
);
395+
}
396+
// add back listeners
397+
this._addListeners(this.viewEl);
398+
this._addResizeObserver();
399+
this._setViewSize();
400+
}
401+
368402
/**
369403
* Disable all parallax elements
370404
*/
371405
disableAllElements() {
406+
console.warn('deprecated: use disableParallaxController() instead');
372407
if (this.elements) {
373408
this.elements = this.elements.map(el => {
374409
return el.updateProps({ disabled: true });
@@ -381,6 +416,7 @@ export class ParallaxController {
381416
* Enable all parallax elements
382417
*/
383418
enableAllElements() {
419+
console.warn('deprecated: use enableParallaxController() instead');
384420
if (this.elements) {
385421
this.elements = this.elements.map(el => {
386422
return el.updateProps({ disabled: false });

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export type ViewElement = HTMLElement | Window;
7777
export type ParallaxControllerOptions = {
7878
scrollAxis?: ValidScrollAxis;
7979
scrollContainer?: HTMLElement;
80+
disabled?: boolean;
8081
};
8182

8283
export type EffectNumber = [number, number, EasingParam?];

0 commit comments

Comments
 (0)