Skip to content

Commit 479b87c

Browse files
And012Andranik Tsaturyan
andauthored
make in-viewport compatible to ember-modifier v4 (#306)
* make in-viewport compatible to ember-modifier v4 * resolve conversation * add missing scenarious * add missing scenarious * fix-lint * remove jquery scenario from ember-try and scenario * make scenario sync with CI * upgrade @embroider/test-setup * resolve conversation regarding packages * install dependencies with npm older version * revert package-lock.json and install dependencies * remove line to make ci work * add embroider macros to version 4 scneario dependancy * add @embroid/core @embroider/compat @embroider/webpack as dev dpcy * resolve could find module issue * revert change in service Co-authored-by: Andranik Tsaturyan <tsaturyana@ae.com>
1 parent 652156e commit 479b87c

File tree

5 files changed

+2057
-290
lines changed

5 files changed

+2057
-290
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,12 @@ jobs:
5858
- ember-beta
5959
- ember-canary
6060
- ember-classic
61-
- ember-default-with-jquery
6261
- embroider-safe
6362
- embroider-optimized
63+
- ember-modifier@2
64+
- ember-modifier@3.1
65+
- ember-modifier@3.2
66+
- ember-modifier@^4.0.0-beta.1
6467

6568
steps:
6669
- uses: actions/checkout@v2

addon/modifiers/in-viewport.js

Lines changed: 163 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,92 +4,184 @@ import { inject as service } from '@ember/service';
44
import { DEBUG } from '@glimmer/env';
55
import Modifier from 'ember-modifier';
66
import deepEqual from 'fast-deep-equal';
7+
import { registerDestructor } from '@ember/destroyable';
8+
import { macroCondition, dependencySatisfies } from '@embroider/macros';
79

810
const WATCHED_ELEMENTS = DEBUG ? new WeakSet() : undefined;
911

10-
export default class InViewportModifier extends Modifier {
11-
@service inViewport;
12+
let modifier;
1213

13-
name = 'in-viewport';
14+
if (macroCondition(dependencySatisfies('ember-modifier', '>=3.2.0 || 4.x'))) {
15+
modifier = class InViewportModifier extends Modifier {
16+
@service inViewport;
1417

15-
lastOptions;
18+
name = 'in-viewport';
1619

17-
get options() {
18-
// eslint-disable-next-line no-unused-vars
19-
const { onEnter, onExit, ...options } = this.args.named;
20-
return options;
21-
}
20+
lastOptions;
21+
element = null;
2222

23-
get hasStaleOptions() {
24-
return !deepEqual(this.options, this.lastOptions);
25-
}
23+
modify(element, positional, named) {
24+
this.element = element;
25+
this.positional = positional;
26+
this.named = named;
27+
this.validateArguments();
2628

27-
validateArguments() {
28-
assert(
29-
`'{{in-viewport}}' does not accept positional parameters. Specify listeners via 'onEnter' / 'onExit'.`,
30-
this.args.positional.length === 0
31-
);
32-
assert(
33-
`'{{in-viewport}}' either expects 'onEnter', 'onExit' or both to be present.`,
34-
typeof this.args.named.onEnter === 'function' ||
35-
typeof this.args.named.onExit === 'function'
36-
);
37-
}
29+
if (!this.didSetup) {
30+
this.setupWatcher(element);
31+
registerDestructor(() => this.destroyWatcher(element));
32+
} else if (this.hasStaleOptions) {
33+
this.destroyWatcher(element);
34+
this.setupWatcher(element);
35+
}
36+
}
37+
38+
get options() {
39+
// eslint-disable-next-line no-unused-vars
40+
const { onEnter, onExit, ...options } = this.named;
41+
return options;
42+
}
43+
44+
get hasStaleOptions() {
45+
return !deepEqual(this.options, this.lastOptions);
46+
}
47+
48+
validateArguments() {
49+
assert(
50+
`'{{in-viewport}}' does not accept positional parameters. Specify listeners via 'onEnter' / 'onExit'.`,
51+
this.positional.length === 0
52+
);
53+
assert(
54+
`'{{in-viewport}}' either expects 'onEnter', 'onExit' or both to be present.`,
55+
typeof this.named.onEnter === 'function' ||
56+
typeof this.named.onExit === 'function'
57+
);
58+
}
59+
60+
@action
61+
onEnter(...args) {
62+
if (this.named.onEnter) {
63+
this.named.onEnter.call(null, this.element, ...args);
64+
}
65+
66+
if (!this.options.viewportSpy) {
67+
this.inViewport.stopWatching(this.element);
68+
}
69+
}
3870

39-
@action
40-
onEnter(...args) {
41-
if (this.args.named.onEnter) {
42-
this.args.named.onEnter.call(null, this.element, ...args);
71+
@action
72+
onExit(...args) {
73+
if (this.named.onExit) {
74+
this.named.onExit.call(null, this.element, ...args);
75+
}
4376
}
4477

45-
if (!this.options.viewportSpy) {
78+
setupWatcher(element) {
79+
assert(
80+
`'${element}' is already being watched. Make sure that '{{in-viewport}}' is only used once on this element and that you are not calling 'inViewport.watchElement(element)' in other places.`,
81+
!WATCHED_ELEMENTS.has(element)
82+
);
83+
if (DEBUG) WATCHED_ELEMENTS.add(element);
84+
this.inViewport.watchElement(
85+
element,
86+
this.options,
87+
this.onEnter,
88+
this.onExit
89+
);
90+
this.lastOptions = this.options;
91+
}
92+
93+
destroyWatcher(element) {
94+
if (DEBUG) WATCHED_ELEMENTS.delete(element);
95+
this.inViewport.stopWatching(element);
96+
}
97+
};
98+
} else {
99+
modifier = class InViewportModifier extends Modifier {
100+
@service inViewport;
101+
102+
name = 'in-viewport';
103+
104+
lastOptions;
105+
106+
get options() {
107+
// eslint-disable-next-line no-unused-vars
108+
const { onEnter, onExit, ...options } = this.args.named;
109+
return options;
110+
}
111+
112+
get hasStaleOptions() {
113+
return !deepEqual(this.options, this.lastOptions);
114+
}
115+
116+
validateArguments() {
117+
assert(
118+
`'{{in-viewport}}' does not accept positional parameters. Specify listeners via 'onEnter' / 'onExit'.`,
119+
this.args.positional.length === 0
120+
);
121+
assert(
122+
`'{{in-viewport}}' either expects 'onEnter', 'onExit' or both to be present.`,
123+
typeof this.args.named.onEnter === 'function' ||
124+
typeof this.args.named.onExit === 'function'
125+
);
126+
}
127+
128+
@action
129+
onEnter(...args) {
130+
if (this.args.named.onEnter) {
131+
this.args.named.onEnter.call(null, this.element, ...args);
132+
}
133+
134+
if (!this.options.viewportSpy) {
135+
this.inViewport.stopWatching(this.element);
136+
}
137+
}
138+
139+
@action
140+
onExit(...args) {
141+
if (this.args.named.onExit) {
142+
this.args.named.onExit.call(null, this.element, ...args);
143+
}
144+
}
145+
146+
setupWatcher() {
147+
assert(
148+
`'${this.element}' is already being watched. Make sure that '{{in-viewport}}' is only used once on this element and that you are not calling 'inViewport.watchElement(element)' in other places.`,
149+
!WATCHED_ELEMENTS.has(this.element)
150+
);
151+
if (DEBUG) WATCHED_ELEMENTS.add(this.element);
152+
this.inViewport.watchElement(
153+
this.element,
154+
this.options,
155+
this.onEnter,
156+
this.onExit
157+
);
158+
this.lastOptions = this.options;
159+
}
160+
161+
destroyWatcher() {
162+
if (DEBUG) WATCHED_ELEMENTS.delete(this.element);
46163
this.inViewport.stopWatching(this.element);
47164
}
48-
}
49-
50-
@action
51-
onExit(...args) {
52-
if (this.args.named.onExit) {
53-
this.args.named.onExit.call(null, this.element, ...args);
54-
}
55-
}
56-
57-
setupWatcher() {
58-
assert(
59-
`'${this.element}' is already being watched. Make sure that '{{in-viewport}}' is only used once on this element and that you are not calling 'inViewport.watchElement(element)' in other places.`,
60-
!WATCHED_ELEMENTS.has(this.element)
61-
);
62-
if (DEBUG) WATCHED_ELEMENTS.add(this.element);
63-
this.inViewport.watchElement(
64-
this.element,
65-
this.options,
66-
this.onEnter,
67-
this.onExit
68-
);
69-
this.lastOptions = this.options;
70-
}
71-
72-
destroyWatcher() {
73-
if (DEBUG) WATCHED_ELEMENTS.delete(this.element);
74-
this.inViewport.stopWatching(this.element);
75-
}
76-
77-
didInstall() {
78-
this.setupWatcher();
79-
}
80-
81-
didUpdateArguments() {
82-
if (this.hasStaleOptions) {
83-
this.destroyWatcher();
165+
166+
didInstall() {
84167
this.setupWatcher();
85168
}
86-
}
87169

88-
didReceiveArguments() {
89-
this.validateArguments();
90-
}
170+
didUpdateArguments() {
171+
if (this.hasStaleOptions) {
172+
this.destroyWatcher();
173+
this.setupWatcher();
174+
}
175+
}
91176

92-
willRemove() {
93-
this.destroyWatcher();
94-
}
177+
didReceiveArguments() {
178+
this.validateArguments();
179+
}
180+
181+
willRemove() {
182+
this.destroyWatcher();
183+
}
184+
};
95185
}
186+
187+
export default modifier;

config/ember-try.js

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,34 @@ module.exports = async function () {
6363
},
6464
},
6565
{
66-
name: 'ember-default-with-jquery',
67-
env: {
68-
EMBER_OPTIONAL_FEATURES: JSON.stringify({
69-
'jquery-integration': true,
70-
}),
66+
name: 'ember-modifier@2',
67+
npm: {
68+
dependencies: {
69+
'ember-modifier': '^2.1.2',
70+
},
7171
},
72+
},
73+
{
74+
name: 'ember-modifier@3.1',
7275
npm: {
73-
devDependencies: {
74-
'@ember/jquery': '^1.1.0',
76+
dependencies: {
77+
'ember-modifier': '^3.1.0',
78+
},
79+
},
80+
},
81+
{
82+
name: 'ember-modifier@3.2',
83+
npm: {
84+
dependencies: {
85+
'ember-modifier': '^3.2.7',
86+
},
87+
},
88+
},
89+
{
90+
name: 'ember-modifier@^4.0.0-beta.1',
91+
npm: {
92+
dependencies: {
93+
'ember-modifier': '^4.0.0-beta.1',
7594
},
7695
},
7796
},

0 commit comments

Comments
 (0)