text: /* 
   * @author    ThemePunch <info@themepunch.com>
   * @link      http://www.themepunch.com/
   * @copyright 2017 ThemePunch
  */
  
  ;(function() {
  	
  	var $, 
  		engine,
  	    requestFrame = window.requestAnimationFrame;
  
  		 
  	window.RsAddonPanorama = function(_$, slider) {
  		
  		if(!engine) {
  			
  			engine = webGL();
  			if(!engine) {
  				
  				slider.addClass('pano-no-webgl');
  				return;
  				
  			}
  			
  		}
  		
  		if(!_$ || !slider || typeof THREE === 'undefined' || !requestFrame) return;
  		if(!slider.find('li[data-panorama]').length) return;
  		
  		$ = _$;
  		$.event.special.rsPanoramaDestroyed = {remove: function(evt) {evt.handler();}};
  		
  		return new Panorama(slider);
  		
  	};
  	
  	function Panorama(slider) {
  		
  		this.slider = slider;	
  		this.slides = [];
  		this.panos = slider.find('li[data-panorama]').each(function(i) {
  			
  			if(i === 0) this.setAttribute('data-fstransition', 'notransition');
  			this.setAttribute('data-transition', 'fade');
  			
  		});
  		
  		slider.one('revolution.slide.onloaded', this.onLoaded.bind(this))
  			  .one('rsPanoramaDestroyed', this.destroy.bind(this));
  		
  	}
  	
  	Panorama.prototype = {
  		
  		onLoaded: function() {
  			
  			this.slider.one('revolution.slide.onchange', this.onReady.bind(this));
  			jQuery(window).on('blur.rsaddonpanorama', this.onBlur.bind(this));
  			
  		},
  		
  		onReady: function(e, data) {
  			
  			this.resize();
  			var $this = this;
  			this.panos.each(function(i) {
  				
  				$this.slides[i] = new PanoramaSlide($(this), $this.slider, $this.width, $this.height);
  				
  			});
  			
  			this.slider.on('revolution.slide.afterdraw', this.resize.bind(this))
  			           .on('revolution.slide.onbeforeswap', this.beforeSwap.bind(this))
  					   .on('revolution.slide.onafterswap', this.afterSwap.bind(this))
  					   .on('layeraction', this.layerAction.bind(this));
  					   
  			var slide = $.data(data.currentslide[0], 'rsaddonpanorama');
  			if(slide) slide.onReset();
  			this.panos = null;
  			
  		},
  		
  		beforeSwap: function(e, data) {
  			
  			var slide = $.data(data.currentslide[0], 'rsaddonpanorama');
  			if(slide && slide.controls) slide.removeEvents();
  			
  			slide = $.data(data.nextslide[0], 'rsaddonpanorama');
  			if(slide) slide.onReset();
  			
  		},
  		
  		afterSwap: function(e, data) {
  			
  			this.currentSlide = $.data(data.currentslide[0], 'rsaddonpanorama');
  			if(!data.prevslide.length) return;
  			
  			var slide = $.data(data.prevslide[0], 'rsaddonpanorama');
  			if(slide) slide.paused = true;
  			
  		},
  		
  		resize: function() {
  			
  			this.width = this.slider.width();
  			this.height = this.slider.height();
  			
  			var i = this.slides.length,
  			    slide;
  				
  			while(i--) {
  				
  				slide = this.slides[i];
  				slide.resize(this.width, this.height);
  				
  			}
  			
  		},
  		
  		onBlur: function() {
  			
  			var i = this.slides.length,
  			    slide;
  				
  			while(i--) {
  				
  				slide = this.slides[i];
  				slide.clear();
  				slide.canvas.trigger('mouseup').trigger('mouseleave').trigger('touchend');
  				
  			}
  			
  		},
  		
  		layerAction: function(e, data) {
  			
  			data = data.event;
  			var action = data.action;
  			
  			if(action && action.search('panorama') !== -1 && this.currentSlide) {
  				
  				var perc = data.hasOwnProperty('percentage') ? data.percentage * 0.01 : false;
  				this.currentSlide.action(action.replace('panorama_', ''), perc);
  				
  			}
  			
  		},
  		
  		destroy: function() {
  			
  			if(this.slides) {
  			
  				while(this.slides.length) {
  					
  					this.slides[0].destroy();
  					this.slides.shift();
  					
  				}
  				
  			}
  			
  			for(var prop in this) if(this.hasOwnProperty(prop)) delete this[prop];
  			
  		}
  	
  	};
  	
  	function PanoramaSlide(slide, slider, width, height) {
  		
  		var options = JSON.parse(slide.attr('data-panorama'));
  		
  		this.x = 0;
  		this.y = 0;
  		this.zoomVal = 1;
  		this.width = width;
  		this.height = height;
  		this.slide = slide;
  		this.slider = slider;
  		this.distX = false;
  		this.distY = false;
  		
  		this.image = options.image;
  		this.controls = options.controls;
  		this.drag = this.controls === 'drag';
  		this.thrw = this.controls === 'throw';
  		this.move = this.drag || this.thrw;
  		this.mouse = this.controls === 'mouse';
  		this.click = this.controls === 'click';
  		this.autoplay = options.autoplay == 'true';
  		this.zoom = options.mousewheelZoom == 'true';
  		this.smoothZoom = options.smoothZoom == 'true';
  		
  		var direction = options.autoplayDirection === 'forward' ? 1 : -1;
  		this.autoplaySpeed = parseInt(options.autoplaySpeed, 10) * 0.001;
  		this.speed = this.autoplaySpeed * direction;
  		
  		this.throwSpeed = parseInt(options.throwSpeed, 10) * 0.001;
  		this.zoomMax = 2 - (parseInt(options.zoomMax, 10) * 0.01);
  		this.zoomMin = 2 - (parseInt(options.zoomMin, 10) * 0.01);
  		this.fov = parseInt(options.cameraFov, 10);
  		
  		this.onStart = this.start.bind(this);
  		this.onZoom = this.zooming.bind(this);
  		this.inZoom = this.zoomIn.bind(this);
  		this.outZoom = this.zoomOut.bind(this);
  		this.onRender = this.render.bind(this);
  		this.onMouse = this.mouseEvent.bind(this);
  		this.onImgChange = this.imgChange.bind(this);
  		this.fireAction = this.onAction.bind(this);
  		
  		this.renderer = new THREE[engine]();
  		this.renderer.setSize(width, height);
  		
  		this.camera = new THREE.PerspectiveCamera(this.fov, width / height, 1, parseInt(options.cameraFar, 10));
  		this.camera.target = new THREE.Vector3(0, 0, 0);
  		
  		var sphere = new THREE.SphereGeometry(parseInt(options.sphereRadius, 10), parseInt(options.sphereWsegments, 10), parseInt(options.sphereHsegments, 10));
  		this.texture = new THREE.TextureLoader();
  		this.texture.minFilter = THREE.LinearFilter;
  			
  		sphere.applyMatrix(new THREE.Matrix4().makeScale(-1, 1, 1));
  		this.material = new THREE.MeshBasicMaterial();
  		
  		this.scene = new THREE.Scene();
  		this.scene.add(new THREE.Mesh(sphere, this.material));
  		
  		$.data(slide[0], 'rsaddonpanorama', this);
  		this.canvas = $(this.renderer.domElement).addClass('rsaddon-panorama').appendTo(slide.find('.slotholder'));
  		
  		slide.on('mouseleave', this.onLeave.bind(this)).find('.tp-withaction').each(setActions);
  		
  	}
  	
  	PanoramaSlide.prototype = {
  		
  		start: function() {
  			
  			if(!this.imgLoaded) this.imgLoaded = true;
  			if(!this.currentSlide) return;
  			
  			if(this.newImage) {
  			
  				this.x = 0;
  				this.y = 0;
  				this.zoomVal = 1;
  				this.camera.fov = this.fov;
  				this.camera.updateProjectionMatrix();
  				this.newImage = false;
  				
  			}
  			
  			this.controller = false;
  			this.paused = false;
  			
  			// this.slider.removeClass('rsaddon-panorama-loading');
  			requestFrame(this.onRender);
  			
  			this.addEvents();
  			this.running = true;
  			this.slider.addClass('rsaddon-pano');
  			
  		},
  		
  		render: function() {
  			
  			if(this.paused || !this.camera) return;
  			this.y = Math.max(-85, Math.min(85, this.y));
  			
  			if(this.distX !== false || this.distY !== false) {
  				
  				if(this.distX !== false) {
  				
  					this.x += (this.distX - this.x) * 0.05;
  					if(Math.abs(this.distX - this.x) < 1) {
  						
  						this.distX = false;
  						clearInterval(this.actionTimer);
  						
  					}
  					
  				}
  				else if(this.distY !== false) {
  					
  					this.y += (this.distY - this.y) * 0.05;
  					if(Math.abs(this.distY - this.y) < 1) {
  						
  						this.distY = false;
  						clearInterval(this.actionTimer);
  						
  					}
  					
  				}
  				
  			}
  			else if(!this.controller) {
  
  				if(this.autoplay) this.x += this.speed;
  				
  			}
  			else if(!this.move) {
  
  				var xx = (this.mouseX - this.left) / this.width,
  				    yy = (this.mouseY - this.top) / this.height;
  				
  				xx = xx <= 0.5 ? (1 - (xx * 2)) * -180 : ((xx - 0.5) * 2) * 180;
  				yy = yy <= 0.5 ? (1 - (yy * 2)) * 85 : ((yy - 0.5) * 2) * -85;
  				yy = Math.max(-85, Math.min(85, yy));
  				
  				this.x += (xx - this.x) * 0.05;
  				this.y += (yy - this.y) * 0.05;
  				
  				if((this.click || this.mouse) && Math.abs(xx - this.x) < 1 && Math.abs(yy - this.y) < 1) this.controller = false;
  				
  			}
  			else if(this.thrw) {
  
  				if(this.mousedown) {
  					
  					this.vx = this.x - this.oldX;
  					this.vy = this.y - this.oldY;
  					this.oldX = this.x;
  					this.oldY = this.y;
  					
  				}
  				else {
  					
  					var vx = Math.abs(this.vx),
  					    vy = Math.abs(this.vy);
  					
  					if(vx > 0.01) this.x += this.vx;
  					if(vy > 0.01) this.y += this.vy;
  					
  					this.vx *= this.throwSpeed;
  					this.vy *= this.throwSpeed;
  					
  					if(vx <= 0.01 && vy <= 0.01) this.controller = false;
  				
  				}
  					
  			}
  			
  			var x = THREE.Math.degToRad(this.x),
  			    y = THREE.Math.degToRad(90 - this.y);
  			
  			this.camera.target.x = Math.sin(y) * Math.cos(x);
  			this.camera.target.z = Math.sin(y) * Math.sin(x);
  			this.camera.target.y = Math.cos(y);
  			this.camera.lookAt(this.camera.target);
  			
  			if(this.smoothZoom) { 
  			
  				this.camera.fov += ((this.fov * this.zoomVal) - this.camera.fov) * 0.05;
  				this.camera.updateProjectionMatrix();
  				
  			}
  			
  			this.renderer.render(this.scene, this.camera);
  			requestFrame(this.onRender);
  			
  		},
  		
  		onLeave: function() {
  			
  			clearInterval(this.actionTimer);
  			clearInterval(this.zoomTimer);
  			
  		},
  		
  		clear: function() {
  			
  			clearInterval(this.actionTimer);
  			clearInterval(this.zoomTimer);
  			
  			this.distX = false;
  			this.distY = false;
  			
  		},
  		
  		onAction: function() {
  			
  			this.action(this.actionType, this.actionPerc);
  			
  		},
  		
  		action: function(tpe, perc) {
  			
  			var actionType,
  				dist;
  				
  			switch(tpe) {
  				
  				case 'left':
  					
  					this.distX = this.x + (-180 * perc);
  				
  				break;
  				
  				case 'right':
  					
  					this.distX = this.x + (180 * perc);
  				
  				break;
  				
  				case 'up':
  					
  					dist = this.y + (85 * perc);
  					this.distY = Math.max(-85, Math.min(85, dist));
  				
  				break;
  				
  				case 'down':
  					
  					dist = this.y + (-85 * perc);
  					this.distY = Math.max(-85, Math.min(85, dist));
  				
  				break;
  				
  				case 'leftstart':
  					
  					actionType = 'left';
  				
  				break;
  				
  				case 'rightstart':
  					
  					actionType = 'right';
  				
  				break;
  				
  				case 'upstart':
  					
  					actionType = 'up';
  				
  				break;
  				
  				case 'downstart':
  					
  					actionType = 'down';
  				
  				break;
  				
  				case 'leftend':
  				case 'rightend':
  				case 'upend':
  				case 'downend':
  				
  					clearInterval(this.actionTimer);
  				
  				break;
  				
  				case 'zoomin':
  					
  					clearInterval(this.zoomTimer);
  					this.zooming('gestureend', 0.5);
  				
  				break;
  				
  				case 'zoomout':
  					
  					clearInterval(this.zoomTimer);
  					this.zooming('gestureend', 1.5);
  				
  				break;
  				
  				case 'zoominstart':
  					
  					clearInterval(this.zoomTimer);
  					this.inZoom();
  					this.zoomTimer = setInterval(this.inZoom, 100);
  				
  				break;
  				
  				case 'zoomoutstart':
  					
  					clearInterval(this.zoomTimer);
  					this.outZoom();
  					this.zoomTimer = setInterval(this.outZoom, 100);
  				
  				break;
  				
  				case 'zoominend':
  				case 'zoomoutend':
  				
  					clearInterval(this.zoomTimer);
  				
  				break;
  				
  			}
  			
  			if(actionType) {
  				
  				this.clear();
  				this.actionPerc = perc;
  				this.actionType = actionType;
  				this.fireAction();
  				this.actionTimer = setInterval(this.fireAction, 100);
  				
  			}
  			
  		},
  		
  		zooming: function(e, scale) {
  			
  			var tpe;
  			this.prevZoom = this.zoomVal;
  			
  			if(e !== 'gestureend') {
  				
  				tpe = e.type;
  				scale = e.scale;
  				
  			}
  			else {	
  			
  				tpe = e;
  				
  			}
  			
  			if(tpe !== 'gestureend') {
  			
  				if(e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) this.zoomVal -= 0.05;
  				else this.zoomVal += 0.05;
  				
  			}
  			else {
  				
  				
  				if(scale < 1) this.zoomVal -= 0.05;
  				else this.zoomVal += 0.05;
  				
  			}
  			
  			this.zoomVal = Math.max(this.zoomMax, Math.min(this.zoomMin, this.zoomVal));
  			if(this.zoomVal === this.zoomMax || this.zoomVal === this.zoomMin) clearInterval(this.zoomTimer);
  			
  			if(!this.smoothZoom) {
  				
  				this.camera.fov = this.fov * this.zoomVal;
  				this.camera.updateProjectionMatrix();
  				
  			}
  
  			return false;
  			
  		},
  		
  		zoomIn: function() {
  			
  			this.zooming('gestureend', 0.5);
  			
  		},
  		
  		zoomOut: function() {
  			
  			this.zooming('gestureend', 1.5);
  			
  		},
  		
  		imgChange: function() {
  			
  			this.timer = setTimeout(this.onStart, 500);
  			
  		},
  		
  		update: function(prop, val, callback) {
  			
  			clearTimeout(this.timer);
  			
  			this.removeEvents();
  			this.paused = true;
  			
  			switch(prop) {
  				
  				case 'image':
  					
  					// this.slider.addClass('rsaddon-panorama-loading');
  					this.newImage = true;
  					this.material.map = this.texture.load(val, this.onImgChange);
  				
  				break;
  				
  				case 'controls':
  					
  					this.controls = val;
  					if(val !== 'none') {
  					
  						this.drag = val === 'drag';
  						this.thrw = val === 'throw';
  						this.mouse = val === 'mouse';
  						this.click = val === 'click';
  						this.move = this.drag || this.thrw;
  						
  					}
  					else {
  						
  						this.x = 0;
  						this.y = 0;
  						
  					}
  				
  				break;
  				
  				case 'autoplay':
  				
  					this.autoplay = val == 'true';
  				
  				break;
  				
  				case 'direction':
  				
  					var direction = val === 'forward' ? 1 : -1;
  					this.speed = this.autoplaySpeed * direction;
  				
  				break;
  				
  				case 'zoom':
  					
  					if(val == 'false') {
  						
  						delete this.zoom;
  						this.zoomVal = 1;
  						this.camera.fov = this.fov;
  						this.camera.updateProjectionMatrix();
  						
  					}
  					else {
  					
  						this.zoom = true;
  						
  					}
  				
  				break;
  				
  				case 'smooth':
  				
  					this.smoothZoom = val == 'true';
  				
  				break;
  			
  			}
  			
  			if(prop !== 'image') this.timer = setTimeout(this.onStart, 500);
  			
  		},
  		
  		resize: function(width, height) {
  			
  			this.width = width;
  			this.height = height;
  			this.renderer.setSize(width, height);
  			this.camera.aspect = width / height;
  			this.camera.updateProjectionMatrix();
  			
  		},
  		
  		onReset: function() {
  			
  			this.paused = true;
  			this.currentSlide = true;
  			
  			this.x = 0;
  			this.y = 0;
  			this.distX = false;
  			this.distY = false;
  				
  			this.zoomVal = 1;
  			this.camera.fov = this.fov;
  			this.camera.updateProjectionMatrix();
  			
  			if(!this.imgLoaded) this.material.map = this.texture.load(this.image, this.onStart);
  			else this.start();
  			
  		},
  		
  		enterMouse: function(e, triggered) {
  			
  			if(this.move) this.canvas.removeClass('rsaddon-panorama-drag').addClass('rsaddon-panorama-dragging');
  			
  			this.clear();
  			this.controller = true;
  			this.mousedown = true;
  			
  			var offset = this.slider.offset();
  			this.left = offset.left;
  			this.top = offset.top;
  			
  			if(!triggered) {
  				
  				var touch = e.originalEvent.touches;
  				if(touch) e = touch[0];
  				
  				this.startX = e.pageX - this.left;
  				this.startY = e.pageY - this.top;
  			
  				this.prevX = this.x;
  				this.prevY = this.y;
  				
  				this.oldX = this.x;
  				this.oldY = this.y;
  				
  				this.canvas.on('mousemove.rsaddonpanorama touchmove.rsaddonpanorama', this.onMouse); 
  				
  			}
  			
  		},
  		
  		mouseEvent: function(e) {
  			
  			this.onLeave();
  			if(e.type.search(/move|click/) !== -1) {
  				 
  				if(this.move) {	
  					if(!this.controller || !this.mousedown) return;
  				}
  				else if(!this.controller) {
  					this.enterMouse(e, true);
  				}
  				
  				var touch = e.originalEvent.touches;
  				if(touch) e = touch[0];
  				
  				if(!this.move) {
  					
  					this.mouseX = e.pageX;
  					this.mouseY = e.pageY;
  					
  				}
  				else {
  				
  					this.x = this.prevX + ((this.startX - (e.pageX - this.left)) * 0.1);
  					this.y = this.prevY + (((e.pageY - this.top) - this.startY) * 0.1);
  					
  				}
  				
  			}
  			else if(e.type.search(/down|enter|start/) !== -1) {
  				
  				this.enterMouse(e);
  				
  			}
  			else {
  
  				this.canvas.off('mousemove.rsaddonpanorama touchmove.rsaddonpanorama'); 
  				if(this.drag) this.controller = false;
  				
  				this.mousedown = false;
  				if(this.move) this.canvas.removeClass('rsaddon-panorama-dragging').addClass('rsaddon-panorama-drag');
  					
  			}
  			
  		},
  		
  		addEvents: function() {
  			
  			switch(this.controls) {
  				
  				case 'drag':
  				case 'throw':
  					
  					this.canvas.on(
  					
  						'mousedown.rsaddonpanorama ' + 
  						'mouseup.rsaddonpanorama ' + 
  						'mouseleave.rsaddonpanorama ' + 
  						'touchstart.rsaddonpanorama ' + 
  						'touchend.rsaddonpanorama ' + 
  						'touchcancel.rsaddonpanorama', 
  						
  					this.onMouse);
  				
  				break;
  				
  				case 'click':
  					
  					this.slide.on('click.rsaddonpanorama', this.onMouse);
  				
  				break;
  				
  				case 'mouse':
  
  					this.slide.on('mousemove.rsaddonpanorama touchmove.rsaddonpanorama', this.onMouse);
  				
  				break;
  				
  			}
  			
  			if(this.zoom) this.slider.on('mousewheel.rsaddonpanorama DOMMouseScroll.rsaddonpanorama gestureend.rsaddonpanorama', this.onZoom);
  			if(this.controls !== 'none') {
  				
  				if(this.move) this.canvas.addClass('rsaddon-panorama-drag');
  				else if(this.click) this.slide.addClass('rsaddon-panorama-click');
  				
  			}
  			
  		},
  		
  		removeEvents: function() {
  			
  			this.clear();
  			this.mousedown = false;
  			this.controller = false;
  			this.currentSlide = false;
  			
  			switch(this.controls) {
  				
  				case 'drag':
  				case 'throw':
  				
  					this.canvas.off('.rsaddonpanorama');
  				
  				break;
  				
  				case 'mouse':
  				case 'click':
  				
  					this.slide.off('.rsaddonpanorama');
  				
  				break;
  				
  			}
  				
  			this.slider.off('.rsaddonpanorama');
  			this.slide.removeClass('rsaddon-panorama-click');
  			this.canvas.removeClass('rsaddon-panorama-drag rsaddon-panorama-dragging');
  			
  		},
  		
  		destroy: function() {
  			
  			for(var prop in this) if(this.hasOwnProperty(prop)) delete this[prop];
  			
  		}
  		
  	};
  	
  	function stopBubble(e) {
  		
  		e.stopPropagation();
  		
  	}
  	
  	function setActions() {
  		
  		var $this = jQuery(this),
  			actions = $this.data().actions;
  			
  		if($this.hasClass('rspanoaction') || !Array.isArray(actions)) return;
  		
  		var i = actions.length,
  			action;
  			
  		while(i--) {
  			
  			action = actions[i];
  			if(action.action.search('panorama') !== -1) $this.addClass('rspanoaction').on('mousedown click mousemove touchmove', stopBubble);
  			
  		}
  		
  	}
  	
  	function webGL() {
  		
  		var canvas;
  		try {
  
  			canvas = document.createElement('canvas'); 
  			canvas = !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
  			if(canvas) canvas = 'WebGLRenderer';
  
  		} 
  		catch(e) {}
  		
  		if(!canvas) {
  			
  			canvas = window.CanvasRenderingContext2D;
  			if(canvas) canvas = 'CanvasRenderer';
  			
  		}
  		
  		return canvas;
  		
  	}
  	
  })();
  
  
  
  
  
  
  
  
  
  
  
  