PageSourceSearch

https://simplelogin.io/assets/js/components/hs.unfold.js

js simplelogin.io collected 2026-09-24 08:43:03 UTC 16,095 bytes, 708 lines download raw bytes

1/**
2 * Unfold Content component.
3 *
4 * @author Htmlstream
5 * @version 1.0
6 */
7;
8(function ($) {
9	'use strict';
10	
11	$.HSCore.components.HSUnfold = {
12		
13		/**
14		 * Base configuration of the component.
15		 *
16		 * @private
17		 */
18		_baseConfig: {
19			unfoldEvent: 'click',
20			unfoldType: 'simple',
21			unfoldDuration: 300,
22			unfoldEasing: 'linear',
23			unfoldAnimationIn: 'fadeIn',
24			unfoldAnimationOut: 'fadeOut',
25			unfoldHideOnScroll: true,
26			unfoldHideOnBlur: false,
27			unfoldDelay: 350,
28			unfoldOpenedElement: 'init',
29			unfoldOverlay: false,
30			afterOpen: function (invoker) {
31			},
32			beforeClose: function (invoker) {
33			},
34			afterClose: function (invoker) {
35			}
36		},
37		
38		/**
39		 * Collection of all initialized items on the page.
40		 *
41		 * @private
42		 */
43		_pageCollection: $(),
44		
45		/**
46		 * Initialization.
47		 *
48		 * @param {jQuery} collection
49		 * @param {Object} config
50		 *
51		 * @public
52		 * @return {jQuery}
53		 */
54		init: function (collection, config) {
55			
56			var self;
57			
58			if (!collection || !collection.length) return;
59			
60			self = this;
61			
62			var fieldsQty;
63			
64			collection.each(function (i, el) {
65				
66				var $this = $(el), itemConfig;
67				
68				if ($this.data('HSUnfold')) return;
69				
70				itemConfig = config && $.isPlainObject(config) ?
71					$.extend(true, {}, self._baseConfig, config, $this.data()) :
72					$.extend(true, {}, self._baseConfig, $this.data());
73				
74				switch (itemConfig.unfoldType) {
75					
76					case 'css-animation' :
77						
78						$this.data('HSUnfold', new UnfoldCSSAnimation($this, itemConfig));
79						
80						break;
81					
82					case 'jquery-slide' :
83						
84						$this.data('HSUnfold', new UnfoldJSlide($this, itemConfig));
85						
86						break;
87					
88					default :
89						
90						$this.data('HSUnfold', new UnfoldSimple($this, itemConfig));
91					
92				}
93				
94				self._pageCollection = self._pageCollection.add($this);
95				self._bindEvents($this, itemConfig.unfoldEvent, itemConfig.unfoldDelay);
96				var UnFold = $(el).data('HSUnfold');
97				
98				fieldsQty = $(UnFold.target).find('input, textarea').length;
99				
100				if ($(UnFold.target).find('[data-unfold-target]').length) {
101					
102					$this.addClass('target-of-invoker-has-unfolds');
103					
104				}
105				
106			});
107			
108			$(document).on('click touchstart', 'body', function (e) {
109				
110				if (e.target.id === self._baseConfig.unfoldOpenedElement) return;
111				
112				if ($(e.target).closest('#' + self._baseConfig.unfoldOpenedElement).length) return;
113				
114				self._pageCollection.each(function (i, el) {
115					
116					var windW = window.innerWidth,
117						optIsMobileOnly = Boolean($(el).data('is-mobile-only'));
118					
119					if (!optIsMobileOnly) {
120						
121						$(el).data('HSUnfold').hide();
122						
123					} else if (optIsMobileOnly && windW < 769) {
124						
125						$(el).data('HSUnfold').hide();
126						
127					}
128					
129					if ($(el).data('HSUnfold').config.unfoldOverlay) {
130						
131						$(el).data('HSUnfold').config.unfoldDelay = setTimeout(function () {
132							
133							$('.' + $(el).data('HSUnfold').config.unfoldOverlay.className).fadeOut($(el).data('HSUnfold').config.unfoldOverlay.animationSpeed ? $(el).data('HSUnfold').config.unfoldOverlay.animationSpeed : 200);
134							
135						}, $(el).data('HSUnfold').config.unfoldDelay)
136						
137					}
138					
139					$(el).data('HSUnfold').config.beforeClose.call(self.target, self.element);
140					
141				});
142				
143			});
144			
145			$(window).on('scroll.HSUnfold', function () {
146				
147				self._pageCollection.each(function (i, el) {
148					
149					var UnFold = $(el).data('HSUnfold');
150					
151					if (UnFold.getOption('unfoldHideOnScroll') && fieldsQty === 0) {
152						
153						UnFold.hide();
154						
155					} else if (UnFold.getOption('unfoldHideOnScroll') && !(/iPhone|iPad|iPod/i.test(navigator.userAgent))) {
156						
157						UnFold.hide();
158						
159					}
160					
161				});
162				
163			});
164			
165			$(window).on('resize.HSUnfold', function () {
166				
167				if (self._resizeTimeOutId) clearTimeout(self._resizeTimeOutId);
168				
169				self._resizeTimeOutId = setTimeout(function () {
170					
171					self._pageCollection.each(function (i, el) {
172						
173						var UnFold = $(el).data('HSUnfold');
174						
175						UnFold.smartPosition(UnFold.target);
176						
177					});
178					
179				}, 50);
180				
181			});
182			
183			$(document).on('keydown.HSUnfold', function (e) {
184				
185				if ($('body').hasClass('u-unfold-opened')) {
186					
187					if (e.keyCode && e.keyCode === 38 || e.keyCode && e.keyCode === 40) {
188						
189						e.preventDefault();
190						
191					}
192					
193					if (e.keyCode && e.keyCode === 27) {
194						
195						self._pageCollection.each(function (i, el) {
196							
197							$(el).data('HSUnfold').hide();
198							
199							$('.' + $(el).data('HSUnfold').config.unfoldOverlay.className).fadeOut($(el).data('HSUnfold').config.unfoldOverlay.animationSpeed ? $(el).data('HSUnfold').config.unfoldOverlay.animationSpeed : 200);
200							
201						});
202						
203						$('body').removeClass('u-unfold-opened');
204						
205					}
206					
207				}
208				
209			});
210			
211			return collection;
212			
213		},
214		
215		/**
216		 * Binds necessary events.
217		 *
218		 * @param {jQuery} $invoker
219		 * @param {String} eventType
220		 * @param {Number} delay
221		 * @private
222		 */
223		_bindEvents: function ($invoker, eventType, delay) {
224			
225			var self = this,
226				$unfold = $($invoker.data('unfold-target'));
227			
228			if (eventType === 'hover' && !_isTouch()) {
229				
230				$invoker.on('mouseenter.HSUnfold', function () {
231					
232					var $invoker = $(this),
233						HSUnfold = $invoker.data('HSUnfold');
234					
235					if (!HSUnfold) return;
236					
237					if (HSUnfold.unfoldTimeOut) clearTimeout(HSUnfold.unfoldTimeOut);
238					HSUnfold.show();
239					$('body').addClass('u-unfold-opened');
240					
241				})
242					.on('mouseleave.HSUnfold', function () {
243						
244						var $invoker = $(this),
245							HSUnfold = $invoker.data('HSUnfold');
246						
247						if (!HSUnfold) return;
248						
249						HSUnfold.unfoldTimeOut = setTimeout(function () {
250							
251							HSUnfold.hide();
252							$('body').removeClass('u-unfold-opened');
253							
254						}, delay);
255						
256					});
257				
258				if ($unfold.length) {
259					
260					$unfold.on('mouseenter.HSUnfold', function () {
261						
262						var HSUnfold = $invoker.data('HSUnfold');
263						
264						if (HSUnfold.unfoldTimeOut) clearTimeout(HSUnfold.unfoldTimeOut);
265						HSUnfold.show();
266						
267					})
268						.on('mouseleave.HSUnfold', function () {
269							
270							var HSUnfold = $invoker.data('HSUnfold');
271							
272							HSUnfold.unfoldTimeOut = setTimeout(function () {
273								HSUnfold.hide();
274							}, delay);
275							
276						});
277				}
278				
279			} else {
280				
281				$invoker.on('click.HSUnfold', function (e) {
282					
283					var $curInvoker = $(this),
284						$unfoldNotHasInnerUnfolds = $('[data-unfold-target].active:not(.target-of-invoker-has-unfolds)'),
285						$unfoldHasInnerUnfold = $('[data-unfold-target].active.target-of-invoker-has-unfolds');
286					
287					self._baseConfig.unfoldOpenedElement = $curInvoker.data('HSUnfold').target[0].id;
288					
289					if (!$curInvoker.data('HSUnfold')) return;
290					
291					if (!$curInvoker.hasClass('target-of-invoker-has-unfolds')) {
292						
293						if ($unfoldNotHasInnerUnfolds.length) {
294							
295							$unfoldNotHasInnerUnfolds.data('HSUnfold').toggle();
296							
297						}
298						
299					} else {
300						
301						if ($unfoldHasInnerUnfold.length) {
302							
303							$unfoldHasInnerUnfold.data('HSUnfold').toggle();
304							
305						}
306						
307					}
308					
309					$curInvoker.data('HSUnfold').toggle();
310					$('body').toggleClass('u-unfold-opened');
311					
312					e.stopPropagation();
313					
314					e.preventDefault();
315					
316				});
317				
318				if (Boolean($invoker.data('unfold-target-is-menu'))) {
319					
320					var $target = $($invoker.data('unfold-target')),
321						$targetItems = $target.children();
322					
323					$targetItems.on('click', function () {
324						
325						$invoker.data('HSUnfold').toggle();
326						
327					});
328					
329				}
330				
331			}
332			
333		}
334	};
335	
336	function _isTouch() {
337		return 'ontouchstart' in window;
338	}
339	
340	/**
341	 * Abstract Unfold class.
342	 *
343	 * @param {jQuery} element
344	 * @param {Object} config
345	 * @abstract
346	 */
347	function AbstractUnfold(element, config) {
348		
349		var $self = this;
350		
351		if (!element.length) return false;
352		
353		$self.element = element;
354		$self.config = config;
355		
356		$self.target = $($self.element.data('unfold-target'));
357		
358		$self.allInvokers = $('[data-unfold-target="' + $self.element.data('unfold-target') + '"]');
359		
360		$self.toggle = function () {
361			if (!$self.target.length) return $self;
362			
363			var dataset = $self.element[0].dataset,
364				overlay = dataset.unfoldOverlay ? JSON.parse(dataset.unfoldOverlay) : false;
365			
366			if ($self.defaultState) {
367				
368				if (dataset.unfoldOverlay) {
369					
370					if (!$('.' + overlay.className).length) {
371						
372						$('<div class="' + overlay.className + '" style="background-color: ' + overlay.background + '"></div>').prependTo('body');
373						
374					}
375					
376					if ($('.' + overlay.className).length) {
377						
378						$('.' + overlay.className).fadeIn(overlay.animationSpeed ? overlay.animationSpeed : 200);
379						
380					}
381					
382				}
383				
384				$self.show();
385				
386			} else {
387				
388				if ($('.' + overlay.className).length) {
389					
390					$self.config.unfoldTimeOut = setTimeout(function () {
391						
392						$('.' + overlay.className).fadeOut(overlay.animationSpeed ? overlay.animationSpeed : 200);
393						
394					}, $self.config.unfoldDelay)
395					
396				}
397				
398				$self.hide();
399				
400			}
401			
402			return $self;
403		};
404		
405		this.smartPosition = function (target) {
406			
407			if (target.data('baseDirection')) {
408				target.css(
409					target.data('baseDirection').direction,
410					target.data('baseDirection').value
411				);
412			}
413			
414			target.removeClass('u-unfold--reverse-y');
415			
416			var $w = $(window),
417				styles = getComputedStyle(target.get(0)),
418				direction = Math.abs(parseInt(styles.left, 10)) < 40 ? 'left' : 'right',
419				targetOuterGeometry = target.offset();
420			
421			// horizontal axis
422			if (direction === 'right') {
423				
424				if (!target.data('baseDirection')) target.data('baseDirection', {
425					direction: 'right',
426					value: parseInt(styles.right, 10)
427				});
428				
429				if (targetOuterGeometry.left < 0) {
430					
431					target.css(
432						'right',
433						(parseInt(target.css('right'), 10) - (targetOuterGeometry.left - 10)) * -1
434					);
435					
436				}
437				
438			} else {
439				
440				if (!target.data('baseDirection')) target.data('baseDirection', {
441					direction: 'left',
442					value: parseInt(styles.left, 10)
443				});
444				
445				if (targetOuterGeometry.left + target.outerWidth() > $w.width()) {
446					
447					target.css(
448						'left',
449						(parseInt(target.css('left'), 10) - (targetOuterGeometry.left + target.outerWidth() + 10 - $w.width()))
450					);
451					
452				}
453				
454			}
455			
456			// vertical axis
457			if (targetOuterGeometry.top + target.outerHeight() - $w.scrollTop() > $w.height()) {
458				
459				target.addClass('u-unfold--reverse-y');
460				
461			}
462			
463		};
464		
465		this.getOption = function (option) {
466			return this.config[option] ? this.config[option] : null;
467		};
468		
469		return true;
470	}
471	
472	
473	/**
474	 * UnfoldSimple constructor.
475	 *
476	 * @param {jQuery} element
477	 * @param {Object} config
478	 * @constructor
479	 */
480	function UnfoldSimple(element, config) {
481		if (!AbstractUnfold.call(this, element, config)) return;
482		
483		Object.defineProperty(this, 'defaultState', {
484			get: function () {
485				return this.target.hasClass('u-unfold--hidden');
486			}
487		});
488		
489		this.target.addClass('u-unfold--simple');
490		
491		this.hide();
492	}
493	
494	/**
495	 * UnfoldCSSAnimation constructor.
496	 *
497	 * @param {jQuery} element
498	 * @param {Object} config
499	 * @constructor
500	 */
501	function UnfoldCSSAnimation(element, config) {
502		if (!AbstractUnfold.call(this, element, config)) return;
503		
504		var self = this;
505		
506		this.target
507			.addClass('u-unfold--css-animation u-unfold--hidden')
508			.css('animation-duration', self.config.unfoldDuration + 'ms');
509		
510		Object.defineProperty(this, 'defaultState', {
511			get: function () {
512				return this.target.hasClass('u-unfold--hidden');
513			}
514		});
515		
516		if (this.target.length) {
517			
518			this.target.on('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function (e) {
519				
520				if (self.target.hasClass(self.config.unfoldAnimationOut)) {
521					
522					self.target.removeClass(self.config.unfoldAnimationOut)
523						.addClass('u-unfold--hidden');
524					
525					
526					if (self.allInvokers.length) self.allInvokers.attr('aria-expanded', 'false');
527					
528					self.config.afterClose.call(self.target, self.element);
529				}
530				
531				if (self.target.hasClass(self.config.unfoldAnimationIn)) {
532					
533					if (self.allInvokers.length) self.allInvokers.attr('aria-expanded', 'true');
534					
535					self.config.afterOpen.call(self.target, self.element);
536				}
537				
538				e.preventDefault();
539				e.stopPropagation();
540			});
541			
542		}
543	}
544	
545	/**
546	 * UnfoldSlide constructor.
547	 *
548	 * @param {jQuery} element
549	 * @param {Object} config
550	 * @constructor
551	 */
552	function UnfoldJSlide(element, config) {
553		if (!AbstractUnfold.call(this, element, config)) return;
554		
555		this.target.addClass('u-unfold--jquery-slide u-unfold--hidden').hide();
556		
557		Object.defineProperty(this, 'defaultState', {
558			get: function () {
559				return this.target.hasClass('u-unfold--hidden');
560			}
561		});
562	}
563	
564	/**
565	 * Shows Unfold.
566	 *
567	 * @public
568	 * @return {UnfoldSimple}
569	 */
570	UnfoldSimple.prototype.show = function () {
571		
572		var activeEls = $(this)[0].config.unfoldTarget;
573		
574		$('[data-unfold-target="' + activeEls + '"]').addClass('active');
575		
576		this.smartPosition(this.target);
577		
578		this.target.removeClass('u-unfold--hidden');
579		if (this.allInvokers.length) this.allInvokers.attr('aria-expanded', 'true');
580		this.config.afterOpen.call(this.target, this.element);
581		
582		return this;
583	};
584	
585	/**
586	 * Hides Unfold.
587	 *
588	 * @public
589	 * @return {UnfoldSimple}
590	 */
591	UnfoldSimple.prototype.hide = function () {
592		
593		var activeEls = $(this)[0].config.unfoldTarget;
594		
595		$('[data-unfold-target="' + activeEls + '"]').removeClass('active');
596		
597		this.target.addClass('u-unfold--hidden');
598		if (this.allInvokers.length) this.allInvokers.attr('aria-expanded', 'false');
599		this.config.afterClose.call(this.target, this.element);
600		
601		return this;
602	};
603	
604	/**
605	 * Shows Unfold.
606	 *
607	 * @public
608	 * @return {UnfoldCSSAnimation}
609	 */
610	UnfoldCSSAnimation.prototype.show = function () {
611		
612		var self = this,
613			activeEls = $(self)[0].config.unfoldTarget;
614		
615		$('[data-unfold-target="' + activeEls + '"]').addClass('active');
616		
617		self.smartPosition(self.target);
618		
619		self.target.removeClass('u-unfold--hidden')
620			.removeClass(self.config.unfoldAnimationOut);
621		
622		if (!self.config.unfoldOverlay) {
623			
624			self.target.addClass(self.config.unfoldAnimationIn);
625			
626		} else {
627			
628			setTimeout(function () {
629				
630				self.target.addClass(self.config.unfoldAnimationIn);
631				
632			});
633			
634		}
635		
636		self.config.afterOpen.call(self.target, self.element);
637		
638	};
639	
640	/**
641	 * Hides Unfold.
642	 *
643	 * @public
644	 * @return {UnfoldCSSAnimation}
645	 */
646	UnfoldCSSAnimation.prototype.hide = function () {
647		
648		var activeEls = $(this)[0].config.unfoldTarget;
649		
650		$('[data-unfold-target="' + activeEls + '"]').removeClass('active');
651		
652		this.target.removeClass(this.config.unfoldAnimationIn)
653			.addClass(this.config.unfoldAnimationOut);
654		
655	};
656	
657	/**
658	 * Shows Unfold.
659	 *
660	 * @public
661	 * @return {UnfoldJSlide}
662	 */
663	UnfoldJSlide.prototype.show = function () {
664		
665		var self = this;
666		
667		var activeEls = $(this)[0].config.unfoldTarget;
668		
669		$('[data-unfold-target="' + activeEls + '"]').addClass('active');
670		
671		this.smartPosition(this.target);
672		
673		this.target.removeClass('u-unfold--hidden').stop().slideDown({
674			duration: self.config.unfoldDuration,
675			easing: self.config.unfoldEasing,
676			complete: function () {
677				self.config.afterOpen.call(self.target, self.element);
678			}
679		});
680		
681	};
682	
683	/**
684	 * Hides Unfold.
685	 *
686	 * @public
687	 * @return {UnfoldJSlide}
688	 */
689	UnfoldJSlide.prototype.hide = function () {
690		
691		var self = this;
692		
693		var activeEls = $(this)[0].config.unfoldTarget;
694		
695		$('[data-unfold-target="' + activeEls + '"]').removeClass('active');
696		
697		this.target.slideUp({
698			duration: self.config.unfoldDuration,
699			easing: self.config.unfoldEasing,
700			complete: function () {
701				self.config.afterClose.call(self.target, self.element);
702				self.target.addClass('u-unfold--hidden');
703			}
704		});
705		
706	}
707	
708})(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.