forked from a64f7bb4-7358-4778-9fbe-3b882c34cc1d/v1
174 lines
4.1 KiB
JavaScript
174 lines
4.1 KiB
JavaScript
/**
|
|
* @file
|
|
* Provides CSS3 flex based on Flexbox layout.
|
|
*
|
|
* Credit: https://fjolt.com/article/css-grthis loader id-masonry
|
|
*
|
|
* @todo deprecated this is worse than NativeGrid Masonry. We can't compete
|
|
* against the fully tested Outlayer or GridStack library.
|
|
*/
|
|
|
|
(function ($, Drupal, _doc) {
|
|
|
|
'use strict';
|
|
|
|
var _context = _doc;
|
|
var _id = 'block-flex';
|
|
var _idOnce = 'b-flex';
|
|
var _isLoading = 'is-b-loading';
|
|
var _element = '.' + _id;
|
|
var _max = 0;
|
|
var _unload = false;
|
|
var _opts = {
|
|
$el: null
|
|
};
|
|
|
|
/**
|
|
* Applies height adjustments to each item.
|
|
*
|
|
* @param {HTMLElement} elm
|
|
* The container HTML element.
|
|
*/
|
|
function process(elm) {
|
|
var _box = '.grid';
|
|
var heights = {};
|
|
var box = $.find(elm, _box);
|
|
|
|
if (!$.isElm(box)) {
|
|
return;
|
|
}
|
|
|
|
var items = $.findAll(elm, _box);
|
|
|
|
function init() {
|
|
var parentWith = $.rect(elm).width;
|
|
var boxWith = $.rect(box).width;
|
|
var style = $.computeStyle(box);
|
|
var itemWith = boxWith + parseFloat(style.marginLeft) + parseFloat(style.marginRight);
|
|
var columnWidth = Math.round((1 / (itemWith / parentWith)));
|
|
|
|
var processItem = function (item, id) {
|
|
var target = item.target;
|
|
var isResized = $.isUnd(id);
|
|
|
|
item = target ? $.closest(target, _box) : item;
|
|
id = isResized ? items.indexOf(item) : id;
|
|
|
|
var layout = function () {
|
|
var cn = $.find(item, _box + '__content');
|
|
if (!$.isElm(cn)) {
|
|
return;
|
|
}
|
|
|
|
var cr = $.rect(cn);
|
|
var ch = cr.height;
|
|
|
|
if (ch < 60) {
|
|
cr = $.rect(item);
|
|
ch = cr.height;
|
|
}
|
|
|
|
if (ch < 60) {
|
|
return;
|
|
}
|
|
|
|
var curColumn = id % columnWidth;
|
|
var style = $.computeStyle(item);
|
|
|
|
if ($.isUnd(heights[curColumn])) {
|
|
heights[curColumn] = 0;
|
|
}
|
|
|
|
item.style.height = ch + 'px';
|
|
heights[curColumn] += ch + parseFloat(style.marginBottom);
|
|
|
|
// If the item has an item above it, then move it to fill the gap.
|
|
if (id - columnWidth >= 0) {
|
|
var nh = id - columnWidth + 1;
|
|
var itemAbove = $.find(elm, _box + ':nth-of-type(' + nh + ')');
|
|
if ($.isElm(itemAbove)) {
|
|
var prevBottom = $.rect(itemAbove).bottom;
|
|
var currentTop = cr.top - parseFloat(style.marginBottom);
|
|
|
|
item.style.top = '-' + (currentTop - prevBottom) + 'px';
|
|
}
|
|
}
|
|
};
|
|
|
|
if (isResized || _unload) {
|
|
if (_unload) {
|
|
item.style.height = '';
|
|
item.style.top = '';
|
|
}
|
|
|
|
setTimeout(layout, _unload ? 100 : 600);
|
|
}
|
|
else {
|
|
layout();
|
|
}
|
|
};
|
|
|
|
// Process on page load.
|
|
$.each(items, processItem);
|
|
|
|
function checkHeight() {
|
|
var max = Math.max.apply(null, Object.values(heights));
|
|
if (max < 0) {
|
|
max = _max;
|
|
}
|
|
|
|
if (_unload) {
|
|
// Prepare space to avoid jumping jack flash.
|
|
elm.style.height = _max + 360 + 'px';
|
|
}
|
|
else {
|
|
elm.style.height = max + 'px';
|
|
}
|
|
|
|
_max = max;
|
|
}
|
|
|
|
checkHeight();
|
|
|
|
// @todo this breaks initial bricks.
|
|
// var checkResize = function () {
|
|
// Process on resize.
|
|
// me.checkResize(items, processItem, elm);
|
|
// };
|
|
}
|
|
|
|
setTimeout(init, _unload ? 1200 : 200);
|
|
|
|
if (!_unload) {
|
|
$.addClass(elm, _isLoading);
|
|
setTimeout(function () {
|
|
$.removeClass(elm, _isLoading);
|
|
}, 600);
|
|
}
|
|
|
|
_opts.$el = elm;
|
|
_unload = false;
|
|
}
|
|
|
|
/**
|
|
* Attaches Blazy behavior to HTML element identified by .block-flex.
|
|
*
|
|
* @type {Drupal~behavior}
|
|
*/
|
|
Drupal.behaviors.blazyFlex = {
|
|
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));
|