1/** 2 * Master Slider Layer Element 3 * @author Averta 4 * @package Master Slider jQuery 5 */ 6 7;(function($){ 8 9 /** 10 * master slider layer element constructor 11 */ 12 window.MSLayerElement = function(){ 13 14 // default layer start animation 15 this.start_anim = { 16 name : 'fade', 17 duration : 1000, 18 ease : 'linear', 19 delay : 0 20 }; 21 22 // default layer end animation 23 this.end_anim = { 24 duration : 1000, 25 ease : 'linear' 26 }; 27 28 // default layer type 29 this.type = 'text'; // video , image 30 31 //this.swipe = true; 32 this.resizable = true; 33 this.minWidth = -1; 34 this.isVisible = true; 35 36 // list of styles which should stores initial values and changes based on screen size for resizable layers 37 this.__cssConfig = [ 38 'margin-top' , 'padding-top' , 39 'margin-bottom' , 'padding-left' , 40 'margin-right' , 'padding-right' , 41 'margin-left' , 'padding-bottom' , 42 43 44 'font-size' , 'line-height' , 45 /*'height' , */ 'width' , 46 'left' , 'right' , 47 'top' , 'bottom' 48 ]; 49 50 this.baseStyle = {}; 51 }; 52 53 var p = MSLayerElement.prototype; 54 55 /*--------------------------------------------------*\ 56 Public Methods 57 \*--------------------------------------------------*/ 58 59 /** 60 * determine start animation for the layer 61 * @param {Objec} anim 62 */ 63 p.setStartAnim = function(anim){ 64 $.extend(this.start_anim , anim); $.extend(this.start_anim, this._parseEff(this.start_anim.name)); 65 this.$element.css('visibility' , 'hidden'); 66 }; 67 68 /** 69 * determine end/hide animation for the layer 70 * @param {Object} anim 71 */ 72 p.setEndAnim = function(anim){ 73 $.extend(this.end_anim, anim); 74 }; 75 76 /** 77 * create layer object from layer element 78 */ 79 p.create = function(){ 80 this.$element.css('display', 'none'); 81 82 // resizable layer 83 this.resizable = this.$element.data('resize') !== false; 84 85 // fixed positioning 86 this.fixed = this.$element.data('fixed') === true; 87 88 // hide under parameter 89 if( this.$element.data('widthlimit') !== undefined ) { 90 this.minWidth = this.$element.data('widthlimit'); 91 } 92 93 if( !this.end_anim.name ) { 94 this.end_anim.name = this.start_anim.name; 95 } 96 97 if( this.end_anim.time ) { 98 this.autoHide = true;//this.end_anim.delay = this.slide.delay * 1000 - this.end_anim.duration; 99 } 100 101 // is this layer static? 102 this.staticLayer = this.$element.data('position') === 'static'; 103 this.fixedLayer = this.$element.data('position') === 'fixed'; 104 this.layersCont = this.controller.$layers; 105 106 // make it visible if it's static 107 if ( this.staticLayer ) { 108 this.$element.css('display', '') 109 .css('visibility', ''); 110 } 111 112 // create action event 113 // @since v1.7.2 114 if( this.$element.data('action') !== undefined ) { 115 var slideController = this.slide.slider.slideController; 116 this.$element.on( this.$element.data('action-event') || 'click' , function(event){ 117 slideController.runAction($(this).data('action')); 118 event.preventDefault(); 119 }).addClass('ms-action-layer'); 120 } 121 122 $.extend(this.end_anim , this._parseEff(this.end_anim.name)); 123 this.slider = this.slide.slider; 124 125 // masked layer 126 if ( this.masked ) { 127 this.$mask = $('<div></div>').addClass('ms-layer-mask'); 128 129 if ( this.link ) { 130 this.link.wrap(this.$mask); 131 this.$mask = this.link.parent(); 132 } else { 133 this.$element.wrap(this.$mask); 134 this.$mask = this.$element.parent(); 135 } 136 137 if ( this.maskWidth ) { 138 this.$mask.width(this.maskWidth); 139 } 140 141 if ( this.maskHeight ) { 142 this.$mask.height(this.maskHeight); 143 144 // add height to css check 145 if ( this.__cssConfig.indexOf('height') === -1 ) { 146 this.__cssConfig.push('height'); 147 } 148 } 149 } 150 151 // new alignment method 152 // @since v1.6.1 153 var layerOrigin = this.layerOrigin = this.$element.data('origin'); 154 155 if ( layerOrigin ){ 156 157 var vOrigin = layerOrigin.charAt(0), 158 hOrigin = layerOrigin.charAt(1), 159 offsetX = this.$element.data('offset-x'), 160 offsetY = this.$element.data('offset-y'), 161 layerEle = this.masked ? this.$mask[0] : this.$element[0]; 162 163 if( offsetY === undefined ){ 164 offsetY = 0; 165 } 166 167 switch ( vOrigin ){ 168 case 't': 169 layerEle.style.top = offsetY + 'px'; 170 break; 171 case 'b': 172 layerEle.style.bottom = offsetY + 'px'; 173 break; 174 case 'm': 175 layerEle.style.top = offsetY + 'px'; 176 this.middleAlign = true; 177 } 178 179 if( offsetX === undefined ){ 180 offsetX = 0; 181 } 182 183 184 switch ( hOrigin ){ 185 case 'l': 186 layerEle.style.left = offsetX + 'px'; 187 break; 188 case 'r': 189 layerEle.style.right = offsetX + 'px'; 190 break; 191 case 'c': 192 layerEle.style.left = offsetX + 'px'; 193 this.centerAlign = true; 194 } 195 } 196 197 // parallax effect 198 // @since v1.6.0 199 this.parallax = this.$element.data('parallax') 200 if( this.parallax != null ) { 201 this.parallax /= 100; 202 this.$parallaxElement = $('<div></div>').addClass('ms-parallax-layer'); 203 204 if( this.masked ) { 205 this.$mask.wrap(this.$parallaxElement); 206 this.$parallaxElement = this.$mask.parent(); 207 } else if( this.link ) { // only for image layer 208 this.link.wrap(this.$parallaxElement); 209 this.$parallaxElement = this.link.parent(); 210 } else { 211 this.$element.wrap(this.$parallaxElement); 212 this.$parallaxElement = this.$element.parent(); 213 } 214 215 this._lastParaX = 0; 216 this._lastParaY = 0; 217 this._paraX = 0; 218 this._paraY = 0; 219 220 221 // add bottom 0 to the parallax element if layer origin specified to the bottom 222 this.alignedToBot = this.layerOrigin && this.layerOrigin.indexOf('b') !== -1; 223 if( this.alignedToBot ) { 224 this.$parallaxElement.css('bottom', 0); 225 } 226 227 if( window._css3d ){ 228 this.parallaxRender = this._parallaxCSS3DRenderer; 229 } else if ( window._css2d ){ 230 this.parallaxRender = this._parallaxCSS2DRenderer; 231 } else { 232 this.parallaxRender = this._parallax2DRenderer; 233 } 234 235 if( this.slider.options.parallaxMode !== 'swipe' ){ // mouse mode 236 averta.Ticker.add(this.parallaxRender, this); 237 } 238 } 239 240 // remove all data- attributes excluding data-src 241 $.removeDataAttrs(this.$element, ['data-src']); 242 }; 243 244 /** 245 * initialize layer 246 */ 247 p.init = function(){ 248 //if(this.initialized) return; 249 this.initialized = true; 250 251 var value; 252 253 this.$element.css('visibility' , ''); 254 // store initial layer styles 255 for(var i = 0 , l = this.__cssConfig.length; i < l ; i ++){ 256 var key = this.__cssConfig[i]; 257 if ( this._isPosition(key) && this.masked ) { 258 value = this.$mask.css(key); 259 } else if( this.type === 'text' && key === 'width' && !this.masked && !this.maskWidth ){ // in some browsers using computed style for width in text layer causes unexpected word wrapping 260 value = this.$element[0].style.width; 261 } else { 262 263 value = this.$element.css(key);
264 var isSize = key === 'width' || key === 'height'; 265 266 if ( isSize && this.masked ){ 267 if ( this.maskWidth && key === 'width' ) { 268 value = this.maskWidth + 'px'; 269 } else if ( this.maskHeight && key === 'height') { 270 value = this.maskHeight + 'px'; 271 } 272 } 273 274 // fix for Google Chrome in ios, sometimes image layers over first slide not showing correctly. 275 if ( isSize && value === '0px' ) { 276 value = this.$element.data(key) + 'px'; 277 } 278 } 279 280 // skip unnecessary positioning styles 281 if ( this.layerOrigin && ( 282 ( key === 'top' && this.layerOrigin.indexOf('t') === -1 && this.layerOrigin.indexOf('m') === -1 ) || 283 ( key === 'bottom' && this.layerOrigin.indexOf('b') === -1 ) || 284 ( key === 'left' && this.layerOrigin.indexOf('l') === -1 && this.layerOrigin.indexOf('c') === -1 ) || 285 ( key === 'right' && this.layerOrigin.indexOf('r') === -1 ) ) 286 ) { 287 continue; 288 } 289 290 if( value != 'auto' && value != "" && value != "normal" ) { 291 this.baseStyle[key] = parseInt(value); 292 } 293 } 294 295 // @since v1.6.0 296 if ( this.middleAlign ){ 297 this.baseHeight = this.$element.outerHeight(false);//this.$element.height(); 298 } 299 300 if ( this.centerAlign ){ 301 // in some browsers using computed style for width in text layer causes unexpected word wrapping 302 //if ( this.type === 'text' ){ 303 // this.baseWidth = parseInt(this.$element[0].style.width); 304 //} else { 305 this.baseWidth = this.$element.outerWidth(false); 306 //} 307 } 308 309 }; 310 311 /** 312 * locate layer over slider 313 */ 314 p.locate = function(){ 315 316 // is slide ready? 317 if ( !this.slide.ready ) { 318 return; 319 } 320 321 var width = parseFloat(this.layersCont.css('width')), 322 height = parseFloat(this.layersCont.css('height')), 323 factor, isPosition, isSize; 324 325 if( !this.staticLayer && this.$element.css('display') === 'none' && this.isVisible) { 326 this.$element.css('display', '') 327 .css('visibility', 'hidden'); 328 } 329 330 if ( this.staticLayer ) { 331 this.$element.addClass('ms-hover-active'); 332 } 333 334 factor = this.resizeFactor = width / this.slide.slider.options.width; 335 336 var $layerEle = this.masked ? this.$mask : this.$element; 337 338 // updated @since v1.6.1 339 for (var key in this.baseStyle) { 340 341 isPosition = this._isPosition(key);
342 isSize = key === 'width' || key === 'height'; 343 344 //switch resize/position factor 345 if( this.fixed && isPosition ){ 346 factor = 1; 347 } else { 348 factor = this.resizeFactor; 349 } 350 351 if( !this.resizable && !isPosition ){ 352 continue; 353 } 354 355 if ( key === 'top' && this.middleAlign ){ 356 $layerEle[0].style.top = '0px'; 357 this.baseHeight = $layerEle.outerHeight(false); 358 $layerEle[0].style.top = this.baseStyle['top'] * factor + (height - this.baseHeight) / 2 + 'px'; 359 } else if ( key === 'left' && this.centerAlign ){ 360 $layerEle[0].style.left = '0px'; 361 this.baseWidth = $layerEle.outerWidth(false); 362 $layerEle[0].style.left = this.baseStyle['left'] * factor + (width - this.baseWidth) / 2 + 'px'; 363 } else if ( isPosition && this.masked ) { 364 $layerEle[0].style[key] = this.baseStyle[key] * factor + 'px'; 365 } else if ( isSize && ( (key === 'width' && this.maskWidth) || (key === 'height' && this.maskHeight) ) ) { 366 $layerEle[0].style[key] = this.baseStyle[key] * factor + 'px'; 367 } else { 368 this.$element.css(key , this.baseStyle[key] * factor + 'px'); 369 } 370 } 371 372 373 this.visible(this.minWidth < width); 374 }; 375 376 /** 377 * start layer animation 378 */ 379 p.start = function(){ 380 381 // is it already showing or is it a static layer? 382 if ( this.isShowing || this.staticLayer ) { 383 return; 384 } 385 386 this.isShowing = true; 387 this.$element.removeClass('ms-hover-active'); 388 389 var key , base; 390 391 // reads css value form LayerEffects 392 MSLayerEffects.rf = this.resizeFactor; 393 var effect_css = MSLayerEffects[this.start_anim.eff_name].apply(null , this._parseEffParams(this.start_anim.eff_params)); 394 395 // checkes effect css and defines TO css values 396 var start_css_eff = {}; 397 398 // set from position 399 for(key in effect_css){ 400 401 // check the position key (top, left, right or bottom) for animatin 402 // It mostly will be used in old browsers 403 // In effect left:100, layer base style right:300 -> effect changes to right:100 404 if( this._checkPosKey(key , effect_css) ){ 405 continue; 406 } 407 408 // set default value from Layer Effects Class 409 if( MSLayerEffects.defaultValues[key] != null ){ 410 start_css_eff[key] = MSLayerEffects.defaultValues[key]; 411 } 412 413 if( key in this.baseStyle ){ 414 base = this.baseStyle[key]; 415 416 // updated @since v1.6.1 417 if ( this.middleAlign && key === 'top' ){ 418 base += (parseInt(this.layersCont.height()) - this.$element.outerHeight(false)) / 2; 419 } 420 421 if ( this.centerAlign && key === 'left' ){
422 base += (parseInt(this.layersCont.width()) - this.$element.outerWidth(false)) / 2; 423 } 424 //---------------------- 425 426 effect_css[key] = base + parseFloat(effect_css[key]) + 'px'; 427 start_css_eff[key] = base + 'px'; 428 } 429 430 this.$element.css(key , effect_css[key]); 431 } 432 433 var that = this; 434 435 clearTimeout(this.to); 436 clearTimeout(this.clHide); 437 this.to = setTimeout(function(){ 438 //that.locate(); 439 that.$element.css('visibility', ''); 440 that._playAnimation(that.start_anim , start_css_eff); 441 } , that.start_anim.delay || 0.01); 442 443 444 this.clTo = setTimeout(function(){ 445 that.show_cl = true; 446 that.$element.addClass('ms-hover-active'); 447 },(this.start_anim.delay || 0.01) + this.start_anim.duration + 1); 448 449 if( this.autoHide ){ 450 clearTimeout(this.hto); 451 this.hto = setTimeout(function(){that.hide();} , that.end_anim.time ); 452 } 453 454 }; 455 456 /** 457 * starts hide animation 458 */ 459 p.hide = function(){ 460 461 // static layers doesn't support animations 462 if ( this.staticLayer ) { 463 return; 464 } 465 466 this.$element.removeClass('ms-hover-active'); 467 468 this.isShowing = false; 469 470 // reads css value form LayerEffects 471 var effect_css = MSLayerEffects[this.end_anim.eff_name].apply(null , this._parseEffParams(this.end_anim.eff_params)); 472 473 for(key in effect_css){ 474 475 if(this._checkPosKey(key , effect_css)) continue; 476 477 if( key === window._jcsspfx + 'TransformOrigin' ){ 478 this.$element.css(key , effect_css[key]); 479 } 480 481 if(key in this.baseStyle){ 482 effect_css[key] = this.baseStyle[key] + parseFloat(effect_css[key]) + 'px'; 483 } 484 485 } 486 487 this._playAnimation(this.end_anim , effect_css); 488 489 clearTimeout(this.clHide); 490 491 if ( effect_css.opacity === 0 ) { 492 this.clHide = setTimeout( function(){ this.$element.css('visibility', 'hidden'); }.bind(this), this.end_anim.duration + 1 ); 493 } 494 495 clearTimeout(this.to); 496 clearTimeout(this.hto); 497 clearTimeout(this.clTo); 498 }; 499 500 /** 501 * reset layer 502 */ 503 p.reset = function(){ 504 if ( this.staticLayer ) { 505 return; 506 } 507 508 this.isShowing = false; 509 //this.$element.css(window._csspfx + 'animation-name', '' ); 510 this.$element[0].style.display = 'none'; 511 this.$element.css('opacity', ''); 512 this.$element[0].style['transitionDuration'] = ''; 513 514 if(this.show_tween) 515 this.show_tween.stop(true); 516 517 clearTimeout(this.to); 518 clearTimeout(this.hto); 519 }; 520 521 /** 522 * destroy layer 523 */ 524 p.destroy = function(){ 525 this.reset(); 526 this.$element.remove(); 527 }; 528 529 /** 530 * change the visibility status 531 * @param {Boolean} value 532 */ 533 p.visible = function(value){ 534 if(this.isVisible == value) return; 535 536 this.isVisible = value; 537 538 this.$element.css('display' , (value ? '' : 'none')); 539 }; 540 541 /** 542 * Change the detestation of parallax position 543 * @param {Number} x 544 * @param {Number} y 545 * @since 1.6.0 546 */ 547 p.moveParallax = function(x, y , fast){ 548 this._paraX = x; 549 this._paraY = y; 550 if( fast ){ 551 this._lastParaX = x; 552 this._lastParaY = y; 553 this.parallaxRender(); 554 } 555 }; 556 557 /*------------------------------------*\ 558 Private Methods 559 \*------------------------------------*/ 560 561 /** 562 * play layer animation 563 * @param {Obeject} animation layer animation object 564 * @param {Object} css animation css object 565 */ 566 p._playAnimation = function(animation , css){ 567 var options = {}; 568 569 if(animation.ease){ 570 options.ease = animation.ease; 571 } 572 573 options.transProperty = window._csspfx + 'transform,opacity'; 574
575 if( this.show_tween ) { 576 this.show_tween.stop(true); 577 } 578 579 this.show_tween = CTween.animate(this.$element, animation.duration , css , options); 580 }; 581 582 /** 583 * generate random value 584 * @param {String} value the pattern value min|max 585 * @return {Number} 586 */ 587 p._randomParam = function(value){ 588 var min = Number(value.slice(0,value.indexOf('|'))); 589 var max = Number(value.slice(value.indexOf('|')+1)); 590 591 return min + Math.random() * (max - min); 592 }; 593 594 /** 595 * parse effect function 596 * @param {String} eff_name effect function 597 * @return {Object} 598 */ 599 p._parseEff = function(eff_name){ 600 601 var eff_params = []; 602 603 if ( eff_name.indexOf('(') !== -1 ) { 604 var temp = eff_name.slice(0 , eff_name.indexOf('(')).toLowerCase(); 605 var value; 606 607 eff_params = eff_name.slice(eff_name.indexOf('(') + 1 , -1).replace(/\"|\'|\s/g , '').split(','); 608 eff_name = temp; 609 610 for ( var i = 0, l = eff_params.length; i < l; ++i) { 611 value = eff_params[i]; 612 613 if ( value in MSLayerEffects.presetEffParams) { 614 value = MSLayerEffects.presetEffParams[value]; 615 } 616 617 eff_params[i] = value; 618 } 619 } 620 621 return {eff_name:eff_name , eff_params:eff_params}; 622 }; 623 624 /** 625 * parse effect function parameters 626 * @param {Aarray} params effect parameters 627 * @return {Array} 628 */ 629 p._parseEffParams = function(params){ 630 var eff_params = []; 631 for(var i = 0 , l = params.length; i < l ; ++i){ 632 var value = params[i]; 633 if(typeof value === 'string' && value.indexOf('|') !== -1) value = this._randomParam(value); 634 635 eff_params[i] = value; 636 } 637 638 return eff_params; 639 }; 640 641 /** 642 * calculates layer position based on initial positioning style and layer effect 643 * @param {string} key positioning key 644 * @param {Object} style style object 645 * @return {Boolean} 646 */ 647 p._checkPosKey = function(key , style){ 648 if(key === 'left' && !(key in this.baseStyle) && 'right' in this.baseStyle){ 649 style.right = -parseInt(style.left) + 'px'; 650 delete style.left; 651 return true; 652 } 653 654 if(key === 'top' && !(key in this.baseStyle) && 'bottom' in this.baseStyle){ 655 style.bottom = -parseInt(style.top) + 'px'; 656 delete style.top; 657 return true; 658 } 659 660 return false; 661 }; 662 663 /** 664 * checks for position key 665 * @param {String} key 666 * @return {Boolean} [description] 667 */ 668 p._isPosition = function( key ) { 669 return key === 'top' || key === 'left' || key === 'bottom' || key === 'right'; 670 }; 671 672 /** 673 * calculate parallax position 674 */ 675 p._parallaxCalc = function(){ 676 var x_def = this._paraX - this._lastParaX, 677 y_def = this._paraY - this._lastParaY; 678 679 this._lastParaX += x_def / 12; 680 this._lastParaY += y_def / 12; 681 682 if( Math.abs( x_def ) < 0.019 ) { 683 this._lastParaX = this._paraX; 684 } 685 686 if( Math.abs( y_def ) < 0.019 ) { 687 this._lastParaY = this._paraY; 688 } 689 690 } 691 692 /** 693 * Parallax move ticker function 694 */ 695 p._parallaxCSS3DRenderer = function(){ 696 this._parallaxCalc(); 697 this.$parallaxElement[0].style[window._jcsspfx + 'Transform'] = 'translateX(' + this._lastParaX * this.parallax + 'px) translateY(' + this._lastParaY * this.parallax + 'px) translateZ(0)'; 698 }; 699 700 /** 701 * parallax move ticker for CSS2 browsers 702 * @return {[type]} [description] 703 */ 704 p._parallaxCSS2DRenderer = function(){ 705 this._parallaxCalc(); 706 this.$parallaxElement[0].style[window._jcsspfx + 'Transform'] = 'translateX(' + this._lastParaX * this.parallax + 'px) translateY(' + this._lastParaY * this.parallax + 'px)'; 707 }; 708 709 /** 710 * parallax move ticker for zombie browsers 711 */ 712 p._parallax2DRenderer = function(){ 713 this._parallaxCalc(); 714 715 // change bottom instead of top if layer aligned to the bottom (origin) 716 if( this.alignedToBot ) { 717 this.$parallaxElement[0].style.bottom = this._lastParaY * this.parallax + 'px'; 718 } else { 719 this.$parallaxElement[0].style.top = this._lastParaY * this.parallax + 'px'; 720 } 721 722 this.$parallaxElement[0].style.left = this._lastParaX * this.parallax + 'px'; 723 }; 724 725})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.