diff options
author | Andinus <andinus@nand.sh> | 2022-06-10 09:51:20 +0530 |
---|---|---|
committer | Andinus <andinus@nand.sh> | 2022-06-10 09:51:20 +0530 |
commit | c868ff796fd8ebf9f0c5f4d69a4abbb0f9682df8 (patch) | |
tree | 4f0bd106c3f9ef8e80db285a941a00418737ec7f /resources | |
parent | 1ac31ef10cc799f3cb7fc94d34178290a4e8dc00 (diff) | |
download | crater-c868ff796fd8ebf9f0c5f4d69a4abbb0f9682df8.tar.gz |
Add bricks.js for masonry layout, fix password input
multi-column didn't do what I wanted. bricks.js does the masonry layout, I think left-to-right would be even better but we'll go with this.
Diffstat (limited to 'resources')
-rw-r--r-- | resources/css/style.css | 17 | ||||
-rw-r--r-- | resources/js/bricks.js | 285 | ||||
-rw-r--r-- | resources/js/gallery.js | 40 |
3 files changed, 333 insertions, 9 deletions
diff --git a/resources/css/style.css b/resources/css/style.css index a49327e..87e6c9d 100644 --- a/resources/css/style.css +++ b/resources/css/style.css @@ -13,7 +13,7 @@ body { background-color: var(--bg-main); font-family: "Iosevka Aile", sans-serif; - margin: 2em auto; + margin: 4em auto; max-width: 90%; line-height: 1.5; } @@ -59,9 +59,8 @@ input, .alert { min-width: 30%; } -img, .text, .heading { - margin: 3.2em 1em; -} +img, .text { width: 384px; } +.heading { width: 364px; } .heading { box-shadow: var(--blue-intense-bg) 0px 0px 0px 2px inset, @@ -85,11 +84,11 @@ img, .text, .heading { padding: 1em; } -.gallery { - column-count: auto; - column-width: 384px; - column-fill: balance; -} +/* .gallery { */ +/* column-count: auto; */ +/* column-width: 384px; */ +/* column-fill: balance; */ +/* } */ .gallery img { transform-origin: center; transform: perspective(800px) rotateY(2deg); diff --git a/resources/js/bricks.js b/resources/js/bricks.js new file mode 100644 index 0000000..7758b05 --- /dev/null +++ b/resources/js/bricks.js @@ -0,0 +1,285 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.Bricks = factory()); +}(this, (function () { 'use strict'; + +var _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; +}; + +var knot = function knot() { + var extended = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var events = Object.create(null); + + function on(name, handler) { + events[name] = events[name] || []; + events[name].push(handler); + return this; + } + + function once(name, handler) { + handler._once = true; + on(name, handler); + return this; + } + + function off(name) { + var handler = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + handler ? events[name].splice(events[name].indexOf(handler), 1) : delete events[name]; + + return this; + } + + function emit(name) { + var _this = this; + + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + // cache the events, to avoid consequences of mutation + var cache = events[name] && events[name].slice(); + + // only fire handlers if they exist + cache && cache.forEach(function (handler) { + // remove handlers added with 'once' + handler._once && off(name, handler); + + // set 'this' context, pass args to handlers + handler.apply(_this, args); + }); + + return this; + } + + return _extends({}, extended, { + + on: on, + once: once, + off: off, + emit: emit + }); +}; + +var bricks = function bricks() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + // privates + + var persist = void 0; // packing new elements, or all elements? + var ticking = void 0; // for debounced resize + + var sizeIndex = void 0; + var sizeDetail = void 0; + + var columnTarget = void 0; + var columnHeights = void 0; + + var nodeTop = void 0; + var nodeLeft = void 0; + var nodeWidth = void 0; + var nodeHeight = void 0; + + var nodes = void 0; + var nodesWidths = void 0; + var nodesHeights = void 0; + + // resolve options + + var packed = options.packed.indexOf('data-') === 0 ? options.packed : 'data-' + options.packed; + var sizes = options.sizes.slice().reverse(); + var position = options.position !== false; + + var container = options.container.nodeType ? options.container : document.querySelector(options.container); + + var selectors = { + all: function all() { + return toArray(container.children); + }, + new: function _new() { + return toArray(container.children).filter(function (node) { + return !node.hasAttribute('' + packed); + }); + } + }; + + // series + + var setup = [setSizeIndex, setSizeDetail, setColumns]; + + var run = [setNodes, setNodesDimensions, setNodesStyles, setContainerStyles]; + + // instance + + var instance = knot({ + pack: pack, + update: update, + resize: resize + }); + + return instance; + + // general helpers + + function runSeries(functions) { + functions.forEach(function (func) { + return func(); + }); + } + + // array helpers + + function toArray(input) { + var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document; + + return Array.prototype.slice.call(input); + } + + function fillArray(length) { + return Array.apply(null, Array(length)).map(function () { + return 0; + }); + } + + // size helpers + + function getSizeIndex() { + // find index of widest matching media query + return sizes.map(function (size) { + return size.mq && window.matchMedia('(min-width: ' + size.mq + ')').matches; + }).indexOf(true); + } + + function setSizeIndex() { + sizeIndex = getSizeIndex(); + } + + function setSizeDetail() { + // if no media queries matched, use the base case + sizeDetail = sizeIndex === -1 ? sizes[sizes.length - 1] : sizes[sizeIndex]; + } + + // column helpers + + function setColumns() { + columnHeights = fillArray(sizeDetail.columns); + } + + // node helpers + + function setNodes() { + nodes = selectors[persist ? 'new' : 'all'](); + } + + function setNodesDimensions() { + // exit if empty container + if (nodes.length === 0) { + return; + } + + nodesWidths = nodes.map(function (element) { + return element.clientWidth; + }); + nodesHeights = nodes.map(function (element) { + return element.clientHeight; + }); + } + + function setNodesStyles() { + nodes.forEach(function (element, index) { + columnTarget = columnHeights.indexOf(Math.min.apply(Math, columnHeights)); + + element.style.position = 'absolute'; + + nodeTop = columnHeights[columnTarget] + 'px'; + nodeLeft = columnTarget * nodesWidths[index] + columnTarget * sizeDetail.gutter + 'px'; + + // support positioned elements (default) or transformed elements + if (position) { + element.style.top = nodeTop; + element.style.left = nodeLeft; + } else { + element.style.transform = 'translate3d(' + nodeLeft + ', ' + nodeTop + ', 0)'; + } + + element.setAttribute(packed, ''); + + // ignore nodes with no width and/or height + nodeWidth = nodesWidths[index]; + nodeHeight = nodesHeights[index]; + + if (nodeWidth && nodeHeight) { + columnHeights[columnTarget] += nodeHeight + sizeDetail.gutter; + } + }); + } + + // container helpers + + function setContainerStyles() { + container.style.position = 'relative'; + container.style.width = sizeDetail.columns * nodeWidth + (sizeDetail.columns - 1) * sizeDetail.gutter + 'px'; + container.style.height = Math.max.apply(Math, columnHeights) - sizeDetail.gutter + 'px'; + } + + // resize helpers + + function resizeFrame() { + if (!ticking) { + window.requestAnimationFrame(resizeHandler); + ticking = true; + } + } + + function resizeHandler() { + if (sizeIndex !== getSizeIndex()) { + pack(); + instance.emit('resize', sizeDetail); + } + + ticking = false; + } + + // API + + function pack() { + persist = false; + runSeries(setup.concat(run)); + + return instance.emit('pack'); + } + + function update() { + persist = true; + runSeries(run); + + return instance.emit('update'); + } + + function resize() { + var flag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + + var action = flag ? 'addEventListener' : 'removeEventListener'; + + window[action]('resize', resizeFrame); + + return instance; + } +}; + +return bricks; + +}))); diff --git a/resources/js/gallery.js b/resources/js/gallery.js new file mode 100644 index 0000000..73e5458 --- /dev/null +++ b/resources/js/gallery.js @@ -0,0 +1,40 @@ +'use strict'; +/* import Bricks from '/bricks.js'; */ + +// mq - the minimum viewport width (String CSS unit: em, px, rem) +// columns - the number of vertical columns +// gutter - the space (in px) between the columns and grid items + +// image width. +const imgW = 384; + +const sizes = [ + { columns: 1, gutter: 30 }, + { mq: ((imgW * 2.5) + 40) + "px", columns: 2, gutter: 40 }, + // { mq: '768px', columns: 2, gutter: 25 }, + // { mq: '1280px', columns: 3, gutter: 50 } +]; + +const instance = Bricks({ + container: '.gallery', + packed: 'data-packed', + sizes: sizes +}); + +instance + .on('pack', () => console.log('ALL grid items packed.')) + .on('update', () => console.log('NEW grid items packed.')) + .on('resize', size => console.log('The grid has be re-packed to accommodate a new BREAKPOINT.', size)); + +// start it up, when the DOM is ready. note that if images are in the +// grid, you may need to wait for document.readyState === 'complete'. + +document.addEventListener('DOMContentLoaded', eve => { + document.addEventListener('readystatechange', event => { + if (event.target.readyState === 'complete') { + instance + .resize(true) // bind resize handler + .pack() // pack initial items + } + }) +}) |