v1/web/modules/contrib/blazy/js/plugin/blazy.animate.js

234 lines
5.3 KiB
JavaScript

/**
* @file
* Provides animate extension for dBlazy when using blur or animate.css.
*
* Alternative for native Element.animate, only with CSS animation instead.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/animate
*/
(function ($, _win) {
'use strict';
var _1px = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
var _ani = 'animation';
var _blur = 'blur';
var _bblur = 'b-' + _blur;
var _blurKey = 'b' + _blur;
var _blurStorage = [];
var _data = 'data-';
var _isStorage = _win.localStorage;
/**
* A simple wrapper to animate anything using animate.css.
*
* @param {dBlazy|Array.<Element>|Element} els
* The HTML element(s), or dBlazy instance.
* @param {string|Function} cb
* Any custom animation name, fallbacks to [data-animation], or a callback.
*
* @return {Object}
* This dBlazy object.
*/
function animate(els, cb) {
var me = this;
var chainCallback = function (el) {
var _set = el.dataset;
if (!$.isElm(el) || !_set) {
return me;
}
var $el = $(el);
var animation = _set.animation;
if ($.isStr(cb)) {
animation = cb;
}
if (!animation) {
return me;
}
var _animated = 'animated';
var _aniEnd = _ani + 'end.' + animation;
var _style = el.style;
var classes = _animated + ' ' + animation;
var props = [
_ani,
_ani + '-duration',
_ani + '-delay',
_ani + '-iteration-count'
];
$el.addClass(classes);
$.each(['Duration', 'Delay', 'IterationCount'], function (key) {
var _aniKey = _ani + key;
if (_set && _aniKey in _set) {
_style[_aniKey] = _set[_aniKey];
}
});
// Supports both BG and regular image.
var cn = $.closest(el, '.media') || el;
var bg = $el.hasClass('b-bg');
var isBlur = animation === _blur;
var an = el;
// The animated blur is image not this container, except a background.
if (isBlur && !bg) {
an = $.find(cn, 'img:not(.' + _bblur + ')') || an;
}
function ended(e) {
$el.addClass('is-b-' + _animated)
.removeClass(classes)
.removeAttr(props, _data);
$.each(props, function (key) {
_style.removeProperty(key);
});
if ($.isFun(cb)) {
cb(e);
}
if (isBlur) {
var elBlur = $.find(cn, 'img.' + _bblur);
if ($.isElm(elBlur)) {
elBlur.src = _1px;
$.removeAttr(elBlur, _data + _bblur);
}
}
}
return $.one(an, _aniEnd, ended, false);
};
return $.chain(els, chainCallback);
}
$.animate = animate.bind($);
$.fn.animate = function (animation) {
return animate(this, animation);
};
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement.
// https://caniuse.com/canvas
function toDataUri(url, mime, cb) {
var img = new Image();
var load = function () {
var me = this;
var canvas = $.create('canvas');
canvas.width = me.naturalWidth;
canvas.height = me.naturalHeight;
canvas.getContext('2d')
.drawImage(me, 0, 0);
cb(canvas.toDataURL(mime));
};
img.src = url;
$.decode(img)
.then(function () {
load.call(img);
})
.catch(function () {
cb(url);
});
}
/**
* Processes blur element.
*
* @param {Element} target
* The .b-lazy element, not the .b-blur one.
*/
function blur(target) {
var cn = $.aniElement && $.aniElement(target);
if (!$.isElm(cn)) {
return;
}
var el = $.find(cn, 'img.' + _bblur);
if (!$.isElm(el)) {
return;
}
var data = $.attr(el, _data + _bblur);
if (!data) {
return;
}
data = data.split('::');
var shouldStore = _isStorage && data[0] === '1';
var isDisabled = data[0] === '-1';
var bid = data[1];
var mime = data[2];
var url = data[3];
var existing = null;
var valid = false;
var stored = $.storage(_blurKey);
// If the browser is capable, and the client option enabled.
if (shouldStore) {
var found = stored && $.contains(stored, bid);
valid = !stored || !found;
_blurStorage = stored ? $.parse(stored) : [];
if (found) {
$.each(_blurStorage, function (img) {
var key = $.keys(img)[0];
if (key === bid) {
existing = img[bid];
return false;
}
});
}
}
else {
// Clear, if disabled (-1), or switching to server from client-side (0).
if (stored) {
$.storage(_blurKey, null);
}
}
// If client is disabled (-1), use server-side data URI. Clear done above.
// Run it late, to ensure storages are cleared above as configured.
if (isDisabled) {
$.removeAttr(el, _data + _bblur);
return;
}
// We are here when client is being enabled.
if (existing) {
el.src = existing;
}
else {
toDataUri(url, mime, function (uri) {
el.src = uri;
if (shouldStore && valid) {
var tmp = {};
tmp[bid] = uri;
_blurStorage.push(tmp);
$.storage(_blurKey, JSON.stringify(_blurStorage));
}
});
}
}
$.blur = blur.bind($);
}(dBlazy, this));