PageSourceSearch

https://institutopedroruiz.com.br/wp-content/plugins/jet-elements/assets/js/jet-elements.js?ver=2.8.2

js institutopedroruiz.com.br collected 2026-10-06 04:45:58 UTC 41,027 bytes, 1,308 lines download raw bytes

1( function( $, elementor ) {
2
3	"use strict";
4
5	var JetElements = {
6
7		callWidget: function ( fnName ) {
8
9            return function ( $scope ) {
10
11                if ( typeof window[fnName] !== 'function' ) {
12                    return;
13                }
14
15                window[fnName]( $scope );
16            };
17        },
18		
19		addedScripts: {},
20
21		addedStyles: {},
22
23		addedAssetsPromises: [],
24
25		init: function() {
26			
27			var widgets = {
28                'jet-carousel.default': JetElements.callWidget( 'widgetCarousel' ),
29                'jet-circle-progress.default': JetElements.callWidget( 'widgetProgress' ),
30                'jet-map.default': JetElements.callWidget( 'widgetMap' ),
31                'jet-countdown-timer.default': JetElements.callWidget( 'widgetCountdown' ),
32                'jet-posts.default': JetElements.callWidget( 'widgetPosts' ),
33                'jet-animated-text.default': JetElements.callWidget( 'widgetAnimatedText' ),
34                'jet-animated-box.default': JetElements.callWidget( 'widgetAnimatedBox' ),
35                'jet-images-layout.default': JetElements.callWidget( 'widgetImagesLayout' ),
36                'jet-slider.default': JetElements.callWidget( 'widgetSlider' ),
37                'jet-testimonials.default': JetElements.callWidget( 'widgetTestimonials' ),
38                'jet-image-comparison.default': JetElements.callWidget( 'widgetImageComparison' ),
39                'jet-instagram-gallery.default': JetElements.callWidget( 'widgetInstagramGallery' ),
40                'jet-scroll-navigation.default': JetElements.callWidget( 'widgetScrollNavigation' ),
41                'jet-subscribe-form.default': JetElements.callWidget( 'widgetSubscribeForm' ),
42                'jet-progress-bar.default': JetElements.callWidget( 'widgetProgressBar' ),
43                'jet-portfolio.default': JetElements.callWidget( 'widgetPortfolio' ),
44                'jet-timeline.default': JetElements.callWidget( 'widgetTimeLine' ),
45                'jet-table.default': JetElements.callWidget( 'widgetTable' ),
46                'jet-dropbar.default': JetElements.callWidget( 'widgetDropbar' ),
47                'jet-video.default': JetElements.callWidget( 'widgetVideo' ),
48                'jet-audio.default': JetElements.callWidget( 'widgetAudio' ),
49                'jet-horizontal-timeline.default': JetElements.callWidget( 'widgetHorizontalTimeline' ),
50                'mp-timetable.default': JetElements.callWidget( 'widgetTimeTable' ),
51                'jet-pie-chart.default': JetElements.callWidget( 'widgetPieChart' ),
52                'jet-bar-chart.default': JetElements.callWidget( 'widgetBarChart' ),
53                'jet-line-chart.default': JetElements.callWidget( 'widgetLineChart' ),
54                'jet-lottie.default': JetElements.callWidget( 'widgetLottie' ),
55                'jet-pricing-table.default': JetElements.callWidget( 'widgetPricingTable' ),
56            };
57
58            $.each(widgets, function ( widget, callback ) {
59                elementorFrontend.hooks.addAction(
60                    'frontend/element_ready/' + widget,
61                    callback
62                );
63            });
64
65            elementorFrontend.hooks.addAction(
66                'frontend/element_ready/section',
67                JetElements.elementorSection
68            );
69
70            elementorFrontend.hooks.addAction(
71                'frontend/element_ready/container',
72                JetElements.elementorSection
73            );
74
75			// Re-init widgets in nested tabs
76			window.elementorFrontend.elements.$window.on(
77				'elementor/nested-tabs/activate',
78				( event, content ) => {
79
80					const $content = $( content );										
81					requestAnimationFrame(() => {
82						JetElements.reinitSlickSlider( $content );
83						JetElements.initWidgetsHandlers( $content );
84					});
85				}
86			);
87
88			elementorFrontend.hooks.addAction( 'frontend/element_ready/loop-carousel.post', function ( $scope ) {
89					
90				var $loopCarousel = $scope.find('.swiper');
91		
92				if ( !$loopCarousel.length ) return;
93		
94				var swiperEl = $loopCarousel[0];
95				var checkSwiper = setInterval(function () {
96					if ( !swiperEl.swiper ) return;
97		
98					clearInterval( checkSwiper );
99					var swiperInstance = swiperEl.swiper;
100		
101					var $audioControls = $scope.find(
102						'.mejs-time-slider, .mejs-horizontal-volume-slider, .mejs-volume-button'
103					);
104		
105					if ( $audioControls.length ) {
106						// Fix swiper loop glitch when audio progress is active
107						if ( swiperInstance.params.loop && swiperInstance.params.slidesPerView === 1 ) {
108							swiperInstance.on('slideChangeTransitionEnd.audioFix', function () {
109								this.loopFix();
110							});
111						}
112		
113						// Disable swipe on audio interaction
114						$audioControls.off('.audioSwipe').on('pointerdown.audioSwipe', function ( event ) {
115								if ( event.button !== 0 ) return;
116								swiperInstance.allowTouchMove = false;
117								event.stopPropagation();
118							});
119		
120						// Re-enable swipe
121						$audioControls.on( 'pointerup.audioSwipe pointercancel.audioSwipe', function ( event ) {
122							if ( event.button !== 0 ) return;
123							setTimeout( function () {
124								swiperInstance.allowTouchMove = true;
125							}, 200 );
126							event.stopPropagation();
127						});
128					}
129				}, 50);
130			}
131		);
132
133		// Handle slider inside nested accordion
134		elementorFrontend.hooks.addAction( 'frontend/element_ready/nested-accordion.default', function ( $scope ) {
135			
136			$scope.find('.e-n-accordion-item').each(function() {
137				const item = this;
138				new MutationObserver(function(mutations) {
139					mutations.forEach(function(mutation) {
140						if ( mutation.type === 'attributes' && mutation.attributeName === 'open' && item.hasAttribute('open') ) {
141							$( item ).find('.slider-pro').each(function () {
142								$( this ).sliderPro('update');
143							});
144						}
145					});
146				}).observe(item, {
147					attributes: true,
148					attributeFilter: ['open']
149				});
150			});
151		} );
152		},	
153
154		reinitSlickSlider: function( $scope ) {
155
156			var $sliders = $scope.find(`
157				[data-widget_type="jet-carousel.default"] .slick-initialized,
158				[data-widget_type="jet-testimonials.default"] .slick-initialized,
159				[data-widget_type="jet-image-comparison.default"] .slick-initialized,
160				[data-widget_type="jet-posts.default"] .slick-initialized
161			`);
162
163			if ( $sliders.length ) {
164				$sliders.each( function() {
165					$( this ).slick('unslick');
166				} );
167			}
168		},
169
170		loadScriptAsync: function( script, uri ) {
171
172			if ( JetElements.addedScripts.hasOwnProperty( script ) ) {
173				return script;
174			}
175
176			if ( !uri ) {
177				return;
178			}
179
180			JetElements.addedScripts[ script ] = uri;
181
182			return new Promise( function( resolve, reject ) {
183				var tag = document.createElement( 'script' );
184
185				tag.src    = uri;
186				tag.async  = true;
187				tag.onload = function() {
188					resolve( script );
189				};
190
191				document.head.appendChild( tag );
192			});
193		},
194
195		loadStyle: function( style, uri ) {
196
197
198			if ( JetElements.addedStyles.hasOwnProperty( style ) && JetElements.addedStyles[ style ] ===  uri) {
199				return style;
200			}
201
202			if ( !uri ) {
203				return;
204			}
205
206			JetElements.addedStyles[ style ] = uri;
207
208			return new Promise( function( resolve, reject ) {
209				var tag = document.createElement( 'link' );
210
211				tag.id      = style;
212				tag.rel     = 'stylesheet';
213				tag.href    = uri;
214				tag.type    = 'text/css';
215				tag.media   = 'all';
216				tag.onload  = function() {
217					resolve( style );
218				};
219
220				document.head.appendChild( tag );
221			});
222		},
223
224		initWidgetsHandlers: function( $selector ) {
225
226			$selector.find( '.elementor-widget-jet-slider, .elementor-widget-jet-testimonials, .elementor-widget-jet-carousel, .elementor-widget-jet-portfolio, .elementor-widget-jet-horizontal-timeline, .elementor-widget-jet-image-comparison, .elementor-widget-jet-posts, .jet-parallax-section' ).each( function() {
227				
228				var $this       = $( this ),
229					elementType = $this.data( 'element_type' );
230
231				if ( !elementType ) {
232					return;
233				}
234
235				if ( 'widget' === elementType ) {
236					elementType = $this.data( 'widget_type' );
237					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ );
238				}
239
240				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ );
241				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ );
242
243			} );
244		},
245
246		initElementsHandlers: function( $selector ) {
247			$selector.find( '[data-element_type]' ).each( function() {
248				var $this       = $( this ),
249					elementType = $this.data( 'element_type' );
250
251				if ( !elementType ) {
252					return;
253				}
254
255				if ( 'widget' === elementType ) {
256					elementType = $this.data( 'widget_type' );
257					window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ );
258				}
259
260				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ );
261				window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ );
262
263			} );
264		},
265
266		observer: function( $elements, callback, options = {} ) {
267			// Default options: activate a section when at least 50% of it is visible
268			const defaultOptions = {
269				threshold: 0.5,      // Activate when the element is more than half visible
270				triggerOnce: false,  // Continuously observe the element
271			};
272		
273			// Merge custom options with defaults
274			options = jQuery.extend( defaultOptions, options );
275
276			const observerOptions = {
277				root: null,         // Use the browser viewport as the container
278				rootMargin: '0px',  // No margin adjustment, relying solely on threshold
279				threshold: options.threshold
280			};
281		
282			// To determine scroll direction, store the previous Y-coordinate for each element
283			const previousY = new WeakMap();
284		
285			const observer = new IntersectionObserver(( entries ) => {
286				// First, determine the scroll direction for each entry
287				entries.forEach( entry => {
288					const currentY = entry.boundingClientRect.y;
289					const prevY = previousY.get( entry.target ) || currentY;
290					// Add a new property "direction" to the entry object
291					entry.direction = currentY < prevY ? 'down' : 'up';
292					previousY.set( entry.target, currentY );
293				});
294		
295				// Filter entries with an intersection ratio greater or equal to the threshold (e.g., 50%)
296				const visibleEntries = entries.filter( entry => entry.intersectionRatio >= options.threshold );
297		
298				// If there are visible entries, choose the one with the highest intersection ratio
299				if ( visibleEntries.length > 0 ) {
300					visibleEntries.sort(( a, b ) => b.intersectionRatio - a.intersectionRatio );
301					callback.call( visibleEntries[0].target, visibleEntries[0].direction, visibleEntries[0] );
302				}
303			}, observerOptions );
304		
305			// Attach the observer to every element in the collection
306			$elements.each( function() {
307				observer.observe( this );
308			});
309		
310			return observer;
311		},
312
313		prepareWaypointOptions: function( $scope, waypointOptions ) {
314			var options = waypointOptions || {},
315				$parentPopup = $scope.closest( '.jet-popup__container-inner, .elementor-popup-modal .dialog-message' );
316
317			if ( $parentPopup[0] ) {
318				options.context = $parentPopup[0];
319			}
320
321			return options;
322		},
323
324		widgetTimeTable: function( $scope ) {
325
326			var $mptt_shortcode_wrapper = $scope.find( '.mptt-shortcode-wrapper' );
327
328			if ( ( typeof typenow ) !== 'undefined' ) {
329				if ( pagenow === typenow ) {
330					switch ( typenow ) {
331
332						case 'mp-event':
333							Registry._get( 'Event' ).init();
334							break;
335
336						case 'mp-column':
337							Registry._get( 'Event' ).initDatePicker();
338							Registry._get( 'Event' ).columnRadioBox();
339							break;
340
341						default:
342							break;
343					}
344				}
345			}
346
347			if ( $mptt_shortcode_wrapper.length ) {
348
349				Registry._get( 'Event' ).initTableData();
350				Registry._get( 'Event' ).filterShortcodeEvents();
351				Registry._get( 'Event' ).getFilterByHash();
352
353				$mptt_shortcode_wrapper.show();
354			}
355
356			if ( $( '.upcoming-events-widget' ).length || $mptt_shortcode_wrapper.length ) {
357				Registry._get( 'Event' ).setColorSettings();
358			}
359		},
360
361		elementorSection: function( $scope ) {
362			var $target   = $scope,
363				instance  = null,
364				editMode  = Boolean( elementor.isEditMode() );
365
366				instance = new jetSectionParallax( $target );
367				instance.init();
368		},
369
370		initCarousel: function( $target, options ) {
371
372			var	defaultOptions,
373				slickOptions,
374				responsive        = [],
375				eTarget           = $target.closest( '.elementor-widget' ),
376				breakpoints       = JetElementsTools.getElementorElementSettings( eTarget ),
377				activeBreakpoints = elementor.config.responsive.activeBreakpoints,
378				dotsEnable        = options.dots,
379				accessibility     = true,
380				prevDeviceToShowValue,
381				prevDeviceToScrollValue,
382				slidesCount,
383				jetListing        = eTarget.closest( '.jet-listing-grid' ).hasClass( 'jet-listing' ),
384				jetListingItem    = eTarget.closest( '.jet-listing-grid__item' ),
385				jetnextArrow      = eTarget.find( '.prev-arrow' ),
386				jetprevArrow      = eTarget.find( '.next-arrow' ),
387				isMobileCheck     = JetElementsTools.mobileAndTabletcheck();
388
389			// Compatibility slick carousel with jet listing
390			if ( jetListing && jetListingItem ){
391
392				options.nextArrow = false;
393				options.prevArrow = false;
394
395				jetListingItem.find( jetnextArrow ).on( 'click', function () {
396					$target.slick( 'slickPrev' );
397				});
398
399				jetListingItem.find( jetprevArrow ).on( 'click', function () {
400					$target.slick( 'slickNext' );
401				});
402			}
403
404			if ( $target.hasClass( 'jet-image-comparison__instance' ) ) {
405				accessibility = false;
406				setTimeout( function() {
407					$target.on( 'beforeChange', function() {
408						var _this = $( this );
409
410						_this.find( '.slick-slide' ).each( function() {
411							$( this ).find( '.jx-controller' ).attr( 'tabindex', '' );
412							$( this ).find( '.jx-label').attr( 'tabindex', '' );
413						} );
414					} );
415
416					$target.on( 'afterChange', function() {
417						var _this = $(this);
418
419						_this.find( '.slick-slide.slick-active' ).each( function() {
420							$( this ).find( '.jx-controller' ).attr( 'tabindex', '0' );
421							$( this ).find( '.jx-label').attr( 'tabindex', 0 );
422						} );
423					} );
424
425				}, 100 );
426			}
427
428			if ( $target.hasClass( 'jet-posts' ) && $target.parent().hasClass( 'jet-carousel' ) ) {
429				function renameKeys( obj, newKeys ) {
430					const keyValues = Object.keys( obj ).map( key => {
431						const newKey = newKeys[key] || key;
432						return { [newKey]: obj[key] };
433					} );
434					return Object.assign( {}, ...keyValues );
435				}
436
437				var newBreakpointsKeys = {
438					columns: "slides_to_show",
439					columns_widescreen: "slides_to_show_widescreen",
440					columns_laptop: "slides_to_show_laptop",
441					columns_tablet_extra: "slides_to_show_tablet_extra",
442					columns_tablet: "slides_to_show_tablet",
443					columns_mobile_extra: "slides_to_show_mobile_extra",
444					columns_mobile: "slides_to_show_mobile"
445				};
446
447				breakpoints = renameKeys( breakpoints, newBreakpointsKeys );
448				slidesCount = $( '> div.jet-posts__item', $target ).length;
449			} else {
450				slidesCount = $( '> div', $target ).length;
451			}
452
453			options.slidesToShow   = +breakpoints.slides_to_show;
454			options.slidesToScroll = breakpoints.slides_to_scroll ? +breakpoints.slides_to_scroll : 1;
455
456			Object.keys( activeBreakpoints ).forEach( function( breakpointName ) {
457				if ( 'widescreen' === breakpointName ) {
458					options.slidesToShow = ( "slides_to_show_widescreen" in breakpoints ) && '' != breakpoints.slides_to_show_widescreen ? +breakpoints.slides_to_show_widescreen : +breakpoints.slides_to_show;
459
460					if ( ( "slides_to_scroll_widescreen" in breakpoints ) && '' != breakpoints.slides_to_scroll_widescreen ) {
461						options.slidesToScroll = +breakpoints.slides_to_scroll_widescreen;
462					} else {
463						if ( options.slidesToShow > +breakpoints.slides_to_scroll ) {
464							options.slidesToScroll = +breakpoints.slides_to_scroll;
465						} else {
466							options.slidesToScroll = options.slidesToShow;
467						}
468					}
469				}
470			} );
471
472			if ( options.slidesToShow >= slidesCount ) {
473				options.dots = false;
474			}
475
476			prevDeviceToShowValue   = options.slidesToShow;
477			prevDeviceToScrollValue = options.slidesToScroll;
478
479			setTimeout( function() {
480				$( '.slick-slide', $target ).each( function () {
481					if ( $(this).attr('aria-describedby') != undefined ) {
482						$( this ).attr('id', $( this ).attr( 'aria-describedby' ) );
483					}
484				} );
485
486				$( '.jet-slick-dots', $target ).removeAttr( 'role' );
487
488				$( '.jet-slick-dots li', $target ).each( function() {
489					$( this ).removeAttr( 'role' );
490					$( this ).attr( 'tabindex', '0' );
491				} );
492			}, 100 );
493
494			$target.on( 'init reInit', function() {
495				$( '.jet-slick-dots', $target ).removeAttr( 'role' );
496
497				$( '.jet-slick-dots li', $( this ) ).each( function() {
498					$( this ).removeAttr( 'role' );
499					$( this ).attr( 'tabindex', '0' );
500				} );
501
502				$( '.jet-slick-dots li', $( this ) ).keydown( function( e ) {
503					var $this   = $( this ),
504						$which  = e.which || e.keyCode;
505
506					if ( $which == 13 || $which == 32 ) {
507						$this.click();
508					}
509
510					if ( $which == 37 ) {
511						if ( 0 != $this.prev().length ) {
512							$this.prev().focus();
513							$this.prev().click();
514						}
515					}
516
517					if ( $which == 39 ) {
518						if ( 0 != $this.next().length ) {
519							$this.next().focus();
520							$this.next().click();
521						}
522					}
523				} );
524
525				$( '.jet-arrow', eTarget ).attr( 'tabindex', 0 );
526
527				$( '.jet-arrow', eTarget ).keydown( function( e ) {
528					var $this  = $( this ),
529						$which = e.which || e.keyCode;
530
531					if ( $which == 13 || $which == 32 ) {
532						$this.click();
533					}
534
535					if ( $which == 37 ) {
536						if ( 0 != $this.prev().length && $this.prev().hasClass( 'slick-arrow' ) ) {
537							$this.prev().focus();
538						}
539					}
540
541					if ( $which == 39 && $this.next().hasClass( 'slick-arrow' ) ) {
542						if ( 0 != $this.next().length ) {
543							$this.next().focus();
544						}
545					}
546				} );
547
548				if ( $target.hasClass( 'jet-image-comparison__instance' ) ) {
549					setTimeout( function() {
550						$target.find( '.slick-slide.slick-active' ).each( function() {
551							$( this ).find( '.jx-controller' ).attr( 'tabindex', '0' );
552							$( this ).find( '.jx-label').attr( 'tabindex', '0' );
553						} );
554					}, 100 );
555				}
556
557				//fix lazyload image loading
558				var slidesTrack = $( '.slick-track', $target );
559
560				slidesTrack.find( '.slick-slide' ).each( function() {
561
562					var _this   = $( this ),
563						itemImg = $( '.jet-carousel__item-img', _this );
564
565					var observer = new IntersectionObserver( function( entries ) {
566						if ( entries[0].isIntersecting === true ) {
567
568							itemImg.each( function() {
569								var attr = $( this ).attr( 'loading' );
570
571								if ( typeof attr !== 'undefined' && attr !== false ) {
572									if ( 0  === $( this ).width() ) {
573										$( this ).attr( 'loading', "" );
574									}
575								}
576							} )
577							observer.unobserve( entries[0].target );
578						}
579					}, { threshold: [0] } );
580
581					observer.observe( _this[0] );
582				} );
583
584				if ( options.infinite ) {
585					var $items        = $( this ),
586						$clonedSlides = $( '> .slick-list > .slick-track > .slick-cloned.jet-carousel__item', $items );
587
588					if ( !$clonedSlides.length ) {
589						return;
590					}
591
592					JetElements.initElementsHandlers( $clonedSlides );
593				}
594			} );
595
596			if ( $target.hasClass( 'slick-initialized' ) ) {
597				$target.not('.slick-initialized').slick('refresh', true );
598				return;
599			}
600
601			Object.keys( activeBreakpoints ).reverse().forEach( function( breakpointName ) {
602
603				if ( breakpoints['slides_to_show_' + breakpointName] || breakpoints['slides_to_scroll_' + breakpointName] ) {
604
605					var breakpointSetting = {
606						breakpoint: null,
607						settings: {}
608					}
609
610					breakpointSetting.breakpoint = 'widescreen' != breakpointName ? activeBreakpoints[breakpointName].value : activeBreakpoints[breakpointName].value - 1;
611
612					if ( 'widescreen' === breakpointName ) {
613						breakpointSetting.settings.slidesToShow   = +breakpoints['slides_to_show'];
614						breakpointSetting.settings.slidesToScroll = +breakpoints['slides_to_scroll'] ? +breakpoints['slides_to_scroll']: 1;
615
616					} else {
617						breakpointSetting.settings.slidesToShow = breakpoints['slides_to_show_' + breakpointName] ? +breakpoints['slides_to_show_' + breakpointName] : prevDeviceToShowValue;
618
619						breakpointSetting.settings.slidesToScroll = breakpoints['slides_to_scroll_' + breakpointName] ? +breakpoints['slides_to_scroll_' + breakpointName] : prevDeviceToScrollValue;
620					}
621
622					if ( breakpointSetting.settings.slidesToShow >= slidesCount ) {
623						breakpointSetting.settings.dots = false;
624					} else {
625						if ( dotsEnable ) {
626							breakpointSetting.settings.dots = true;
627						}
628					}
629
630					prevDeviceToShowValue   = breakpointSetting.settings.slidesToShow;
631					prevDeviceToScrollValue = breakpointSetting.settings.slidesToScroll
632
633					responsive.push( breakpointSetting );
634				}
635			} );
636
637			options.responsive = responsive;
638
639			if ( options.slidesToShow >= slidesCount ) {
640				options.dots = false;
641			}
642
643			// Disable variableWidth on mobile if it was requested
644
645			if ( isMobileCheck && options.variableWidth ) {
646				options.variableWidth = false;
647				options.centerMode = false;
648				options.slidesToScroll = 1;
649				options.slidesToShow = 1;
650			}
651
652			// Enable centerMode when variableWidth is active on desktop
653
654			else if ( options.variableWidth ) {
655				options.slidesToShow = 1;
656				options.centerMode = true;
657			}
658
659			defaultOptions = {
660				customPaging: function(slider, i) {
661					return $( '<span />' ).text( i + 1 );
662				},
663				dotsClass: 'jet-slick-dots',
664				accessibility: accessibility
665			};
666
667			slickOptions = $.extend( {}, defaultOptions, options );
668
669			$target.slick( slickOptions );
670
671			if ( $target.hasClass( 'jet-image-comparison__instance' ) ) {
672				let juxtaposeSlidersLength = window.juxtapose.sliders.length;
673
674				for ( let i = 0; i < juxtaposeSlidersLength; i++ ) {
675					window.juxtapose.sliders[i].setWrapperDimensions();
676				}
677			}
678		},
679	};
680
681	window.JetElements = JetElements;
682
683	$( window ).on( 'elementor/frontend/init', JetElements.init );
684
685	var JetElementsTools = {
686
687		getElementPercentageSeen: function( $element, offset ) {
688			var offsetSettings      = offset || {},
689				startOffset         = offsetSettings.start || 0,
690				endOffset           = offsetSettings.end || 0,
691				viewportHeight      = $( window ).height(),
692				viewportStartOffset = viewportHeight * startOffset / 100,
693				viewportEndOffset   = viewportHeight * endOffset / 100,
694				scrollTop           = $( window ).scrollTop(),
695				elementOffsetTop    = $element.offset().top,
696				elementHeight       = $element.height(),
697				percentage;
698
699			percentage = (scrollTop + viewportHeight + viewportStartOffset - elementOffsetTop) / (viewportHeight + viewportStartOffset + viewportEndOffset + elementHeight);
700			percentage = Math.min( 100, Math.max( 0, percentage * 100 ) );
701
702			return parseFloat( percentage.toFixed( 2 ) );
703		},
704
705		isRTL: function() {
706			return $( 'body' ).hasClass( 'rtl' );
707		},
708
709		inArray: function( needle, haystack ) {
710			return -1 < haystack.indexOf( needle );
711		},
712
713		debounce: function( threshold, callback ) {
714			var timeout;
715
716			return function debounced( $event ) {
717				function delayed() {
718					callback.call( this, $event );
719					timeout = null;
720				}
721
722				if ( timeout ) {
723					clearTimeout( timeout );
724				}
725
726				timeout = setTimeout( delayed, threshold );
727			};
728		},
729
730		getObjectNextKey: function( object, key ) {
731			var keys      = Object.keys( object ),
732				idIndex   = keys.indexOf( key ),
733				nextIndex = idIndex += 1;
734
735			if( nextIndex >= keys.length ) {
736				//we're at the end, there is no next
737				return false;
738			}
739
740			var nextKey = keys[ nextIndex ];
741
742			return nextKey;
743		},
744
745		getObjectPrevKey: function( object, key ) {
746			var keys      = Object.keys( object ),
747				idIndex   = keys.indexOf( key ),
748				prevIndex = idIndex -= 1;
749
750			if ( 0 > idIndex ) {
751				//we're at the end, there is no next
752				return false;
753			}
754
755			var prevKey = keys[ prevIndex ];
756
757			return prevKey;
758		},
759
760		getObjectFirstKey: function( object ) {
761			return Object.keys( object )[0];
762		},
763
764		getObjectLastKey: function( object ) {
765			return Object.keys( object )[ Object.keys( object ).length - 1 ];
766		},
767
768		getObjectValues: function( object ) {
769			var values;
770
771			if ( !Object.values ) {
772				values = Object.keys( object ).map( function( e ) {
773					return object[e]
774				} );
775
776				return values;
777			}
778
779			return Object.values( object );
780		},
781
782		validateEmail: function( email ) {
783			var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
784
785			return re.test( email );
786		},
787
788		mobileAndTabletcheck: function() {
789			var check = false;
790
791			(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
792
793			return check;
794		},
795
796		addThousandCommaSeparator: function ( nStr, separator ) {
797
798			var nStr      = nStr + '',
799				separator = separator.toString().replace(/[0-9]/g, ''),
800				x         = nStr.split('.'),
801				x1        = x[0],
802				x2        = x.length > 1 ? '.' + x[1] : '',
803				rgx       = /(\d+)(\d{3})/;
804
805			if ( '' === separator )	{
806				return nStr;
807			}
808
809			while ( rgx.test(x1) ) {
810				x1 = x1.replace(rgx, '$1' + separator + '$2');
811			}
812
813			return x1 + x2;
814		},
815
816		getElementorElementSettings: function( $scope ) {
817
818			if ( window.elementorFrontend && window.elementorFrontend.isEditMode() && $scope.hasClass( 'elementor-element-edit-mode' ) ) {
819				return JetElementsTools.getEditorElementSettings( $scope );
820			}
821
822			return $scope.data( 'settings' ) || {};
823		},
824
825		getEditorElementSettings: function( $scope ) {
826			var modelCID = $scope.data( 'model-cid' ),
827				elementData;
828
829			if ( ! modelCID ) {
830				return {};
831			}
832
833			if ( ! elementor.hasOwnProperty( 'config' ) ) {
834				return {};
835			}
836
837			if ( ! elementor.config.hasOwnProperty( 'elements' ) ) {
838				return {};
839			}
840
841			if ( ! elementor.config.elements.hasOwnProperty( 'data' ) ) {
842				return {};
843			}
844
845			elementData = elementor.config.elements.data[ modelCID ];
846
847			if ( ! elementData ) {
848				return {};
849			}
850
851			return elementData.toJSON();
852		}
853	}
854
855	window.JetElementsTools = JetElementsTools;
856
857	/**
858	 * jetSectionParallax Class
859	 *
860	 * @return {void}
861	 */
862	window.jetSectionParallax = function( $target ) {
863		var self             = this,
864			sectionId        = $target.data('id'),
865			settings         = false,
866			editMode         = Boolean( elementor.isEditMode() ),
867			$window          = $( window ),
868			$body            = $( 'body' ),
869			scrollLayoutList = [],
870			mouseLayoutList  = [],
871			winScrollTop     = $window.scrollTop(),
872			winHeight        = $window.height(),
873			requesScroll     = null,
874			requestMouse     = null,
875			tiltx            = 0,
876			tilty            = 0,
877			isSafari         = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/),
878			platform         = navigator.platform;
879
880		/**
881		 * Init
882		 */
883		self.init = function() {
884
885			if ( ! editMode ) {
886				settings = $target.data('settings') || false;
887				settings = false != settings ? settings['jet_parallax_layout_list'] : false;
888			} else {
889				settings = self.generateEditorSettings( $target );
890			}
891
892			if ( ! settings ) {
893				return false;
894			}
895
896			self.generateLayouts();
897
898			$window.on( 'resize.jetSectionParallax orientationchange.jetSectionParallax', JetElementsTools.debounce( 30, self.generateLayouts ) );
899
900			if ( 0 !== scrollLayoutList.length ) {
901				$window.on( 'scroll.jetSectionParallax resize.jetSectionParallax', self.scrollHandler );
902			}
903
904			if ( 0 !== mouseLayoutList.length ) {
905				$target.on( 'mousemove.jetSectionParallax resize.jetSectionParallax', self.mouseMoveHandler );
906				$target.on( 'mouseleave.jetSectionParallax', self.mouseLeaveHandler );
907			}
908
909			self.scrollUpdate();
910		};
911
912		self.generateEditorSettings = function( $target ) {
913			var editorElements      = null,
914				sectionsData        = {},
915				sectionData         = {},
916				sectionParallaxData = {},
917				settings            = [];
918
919			if ( ! window.elementor.hasOwnProperty( 'elements' ) ) {
920				return false;
921			}
922
923			sectionData = JetElementsTools.getElementorElementSettings( $target );
924
925			if ( ! sectionData.hasOwnProperty( 'jet_parallax_layout_list' ) || 0 === Object.keys( sectionData ).length ) {
926				return false;
927			}
928
929			sectionParallaxData = sectionData[ 'jet_parallax_layout_list' ];
930
931			$.each( sectionParallaxData, function( index, obj ) {
932				settings.push( obj );
933			} );
934
935			if ( 0 !== settings.length ) {
936				return settings;
937			}
938
939			return false;
940		};
941
942		self.generateLayouts = function() {
943
944			$( '.jet-parallax-section__layout', $target ).remove();
945
946			$.each( settings, function( index, layout ) {
947				var imageData      = layout['jet_parallax_layout_image'],
948					speed          = layout['jet_parallax_layout_speed']['size'] || 50,
949					zIndex         = layout['jet_parallax_layout_z_index'],
950					animProp       = layout['jet_parallax_layout_animation_prop'] || 'bgposition',
951					deviceMode     = elementorFrontend.getCurrentDeviceMode(),
952					activeBreakpoints = elementor.config.responsive.activeBreakpoints,
953					activeBreakpointsArray = [],
954					bgX            = layout['jet_parallax_layout_bg_x'],
955					bgY            = layout['jet_parallax_layout_bg_y'],
956					type           = layout['jet_parallax_layout_type'] || 'none',
957					direction      = layout['jet_parallax_layout_direction'] || '1',
958					fxDirection    = layout['jet_parallax_layout_fx_direction'] || 'fade-in',
959					device         = layout['jet_parallax_layout_on'] || ['desktop', 'tablet'],
960					_id            = layout['_id'],
961					$layout        = null,
962					layoutData     = {},
963					safariClass    = isSafari ? ' is-safari' : '',
964					macClass       = 'MacIntel' == platform ? ' is-mac' : '';
965
966				if ( -1 === device.indexOf( deviceMode ) ) {
967					return false;
968				}
969			
970				
971				for ( var [key, value] of Object.entries( activeBreakpoints ) ) {
972					if ( 'widescreen' === key ) {
973						activeBreakpointsArray.push( 'desktop' );
974						activeBreakpointsArray.push( key );
975					} else {
976						activeBreakpointsArray.push( key );
977					}
978					
979				}
980
981				if ( -1 === activeBreakpointsArray.indexOf( 'widescreen' ) ) {
982					activeBreakpointsArray.push( 'desktop' );
983				}
984
985				activeBreakpointsArray = activeBreakpointsArray.reverse();
986
987				var breakpoints = [ 'widescreen', 'desktop', 'laptop', 'tablet_extra', 'tablet', 'mobile_extra', 'mobile'],
988					i = 0,
989					prevDevice,
990					layoutBreakpoinntsSettings = [];
991
992				breakpoints.forEach( function( item ) {
993
994					if ( -1 != activeBreakpointsArray.indexOf( item ) ) {
995
996						layoutBreakpoinntsSettings[i] = [];
997
998						if ( 'widescreen' === item ) {
999							layoutBreakpoinntsSettings[i][item] = {
1000								'bgX' : '' != layout['jet_parallax_layout_bg_x_' + item] ? layout['jet_parallax_layout_bg_x'] : 0,
1001
1002								'bgY' : '' != layout['jet_parallax_layout_bg_y_' + item] ? layout['jet_parallax_layout_bg_y'] : 0,
1003
1004								'layoutImageData' : '' != layout['jet_parallax_layout_image_' + item] ? layout['jet_parallax_layout_image_' + item] : ''
1005							};
1006						} else if ( 'desktop' === item ) {
1007							layoutBreakpoinntsSettings[i][item] = {
1008								'bgX' : '' != layout['jet_parallax_layout_bg_x'] ? layout['jet_parallax_layout_bg_x'] : 0,
1009
1010								'bgY' : '' != layout['jet_parallax_layout_bg_y'] ? layout['jet_parallax_layout_bg_y'] : 0,
1011
1012								'layoutImageData' : imageData['url'] || layout['jet_parallax_layout_image']['url']
1013							};
1014						} else {
1015							layoutBreakpoinntsSettings[i][item] = {
1016								'bgX': ( layout['jet_parallax_layout_bg_x_' + item] && '' != layout['jet_parallax_layout_bg_x_' + item] ) ? layout['jet_parallax_layout_bg_x_' + item] : layoutBreakpoinntsSettings[i-1][prevDevice].bgX,
1017
1018								'bgY' : ( layout['jet_parallax_layout_bg_y_' + item] && '' != layout['jet_parallax_layout_bg_y_' + item] ) ? layout['jet_parallax_layout_bg_y_' + item] : layoutBreakpoinntsSettings[i-1][prevDevice].bgY,
1019
1020								'layoutImageData' : ( layout['jet_parallax_layout_image_' + item] && '' != layout['jet_parallax_layout_image_' + item]['url'] ) ? layout['jet_parallax_layout_image_' + item]['url'] : layoutBreakpoinntsSettings[i-1][prevDevice].layoutImageData
1021							};
1022						}
1023
1024						if ( deviceMode === item ) {
1025							bgX    = layoutBreakpoinntsSettings[i][item].bgX;
1026							bgY    = layoutBreakpoinntsSettings[i][item].bgY;
1027							imageData = layoutBreakpoinntsSettings[i][item].layoutImageData;
1028						}
1029
1030						prevDevice = item;
1031
1032						i++;
1033					}
1034
1035				} );
1036
1037				if ( ! $target.hasClass( 'jet-parallax-section' ) ) {
1038					$target.addClass( 'jet-parallax-section' );
1039				}
1040
1041				$layout = $( '<div class="jet-parallax-section__layout elementor-repeater-item-' + _id + ' jet-parallax-section__' + type +'-layout' + macClass + '"><div class="jet-parallax-section__image"></div></div>' )
1042					.prependTo( $target )
1043					.css( {
1044						'z-index': zIndex
1045					} );
1046
1047				var imageCSS = {
1048					'background-position-x': bgX + '%',
1049					'background-position-y': bgY + '%',
1050					'background-image': 'url(' + imageData + ')'
1051				};
1052
1053				$( '> .jet-parallax-section__image', $layout ).css( imageCSS );
1054
1055				layoutData = {
1056					selector: $layout,
1057					prop: animProp,
1058					type: type,
1059					device: device,
1060					xPos: bgX,
1061					yPos: bgY,
1062					direction: +direction,
1063					fxDirection: fxDirection,
1064					speed: 2 * ( speed / 100 )
1065				};
1066
1067				if ( 'none' !== type ) {
1068					if ( JetElementsTools.inArray( type, ['scroll', 'h-scroll', 'zoom', 'rotate', 'blur', 'opacity'] ) ) {
1069						scrollLayoutList.push( layoutData );
1070					}
1071
1072					if ( 'mouse' === type ) {
1073						mouseLayoutList.push( layoutData );
1074					}
1075				}
1076
1077			} );
1078
1079		};
1080
1081		self.scrollHandler = function( event ) {
1082			winScrollTop = $window.scrollTop();
1083			winHeight    = $window.height();
1084
1085			self.scrollUpdate();
1086		};
1087
1088		self.scrollUpdate = function() {
1089			$.each( scrollLayoutList, function( index, layout ) {
1090
1091				var $this      = layout.selector,
1092					$image     = $( '.jet-parallax-section__image', $this ),
1093					speed      = layout.speed,
1094					offsetTop  = $this.offset().top,
1095					thisHeight = $this.outerHeight(),
1096					prop       = layout.prop,
1097					type       = layout.type,
1098					dir        = layout.direction,
1099					fxDir      = layout.fxDirection,
1100					posY       = ( winScrollTop - offsetTop + winHeight ) / thisHeight * 100,
1101					device     = elementorFrontend.getCurrentDeviceMode();
1102
1103				if ( -1 === layout.device.indexOf( device ) ) {
1104					$image.css( {
1105						'transform': 'translateX(0) translateY(0)',
1106						'background-position-y': layout.yPos,
1107						'background-position-x': layout.xPos,
1108						'filter': 'none',
1109						'opacity': '1'
1110					} );
1111
1112					return false;
1113				}
1114
1115				if ( winScrollTop < offsetTop - winHeight ) posY = 0;
1116				if ( winScrollTop > offsetTop + thisHeight) posY = 200;
1117
1118				posY = parseFloat( speed * posY ).toFixed(1);
1119
1120				switch( type ) {
1121					case 'scroll':
1122						if ( 'bgposition' === prop ) {
1123							$image.css( {
1124								'background-position-y': 'calc(' + layout.yPos + '% + ' + (posY * dir) + 'px)'
1125							} );
1126						} else {
1127							$image.css( {
1128								'transform': 'translateY(' + (posY * dir) + 'px)'
1129							} );
1130						}
1131						break;
1132					case 'h-scroll':
1133						if ( 'bgposition' === prop ) {
1134							$image.css( {
1135								'background-position-x': 'calc(' + layout.xPos + '% + ' + (posY * dir) + 'px)'
1136							} );
1137						} else {
1138							$image.css( {
1139								'transform': 'translateX(' + (posY * dir) + 'px)'
1140							} );
1141						}
1142						break;
1143					case 'zoom':
1144						var deltaScale = ( winScrollTop - offsetTop + winHeight ) / winHeight,
1145							scale      = deltaScale * speed;
1146
1147						scale = scale + 1;
1148
1149						$image.css( {
1150							'transform': 'scale(' + scale + ')'
1151						} );
1152						break;
1153					case 'rotate':
1154						var rotate = posY;
1155
1156						$image.css( {
1157							'transform': 'rotateZ(' + (rotate * dir) + 'deg)'
1158						} );
1159						break;
1160					case 'blur':
1161						var blur = 0;
1162
1163						switch ( fxDir ) {
1164							case 'fade-in':
1165								blur = posY / 40;
1166								break;
1167
1168							case 'fade-out':
1169								blur = (5 * speed) - (posY / 40);
1170								break
1171						}
1172
1173						$image.css( {
1174							'filter': 'blur(' + blur + 'px)'
1175						} );
1176						break;
1177					case 'opacity':
1178						var opacity = 1;
1179
1180						switch ( fxDir ) {
1181							case 'fade-in':
1182								opacity = 1 - (posY / 400);
1183								break;
1184
1185							case 'fade-out':
1186								opacity = (1 - (0.5 * speed)) + (posY / 400);
1187								break
1188						}
1189
1190						$image.css( {
1191							'opacity': opacity
1192						} );
1193						break;
1194				}
1195
1196			} );
1197		};
1198
1199		self.mouseMoveHandler = function( event ) {
1200			var windowWidth  = $window.width(),
1201				windowHeight = $window.height(),
1202				cx           = Math.ceil( windowWidth / 2 ),
1203				cy           = Math.ceil( windowHeight / 2 ),
1204				dx           = event.clientX - cx,
1205				dy           = event.clientY - cy;
1206
1207			tiltx = -1 * ( dx / cx );
1208			tilty = -1 * ( dy / cy );
1209
1210			self.mouseMoveUpdate();
1211		};
1212
1213		self.mouseLeaveHandler = function( event ) {
1214
1215			$.each( mouseLayoutList, function( index, layout ) {
1216				var $this  = layout.selector,
1217					$image = $( '.jet-parallax-section__image', $this );
1218
1219				switch( layout.prop ) {
1220					case 'transform3d':
1221						TweenMax.to(
1222							$image[0],
1223							1.2, {
1224								x: 0,
1225								y: 0,
1226								z: 0,
1227								rotationX: 0,
1228								rotationY: 0,
1229								ease:Power2.easeOut
1230							}
1231						);
1232					break;
1233				}
1234
1235			} );
1236		};
1237
1238		self.mouseMoveUpdate = function() {
1239			$.each( mouseLayoutList, function( index, layout ) {
1240				var $this   = layout.selector,
1241					$image  = $( '.jet-parallax-section__image', $this ),
1242					speed   = layout.speed,
1243					prop    = layout.prop,
1244					posX    = parseFloat( tiltx * 125 * speed ).toFixed(1),
1245					posY    = parseFloat( tilty * 125 * speed ).toFixed(1),
1246					posZ    = layout.zIndex * 50,
1247					rotateX = parseFloat( tiltx * 25 * speed ).toFixed(1),
1248					rotateY = parseFloat( tilty * 25 * speed ).toFixed(1),
1249					device  = elementorFrontend.getCurrentDeviceMode();
1250
1251				if ( -1 == layout.device.indexOf( device ) ) {
1252					$image.css( {
1253						'transform': 'translateX(0) translateY(0)',
1254						'background-position-x': layout.xPos,
1255						'background-position-y': layout.yPos
1256					} );
1257
1258					return false;
1259				}
1260
1261				switch( prop ) {
1262					case 'bgposition':
1263
1264						var bgPosX = layout.xPos + ( posX / $image[0].offsetWidth ) * 100,
1265							bgPosY = layout.yPos + ( posY / $image[0].offsetHeight ) * 100;
1266
1267						TweenMax.to(
1268							$image[0],
1269							1, {
1270								backgroundPositionX: bgPosX,
1271								backgroundPositionY: bgPosY,
1272								ease:Power2.easeOut
1273							}
1274						);
1275					break;
1276
1277					case 'transform':
1278						TweenMax.to(
1279							$image[0],
1280							1, {
1281								x: posX,
1282								y: posY,
1283								ease:Power2.easeOut
1284							}
1285						);
1286					break;
1287
1288					case 'transform3d':
1289						TweenMax.to(
1290							$image[0],
1291							2, {
1292								x: posX,
1293								y: posY,
1294								z: posZ,
1295								rotationX: rotateY,
1296								rotationY: -rotateX,
1297								ease:Power2.easeOut
1298							}
1299						);
1300					break;
1301				}
1302
1303			} );
1304		};
1305
1306	}
1307
1308}( jQuery, window.elementorFrontend ) );

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.