Skip to content

Commit

Permalink
make in-viewport compatible to ember-modifier v4 (#306)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
And012 and Andranik Tsaturyan authored Oct 31, 2022
1 parent 652156e commit 479b87c
Show file tree
Hide file tree
Showing 5 changed files with 2,057 additions and 290 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ jobs:
- ember-beta
- ember-canary
- ember-classic
- ember-default-with-jquery
- embroider-safe
- embroider-optimized
- ember-modifier@2
- [email protected]
- [email protected]
- ember-modifier@^4.0.0-beta.1

steps:
- uses: actions/checkout@v2
Expand Down
234 changes: 163 additions & 71 deletions addon/modifiers/in-viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,92 +4,184 @@ import { inject as service } from '@ember/service';
import { DEBUG } from '@glimmer/env';
import Modifier from 'ember-modifier';
import deepEqual from 'fast-deep-equal';
import { registerDestructor } from '@ember/destroyable';
import { macroCondition, dependencySatisfies } from '@embroider/macros';

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

export default class InViewportModifier extends Modifier {
@service inViewport;
let modifier;

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

lastOptions;
name = 'in-viewport';

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

get hasStaleOptions() {
return !deepEqual(this.options, this.lastOptions);
}
modify(element, positional, named) {
this.element = element;
this.positional = positional;
this.named = named;
this.validateArguments();

validateArguments() {
assert(
`'{{in-viewport}}' does not accept positional parameters. Specify listeners via 'onEnter' / 'onExit'.`,
this.args.positional.length === 0
);
assert(
`'{{in-viewport}}' either expects 'onEnter', 'onExit' or both to be present.`,
typeof this.args.named.onEnter === 'function' ||
typeof this.args.named.onExit === 'function'
);
}
if (!this.didSetup) {
this.setupWatcher(element);
registerDestructor(() => this.destroyWatcher(element));
} else if (this.hasStaleOptions) {
this.destroyWatcher(element);
this.setupWatcher(element);
}
}

get options() {
// eslint-disable-next-line no-unused-vars
const { onEnter, onExit, ...options } = this.named;
return options;
}

get hasStaleOptions() {
return !deepEqual(this.options, this.lastOptions);
}

validateArguments() {
assert(
`'{{in-viewport}}' does not accept positional parameters. Specify listeners via 'onEnter' / 'onExit'.`,
this.positional.length === 0
);
assert(
`'{{in-viewport}}' either expects 'onEnter', 'onExit' or both to be present.`,
typeof this.named.onEnter === 'function' ||
typeof this.named.onExit === 'function'
);
}

@action
onEnter(...args) {
if (this.named.onEnter) {
this.named.onEnter.call(null, this.element, ...args);
}

if (!this.options.viewportSpy) {
this.inViewport.stopWatching(this.element);
}
}

@action
onEnter(...args) {
if (this.args.named.onEnter) {
this.args.named.onEnter.call(null, this.element, ...args);
@action
onExit(...args) {
if (this.named.onExit) {
this.named.onExit.call(null, this.element, ...args);
}
}

if (!this.options.viewportSpy) {
setupWatcher(element) {
assert(
`'${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.`,
!WATCHED_ELEMENTS.has(element)
);
if (DEBUG) WATCHED_ELEMENTS.add(element);
this.inViewport.watchElement(
element,
this.options,
this.onEnter,
this.onExit
);
this.lastOptions = this.options;
}

destroyWatcher(element) {
if (DEBUG) WATCHED_ELEMENTS.delete(element);
this.inViewport.stopWatching(element);
}
};
} else {
modifier = class InViewportModifier extends Modifier {
@service inViewport;

name = 'in-viewport';

lastOptions;

get options() {
// eslint-disable-next-line no-unused-vars
const { onEnter, onExit, ...options } = this.args.named;
return options;
}

get hasStaleOptions() {
return !deepEqual(this.options, this.lastOptions);
}

validateArguments() {
assert(
`'{{in-viewport}}' does not accept positional parameters. Specify listeners via 'onEnter' / 'onExit'.`,
this.args.positional.length === 0
);
assert(
`'{{in-viewport}}' either expects 'onEnter', 'onExit' or both to be present.`,
typeof this.args.named.onEnter === 'function' ||
typeof this.args.named.onExit === 'function'
);
}

@action
onEnter(...args) {
if (this.args.named.onEnter) {
this.args.named.onEnter.call(null, this.element, ...args);
}

if (!this.options.viewportSpy) {
this.inViewport.stopWatching(this.element);
}
}

@action
onExit(...args) {
if (this.args.named.onExit) {
this.args.named.onExit.call(null, this.element, ...args);
}
}

setupWatcher() {
assert(
`'${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.`,
!WATCHED_ELEMENTS.has(this.element)
);
if (DEBUG) WATCHED_ELEMENTS.add(this.element);
this.inViewport.watchElement(
this.element,
this.options,
this.onEnter,
this.onExit
);
this.lastOptions = this.options;
}

destroyWatcher() {
if (DEBUG) WATCHED_ELEMENTS.delete(this.element);
this.inViewport.stopWatching(this.element);
}
}

@action
onExit(...args) {
if (this.args.named.onExit) {
this.args.named.onExit.call(null, this.element, ...args);
}
}

setupWatcher() {
assert(
`'${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.`,
!WATCHED_ELEMENTS.has(this.element)
);
if (DEBUG) WATCHED_ELEMENTS.add(this.element);
this.inViewport.watchElement(
this.element,
this.options,
this.onEnter,
this.onExit
);
this.lastOptions = this.options;
}

destroyWatcher() {
if (DEBUG) WATCHED_ELEMENTS.delete(this.element);
this.inViewport.stopWatching(this.element);
}

didInstall() {
this.setupWatcher();
}

didUpdateArguments() {
if (this.hasStaleOptions) {
this.destroyWatcher();

didInstall() {
this.setupWatcher();
}
}

didReceiveArguments() {
this.validateArguments();
}
didUpdateArguments() {
if (this.hasStaleOptions) {
this.destroyWatcher();
this.setupWatcher();
}
}

willRemove() {
this.destroyWatcher();
}
didReceiveArguments() {
this.validateArguments();
}

willRemove() {
this.destroyWatcher();
}
};
}

export default modifier;
33 changes: 26 additions & 7 deletions config/ember-try.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,34 @@ module.exports = async function () {
},
},
{
name: 'ember-default-with-jquery',
env: {
EMBER_OPTIONAL_FEATURES: JSON.stringify({
'jquery-integration': true,
}),
name: 'ember-modifier@2',
npm: {
dependencies: {
'ember-modifier': '^2.1.2',
},
},
},
{
name: '[email protected]',
npm: {
devDependencies: {
'@ember/jquery': '^1.1.0',
dependencies: {
'ember-modifier': '^3.1.0',
},
},
},
{
name: '[email protected]',
npm: {
dependencies: {
'ember-modifier': '^3.2.7',
},
},
},
{
name: 'ember-modifier@^4.0.0-beta.1',
npm: {
dependencies: {
'ember-modifier': '^4.0.0-beta.1',
},
},
},
Expand Down
Loading

0 comments on commit 479b87c

Please sign in to comment.