forked from a64f7bb4-7358-4778-9fbe-3b882c34cc1d/v1
258 lines
6.8 KiB
JavaScript
258 lines
6.8 KiB
JavaScript
/**
|
|
* @file
|
|
* Provides shared drupal-related methods normally driven by Drupal UI options.
|
|
*
|
|
* Old bLazy is now IO fallback to reduce competition and complexity
|
|
* and cross-compat better between Native and old approach (data-[SRC|SRCSET]).
|
|
* The reason old bLazy was not designed to cope with Native, Bio is.
|
|
* Native lazy was born (2019) after bLazy ceased 3 years before (2016).
|
|
*/
|
|
|
|
(function ($, Drupal, drupalSettings, _win, _doc) {
|
|
|
|
'use strict';
|
|
|
|
var _id = 'blazy';
|
|
var _ns = 'Drupal.' + _id;
|
|
var _data = 'data';
|
|
var _bbg = 'b-bg';
|
|
var _dataBg = _data + '-' + _bbg;
|
|
var _dataRatios = _data + '-ratios';
|
|
var _elBlur = '.b-blur';
|
|
var _media = 'media';
|
|
var _elMedia = '.' + _media;
|
|
var _successClass = 'successClass';
|
|
var _eventDone = _id + '.done';
|
|
var _noop = function () {};
|
|
var _extensions = {};
|
|
|
|
/**
|
|
* Blazy public properties and methods.
|
|
*
|
|
* @namespace
|
|
*/
|
|
Drupal.blazy = {
|
|
context: _doc,
|
|
name: _ns,
|
|
init: null,
|
|
instances: [],
|
|
resizeTick: 0,
|
|
resizeTrigger: false,
|
|
blazySettings: drupalSettings.blazy || {},
|
|
ioSettings: drupalSettings.blazyIo || {},
|
|
options: {},
|
|
clearCompat: _noop,
|
|
clearScript: _noop,
|
|
checkResize: _noop,
|
|
resizing: _noop,
|
|
revalidate: _noop,
|
|
|
|
// Enforced since IO (bio.js) makes bLazy a fallback internally since 2.6.
|
|
isIo: function () {
|
|
return true;
|
|
},
|
|
|
|
isBlazy: function () {
|
|
return !$.isIo && 'Blazy' in _win;
|
|
},
|
|
|
|
isFluid: function (el, cn) {
|
|
return $.equal(el.parentNode, 'picture') && $.hasAttr(cn, _dataRatios);
|
|
},
|
|
|
|
isLoaded: function (el) {
|
|
return $.hasClass(el, this.options[_successClass]);
|
|
},
|
|
|
|
globals: function () {
|
|
var me = this;
|
|
var commons = {
|
|
isMedia: true,
|
|
success: me.clearing.bind(me),
|
|
error: me.clearing.bind(me),
|
|
resizing: me.resizing.bind(me),
|
|
selector: '.b-lazy',
|
|
parent: _elMedia,
|
|
errorClass: 'b-error',
|
|
successClass: 'b-loaded'
|
|
};
|
|
|
|
return $.extend(me.blazySettings, me.ioSettings, commons);
|
|
},
|
|
|
|
extend: function (plugins) {
|
|
_extensions = $.extend({}, _extensions, plugins);
|
|
},
|
|
|
|
merge: function (opts) {
|
|
var me = this;
|
|
me.options = $.extend({}, me.globals(), me.options, opts || {});
|
|
return me.options;
|
|
},
|
|
|
|
run: function (opts) {
|
|
// @see https://www.drupal.org/project/blazy/issues/3258851
|
|
// var els = $.findAll(_doc, '.media--ratio--fluid, .' + _bbg);
|
|
// opts.disconnect = opts.disconnect || (!els.length && $.isUnd(Drupal.io));
|
|
return new BioMedia(opts);
|
|
},
|
|
|
|
mount: function (exe) {
|
|
var me = this;
|
|
|
|
// This may be set by lazyload script, but not when `No JavaScript` off.
|
|
me.merge();
|
|
|
|
// Executes all extensions.
|
|
if (exe) {
|
|
$.each(_extensions, function (fn) {
|
|
if ($.isFun(fn)) {
|
|
fn.call(me);
|
|
}
|
|
});
|
|
}
|
|
|
|
return $.extend(me, _extensions);
|
|
},
|
|
|
|
selector: function (suffix) {
|
|
suffix = suffix || '';
|
|
var opts = this.options;
|
|
return opts.selector + suffix + ':not(.' + opts[_successClass] + ')';
|
|
},
|
|
|
|
clearing: function (el) {
|
|
// While IO has a mechanism to unobserve, bLazy not.
|
|
if (el.bclearing) {
|
|
return;
|
|
}
|
|
|
|
var me = this;
|
|
var ie = $.hasClass(el, 'b-responsive') && $.hasAttr(el, _data + '-pfsrc');
|
|
|
|
// Clear loading classes. Also supports future delayed Native loading.
|
|
if ($.isFun($.unloading)) {
|
|
$.unloading(el);
|
|
}
|
|
|
|
// Provides event listeners for easy overrides without full overrides.
|
|
// Runs before native to allow native use this on its own onload event.
|
|
$.trigger(el, _eventDone, {
|
|
options: me.options
|
|
});
|
|
|
|
// With `No JavaScript` on, facilitate both parties: native vs. script.
|
|
// This is to use the same clearing approach for all parties.
|
|
me.clearCompat(el);
|
|
me.clearScript(el);
|
|
|
|
// @see http://scottjehl.github.io/picturefill/
|
|
if (_win.picturefill && ie) {
|
|
_win.picturefill({
|
|
reevaluate: true,
|
|
elements: [el]
|
|
});
|
|
}
|
|
|
|
el.bclearing = true;
|
|
},
|
|
|
|
windowData: function () {
|
|
return this.init ? this.init.windowData() : {};
|
|
},
|
|
|
|
// Only do this to fix errors, revalidation.
|
|
load: function (cn) {
|
|
var me = this;
|
|
|
|
// DOM ready fix.
|
|
_win.setTimeout(function () {
|
|
// Filterout the failing ones.
|
|
var elms = $.findAll(cn || _doc, me.selector());
|
|
|
|
if (elms.length) {
|
|
$.each(elms, me.update.bind(me));
|
|
}
|
|
}, 100);
|
|
},
|
|
|
|
update: function (el, delayed, winData) {
|
|
var me = this;
|
|
var opts = me.options;
|
|
var sel = opts.selector;
|
|
var _update = function () {
|
|
if ($.hasAttr(el, _dataBg) && $.isFun($.bg)) {
|
|
$.bg(el, winData || me.windowData());
|
|
}
|
|
else {
|
|
if (me.init) {
|
|
if (!$.hasClass(el, sel.substring(1))) {
|
|
el = $.find(el, sel) || el;
|
|
}
|
|
me.init.load(el, true, opts);
|
|
}
|
|
}
|
|
};
|
|
|
|
delayed = delayed || false;
|
|
if (delayed) {
|
|
// DOM ready fix.
|
|
_win.setTimeout(_update, 100);
|
|
}
|
|
else {
|
|
_update();
|
|
}
|
|
},
|
|
|
|
// Re-calculate image dimensions which may vary per breakpoint such as for
|
|
// Masonry during resizing. When images are loaded, Flexbox or Native Grid
|
|
// as Masonry might need info about the loaded image dimensions to calculate
|
|
// gaps or positions. Hooking into onload event ensures dimensions correct.
|
|
// @todo move it out to grid-related which requires this.
|
|
rebind: function (root, cb, observer) {
|
|
var me = this;
|
|
var elms = $.findAll(root, me.options.selector + ':not(' + _elBlur + ')');
|
|
var isMe = elms.length;
|
|
|
|
if (!isMe) {
|
|
elms = $.findAll(root, 'img:not(' + _elBlur + ')');
|
|
}
|
|
|
|
if (elms.length) {
|
|
$.each(elms, function (el) {
|
|
var type = isMe ? _eventDone : 'load';
|
|
$.one(el, type, cb, isMe);
|
|
|
|
if (observer) {
|
|
observer.observe(el);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
pad: function (el, cb, delay) {
|
|
var me = this;
|
|
var cn = $.closest(el, _elMedia) || el;
|
|
|
|
var check = function () {
|
|
var pad = Math.round(((el.naturalHeight / el.naturalWidth) * 100), 2);
|
|
|
|
// Only applies to aspect ratio fluid.
|
|
if (me.isFluid(el, cn)) {
|
|
cn.style.paddingBottom = pad + '%';
|
|
}
|
|
|
|
// Any functions which require dimensions setup: blur, bg, ratio, etc.
|
|
if ($.isFun(cb)) {
|
|
cb.call(me, el, cn, pad);
|
|
}
|
|
};
|
|
|
|
// Fixed for effect Blur messes up Aspect ratio Fluid calculation.
|
|
setTimeout(check, delay || 0);
|
|
}
|
|
|
|
};
|
|
|
|
}(dBlazy, Drupal, drupalSettings, this, this.document));
|