PageSourceSearch

https://www.tuskevents.co.za/wp-content/themes/thegem/js/thegem-lazyLoading.js?ver=5.12.0

js tuskevents.co.za collected 2026-09-26 15:31:02 UTC 12,061 bytes, 450 lines download raw bytes

1(function($) {
2
3	var prefixes = 'Webkit Moz ms Ms O'.split(' ');
4    var docElemStyle = document.documentElement.style;
5
6    function getStyleProperty( propName ) {
7        if ( !propName ) {
8            return;
9        }
10
11        // test standard property first
12        if ( typeof docElemStyle[ propName ] === 'string' ) {
13            return propName;
14        }
15
16        // capitalize
17        propName = propName.charAt(0).toUpperCase() + propName.slice(1);
18
19        // test vendor specific properties
20        var prefixed;
21        for ( var i=0, len = prefixes.length; i < len; i++ ) {
22            prefixed = prefixes[i] + propName;
23            if ( typeof docElemStyle[ prefixed ] === 'string' ) {
24                return prefixed;
25            }
26        }
27    }
28
29    var transitionProperty = getStyleProperty('transition');
30    var transitionEndEvent = {
31        WebkitTransition: 'webkitTransitionEnd',
32        MozTransition: 'transitionend',
33        OTransition: 'otransitionend',
34        transition: 'transitionend'
35    }[ transitionProperty ];
36
37	function getElementData(element, attributeNameCamel, attributeName, defaultValue) {
38		if (element.dataset != undefined) {
39			if (element.dataset[attributeNameCamel] != undefined) {
40				return element.dataset[attributeNameCamel];
41			} else {
42				var value = $(element).data(attributeName);
43				if (value == undefined) {
44					return defaultValue;
45				}
46				return value;
47			}
48			return element.dataset[attributeNameCamel] != undefined ? element.dataset[attributeNameCamel] : defaultValue;
49		}
50		var value = this.getAttribute(attributeName);
51		return value != null && value != '' ? value : defaultValue;
52	}
53
54	function Queue(lazyInstance) {
55		this.lazyInstance = lazyInstance;
56		this.queue = [];
57		this.running = false;
58		this.initTimer();
59	}
60
61	Queue.prototype = {
62		add: function(element) {
63			this.queue.push(element);
64		},
65
66		next: function() {
67			if (this.running || this.queue.length == 0) return false;
68			this.running = true;
69			var element = this.queue.shift();
70			if (element.isOnTop()) {
71				element.forceShow();
72				this.finishPosition();
73				return;
74			}
75//			console.log(element.options['itemDelay']);
76			setTimeout(function() {
77			element.startAnimation();
78			}, element.options['itemDelay']);
79		},
80
81		finishPosition: function() {
82			this.running = false;
83			this.next();
84		},
85
86		initTimer: function() {
87			var self = this;
88
89			this.timer = document.createElement('div');
90			this.timer.className = 'lazy-loading-timer-element';
91			document.body.appendChild(this.timer);
92
93			this.timerCallback = function() {};
94			$(this.timer).bind(transitionEndEvent, function(event) {
95				self.timerCallback();
96			});
97			this.timer.className += ' start-timer';
98		},
99
100		startTimer: function(callback) {
101			// this.timerCallback = callback;
102			setTimeout(callback, 200);
103			if (this.timer.className.indexOf('start-timer') != -1) {
104				this.timer.className = this.timer.className.replace(' start-timer', '');
105			} else {
106				this.timer.className += ' start-timer';
107			}
108		}
109	};
110
111	function Group(el, lazyInstance) {
112		this.el = el;
113		this.$el = $(el);
114		this.lazyInstance = lazyInstance;
115		this.elements = [];
116		this.showed = false;
117		this.finishedElementsCount = 0;
118		this.position = {
119			left: 0,
120			top: 0
121		};
122		this.options = {
123			offset: parseFloat(getElementData(el, 'llOffset', 'll-offset', 0.7)),
124			itemDelay: getElementData(el, 'llItemDelay', 'll-item-delay', -1),
125			isFirst: lazyInstance.hasHeaderVisuals && this.el.className.indexOf('lazy-loading-first') != -1,
126			force: getElementData(el, 'llForceStart', 'll-force-start', 0) != 0,
127			finishDelay: getElementData(el, 'llFinishDelay', 'll-finish-delay', 200)
128		};
129		this.$el.addClass('lazy-loading-before-start-animation');
130	}
131
132	timeNow = function () {
133		var newDate = new Date();
134		return ((newDate.getHours() < 10)?"0":"") + newDate.getHours() +":"+ ((newDate.getMinutes() < 10)?"0":"") + newDate.getMinutes() +":"+ ((newDate.getSeconds() < 10)?"0":"") + newDate.getSeconds();
135	}
136
137	Group.prototype = {
138		addElement: function(element) {
139			this.elements.push(element);
140		},
141
142		setElements: function(elements) {
143			this.elements = elements;
144		},
145
146		getElements: function() {
147			return this.elements;
148		},
149
150		getElementsCount: function() {
151			return this.elements.length;
152		},
153
154		getItemDelay: function() {
155			return this.options.itemDelay;
156		},
157
158		updatePosition: function() {
159			this.position = $(this.el).offset();
160		},
161
162		getPosition: function() {
163			return this.position;
164		},
165
166		isShowed: function() {
167			return this.showed;
168		},
169
170		isVisible: function() {
171			if (this.options.force) return true;
172
173			return (this.position.top + this.options.offset * this.el.offsetHeight <= this.lazyInstance.getWindowBottom()) &&
174				(this.position.top + (1 - this.options.offset) * this.el.offsetHeight >= this.lazyInstance.getWindowTop());
175		},
176
177		isOnTop: function() {
178			return false;
179			//return this.position.top + this.el.offsetHeight < this.lazyInstance.getWindowBottom() - this.lazyInstance.getWindowHeight();
180		},
181
182		show: function() {
183			this.lazyInstance.queue.add(this);
184			this.showed = true;
185		},
186
187		forceShow: function() {
188			this.showed = true;
189			this.el.className = this.el.className.replace('lazy-loading-before-start-animation', 'lazy-loading-end-animation');
190		},
191
192		startAnimation: function() {
193			var self = this;
194			self.elements.forEach(function(element) {
195				element.$el.bind(transitionEndEvent, function(event) {
196					var target = event.target || event.srcElement;
197					if (target != element.el) {
198						return;
199					}
200					element.$el.unbind(transitionEndEvent);
201					self.finishedElementsCount++;
202					if (self.finishedElementsCount >= self.getElementsCount()) {
203						setTimeout(function() {
204							var className = self.el.className
205								.replace('lazy-loading-before-start-animation', '')
206								.replace('lazy-loading-start-animation', 'lazy-loading-end-animation');
207							self.el.className = className;
208
209							if (window.gemSettings.fullpageEnabled) {
210								self.el.classList.add('fullpage-lazy-loading-initialized');
211							}
212
213						}, self.options.finishDelay);
214					}
215				});
216				element.show();
217			});
218
219			if (self.options.finishDelay > 0) {
220				self.lazyInstance.queue.startTimer(function() {
221					self.finishAnimation();
222				});
223			} else {
224				self.finishAnimation();
225			}
226
227			self.$el.addClass('lazy-loading-start-animation');
228		},
229
230		finishAnimation: function() {
231			this.lazyInstance.queue.finishPosition();
232		}
233	};
234
235	function Element(el, group) {
236		this.el = el;
237		this.$el = $(el);
238		this.group = group;
239		this.options = {
240			effect: getElementData(el, 'llEffect', 'll-effect', ''),
241			delay: getElementData(el, 'llItemDelay', 'll-item-delay', group.getItemDelay()),
242			actionFunction: getElementData(el, 'llActionFunc', 'll-action-func', '')
243		};
244		this.options.queueType = this.options.delay != -1 ? 'async' : 'sync';
245		if (this.options.effect != '') {
246			this.$el.addClass('lazy-loading-item-' + this.getEffectClass());
247		}
248	}
249
250	Element.prototype = {
251		effects: {
252			action: function(element) {
253				if (!element.options.actionFunction ||
254						window[element.options.actionFunction] == null ||
255						window[element.options.actionFunction] == undefined) {
256					return;
257				}
258				window[element.options.actionFunction](element.el);
259			}
260		},
261
262		getEffectClass: function() {
263			var effectClass = this.options.effect;
264			if (effectClass == 'drop-right-without-wrap' || effectClass == 'drop-right-unwrap') {
265				return 'drop-right';
266			}
267			return effectClass;
268		},
269
270		show: function() {
271			if (this.effects[this.options.effect] != undefined) {
272				this.effects[this.options.effect](this);
273			}
274		}
275	};
276
277	LazyLoading.prototype = {
278		initialize: function() {
279			this.queue = new Queue(this);
280			this.groups = [];
281			this.hasHeaderVisuals = $('.ls-wp-container').length > 0;
282			this.$checkPoint = $('#lazy-loading-point');
283			if (!this.$checkPoint.length) {
284				$('<div id="lazy-loading-point"></div>').insertAfter('#main');
285				this.$checkPoint = $('#lazy-loading-point');
286			}
287			this.windowBottom = 0;
288			this.windowHeight = 0;
289			this.scrollHandle = false;
290			this.perspectiveOpened = false;
291			this.$page = $('#page');
292			$(document).ready(this.documentReady.bind(this));
293		},
294
295		documentReady: function() {
296			var self = this;
297			this.updateCheckPointOffset();
298			this.updateWindowHeight();
299			this.buildGroups();
300			this.windowScroll();
301			$(window).resize(this.windowResize.bind(this));
302
303			$(window).scroll(this.windowScroll.bind(this));
304			//this.$page.scroll(this.windowScroll.bind(this));
305			$(window).on('perspective-modalview-opened', function() {
306				self.perspectiveOpened = true;
307			});
308			$(window).on('perspective-modalview-closed', function() {
309				self.perspectiveOpened = false;
310			});
311		},
312
313		windowResize: function() {
314			this.updateWindowHeight();
315			this.updateGroups();
316			this.windowScroll();
317		},
318
319		buildGroups: function() {
320			var self = this;
321			self.groups = [];
322
323			$('.lazy-loading').each(function() {
324				if (window.gemSettings.fullpageEnabled && $(this).hasClass('fullpage-lazy-loading-initialized')) {
325					return;
326				}
327
328				var group = new Group(this, self);
329				group.updatePosition();
330				$('.lazy-loading-item', this).each(function() {
331					group.addElement(new Element(this, group));
332				});
333				if (group.getElementsCount() > 0) {
334					self.groups.push(group);
335				}
336			});
337		},
338
339		updateGroups: function() {
340			var self = this;
341			self.groups.forEach(function(group) {
342				if (group.isShowed()) {
343					return;
344				}
345				group.updatePosition();
346			});
347		},
348
349		windowScroll: function() {
350			if (this.scrollHandle) {
351				//return;
352			}
353			this.scrollHandle = true;
354			this.calculateWindowTop();
355			this.calculateWindowBottom();
356			if (this.isGroupsPositionsChanged()) {
357				this.updateGroups();
358			}
359			this.groups.forEach(function(group) {
360				if (group.isShowed()) {
361					return;
362				}
363				if (group.isOnTop()) {
364					group.forceShow();
365				}
366				if (group.isVisible()) {
367					group.show();
368				}
369			});
370			this.scrollHandle = false;
371			this.queue.next();
372		},
373
374		calculateWindowBottom: function() {
375			if (self.perspectiveOpened) {
376				this.windowBottom = this.windowTop + this.$page.height();
377			} else {
378				this.windowBottom = this.windowTop + this.windowHeight;
379			}
380		},
381
382		calculateWindowTop: function() {
383			if (self.perspectiveOpened) {
384				this.windowTop = this.$page.scrollTop();
385			} else {
386				this.windowTop = $(window).scrollTop();
387			}
388		},
389
390		getWindowTop: function() {
391			return this.windowTop;
392		},
393
394		getWindowBottom: function() {
395			return this.windowBottom;
396		},
397
398		updateWindowHeight: function() {
399			this.windowHeight = $(window).height();
400		},
401
402		getWindowHeight: function() {
403			return this.windowHeight;
404		},
405
406		updateCheckPointOffset: function() {
407			this.checkPointOffset = this.$checkPoint.length ? this.$checkPoint.offset().top : 0;
408		},
409
410		isGroupsPositionsChanged: function() {
411			var oldCheckPointOffset = this.checkPointOffset;
412			this.updateCheckPointOffset();
413			return Math.abs(this.checkPointOffset - oldCheckPointOffset) > 1;
414		},
415
416		getLastGroup: function() {
417			if (!this.groups.length) {
418				return null;
419			}
420			return this.groups[this.groups.length - 1];
421		}
422	};
423
424	function LazyLoading(options) {
425		this.options = {};
426		$.extend(this.options, options);
427		this.initialize();
428	}
429
430	$.lazyLoading = function(options) {
431		return new LazyLoading(options);
432	}
433
434	if (window.gemSettings !== undefined && !window.gemSettings.lasyDisabled) {
435	    $('.wpb_text_column.wpb_animate_when_almost_visible.wpb_fade').each(function() {
436	        $(this).wrap('<div class="lazy-loading"></div>').addClass('lazy-loading-item').data('ll-effect', 'fading');
437	    });
438
439	    $('.gem-list.lazy-loading').each(function() {
440	        $(this).data('ll-item-delay', '200');
441	        $('li', this).addClass('lazy-loading-item').data('ll-effect', 'slide-right');
442	        $('li', this).each(function(index) {
443	            $(this).attr("style", "transition-delay: " + (index + 1) * 0.2 + "s;");
444	        });
445	    });
446
447	    $.lazyLoading();
448	}
449
450})(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.