Skip to content

Commit

Permalink
feat: add nested option (#11)
Browse files Browse the repository at this point in the history
* feat: add nested option

* refactor: use isReachStart, isReachEnd for nested movement
  • Loading branch information
malangfox committed May 23, 2022
1 parent ec71888 commit f4bd222
Show file tree
Hide file tree
Showing 7 changed files with 12,224 additions and 5,585 deletions.
17,609 changes: 12,060 additions & 5,549 deletions packages/conveyer/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/conveyer/package.json
Expand Up @@ -31,7 +31,7 @@
"drag"
],
"dependencies": {
"@egjs/axes": "^2.8.0",
"@egjs/axes": "^3.2.0",
"@egjs/component": "^3.0.1"
},
"devDependencies": {
Expand Down
17 changes: 12 additions & 5 deletions packages/conveyer/src/Conveyer.ts
Expand Up @@ -368,6 +368,7 @@ class Conveyer extends Component<ConveyerEvents> {
this._scrollAreaElement = el;
let isDrag = false;
const scrollAreaElement = this._scrollAreaElement;
const options = this._options;
const axes = new Axes({
scroll: {
circular: true,
Expand All @@ -376,6 +377,7 @@ class Conveyer extends Component<ConveyerEvents> {
}, {
deceleration: 0.005,
round: 1,
nested: options.nested,
});
let isHold = false;

Expand All @@ -388,7 +390,6 @@ class Conveyer extends Component<ConveyerEvents> {
if (!inputEvent) {
return;
}
const options = this._options;
if (options.preventDefault) {
inputEvent.preventDefault();
}
Expand All @@ -405,11 +406,14 @@ class Conveyer extends Component<ConveyerEvents> {
isDrag = true;
const scroll = e.delta.scroll;

if (this._options.horizontal) {
if (options.horizontal) {
scrollAreaElement.scrollLeft -= scroll;
} else {
scrollAreaElement.scrollTop -= scroll;
}
if (options.nested && e.inputEvent.srcEvent) {
this._checkNestedMove(e);
}
},
"release": e => {
if (!isDrag) {
Expand All @@ -424,9 +428,7 @@ class Conveyer extends Component<ConveyerEvents> {
if (this._options.useDrag) {
axes.connect(this._options.horizontal ? ["scroll", ""] : ["", "scroll"], new PanInput(scrollAreaElement, {
inputType: ["mouse"],
hammerManagerOptions: {
touchAction: "auto",
},
touchAction: "auto",
}));
}
scrollAreaElement.addEventListener("scroll", this._onScroll);
Expand Down Expand Up @@ -480,6 +482,11 @@ class Conveyer extends Component<ConveyerEvents> {
}
return scrollPos;
}
private _checkNestedMove(e: any) {
if (this.isReachStart || this.isReachEnd) {
e.inputEvent.srcEvent.__childrenAxesAlreadyChanged = false;
}
}
private _onScroll = (e?: any) => {
if (e) {
this._debounceScroll();
Expand Down
2 changes: 2 additions & 0 deletions packages/conveyer/src/types.ts
Expand Up @@ -14,6 +14,7 @@ import Conveyer from "./Conveyer";
* @property - Whether to prevent being selected. (default: true) <ko>셀렉트가 되는 것을 막을지 여부. (default: true) </ko>
* @property - Whether to prevent click event when dragging. (default: false) <ko>드래그하면 클릭이벤트를 막을지 여부. (default: true)</ko>
* @property - Whether to automatically initialize when an instance is created. If set to false, initialization is possible while calling the init method. (default: true) <ko>인스턴스를 생성할 때 자동으로 초기화할지 여부. false로 설정하면 init 메서드를 호출하면서 초기화가 가능하다. (default: true)</ko>
* @property - If this option is enabled on a Conveyer placed inside an egjs component that has the same scroll direction including the Conveyer itself. The parent component moves in the same direction after the Conveyer reaches the first/last scroll position. <ko>Conveyer 자신을 포함해서 동일한 스크롤 방향을 가진 egjs 컴포넌트 내부에 배치된 Conveyer에서 이 옵션을 활성화하면 Conveyer가 첫/마지막 스크롤 위치에 도달한 뒤부터 같은 방향으로 상위 컴포넌트가 움직인다.</ko>
*/
export interface ConveyerOptions {
horizontal?: boolean;
Expand All @@ -23,6 +24,7 @@ export interface ConveyerOptions {
preventDefault?: boolean;
preventClickOnDrag?: boolean;
autoInit?: boolean;
nested?: boolean;
}

/**
Expand Down
147 changes: 120 additions & 27 deletions packages/conveyer/test/unit/Conveyer.spec.ts
@@ -1,7 +1,13 @@
import { cleanup, dispatchDrag, sandbox, waitEvent, waitFor } from "./utils/utils";
import {
cleanup,
dispatchDrag,
sandbox,
waitEvent,
waitFor,
} from "./utils/utils";
import * as sinon from "sinon";
import Conveyer from "src";
import { CONVEYER_HTML } from "./utils/consts";
import { CONVEYER_HTML, NESTED_CONVEYER_HTML } from "./utils/consts";
import * as browserModules from "../../src/browser";
import { ImportMock } from "ts-mock-imports";

Expand All @@ -25,7 +31,9 @@ describe("test Conveyer", () => {
conveyer = new Conveyer(".items");

// Then
expect(document.querySelector<HTMLElement>(".items")!.style.touchAction).to.be.equal("auto");
expect(
document.querySelector<HTMLElement>(".items")!.style.touchAction
).to.be.equal("auto");
});
it("should check if touchAction is auto if horizontal is false", () => {
// Given, When
Expand All @@ -34,7 +42,9 @@ describe("test Conveyer", () => {
});

// Then
expect(document.querySelector<HTMLElement>(".items")!.style.touchAction).to.be.equal("auto");
expect(
document.querySelector<HTMLElement>(".items")!.style.touchAction
).to.be.equal("auto");
});
it("should check if css is not set if not init", () => {
// Given, When
Expand All @@ -43,22 +53,28 @@ describe("test Conveyer", () => {
});

// Then
expect(document.querySelector<HTMLElement>(".items")!.style.touchAction).to.be.not.equal("auto");
expect(
document.querySelector<HTMLElement>(".items")!.style.touchAction
).to.be.not.equal("auto");
});
it("should check if css is set if target is element", () => {
// Given, When
conveyer = new Conveyer(document.querySelector<HTMLElement>(".items")!);

// Then
expect(document.querySelector<HTMLElement>(".items")!.style.touchAction).to.be.equal("auto");
expect(
document.querySelector<HTMLElement>(".items")!.style.touchAction
).to.be.equal("auto");
});
it("should check if css is set if target is ref", () => {
// Given, When
const ref = { current: document.querySelector<HTMLElement>(".items") };
conveyer = new Conveyer(ref);

// Then
expect(document.querySelector<HTMLElement>(".items")!.style.touchAction).to.be.equal("auto");
expect(
document.querySelector<HTMLElement>(".items")!.style.touchAction
).to.be.equal("auto");
});
it(`should check whether the width is corrected when scrollWidth is rounded up for IE`, () => {
// Given
Expand Down Expand Up @@ -155,7 +171,9 @@ describe("test Conveyer", () => {
conveyer = new Conveyer(".items");

// When
conveyer.scrollTo(document.querySelector<HTMLElement>(".items")!.scrollWidth);
conveyer.scrollTo(
document.querySelector<HTMLElement>(".items")!.scrollWidth
);
await waitFor(100);

// Then
Expand All @@ -169,7 +187,9 @@ describe("test Conveyer", () => {
// When
const spy = sinon.spy();
conveyer.subscribe("isReachEnd", spy);
conveyer.scrollTo(document.querySelector<HTMLElement>(".items")!.scrollWidth);
conveyer.scrollTo(
document.querySelector<HTMLElement>(".items")!.scrollWidth
);
await waitFor(100);

// Then
Expand All @@ -182,7 +202,9 @@ describe("test Conveyer", () => {
// When
const spy = sinon.spy();
conveyer.subscribe("isReachStart", spy);
conveyer.scrollTo(document.querySelector<HTMLElement>(".items")!.scrollWidth);
conveyer.scrollTo(
document.querySelector<HTMLElement>(".items")!.scrollWidth
);
await waitFor(100);

// Then
Expand Down Expand Up @@ -218,7 +240,7 @@ describe("test Conveyer", () => {
items,
{ left: 0, top: 0 },
{ left: -100, top: 0 },
{ duration: 100, interval: 50 },
{ duration: 100, interval: 50 }
);

await waitEvent(conveyer, "finishScroll");
Expand All @@ -244,7 +266,7 @@ describe("test Conveyer", () => {
container,
{ left: 0, top: 0 },
{ left: -100, top: 0 },
{ duration: 100, interval: 50 },
{ duration: 100, interval: 50 }
);
await waitFor(100);

Expand All @@ -270,7 +292,7 @@ describe("test Conveyer", () => {
items,
{ left: 0, top: 0 },
{ left: 0, top: 0 },
{ duration: 0, interval: 50 },
{ duration: 0, interval: 50 }
);
await waitFor(60);

Expand All @@ -288,7 +310,9 @@ describe("test Conveyer", () => {
await waitFor(100);

// Then
expect(document.querySelector<HTMLElement>(".items")!.scrollLeft).to.be.equals(100);
expect(
document.querySelector<HTMLElement>(".items")!.scrollLeft
).to.be.equals(100);
expect(conveyer.scrollPos).to.be.equals(100);
});
it("should check if scrollLeft is changed when scrollBy is called", async () => {
Expand All @@ -300,7 +324,9 @@ describe("test Conveyer", () => {
await waitFor(100);

// Then
expect(document.querySelector<HTMLElement>(".items")!.scrollLeft).to.be.equals(100);
expect(
document.querySelector<HTMLElement>(".items")!.scrollLeft
).to.be.equals(100);
expect(conveyer.scrollPos).to.be.equals(100);
});
it("should check if start and end are inside when scrollLeft is 0", async () => {
Expand Down Expand Up @@ -388,13 +414,18 @@ describe("test Conveyer", () => {

// When
// 200
conveyer.scrollIntoView(document.querySelector<HTMLElement>(".item:nth-child(2)")!, {
align: "start",
});
conveyer.scrollIntoView(
document.querySelector<HTMLElement>(".item:nth-child(2)")!,
{
align: "start",
}
);
await waitFor(100);

// Then
expect(document.querySelector<HTMLElement>(".items")!.scrollLeft).to.be.equals(200);
expect(
document.querySelector<HTMLElement>(".items")!.scrollLeft
).to.be.equals(200);
expect(conveyer.scrollPos).to.be.equals(200);
});
it("should check it target moves center when align is center", async () => {
Expand All @@ -404,9 +435,12 @@ describe("test Conveyer", () => {
// When
// viewport 600
// 400
conveyer.scrollIntoView(document.querySelector<HTMLElement>(".item:nth-child(3)")!, {
align: "center",
});
conveyer.scrollIntoView(
document.querySelector<HTMLElement>(".item:nth-child(3)")!,
{
align: "center",
}
);
await waitFor(100);

// Then
Expand All @@ -422,9 +456,12 @@ describe("test Conveyer", () => {
// When
// viewport 600
// 1200
conveyer.scrollIntoView(document.querySelector<HTMLElement>(".item:nth-child(7)")!, {
align: "end",
});
conveyer.scrollIntoView(
document.querySelector<HTMLElement>(".item:nth-child(7)")!,
{
align: "end",
}
);
await waitFor(100);

// Then
Expand Down Expand Up @@ -532,7 +569,9 @@ describe("test Conveyer", () => {
const spy = sinon.spy();
conveyer.on("reachEnd", spy);
conveyer.init();
conveyer.scrollTo(document.querySelector<HTMLElement>(".items")!.scrollWidth);
conveyer.scrollTo(
document.querySelector<HTMLElement>(".items")!.scrollWidth
);
await waitFor(100);

// Then
Expand All @@ -541,7 +580,9 @@ describe("test Conveyer", () => {
it("should check if leaveEnd event triggered, isReachEnd is false", async () => {
// Given
conveyer = new Conveyer(".items");
conveyer.scrollTo(document.querySelector<HTMLElement>(".items")!.scrollWidth);
conveyer.scrollTo(
document.querySelector<HTMLElement>(".items")!.scrollWidth
);
await waitFor(100);

// When
Expand All @@ -555,4 +596,56 @@ describe("test Conveyer", () => {
expect(spy.callCount).to.be.equals(1);
});
});
describe("Options", () => {
describe("nested", () => {
let childConveyer!: Conveyer;

beforeEach(() => {
container.innerHTML = NESTED_CONVEYER_HTML;
conveyer = new Conveyer("#parent");
});

afterEach(() => {
childConveyer?.destroy();
});

it("should check if parent Conveyer is moving when child Conveyer reaches end and nested is true", async () => {
// Given
childConveyer = new Conveyer("#child", {
nested: true,
});
const nestedItem = document.querySelector<HTMLElement>("#child")!;

// When
await dispatchDrag(
nestedItem,
{ left: 0, top: 0 },
{ left: -4000, top: 0 },
{ duration: 200, interval: 50 }
);

// Then
expect(conveyer.scrollPos).to.be.equals(1000);
expect(childConveyer.scrollPos).to.be.equals(1000);
});

it("should check if parent Conveyer is not moving when nested is false by default", async () => {
// Given
childConveyer = new Conveyer("#child");
const nestedItem = document.querySelector<HTMLElement>("#child")!;

// When
await dispatchDrag(
nestedItem,
{ left: 0, top: 0 },
{ left: -4000, top: 0 },
{ duration: 200, interval: 50 }
);

// Then
expect(conveyer.scrollPos).to.be.equals(0);
expect(childConveyer.scrollPos).to.be.equals(1000);
});
});
});
});

0 comments on commit f4bd222

Please sign in to comment.