PageSourceSearch

https://rozinaali.com/wp-content/plugins/trx_addons/components/api…/elementor-parallax.js?reload=2099061772

js rozinaali.com collected 2026-10-04 21:03:45 UTC 62,925 bytes, 1,555 lines download raw bytes

1( function() {
2
3	'use strict';
4
5	//--- Get block sizes at each scroll event (slow) or only on resize event (fast)
6	var GET_SIZES_ON_SCROLL = false;
7
8	var $window            = jQuery( window ),
9		$document          = jQuery( document ),
10		$body              = jQuery( 'body' );
11
12	var edit_mode = false,
13		animation_allowed = true,
14		motion_step   = 0,
15		motion_period = 250;
16
17	var parallax_items = [];
18
19	// Parameters, which depend from responsive breakpoints
20	var bp_params = {
21		range_start: { default: 0 },
22		range_end: { default: 40 },
23		sticky_offset: { default: 0 },
24		lag: { default: 0 },
25		x_start: { default: 0, unit: 'px' },
26		x_end: { default: 0, unit: 'px' },
27		y_start: { default: 0, unit: 'px' },
28		y_end: { default: 0, unit: 'px' },
29		scale_start: { default: 100 },
30		scale_end: { default: 100 },
31		rotate_start: { default: 0 },
32		rotate_end: { default: 0 },
33		opacity_start: { default: 1 },
34		opacity_end: { default: 1 },
35		crop_start: { default: 0 },
36		crop_end: { default: 100 }
37	};
38
39	$document.on( 'action.after_add_content', function( e, $cont ) {
40		if ( $cont && $cont.length ) {
41			$cont
42				.find( '.trx_addons_parallax_layers_inited,.trx_addons_parallax_blocks_inited' )
43				.removeClass( 'trx_addons_parallax_layers_inited trx_addons_parallax_blocks_inited' );
44		}
45	} );
46
47	$document.on( 'action.got_ajax_response action.init_hidden_elements', function( e ) {
48		// Check items after timeout to allow theme add params
49		setTimeout( function() {
50			var items = jQuery('.trx_addons_parallax_layers:not(.trx_addons_parallax_layers_inited)');
51			if ( items.length > 0 ) {
52				items.each( function() {
53					var layers = new trx_addons_parallax( jQuery(this).addClass('trx_addons_parallax_layers_inited'), 'layers' );
54					if ( layers.init() ) {
55						parallax_items.push( layers );
56					}
57				} );
58			}
59			items = jQuery('.trx_addons_parallax_blocks:not(.trx_addons_parallax_blocks_inited)');
60			if ( items.length > 0 ) {
61				items.each( function() {
62					var $self = jQuery(this);
63					if ( $self.hasClass( 'sc_parallax_text_separate_on' ) ) {
64						// Prepare text blocks: wrap each word (char) to the span and remove parallax behavior from the current block if separate text blocks present
65						var $inner_obj = parallax_text_prepare( $self );
66						if ( $inner_obj && $inner_obj.length ) {
67							// Add inner_obj to the items list to check it later
68							items.add( $inner_obj );
69							$self.removeClass( 'trx_addons_parallax_blocks' );
70						}
71					} else {
72						// Init blocks
73						var blocks = new trx_addons_parallax( $self.addClass('trx_addons_parallax_blocks_inited'), 'blocks' );
74						if ( blocks.init() ) {
75							parallax_items.push( blocks );
76						}
77					}
78				} );
79			}
80		}, 0 );
81	} );
82
83	$window.on( 'elementor/frontend/init', function() {
84		edit_mode = Boolean( window.elementorFrontend.isEditMode() );
85		// Uncomment a next line to disable animations in the Elementor Editor
86		// animation_allowed = ! edit_mode;
87
88		window.elementorFrontend.hooks.addAction( 'frontend/element_ready/container',  parallax_init );	/* Elm 3.16.0+ */
89		window.elementorFrontend.hooks.addAction( 'frontend/element_ready/section', parallax_init );
90		window.elementorFrontend.hooks.addAction( 'frontend/element_ready/column',  parallax_init );
91		window.elementorFrontend.hooks.addAction( 'frontend/element_ready/element', parallax_init );
92		window.elementorFrontend.hooks.addAction( 'frontend/element_ready/widget',  parallax_init );
93	} );
94
95	// Create a controlling object for each target item
96	function parallax_init( $init_obj ) {
97		// Remove old handlers in edit mode (if Parallax is switched off)
98		if ( edit_mode ) {
99			parallax_remove_handlers( $init_obj );
100		}
101		// Init layers
102		var layers = new trx_addons_parallax( $init_obj, 'layers' );
103		if ( layers.init() ) {
104			parallax_items.push( layers );
105		}
106		$init_obj.addClass('trx_addons_parallax_layers_inited');
107		// Init blocks
108		if ( $init_obj.hasClass( 'sc_parallax_text_separate_on' ) ) {
109			// Prepare text blocks: wrap each word (char) to the span and remove parallax behavior from the current block if separate text blocks present
110			var $inner_obj = parallax_text_prepare( $init_obj );
111			if ( $inner_obj && $inner_obj.length ) {
112				$inner_obj.each( function() {
113					var $self = jQuery( this );
114					var blocks = new trx_addons_parallax( $self, 'blocks' );
115					if ( blocks.init() ) {
116						parallax_items.push( blocks );
117					}
118					$self.addClass('trx_addons_parallax_blocks_inited');
119				} );
120			}
121		} else {
122			var blocks = new trx_addons_parallax( $init_obj, 'blocks' );
123			if ( blocks.init() ) {
124				parallax_items.push( blocks );
125			}
126		}
127		$init_obj.addClass('trx_addons_parallax_blocks_inited');
128	}
129
130	// Remove old handlers in edit mode (if Parallax is switched off)
131	function parallax_remove_handlers( $init_obj ) {
132		if ( animation_allowed && parallax_items.length ) {
133			if ( $init_obj.hasClass( 'sc_parallax_text_separate_on' ) ) {
134				$init_obj.find( '.sc_parallax_text_block' ).each( function() {
135					var $self = jQuery( this );
136					parallax_items = parallax_items.filter( function( item ) {
137						return ! item.remove_handlers( $self );
138					} );
139				} );
140			} else {
141				parallax_items = parallax_items.filter( function( item ) {
142					return ! item.remove_handlers( $init_obj );
143				} );
144			}
145		}
146	}
147
148	// Prepare text blocks: wrap each word (char) to the span and remove parallax behavior from the current block if separate text blocks present
149	function parallax_text_prepare( $init_obj, settings ) {
150		if ( ! settings ) {
151			if ( ! edit_mode ) {
152				var params = $init_obj.data( 'parallax-params' ) || false;					
153				if ( params ) {
154					settings = [];
155					settings.push(params);
156				}
157			} else {
158				settings = get_editor_settings( $init_obj, 'blocks' );
159			}
160		}
161		if ( ! settings || settings.length === 0 || ['chars', 'words'].indexOf( settings[0].text ) == -1 || ! $init_obj.data('element_type') ) {
162			return false;
163		}
164		// Prepare (split) text with 'by words' and 'by chars' effects
165		var sc = ( $init_obj.data('element_type') == 'widget' ? $init_obj.data('widget_type') : $init_obj.data('element_type') ).split('.')[0],
166			$inner_obj = $init_obj.find('.sc_parallax_text_block');
167		if ( $inner_obj.length === 0 ) {
168			$inner_obj = $init_obj.find(
169						sc == 'trx_sc_title'
170							? '.sc_item_title_text,.sc_item_subtitle'
171							: ( sc == 'trx_sc_supertitle'
172								? '.sc_supertitle_text'
173								: ( sc == 'heading'
174									? '.elementor-heading-title'
175									: 'p'
176									)
177								)
178						);
179			if ( $inner_obj.length > 0 ) {
180				$inner_obj.each( function( idx ) {
181					$inner_obj.eq( idx )
182						.html(
183							settings[0].text == 'chars'
184								? parallax_text_wrap_chars( $inner_obj.eq( idx ).html(), true )
185								: parallax_text_wrap_words( $inner_obj.eq( idx ).html() )
186						);
187				} );
188				$inner_obj = $inner_obj.find('.sc_parallax_text_block');
189				if ( settings[0].text_separate ) {
190					$inner_obj.each( function( idx ) {
191						var params = trx_addons_object_clone( settings[0] );
192						if ( params.lag > 0 ) {
193							params.lag = trx_addons_window_width() < TRX_ADDONS_STORAGE['mobile_breakpoint_scroll_lag_off'] ? 0 : params.lag * ( idx + 1 );
194						}
195						$inner_obj.eq( idx ).attr( 'data-parallax-params', JSON.stringify( params ) );
196					} );
197				}
198			}
199		}
200		return $inner_obj;
201	}
202
203	// Wrap each char to the <span>
204	function parallax_text_wrap_chars( txt, wrap_words ) {
205		return trx_addons_wrap_chars( txt,
206										'<span class="sc_parallax_text_block">',
207										'</span>',
208										wrap_words ? '<span class="sc_parallax_word_wrap">' : '',
209										wrap_words ? '</span>' : ''
210									);
211	}
212
213	// Wrap each word to the <span>
214	function parallax_text_wrap_words( txt ) {
215		return trx_addons_wrap_words( txt, '<span class="sc_parallax_text_block">', '</span>' );
216	}
217
218	function get_editor_settings( $target, init_type ) {
219		if ( ! window.elementor || ! window.elementor.hasOwnProperty( 'elements' ) ) {
220			return false;
221		}
222
223		var elements = window.elementor.elements;
224
225		if ( ! elements.models ) {
226			return false;
227		}
228
229		var section_id = $target.data('id'),
230			section_cid = $target.data('model-cid'),
231			section_data = {};
232
233		function get_section_data( idx, obj ) {
234			if ( 0 < Object.keys( section_data ).length ) {
235				return;
236			} else if ( section_id == obj.id ) {
237				section_data = obj.attributes.settings.attributes;
238			} else if ( obj.attributes && obj.attributes.elements && obj.attributes.elements.models ) {
239				jQuery.each( obj.attributes.elements.models, get_section_data );
240			}
241		}
242
243		jQuery.each( elements.models, get_section_data );
244
245		if ( 0 === Object.keys( section_data ).length ) {
246			return false;
247		}
248
249		var settings = [];
250		
251		if ( init_type == 'layers' && section_data.hasOwnProperty( 'parallax_blocks' ) ) {
252			jQuery.each( section_data[ 'parallax_blocks' ].models, function( index, obj ) {
253				settings.push( obj.attributes );
254			} );
255		} else if ( init_type == 'blocks'
256					&& ( section_data.hasOwnProperty( 'parallax' ) && section_data.parallax == 'parallax'
257						||
258						section_data.hasOwnProperty( 'parallax_mouse' ) && section_data.parallax_mouse == 'mouse'
259						)
260		) {
261			var parallax_on = section_data.hasOwnProperty( 'parallax' ) && section_data.parallax == 'parallax',
262				mouse_on = section_data.hasOwnProperty( 'parallax_mouse' ) && section_data.parallax_mouse == 'mouse';
263
264			// Object with a list of general params (not depend from responsive breakpoints)
265			var data = {
266				// Common parallax settings
267				parallax: 	   parallax_on ? 1 : 0,
268				type:          parallax_on && section_data.hasOwnProperty( 'parallax_type' ) ? section_data.parallax_type : 'object',
269				flow:          parallax_on && section_data.hasOwnProperty( 'parallax_flow' ) ? section_data.parallax_flow : 'default',
270				crop:          parallax_on && section_data.hasOwnProperty( 'parallax_crop' ) ? section_data.parallax_crop : 'none',
271				duration:      parallax_on && section_data.hasOwnProperty( 'parallax_duration' ) ? section_data.parallax_duration.size : 1,
272				delay:         parallax_on && section_data.hasOwnProperty( 'parallax_delay' ) ? section_data.parallax_delay.size : 0,
273				squeeze:       parallax_on && section_data.hasOwnProperty( 'parallax_squeeze' ) ? section_data.parallax_squeeze.size : 1,
274				ease:          parallax_on && section_data.hasOwnProperty( 'parallax_ease' ) ? section_data.parallax_ease : 'power2',
275				// Text settings
276				text:          parallax_on && section_data.hasOwnProperty( 'parallax_text' ) ? section_data.parallax_text : 'block',
277				text_separate: parallax_on && section_data.hasOwnProperty( 'parallax_text_separate' ) ? section_data.parallax_text_separate : 0,
278				text_wrap:     parallax_on && section_data.hasOwnProperty( 'parallax_text_wrap' ) ? 1 : 0,
279				// Mouse settings
280				mouse:             mouse_on ? 1 : 0,
281				mouse_type:        mouse_on && section_data.hasOwnProperty( 'parallax_mouse_type' ) ? section_data.parallax_mouse_type : 'transform3d',
282				mouse_tilt_amount: mouse_on && section_data.hasOwnProperty( 'parallax_mouse_tilt_amount' ) ? section_data.parallax_mouse_tilt_amount.size : 70,
283				mouse_speed:       mouse_on && section_data.hasOwnProperty( 'parallax_mouse_speed' ) ? section_data.parallax_mouse_speed.size : 10,
284				mouse_z:           mouse_on && section_data.hasOwnProperty( 'parallax_mouse_z' ) ? section_data.parallax_mouse_z.size : '',
285				mouse_handler:     mouse_on && section_data.hasOwnProperty( 'parallax_mouse_handler' ) ? section_data.parallax_mouse_handler : 'row'
286			};
287
288			// Add params for each breakpoint
289			var suffix_prev = '', suffix = '', param_name = '', param_prev = '', defa = {};
290			for ( var resp in TRX_ADDONS_STORAGE['elementor_breakpoints'] ) {
291				suffix = resp == 'desktop' ? '' : '_' + resp;
292				for ( var param in bp_params ) {
293					defa = bp_params[ param ];
294					param_name = param + suffix;
295					param_prev = param + suffix_prev;
296					// Skip if the parameter is not responsive
297					if ( suffix && ! section_data.hasOwnProperty( 'parallax_' + param_name ) ) continue;
298					// Set parameter value
299					data[ param_name ] = section_data.hasOwnProperty( 'parallax_' + param_name ) && section_data[ 'parallax_' + param_name ]['size'] !== ''
300											? section_data[ 'parallax_' + param_name ]['size']
301											: ( ! suffix ? defa['default'] : data[ param_prev ] );
302					if ( defa['unit'] ) {
303						data[ param_name + '_unit' ] = section_data.hasOwnProperty( 'parallax_' + param_name ) && section_data[ 'parallax_' + param_name ].hasOwnProperty( 'unit' ) && section_data[ 'parallax_' + param_name ]['size'] !== ''
304											? section_data[ 'parallax_' + param_name ]['unit']
305											: ( ! suffix ? defa['unit'] : data[ param_prev + '_unit' ] );
306					}
307					// Duplicate values without suffix to the '_desktop' suffix
308					if ( ! suffix ) {
309						data[ param_name + '_desktop' ] = data[ param_name ];
310						if ( defa['unit'] ) {
311							data[ param_name + '_unit_desktop' ] = data[ param_name + '_unit' ];
312						}
313					}
314				}
315				// Set equal units for start and end values if one of them is zero
316				if ( typeof data['x_start' + suffix] != 'undefined' && typeof data['x_end' + suffix] != 'undefined' ) {
317					if ( data['x_end' + suffix] == 0 ) data['x_end' + suffix + '_unit'] = data['x_start' + suffix + '_unit'];
318					else if ( data['x_start' + suffix] == 0 ) data['x_start' + suffix + '_unit'] = data['x_end' + suffix + '_unit'];
319				}
320				if ( typeof data['y_start' + suffix] != 'undefined' && typeof data['y_end' + suffix] != 'undefined' ) {
321					if ( data['y_end' + suffix] == 0 ) data['y_end' + suffix + '_unit'] = data['y_start' + suffix + '_unit'];
322					else if ( data['y_start' + suffix] == 0 ) data['y_start' + suffix + '_unit'] = data['y_end' + suffix + '_unit'];
323				}
324				// Save suffix for the next iteration
325				suffix_prev = suffix;
326			}
327
328			// Add data to the wrapper
329			settings.push( parallax_bp_settings( data ) );
330		}
331
332		return 0 !== settings.length ? settings : false;
333	}
334
335	// Update settings without a suffix with values from the current responsive breakpoint
336	function parallax_bp_settings( settings ) {
337		// Add a property with a last responsive breakpoint
338		if ( ! settings.hasOwnProperty( 'last_bp' ) ) {
339			settings['last_bp'] = 'desktop';
340			// Duplicate values without suffix to the '_desktop' suffix
341			for ( var param in bp_params ) {
342				var param_name = param + '_desktop';
343				if ( ! settings.hasOwnProperty( param_name ) ) {
344					settings[ param_name ] = settings[ param ];
345					if ( bp_params[ param ]['unit'] ) {
346						settings[ param_name + '_unit' ] = settings[ param + '_unit' ];
347					}
348				}
349			}
350		}
351		// Get current responsive breakpoint and update settings with values from the current breakpoint
352		var bp = trx_addons_get_responsive_breakpoint();
353		if ( bp != settings['last_bp'] ) {
354			for ( var param in bp_params ) {
355				var param_name = param + '_' + bp;
356				if ( settings.hasOwnProperty( param_name ) ) {
357					settings[ param ] = settings[ param_name ];
358					if ( bp_params[ param ]['unit'] ) {
359						settings[ param + '_unit' ] = settings[ param_name + '_unit' ];
360					}
361				}
362			}
363			settings['last_bp'] = bp;
364		}
365		return settings;
366	}
367
368
369	// Class to control a parallax item
370	//-----------------------------------------------------------------
371	window.trx_addons_parallax = function( $target, init_type ) {
372		var self          = this,
373			settings      = false,
374			parallax_type = 'none',
375			$targetLayers = $target,
376			$targetBlocks = $target,
377			target_id     = $target.data( 'id' );
378
379		if ( ! target_id ) {
380			target_id = 'parallax' + ( '' + Math.random() ).replace( '.', '' );
381			$target.data( 'id', target_id );
382		}
383
384		var scroll_list   = [],
385			mouse_list    = [],
386			motion_list   = [];
387
388		var on_start_inited = false;
389
390		var wst           = trx_addons_window_scroll_top() + trx_addons_fixed_rows_height(),
391			ww            = trx_addons_window_width(),
392			wh            = trx_addons_window_height() - trx_addons_fixed_rows_height(),
393			is_safari     = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/),
394			platform      = navigator.platform;
395
396		var tl            = 0,
397			tt            = 0,
398			tw            = 0,
399			th            = 0,
400			tx            = 0,
401			ty            = 0,
402			cx            = 0,
403			cy            = 0,
404			dx            = 0,
405			dy            = 0;
406
407		self.init = function() {
408			if ( ! edit_mode ) {
409				if ( init_type == 'layers' ) {
410					settings = $target.data( 'parallax-blocks' ) || false;
411					if ( settings ) {
412						parallax_type = 'layers';
413					}
414				} else {
415					var params = $target.data( 'parallax-params' ) || false;					
416					if ( params ) {
417						settings = [];
418						settings.push(params);
419						parallax_type = 'blocks';
420					}
421				}
422			} else {
423				settings = get_editor_settings( $target, init_type );
424				if ( settings ) {
425					parallax_type = init_type;
426				}
427			}
428			if ( ! settings ) {
429				return false;
430			}
431
432			// If block must catch mouse events
433			if ( settings[0].mouse == 1 ) {
434
435				parallax_type += '|layers';
436
437				var layout_data = {
438						selector: $target,
439						image: false,
440						size: 'auto',
441						prop: settings[0].mouse_type || 'transform3d',
442						type: 'mouse',
443						x: 0,
444						y: 0,
445						z: settings[0].mouse_z || 0,
446						speed: 2 * ( ( settings[0].mouse_speed ? settings[0].mouse_speed : 10 ) / 100 ),
447						tilt_amount: settings[0].mouse_tilt_amount || 70,
448						motion_dir: 'round',
449						motion_time: 5
450					};
451
452				mouse_list.push( layout_data );
453			}
454
455			if ( init_type == 'layers' || settings[0].mouse == 1 ) {
456				if ( settings[0].mouse_handler == 'window' ) {
457					$targetLayers = $body;
458				} else if ( settings[0].mouse_handler == 'content' ) {
459					$targetLayers = jQuery( trx_addons_apply_filters( 'trx_addons_filter_page_wrap_class', TRX_ADDONS_STORAGE['page_wrap_class'] ? TRX_ADDONS_STORAGE['page_wrap_class'] : '.page_wrap', 'elementor-parallax' ) ).eq(0);
460				} else if ( settings[0].mouse_handler == 'row' ) {
461					if ( init_type != 'layers' ) {
462						$targetLayers = $target.hasClass( 'trx_addons_parallax_blocks' )
463											? $target.parent()
464											: $target.parents( '.elementor-section,.e-con.e-parent' ).eq(0);
465					}
466				} else if ( settings[0].mouse_handler == 'column' ) {
467					$targetLayers = $target.hasClass( 'trx_addons_parallax_blocks' )
468										? $target.parent()
469										: $target.parents( '.elementor-column,.e-con.e-child' ).eq(0);
470				} else if ( settings[0].mouse_handler == 'parent' ) {
471					$targetLayers = $target.parent();
472				} else if ( settings[0].mouse_handler && '.#'.indexOf( settings[0].mouse_handler.substring(0, 1) ) != -1 ) {
473					$targetLayers = $target.parents( settings[0].mouse_handler );
474				} else if ( settings[0].mouse_type == 'tilt' ) {
475					var $tilt_trigger = $target.parents( '.trx_addons_tilt_trigger' );
476					if ( $tilt_trigger.length > 0 ) {
477						$targetLayers = $tilt_trigger.eq(0);
478					}
479				}
480				$targetLayers.data('mouse-handler', settings[0].mouse_handler);
481			}
482
483			if ( parallax_type.indexOf('layers') >= 0 ) {
484				if ( init_type == 'layers' ) {
485					self.create_layers();
486				}
487				if ( animation_allowed ) {
488					if ( ! $targetLayers.attr( 'data-mousemove-' + target_id ) ) {
489						$targetLayers.attr( 'data-mousemove-' + target_id, target_id );
490						$targetLayers.on( 'mousemove.trx_addons_parallax', self.mouse_move_handler );
491						$targetLayers.on( 'mouseleave.trx_addons_parallax', self.mouse_leave_handler );
492					}
493					if ( motion_list.length > 0 ) {
494						$targetLayers.attr( 'data-motionmove-' + target_id, setInterval( self.motion_move_handler, motion_period ) );
495					}
496				}
497			}
498
499			if ( parallax_type.indexOf('blocks') >= 0 ) {
500				settings[0].selector = $targetBlocks;
501				settings[0].hsection = $targetBlocks.parents( '.sc_hscroll_section' );
502				settings[0].hscroller = settings[0].hsection.length ? settings[0].hsection.parents( '.sc_hscroll_scroller' ) : false;
503				if ( settings[0].flow == 'sticky' ) {	//$targetBlocks.hasClass( 'sc_parallax_sticky' ) ) {
504					$targetBlocks.css( 'top', ( 100 - settings[0].range_start ) + '%' );
505				}
506				scroll_list.push(settings[0]);
507				settings[0].selector.addClass( 'trx_addons_parallax_blocks_need_start' );
508			}
509
510			if ( ! GET_SIZES_ON_SCROLL ) {
511				self.get_blocks_sizes();
512				$document.on( 'action.init_hidden_elements action.hscroll_inited', self.get_blocks_sizes );
513				$document.on( 'action.sc_layouts_row_fixed_on action.sc_layouts_row_fixed_off', self.get_blocks_sizes );
514				$document.on( 'action.resize_trx_addons', self.get_blocks_sizes );
515			}
516
517			if ( animation_allowed ) {
518				on_start_inited = false;
519				var on_start_init = trx_addons_throttle( function() {
520					if ( ! on_start_inited ) {
521						on_start_inited = true;
522						// Put blocks to the start positions
523						self.scroll_update( true );
524						// Wait for the end of the animation and update blocks positions
525						setTimeout( function() {
526							self.scroll_handler();
527						}, 10 );
528					}
529				}, 100 );
530				$document.on( 'action.resize_trx_addons action.scroll_trx_addons action.hscroll_inited', self.scroll_handler );
531				$document.on( 'action.resize_trx_addons action.scroll_trx_addons action.hscroll_inited action.init_hidden_elements action.sc_layouts_row_fixed_on action.sc_layouts_row_fixed_off', on_start_init );
532			}
533
534			return true;
535		};
536
537		self.remove_handlers = function( $init_obj, force ) {
538			var found = $target.is( $init_obj ) || force;
539			// Remove handlers if is a checked obj
540			if ( found ) {
541				var id = $init_obj.data( 'id' );
542				// Reset attribute 'style' if parallax turned off
543				$init_obj.attr( 'style', '' );
544				// Delete mousemove handlers
545				if ( $init_obj.attr( 'data-mousemove-' + id ) ) {
546					$init_obj.removeAttr( 'data-mousemove-' + id );
547					$init_obj.off( 'mousemove.trx_addons_parallax', self.mouse_move_handler );
548					$init_obj.off( 'mouseleave.trx_addons_parallax', self.mouse_leave_handler );
549				}
550				// Stop motion
551				if ( $init_obj.attr( 'data-motionmove-' + id ) ) {
552					clearInterval( $init_obj.attr( 'data-motionmove-' + id ) );
553					$init_obj.removeAttr( 'data-motionmove-' + id );
554				}
555			}
556			return found;
557		};
558
559		self.get_blocks_sizes = function() {
560			jQuery.each( scroll_list, function( index, block ) {
561				// Calc additional offset of the block to compatibility with blocks inside a widget 'Horizontal Scroll'
562				var hscroller_offset = block.hsection.length ? block.hscroller.data( 'hscroll-offset' ) || 0 : 0;
563				var hsection_offset = block.hsection.length ? block.hsection.data( 'hscroll-section-offset' ) || 0 : 0;
564				hscroller_offset += hsection_offset;
565				// Get block sizes
566				block.sizes = {
567					width: block.selector.outerWidth(),
568					height: block.selector.outerHeight(),
569					top: block.selector.offset().top + hscroller_offset
570				};
571				if ( block.flow == 'sticky' ) {	//block.selector.hasClass( 'sc_parallax_sticky' ) ) {
572					var $parent = block.selector.parent();
573					block.sizes.parent_selector = $parent;
574					block.sizes.parent_height = $parent.length ? $parent.outerHeight() : 0;
575					block.sizes.parent_top = $parent.length ? $parent.offset().top + hscroller_offset : 0;
576				}
577			} );
578		};
579
580		self.create_layers = function() {
581
582			$target.find( '> .sc_parallax_block' ).remove();
583			
584			var bg_parallax_present = false;
585
586			jQuery.each( settings, function( index, block ) {
587				var image       = block['image'].url,
588					speed       = block['speed'].size,
589					z_index     = block['z_index'].size,
590					bg_size     = block['bg_size'] ? block['bg_size'] : 'auto',
591					type        = block['type'] ? block['type'] : 'none',
592					anim_prop   = block['animation_prop']
593									? ( ['scroll', 'motion'].indexOf(type) != -1 && block['animation_prop'] != 'background'
594											? 'transform'
595											: block['animation_prop']
596											)
597									: 'background',
598					left        = block['left'].size,
599					top         = block['top'].size,
600					// Motion parameters
601					motion_dir  = block['motion_dir'] ? block['motion_dir'] : 'round',
602					motion_time = block['motion_time'] ? block['motion_time'].size : 5,
603					// Mouse parameters
604					tilt_amount = block['mouse_tilt_amount'] ? block['mouse_tilt_amount'].size : 70,
605					mouse_handler = block['mouse_handler'] ? block['mouse_handler'] : 'row',
606					// New parallax to fix Chrome scroll: used only for layers with type=='scroll' and animation type=='background'
607					bg_parallax = block['bg_parallax'] && type =='scroll' && anim_prop == 'background' ? block['bg_parallax'] : false,
608					$layout     = null;
609
610				if ( bg_parallax ) {
611					bg_parallax_present = true;
612				}
613
614				if ( '' !== image || 'none' !== type ) {
615					var layout_init = {
616						'z-index': z_index
617					};
618					if ( 'none' === type ) {
619						layout_init['left'] = left + '%';
620						layout_init['top'] = top + '%';
621					}
622					$layout = jQuery( '<div class="sc_parallax_block'
623											+ ' sc_parallax_block_type_' + type
624											+ ' sc_parallax_block_animation_' + ( bg_parallax ? 'bg_parallax' : anim_prop )
625											+ (is_safari ? ' is-safari' : '')
626											+ ('MacIntel' == platform ? ' is-mac' : '')
627											+ (typeof block['class'] !== 'undefined' && block['class'] != '' ? ' ' + block['class'] : '')
628										+ '">'
629											+ '<div class="sc_parallax_block_image"'
630												+ ( bg_parallax
631													? ' parallax="' + ( speed / 100 ) + '"'
632													: ''
633													)
634											+ '></div>'
635										+ '</div>' )
636								.prependTo( $target )
637								.css( layout_init );
638
639					layout_init = {
640						'background-image': 'url(' + image + ')',
641						'background-size': bg_size,
642						'background-position-x': left + '%',
643						'background-position-y': top + '%'
644					};
645					$layout.find( '> .sc_parallax_block_image' ).css(layout_init);
646
647					var layout_data = {
648						selector: $layout,
649						image: image,
650						size: bg_size,
651						bg_parallax: bg_parallax,
652						prop: anim_prop,
653						type: type,
654						x: left,
655						y: top,
656						z: z_index,
657						speed: 2 * ( speed / 100 ),
658						tilt_amount: tilt_amount,
659						mouse_handler: mouse_handler,
660						motion_dir: motion_dir,
661						motion_time: motion_time
662					};
663
664					if ( 'scroll' === type ) {
665						layout_data.hsection = layout_data.selector.parents( '.sc_hscroll_section' );
666						layout_data.hscroller = layout_data.hsection.length ? layout_data.hsection.parents( '.sc_hscroll_scroller' ) : false;
667						scroll_list.push( layout_data );
668						// Don't need to set a start position for the background layers
669						//layout_data.selector.addClass( 'trx_addons_parallax_blocks_need_start' );
670					} else if ( 'mouse' === type ) {
671						mouse_list.push( layout_data );
672					} else if ( 'motion' === type ) {
673						motion_list.push( layout_data );
674					}
675				}
676			});
677
678			// Init new parallax method (to fix Google Chrome scroll)
679			if ( bg_parallax_present ) {
680				trx_addons_bg_parallax( $target.get(0) );
681			}
682		};
683
684
685		// Scroll handlers
686		//-------------------------------------
687		var in_out_last_state = '';
688		self.get_block_params = function( block ) {
689
690			var params = trx_addons_object_merge( {}, parallax_bp_settings( block ) );
691
692			// Prepare defaults
693			if ( typeof params.type == 'undefined' ) params.type = 'object';
694			if ( typeof params.flow == 'undefined' ) params.flow = 'default';
695			if ( typeof params.crop == 'undefined' ) params.crop = 'none';
696			if ( typeof params.range_start == 'undefined' ) params.range_start = 0;
697			if ( typeof params.range_end == 'undefined' ) params.range_end = 40;
698			if ( params.range_end <= params.range_start ) {
699				params.range_end = Math.min( 100, params.range_start + params.range_end );
700			}
701			if ( typeof params.sticky_offset == 'undefined' ) params.sticky_offset = 0;
702			if ( params.flow == 'entrance' ) {
703				params.range_end = 100;
704			} else if ( params.flow == 'sticky' ) {
705				params.range_end = params.range_start;
706			}
707			if ( typeof params.duration == 'undefined' ) params.duration = 1;
708			if ( typeof params.delay == 'undefined' ) params.delay = 0;
709			if ( typeof params.squeeze == 'undefined' ) params.squeeze = 1;
710			if ( typeof params.ease == 'undefined' ) params.ease = "power2";
711			if ( typeof params.lag == 'undefined' ) params.lag = 0;
712			if ( typeof params.x_start == 'undefined' ) params.x_start = 0;
713			if ( typeof params.x_start_unit == 'undefined' ) params.x_start_unit = 'px';
714			if ( typeof params.x_end == 'undefined' ) params.x_end = 0;
715			if ( typeof params.x_end_unit == 'undefined' ) params.x_end_unit = 'px';
716			if ( typeof params.y_start == 'undefined' ) params.y_start = 0;
717			if ( typeof params.y_start_unit == 'undefined' ) params.y_start_unit = 'px';
718			if ( typeof params.y_end == 'undefined' ) params.y_end = 0;
719			if ( typeof params.y_end_unit == 'undefined' ) params.y_end_unit = 'px';
720			if ( typeof params.scale_start == 'undefined' ) params.scale_start = 100;
721			if ( typeof params.scale_end == 'undefined' ) params.scale_end = 100;
722			if ( typeof params.rotate_start == 'undefined' ) params.rotate_start = 0;
723			if ( typeof params.rotate_end == 'undefined' ) params.rotate_end = 0;
724			if ( typeof params.opacity_start == 'undefined' ) params.opacity_start = 1;
725			if ( typeof params.opacity_end == 'undefined' ) params.opacity_end = 1;
726			if ( typeof params.crop_start == 'undefined' ) params.crop_start = 100;
727			if ( typeof params.crop_end == 'undefined' ) params.crop_end = 100;
728			if ( typeof params.text == 'undefined' ) params.text = 'block';
729			if ( typeof params.text_separate == 'undefined' ) params.text_separate = 0;
730
731			// If an animation flow is 'In Out' - prepare Start and End Point and its values
732			if ( params.flow == 'in_out' ) {
733				// Calc additional offset of the block to compatibility with blocks inside a widget 'Horizontal Scroll'
734				// var hscroller_offset = params.hsection.length ? params.hscroller.data( 'hscroll-offset' ) || 0 : 0;
735				// var hsection_offset  = params.hsection.length ? params.hsection.data( 'hscroll-section-offset' ) || 0 : 0;
736				// hscroller_offset += hsection_offset;
737
738				var w_top      = wst + wh * ( 1 - params.range_end / 100 ),
739					w_bottom   = wst + wh * ( 1 - params.range_start / 100 ),
740					// obj        = params.selector,
741					// obj_width  = params.sizes.width,
742					obj_height = params.sizes.height,
743					obj_top    = params.sizes.top + ( ww < TRX_ADDONS_STORAGE['mobile_breakpoint_scroll_lag_off'] ? 0 : params.lag ),// + hscroller_offset
744					obj_bottom = obj_top + obj_height;
745
746				if ( w_top >= obj_bottom || in_out_last_state == 'out' ) {				// Set range from range_end to 100%
747					in_out_last_state = w_top >= obj_bottom ? 'out' : '';
748					params.in_out_state = 'out';
749					params.force = w_top < obj_bottom;
750					params.range_start = params.range_end;
751					params.range_end = 100;
752					params.x_start = 0;
753					params.y_start = 0;
754					params.scale_start = 100;
755					params.rotate_start = 0;
756					params.opacity_start = 1;
757					params.crop_start = 100;
758					params.crop = self.crop_reverse( params, 'out' );
759
760				} else if ( w_bottom <= obj_top || in_out_last_state == 'in' ) {	// Set range from 0% to range_start
761					in_out_last_state = w_bottom <= obj_top ? 'in' : '';
762					params.in_out_state = 'in';
763					params.force = w_bottom > obj_top;
764					params.range_end = params.range_start;
765					params.range_start = 0;
766					params.x_end = 0;
767					params.y_end = 0;
768					params.scale_end = 100;
769					params.rotate_end = 0;
770					params.opacity_end = 1;
771					params.crop_end = 100;
772					params.crop = self.crop_reverse( params, 'in' );
773
774				} else {								// Set equal settings from range_start to range_end
775					params.in_out_state = '';
776					params.x_start = params.x_end = 0;
777					params.y_start = params.y_end = 0;
778					params.scale_start = params.scale_end = 100;
779					params.rotate_start = params.rotate_end = 0;
780					params.opacity_start = params.opacity_end = 1;
781					params.crop_start = params.crop_end = 100;
782				}
783			}
784			return params;
785		};
786
787		self.scroll_handler = function( e ) {
788			if ( ! animation_allowed ) {
789				return;
790			}
791			wst = trx_addons_window_scroll_top() + trx_addons_fixed_rows_height();
792			ww  = trx_addons_window_width();
793			wh  = trx_addons_window_height() - trx_addons_fixed_rows_height();
794			if ( on_start_inited ) {
795				self.scroll_update();
796			}
797		};
798
799		self.scroll_update = function( force ) {
800
801			if ( GET_SIZES_ON_SCROLL ) {
802				self.get_blocks_sizes();
803			}
804
805			jQuery.each( scroll_list, function( index, block ) {
806
807				// Commented because the object is not come to the end point if a scroll is very fast
808				// if ( ! block.selector.is(':visible') ) return;
809
810				// Calc additional offset of the block to compatibility with blocks inside a widget 'Horizontal Scroll'
811				// var hscroller_offset = block.hsection.length ? block.hscroller.data( 'hscroll-offset' ) || 0 : 0;
812				// var hsection_offset = block.hsection.length ? block.hsection.data( 'hscroll-section-offset' ) || 0 : 0;
813				// hscroller_offset += hsection_offset;
814
815				// Section (row) layers
816				if ( parallax_type.indexOf('layers') >= 0 ) {
817					if ( ( ! block.bg_parallax || block.prop != 'background' ) && block.speed !== undefined ) {
818						var $image     = block.selector.find( '.sc_parallax_block_image' ).eq(0),
819							speed      = block.speed,
820							offset_top = block.sizes.top, // + hscroller_offset
821							h          = block.sizes.height,
822							y          = ( wst + wh - offset_top ) / h * 100;
823						if ( wst < offset_top - wh) y = 0;
824						if ( wst > offset_top + h)  y = 200;
825						y = parseFloat( speed * y ).toFixed(1);
826						if ( 'background' === block.prop ) {
827							$image.css( {
828								'background-position': block.x + '% calc(' + block.y + '% + ' + y + 'px)'
829							} );
830						} else {
831							$image.css( {
832								'transform': 'translateY(' + y + 'px)'
833							} );
834						}
835					}
836				}
837
838				// Widgets (blocks)
839				if ( parallax_type.indexOf('blocks') >= 0 ) {
840
841					var params = self.get_block_params( block );
842
843					var w_top         = wst + wh * ( 1 - params.range_end / 100 ),
844						w_bottom      = wst + wh * ( 1 - params.range_start / 100 ),
845						w_delta       = params.flow == 'entrance' ? 0 : 100,
846						obj           = params.selector,
847						obj_width     = params.sizes.width,
848						obj_height    = params.sizes.height,
849						obj_top       = params.sizes.top
850										// + hscroller_offset
851										+ ( ww < TRX_ADDONS_STORAGE['mobile_breakpoint_scroll_lag_off'] ? 0 : params.lag ),
852						obj_bottom    = obj_top + obj_height,
853						parent_top    = params.flow == 'sticky'
854											? params.sizes.parent_top // + hscroller_offset
855											: 0,
856						parent_bottom = params.flow == 'sticky'
857											? parent_top + params.sizes.parent_height * ( 1 - params.sticky_offset / 100 )
858											: 0;
859
860					var entrance_complete = obj.hasClass('sc_parallax_entrance_complete'),
861						bottom_delta = params.flow == 'entrance' && params.range_start == 0
862											? wh * ( 1 - params.range_start / 100 ) / 10
863											: 0;
864
865					// Set a start settings for the object
866					// via imitation his place at the top or bottom of the range
867					var obj_visible = true;
868					if ( obj.data('inited') === undefined && params.flow != 'sticky' ) {
869						if ( obj_top > w_bottom ) {
870							obj_top = w_bottom + w_delta - bottom_delta;
871							obj_visible = false;
872						} else if ( obj_bottom < w_top ) {
873							obj_bottom = w_top - w_delta;
874							obj_visible = false;
875						}
876						obj.data( 'inited', 1 );
877					}
878
879					if ( ( force || params.force )
880						|| ( ! entrance_complete
881								&& w_top - w_delta <= ( params.flow == 'sticky'
882															? parent_bottom
883															: ( params.flow == 'in_out' && params.in_out_state == 'in'
884																	? obj_top
885																	: obj_bottom
886																	)
887																)
888								&& ( params.flow == 'sticky'
889										? parent_top
890										: ( params.flow == 'in_out' && params.in_out_state == 'out'
891												? obj_bottom
892												: obj_top
893											)
894										) <= w_bottom + w_delta - bottom_delta
895							)
896					) {
897						if ( params.flow == 'entrance' ) {
898							var entrance_start = false;
899							if ( ! obj.data( 'entrance-inited' ) ) {
900								// Old way: If a top of the object is over than the bottom side of the window - mark it as complete
901//								if ( obj_top < w_bottom - bottom_delta ) {
902								// New way: If a bottom of the object is over than the top side of the window - mark it as complete
903								if ( obj_bottom <= w_top - w_delta ) {
904									obj.addClass('sc_parallax_entrance_complete');
905									//return;
906								} else {
907									entrance_start = true;
908								}
909								obj.data( 'entrance-inited', 1 );
910							} else if ( ! obj.hasClass('sc_parallax_entrance_complete') ) {
911								obj.addClass('sc_parallax_entrance_complete');
912							}
913						}
914
915						var delta, shift;
916						if ( params.flow == 'entrance' ) {
917							delta = 1;
918							shift = entrance_start ? 0 : 1;
919						} else if ( params.flow == 'sticky' ) {
920							var obj_anchor = obj_top + Math.round( obj_height * ( 100 - params.range_start ) / 100 );
921							delta = Math.max( 1, parent_bottom - obj_bottom );
922							shift = Math.max( 0, w_bottom - obj_anchor );
923							if ( force ) {
924								block.selector.css( 'top', 'calc( ' + ( 100 - params.range_start ) + '% - ' + ( obj_anchor - obj_top ) + 'px )' );
925							}
926						} else if ( params.flow == 'in_out' ) {
927							delta = Math.max( 1, wh * ( params.range_end - params.range_start ) / 100 );
928							shift = w_bottom - ( params.in_out_state == 'in' ? obj_top : obj_bottom );
929						} else {
930							delta = Math.max( 1, wh * ( params.range_end - params.range_start ) / 100 + obj_height );
931							shift = w_bottom - obj_top;
932						}
933
934						var x_start_in_px = params.x_start_unit == 'px' || params.x_start_unit == params.x_end_unit ? params.x_start : trx_addons_units2px( params.x_start + params.x_start_unit, obj, 'x' ),
935							x_end_in_px   = params.x_end_unit == 'px' || params.x_start_unit == params.x_end_unit ? params.x_end : trx_addons_units2px( params.x_end + params.x_end_unit, obj, 'x' ),
936							y_start_in_px = params.y_start_unit == 'px' || params.y_start_unit == params.y_end_unit ? params.y_start : trx_addons_units2px( params.y_start + params.y_start_unit, obj, 'y' ),
937							y_end_in_px   = params.y_end_unit == 'px' || params.y_start_unit == params.y_end_unit ? params.y_end : trx_addons_units2px( params.y_end + params.y_end_unit, obj, 'y' ),
938							step_x = x_start_in_px != x_end_in_px ? ( x_end_in_px - x_start_in_px ) / delta : 0,
939							step_y = y_start_in_px != y_end_in_px ? ( y_end_in_px - y_start_in_px ) / delta : 0,
940							step_scale = params.scale_start != params.scale_end ? ( params.scale_end - params.scale_start ) / 100 / delta : 0,
941							step_rotate = params.rotate_start != params.rotate_end ? ( params.rotate_end - params.rotate_start ) / delta : 0,
942							step_opacity = params.opacity_start != params.opacity_end ? ( params.opacity_end - params.opacity_start ) / delta : 0,
943							step_crop = ! trx_addons_is_off( params.crop ) && params.crop_start != params.crop_end ? ( params.crop_end - params.crop_start ) / delta : 0;
944
945						var scroller_init = {
946												overwrite: true,
947												ease: self.get_ease( params.ease )
948											},
949//							transform = '',
950							val = false;
951
952						if ( step_x !== 0 ) {
953							val = Math.round( x_start_in_px + shift * step_x );	// - (params.type == 'bg' && params.x > 0 ? params.x : 0)
954							if ( x_start_in_px < x_end_in_px && val < x_start_in_px || x_start_in_px > x_end_in_px && val > x_start_in_px ) {
955								val = x_start_in_px;
956							}
957							if ( x_start_in_px < x_end_in_px && val > x_end_in_px || x_start_in_px > x_end_in_px && val < x_end_in_px ) {
958								val = x_end_in_px;
959							}
960//							transform += 'translateX(' + val + ( params.x_start_unit == params.x_end_unit ? params.x_start_unit : 'px' ) + ')';
961							scroller_init.x = val + ( params.x_start_unit == params.x_end_unit ? params.x_start_unit : 'px' );
962						}
963
964						if ( step_y !== 0 ) {
965							val = Math.round( y_start_in_px + shift * step_y );	// - (params.type == 'bg' && params.y > 0 ? params.y : 0)
966							if ( y_start_in_px < y_end_in_px && val < y_start_in_px || y_start_in_px > y_end_in_px && val > y_start_in_px ) {
967								val = y_start_in_px;
968							}
969							if ( y_start_in_px < y_end_in_px && val > y_end_in_px || y_start_in_px > y_end_in_px && val < y_end_in_px ) {
970								val = y_end_in_px;
971							}
972//							transform += ( transform != '' ? ' ' : '' ) + 'translateY(' + val + ( params.y_start_unit == params.y_end_unit ? params.y_start_unit : 'px' ) + ')';
973							scroller_init.y = val + ( params.y_start_unit == params.y_end_unit ? params.y_start_unit : 'px' );
974						}
975
976						if ( step_rotate !== 0 ) {
977							val = trx_addons_round_number( params.rotate_start + shift * step_rotate, 2);
978							if ( params.rotate_start < params.rotate_end && val < params.rotate_start || params.rotate_start > params.rotate_end && val > params.rotate_start ) {
979								val = params.rotate_start;
980							}
981							if ( params.rotate_start < params.rotate_end && val > params.rotate_end || params.rotate_start > params.rotate_end && val < params.rotate_end ) {
982								val = params.rotate_end;
983							}
984//							transform += ( transform != '' ? ' ' : '' ) + 'rotate(' + val + 'deg)';
985							scroller_init.rotation = val;
986						}
987
988						if ( step_scale !== 0 ) {
989							val = trx_addons_round_number( params.scale_start / 100 + shift * step_scale, 2 );	//- (params.type == 'bg' && params.scale < 0 ? params.scale / 100 : 0)
990							if ( params.scale_start < params.scale_end && val < params.scale_start / 100 || params.scale_start > params.scale_end && val > params.scale_start / 100 ) {
991								val = params.scale_start / 100;
992							}
993							if ( params.scale_start < params.scale_end && val > params.scale_end / 100 || params.scale_start > params.scale_end && val < params.scale_end / 100 ) {
994								val = params.scale_end / 100;
995							}
996//							transform += ( transform != '' ? ' ' : '' ) + 'scale(' + val + ')';
997							scroller_init.scale = val;
998						}
999
1000						if ( step_opacity !== 0 ) {
1001							val = trx_addons_round_number( params.opacity_start + shift * step_opacity, 2 );
1002							if ( params.opacity_start < params.opacity_end && val < params.opacity_start || params.opacity_start > params.opacity_end && val > params.opacity_start ) {
1003								val = params.opacity_start;
1004							}
1005							if ( params.opacity_start < params.opacity_end && val > params.opacity_end || params.opacity_start > params.opacity_end && val < params.opacity_end ) {
1006								val = params.opacity_end;
1007							}
1008							scroller_init.opacity = Math.max( 0, Math.min( 1, val ) );
1009						}
1010
1011						if ( step_crop !== 0 ) {
1012							val = trx_addons_round_number( params.crop_start + shift * step_crop, 2 );
1013							if ( params.crop_start < params.crop_end && val < params.crop_start || params.crop_start > params.crop_end && val > params.crop_start ) {
1014								val = params.crop_start;
1015							}
1016							if ( params.crop_start < params.crop_end && val > params.crop_end || params.crop_start > params.crop_end && val < params.crop_end ) {
1017								val = params.crop_end;
1018							}
1019							scroller_init.crop = Math.max( 0, Math.min( 100, val ) );
1020							scroller_init.onUpdate = function( t ) {
1021								obj.css( 'clip-path', self.clip_path( obj.prop( 'crop' ), params.crop, obj ) );
1022							};
1023						}
1024
1025						// Save a current transform object to data-param
1026						obj.data( 'trx-parallax-scroller-init', scroller_init );
1027
1028						// Prepare (split) text with 'by words' and 'by chars' effects
1029						if ( [ 'chars', 'words'].indexOf( params.text ) != -1 && obj.data('element_type') !== undefined ) {
1030							var $inner_obj = parallax_text_prepare( obj, [params] );
1031							if ( $inner_obj && $inner_obj.length > 0 ) {
1032								$inner_obj.addClass( 'trx_addons_parallax_blocks_need_start' );
1033								obj.removeClass( 'trx_addons_parallax_blocks_need_start' );
1034								obj = $inner_obj;
1035							}
1036						}
1037
1038						if ( step_crop !== 0 ) {
1039							obj.each( function() {
1040								if ( jQuery( this ).prop( 'crop' ) === undefined ) {
1041									jQuery( this ).prop( 'crop', scroller_init.crop );
1042								}
1043							} );
1044						}
1045
1046						// If any property is changed
1047						var set_start_position = force;	// && obj_visible;
1048						if ( val !== false ) {
1049
1050							var animate = function() {
1051								// if ( set_start_position ) {
1052								// 	// Set a start transform for each object if it is visible in the viewport
1053								// 	var css_init = {
1054								// 		'translate': 'none',
1055								// 		'rotate': 'none',
1056								// 		'scale': 'none',
1057								// 		'transform': transform
1058								// 	};
1059								// 	if ( scroller_init.opacity !== undefined ) {
1060								// 		css_init.opacity = scroller_init.opacity;
1061								// 	}
1062								// 	obj.css( css_init );
1063								// } else {
1064									// Animate each object
1065									obj.each( function(idx) {
1066										if ( idx === 0 || set_start_position ) {
1067											TweenMax.to( obj.eq( idx ), set_start_position ? 0 : params.duration, scroller_init );
1068											if ( set_start_position ) {
1069												obj.eq( idx ).addClass( 'trx_addons_parallax_blocks_on_start' );
1070											}
1071										} else {
1072											setTimeout( function() {
1073												TweenMax.to( obj.eq( idx ), params.duration, scroller_init );
1074											}, ( params.text == 'chars' ? 75 : 250 ) * idx * params.squeeze );
1075										}
1076									} );
1077								// }
1078							};
1079							if ( params.flow == 'entrance' && params.delay > 0 && ! entrance_start ) {
1080								setTimeout( animate, params.delay * 1000 );
1081							} else {
1082								animate();
1083							}
1084						} else if ( set_start_position ) {
1085							obj.addClass( 'trx_addons_parallax_blocks_on_start' );
1086						}
1087					}
1088				}
1089			} );
1090		};
1091
1092		// Reverse crop type
1093		self.crop_reverse = function( params, state ) {
1094			var crop_in  = params.crop_orig ? params.crop_orig : params.crop,
1095				crop_out = crop_in;
1096			if ( state == 'out' ) {
1097				// Save original crop type
1098				if ( ! params.crop_orig ) params.crop_orig = crop_in;
1099				// Reverse crop type
1100				if      ( crop_in == 'wipe_left_right') crop_out = 'wipe_right_left';
1101				else if ( crop_in == 'wipe_right_left') crop_out = 'wipe_left_right';
1102				else if ( crop_in == 'wipe_top_bottom') crop_out = 'wipe_bottom_top';
1103				else if ( crop_in == 'wipe_bottom_top') crop_out = 'wipe_top_bottom';
1104				else if ( crop_in == 'corner_top_left') crop_out = 'corner_bottom_right';
1105				else if ( crop_in == 'corner_top_right') crop_out = 'corner_bottom_left';
1106				else if ( crop_in == 'corner_bottom_left') crop_out = 'corner_top_right';
1107				else if ( crop_in == 'corner_bottom_right') crop_out = 'corner_top_left';
1108				else if ( crop_in == 'box_left') crop_out = 'box_right';
1109				else if ( crop_in == 'box_right') crop_out = 'box_left';
1110				else if ( crop_in == 'box_top') crop_out = 'box_bottom';
1111				else if ( crop_in == 'box_bottom') crop_out = 'box_top';
1112			}
1113			return state == 'in' ? crop_in : crop_out;
1114		};
1115		
1116		// Clip path
1117		self.clip_path = function( val, type, obj ) {
1118			var clip = '';
1119			if ( type == 'circle' ) {
1120				clip = 'circle(' + val + '% at center)';
1121			} else if ( type == 'ellipse_hor' ) {
1122				clip = 'ellipse( ' + Math.min( 100, val * 1.2 ) + '% ' + val + '% at center)';
1123			} else if ( type == 'ellipse_ver' ) {
1124				clip = 'ellipse(' + val + '% ' + Math.min( 100, val * 2.5 ) + '% at center)';
1125			} else {
1126				var border_radius = obj.data( 'trx-addons-clip-border-radius' ) === undefined
1127									? obj.find('>.elementor-widget-container').css( 'border-radius' )
1128									: obj.data( 'trx-addons-clip-border-radius' );
1129				if ( obj.data( 'trx-addons-clip-border-radius' ) === undefined ) {
1130					obj.data( 'trx-addons-clip-border-radius', border_radius );
1131				}
1132				var x_divider     = ['wipe_out_vertical', 'box_center', 'box_top', 'box_bottom'].indexOf( type ) != -1 ? 2 : 1;
1133				var y_divider     = ['wipe_out_horizontal', 'box_center', 'box_left', 'box_right'].indexOf( type ) != -1 ? 2 : 1;
1134				var shift_top     = ['wipe_bottom_top', 'wipe_out_horizontal', 'corner_bottom_left', 'corner_bottom_right', 'box_center', 'box_left', 'box_right', 'box_bottom'].indexOf( type ) != -1 ? 1 : 0;
1135				var shift_bottom  = ['wipe_top_bottom', 'wipe_out_horizontal', 'corner_top_left', 'corner_top_right', 'box_center', 'box_left', 'box_right', 'box_top'].indexOf( type ) != -1 ? 1 : 0;
1136				var shift_left    = ['wipe_right_left', 'wipe_out_vertical', 'corner_top_right', 'corner_bottom_right', 'box_center', 'box_top', 'box_right', 'box_bottom'].indexOf( type ) != -1 ? 1 : 0;
1137				var shift_right   = ['wipe_left_right', 'wipe_out_vertical', 'corner_top_left', 'corner_bottom_left', 'box_center', 'box_top', 'box_left', 'box_bottom'].indexOf( type ) != -1 ? 1 : 0;
1138				clip = 'inset('
1139							+ ( shift_top ? ( 100 - val ) / y_divider : 0 ) + '% '
1140							+ ( shift_right ? ( 100 - val ) / x_divider : 0 ) + '% '
1141							+ ( shift_bottom ? ( 100 - val ) / y_divider : 0 ) + '% '
1142							+ ( shift_left ? ( 100 - val ) / x_divider : 0 ) + '%'
1143							+ ( parseFloat( border_radius ) > 0 ? ' round ' + border_radius : '' )
1144							+ ')';
1145			}
1146			return clip;
1147		};
1148
1149		// Mouse move/leave handlers
1150		//-----------------------------------------
1151		self.mouse_move_handler = function( e ) {
1152			if ( tw === 0 ) {
1153				tl = $targetLayers.offset().left;
1154				tt = $targetLayers.offset().top;
1155				tw = $targetLayers.width();
1156				th = ['window', 'content'].indexOf($targetLayers.data('mouse-handler'))!=-1
1157						? Math.min(trx_addons_window_height(), $targetLayers.height())
1158						: $targetLayers.height();
1159				cx  = Math.ceil( tw / 2 );	// + tl,
1160				cy  = Math.ceil( th / 2 );	// + tt,
1161			}
1162			wst = trx_addons_window_scroll_top() + trx_addons_fixed_rows_height();
1163			ww  = trx_addons_window_width();
1164			wh  = trx_addons_window_height() - trx_addons_fixed_rows_height();
1165			
1166			dx  = e.clientX - tl - cx;
1167			dy  = ['window', 'content'].indexOf($targetLayers.data('mouse-handler'))!=-1
1168						? e.clientY - cy
1169						: e.clientY + wst - tt - cy;
1170			tx  = -1 * ( dx / cx );
1171			ty  = -1 * ( dy / cy );
1172
1173			jQuery.each( mouse_list, self.mouse_move_update );
1174		};
1175
1176		self.mouse_leave_handler = function( e ) {
1177			jQuery.each( mouse_list, function( index, block ) {
1178				var $image = block.selector.find( '.sc_parallax_block_image' ).eq(0);
1179				if ( $image.length === 0 ) {
1180					$image = block.selector;
1181				}
1182
1183				var x = 0, y = 0, z = 0;
1184
1185				// Add scroll parameters
1186				var scroller_init = block.selector.data( 'trx-parallax-scroller-init' );
1187				if ( scroller_init ) {
1188					x = x * 1 + trx_addons_units2px( ( scroller_init.css ? scroller_init.css.x : scroller_init.x ) || 0, block, 'x' );
1189					y = y * 1 + trx_addons_units2px( ( scroller_init.css ? scroller_init.css.y : scroller_init.y ) || 0, block, 'y' );
1190				}
1191
1192				if ( block.prop == 'background' ) {
1193					TweenMax.to(
1194						$image,
1195						1.5,
1196						{
1197							overwrite: true,
1198							backgroundPositionX: block.x + '%',
1199							backgroundPositionY: block.y + '%',
1200							ease: Power2.easeOut
1201						}
1202					);
1203				} else if ( block.prop == 'transform' ) {
1204					TweenMax.to(
1205						$image,
1206						1.5,
1207						{
1208							overwrite: true,
1209							x: x,
1210							y: y,
1211							ease:Power2.easeOut
1212						}
1213					);
1214				} else if ( block.prop == 'transform3d' ) {
1215					TweenMax.to(
1216						$image,
1217						1.5,
1218						{
1219							overwrite: true,
1220							x: x,
1221							y: y,
1222							z: z,
1223							rotationX: 0,
1224							rotationY: 0,
1225							ease:Power2.easeOut
1226						}
1227					);
1228				} else if ( block.prop == 'tilt' ) {
1229					TweenMax.to(
1230						$image,
1231						0.2,
1232						{
1233							overwrite: true,
1234							x: x,
1235							y: y,
1236							z: z,
1237							rotationX: 0,
1238							rotationY: 0,
1239							scale: 1,
1240							transformPerspective: 1500,
1241							ease:Power2.easeOut
1242						}
1243					);
1244				}
1245
1246			} );
1247		};
1248
1249		self.mouse_move_update = function( index, block, time, ease ) {
1250			var	$image   = block.selector.find( '.sc_parallax_block_image' ).eq(0),
1251				speed    = block.speed,
1252				x        = parseFloat( tx * 125 * speed ).toFixed(1),
1253				y        = parseFloat( ty * 125 * speed ).toFixed(1),
1254				z        = block.z * 50,
1255				rotate_x = parseFloat( tx * 25 * speed ).toFixed(1),
1256				rotate_y = parseFloat( ty * 25 * speed ).toFixed(1);
1257			// Add scroll parameters
1258			var scroller_init = block.selector.data( 'trx-parallax-scroller-init' );
1259			if ( scroller_init ) {
1260				x = x * 1 + trx_addons_units2px( ( scroller_init.css ? scroller_init.css.x : scroller_init.x ) || 0, block, 'x' );
1261				y = y * 1 + trx_addons_units2px( ( scroller_init.css ? scroller_init.css.y : scroller_init.y ) || 0, block, 'y' );
1262			}
1263
1264			if ( $image.length === 0 ) {
1265				$image = block.selector;
1266			}
1267
1268			if ( block.prop == 'background' ) {
1269				var bx = block.x * 1 + x / ww * 100,
1270					by = block.y * 1 + y / wh * 100;
1271				TweenMax.to(
1272					$image,
1273					time === undefined ? 1 : time,
1274					{
1275						overwrite: true,
1276						backgroundPositionX: bx + '%',	// 'calc(' + block.x + '%' + ( x > 0 ? ' + ' + x : ' - ' + Math.round( Math.abs( x ) ) ) + 'px)',
1277						backgroundPositionY: by + '%',	// 'calc(' + block.y + '%' + ( y > 0 ? ' + ' + y : ' - ' + Math.round( Math.abs( y ) ) ) + 'px)',
1278						ease: ease === undefined ? Power2.easeOut : ease
1279					}
1280				);
1281			} else if ( block.prop == 'transform' ) {
1282				TweenMax.to(
1283					$image,
1284					time === undefined ? 1 : time,
1285					{
1286						overwrite: true,
1287						x: x,
1288						y: y,
1289						ease: ease === undefined ? Power2.easeOut : ease
1290					}
1291				);
1292			} else if ( block.prop == 'transform3d' ) {
1293				TweenMax.to(
1294					$image,
1295					time === undefined ? 2 : time,
1296					{
1297						overwrite: true,
1298						x: x,
1299						y: y,
1300						z: z,
1301						rotationX: rotate_y,
1302						rotationY: -rotate_x,
1303						ease: ease === undefined ? Power2.easeOut : ease
1304					}
1305				);
1306			} else if ( block.prop == 'tilt' ) {
1307				var m = block.tilt_amount > 0 ? block.tilt_amount : 70,
1308					k = ['window', 'content'].indexOf($targetLayers.data('mouse-handler')) != -1 ? 2 : 4;
1309				z = Math.max(0, block.z);
1310				if ( isNaN(z) ) z = 0;
1311				TweenMax.set( $image,
1312					{
1313						transformOrigin: ((dx + cx) * 25 / tw + 40) + "% " + ((dy + cy) * 25 / th + 40) + "%",
1314						transformPerspective: 1000 + 500 * z
1315					}
1316				);
1317				TweenMax.to(
1318					$image,
1319					time === undefined ? 0.5 : time,
1320					{
1321						overwrite: true,
1322						rotationX:  dy / ( m - k * z ),	// ( m - 2 * z )	//( m * ( z + 2 ) / 2 )
1323						rotationY: -dx / ( m - k * z ),	// ( m - 2 * z )	//( m * ( z + 2 ) / 2 )
1324						y: ty * 2 * z,
1325						x: tx * 2 * z,
1326						z: 2 * z,
1327						scale: 1 + z / 100,
1328						ease: ease === undefined ? Power2.easeOut : ease
1329					}
1330				);
1331			}
1332		};
1333
1334
1335		// Permanent motion handlers
1336		//-----------------------------------------
1337		self.motion_move_handler = function() {
1338			if ( tw === 0 ) {
1339				tl = $targetLayers.offset().left;
1340				tt = $targetLayers.offset().top;
1341				tw = $targetLayers.width();
1342				th = $targetLayers.height();
1343				cx = Math.ceil( tw / 2 );	// + tl,
1344				cy = Math.ceil( th / 2 );	// + tt;
1345			}
1346			jQuery.each( motion_list, function( index, block ) {
1347				var fi,
1348					delta = ( ( motion_period * motion_step ) % ( block['motion_time'] * 1000 ) ) / ( block['motion_time'] * 1000 ),
1349					angle = 2 * Math.PI * delta;
1350				if ( block['motion_dir'] == 'round' ) {
1351					fi = Math.atan2(tw / 2 * Math.sin(angle), th / 2 * Math.cos(angle));
1352					dx = tw / 2 * Math.cos(fi);
1353					dy = th / 2 * Math.sin(fi);
1354				} else if ( block['motion_dir'] == 'random' ) {
1355					dx = -tw + tw * 2 * Math.random();
1356					dy = -th + th * 2 * Math.random();
1357				} else {
1358					dx = block['motion_dir'] == 'vertical' ? 0 : tw / 2 * Math.cos(angle);
1359					dy = block['motion_dir'] == 'horizontal' ? 0 : th / 2 * Math.sin(angle);
1360				}
1361				tx = -1 * ( dx / cx );
1362				ty = -1 * ( dy / cy );
1363				if ( block['motion_dir'] == 'random' ) {
1364					if ( delta === 0 ) {
1365						self.mouse_move_update(index, block, block['motion_time'], Power0.easeNone);
1366					}
1367				} else {
1368					self.mouse_move_update(index, block, block['motion_time'], block['motion_dir'] == 'round' ? Power0.easeNone : Power2.easeOut );
1369				}
1370			} );
1371			motion_step++;
1372		};
1373
1374
1375		// Utilities
1376		//-----------------------------------------
1377
1378		// Return easing method from its name
1379		self.get_ease = function(name) {
1380			name = name.toLowerCase();
1381			if ( name == 'none' || name == 'line' || name == 'linear' || name == 'power0' )
1382				return Power0.easeNone;
1383			else if ( name == 'power1')
1384				return Power1.easeOut;
1385			else if ( name == 'power2')
1386				return Power2.easeOut;
1387			else if ( name == 'power3')
1388				return Power3.easeOut;
1389			else if ( name == 'power4')
1390				return Power4.easeOut;
1391			else if ( name == 'back')
1392				return Back.easeOut;
1393			else if ( name == 'elastic')
1394				return Elastic.easeOut;
1395			else if ( name == 'bounce')
1396				return Bounce.easeOut;
1397			else if ( name == 'rough')
1398				return Rough.easeOut;
1399			else if ( name == 'slowmo')
1400				return SlowMo.easeOut;
1401			else if ( name == 'stepped')
1402				return Stepped.easeOut;
1403			else if ( name == 'circ')
1404				return Circ.easeOut;
1405			else if ( name == 'expo')
1406				return Expo.easeOut;
1407			else if ( name == 'sine')
1408				return Sine.easeOut;
1409		};
1410	};
1411
1412
1413	// New parallax (to fix Google Chrome scroll)
1414	// CSS transform3D and perspective are used instead shift background position on scroll events
1415	// This method needs a special layout:
1416	// 	body (with overflow hidden)
1417	// 		.viewport (with overflow-y: scroll | auto and height: 100%)
1418	//			.parallax_wrap
1419	//				.parallax_image
1420	//				.parallax_image
1421	//				.parallax_image
1422	//				...
1423	//----------------------------------------------------------------------------
1424	window.trx_addons_bg_parallax = function(clip) {
1425		var parallax        = clip.querySelectorAll('.sc_parallax_block_image[parallax]'),
1426			parallaxDetails = [],
1427			sticky          = false;
1428		
1429		// Edge requires a transform on the document body and a fixed position element
1430		// in order for it to properly render the parallax effect as you scroll.
1431		// See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/5084491/
1432//		if (getComputedStyle(document.body).transform == 'none') {
1433			// Broke page in WordPress - admin bar shift down and margin-top is appear in the body
1434//			document.body.style.transform = 'translateZ(0)';
1435//		}
1436
1437		var fixedPos = document.createElement('div');
1438		fixedPos.style.position = 'fixed';
1439		fixedPos.style.top = '0';
1440		fixedPos.style.width = '1px';
1441		fixedPos.style.height = '1px';
1442		fixedPos.style.zIndex = 1;
1443		document.body.insertBefore(fixedPos, document.body.firstChild);
1444
1445		for ( var i = 0; i < parallax.length; i++ ) {
1446			var elem = parallax[i];
1447			var container = elem.parentNode;
1448			if ( getComputedStyle(container).overflow != 'visible' ) {
1449				console.error('Need non-scrollable container to apply perspective for', elem);
1450				continue;
1451			}
1452			if ( clip && container.parentNode != clip ) {
1453				console.warn('Currently we only track a single overflow clip, but elements from multiple clips found.', elem);
1454			}
1455			clip = container.parentNode;
1456			if (getComputedStyle(clip).overflow == 'visible') {
1457				console.error('Parent of sticky container should be scrollable element', elem);
1458			}
1459			// TODO(flackr): optimize to not redo this for the same clip/container.
1460			var perspectiveElement;
1461			if (sticky || getComputedStyle(clip).webkitOverflowScrolling) {
1462				sticky = true;
1463				perspectiveElement = container;
1464			} else {
1465				perspectiveElement = clip;
1466				container.style.transformStyle = 'preserve-3d';
1467			}
1468			perspectiveElement.style.perspectiveOrigin = 'bottom right';
1469			perspectiveElement.style.perspective = '1px';
1470			if (sticky) {
1471				elem.style.position = '-webkit-sticky';
1472				elem.style.top = '0';
1473			}
1474			elem.style.transformOrigin = 'bottom right';
1475			// Find the previous and next elements to parallax between.
1476			var previousCover = parallax[i].previousElementSibling;
1477			while (previousCover && previousCover.hasAttribute('parallax')) {
1478				previousCover = previousCover.previousElementSibling;
1479			}
1480			var nextCover = parallax[i].nextElementSibling;
1481			while (nextCover && !nextCover.hasAttribute('parallax-cover')) {
1482				nextCover = nextCover.nextElementSibling;
1483			}
1484			parallaxDetails.push( {
1485				'node': parallax[i],
1486				'top': parallax[i].offsetTop,
1487				'sticky': !!sticky,
1488				'nextCover': nextCover,
1489				'previousCover': previousCover
1490			} );
1491		}
1492
1493		for ( i = 0; i < parallax.length; i++ ) {
1494			parallax[i].parentNode.insertBefore(parallax[i], parallax[i].parentNode.firstChild);
1495		}
1496
1497		// Add a scroll listener to hide perspective elements when they should no longer be visible.
1498		clip.addEventListener( 'scroll', function() {
1499			for (var i = 0; i < parallaxDetails.length; i++) {
1500				var container = parallaxDetails[i].node.parentNode;
1501				var previousCover = parallaxDetails[i].previousCover;
1502				var nextCover = parallaxDetails[i].nextCover;
1503				var parallaxStart = previousCover ? (previousCover.offsetTop + previousCover.offsetHeight) : 0;
1504				var parallaxEnd = nextCover ? nextCover.offsetTop : container.offsetHeight;
1505				var threshold = 200;
1506				var visible = parallaxStart - threshold - clip.clientHeight < clip.scrollTop &&
1507				parallaxEnd + threshold > clip.scrollTop;
1508				// FIXME: Repainting the images while scrolling can cause jank.
1509				// For now, keep them all.
1510				// var display = visible ? 'block' : 'none'
1511				var display = 'block';
1512				if (parallaxDetails[i].node.style.display != display) {
1513					parallaxDetails[i].node.style.display = display;
1514				}
1515			}
1516		} );
1517
1518		var bg_parallax_resize = function(details) {
1519			for (var i = 0; i < details.length; i++) {
1520				var container = details[i].node.parentNode;
1521				var clip = container.parentNode;
1522				var previousCover = details[i].previousCover;
1523				var nextCover = details[i].nextCover;
1524				var rate = details[i].node.getAttribute('parallax');
1525				var parallaxStart = previousCover ? (previousCover.offsetTop + previousCover.offsetHeight) : 0;
1526				var scrollbarWidth = details[i].sticky ? 0 : clip.offsetWidth - clip.clientWidth;
1527				var parallaxElem = details[i].sticky ? container : clip;
1528				var height = details[i].node.offsetHeight;
1529				var depth = 0;
1530				if ( rate ) {
1531					depth = 1 - (1 / rate);
1532				} else {
1533					var parallaxEnd = nextCover ? nextCover.offsetTop : container.offsetHeight;
1534					depth = (height - parallaxEnd + parallaxStart) / (height - clip.clientHeight);
1535				}
1536				if ( details[i].sticky ) {
1537					depth = 1.0 / depth;
1538				}
1539				var scale = 1.0 / (1.0 - depth);
1540				// The scrollbar is included in the 'bottom right' perspective origin.
1541				var dx = scrollbarWidth * (scale - 1);
1542				// Offset for the position within the container.
1543				var dy = details[i].sticky
1544							? -(clip.scrollHeight - parallaxStart - height) * (1 - scale)
1545							: (parallaxStart - depth * (height - clip.clientHeight)) * scale;
1546				details[i].node.style.transform = 'scale(' + (1 - depth) + ') translate3d(' + dx + 'px, ' + dy + 'px, ' + depth + 'px)';
1547			}
1548		};
1549
1550		window.addEventListener('resize', bg_parallax_resize.bind(null, parallaxDetails));
1551		bg_parallax_resize(parallaxDetails);
1552
1553	};
1554
1555}() );

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.