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.