PageSourceSearch

https://blk-sqr.com/wp-content/plugins/grid-kit-premium/js/crp-preloader.js?ver=6.6.9

js blk-sqr.com collected 2026-10-02 20:58:18 UTC 19,000 bytes, 590 lines download raw bytes

1(function($) {
2	/*
3	**	Defaults:
4	**
5	**	preloadSelector
6	**		If set to true will preload the selector's background image, note
7	**		that the image will show as soon as it is loaded and not only
8	**		once the preloader is done loading.
9	**
10	**	truePercentage
11	**		NOTE: does not work with cross-domain calls.
12	**		If set to true will get the actual (compressed) file size of all
13	**		the images instead of just looking at the number of images loaded
14	**		divided by the total number of images.
15	**
16	**	disableOverlay
17	**		If set to true will not create the blocking overlay.
18	**
19	**	showInContainer
20	**		If set to true will load the preloader inside the selector element
21	**		instead of across the whole page.
22	**
23	**	hideBackground
24	**		NOTE: hideBackground is an option for when showInContainer is set
25	**		to true.
26	**		If set to true will hide the css background-image of the selector
27	**		element.
28	**
29	**	hideNonImageElements
30	**		If set to true will hide all elements of the selector, not only
31	**		the images.
32	**
33	**	progressiveReveal
34	**		NOTE: if hideNonImageElements is set to true then progessiveReveal
35	**		might not return the expected result because the image element's
36	**		parent might be hidden.
37	**		If set to true will show images as soon as they are preloaded.
38	**
39	**	forceSequentialLoad
40	**		Will force images to load in the order they appear in the DOM, this
41	**		can potentially increase the load time because images won't start
42	**		loading in parallel.
43	**
44	**	silentMode
45	**		If set to true will hide the preloader.
46	**
47	**	debugMode
48	**		If set to true will show errors.
49	**
50	**	useOpacity
51	**		If set to true will use opacity property to hide elements instead
52	**		of display property.
53	**
54	**	hidePercentage
55	**		If set to true will not show the percentage numbers while loading.
56	**
57	**	loaderText
58	**		Set the text of the loading message.
59	**
60	**	animateDuration
61	**		Set the duration in milliseconds for each progress animation.
62	**
63	**	fadeOutDuration
64	**		Set the duration in milliseconds for the preloader fadeout animation.
65	**
66	**	showImagesBeforeComplete
67	**		If set to false will wait for the animation of the preloader fadeout
68	**		to complete before showing the images.
69	**
70	**	afterEach
71	**		Called once after every image load.
72	**
73	**	beforeComplete
74	**		Called once after all images have been loaded and before the fadeout
75	**		animation of the preloader triggers.
76	**
77	**	onComplete
78	**		Called once after all images have been loaded and all preloader
79	**		animations have completed.
80	*/
81
82	var defaults = {
83		selector: false,
84		preloadSelector          : true,
85		truePercentage           : false,
86		disableOverlay           : false,
87		showInContainer          : false,
88		hideBackground           : false,
89		hideNonImageElements     : false,
90		progressiveReveal        : false,
91		forceSequentialLoad      : false,
92		silentMode               : false,
93		debugMode                : false,
94		useOpacity               : false,
95		hidePercentage           : false,
96		loaderText               : 'loading images, please wait...',
97		animateDuration          : 1000,
98		fadeOutDuration          : 100,
99		showImagesBeforeComplete : true,
100		afterEach                : function() {},
101		beforeComplete           : function() {},
102		onComplete               : function() {}
103	};
104
105	var methods = {
106		init: function(options) {
107			var settings = $.extend({}, defaults, options);
108
109			return this.each(function() {
110				var parent             = $(this);
111				var elementChildren    = getAllChildren(parent);
112				var imageElements      = [];
113				var nonImageElements   = [];
114				var imagesLoaded       = 0;
115				var totalImages        = 0;
116				var progressPercentage = 0;
117				var totalPercentage    = 0;
118				var count              = 0;
119				var minUpdateToValue   = 0; // prevents preloader from jumping backwards
120
121				// Create preloader DOM elements.
122				var preloadContainer = $('<div id="crp_preloader"></div>');
123
124				if (!settings.showInContainer) {
125					preloadContainer.appendTo('body');
126					preloadContainer.css('position', 'fixed');
127				} else {
128					preloadContainer.appendTo(parent);
129					parent.css('position', 'relative');
130					preloadContainer.css('position', 'absolute');
131				}
132
133				if (!settings.disableOverlay) {
134					var preloadOverlay = $('<div class="crp_loader_overlay"></div>').appendTo(preloadContainer);
135				} else {
136					preloadContainer.css('height', 'auto');
137				}
138
139				var preloadLoader = $('<div class="crp_loader"></div>').appendTo(preloadContainer);
140
141				if (!settings.hidePercentage) {
142					var progressNotification = $('<div class="crp_progress_notification">' + settings.loaderText + ' <span class="crp_progress_percentage">' + progressPercentage + '</span>%</div>').appendTo(preloadLoader);
143				} else {
144					var progressNotification = $('<div class="crp_progress_notification">' + settings.loaderText + '</div>').appendTo(preloadLoader);
145				}
146
147				var progressBar    = $('<div class="crp_progress_bar"></div>').appendTo(preloadLoader);
148				var progressLoaded = $('<div class="crp_progress_loaded"></div>').appendTo(progressBar);
149
150				if (settings.silentMode) {
151					preloadContainer.hide();
152				}
153
154				// Start animating progress bar to indicate activity
155				if (settings.truePercentage) {
156					updateProgressbar(1, 3000); // 3s initial trickle
157				}
158
159				if (settings.debugMode) {
160					var startTime = (new Date).getTime();
161
162					console.groupCollapsed('crpPreload > ', parent);
163					console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': scanning DOM for image elements...');
164					console.groupCollapsed('image elements');
165				}
166
167				/*
168				**	Get all elements that contain images or background images
169				**	to check how many images have to be preloaded.
170				*/
171				elementChildren.forEach(function(child) {
172					if (child.is('img') || child.css('background-image') !== 'none' && child.css('background-image').indexOf('gradient') == -1) {
173
174						// While preloading hide all elements except parent if set to false.
175						if (!(settings.preloadSelector && settings.showInContainer && child === parent)) {
176							if (!settings.useOpacity) {
177								child.hide();
178							} else {
179								child.css('opacity', '0');
180							}
181						} else if (settings.hideBackground) {
182							child.attr('data-bg', child.css('background-image')).css('background-image', 'none');
183						}
184
185						var imageElement = {
186							node     : child,
187							fileSize : 0
188						};
189
190						if (settings.debugMode) {
191							console.log(imageElement.node);
192						}
193
194						imageElements.push(imageElement);
195						totalImages++;
196					} else if (settings.hideNonImageElements) {
197						if (!settings.useOpacity) {
198							child.hide();
199						} else {
200							child.css('opacity', '0');
201						}
202
203						nonImageElements.push(child);
204					}
205				});
206
207				if (settings.debugMode) {
208					console.groupEnd();
209					console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': scanning DOM for image elements DONE');
210				}
211
212				/*
213				**	Get the percentage total of all the images. Once this number is reached
214				**	by the preloader the loading is done.
215				*/
216				if (settings.truePercentage) {
217					if (settings.debugMode) {
218						console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': getting image sizes...');
219						console.groupCollapsed('image sizes');
220					}
221
222					/*
223					**	Get the Content-Length attribute as rough estimate of the actual
224					**	file size. Use this to get the total file size of all images and
225					**	calculate percentage relative to it.
226					*/
227					imageElements.forEach(function(element) {
228						$.ajax({
229							type: 'HEAD',
230							cache: false,
231							url: getImageUrl(element.node),
232							success: function(response, message, object) {
233								element.fileSize = parseInt(object.getResponseHeader('Content-Length'));
234								totalPercentage += element.fileSize;
235
236								if (settings.debugMode) {
237									console.log((element.fileSize / 1000).toFixed(2) + ' KB \t' + (totalPercentage / 1000).toFixed(2) + ' KB total');
238								}
239
240								continueCounting();
241							},
242							error: function(object, response, message) {
243								// Ignore errors, they will be handled later. Show a message to notify.
244								continueCounting();
245
246								var markup = '';
247
248								markup += 'Not all of your images were preloaded!<br>';
249								markup += 'Loader failed getting image sizes.<br><br>';
250								markup += '1. Make sure your images exist.<br>';
251								markup += '2. Make sure your image paths/urls are correct.<br>';
252								markup += '3. If you load images from a remote domain set <code>truePercentage: false</code>.<br><br>';
253								markup += '<button>Close</button>';
254
255								progressNotification.addClass('error').html(markup);
256								progressBar.addClass('error');
257
258								settings.fadeOutDuration = 500000;
259
260								$('#crp_preloader button').click(function() {
261									preloadContainer.remove();
262								});
263							}
264						});
265
266						function continueCounting() {
267							count++;
268
269							if (count === totalImages) {
270								if (settings.debugMode) {
271									console.groupEnd();
272									console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': getting image sizes DONE');
273								}
274
275								startPreloading();
276							}
277						}
278					});
279				} else {
280					if (settings.debugMode) {
281						console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': getting image sizes SKIPPED');
282					}
283
284					/*
285					**	Get number of total images and use that to calculate percentage
286					**	relative to number of images loaded.
287					*/
288					totalPercentage = totalImages;
289					startPreloading();
290				}
291
292				function startPreloading() {
293					if (settings.debugMode) {
294						console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': preloading image elements...');
295						console.groupCollapsed('intervals');
296					}
297
298					/*
299					**	Get the url of the image or the css background image. Create a
300					**	DOM image element which holds the image (preloads it) and triggers
301					**	a progressbar update on successful load. Show all images or elements
302					**	with background images only once all images have been preloaded.
303					*/
304					if (!settings.forceSequentialLoad) {
305						imageElements.forEach(function(element, index) {
306							var img = element.node;
307
308							img.load(function() {
309								updateLoader(element);
310							}).error(function() {
311								updateLoader(element);
312								handleLoadingError(img, element);
313							});
314
315							img.attr('src', getImageUrl(element.node));
316						});
317					} else {
318						(function loadImage(index) {
319							var currentElement = imageElements[index];
320							var img = currentElement.node;
321
322							img.load(function() {
323								updateLoader(currentElement);
324
325								if (++index < imageElements.length) {
326									loadImage(index);
327								}
328							}).error(function() {
329								// Ignore failed image loads but add an error class to the image.
330								updateLoader(currentElement);
331
332								if (++index < imageElements.length) {
333									loadImage(index);
334								}
335								handleLoadingError(img, currentElement);
336							});
337
338							img.attr('src', getImageUrl(currentElement.node));
339						})(0);
340					}
341				}
342
343				function handleLoadingError(image, element) {
344					element.node.addClass('crp_preloader_not_found_error');
345				}
346
347				function updateLoader(element) {
348					imagesLoaded++;
349					updateProgressPercentage(element);
350					updateProgressbar(progressPercentage, undefined, element);
351
352					if (settings.progressiveReveal) {
353						revealElement(element.node);
354					}
355
356					settings.afterEach.call(element.node);
357				}
358
359				function updateProgressPercentage(element) {
360					if (settings.truePercentage) {
361						progressPercentage += (element.fileSize / totalPercentage) * 100;
362
363						if (imagesLoaded === totalImages) {
364							/*
365							**	Sometimes truePercentage calculations end up being slighlty
366							**	less or greater than 100% due to JavaScript's handling of
367							**	floating point numbers, so here we make sure the progress
368							**	is 100%.
369							*/
370							progressPercentage = 100;
371						}
372					} else {
373						progressPercentage = (imagesLoaded / totalPercentage) * 100;
374					}
375				}
376
377				function updateProgressbar(value, updateDuration, element) {
378					// Animates the progress bar and percentage to reflect the value specified.
379					updateDuration = updateDuration !== undefined ? updateDuration : settings.animateDuration;
380					var totalWidth = 0;
381					var updateTo   = value;
382					var remaining  = 0;
383
384					if (updateDuration === undefined && settings.debugMode) {
385						console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': ' + value.toFixed(2) + '%');
386					}
387
388					/*
389					**	Here we actually set the loader to load less than the actual value.
390					**	We do this so we can creep up do the actual value and prevent the
391					**	loader from ever reaching the value. This will give the impression
392					**	that the loader is constantly loading and not getting stuck as
393					**	often on a random number while waiting for the next animation.
394					*/
395					if (value < 100) {
396						if (element !== undefined) {
397							if (element.round === undefined) {
398								element.round = 0;
399
400								updateTo  = value / 4 * 3;
401								remaining = value / 4;
402							} else {
403								element.round++;
404
405								updateTo       = value / (4 + element.round) * (3 + element.round);
406								remaining      = value / (4 + element.round);
407								updateDuration = 200;
408							}
409						}
410					}
411
412					if (element === undefined) {
413						element = {};
414					}
415
416					if (element.round === undefined) {
417						element.round = 0;
418					}
419
420					if (updateTo > minUpdateToValue) {
421						minUpdateToValue = updateTo;
422					}
423
424					if (updateTo < minUpdateToValue) {
425						updateTo = minUpdateToValue;
426					}
427
428					progressLoaded.stop();
429
430					if (element.round < 30) {
431						progressLoaded.animate({'width': updateTo + '%'}, {
432							duration: updateDuration,
433							easing: 'linear',
434							step: function() {
435								/*
436								**	Update totalWidth on each step rather than at top of function
437								**	to ensure that the loading percentage is correct for the odd
438								**	case when the browser window gets resized during loading.
439								*/
440								totalWidth = progressBar.width();
441
442								// Set the progress percentage text to the currently animated width.
443								progressNotification.children('span').html(Math.round((progressLoaded.width() / totalWidth) * 100));
444							},
445							complete: function() {
446								/*
447								**	The "step" function does not always trigger after the animation
448								**	is done, that is why we make sure to always set the value here.
449								**	E.g. we animate width to 100%, but at 99% the "step" function
450								**	might trigger for the last time, which would cause an unwanted
451								**	result. Also, the lower the animation speed is the less accurate
452								**	the "step" gets, leading to scenarios where the progress bar's
453								**	width could be 100% while the text reads something like 87%.
454								*/
455								progressNotification.children('span').html(Math.round(updateTo));
456
457								// Once done loading show all elements and delete preloader DOM elements.
458								if (imagesLoaded === totalImages) {
459									if (settings.debugMode) {
460										console.groupEnd();
461										console.log((((new Date).getTime() - startTime) / 1000).toFixed(3) + ': preloading image elements DONE');
462										console.groupEnd();
463									}
464
465									progressLoaded.delay(100).queue(function() {
466										if (settings.showImagesBeforeComplete) {
467											imageElements.forEach(function(element) {
468												revealElement(element.node);
469											});
470
471											nonImageElements.forEach(function(element) {
472												revealElement(element);
473											});
474
475											settings.beforeComplete.call(this);
476
477											preloadContainer.animate({'opacity':'0'}, settings.fadeOutDuration, function() {
478												preloadContainer.remove();
479												settings.onComplete.call(this);
480											});
481										} else {
482											settings.beforeComplete.call(this);
483
484											preloadContainer.animate({'opacity':'0'}, settings.fadeOutDuration, function() {
485												imageElements.forEach(function(element) {
486													revealElement(element.node);
487												});
488
489												nonImageElements.forEach(function(element) {
490													revealElement(element);
491												});
492
493												preloadContainer.remove();
494												settings.onComplete.call(this);
495											});
496										}
497									});
498								} else {
499									/*
500									**	Continue animating. We do this to try and prevent the
501									**	loader from getting stuck on a random number.
502									*/
503									updateProgressbar(value, updateDuration, element);
504								}
505							}
506						});
507					}
508				}
509
510				function getAllChildren(selector) {
511					var selectorChildren = [];
512
513					if (selector.children().length > 0) {
514						if (settings.preloadSelector) {
515							selectorChildren.push(selector);
516						}
517
518						getChildren(selector);
519					} else if (settings.preloadSelector) {
520						selectorChildren.push(selector);
521					}
522
523					function getChildren(element) {
524						var children = element.children();
525
526						if (children.length > 0) {
527							children.each(function() {
528								var _this = $(this);
529
530								selectorChildren.push(_this);
531
532								if (_this.children().length > 0) {
533									getChildren(_this);
534								}
535							});
536						}
537					}
538
539					return selectorChildren;
540				}
541
542				function getImageUrl(image) {
543					if (image.css('background-image') !== 'none') {
544						return image.css('background-image').replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
545					} else if (image.css('background-image') === 'none' && image.attr('data-bg')) {
546						return image.attr('data-bg').replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
547					} else {
548						return image.attr('data-src');
549					}
550				}
551
552				function revealElement(element) {
553					if (!settings.useOpacity) {
554						element.show();
555					} else {
556						element.css('opacity', '1');
557					}
558					if (element.attr('data-bg')) {
559						element.css('background-image', element.attr('data-bg'));
560					}
561				}
562			});
563		}
564	};
565
566	/*
567	**	Check if browser supports Array.forEach() method, if it doesn't
568	**	mimic that functionality, implementation from here:
569	**	http://stackoverflow.com/questions/2790001/fixing-javascript-array-functions-in-internet-explorer-indexof-foreach-etc
570	*/
571	if (!('forEach' in Array.prototype)) {
572		Array.prototype.forEach = function(action, that /*opt*/) {
573			for (var i = 0, n = this.length; i < n; i++) {
574				if (i in this) {
575					action.call(that, this[i], i, this);
576				}
577			}
578		};
579	}
580
581	$.fn.crpPreload = function(method) {
582		if (methods[method]) {
583			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
584		} else if (typeof method === 'object' || !method) {
585			return methods.init.apply(this, arguments);
586		} else {
587			$.error('Method ' +  method + ' does not exist on jQuery.crpPreload');
588		}
589	};
590})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.