monitor-dashboard/src/assets/theme-assets/js/custom/jquery.waitforimages.js

229 lines
8.0 KiB
JavaScript
Executable File

/*! waitForImages jQuery Plugin - v2.2.0 - 2017-02-20
* https://github.com/alexanderdickson/waitForImages
* Copyright (c) 2017 Alex Dickson; Licensed MIT */
;(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS / nodejs module
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
// Namespace all events.
var eventNamespace = 'waitForImages';
// Is srcset supported by this browser?
var hasSrcset = (function(img) {
return img.srcset && img.sizes;
})(new Image());
// CSS properties which contain references to images.
$.waitForImages = {
hasImageProperties: [
'backgroundImage',
'listStyleImage',
'borderImage',
'borderCornerImage',
'cursor'
],
hasImageAttributes: ['srcset']
};
// Custom selector to find all `img` elements with a valid `src` attribute.
$.expr[':']['has-src'] = function (obj) {
// Ensure we are dealing with an `img` element with a valid
// `src` attribute.
return $(obj).is('img[src][src!=""]');
};
// Custom selector to find images which are not already cached by the
// browser.
$.expr[':'].uncached = function (obj) {
// Ensure we are dealing with an `img` element with a valid
// `src` attribute.
if (!$(obj).is(':has-src')) {
return false;
}
return !obj.complete;
};
$.fn.waitForImages = function () {
var allImgsLength = 0;
var allImgsLoaded = 0;
var deferred = $.Deferred();
var originalCollection = this;
var allImgs = [];
// CSS properties which may contain an image.
var hasImgProperties = $.waitForImages.hasImageProperties || [];
// Element attributes which may contain an image.
var hasImageAttributes = $.waitForImages.hasImageAttributes || [];
// To match `url()` references.
// Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri
var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g;
var finishedCallback;
var eachCallback;
var waitForAll;
// Handle options object (if passed).
if ($.isPlainObject(arguments[0])) {
waitForAll = arguments[0].waitForAll;
eachCallback = arguments[0].each;
finishedCallback = arguments[0].finished;
} else {
// Handle if using deferred object and only one param was passed in.
if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') {
waitForAll = arguments[0];
} else {
finishedCallback = arguments[0];
eachCallback = arguments[1];
waitForAll = arguments[2];
}
}
// Handle missing callbacks.
finishedCallback = finishedCallback || $.noop;
eachCallback = eachCallback || $.noop;
// Convert waitForAll to Boolean.
waitForAll = !! waitForAll;
// Ensure callbacks are functions.
if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) {
throw new TypeError('An invalid callback was supplied.');
}
this.each(function () {
// Build a list of all imgs, dependent on what images will
// be considered.
var obj = $(this);
if (waitForAll) {
// Get all elements (including the original), as any one of
// them could have a background image.
obj.find('*').addBack().each(function () {
var element = $(this);
// If an `img` element, add it. But keep iterating in
// case it has a background image too.
if (element.is('img:has-src') &&
!element.is('[srcset]')) {
allImgs.push({
src: element.attr('src'),
element: element[0]
});
}
$.each(hasImgProperties, function (i, property) {
var propertyValue = element.css(property);
var match;
// If it doesn't contain this property, skip.
if (!propertyValue) {
return true;
}
// Get all url() of this element.
while (match = matchUrl.exec(propertyValue)) {
allImgs.push({
src: match[2],
element: element[0]
});
}
});
$.each(hasImageAttributes, function (i, attribute) {
var attributeValue = element.attr(attribute);
var attributeValues;
// If it doesn't contain this property, skip.
if (!attributeValue) {
return true;
}
allImgs.push({
src: element.attr('src'),
srcset: element.attr('srcset'),
element: element[0]
});
});
});
} else {
// For images only, the task is simpler.
obj.find('img:has-src')
.each(function () {
allImgs.push({
src: this.src,
element: this
});
});
}
});
allImgsLength = allImgs.length;
allImgsLoaded = 0;
// If no images found, don't bother.
if (allImgsLength === 0) {
finishedCallback.call(originalCollection);
deferred.resolveWith(originalCollection);
}
// Now that we've found all imgs in all elements in this,
// load them and attach callbacks.
$.each(allImgs, function (i, img) {
var image = new Image();
var events =
'load.' + eventNamespace + ' error.' + eventNamespace;
// Handle the image loading and error with the same callback.
$(image).one(events, function me (event) {
// If an error occurred with loading the image, set the
// third argument accordingly.
var eachArguments = [
allImgsLoaded,
allImgsLength,
event.type == 'load'
];
allImgsLoaded++;
eachCallback.apply(img.element, eachArguments);
deferred.notifyWith(img.element, eachArguments);
// Unbind the event listeners. I use this in addition to
// `one` as one of those events won't be called (either
// 'load' or 'error' will be called).
$(this).off(events, me);
if (allImgsLoaded == allImgsLength) {
finishedCallback.call(originalCollection[0]);
deferred.resolveWith(originalCollection[0]);
return false;
}
});
if (hasSrcset && img.srcset) {
image.srcset = img.srcset;
image.sizes = img.sizes;
}
image.src = img.src;
});
return deferred.promise();
};
}));