|
@@ -0,0 +1,52 @@
|
|
|
|
+import { clamp } from "./utils.js";
|
|
|
|
+
|
|
|
|
+export function setupMasonries(options = {}, selector = ".masonry") {
|
|
|
|
+ options = {
|
|
|
|
+ minColumnWidth: 300,
|
|
|
|
+ maxColumns: 6,
|
|
|
|
+ ...options
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const masonryContainers = document.querySelectorAll(selector);
|
|
|
|
+
|
|
|
|
+ for (let i = 0; i < masonryContainers.length; i++) {
|
|
|
|
+ const container = masonryContainers[i];
|
|
|
|
+ const items = Array.from(container.children);
|
|
|
|
+ let previousColumnsCount = 0;
|
|
|
|
+
|
|
|
|
+ const render = function() {
|
|
|
|
+ const columnsCount = clamp(
|
|
|
|
+ Math.floor(container.offsetWidth / options.minColumnWidth),
|
|
|
|
+ 1,
|
|
|
|
+ Math.min(options.maxColumns, items.length)
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ if (columnsCount === previousColumnsCount) {
|
|
|
|
+ return;
|
|
|
|
+ } else {
|
|
|
|
+ container.textContent = "";
|
|
|
|
+ previousColumnsCount = columnsCount;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const columnsFragment = document.createDocumentFragment();
|
|
|
|
+
|
|
|
|
+ for (let i = 0; i < columnsCount; i++) {
|
|
|
|
+ const column = document.createElement("div");
|
|
|
|
+ column.className = "masonry-column";
|
|
|
|
+ columnsFragment.append(column);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // poor man's masonry
|
|
|
|
+ // TODO: add an option that allows placing items in the
|
|
|
|
+ // shortest column instead of iterating the columns in order
|
|
|
|
+ for (let i = 0; i < items.length; i++) {
|
|
|
|
+ columnsFragment.children[i % columnsCount].appendChild(items[i]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ container.append(columnsFragment);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const observer = new ResizeObserver(() => requestAnimationFrame(render));
|
|
|
|
+ observer.observe(container);
|
|
|
|
+ }
|
|
|
|
+}
|