v1/web/modules/contrib/blazy/js/components/grid/blazy.nativegrid.masonry.js

161 lines
3.8 KiB
JavaScript

/**
* @file
* Provides CSS3 Native Grid treated as Masonry based on Grid Layout.
*
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout
* The two-dimensional Native Grid does not use JS until treated as a Masonry.
* If you need GridStack kind, avoid inputting numeric value for Grid.
* Below is the cheap version of GridStack.
*/
(function ($, Drupal, _doc) {
'use strict';
var _context = _doc;
var _id = 'block-nativegrid';
var _idOnce = 'b-masonry';
var _isMasonry = 'is-' + _idOnce;
var _isUnload = 'is-b-unload';
var _element = '.' + _id + '.' + _isMasonry;
var _unload = false;
Drupal.blazy = Drupal.blazy || {};
var _opts = {
$el: null,
gap: 15,
height: 15,
rows: 10
};
var _heights = [];
/**
* Applies the correct span to each grid item.
*
* @param {HTMLElement|Event} el
* The item HTML element, or event object on blazy.done.
* @param {int} i
* The element index.
* @param {bool} isResized
* If the resize event is triggered.
*/
function processItem(el, i, isResized) {
var target = el.target;
var box = 'target' in el ? $.closest(target, '.grid') : el;
if (!$.isElm(box)) {
return;
}
var cn = $.find(box, '.grid__content');
if ($.isElm(cn)) {
if (_opts.gap === 0) {
_opts.gap = 0.0001;
}
// Once setup, we rely on CSS to make it responsive.
var layout = function () {
_heights.push($.outerHeight(cn, true));
var rect = $.rect(cn);
var span = Math.ceil((rect.height + _opts.gap) / (_opts.height + _opts.gap));
// Sets the grid row span based on content and gap height.
box.style.gridRowEnd = 'span ' + span;
$.addClass(box, 'is-b-grid');
setTimeout(function () {
cn.style.minHeight = '';
$.addClass(box, 'is-b-layout');
}, _unload ? 600 : 200);
};
if (isResized || _unload) {
setTimeout(layout, _unload ? 300 : 200);
}
else {
layout();
}
}
}
/**
* Applies grid row end to each grid item.
*
* @param {HTMLElement} elm
* The container HTML element.
*/
function process(elm) {
var selector = '.grid:not(.is-b-grid)';
// The is-b-grid is flag to not re-do with VIS, views infinite scroll/ IO.
var items = $.findAll(elm, selector);
var init = function () {
var style = $.computeStyle(elm);
var gap = style.getPropertyValue('grid-row-gap');
var rows = style.getPropertyValue('grid-auto-rows');
if (gap) {
_opts.gap = parseInt(gap, 10);
}
if (rows) {
_opts.height = parseInt(rows, 10);
}
if (items.length) {
if (_unload) {
$.each(items, function (item, i) {
var cn = $.find(item, '.grid__content');
if (cn && _heights[i]) {
cn.style.minHeight = _heights[i] + 'px';
}
});
}
// Process on page load.
$.each(items, processItem);
// Process on resize.
if (!_unload) {
Drupal.blazy.checkResize(items, processItem, elm, processItem);
}
}
};
setTimeout(init, _unload ? 110 : 0);
_opts.$el = elm;
// $.addClass(elm, _isMounted);
if (_unload) {
$.addClass(elm, _isUnload);
}
_unload = false;
}
/**
* Attaches Blazy behavior to HTML element identified by .block-nativegrid.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.blazyNativeGrid = {
attach: function (context) {
_context = $.context(context);
$.once(process, _idOnce, _element, _context);
},
detach: function (context, setting, trigger) {
_unload = trigger === 'unload';
if (_unload) {
$.once.removeSafely(_idOnce, _element, _context);
}
}
};
}(dBlazy, Drupal, this.document));