Skip to content

Commit

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

* fix: fix size functions

* test: test useOffset option

* skip: apply review

* test: add github workflow
  • Loading branch information
daybrush authored Jul 21, 2021
1 parent 081e934 commit 78d36c9
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 56 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/run-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Run tests
on: [push, pull_request]
jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2.1.5
with:
node-version: 14.15.4
- name: install
run: npm install
- name: lint
run: npm run lint
- name: test
run: npm run coverage
- name: Coveralls GitHub Action
uses: coverallsapp/github-action@v1.1.2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
18 changes: 10 additions & 8 deletions src/DOMRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import {
import { window, document } from "./browser";
import {
$,
innerHeight,
innerWidth,
getSize,
getStyle,
addOnceEvent,
assign,
getOffsetSize,
getClientWidth,
getClientHeight,
getRectSize,
} from "./utils";
import {
RectType, IPosition, IJQuery,
Expand Down Expand Up @@ -105,6 +106,7 @@ export default class DOMRenderer {
public container: HTMLElement;
public view: Window | HTMLElement;
public options: IDOMRendererOptions = {
useOffset: false,
isEqualSize: false,
isConstantSize: false,
horizontal: false,
Expand Down Expand Up @@ -136,19 +138,19 @@ export default class DOMRenderer {
assign(this._size, status._size);
}
public updateSize(items: IInfiniteGridItem[]) {
const { isEqualSize, isConstantSize } = this.options;
const { isEqualSize, isConstantSize, useOffset } = this.options;
const size = this._size;

return items.map(item => {
if (!item.el) {
return item;
}
if (isEqualSize && !size.item) {
size.item = getSize(item.el);
size.item = useOffset ? getOffsetSize(item.el) : getRectSize(item.el);
}
item.size = (isEqualSize && assign({}, size.item)) ||
(isConstantSize && item.orgSize && item.orgSize.width && assign({}, item.orgSize)) ||
getSize(item.el);
(useOffset ? getOffsetSize(item.el) : getRectSize(item.el));
if (!item.orgSize || !item.orgSize.width || !item.orgSize.height) {
item.orgSize = assign({}, item.size);
}
Expand Down Expand Up @@ -226,7 +228,7 @@ export default class DOMRenderer {
item: null,
};
}
this._size.view = horizontal ? innerWidth(view) : innerHeight(view);
this._size.view = horizontal ? getClientWidth(view) : getClientHeight(view);
return isResize;
}
public isNeededResize() {
Expand Down Expand Up @@ -297,7 +299,7 @@ export default class DOMRenderer {
}
private _calcSize() {
return this.options.horizontal ?
innerHeight(this.container) : innerWidth(this.container);
getClientHeight(this.container) : getClientWidth(this.container);
}
private _render(properties: RectType[], rect: IInfiniteGridItem["rect"], style: HTMLElement["style"]) {
const isSizePercentage = this._isSizePercentage;
Expand Down
16 changes: 14 additions & 2 deletions src/InfiniteGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
DEFAULT_OPTIONS,
} from "./consts";
import Infinite from "./Infinite";
import { toArray, $, outerHeight, outerWidth, assign, resetSize, hasClass, addClass } from "./utils";
import { toArray, $, assign, resetSize, hasClass, addClass, getOffsetWidth, getOffsetHeight, getRectWidth, getRectHeight } from "./utils";
import {
IJQuery, ILayout,
CursorType, StyleType,
Expand Down Expand Up @@ -122,6 +122,8 @@ class InfiniteGrid extends Component<InfiniteGridEvents> {
* @param {boolean} [options.isOverflowScroll=false] Indicates whether overflow:scroll is applied<ko>overflow:scroll 적용여부를 결정한다.</ko>
* @param {boolean} [options.horizontal=false] Direction of the scroll movement (true: horizontal, false: vertical) <ko>스크롤 이동 방향 (true 가로방향, false 세로방향)</ko>
* @param {boolean} [options.useFit=true] The useFit option scrolls upwards so that no space is visible until an item is added <ko>위로 스크롤할 시 아이템을 추가하는 동안 보이는 빈 공간을 안보이게 한다.</ko>
* @param {boolean} [options.useOffset=false] Whether to get the size as offsetWidth, offsetHeight. Set to true if transform is applied to the container. If false, get the size through getBoundingClientRect. <ko>사이즈를 offsetWidth, offsetHeight로 가져올지 여부.
container에 transform이 적용되어 있다면 true로 설정해라. false면 getBoundingClientRect를 통해 사이즈를 가져온다.</ko>
* @param {boolean} [options.isEqualSize=false] Indicates whether sizes of all card elements are equal to one another. If sizes of card elements to be arranged are all equal and this option is set to "true", the performance of layout arrangement can be improved. <ko>카드 엘리먼트의 크기가 동일한지 여부. 배치될 카드 엘리먼트의 크기가 모두 동일할 때 이 옵션을 'true'로 설정하면 레이아웃 배치 성능을 높일 수 있다</ko>
* @param {boolean} [options.isConstantSize=false] Indicates whether sizes of all card elements does not change, the performance of layout arrangement can be improved. <ko>모든 카드 엘리먼트의 크기가 불변일 때 이 옵션을 'true'로 설정하면 레이아웃 배치 성능을 높일 수 있다</ko>
* @param {number} [options.transitionDruation=0] Indicates how many seconds a transition effect takes to complete. <ko>트랜지션 효과를 완료하는데 걸리는 시간을 나타낸다.</ko>
Expand Down Expand Up @@ -152,6 +154,7 @@ class InfiniteGrid extends Component<InfiniteGridEvents> {
resizeDebounce,
maxResizeDebounce,
percentage,
useOffset,
} = this.options;

this._itemManager = new ItemManager();
Expand All @@ -161,6 +164,7 @@ class InfiniteGrid extends Component<InfiniteGridEvents> {
horizontal,
container: isOverflowScroll,
percentage,
useOffset,
});
this._watcher = new Watcher(
this._renderer.view,
Expand Down Expand Up @@ -1096,7 +1100,15 @@ class InfiniteGrid extends Component<InfiniteGridEvents> {
for (const property in style) {
el.style[property] = style[property as keyof StyleType];
}
this._status.loadingSize = this.options.horizontal ? outerWidth(el) : outerHeight(el);
const {
useOffset,
horizontal,
} = this.options;
if (horizontal) {
this._status.loadingSize = useOffset ? getOffsetWidth(el) : getRectWidth(el);
} else {
this._status.loadingSize = useOffset ? getOffsetHeight(el) : getRectHeight(el);
}
const posName = this.options.horizontal ? "left" : "top";

if (!(posName in style)) {
Expand Down
1 change: 1 addition & 0 deletions src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const DEFAULT_OPTIONS = {
resizeDebounce: 100,
maxResizeDebounce: 0,
percentage: false,
useOffset: false,
};

export const DEFAULT_LAYOUT_OPTIONS = {
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface IInfiniteGridOptions {
resizeDebounce: number;
maxResizeDebounce: number;
percentage: boolean | Array<"size" | "position">;
useOffset: boolean;
}

export interface IInfiniteGridGroup {
Expand Down Expand Up @@ -255,6 +256,7 @@ export interface LoadingImageElement extends HTMLImageElement {
}

export interface IDOMRendererOptions {
useOffset: boolean;
isEqualSize: boolean;
isConstantSize: boolean;
horizontal: boolean;
Expand Down
41 changes: 28 additions & 13 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ export function getStyle(el: Element) {
return (SUPPORT_COMPUTEDSTYLE ?
window.getComputedStyle(el) : (el as any).currentStyle) || {};
}
function _getSize(el: Window | Document | HTMLElement, name: "Width" | "Height", isOffset?: boolean) {

function getSize(el: Window | Document | HTMLElement, name: "Width" | "Height", type: "client" | "offset" | "rect") {
if (isWindow(el)) { // WINDOW
return window[`inner${name}` as InnerSizeType] || document.body[`client${name}` as ClientSizeType];
} else if (isDocument(el)) { // DOCUMENT_NODE
Expand All @@ -182,10 +183,12 @@ function _getSize(el: Window | Document | HTMLElement, name: "Width" | "Height",
} else { // NODE
let size = 0;

if (isOffset) {
if (type === "rect") {
const clientRect = el.getBoundingClientRect();

size = name === "Width" ? clientRect.right - clientRect.left : clientRect.bottom - clientRect.top;
} else if (type === "offset") {
size = el[`offset${name}` as OffsetSizeType] || el[`client${name}` as ClientSizeType];
} else {
size = el[`client${name}` as ClientSizeType] || el[`offset${name}` as OffsetSizeType];
}
Expand All @@ -198,22 +201,34 @@ function _getSize(el: Window | Document | HTMLElement, name: "Width" | "Height",
}
}

export function innerWidth(el: Window | Document | HTMLElement) {
return _getSize(el, "Width", false);
export function getClientWidth(el: Window | Document | HTMLElement) {
return getSize(el, "Width", "client");
}
export function getClientHeight(el: Window | Document | HTMLElement) {
return getSize(el, "Height", "client");
}
export function getOffsetWidth(el: Window | Document | HTMLElement) {
return getSize(el, "Width", "offset");
}
export function innerHeight(el: Window | Document | HTMLElement) {
return _getSize(el, "Height", false);
export function getOffsetHeight(el: Window | Document | HTMLElement) {
return getSize(el, "Height", "offset");
}
export function outerWidth(el: Window | Document | HTMLElement) {
return _getSize(el, "Width", true);
export function getRectWidth(el: Window | Document | HTMLElement) {
return getSize(el, "Width", "rect");
}
export function outerHeight(el: Window | Document | HTMLElement) {
return _getSize(el, "Height", true);
export function getRectHeight(el: Window | Document | HTMLElement) {
return getSize(el, "Height", "rect");
}
export function getOffsetSize(el: HTMLElement) {
return {
width: getOffsetWidth(el),
height: getOffsetHeight(el),
};
}
export function getSize(el: HTMLElement) {
export function getRectSize(el: HTMLElement) {
return {
width: outerWidth(el),
height: outerHeight(el),
width: getRectWidth(el),
height: getRectHeight(el),
};
}
export const STYLE: {
Expand Down
69 changes: 63 additions & 6 deletions test/unit/InfiniteGrid.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import PackingLayout from "../../src/layouts/PackingLayout";
import JustifiedLayout from "../../src/layouts/JustifiedLayout";
import { getItems, insert, wait, waitInsert, waitEvent } from "./helper/TestHelper";
import { LOADING_APPEND, LOADING_PREPEND, DEFENSE_BROWSER, IDLE } from "../../src/consts";
import { scroll, innerHeight, innerWidth } from "../../src/utils";
import { scroll, getClientHeight, getClientWidth } from "../../src/utils";
import { expectConnectGroupsOutline } from "./helper/common";

/* eslint-disable */
Expand Down Expand Up @@ -545,7 +545,7 @@ describe("InfiniteGrid Test", function () {
this.inst.append(`<div class="item" style="width: 100%; height: 50px;">Item</div>`);
const e = await event;
const isScroll = e.isScroll;
const size = isOverflowScroll ? 250 : innerHeight(window);
const size = isOverflowScroll ? 250 : getClientHeight(window);

// Then
if (e.size <= size) {
Expand Down Expand Up @@ -978,7 +978,7 @@ describe("InfiniteGrid Test", function () {

const layoutCompleteHandler = sinon.spy(e => {
if (!isOverflowScroll) {
expect(innerHeight(this.inst._renderer.container)).to.be.equal(this.inst._getEdgeValue("end") - this.inst._getEdgeValue("start") + (isAppend ? 75 : 100));
expect(getClientHeight(this.inst._renderer.container)).to.be.equal(this.inst._getEdgeValue("end") - this.inst._getEdgeValue("start") + (isAppend ? 75 : 100));
}
expect(this.inst.isLoading()).to.be.true;
if (isAppend) {
Expand All @@ -988,7 +988,7 @@ describe("InfiniteGrid Test", function () {
this.inst.on("layoutComplete", layoutCompleteHandler);

if (!isOverflowScroll) {
expect(innerHeight(this.inst._renderer.container)).to.be.equal(isAppend ? 75 : 100);
expect(getClientHeight(this.inst._renderer.container)).to.be.equal(isAppend ? 75 : 100);
}
const handler = await waitInsert(this.inst, isAppend, ITEMCOUNT, 2);
// End Loading
Expand Down Expand Up @@ -1055,6 +1055,63 @@ describe("InfiniteGrid Test", function () {
});
});
});
describe("test useOffset option", function () {
beforeEach(() => {
this.el = sandbox();
this.el.innerHTML = "<div id='infinite'></div>";
});
afterEach(() => {
if (this.inst) {
this.inst.destroy();
this.inst = null;
}
cleanup();
});
[false, true].forEach(useOffset => {
it(`should check if rendering is normal when scale is 1 (useOffset: ${useOffset}) `, async () => {
// Given
this.inst = new InfiniteGrid("#infinite", {
useRecycle: true,
isOverflowScroll: false,
useOffset,
});
this.inst.setLayout(GridLayout);
await waitInsert(this.inst, true, 5, 4);

expect(document.querySelector("#infinite").style.height).to.be.equals("1000px");
});
});
it(`should check if rendering is abnormal when scale is 0.5 (useOffset: false) `, async () => {
// Given
const container = document.querySelector("#infinite");

container.style.transform = "scale(0.5)";
this.inst = new InfiniteGrid(container, {
useRecycle: true,
isOverflowScroll: false,
useOffset: false,
});
this.inst.setLayout(GridLayout);
await waitInsert(this.inst, true, 5, 4);

expect(document.querySelector("#infinite").style.height).to.be.equals("300px");
});
it(`should check if rendering is normal when scale is 0.5 (useOffset: true) `, async () => {
// Given
const container = document.querySelector("#infinite");

container.style.transform = "scale(0.5)";
this.inst = new InfiniteGrid(container, {
useRecycle: true,
isOverflowScroll: false,
useOffset: true,
});
this.inst.setLayout(GridLayout);
await waitInsert(this.inst, true, 5, 4);

expect(document.querySelector("#infinite").style.height).to.be.equals("1000px");
});
});
describe("append/prepend Test on layoutComplete", function () {
[true, false].forEach(isOverflowScroll => {
beforeEach(() => {
Expand Down Expand Up @@ -1175,7 +1232,7 @@ describe("InfiniteGrid Test", function () {
const size = datas.map(data => data.items.map(item => Object.assign(item.size)));
const waitLayout = waitEvent(this.inst, "layoutComplete");
const container = this.el.querySelector("#infinite");
const width = innerWidth(container);
const width = getClientWidth(container);
container.style.width = `${width * 2}px`;
datas[0].outlines.start = [0];
this.inst._renderer._size.viewport = width * 2;
Expand Down Expand Up @@ -1336,7 +1393,7 @@ describe("InfiniteGrid Test", function () {
// When
const waitLayoutComplete = waitEvent(this.inst, "layoutComplete");
const container = this.el.querySelector("#infinite");
const width = innerWidth(container);
const width = getClientWidth(container);
container.style.width = `${width * 3}px`;
datas[0].outlines.start = [];
this.inst._renderer._size.viewport = width * 3;
Expand Down
Loading

0 comments on commit 78d36c9

Please sign in to comment.