PageSourceSearch

https://www.cutpoint-inc.com/assets/plugins/master-slider/source/layers/LayerElement.js

js cutpoint-inc.com collected 2026-10-02 01:29:12 UTC 21,348 bytes, 725 lines download raw bytes

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.