Skip to content

Commit

Permalink
fix: fix multiple columns (#24)
Browse files Browse the repository at this point in the history
* fix: fix multiple columns

* test: test multiple columns

* demo: fix multiple columns

* fix: fix workflow

* fix: fix token
  • Loading branch information
daybrush committed Jul 9, 2021
1 parent cee4a30 commit 5a5a808
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 57 deletions.
19 changes: 18 additions & 1 deletion .github/workflows/run-e2e.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
name: Run e2e tests
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 }}
e2e:
runs-on: ubuntu-latest
steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item" data-grid-column="3">8</div>
<div class="item">9</div>
<div class="item">10</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function App(props: Record<string, any>) {
<div className={"item"}>5</div>
<div className={"item"}>6</div>
<div className={"item"}>7</div>
<div className={"item"}>8</div>
<div className={"item"} data-grid-column="3">8</div>
<div className={"item"}>9</div>
<div className={"item"}>10</div>
</MasonryGrid>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item" data-grid-column="3">8</div>
<div class="item">9</div>
<div class="item">10</div>
</MasonryGrid>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item" data-grid-column="3">8</div>
<div class="item">9</div>
<div class="item">10</div>
</masonry-grid>
Expand Down
106 changes: 56 additions & 50 deletions src/grids/MasonryGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@ import { range, GetterSetter } from "../utils";
import { GridItem } from "../GridItem";


function getColumnPoint(
outline: number[],
columnIndex: number,
columnCount: number,
pointCaculationName: "max" | "min",
) {
return Math[pointCaculationName](...outline.slice(columnIndex, columnIndex + columnCount));
}

function getColumnIndex(outline: number[], columnCount: number, nearestCalculationName: "max" | "min") {
const length = outline.length - columnCount + 1;
const pointCaculationName = nearestCalculationName === "max" ? "min" : "max";
const indexCaculationName = nearestCalculationName === "max" ? "lastIndexOf" : "indexOf";
const points = range(length).map((index) => {
return getColumnPoint(outline, index, columnCount, pointCaculationName);
});

return points[indexCaculationName](Math[nearestCalculationName](...points));
}

/**
* @typedef
* @memberof Grid.MasonryGrid
Expand Down Expand Up @@ -70,14 +90,14 @@ export class MasonryGrid extends Grid<MasonryGridOptions> {
const itemsLength = items.length;
const alignPoses = this._getAlignPoses();
const isEndDirection = direction === "end";
const pointCalculateName = isEndDirection ? "min" : "max";
const indexCalculateName = isEndDirection ? "indexOf" : "lastIndexOf";
const nearestCalculationName = isEndDirection ? "min" : "max";
const pointCalculationName = isEndDirection ? "max" : "min";
let startOutline = [0];

if (outlineLength === column) {
startOutline = outline.slice();
} else {
const point = outlineLength ? Math[pointCalculateName](...outline) : 0;
const point = outlineLength ? Math[nearestCalculationName](...outline) : 0;

startOutline = range(column).map(() => point);
}
Expand All @@ -86,66 +106,52 @@ export class MasonryGrid extends Grid<MasonryGridOptions> {
const isStretch = align === "stretch";

for (let i = 0; i < itemsLength; ++i) {
const point = Math[pointCalculateName](...endOutline) || 0;
let columnIndex = endOutline[indexCalculateName](point);
const item = items[isEndDirection ? i : itemsLength - 1 - i];
const columnAttribute = parseInt(item.attributes.column || "1", 10);
const maxColumnAttribute = parseInt(item.attributes.maxColumn || "1", 10);
let inlineSize = item.inlineSize;
let contentSize = item.contentSize;
const maxColumn = Math.min(column, parseInt(item.attributes.maxColumn || "1", 10));
let itemColumn = Math.min(column, columnAttribute || Math.max(1, Math.ceil((inlineSize + gap) / columnDist)));
let columnCount = Math.min(column, columnAttribute || Math.max(1, Math.ceil((inlineSize + gap) / columnDist)));
const maxColumnCount = Math.min(column, Math.max(columnCount, maxColumnAttribute));
let columnIndex = getColumnIndex(endOutline, columnCount, nearestCalculationName);
let contentPos = getColumnPoint(endOutline, columnIndex, columnCount, pointCalculationName);

if (columnIndex === -1) {
columnIndex = 0;
}
if (column > 1 && itemColumn > 1) {
if (isEndDirection) {
// 0 columnIndex(+itemColumn) column
columnIndex = Math.min(columnIndex, Math.max(0, column - itemColumn));
} else {
// 0 columnIndex(-itemColumn) column
columnIndex = Math.max(columnIndex, Math.min(column - 1, itemColumn));
}
}
if (columnAttribute > 0) {
const endColumnIndex = columnIndex + (isEndDirection ? itemColumn : -itemColumn);
const columnOutline = outline.slice(
Math.min(columnIndex, endColumnIndex), Math.max(columnIndex, endColumnIndex));
const columnPoint = isEndDirection ? Math.max(...columnOutline) : Math.min(...columnOutline);

while (itemColumn < maxColumn) {
const nextEndColumnIndex = columnIndex + (isEndDirection ? itemColumn + 1 : -itemColumn - 1);

if (nextEndColumnIndex < 0 || nextEndColumnIndex > column) {
break;
}
if (
(isEndDirection && outline[nextEndColumnIndex - 1] > columnPoint)
|| (!isEndDirection && outline[nextEndColumnIndex] < columnPoint)
) {
break;
}
++itemColumn;
while (columnCount < maxColumnCount) {
const nextEndColumnIndex = columnIndex + columnCount;
const nextColumnIndex = columnIndex - 1;

if (isEndDirection && (nextEndColumnIndex >= column || endOutline[nextEndColumnIndex] > contentPos)) {
break;
}
if (itemColumn > 1 || isStretch || columnSizeOption) {
inlineSize = (itemColumn - 1) * columnDist + columnSize;
item.cssInlineSize = inlineSize;
if (!isEndDirection && (nextColumnIndex < 0 || endOutline[nextColumnIndex]) < contentPos) {
break;
}
if (columnSizeRatio > 0) {
contentSize = inlineSize / columnSizeRatio;
item.cssContentSize = contentSize;
if (!isEndDirection) {
--columnIndex;
}
++columnCount;
}

columnIndex = Math.max(0, columnIndex);
columnCount = Math.min(column - columnIndex, columnCount);

if (columnAttribute > 0 && (columnCount > 1 || isStretch || columnSizeOption)) {
inlineSize = (columnCount - 1) * columnDist + columnSize;
item.cssInlineSize = inlineSize;
}
if (columnSizeRatio > 0) {
contentSize = inlineSize / columnSizeRatio;
item.cssContentSize = contentSize;
}
const inlinePos = alignPoses[columnIndex];
const contentPos = isEndDirection ? point : point - gap - contentSize;
const endContentPos = contentPos + contentSize + gap;
contentPos = isEndDirection ? contentPos : contentPos - gap - contentSize;

item.cssInlinePos = inlinePos;
item.cssContentPos = contentPos;
const endPoint = isEndDirection ? endContentPos : contentPos;
const nextOutlinePoint = isEndDirection ? contentPos + contentSize + gap : contentPos;

range(itemColumn).forEach((indexOffset) => {
endOutline[columnIndex + (isEndDirection ? indexOffset : -indexOffset)] = endPoint;
range(columnCount).forEach((indexOffset) => {
endOutline[columnIndex + indexOffset] = nextOutlinePoint;
});
}

Expand Down Expand Up @@ -175,7 +181,7 @@ export class MasonryGrid extends Grid<MasonryGridOptions> {
} else {
for (const item of items) {
const attributes = item.attributes;
if (item.updateState !== UPDATE_STATE.UPDATED || !item.rect || attributes.column || attributes.maxColumn) {
if (item.updateState !== UPDATE_STATE.UPDATED || !item.rect || attributes.column || attributes.maxColumnCount) {
continue;
}
const inlineSize = item.inlineSize;
Expand Down
2 changes: 1 addition & 1 deletion stories/1-MasonryGrid/2-MasonryGridMultiple.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const MasonryGridMultipleTemplate = getApp(MasonryGrid, MasonryGridApp, (
<div className={"item"}>5</div>
<div className={"item"}>6</div>
<div className={"item"}>7</div>
<div className={"item"}>8</div>
<div className={"item"} data-grid-column="3">8</div>
<div className={"item"}>9</div>
<div className={"item"}>10</div>
</div>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item" data-grid-column="3">8</div>
<div class="item">9</div>
<div class="item">10</div>
</div>
35 changes: 35 additions & 0 deletions test/unit/MasonryGrid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,41 @@ describe("test MasonryGrid", () => {
]);
expect(container!.style.height).to.be.deep.equals("805px");
});
it(`should check whether multiple columns are used when data-grid-column="2"`, async () => {
// Given
container!.style.cssText = "width: 660px; height: 660px;";
container!.innerHTML = `
<div style="position: absolute;width: 500px; height: 300px;" data-grid-column="2"></div>
<div style="position: absolute;width: 200px; height: 200px;" ></div>
<div style="position: absolute;width: 500px; height: 500px;" data-grid-column="2"></div>
<div style="position: absolute;width: 250px; height: 250px;"></div>
`;
grid = new MasonryGrid(container!, {
gap: 10,
});

// When
grid.renderItems();

await waitEvent(grid, "renderComplete");

// Then
expect(grid.getOutlines()).to.be.deep.equals({
start: [0, 0, 0],
end: [820, 820, 470],
});
expect(grid.getItems().map((item) => item.cssRect)).to.be.deep.equals([
// column: 2
{ width: 430, left: 0, top: 0 },
// column: 1
{ left: 460, top: 0 },
// column: 2
{ width: 430, left: 0, top: 310 },
// column: 1
{ left: 460, top: 210 },
]);
expect(container!.style.height).to.be.deep.equals("810px");
});
it(`should check whether multiple columns are used when data-grid-max-column="3"`, async () => {
// Given
container!.style.cssText = "width: 660px; height: 660px;";
Expand Down

0 comments on commit 5a5a808

Please sign in to comment.