Skip to content

Commit 0c6a22b

Browse files
authored
Merge pull request #397 from chriskrycho/programmatic-observation
Allow programmatic control of observation
2 parents 9b79804 + 220c6d0 commit 0c6a22b

File tree

5 files changed

+110
-14
lines changed

5 files changed

+110
-14
lines changed

addon/modifiers/did-intersect.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,14 @@ export default class DidIntersectModifier extends Modifier {
7777
return;
7878
}
7979

80-
let { onEnter, onExit, maxEnter, maxExit, options } = this.args.named;
80+
let {
81+
onEnter,
82+
onExit,
83+
maxEnter,
84+
maxExit,
85+
options,
86+
isObserving = true,
87+
} = this.args.named;
8188

8289
assert('onEnter or/and onExit is required', onEnter || onExit);
8390

@@ -161,7 +168,11 @@ export default class DidIntersectModifier extends Modifier {
161168
this._options = options;
162169
}
163170

164-
this.observe();
171+
if (isObserving) {
172+
this.observe();
173+
} else {
174+
this.unobserve();
175+
}
165176
}
166177

167178
// Move to willDestroy when we want to drop support for versions below ember-modifier 2.x

tests/dummy/app/controllers/index.js

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export default class IndexController extends Controller {
1111

1212
maxIntersections = 5;
1313

14+
@tracked
15+
isObserving = true;
16+
17+
@tracked
18+
numIntersectionsWithIsObserving = 0;
19+
1420
@tracked
1521
shouldScrollIntoView = false;
1622

@@ -24,6 +30,16 @@ export default class IndexController extends Controller {
2430
this.numIntersectionsWithMaxEnter++;
2531
}
2632

33+
@action
34+
toggleIsObserving() {
35+
this.isObserving = !this.isObserving;
36+
}
37+
38+
@action
39+
onEnteringWithIsObserving() {
40+
this.numIntersectionsWithIsObserving++;
41+
}
42+
2743
@action
2844
onScrollIntoViewTrigger() {
2945
this.shouldScrollIntoView = true;

tests/dummy/app/styles/app.scss

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@
99
}
1010
}
1111

12+
.action-button {
13+
border-radius: 4px;
14+
padding: 0.5em;
15+
background-color: orangered;
16+
color: white;
17+
}
18+
1219
.scroll-into-view {
1320
border: 1px dotted black;
1421
padding: 50px 16px;
1522
text-align: center;
16-
17-
button {
18-
border-radius: 4px;
19-
padding: .5em;
20-
background-color: orangered;
21-
color: white;
22-
}
2323
}
2424

2525
// prevent copy button from overlapping code

tests/dummy/app/templates/index.hbs

+20-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,31 @@
2424
</demo.example>
2525
{{demo.snippet "did-intersect-with-max-enter.hbs" label="example with max enter.hbs"}}
2626

27+
<demo.example @name="did-intersect-with-is-observing.hbs">
28+
<div
29+
class="intersection-box"
30+
{{did-intersect
31+
isObserving=this.isObserving
32+
onEnter=this.onEnteringWithIsObserving
33+
}}
34+
>
35+
<p>Number of times this box has intersected the screen: {{this.numIntersectionsWithIsObserving}}</p>
36+
37+
<p>isObserving: {{this.isObserving}}</p>
38+
39+
<button type='button' class="action-button" {{on "click" this.toggleIsObserving}}>
40+
{{if this.isObserving "Stop" "Start"}} observing
41+
</button>
42+
</div>
43+
</demo.example>
44+
{{demo.snippet "did-intersect-with-is-observing.hbs" label="example with isObserving.hbs"}}
45+
2746
<demo.example @name="scroll-into-view.hbs">
2847
<div
2948
class="scroll-into-view"
3049
{{scroll-into-view shouldScroll=this.shouldScrollIntoView}}
3150
>
32-
<button type="button" class="scroll-into-view__button" {{on "click" this.onScrollIntoViewTrigger}}>
51+
<button type="button" class="action-button" {{on "click" this.onScrollIntoViewTrigger}}>
3352
Trigger Scroll-into-view on click
3453
</button>
3554
</div>

tests/integration/modifiers/did-intersect-test.js

+54-4
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,21 @@ module('Integration | Modifier | did-intersect', function (hooks) {
1616
this._admin = {};
1717
}
1818

19-
observe = sinon.stub();
20-
unobserve = sinon.stub();
19+
observe = sinon.stub().callsFake(() => {
20+
this.isObserving = true;
21+
});
22+
unobserve = sinon.stub().callsFake(() => {
23+
this.isObserving = false;
24+
});
2125
addEnterCallback = sinon.stub().callsFake((element, callback) => {
22-
this.onEnterCallback = sinon.spy(callback);
26+
this.onEnterCallback = sinon.spy(() => {
27+
if (this.isObserving) callback();
28+
});
2329
});
2430
addExitCallback = sinon.stub().callsFake((element, callback) => {
25-
this.onExitCallback = sinon.spy(callback);
31+
this.onExitCallback = sinon.spy(() => {
32+
if (this.isObserving) callback();
33+
});
2634
});
2735
}
2836

@@ -344,4 +352,46 @@ module('Integration | Modifier | did-intersect', function (hooks) {
344352

345353
assert.equal(this.newExitStub.callCount, 1, 'new exit callback is called');
346354
});
355+
356+
module('modifier accepts `isObserving` argument', function () {
357+
test('with a truth(y) value', async function (assert) {
358+
assert.expect(2);
359+
360+
await render(hbs`
361+
<div
362+
{{did-intersect
363+
isObserving=true
364+
onEnter=this.enterStub
365+
onExit=this.exitStub
366+
}}
367+
></div>
368+
`);
369+
370+
this.observerManagerMock.onEnterCallback();
371+
this.observerManagerMock.onExitCallback();
372+
373+
assert.ok(this.enterStub.calledOnce, 'the enter callback is invoked');
374+
assert.ok(this.exitStub.calledOnce, 'the onExit callback is invoked');
375+
});
376+
377+
test('with a false(y) value', async function (assert) {
378+
assert.expect(2);
379+
380+
await render(hbs`
381+
<div
382+
{{did-intersect
383+
isObserving=false
384+
onEnter=this.enterStub
385+
onExit=this.exitStub
386+
}}
387+
></div>
388+
`);
389+
390+
this.observerManagerMock.onEnterCallback();
391+
this.observerManagerMock.onExitCallback();
392+
393+
assert.ok(this.enterStub.notCalled, 'the enter callback is not invoked');
394+
assert.ok(this.exitStub.notCalled, 'the onExit callback is not invoked');
395+
});
396+
});
347397
});

0 commit comments

Comments
 (0)