PageSourceSearch

https://e-engine.de/wp-content/plugins/post-carousel-pro/public/assets/js/remodal.js?ver=1.2.13

js e-engine.de collected 2026-10-07 14:42:43 UTC 19,147 bytes, 838 lines download raw bytes

vendor: 19,147 bytes, lines 1-838
1 ! (function(root, factory) {
2	if (typeof define === 'function' && define.amd) {
3		define(
4			['jquery'], function($) {
5				return factory( root, $ );
6			}
7		);
8	} else if (typeof exports === 'object') {
9		factory( root, require( 'jquery' ) );
10	} else {
11		factory( root, root.jQuery || root.Zepto );
12	}
13})(
14	this, function(global, $) {
15
16		'use strict';
17
18		/**
19		 * Name of the plugin
20		 *
21		 * @private
22		 * @const
23		 * @type {String}
24		 */
25		var PLUGIN_NAME = 'remodal';
26
27		/**
28		 * Namespace for CSS and events
29		 *
30		 * @private
31		 * @const
32		 * @type {String}
33		 */
34		var NAMESPACE = global.REMODAL_GLOBALS && global.REMODAL_GLOBALS.NAMESPACE || PLUGIN_NAME;
35
36		/**
37		 * Animationstart event with vendor prefixes
38		 *
39		 * @private
40		 * @const
41		 * @type {String}
42		 */
43		var ANIMATIONSTART_EVENTS = $.map(
44			['animationstart', 'webkitAnimationStart', 'MSAnimationStart', 'oAnimationStart'],
45			function(eventName) {
46				return eventName + '.' + NAMESPACE;
47			}
48		).join( ' ' );
49
50		/**
51		 * Animationend event with vendor prefixes
52		 *
53		 * @private
54		 * @const
55		 * @type {String}
56		 */
57		var ANIMATIONEND_EVENTS = $.map(
58			['animationend', 'webkitAnimationEnd', 'MSAnimationEnd', 'oAnimationEnd'],
59			function(eventName) {
60				return eventName + '.' + NAMESPACE;
61			}
62		).join( ' ' );
63
64		/**
65		 * Default settings
66		 *
67		 * @private
68		 * @const
69		 * @type {Object}
70		 */
71		var DEFAULTS = $.extend(
72			{
73				hashTracking: true,
74				closeOnConfirm: true,
75				closeOnCancel: true,
76				closeOnEscape: true,
77				closeOnOutsideClick: true,
78				modifier: '',
79				appendTo: null
80			}, global.REMODAL_GLOBALS && global.REMODAL_GLOBALS.DEFAULTS
81		);
82
83		/**
84		 * States of the Remodal
85		 *
86		 * @private
87		 * @const
88		 * @enum {String}
89		 */
90		var STATES = {
91			CLOSING: 'closing',
92			CLOSED: 'closed',
93			OPENING: 'opening',
94			OPENED: 'opened'
95		};
96
97		/**
98		 * Reasons of the state change.
99		 *
100		 * @private
101		 * @const
102		 * @enum {String}
103		 */
104		var STATE_CHANGE_REASONS = {
105			CONFIRMATION: 'confirmation',
106			CANCELLATION: 'cancellation'
107		};
108
109		/**
110		 * Is animation supported?
111		 *
112		 * @private
113		 * @const
114		 * @type {Boolean}
115		 */
116		var IS_ANIMATION = (function() {
117			var style = document.createElement( 'div' ).style;
118
119			return style.animationName !== undefined ||
120			style.WebkitAnimationName !== undefined ||
121			style.MozAnimationName !== undefined ||
122			style.msAnimationName !== undefined ||
123			style.OAnimationName !== undefined;
124		})();
125
126		/**
127		 * Is iOS?
128		 *
129		 * @private
130		 * @const
131		 * @type {Boolean}
132		 */
133		var IS_IOS = /iPad|iPhone|iPod/.test( navigator.platform );
134
135		/**
136		 * Current modal
137		 *
138		 * @private
139		 * @type {Remodal}
140		 */
141		var current;
142
143		/**
144		 * Scrollbar position
145		 *
146		 * @private
147		 * @type {Number}
148		 */
149		var scrollTop;
150
151		/**
152		 * Returns an animation duration
153		 *
154		 * @private
155		 * @param {jQuery} $elem
156		 * @returns {Number}
157		 */
158		function getAnimationDuration($elem) {
159			if (
160			IS_ANIMATION &&
161			$elem.css( 'animation-name' ) === 'none' &&
162			$elem.css( '-webkit-animation-name' ) === 'none' &&
163			$elem.css( '-moz-animation-name' ) === 'none' &&
164			$elem.css( '-o-animation-name' ) === 'none' &&
165			$elem.css( '-ms-animation-name' ) === 'none'
166			) {
167				return 0;
168			}
169
170			var duration = $elem.css( 'animation-duration' ) ||
171			$elem.css( '-webkit-animation-duration' ) ||
172			$elem.css( '-moz-animation-duration' ) ||
173			$elem.css( '-o-animation-duration' ) ||
174			$elem.css( '-ms-animation-duration' ) ||
175			'0s';
176
177			var delay = $elem.css( 'animation-delay' ) ||
178			$elem.css( '-webkit-animation-delay' ) ||
179			$elem.css( '-moz-animation-delay' ) ||
180			$elem.css( '-o-animation-delay' ) ||
181			$elem.css( '-ms-animation-delay' ) ||
182			'0s';
183
184			var iterationCount = $elem.css( 'animation-iteration-count' ) ||
185			$elem.css( '-webkit-animation-iteration-count' ) ||
186			$elem.css( '-moz-animation-iteration-count' ) ||
187			$elem.css( '-o-animation-iteration-count' ) ||
188			$elem.css( '-ms-animation-iteration-count' ) ||
189			'1';
190
191			var max;
192			var len;
193			var num;
194			var i;
195
196			duration       = duration.split( ', ' );
197			delay          = delay.split( ', ' );
198			iterationCount = iterationCount.split( ', ' );
199
200			// The 'duration' size is the same as the 'delay' size
201			for (i = 0, len = duration.length, max = Number.NEGATIVE_INFINITY; i < len; i++) {
202				num = parseFloat( duration[i] ) * parseInt( iterationCount[i], 10 ) + parseFloat( delay[i] );
203
204				if (num > max) {
205					max = num;
206				}
207			}
208
209			return max;
210		}
211
212		/**
213		 * Returns a scrollbar width
214		 *
215		 * @private
216		 * @returns {Number}
217		 */
218		function getScrollbarWidth() {
219			if ($( document ).height() <= $( window ).height()) {
220				return 0;
221			}
222
223			var outer = document.createElement( 'div' );
224			var inner = document.createElement( 'div' );
225			var widthNoScroll;
226			var widthWithScroll;
227
228			outer.style.visibility = 'hidden';
229			outer.style.width      = '100px';
230			document.body.appendChild( outer );
231
232			widthNoScroll = outer.offsetWidth;
233
234			// Force scrollbars
235			outer.style.overflow = 'scroll';
236
237			// Add inner div
238			inner.style.width = '100%';
239			outer.appendChild( inner );
240
241			widthWithScroll = inner.offsetWidth;
242
243			// Remove divs
244			outer.parentNode.removeChild( outer );
245
246			return widthNoScroll - widthWithScroll;
247		}
248
249		/**
250		 * Locks the screen
251		 *
252		 * @private
253		 */
254		function lockScreen() {
255			if (IS_IOS) {
256				return;
257			}
258
259			var $html       = $( 'html' );
260			var lockedClass = namespacify( 'is-locked' );
261			var paddingRight;
262			var $body;
263
264			if ( ! $html.hasClass( lockedClass )) {
265				$body = $( document.body );
266
267				// Zepto does not support '-=', '+=' in the `css` method
268				paddingRight = parseInt( $body.css( 'padding-right' ), 10 ) + getScrollbarWidth();
269
270				$body.css( 'padding-right', paddingRight + 'px' );
271				$html.addClass( lockedClass );
272			}
273		}
274
275		/**
276		 * Unlocks the screen
277		 *
278		 * @private
279		 */
280		function unlockScreen() {
281			if (IS_IOS) {
282				return;
283			}
284
285			var $html       = $( 'html' );
286			var lockedClass = namespacify( 'is-locked' );
287			var paddingRight;
288			var $body;
289
290			if ($html.hasClass( lockedClass )) {
291				$body = $( document.body );
292
293				// Zepto does not support '-=', '+=' in the `css` method
294				paddingRight = parseInt( $body.css( 'padding-right' ), 10 ) - getScrollbarWidth();
295
296				$body.css( 'padding-right', paddingRight + 'px' );
297				$html.removeClass( lockedClass );
298			}
299		}
300
301		/**
302		 * Sets a state for an instance
303		 *
304		 * @private
305		 * @param {Remodal} instance
306		 * @param {STATES} state
307		 * @param {Boolean} isSilent If true, Remodal does not trigger events
308		 * @param {String} Reason of a state change.
309		 */
310		function setState(instance, state, isSilent, reason) {
311
312			var newState  = namespacify( 'is', state );
313			var allStates = [namespacify( 'is', STATES.CLOSING ),
314					 namespacify( 'is', STATES.OPENING ),
315					 namespacify( 'is', STATES.CLOSED ),
316					 namespacify( 'is', STATES.OPENED )].join( ' ' );
317
318			instance.$bg
319			.removeClass( allStates )
320			.addClass( newState );
321
322			instance.$overlay
323			.removeClass( allStates )
324			.addClass( newState );
325
326			instance.$wrapper
327			.removeClass( allStates )
328			.addClass( newState );
329
330			instance.$modal
331			.removeClass( allStates )
332			.addClass( newState );
333
334			instance.state = state;
335			! isSilent && instance.$modal.trigger(
336				{
337					type: state,
338					reason: reason
339				}, [{ reason: reason }]
340			);
341		}
342
343		/**
344		 * Synchronizes with the animation
345		 *
346		 * @param {Function} doBeforeAnimation
347		 * @param {Function} doAfterAnimation
348		 * @param {Remodal} instance
349		 */
350		function syncWithAnimation(doBeforeAnimation, doAfterAnimation, instance) {
351			var runningAnimationsCount = 0;
352
353			var handleAnimationStart = function(e) {
354				if (e.target !== this) {
355					return;
356				}
357
358				runningAnimationsCount++;
359			};
360
361			var handleAnimationEnd = function(e) {
362				if (e.target !== this) {
363					return;
364				}
365
366				if (--runningAnimationsCount === 0) {
367
368					// Remove event listeners
369					$.each(
370						['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
371							instance[elemName].off( ANIMATIONSTART_EVENTS + ' ' + ANIMATIONEND_EVENTS );
372						}
373					);
374
375					doAfterAnimation();
376				}
377			};
378
379			$.each(
380				['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
381					instance[elemName]
382					.on( ANIMATIONSTART_EVENTS, handleAnimationStart )
383					.on( ANIMATIONEND_EVENTS, handleAnimationEnd );
384				}
385			);
386
387			doBeforeAnimation();
388
389			// If the animation is not supported by a browser or its duration is 0
390			if (
391			getAnimationDuration( instance.$bg ) === 0 &&
392			getAnimationDuration( instance.$overlay ) === 0 &&
393			getAnimationDuration( instance.$wrapper ) === 0 &&
394			getAnimationDuration( instance.$modal ) === 0
395			) {
396
397				// Remove event listeners
398				$.each(
399					['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
400						instance[elemName].off( ANIMATIONSTART_EVENTS + ' ' + ANIMATIONEND_EVENTS );
401					}
402				);
403
404				doAfterAnimation();
405			}
406		}
407
408		/**
409		 * Closes immediately
410		 *
411		 * @private
412		 * @param {Remodal} instance
413		 */
414		function halt(instance) {
415			if (instance.state === STATES.CLOSED) {
416				return;
417			}
418
419			$.each(
420				['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
421					instance[elemName].off( ANIMATIONSTART_EVENTS + ' ' + ANIMATIONEND_EVENTS );
422				}
423			);
424
425			instance.$bg.removeClass( instance.settings.modifier );
426			instance.$overlay.removeClass( instance.settings.modifier ).hide();
427			instance.$wrapper.hide();
428			unlockScreen();
429			setState( instance, STATES.CLOSED, true );
430		}
431
432		/**
433		 * Parses a string with options
434		 *
435		 * @private
436		 * @param str
437		 * @returns {Object}
438		 */
439		function parseOptions(str) {
440			var obj = {};
441			var arr;
442			var len;
443			var val;
444			var i;
445
446			// Remove spaces before and after delimiters
447			str = str.replace( /\s*:\s*/g, ':' ).replace( /\s*,\s*/g, ',' );
448
449			// Parse a string
450			arr = str.split( ',' );
451			for (i = 0, len = arr.length; i < len; i++) {
452				arr[i] = arr[i].split( ':' );
453				val    = arr[i][1];
454
455				// Convert a string value if it is like a boolean
456				if (typeof val === 'string' || val instanceof String) {
457					val = val === 'true' || (val === 'false' ? false : val);
458				}
459
460				// Convert a string value if it is like a number
461				if (typeof val === 'string' || val instanceof String) {
462					val = ! isNaN( val ) ? +val : val;
463				}
464
465				obj[arr[i][0]] = val;
466			}
467
468			return obj;
469		}
470
471		/**
472		 * Generates a string separated by dashes and prefixed with NAMESPACE
473		 *
474		 * @private
475		 * @param {...String}
476		 * @returns {String}
477		 */
478		function namespacify() {
479			var result = NAMESPACE;
480
481			for (var i = 0; i < arguments.length; ++i) {
482				result += '-' + arguments[i];
483			}
484
485			return result;
486		}
487
488		/**
489		 * Handles the hashchange event
490		 *
491		 * @private
492		 * @listens hashchange
493		 */
494		function handleHashChangeEvent() {
495			var id = location.hash.replace( '#', '' );
496			var instance;
497			var $elem;
498
499			if ( ! id) {
500
501				// Check if we have currently opened modal and animation was completed
502				if (current && current.state === STATES.OPENED && current.settings.hashTracking) {
503					current.close();
504				}
505			} else {
506
507				// Catch syntax error if your hash is bad
508				try {
509					$elem = $(
510						'[data-' + PLUGIN_NAME + '-id="' + id + '"]'
511					);
512				} catch (err) {
513				}
514
515				if ($elem && $elem.length) {
516					instance = $[PLUGIN_NAME].lookup[$elem.data( PLUGIN_NAME )];
517
518					if (instance && instance.settings.hashTracking) {
519						instance.open();
520					}
521				}
522
523			}
524		}
525
526		/**
527		 * Remodal constructor
528		 *
529		 * @constructor
530		 * @param {jQuery} $modal
531		 * @param {Object} options
532		 */
533		function Remodal($modal, options) {
534			var $body     = $( document.body );
535			var $appendTo = $body;
536			var remodal   = this;
537
538			remodal.settings = $.extend( {}, DEFAULTS, options );
539			remodal.index    = $[PLUGIN_NAME].lookup.push( remodal ) - 1;
540			remodal.state    = STATES.CLOSED;
541
542			remodal.$overlay = $( '.' + namespacify( 'overlay' ) );
543
544			if (remodal.settings.appendTo !== null && remodal.settings.appendTo.length) {
545				$appendTo = $( remodal.settings.appendTo );
546			}
547
548			if ( ! remodal.$overlay.length) {
549				remodal.$overlay = $( '<div>' ).addClass( namespacify( 'overlay' ) + ' ' + namespacify( 'is', STATES.CLOSED ) ).hide();
550				$appendTo.append( remodal.$overlay );
551			}
552
553			remodal.$bg = $( '.' + namespacify( 'bg' ) ).addClass( namespacify( 'is', STATES.CLOSED ) );
554
555			remodal.$modal = $modal
556			.addClass(
557				NAMESPACE + ' ' +
558				namespacify( 'is-initialized' ) + ' ' +
559				remodal.settings.modifier + ' ' +
560				namespacify( 'is', STATES.CLOSED )
561			)
562			.attr( 'tabindex', '-1' );
563
564			remodal.$wrapper = $( '<div>' )
565			.addClass(
566				namespacify( 'wrapper' ) + ' ' +
567				remodal.settings.modifier + ' ' +
568				namespacify( 'is', STATES.CLOSED )
569			)
570			.hide()
571			.append( remodal.$modal );
572			$appendTo.append( remodal.$wrapper );
573
574			// Add the event listener for the close button
575			remodal.$wrapper.on(
576				'click.' + NAMESPACE, '[data-' + PLUGIN_NAME + '-action="close"]', function(e) {
577					e.preventDefault();
578
579					remodal.close();
580				}
581			);
582
583			// Add the event listener for the cancel button
584			remodal.$wrapper.on(
585				'click.' + NAMESPACE, '[data-' + PLUGIN_NAME + '-action="cancel"]', function(e) {
586					e.preventDefault();
587
588					remodal.$modal.trigger( STATE_CHANGE_REASONS.CANCELLATION );
589
590					if (remodal.settings.closeOnCancel) {
591						remodal.close( STATE_CHANGE_REASONS.CANCELLATION );
592					}
593				}
594			);
595
596			// Add the event listener for the confirm button
597			remodal.$wrapper.on(
598				'click.' + NAMESPACE, '[data-' + PLUGIN_NAME + '-action="confirm"]', function(e) {
599					e.preventDefault();
600
601					remodal.$modal.trigger( STATE_CHANGE_REASONS.CONFIRMATION );
602
603					if (remodal.settings.closeOnConfirm) {
604						remodal.close( STATE_CHANGE_REASONS.CONFIRMATION );
605					}
606				}
607			);
608
609			// Add the event listener for the overlay
610			remodal.$wrapper.on(
611				'click.' + NAMESPACE, function(e) {
612					var $target = $( e.target );
613
614					if ( ! $target.hasClass( namespacify( 'wrapper' ) )) {
615						return;
616					}
617
618					if (remodal.settings.closeOnOutsideClick) {
619						remodal.close();
620					}
621				}
622			);
623		}
624
625		/**
626		 * Opens a modal window
627		 *
628		 * @public
629		 */
630		Remodal.prototype.open = function() {
631			var remodal = this;
632			var id;
633
634			// Check if the animation was completed
635			if (remodal.state === STATES.OPENING || remodal.state === STATES.CLOSING) {
636				return;
637			}
638
639			id = remodal.$modal.attr( 'data-' + PLUGIN_NAME + '-id' );
640
641			if (id && remodal.settings.hashTracking) {
642				scrollTop     = $( window ).scrollTop();
643				location.hash = id;
644			}
645
646			if (current && current !== remodal) {
647				halt( current );
648			}
649
650			current = remodal;
651			lockScreen();
652			remodal.$bg.addClass( remodal.settings.modifier );
653			remodal.$overlay.addClass( remodal.settings.modifier ).show();
654			remodal.$wrapper.show().scrollTop( 0 );
655			remodal.$modal.focus();
656
657			syncWithAnimation(
658				function() {
659					setState( remodal, STATES.OPENING );
660				},
661				function() {
662					setState( remodal, STATES.OPENED );
663				},
664				remodal
665			);
666		};
667
668		/**
669		 * Closes a modal window
670		 *
671		 * @public
672		 * @param {String} reason
673		 */
674		Remodal.prototype.close = function(reason) {
675			var remodal = this;
676
677			// Check if the animation was completed
678			if (remodal.state === STATES.OPENING || remodal.state === STATES.CLOSING || remodal.state === STATES.CLOSED) {
679				return;
680			}
681
682			if (
683			remodal.settings.hashTracking &&
684			remodal.$modal.attr( 'data-' + PLUGIN_NAME + '-id' ) === location.hash.substr( 1 )
685			) {
686				location.hash = '';
687				$( window ).scrollTop( scrollTop );
688			}
689
690			syncWithAnimation(
691				function() {
692					setState( remodal, STATES.CLOSING, false, reason );
693				},
694				function() {
695					remodal.$bg.removeClass( remodal.settings.modifier );
696					remodal.$overlay.removeClass( remodal.settings.modifier ).hide();
697					remodal.$wrapper.hide();
698					unlockScreen();
699
700					setState( remodal, STATES.CLOSED, false, reason );
701				},
702				remodal
703			);
704		};
705
706		/**
707		 * Returns a current state of a modal
708		 *
709		 * @public
710		 * @returns {STATES}
711		 */
712		Remodal.prototype.getState = function() {
713			return this.state;
714		};
715
716		/**
717		 * Destroys a modal
718		 *
719		 * @public
720		 */
721		Remodal.prototype.destroy = function() {
722			var lookup = $[PLUGIN_NAME].lookup;
723			var instanceCount;
724
725			halt( this );
726			this.$wrapper.remove();
727
728			delete lookup[this.index];
729			instanceCount = $.grep(
730				lookup, function(instance) {
731					return ! ! instance;
732				}
733			).length;
734
735			if (instanceCount === 0) {
736				this.$overlay.remove();
737				this.$bg.removeClass(
738					namespacify( 'is', STATES.CLOSING ) + ' ' +
739					namespacify( 'is', STATES.OPENING ) + ' ' +
740					namespacify( 'is', STATES.CLOSED ) + ' ' +
741					namespacify( 'is', STATES.OPENED )
742				);
743			}
744		};
745
746		/**
747	* Special plugin object for instances
748	*
749	* @public
750	* @type {Object}
751	*/
752		$[PLUGIN_NAME] = {
753			lookup: []
754		};
755
756		/**
757	* Plugin constructor
758	*
759	* @constructor
760	* @param {Object} options
761	* @returns {JQuery}
762	*/
763		$.fn[PLUGIN_NAME] = function(opts) {
764			var instance;
765			var $elem;
766
767			this.each(
768				function(index, elem) {
769					$elem = $( elem );
770
771					if ($elem.data( PLUGIN_NAME ) == null) {
772						instance = new Remodal( $elem, opts );
773						$elem.data( PLUGIN_NAME, instance.index );
774
775						if (
776						instance.settings.hashTracking &&
777						$elem.attr( 'data-' + PLUGIN_NAME + '-id' ) === location.hash.substr( 1 )
778						) {
779							instance.open();
780						}
781					} else {
782						instance = $[PLUGIN_NAME].lookup[$elem.data( PLUGIN_NAME )];
783					}
784				}
785			);
786
787			return instance;
788		};
789
790		$( document ).ready(
791			function() {
792
793				// data-remodal-target opens a modal window with the special Id
794				$( document ).on(
795					'click', '[data-' + PLUGIN_NAME + '-target]', function(e) {
796						e.preventDefault();
797
798						var elem    = e.currentTarget;
799						var id      = elem.getAttribute( 'data-' + PLUGIN_NAME + '-target' );
800						var $target = $( '[data-' + PLUGIN_NAME + '-id="' + id + '"]' );
801
802						$[PLUGIN_NAME].lookup[$target.data( PLUGIN_NAME )].open();
803					}
804				);
805
806				// Auto initialization of modal windows
807				// They should have the 'remodal' class attribute
808				// Also you can write the `data-remodal-options` attribute to pass params into the modal
809				$( document ).find( '.' + NAMESPACE ).each(
810					function(i, container) {
811						var $container = $( container );
812						var options    = $container.data( PLUGIN_NAME + '-options' );
813
814						if ( ! options) {
815							options = {};
816						} else if (typeof options === 'string' || options instanceof String) {
817							options = parseOptions( options );
818						}
819
820						$container[PLUGIN_NAME](options);
821					}
822				);
823
824				// Handles the keydown event
825				$( document ).on(
826					'keydown.' + NAMESPACE, function(e) {
827						if (current && current.settings.closeOnEscape && current.state === STATES.OPENED && e.keyCode === 27) {
828							current.close();
829						}
830					}
831				);
832
833				// Handles the hashchange event
834				$( window ).on( 'hashchange.' + NAMESPACE, handleHashChangeEvent );
835			}
836		);
837	}
838);

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.