window.pannellum=(function(window, document, undefined){
'use strict';
function Viewer(container, initialConfig){
var _this=this;
var config,
renderer,
preview,
isUserInteracting=false,
latestInteraction=Date.now(),
onPointerDownPointerX=0,
onPointerDownPointerY=0,
onPointerDownPointerDist=-1,
onPointerDownYaw=0,
onPointerDownPitch=0,
keysDown=new Array(10),
fullscreenActive=false,
loaded,
error=false,
isTimedOut=false,
listenersAdded=false,
panoImage,
prevTime,
speed={'yaw': 0, 'pitch': 0, 'hfov': 0},
animating=false,
orientation=false,
orientationYawOffset=0,
autoRotateStart,
autoRotateSpeed=0,
origHfov,
origPitch,
animatedMove={},
externalEventListeners={},
specifiedPhotoSphereExcludes=[],
update=false,
eps=1e-6,
hotspotsCreated=false,
destroyed=false;
var defaultConfig={
hfov: 100,
minHfov: 50,
multiResMinHfov: false,
maxHfov: 120,
pitch: 0,
minPitch: undefined,
maxPitch: undefined,
yaw: 0,
minYaw: -180,
maxYaw: 180,
roll: 0,
haov: 360,
vaov: 180,
vOffset: 0,
autoRotate: false,
autoRotateInactivityDelay: -1,
autoRotateStopDelay: undefined,
type: 'equirectangular',
northOffset: 0,
showFullscreenCtrl: true,
dynamic: false,
dynamicUpdate: false,
doubleClickZoom: true,
keyboardZoom: true,
mouseZoom: true,
showZoomCtrl: true,
autoLoad: false,
showControls: true,
orientationOnByDefault: false,
hotSpotDebug: false,
backgroundColor: [0, 0, 0],
avoidShowingBackground: false,
animationTimingFunction: timingFunction,
draggable: true,
disableKeyboardCtrl: false,
crossOrigin: 'anonymous',
touchPanSpeedCoeffFactor: -1,
capturedKeyNumbers: [16, 17, 27, 37, 38, 39, 40, 61, 65, 68, 83, 87, 107, 109, 173, 187, 189],
friction: 0.15
};
defaultConfig.strings={
loadButtonLabel: 'Click to<br>Load<br>Panorama',
loadingLabel: 'Loading...',
bylineLabel: ' %s',
noPanoramaError: 'No panorama image was specified.',
fileAccessError: 'The file %s could not be accessed.',
malformedURLError: 'There is something wrong with the panorama URL.',
iOS8WebGLError: "Due to iOS 8's broken WebGL implementation, only " +
"progressive encoded JPEGs work for your device (this " +
"panorama uses standard encoding).",
genericWebGLError: 'Your browser does not have the necessary WebGL support to display this panorama.',
textureSizeError: 'This panorama is too big for your device! It\'s ' +
'%spx wide, but your device only supports images up to ' +
'%spx wide. Try another device.' +
' (If you\'re the author, try scaling down the image.)',
unknownError: 'Unknown error. Check developer console.',
};
container=typeof container==='string' ? document.getElementById(container):container;
container.classList.add('pnlm-container');
container.tabIndex=0;
var uiContainer=document.createElement('div');
uiContainer.className='pnlm-ui';
container.appendChild(uiContainer);
var renderContainer=document.createElement('div');
renderContainer.className='pnlm-render-container';
container.appendChild(renderContainer);
var dragFix=document.createElement('div');
dragFix.className='pnlm-dragfix';
uiContainer.appendChild(dragFix);
var aboutMsg=document.createElement('span');
aboutMsg.className='pnlm-about-msg';
var wpvrAboutMsgHtml='';
if(window.wpvr_public&&!window.wpvr_public.is_pro_active){
var wpvrBadgeVariants=[
{label: 'Powered by WPVR', utmContent: 'control'},
{label: 'Create your own virtual tour - Free', utmContent: 'benefit_cta'},
{label: 'Built with WPVR -> Create yours', utmContent: 'action_cta'}
];
var wpvrSelectedVariant=wpvrBadgeVariants[Math.floor(Math.random() * wpvrBadgeVariants.length)];
var wpvrBadgeUrl='https://rextheme.com/go/wpvr/' + wpvrSelectedVariant.utmContent;
wpvrAboutMsgHtml='<a href="' + wpvrBadgeUrl + '" target="_blank" rel="noopener noreferrer">' + wpvrSelectedVariant.label + '</a>';
}
if(wpvrAboutMsgHtml){
aboutMsg.innerHTML=wpvrAboutMsgHtml;
uiContainer.appendChild(aboutMsg);
dragFix.addEventListener('contextmenu', aboutMessage);
}
var infoDisplay={};
var hotSpotDebugIndicator=document.createElement('div');
hotSpotDebugIndicator.className='pnlm-sprite pnlm-hot-spot-debug-indicator';
uiContainer.appendChild(hotSpotDebugIndicator);
infoDisplay.container=document.createElement('div');
infoDisplay.container.className='pnlm-panorama-info';
infoDisplay.title=document.createElement('div');
infoDisplay.title.className='pnlm-title-box';
infoDisplay.container.appendChild(infoDisplay.title);
infoDisplay.author=document.createElement('div');
infoDisplay.author.className='pnlm-author-box';
infoDisplay.container.appendChild(infoDisplay.author);
uiContainer.appendChild(infoDisplay.container);
infoDisplay.load={};
infoDisplay.load.box=document.createElement('div');
infoDisplay.load.box.className='pnlm-load-box';
infoDisplay.load.boxp=document.createElement('p');
infoDisplay.load.box.appendChild(infoDisplay.load.boxp);
infoDisplay.load.lbox=document.createElement('div');
infoDisplay.load.lbox.className='pnlm-lbox';
infoDisplay.load.lbox.innerHTML='<div class="pnlm-loading"></div>';
infoDisplay.load.box.appendChild(infoDisplay.load.lbox);
infoDisplay.load.lbar=document.createElement('div');
infoDisplay.load.lbar.className='pnlm-lbar';
infoDisplay.load.lbarFill=document.createElement('div');
infoDisplay.load.lbarFill.className='pnlm-lbar-fill';
infoDisplay.load.lbar.appendChild(infoDisplay.load.lbarFill);
infoDisplay.load.box.appendChild(infoDisplay.load.lbar);
infoDisplay.load.msg=document.createElement('p');
infoDisplay.load.msg.className='pnlm-lmsg';
infoDisplay.load.box.appendChild(infoDisplay.load.msg);
uiContainer.appendChild(infoDisplay.load.box);
infoDisplay.errorMsg=document.createElement('div');
infoDisplay.errorMsg.className='pnlm-error-msg pnlm-info-box';
uiContainer.appendChild(infoDisplay.errorMsg);
var controls={};
controls.container=document.createElement('div');
controls.container.className='pnlm-controls-container';
uiContainer.appendChild(controls.container);
controls.load=document.createElement('div');
controls.load.className='pnlm-load-button';
controls.load.addEventListener('click', function(){
processOptions();
load();
});
uiContainer.appendChild(controls.load);
controls.zoom=document.createElement('div');
controls.zoom.className='pnlm-zoom-controls pnlm-controls';
controls.zoomIn=document.createElement('div');
controls.zoomIn.className='pnlm-zoom-in pnlm-sprite pnlm-control';
controls.zoomIn.addEventListener('click', zoomIn);
controls.zoom.appendChild(controls.zoomIn);
controls.zoomOut=document.createElement('div');
controls.zoomOut.className='pnlm-zoom-out pnlm-sprite pnlm-control';
controls.zoomOut.addEventListener('click', zoomOut);
controls.zoom.appendChild(controls.zoomOut);
controls.container.appendChild(controls.zoom);
controls.fullscreen=document.createElement('div');
controls.fullscreen.addEventListener('click', toggleFullscreen);
controls.fullscreen.className='pnlm-fullscreen-toggle-button pnlm-sprite pnlm-fullscreen-toggle-button-inactive pnlm-controls pnlm-control';
if(document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled)
controls.container.appendChild(controls.fullscreen);
controls.orientation=document.createElement('div');
controls.orientation.addEventListener('click', function(e){
if(orientation)
stopOrientation();
else
startOrientation();
});
controls.orientation.addEventListener('mousedown', function(e){e.stopPropagation();});
controls.orientation.addEventListener('touchstart', function(e){e.stopPropagation();});
controls.orientation.addEventListener('pointerdown', function(e){e.stopPropagation();});
controls.orientation.className='pnlm-orientation-button pnlm-orientation-button-inactive pnlm-sprite pnlm-controls pnlm-control';
var orientationSupport=false;
if(window.DeviceOrientationEvent&&location.protocol=='https:' &&
navigator.userAgent.toLowerCase().indexOf('mobi') >=0){
controls.container.appendChild(controls.orientation);
orientationSupport=true;
}
var compass=document.createElement('div');
compass.className='pnlm-compass pnlm-controls pnlm-control';
uiContainer.appendChild(compass);
if(initialConfig.firstScene){
mergeConfig(initialConfig.firstScene);
}else if(initialConfig.default&&initialConfig.default.firstScene){
mergeConfig(initialConfig.default.firstScene);
}else{
mergeConfig(null);
}
processOptions(true);
function init(){
var div=document.createElement("div");
div.innerHTML="<!--[if lte IE 9]><i></i><![endif]-->";
if(div.getElementsByTagName("i").length==1){
anError();
return;
}
origHfov=config.hfov;
origPitch=config.pitch;
var i, p;
if(config.type=='cubemap'){
panoImage=[];
for (i=0; i < 6; i++){
panoImage.push(new Image());
panoImage[i].crossOrigin=config.crossOrigin;
}
infoDisplay.load.lbox.style.display='block';
infoDisplay.load.lbar.style.display='none';
}else if(config.type=='multires'){
var c=JSON.parse(JSON.stringify(config.multiRes));
if(config.basePath&&config.multiRes.basePath &&
!(/^(?:[a-z]+:)?\/\//i.test(config.multiRes.basePath))){
c.basePath=config.basePath + config.multiRes.basePath;
}else if(config.multiRes.basePath){
c.basePath=config.multiRes.basePath;
}else if(config.basePath){
c.basePath=config.basePath;
}
panoImage=c;
}else{
if(config.dynamic===true){
panoImage=config.panorama;
}else{
if(config.panorama===undefined){
anError(config.strings.noPanoramaError);
return;
}
panoImage=new Image();
}}
if(config.type=='cubemap'){
var itemsToLoad=6;
var onLoad=function(){
itemsToLoad--;
if(itemsToLoad===0){
onImageLoad();
}};
var onError=function(e){
var a=document.createElement('a');
a.href=e.target.src;
a.textContent=a.href;
anError(config.strings.fileAccessError.replace('%s', a.outerHTML));
};
for (i=0; i < panoImage.length; i++){
p=config.cubeMap[i];
if(p=="null"){
console.log('Will use background instead of missing cubemap face ' + i);
onLoad();
}else{
if(config.basePath&&!absoluteURL(p)){
p=config.basePath + p;
}
panoImage[i].onload=onLoad;
panoImage[i].onerror=onError;
panoImage[i].src=sanitizeURL(p);
}}
}else if(config.type=='multires'){
onImageLoad();
}else{
p='';
if(config.basePath){
p=config.basePath;
}
if(config.dynamic!==true){
p=absoluteURL(config.panorama) ? config.panorama:p + config.panorama;
panoImage.onload=function(){
window.URL.revokeObjectURL(this.src);
onImageLoad();
};
var xhr=new XMLHttpRequest();
xhr.onloadend=function(){
if(xhr.status!=200){
var a=document.createElement('a');
a.href=p;
a.textContent=a.href;
anError(config.strings.fileAccessError.replace('%s', a.outerHTML));
}
var img=this.response;
parseGPanoXMP(img, p);
infoDisplay.load.msg.innerHTML='';
};
xhr.onprogress=function(e){
if(e.lengthComputable){
var percent=e.loaded / e.total * 100;
infoDisplay.load.lbarFill.style.width=percent + '%';
var unit, numerator, denominator;
if(e.total > 1e6){
unit='MB';
numerator=(e.loaded / 1e6).toFixed(2);
denominator=(e.total / 1e6).toFixed(2);
}else if(e.total > 1e3){
unit='kB';
numerator=(e.loaded / 1e3).toFixed(1);
denominator=(e.total / 1e3).toFixed(1);
}else{
unit='B';
numerator=e.loaded;
denominator=e.total;
}
infoDisplay.load.msg.innerHTML=numerator + ' / ' + denominator + ' ' + unit;
}else{
infoDisplay.load.lbox.style.display='block';
infoDisplay.load.lbar.style.display='none';
}};
try {
xhr.open('GET', p, true);
} catch (e){
anError(config.strings.malformedURLError);
}
xhr.responseType='blob';
xhr.setRequestHeader('Accept', 'image*;q=0.9');
xhr.withCredentials=config.crossOrigin==='use-credentials';
xhr.send();
}}
if(config.draggable)
uiContainer.classList.add('pnlm-grab');
uiContainer.classList.remove('pnlm-grabbing');
update=config.dynamicUpdate===true;
if(config.dynamic&&update){
panoImage=config.panorama;
onImageLoad();
}}
function absoluteURL(url){
return new RegExp('^(?:[a-z]+:)?//', 'i').test(url)||url[0]=='/'||url.slice(0, 5)=='blob:';
}
function onImageLoad(){
if(!renderer)
renderer=new libpannellum.renderer(renderContainer);
if(!listenersAdded){
listenersAdded=true;
dragFix.addEventListener('mousedown', onDocumentMouseDown, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
document.addEventListener('mouseup', onDocumentMouseUp, false);
if(config.mouseZoom){
uiContainer.addEventListener('mousewheel', onDocumentMouseWheel, false);
uiContainer.addEventListener('DOMMouseScroll', onDocumentMouseWheel, false);
}
if(config.doubleClickZoom){
dragFix.addEventListener('dblclick', onDocumentDoubleClick, false);
}
container.addEventListener('mozfullscreenchange', onFullScreenChange, false);
container.addEventListener('webkitfullscreenchange', onFullScreenChange, false);
container.addEventListener('msfullscreenchange', onFullScreenChange, false);
container.addEventListener('fullscreenchange', onFullScreenChange, false);
window.addEventListener('resize', onDocumentResize, false);
window.addEventListener('orientationchange', onDocumentResize, false);
if(!config.disableKeyboardCtrl){
container.addEventListener('keydown', onDocumentKeyPress, false);
container.addEventListener('keyup', onDocumentKeyUp, false);
container.addEventListener('blur', clearKeys, false);
}
document.addEventListener('mouseleave', onDocumentMouseUp, false);
if(window.PointerEvent){
dragFix.addEventListener('pointerdown', onDocumentPointerDown, false);
dragFix.addEventListener('pointermove', onDocumentPointerMove, false);
dragFix.addEventListener('pointerup', onDocumentPointerUp, false);
dragFix.addEventListener('pointerleave', onDocumentPointerUp, false);
}else{
dragFix.addEventListener('touchstart', onDocumentTouchStart, { passive: false });
dragFix.addEventListener('touchmove', onDocumentTouchMove, { passive: false });
dragFix.addEventListener('touchend', onDocumentTouchEnd, false);
}
if(window.navigator.pointerEnabled)
container.style.touchAction='none';
}
renderInit();
setHfov(config.hfov);
setTimeout(function(){isTimedOut=true;}, 500);
}
function parseGPanoXMP(image, url){
var reader=new FileReader();
reader.addEventListener('loadend', function(){
var img=reader.result;
if(navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 8_/)){
var flagIndex=img.indexOf('\xff\xc2');
if(flagIndex < 0||flagIndex > 65536)
anError(config.strings.iOS8WebGLError);
}
var start=img.indexOf('<x:xmpmeta');
if(start > -1&&config.ignoreGPanoXMP!==true){
var xmpData=img.substring(start, img.indexOf('</x:xmpmeta>') + 12);
var getTag=function(tag){
var result;
if(xmpData.indexOf(tag + '="') >=0){
result=xmpData.substring(xmpData.indexOf(tag + '="') + tag.length + 2);
result=result.substring(0, result.indexOf('"'));
}else if(xmpData.indexOf(tag + '>') >=0){
result=xmpData.substring(xmpData.indexOf(tag + '>') + tag.length + 1);
result=result.substring(0, result.indexOf('<'));
}
if(result!==undefined){
return Number(result);
}
return null;
};
var xmp={
fullWidth: getTag('GPano:FullPanoWidthPixels'),
croppedWidth: getTag('GPano:CroppedAreaImageWidthPixels'),
fullHeight: getTag('GPano:FullPanoHeightPixels'),
croppedHeight: getTag('GPano:CroppedAreaImageHeightPixels'),
topPixels: getTag('GPano:CroppedAreaTopPixels'),
heading: getTag('GPano:PoseHeadingDegrees'),
horizonPitch: getTag('GPano:PosePitchDegrees'),
horizonRoll: getTag('GPano:PoseRollDegrees')
};
if(xmp.fullWidth!==null&&xmp.croppedWidth!==null &&
xmp.fullHeight!==null&&xmp.croppedHeight!==null &&
xmp.topPixels!==null){
if(specifiedPhotoSphereExcludes.indexOf('haov') < 0)
config.haov=xmp.croppedWidth / xmp.fullWidth * 360;
if(specifiedPhotoSphereExcludes.indexOf('vaov') < 0)
config.vaov=xmp.croppedHeight / xmp.fullHeight * 180;
if(specifiedPhotoSphereExcludes.indexOf('vOffset') < 0)
config.vOffset=((xmp.topPixels + xmp.croppedHeight / 2) / xmp.fullHeight - 0.5) * -180;
if(xmp.heading!==null&&specifiedPhotoSphereExcludes.indexOf('northOffset') < 0){
config.northOffset=xmp.heading;
if(config.compass!==false){
config.compass=true;
}}
if(xmp.horizonPitch!==null&&xmp.horizonRoll!==null){
if(specifiedPhotoSphereExcludes.indexOf('horizonPitch') < 0)
config.horizonPitch=xmp.horizonPitch;
if(specifiedPhotoSphereExcludes.indexOf('horizonRoll') < 0)
config.horizonRoll=xmp.horizonRoll;
}}
}
panoImage.src=window.URL.createObjectURL(image);
panoImage.onerror=function(){
function getCspHeaders(){
if(!window.fetch)
return null;
return window.fetch(document.location.href)
.then(function(resp){
return resp.headers.get('Content-Security-Policy');
});
}
getCspHeaders().then(function(cspHeaders){
if(cspHeaders){
var invalidImgSource=cspHeaders.split(";").find(function(p){
var matchstring=p.match(/img-src(.*)/);
if(matchstring){
return !matchstring[1].includes("blob");
}});
if(invalidImgSource){
console.log('CSP blocks blobs; reverting to URL.');
panoImage.crossOrigin=config.crossOrigin;
panoImage.src=url;
}}
});
}});
if(reader.readAsBinaryString!==undefined)
reader.readAsBinaryString(image);
else
reader.readAsText(image);
}
function anError(errorMsg){
if(errorMsg===undefined)
errorMsg=config.strings.genericWebGLError;
infoDisplay.errorMsg.innerHTML='<p>' + errorMsg + '</p>';
controls.load.style.display='none';
infoDisplay.load.box.style.display='none';
infoDisplay.errorMsg.style.display='table';
error=true;
loaded=undefined;
renderContainer.style.display='none';
fireEvent('error', errorMsg);
}
function clearError(){
if(error){
infoDisplay.load.box.style.display='none';
infoDisplay.errorMsg.style.display='none';
error=false;
renderContainer.style.display='block';
fireEvent('errorcleared');
}}
function aboutMessage(event){
var pos=mousePosition(event);
aboutMsg.style.left=pos.x + 'px';
aboutMsg.style.top=pos.y + 'px';
clearTimeout(aboutMessage.t1);
clearTimeout(aboutMessage.t2);
aboutMsg.style.display='block';
aboutMsg.style.opacity=1;
aboutMessage.t1=setTimeout(function(){aboutMsg.style.opacity=0;}, 2000);
aboutMessage.t2=setTimeout(function(){aboutMsg.style.display='none';}, 2500);
event.preventDefault();
}
function mousePosition(event){
var bounds=container.getBoundingClientRect();
var pos={};
pos.x=(event.clientX||event.pageX) - bounds.left;
pos.y=(event.clientY||event.pageY) - bounds.top;
return pos;
}
function onDocumentMouseDown(event){
event.preventDefault();
container.focus();
if(!loaded||!config.draggable){
return;
}
var pos=mousePosition(event);
if(config.hotSpotDebug){
var coords=mouseEventToCoords(event);
console.log('Pitch: ' + coords[0] + ', Yaw: ' + coords[1] + ', Center Pitch: ' +
config.pitch + ', Center Yaw: ' + config.yaw + ', HFOV: ' + config.hfov);
}
stopAnimation();
stopOrientation();
config.roll=0;
speed.hfov=0;
isUserInteracting=true;
latestInteraction=Date.now();
onPointerDownPointerX=pos.x;
onPointerDownPointerY=pos.y;
onPointerDownYaw=config.yaw;
onPointerDownPitch=config.pitch;
uiContainer.classList.add('pnlm-grabbing');
uiContainer.classList.remove('pnlm-grab');
fireEvent('mousedown', event);
animateInit();
}
function onDocumentDoubleClick(event){
if(config.minHfov===config.hfov){
_this.setHfov(origHfov, 1000);
}else{
var coords=mouseEventToCoords(event);
_this.lookAt(coords[0], coords[1], config.minHfov, 1000);
}}
function mouseEventToCoords(event){
var pos=mousePosition(event);
var canvas=renderer.getCanvas();
var canvasWidth=canvas.clientWidth,
canvasHeight=canvas.clientHeight;
var x=pos.x / canvasWidth * 2 - 1;
var y=(1 - pos.y / canvasHeight * 2) * canvasHeight / canvasWidth;
var focal=1 / Math.tan(config.hfov * Math.PI / 360);
var s=Math.sin(config.pitch * Math.PI / 180);
var c=Math.cos(config.pitch * Math.PI / 180);
var a=focal * c - y * s;
var root=Math.sqrt(x*x + a*a);
var pitch=Math.atan((y * c + focal * s) / root) * 180 / Math.PI;
var yaw=Math.atan2(x / root, a / root) * 180 / Math.PI + config.yaw;
if(yaw < -180)
yaw +=360;
if(yaw > 180)
yaw -=360;
return [pitch, yaw];
}
function onDocumentMouseMove(event){
if(isUserInteracting&&loaded){
latestInteraction=Date.now();
var canvas=renderer.getCanvas();
var canvasWidth=canvas.clientWidth,
canvasHeight=canvas.clientHeight;
var pos=mousePosition(event);
var yaw=((Math.atan(onPointerDownPointerX / canvasWidth * 2 - 1) - Math.atan(pos.x / canvasWidth * 2 - 1)) * 180 / Math.PI * config.hfov / 90) + onPointerDownYaw;
speed.yaw=(yaw - config.yaw) % 360 * 0.2;
config.yaw=yaw;
var vfov=2 * Math.atan(Math.tan(config.hfov/360*Math.PI) * canvasHeight / canvasWidth) * 180 / Math.PI;
var pitch=((Math.atan(pos.y / canvasHeight * 2 - 1) - Math.atan(onPointerDownPointerY / canvasHeight * 2 - 1)) * 180 / Math.PI * vfov / 90) + onPointerDownPitch;
speed.pitch=(pitch - config.pitch) * 0.2;
config.pitch=pitch;
var mirrorData={
pitch: pitch,
yaw: yaw
}
fireEvent('mousemove', mirrorData);
}}
function onDocumentMouseUp(event){
if(!isUserInteracting){
return;
}
isUserInteracting=false;
if(Date.now() - latestInteraction > 15){
speed.pitch=speed.yaw=0;
}
uiContainer.classList.add('pnlm-grab');
uiContainer.classList.remove('pnlm-grabbing');
latestInteraction=Date.now();
fireEvent('mouseup', event);
}
function onDocumentTouchStart(event){
if(!loaded||!config.draggable){
return;
}
stopAnimation();
stopOrientation();
config.roll=0;
speed.hfov=0;
var pos0=mousePosition(event.targetTouches[0]);
onPointerDownPointerX=pos0.x;
onPointerDownPointerY=pos0.y;
if(event.targetTouches.length==2){
var pos1=mousePosition(event.targetTouches[1]);
onPointerDownPointerX +=(pos1.x - pos0.x) * 0.5;
onPointerDownPointerY +=(pos1.y - pos0.y) * 0.5;
onPointerDownPointerDist=Math.sqrt((pos0.x - pos1.x) * (pos0.x - pos1.x) +
(pos0.y - pos1.y) * (pos0.y - pos1.y));
}
isUserInteracting=true;
latestInteraction=Date.now();
onPointerDownYaw=config.yaw;
onPointerDownPitch=config.pitch;
fireEvent('touchstart', event);
animateInit();
}
function onDocumentTouchMove(event){
if(!config.draggable){
return;
}
event.preventDefault();
if(loaded){
latestInteraction=Date.now();
}
if(isUserInteracting&&loaded){
var pos0=mousePosition(event.targetTouches[0]);
var clientX=pos0.x;
var clientY=pos0.y;
if(event.targetTouches.length==2&&onPointerDownPointerDist!=-1){
var pos1=mousePosition(event.targetTouches[1]);
clientX +=(pos1.x - pos0.x) * 0.5;
clientY +=(pos1.y - pos0.y) * 0.5;
var clientDist=Math.sqrt((pos0.x - pos1.x) * (pos0.x - pos1.x) +
(pos0.y - pos1.y) * (pos0.y - pos1.y));
setHfov(config.hfov + (onPointerDownPointerDist - clientDist) * 0.1);
onPointerDownPointerDist=clientDist;
}
var touchmovePanSpeedCoeff=(config.hfov / 360) * config.touchPanSpeedCoeffFactor;
var yaw=(clientX - onPointerDownPointerX) * touchmovePanSpeedCoeff + onPointerDownYaw;
speed.yaw=(yaw - config.yaw) % 360 * 0.2;
config.yaw=yaw;
var pitch=(onPointerDownPointerY - clientY) * touchmovePanSpeedCoeff + onPointerDownPitch;
speed.pitch=(pitch - config.pitch) * 0.2;
config.pitch=pitch;
var mirrorData={
pitch: pitch,
yaw: yaw
}
fireEvent('touchmove', mirrorData);
}}
function onDocumentTouchEnd(){
isUserInteracting=false;
if(Date.now() - latestInteraction > 150){
speed.pitch=speed.yaw=0;
}
onPointerDownPointerDist=-1;
latestInteraction=Date.now();
fireEvent('touchend', event);
}
var pointerIDs=[],
pointerCoordinates=[];
function onDocumentPointerDown(event){
if(event.pointerType=='touch'){
if(!loaded||!config.draggable)
return;
pointerIDs.push(event.pointerId);
var pos=mousePosition(event);
pointerCoordinates.push({clientX: pos.x, clientY: pos.y});
event.targetTouches=pointerCoordinates;
onDocumentTouchStart(event);
event.preventDefault();
}}
function onDocumentPointerMove(event){
if(event.pointerType=='touch'){
if(!config.draggable)
return;
for (var i=0; i < pointerIDs.length; i++){
if(event.pointerId==pointerIDs[i]){
var pos=mousePosition(event);
pointerCoordinates[i].clientX=pos.x;
pointerCoordinates[i].clientY=pos.y;
event.targetTouches=pointerCoordinates;
onDocumentTouchMove(event);
event.preventDefault();
return;
}}
}}
function onDocumentPointerUp(event){
if(event.pointerType=='touch'){
var defined=false;
for (var i=0; i < pointerIDs.length; i++){
if(event.pointerId==pointerIDs[i])
pointerIDs[i]=undefined;
if(pointerIDs[i])
defined=true;
}
if(!defined){
pointerIDs=[];
pointerCoordinates=[];
onDocumentTouchEnd();
}
event.preventDefault();
}}
function onDocumentMouseWheel(event){
if(!loaded||(config.mouseZoom=='fullscreenonly'&&!fullscreenActive)){
return;
}
event.preventDefault();
stopAnimation();
latestInteraction=Date.now();
if(event.wheelDeltaY){
setHfov(config.hfov - event.wheelDeltaY * 0.05);
speed.hfov=event.wheelDelta < 0 ? 1:-1;
}else if(event.wheelDelta){
setHfov(config.hfov - event.wheelDelta * 0.05);
speed.hfov=event.wheelDelta < 0 ? 1:-1;
}else if(event.detail){
setHfov(config.hfov + event.detail * 1.5);
speed.hfov=event.detail > 0 ? 1:-1;
}
animateInit();
}
function onDocumentKeyPress(event){
stopAnimation();
latestInteraction=Date.now();
stopOrientation();
config.roll=0;
var keynumber=event.which||event.keycode;
if(config.capturedKeyNumbers.indexOf(keynumber) < 0)
return;
event.preventDefault();
if(keynumber==27){
if(fullscreenActive){
toggleFullscreen();
}}else{
changeKey(keynumber, true);
}}
function clearKeys(){
for (var i=0; i < 10; i++){
keysDown[i]=false;
}}
function onDocumentKeyUp(event){
var keynumber=event.which||event.keycode;
if(config.capturedKeyNumbers.indexOf(keynumber) < 0)
return;
event.preventDefault();
changeKey(keynumber, false);
}
function changeKey(keynumber, value){
var keyChanged=false;
switch(keynumber){
case 109: case 189: case 17: case 173:
if(keysDown[0]!=value){ keyChanged=true; }
keysDown[0]=value; break;
case 107: case 187: case 16: case 61:
if(keysDown[1]!=value){ keyChanged=true; }
keysDown[1]=value; break;
case 38:
if(keysDown[2]!=value){ keyChanged=true; }
keysDown[2]=value; break;
case 87:
if(keysDown[6]!=value){ keyChanged=true; }
keysDown[6]=value; break;
case 40:
if(keysDown[3]!=value){ keyChanged=true; }
keysDown[3]=value; break;
case 83:
if(keysDown[7]!=value){ keyChanged=true; }
keysDown[7]=value; break;
case 37:
if(keysDown[4]!=value){ keyChanged=true; }
keysDown[4]=value; break;
case 65:
if(keysDown[8]!=value){ keyChanged=true; }
keysDown[8]=value; break;
case 39:
if(keysDown[5]!=value){ keyChanged=true; }
keysDown[5]=value; break;
case 68:
if(keysDown[9]!=value){ keyChanged=true; }
keysDown[9]=value;
}
if(keyChanged&&value){
if(typeof performance!=='undefined'&&performance.now()){
prevTime=performance.now();
}else{
prevTime=Date.now();
}
animateInit();
}}
function keyRepeat(){
if(!loaded){
return;
}
var isKeyDown=false;
var prevPitch=config.pitch;
var prevYaw=config.yaw;
var prevZoom=config.hfov;
var newTime;
if(typeof performance!=='undefined'&&performance.now()){
newTime=performance.now();
}else{
newTime=Date.now();
}
if(prevTime===undefined){
prevTime=newTime;
}
var diff=(newTime - prevTime) * config.hfov / 1700;
diff=Math.min(diff, 1.0);
if(keysDown[0]&&config.keyboardZoom===true){
setHfov(config.hfov + (speed.hfov * 0.8 + 0.5) * diff);
isKeyDown=true;
}
if(keysDown[1]&&config.keyboardZoom===true){
setHfov(config.hfov + (speed.hfov * 0.8 - 0.2) * diff);
isKeyDown=true;
}
if(keysDown[2]||keysDown[6]){
config.pitch +=(speed.pitch * 0.8 + 0.2) * diff;
isKeyDown=true;
}
if(keysDown[3]||keysDown[7]){
config.pitch +=(speed.pitch * 0.8 - 0.2) * diff;
isKeyDown=true;
}
if(keysDown[4]||keysDown[8]){
config.yaw +=(speed.yaw * 0.8 - 0.2) * diff;
isKeyDown=true;
}
if(keysDown[5]||keysDown[9]){
config.yaw +=(speed.yaw * 0.8 + 0.2) * diff;
isKeyDown=true;
}
if(isKeyDown)
latestInteraction=Date.now();
if(config.autoRotate){
if(newTime - prevTime > 0.001){
var timeDiff=(newTime - prevTime) / 1000;
var yawDiff=(speed.yaw / timeDiff * diff - config.autoRotate * 0.2) * timeDiff;
yawDiff=(-config.autoRotate > 0 ? 1:-1) * Math.min(Math.abs(config.autoRotate * timeDiff), Math.abs(yawDiff));
config.yaw +=yawDiff;
}
if(config.autoRotateStopDelay){
config.autoRotateStopDelay -=newTime - prevTime;
if(config.autoRotateStopDelay <=0){
config.autoRotateStopDelay=false;
autoRotateSpeed=config.autoRotate;
config.autoRotate=0;
}}
}
if(animatedMove.pitch){
animateMove('pitch');
prevPitch=config.pitch;
}
if(animatedMove.yaw){
animateMove('yaw');
prevYaw=config.yaw;
}
if(animatedMove.hfov){
animateMove('hfov');
prevZoom=config.hfov;
}
if(diff > 0&&!config.autoRotate){
var slowDownFactor=1 - config.friction;
if(!keysDown[4]&&!keysDown[5]&&!keysDown[8]&&!keysDown[9]&&!animatedMove.yaw){
config.yaw +=speed.yaw * diff * slowDownFactor;
}
if(!keysDown[2]&&!keysDown[3]&&!keysDown[6]&&!keysDown[7]&&!animatedMove.pitch){
config.pitch +=speed.pitch * diff * slowDownFactor;
}
if(!keysDown[0]&&!keysDown[1]&&!animatedMove.hfov){
setHfov(config.hfov + speed.hfov * diff * slowDownFactor);
}}
prevTime=newTime;
if(diff > 0){
speed.yaw=speed.yaw * 0.8 + (config.yaw - prevYaw) / diff * 0.2;
speed.pitch=speed.pitch * 0.8 + (config.pitch - prevPitch) / diff * 0.2;
speed.hfov=speed.hfov * 0.8 + (config.hfov - prevZoom) / diff * 0.2;
var maxSpeed=config.autoRotate ? Math.abs(config.autoRotate):5;
speed.yaw=Math.min(maxSpeed, Math.max(speed.yaw, -maxSpeed));
speed.pitch=Math.min(maxSpeed, Math.max(speed.pitch, -maxSpeed));
speed.hfov=Math.min(maxSpeed, Math.max(speed.hfov, -maxSpeed));
}
if(keysDown[0]&&keysDown[1]){
speed.hfov=0;
}
if((keysDown[2]||keysDown[6])&&(keysDown[3]||keysDown[7])){
speed.pitch=0;
}
if((keysDown[4]||keysDown[8])&&(keysDown[5]||keysDown[9])){
speed.yaw=0;
}}
function animateMove(axis){
var t=animatedMove[axis];
var normTime=Math.min(1, Math.max((Date.now() - t.startTime) / 1000 / (t.duration / 1000), 0));
var result=t.startPosition + config.animationTimingFunction(normTime) * (t.endPosition - t.startPosition);
if((t.endPosition > t.startPosition&&result >=t.endPosition) ||
(t.endPosition < t.startPosition&&result <=t.endPosition) ||
t.endPosition===t.startPosition){
result=t.endPosition;
speed[axis]=0;
delete animatedMove[axis];
}
config[axis]=result;
}
function timingFunction(t){
return t < 0.5 ? 2*t*t:-1+(4-2*t)*t;
}
function onDocumentResize(){
onFullScreenChange('resize');
}
function animateInit(){
if(animating){
return;
}
animating=true;
animate();
}
function animate(){
if(destroyed){
return;
}
render();
if(autoRotateStart)
clearTimeout(autoRotateStart);
if(isUserInteracting||orientation===true){
requestAnimationFrame(animate);
}else if(keysDown[0]||keysDown[1]||keysDown[2]||keysDown[3] ||
keysDown[4]||keysDown[5]||keysDown[6]||keysDown[7] ||
keysDown[8]||keysDown[9]||config.autoRotate ||
animatedMove.pitch||animatedMove.yaw||animatedMove.hfov ||
Math.abs(speed.yaw) > 0.01||Math.abs(speed.pitch) > 0.01 ||
Math.abs(speed.hfov) > 0.01){
keyRepeat();
if(config.autoRotateInactivityDelay >=0&&autoRotateSpeed &&
Date.now() - latestInteraction > config.autoRotateInactivityDelay &&
!config.autoRotate){
config.autoRotate=autoRotateSpeed;
_this.lookAt(origPitch, undefined, origHfov, 3000);
}
requestAnimationFrame(animate);
}else if(renderer&&(renderer.isLoading()||(config.dynamic===true&&update))){
requestAnimationFrame(animate);
}else{
fireEvent('animatefinished', {pitch: _this.getPitch(), yaw: _this.getYaw(), hfov: _this.getHfov()});
animating=false;
prevTime=undefined;
var autoRotateStartTime=config.autoRotateInactivityDelay -
(Date.now() - latestInteraction);
if(autoRotateStartTime > 0){
autoRotateStart=setTimeout(function(){
config.autoRotate=autoRotateSpeed;
_this.lookAt(origPitch, undefined, origHfov, 3000);
animateInit();
}, autoRotateStartTime);
}else if(config.autoRotateInactivityDelay >=0&&autoRotateSpeed){
config.autoRotate=autoRotateSpeed;
_this.lookAt(origPitch, undefined, origHfov, 3000);
animateInit();
}}
}
function render(){
var tmpyaw;
if(loaded){
var canvas=renderer.getCanvas();
if(config.autoRotate!==false){
if(config.yaw > 360){
config.yaw -=360;
}else if(config.yaw < -360){
config.yaw +=360;
}}
tmpyaw=config.yaw;
var hoffcut=0,
voffcut=0;
if(config.avoidShowingBackground){
var hfov2=config.hfov / 2,
vfov2=Math.atan2(Math.tan(hfov2 / 180 * Math.PI), (canvas.width / canvas.height)) * 180 / Math.PI,
transposed=config.vaov > config.haov;
if(transposed){
voffcut=vfov2 * (1 - Math.min(Math.cos((config.pitch - hfov2) / 180 * Math.PI),
Math.cos((config.pitch + hfov2) / 180 * Math.PI)));
}else{
hoffcut=hfov2 * (1 - Math.min(Math.cos((config.pitch - vfov2) / 180 * Math.PI),
Math.cos((config.pitch + vfov2) / 180 * Math.PI)));
}}
var yawRange=config.maxYaw - config.minYaw,
minYaw=-180,
maxYaw=180;
if(yawRange < 360){
minYaw=config.minYaw + config.hfov / 2 + hoffcut;
maxYaw=config.maxYaw - config.hfov / 2 - hoffcut;
if(yawRange < config.hfov){
minYaw=maxYaw=(minYaw + maxYaw) / 2;
}
config.yaw=Math.max(minYaw, Math.min(maxYaw, config.yaw));
}
if(!(config.autoRotate!==false)){
if(config.yaw > 360){
config.yaw -=360;
}else if(config.yaw < -360){
config.yaw +=360;
}}
if(config.autoRotate!==false&&tmpyaw!=config.yaw &&
prevTime!==undefined){
config.autoRotate *=-1;
}
var vfov=2 * Math.atan(Math.tan(config.hfov / 180 * Math.PI * 0.5) /
(canvas.width / canvas.height)) / Math.PI * 180;
var minPitch=config.minPitch + vfov / 2,
maxPitch=config.maxPitch - vfov / 2;
var pitchRange=config.maxPitch - config.minPitch;
if(pitchRange < vfov){
minPitch=maxPitch=(minPitch + maxPitch) / 2;
}
if(isNaN(minPitch))
minPitch=-90;
if(isNaN(maxPitch))
maxPitch=90;
config.pitch=Math.max(minPitch, Math.min(maxPitch, config.pitch));
renderer.render(config.pitch * Math.PI / 180, config.yaw * Math.PI / 180, config.hfov * Math.PI / 180, {roll: config.roll * Math.PI / 180});
renderHotSpots();
if(config.compass){
compass.style.transform='rotate(' + (-config.yaw - config.northOffset) + 'deg)';
compass.style.webkitTransform='rotate(' + (-config.yaw - config.northOffset) + 'deg)';
}}
}
function Quaternion(w, x, y, z){
this.w=w;
this.x=x;
this.y=y;
this.z=z;
}
Quaternion.prototype.multiply=function(q){
return new Quaternion(this.w*q.w - this.x*q.x - this.y*q.y - this.z*q.z,
this.x*q.w + this.w*q.x + this.y*q.z - this.z*q.y,
this.y*q.w + this.w*q.y + this.z*q.x - this.x*q.z,
this.z*q.w + this.w*q.z + this.x*q.y - this.y*q.x);
};
Quaternion.prototype.toEulerAngles=function(){
var phi=Math.atan2(2 * (this.w * this.x + this.y * this.z),
1 - 2 * (this.x * this.x + this.y * this.y)),
theta=Math.asin(2 * (this.w * this.y - this.z * this.x)),
psi=Math.atan2(2 * (this.w * this.z + this.x * this.y),
1 - 2 * (this.y * this.y + this.z * this.z));
return [phi, theta, psi];
};
function taitBryanToQuaternion(alpha, beta, gamma){
var r=[beta ? beta * Math.PI / 180 / 2:0,
gamma ? gamma * Math.PI / 180 / 2:0,
alpha ? alpha * Math.PI / 180 / 2:0];
var c=[Math.cos(r[0]), Math.cos(r[1]), Math.cos(r[2])],
s=[Math.sin(r[0]), Math.sin(r[1]), Math.sin(r[2])];
return new Quaternion(c[0]*c[1]*c[2] - s[0]*s[1]*s[2],
s[0]*c[1]*c[2] - c[0]*s[1]*s[2],
c[0]*s[1]*c[2] + s[0]*c[1]*s[2],
c[0]*c[1]*s[2] + s[0]*s[1]*c[2]);
}
function computeQuaternion(alpha, beta, gamma){
var quaternion=taitBryanToQuaternion(alpha, beta, gamma);
quaternion=quaternion.multiply(new Quaternion(Math.sqrt(0.5), -Math.sqrt(0.5), 0, 0));
var angle=window.orientation ? -window.orientation * Math.PI / 180 / 2:0;
return quaternion.multiply(new Quaternion(Math.cos(angle), 0, -Math.sin(angle), 0));
}
function orientationListener(e){
var q=computeQuaternion(e.alpha, e.beta, e.gamma).toEulerAngles();
if(typeof(orientation)=='number'&&orientation < 10){
orientation +=1;
}else if(orientation===10){
orientationYawOffset=q[2] / Math.PI * 180 + config.yaw;
orientation=true;
requestAnimationFrame(animate);
}else{
config.pitch=q[0] / Math.PI * 180;
config.roll=-q[1] / Math.PI * 180;
config.yaw=-q[2] / Math.PI * 180 + orientationYawOffset;
}}
function renderInit(){
try {
var params={};
if(config.horizonPitch!==undefined)
params.horizonPitch=config.horizonPitch * Math.PI / 180;
if(config.horizonRoll!==undefined)
params.horizonRoll=config.horizonRoll * Math.PI / 180;
if(config.backgroundColor!==undefined)
params.backgroundColor=config.backgroundColor;
renderer.init(panoImage, config.type, config.dynamic, config.haov * Math.PI / 180, config.vaov * Math.PI / 180, config.vOffset * Math.PI / 180, renderInitCallback, params);
if(config.dynamic!==true){
panoImage=undefined;
}} catch(event){
if(event.type=='webgl error'||event.type=='no webgl'){
anError();
}else if(event.type=='webgl size error'){
anError(config.strings.textureSizeError.replace('%s', event.width).replace('%s', event.maxWidth));
}else{
anError(config.strings.unknownError);
throw event;
}}
}
function renderInitCallback(){
if(config.sceneFadeDuration&&renderer.fadeImg!==undefined){
renderer.fadeImg.style.opacity=0;
var fadeImg=renderer.fadeImg;
delete renderer.fadeImg;
setTimeout(function(){
renderContainer.removeChild(fadeImg);
fireEvent('scenechangefadedone');
}, config.sceneFadeDuration);
}
if(config.compass){
compass.style.display='inline';
}else{
compass.style.display='none';
}
createHotSpots();
infoDisplay.load.box.style.display='none';
if(preview!==undefined){
renderContainer.removeChild(preview);
preview=undefined;
}
loaded=true;
animateInit();
fireEvent('load');
}
function createHotSpot(hs){
hs.pitch=Number(hs.pitch)||0;
hs.yaw=Number(hs.yaw)||0;
var div=document.createElement('div');
div.className='pnlm-hotspot-base';
if(hs.cssClass)
div.className +=' ' + hs.cssClass;
else
div.className +=' pnlm-hotspot pnlm-sprite pnlm-' + escapeHTML(hs.type);
var span=document.createElement('span');
if(hs.text)
span.innerHTML=escapeHTML(hs.text);
var a;
if(hs.video){
var video=document.createElement('video'),
vidp=hs.video;
if(config.basePath&&!absoluteURL(vidp))
vidp=config.basePath + vidp;
video.src=sanitizeURL(vidp);
video.controls=true;
video.style.width=hs.width + 'px';
renderContainer.appendChild(div);
span.appendChild(video);
}else if(hs.image){
var imgp=hs.image;
if(config.basePath&&!absoluteURL(imgp))
imgp=config.basePath + imgp;
a=document.createElement('a');
a.href=sanitizeURL(hs.URL ? hs.URL:imgp, true);
a.target='_blank';
span.appendChild(a);
var image=document.createElement('img');
image.src=sanitizeURL(imgp);
image.style.width=hs.width + 'px';
image.style.paddingTop='5px';
renderContainer.appendChild(div);
a.appendChild(image);
span.style.maxWidth='initial';
}else if(hs.URL){
a=document.createElement('a');
a.href=sanitizeURL(hs.URL, true);
if(hs.attributes){
for (var key in hs.attributes){
a.setAttribute(key, hs.attributes[key]);
}}else{
if(hs.wpvr_url_open=='on'){
a.target='_self';
}else{
a.target='_blank';
}}
renderContainer.appendChild(a);
div.className +=' pnlm-pointer';
span.className +=' pnlm-pointer';
a.appendChild(div);
}else{
if(hs.sceneId){
div.onclick=div.ontouchend=function(){
if(!div.clicked){
div.clicked=true;
loadScene(hs.sceneId, hs.targetPitch, hs.targetYaw, hs.targetHfov);
}
return false;
};
div.className +=' pnlm-pointer';
span.className +=' pnlm-pointer';
}
renderContainer.appendChild(div);
}
if(hs.createTooltipFunc){
hs.createTooltipFunc(div, hs.createTooltipArgs);
}else if(hs.text||hs.video||hs.image){
div.classList.add('pnlm-tooltip');
div.appendChild(span);
span.style.width=span.scrollWidth - 20 + 'px';
span.style.marginLeft=-(span.scrollWidth - div.offsetWidth) / 2 + 'px';
span.style.marginTop=-span.scrollHeight - 12 + 'px';
}
if(hs.clickHandlerFunc){
div.addEventListener('click', function(e){
hs.clickHandlerFunc(e, hs.clickHandlerArgs);
}, 'false');
div.className +=' pnlm-pointer';
span.className +=' pnlm-pointer';
}
hs.div=div;
}
function createHotSpots(){
if(hotspotsCreated) return;
if(!config.hotSpots){
config.hotSpots=[];
}else{
config.hotSpots=config.hotSpots.sort(function(a, b){
return a.pitch < b.pitch;
});
config.hotSpots.forEach(createHotSpot);
}
hotspotsCreated=true;
renderHotSpots();
}
function destroyHotSpots(){
var hs=config.hotSpots;
hotspotsCreated=false;
delete config.hotSpots;
if(hs){
for (var i=0; i < hs.length; i++){
var current=hs[i].div;
if(current){
while (current.parentNode&&current.parentNode!=renderContainer){
current=current.parentNode;
}
renderContainer.removeChild(current);
}
delete hs[i].div;
}}
}
function renderHotSpot(hs){
var hsPitchSin=Math.sin(hs.pitch * Math.PI / 180),
hsPitchCos=Math.cos(hs.pitch * Math.PI / 180),
configPitchSin=Math.sin(config.pitch * Math.PI / 180),
configPitchCos=Math.cos(config.pitch * Math.PI / 180),
yawCos=Math.cos((-hs.yaw + config.yaw) * Math.PI / 180);
var z=hsPitchSin * configPitchSin + hsPitchCos * yawCos * configPitchCos;
if((hs.yaw <=90&&hs.yaw > -90&&z <=0) ||
((hs.yaw > 90||hs.yaw <=-90)&&z <=0)){
hs.div.style.visibility='hidden';
}else{
var yawSin=Math.sin((-hs.yaw + config.yaw) * Math.PI / 180),
hfovTan=Math.tan(config.hfov * Math.PI / 360);
hs.div.style.visibility='visible';
var canvas=renderer.getCanvas(),
canvasWidth=canvas.clientWidth,
canvasHeight=canvas.clientHeight;
var coord=[-canvasWidth / hfovTan * yawSin * hsPitchCos / z / 2,
-canvasWidth / hfovTan * (hsPitchSin * configPitchCos -
hsPitchCos * yawCos * configPitchSin) / z / 2];
var rollSin=Math.sin(config.roll * Math.PI / 180),
rollCos=Math.cos(config.roll * Math.PI / 180);
coord=[coord[0] * rollCos - coord[1] * rollSin,
coord[0] * rollSin + coord[1] * rollCos];
coord[0] +=(canvasWidth - hs.div.offsetWidth) / 2;
coord[1] +=(canvasHeight - hs.div.offsetHeight) / 2;
var transform='translate(' + coord[0] + 'px, ' + coord[1] +
'px) translateZ(9999px) rotate(' + config.roll + 'deg)';
if(hs.scale){
transform +=' scale(' + (origHfov/config.hfov) / z + ')';
}
hs.div.style.webkitTransform=transform;
hs.div.style.MozTransform=transform;
hs.div.style.transform=transform;
}}
function renderHotSpots(){
config.hotSpots.forEach(renderHotSpot);
}
function mergeConfig(sceneId){
config={};
var k, s;
var photoSphereExcludes=['haov', 'vaov', 'vOffset', 'northOffset', 'horizonPitch', 'horizonRoll'];
specifiedPhotoSphereExcludes=[];
for (k in defaultConfig){
if(defaultConfig.hasOwnProperty(k)){
config[k]=defaultConfig[k];
}}
for (k in initialConfig.default){
if(initialConfig.default.hasOwnProperty(k)){
if(k=='strings'){
for (s in initialConfig.default.strings){
if(initialConfig.default.strings.hasOwnProperty(s)){
config.strings[s]=escapeHTML(initialConfig.default.strings[s]);
}}
}else{
config[k]=initialConfig.default[k];
if(photoSphereExcludes.indexOf(k) >=0){
specifiedPhotoSphereExcludes.push(k);
}}
}}
if((sceneId!==null)&&(sceneId!=='')&&(initialConfig.scenes)&&(initialConfig.scenes[sceneId])){
var scene=initialConfig.scenes[sceneId];
for (k in scene){
if(scene.hasOwnProperty(k)){
if(k=='strings'){
for (s in scene.strings){
if(scene.strings.hasOwnProperty(s)){
config.strings[s]=escapeHTML(scene.strings[s]);
}}
}else{
config[k]=scene[k];
if(photoSphereExcludes.indexOf(k) >=0){
specifiedPhotoSphereExcludes.push(k);
}}
}}
config.scene=sceneId;
}
for (k in initialConfig){
if(initialConfig.hasOwnProperty(k)){
if(k=='strings'){
for (s in initialConfig.strings){
if(initialConfig.strings.hasOwnProperty(s)){
config.strings[s]=escapeHTML(initialConfig.strings[s]);
}}
}else{
config[k]=initialConfig[k];
if(photoSphereExcludes.indexOf(k) >=0){
specifiedPhotoSphereExcludes.push(k);
}}
}}
}
function processOptions(isPreview){
isPreview=isPreview ? isPreview:false;
if(isPreview&&'preview' in config){
var p=config.preview;
if(config.basePath&&!absoluteURL(p))
p=config.basePath + p;
preview=document.createElement('div');
preview.className='pnlm-preview-img';
preview.style.backgroundImage="url('" + sanitizeURLForCss(p) + "')";
renderContainer.appendChild(preview);
}
var title=config.title,
author=config.author;
if(isPreview){
if('previewTitle' in config)
config.title=config.previewTitle;
if('previewAuthor' in config)
config.author=config.previewAuthor;
}
if(!config.hasOwnProperty('title'))
infoDisplay.title.innerHTML='';
if(!config.hasOwnProperty('author'))
infoDisplay.author.innerHTML='';
if(!config.hasOwnProperty('title')&&!config.hasOwnProperty('author'))
infoDisplay.container.style.display='none';
controls.load.innerHTML='<p>' + config.strings.loadButtonLabel + '</p>';
infoDisplay.load.boxp.innerHTML=config.strings.loadingLabel;
for (var key in config){
if(config.hasOwnProperty(key)){
switch(key){
case 'title':
infoDisplay.title.innerHTML=escapeHTML(config[key]);
infoDisplay.container.style.display='inline';
break;
case 'author':
var authorText=escapeHTML(config[key]);
if(config.authorURL){
var authorLink=document.createElement('a');
authorLink.href=sanitizeURL(config['authorURL'], true);
authorLink.target='_blank';
authorLink.innerHTML=escapeHTML(config[key]);
authorText=authorLink.outerHTML;
}
infoDisplay.author.innerHTML=config.strings.bylineLabel.replace('%s', authorText);
infoDisplay.container.style.display='inline';
break;
case 'fallback':
var link=document.createElement('a');
link.href=sanitizeURL(config[key], true);
link.target='_blank';
link.textContent='Click here to view this panorama in an alternative viewer.';
var message=document.createElement('p');
message.textContent='Your browser does not support WebGL.';
message.appendChild(document.createElement('br'));
message.appendChild(link);
infoDisplay.errorMsg.innerHTML='';
infoDisplay.errorMsg.appendChild(message);
break;
case 'hfov':
setHfov(Number(config[key]));
break;
case 'autoLoad':
if(config[key]===true&&renderer===undefined){
infoDisplay.load.box.style.display='inline';
controls.load.style.display='none';
init();
}
break;
case 'showZoomCtrl':
if(config[key]&&config.showControls!=false){
controls.zoom.style.display='block';
}else{
controls.zoom.style.display='none';
}
break;
case 'showFullscreenCtrl':
if(config[key]&&config.showControls!=false&&('fullscreen' in document||'mozFullScreen' in document ||
'webkitIsFullScreen' in document||'msFullscreenElement' in document)){
controls.fullscreen.style.display='block';
}else{
controls.fullscreen.style.display='none';
}
break;
case 'hotSpotDebug':
if(config[key])
hotSpotDebugIndicator.style.display='block';
else
hotSpotDebugIndicator.style.display='none';
break;
case 'showControls':
if(!config[key]){
controls.orientation.style.display='none';
controls.zoom.style.display='none';
controls.fullscreen.style.display='none';
}
break;
case 'orientationOnByDefault':
if(config[key])
startOrientation();
break;
}}
}
if(isPreview){
if(title)
config.title=title;
else
delete config.title;
if(author)
config.author=author;
else
delete config.author;
}}
function toggleFullscreen(){
if(loaded&&!error){
if(!fullscreenActive){
try {
if(container.requestFullscreen){
container.requestFullscreen();
}else if(container.mozRequestFullScreen){
container.mozRequestFullScreen();
}else if(container.msRequestFullscreen){
container.msRequestFullscreen();
}else{
container.webkitRequestFullScreen();
}} catch(event){
}}else{
if(document.exitFullscreen){
document.exitFullscreen();
}else if(document.mozCancelFullScreen){
document.mozCancelFullScreen();
}else if(document.webkitCancelFullScreen){
document.webkitCancelFullScreen();
}else if(document.msExitFullscreen){
document.msExitFullscreen();
}}
}}
function onFullScreenChange(resize){
if(document.fullscreenElement||document.fullscreen||document.mozFullScreen||document.webkitIsFullScreen||document.msFullscreenElement){
controls.fullscreen.classList.add('pnlm-fullscreen-toggle-button-active');
fullscreenActive=true;
}else{
controls.fullscreen.classList.remove('pnlm-fullscreen-toggle-button-active');
fullscreenActive=false;
}
if(resize!=='resize')
fireEvent('fullscreenchange', fullscreenActive);
renderer.resize();
setHfov(config.hfov);
animateInit();
}
function zoomIn(){
if(loaded){
setHfov(config.hfov - 5);
animateInit();
}}
function zoomOut(){
if(loaded){
setHfov(config.hfov + 5);
animateInit();
}}
function constrainHfov(hfov){
var minHfov=config.minHfov;
if(config.type=='multires'&&renderer&&!config.multiResMinHfov){
minHfov=Math.min(minHfov, renderer.getCanvas().width / (config.multiRes.cubeResolution / 90 * 0.9));
}
if(minHfov > config.maxHfov){
console.log('HFOV bounds do not make sense (minHfov > maxHfov).');
return config.hfov;
}
var newHfov=config.hfov;
if(hfov < minHfov){
newHfov=minHfov;
}else if(hfov > config.maxHfov){
newHfov=config.maxHfov;
}else{
newHfov=hfov;
}
if(config.avoidShowingBackground&&renderer){
var canvas=renderer.getCanvas();
newHfov=Math.min(newHfov,
Math.atan(Math.tan((config.maxPitch - config.minPitch) / 360 * Math.PI) /
canvas.height * canvas.width) * 360 / Math.PI);
}
return newHfov;
}
function setHfov(hfov){
config.hfov=constrainHfov(hfov);
fireEvent('zoomchange', config.hfov);
}
function stopAnimation(){
animatedMove={};
autoRotateSpeed=config.autoRotate ? config.autoRotate:autoRotateSpeed;
config.autoRotate=false;
}
function load(){
clearError();
loaded=false;
controls.load.style.display='none';
infoDisplay.load.box.style.display='inline';
init();
}
function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone){
if(!loaded)
fadeDone=true;
loaded=false;
animatedMove={};
var fadeImg, workingPitch, workingYaw, workingHfov;
if(config.sceneFadeDuration&&!fadeDone){
var data=renderer.render(config.pitch * Math.PI / 180, config.yaw * Math.PI / 180, config.hfov * Math.PI / 180, {returnImage: true});
if(data!==undefined){
fadeImg=new Image();
fadeImg.className='pnlm-fade-img';
fadeImg.style.transition='opacity ' + (config.sceneFadeDuration / 1000) + 's';
fadeImg.style.width='100%';
fadeImg.style.height='100%';
fadeImg.onload=function(){
loadScene(sceneId, targetPitch, targetYaw, targetHfov, true);
};
fadeImg.src=data;
renderContainer.appendChild(fadeImg);
renderer.fadeImg=fadeImg;
return;
}}
if(targetPitch==='same'){
workingPitch=config.pitch;
}else{
workingPitch=targetPitch;
}
if(targetYaw==='same'){
workingYaw=config.yaw;
}else if(targetYaw==='sameAzimuth'){
workingYaw=config.yaw + (config.northOffset||0) - (initialConfig.scenes[sceneId].northOffset||0);
}else{
workingYaw=targetYaw;
}
if(targetHfov==='same'){
workingHfov=config.hfov;
}else{
workingHfov=targetHfov;
}
destroyHotSpots();
mergeConfig(sceneId);
speed.yaw=speed.pitch=speed.hfov=0;
processOptions();
if(workingPitch!==undefined){
config.pitch=workingPitch;
}
if(workingYaw!==undefined){
config.yaw=workingYaw;
}
if(workingHfov!==undefined){
config.hfov=workingHfov;
}
fireEvent('scenechange', sceneId);
load();
}
function stopOrientation(){
window.removeEventListener('deviceorientation', orientationListener);
controls.orientation.classList.remove('pnlm-orientation-button-active');
orientation=false;
}
function startOrientation(){
if(!orientationSupport)
return;
if(typeof DeviceMotionEvent!=='undefined' &&
typeof DeviceMotionEvent.requestPermission==='function'){
DeviceOrientationEvent.requestPermission().then(function(response){
if(response=='granted'){
orientation=1;
window.addEventListener('deviceorientation', orientationListener);
controls.orientation.classList.add('pnlm-orientation-button-active');
}});
}else{
orientation=1;
window.addEventListener('deviceorientation', orientationListener);
controls.orientation.classList.add('pnlm-orientation-button-active');
}}
function escapeHTML(s){
if(!initialConfig.escapeHTML)
return String(s).split('\n').join('<br>');
return String(s).split(/&/g).join('&amp;')
.split('"').join('&quot;')
.split("'").join('&#39;')
.split('<').join('&lt;')
.split('>').join('&gt;')
.split('/').join('&#x2f;')
.split('\n').join('<br>');
}
function sanitizeURL(url, href){
try {
var decoded_url=decodeURIComponent(unescape(url)).replace(/[^\w:]/g, '').toLowerCase();
} catch (e){
return 'about:blank';
}
if(decoded_url.indexOf('javascript:')===0 ||
decoded_url.indexOf('vbscript:')===0){
console.log('Script URL removed.');
return 'about:blank';
}
if(href&&decoded_url.indexOf('data:')===0){
console.log('Data URI removed from link.');
return 'about:blank';
}
return url;
}
function unescape(html){
return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n){
n=n.toLowerCase();
if(n==='colon') return ':';
if(n.charAt(0)==='#'){
return n.charAt(1)==='x'
? String.fromCharCode(parseInt(n.substring(2), 16))
: String.fromCharCode(+n.substring(1));
}
return '';
});
}
function sanitizeURLForCss(url){
return sanitizeURL(url)
.replace(/"/g, '%22')
.replace(/'/g, '%27');
}
this.isLoaded=function(){
return Boolean(loaded);
};
this.getPitch=function(){
return config.pitch;
};
this.setPitch=function(pitch, animated, callback, callbackArgs){
latestInteraction=Date.now();
if(Math.abs(pitch - config.pitch) <=eps){
if(typeof callback=='function')
callback(callbackArgs);
return this;
}
animated=animated==undefined ? 1000: Number(animated);
if(animated){
animatedMove.pitch={
'startTime': Date.now(),
'startPosition': config.pitch,
'endPosition': pitch,
'duration': animated
};
if(typeof callback=='function')
setTimeout(function(){callback(callbackArgs);}, animated);
}else{
config.pitch=pitch;
}
animateInit();
return this;
};
this.getPitchBounds=function(){
return [config.minPitch, config.maxPitch];
};
this.setPitchBounds=function(bounds){
config.minPitch=Math.max(-90, Math.min(bounds[0], 90));
config.maxPitch=Math.max(-90, Math.min(bounds[1], 90));
return this;
};
this.getYaw=function(){
return (config.yaw + 540) % 360 - 180;
};
this.setYaw=function(yaw, animated, callback, callbackArgs){
latestInteraction=Date.now();
if(Math.abs(yaw - config.yaw) <=eps){
if(typeof callback=='function')
callback(callbackArgs);
return this;
}
animated=animated==undefined ? 1000: Number(animated);
yaw=((yaw + 180) % 360) - 180;
if(animated){
if(config.yaw - yaw > 180)
yaw +=360;
else if(yaw - config.yaw > 180)
yaw -=360;
animatedMove.yaw={
'startTime': Date.now(),
'startPosition': config.yaw,
'endPosition': yaw,
'duration': animated
};
if(typeof callback=='function')
setTimeout(function(){callback(callbackArgs);}, animated);
}else{
config.yaw=yaw;
}
animateInit();
return this;
};
this.getYawBounds=function(){
return [config.minYaw, config.maxYaw];
};
this.setYawBounds=function(bounds){
config.minYaw=Math.max(-360, Math.min(bounds[0], 360));
config.maxYaw=Math.max(-360, Math.min(bounds[1], 360));
return this;
};
this.getHfov=function(){
return config.hfov;
};
this.setHfov=function(hfov, animated, callback, callbackArgs){
latestInteraction=Date.now();
if(Math.abs(hfov - config.hfov) <=eps){
if(typeof callback=='function')
callback(callbackArgs);
return this;
}
animated=animated==undefined ? 1000: Number(animated);
if(animated){
animatedMove.hfov={
'startTime': Date.now(),
'startPosition': config.hfov,
'endPosition': constrainHfov(hfov),
'duration': animated
};
if(typeof callback=='function')
setTimeout(function(){callback(callbackArgs);}, animated);
}else{
setHfov(hfov);
}
animateInit();
return this;
};
this.getHfovBounds=function(){
return [config.minHfov, config.maxHfov];
};
this.setHfovBounds=function(bounds){
config.minHfov=Math.max(0, bounds[0]);
config.maxHfov=Math.max(0, bounds[1]);
return this;
};
this.lookAt=function(pitch, yaw, hfov, animated, callback, callbackArgs){
animated=animated==undefined ? 1000: Number(animated);
if(pitch!==undefined&&Math.abs(pitch - config.pitch) > eps){
this.setPitch(pitch, animated, callback, callbackArgs);
callback=undefined;
}
if(yaw!==undefined&&Math.abs(yaw - config.yaw) > eps){
this.setYaw(yaw, animated, callback, callbackArgs);
callback=undefined;
}
if(hfov!==undefined&&Math.abs(hfov - config.hfov) > eps){
this.setHfov(hfov, animated, callback, callbackArgs);
callback=undefined;
}
if(typeof callback=='function')
callback(callbackArgs);
return this;
};
this.getNorthOffset=function(){
return config.northOffset;
};
this.setNorthOffset=function(heading){
config.northOffset=Math.min(360, Math.max(0, heading));
animateInit();
return this;
};
this.getHorizonRoll=function(){
return config.horizonRoll;
};
this.setHorizonRoll=function(roll){
config.horizonRoll=Math.min(90, Math.max(-90, roll));
renderer.setPose(config.horizonPitch * Math.PI / 180, config.horizonRoll * Math.PI / 180);
animateInit();
return this;
};
this.getHorizonPitch=function(){
return config.horizonPitch;
};
this.setHorizonPitch=function(pitch){
config.horizonPitch=Math.min(90, Math.max(-90, pitch));
renderer.setPose(config.horizonPitch * Math.PI / 180, config.horizonRoll * Math.PI / 180);
animateInit();
return this;
};
this.startAutoRotate=function(speed, pitch){
speed=speed||autoRotateSpeed||1;
pitch=pitch===undefined ? origPitch:pitch;
config.autoRotate=speed;
_this.lookAt(pitch, undefined, origHfov, 3000);
animating=false;
animateInit();
return this;
};
this.stopAutoRotate=function(){
autoRotateSpeed=config.autoRotate ? config.autoRotate:autoRotateSpeed;
config.autoRotate=false;
config.autoRotateInactivityDelay=-1;
return this;
};
this.stopMovement=function(){
stopAnimation();
speed={'yaw': 0, 'pitch': 0, 'hfov': 0};};
this.getRenderer=function(){
return renderer;
};
this.setUpdate=function(bool){
update=bool===true;
if(renderer===undefined)
onImageLoad();
else
animateInit();
return this;
};
this.mouseEventToCoords=function(event){
return mouseEventToCoords(event);
};
this.loadScene=function(sceneId, pitch, yaw, hfov){
if(loaded!==false)
loadScene(sceneId, pitch, yaw, hfov);
return this;
};
this.getScene=function(){
return config.scene;
};
this.addScene=function(sceneId, config){
initialConfig.scenes[sceneId]=config;
return this;
};
this.removeScene=function(sceneId){
if(config.scene===sceneId||!initialConfig.scenes.hasOwnProperty(sceneId))
return false;
delete initialConfig.scenes[sceneId];
return true;
};
this.toggleFullscreen=function(){
toggleFullscreen();
return this;
};
this.getConfig=function(){
return config;
};
this.getContainer=function(){
return container;
};
this.addHotSpot=function(hs, sceneId){
if(sceneId===undefined&&config.scene===undefined){
config.hotSpots.push(hs);
}else{
var id=sceneId!==undefined ? sceneId:config.scene;
if(initialConfig.scenes.hasOwnProperty(id)){
if(!initialConfig.scenes[id].hasOwnProperty('hotSpots')){
initialConfig.scenes[id].hotSpots=[];
if(id==config.scene)
config.hotSpots=initialConfig.scenes[id].hotSpots;
}
initialConfig.scenes[id].hotSpots.push(hs);
}else{
throw 'Invalid scene ID!';
}}
if(sceneId===undefined||config.scene==sceneId){
createHotSpot(hs);
if(loaded)
renderHotSpot(hs);
}
return this;
};
this.removeHotSpot=function(hotSpotId, sceneId){
if(sceneId===undefined||config.scene==sceneId){
if(!config.hotSpots)
return false;
for (var i=0; i < config.hotSpots.length; i++){
if(config.hotSpots[i].hasOwnProperty('id') &&
config.hotSpots[i].id===hotSpotId){
var current=config.hotSpots[i].div;
while (current.parentNode!=renderContainer)
current=current.parentNode;
renderContainer.removeChild(current);
delete config.hotSpots[i].div;
config.hotSpots.splice(i, 1);
return true;
}}
}else{
if(initialConfig.scenes.hasOwnProperty(sceneId)){
if(!initialConfig.scenes[sceneId].hasOwnProperty('hotSpots'))
return false;
for (var j=0; j < initialConfig.scenes[sceneId].hotSpots.length; j++){
if(initialConfig.scenes[sceneId].hotSpots[j].hasOwnProperty('id') &&
initialConfig.scenes[sceneId].hotSpots[j].id===hotSpotId){
initialConfig.scenes[sceneId].hotSpots.splice(j, 1);
return true;
}}
}else{
return false;
}}
};
this.resize=function(){
if(renderer)
onDocumentResize();
};
this.isLoaded=function(){
return loaded;
};
this.isOrientationSupported=function(){
return orientationSupport||false;
};
this.stopOrientation=function(){
stopOrientation();
};
this.startOrientation=function(){
if(orientationSupport)
startOrientation();
};
this.isOrientationActive=function(){
return Boolean(orientation);
};
this.on=function(type, listener){
externalEventListeners[type]=externalEventListeners[type]||[];
externalEventListeners[type].push(listener);
return this;
};
this.off=function(type, listener){
if(!type){
externalEventListeners={};
return this;
}
if(listener){
var i=externalEventListeners[type].indexOf(listener);
if(i >=0){
externalEventListeners[type].splice(i, 1);
}
if(externalEventListeners[type].length==0){
delete externalEventListeners[type];
}}else{
delete externalEventListeners[type];
}
return this;
};
function fireEvent(type){
if(type in externalEventListeners){
for (var i=externalEventListeners[type].length; i > 0; i--){
externalEventListeners[type][externalEventListeners[type].length - i].apply(null, [].slice.call(arguments, 1));
}}
}
this.destroy=function(){
destroyed=true;
clearTimeout(autoRotateStart);
if(renderer)
renderer.destroy();
if(listenersAdded){
document.removeEventListener('mousemove', onDocumentMouseMove, false);
document.removeEventListener('mouseup', onDocumentMouseUp, false);
container.removeEventListener('mozfullscreenchange', onFullScreenChange, false);
container.removeEventListener('webkitfullscreenchange', onFullScreenChange, false);
container.removeEventListener('msfullscreenchange', onFullScreenChange, false);
container.removeEventListener('fullscreenchange', onFullScreenChange, false);
window.removeEventListener('resize', onDocumentResize, false);
window.removeEventListener('orientationchange', onDocumentResize, false);
container.removeEventListener('keydown', onDocumentKeyPress, false);
container.removeEventListener('keyup', onDocumentKeyUp, false);
container.removeEventListener('blur', clearKeys, false);
document.removeEventListener('mouseleave', onDocumentMouseUp, false);
}
container.innerHTML='';
container.classList.remove('pnlm-container');
};}
return {
viewer: function(container, config){
return new Viewer(container, config);
}};})(window, document);
window.libpannellum=(function(window, document, undefined){
'use strict';
function Renderer(container){
var canvas=document.createElement('canvas');
canvas.style.width=canvas.style.height='100%';
container.appendChild(canvas);
var program, gl, vs, fs;
var fallbackImgSize;
var world;
var vtmps;
var pose;
var image, imageType, dynamic;
var texCoordBuffer, cubeVertBuf, cubeVertTexCoordBuf, cubeVertIndBuf;
var globalParams;
this.init=function(_image, _imageType, _dynamic, haov, vaov, voffset, callback, params){
if(_imageType===undefined)
_imageType='equirectangular';
if(_imageType!='equirectangular'&&_imageType!='cubemap' &&
_imageType!='multires'){
console.log('Error: invalid image type specified!');
throw {type: 'config error'};}
imageType=_imageType;
image=_image;
dynamic=_dynamic;
globalParams=params||{};
if(program){
if(vs){
gl.detachShader(program, vs);
gl.deleteShader(vs);
}
if(fs){
gl.detachShader(program, fs);
gl.deleteShader(fs);
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
if(program.texture)
gl.deleteTexture(program.texture);
if(program.nodeCache)
for (var i=0; i < program.nodeCache.length; i++)
gl.deleteTexture(program.nodeCache[i].texture);
gl.deleteProgram(program);
program=undefined;
}
pose=undefined;
var s;
var faceMissing=false;
var cubeImgWidth;
if(imageType=='cubemap'){
for (s=0; s < 6; s++){
if(image[s].width > 0){
if(cubeImgWidth===undefined)
cubeImgWidth=image[s].width;
if(cubeImgWidth!=image[s].width)
console.log('Cube faces have inconsistent widths: ' + cubeImgWidth + ' vs. ' + image[s].width);
} else
faceMissing=true;
}}
function fillMissingFaces(imgSize){
if(faceMissing){
var nbytes=imgSize * imgSize * 4;
var imageArray=new Uint8ClampedArray(nbytes);
var rgb=params.backgroundColor ? params.backgroundColor:[0, 0, 0];
rgb[0] *=255;
rgb[1] *=255;
rgb[2] *=255;
for (var i=0; i < nbytes; i++){
imageArray[i++]=rgb[0];
imageArray[i++]=rgb[1];
imageArray[i++]=rgb[2];
}
var backgroundSquare=new ImageData(imageArray, imgSize, imgSize);
for (s=0; s < 6; s++){
if(image[s].width==0)
image[s]=backgroundSquare;
}}
}
if(!(imageType=='cubemap' &&
(cubeImgWidth & (cubeImgWidth - 1))!==0 &&
(navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 8_/) ||
navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 9_/) ||
navigator.userAgent.toLowerCase().match(/(iphone|ipod|ipad).* os 10_/) ||
navigator.userAgent.match(/Trident.*rv[ :]*11\./)))){
if(!gl)
gl=canvas.getContext('experimental-webgl', {alpha: false, depth: false});
if(gl&&gl.getError()==1286)
handleWebGLError1286();
}
if(!gl&&((imageType=='multires'&&image.hasOwnProperty('fallbackPath')) ||
imageType=='cubemap') &&
('WebkitAppearance' in document.documentElement.style ||
navigator.userAgent.match(/Trident.*rv[ :]*11\./) ||
navigator.appVersion.indexOf('MSIE 10')!==-1)){
if(world){
container.removeChild(world);
}
world=document.createElement('div');
world.className='pnlm-world';
var path;
if(image.basePath){
path=image.basePath + image.fallbackPath;
}else{
path=image.fallbackPath;
}
var sides=['f', 'r', 'b', 'l', 'u', 'd'];
var loaded=0;
var onLoad=function(){
var faceCanvas=document.createElement('canvas');
faceCanvas.className='pnlm-face pnlm-' + sides[this.side] + 'face';
world.appendChild(faceCanvas);
var faceContext=faceCanvas.getContext('2d');
faceCanvas.style.width=this.width + 4 + 'px';
faceCanvas.style.height=this.height + 4 + 'px';
faceCanvas.width=this.width + 4;
faceCanvas.height=this.height + 4;
faceContext.drawImage(this, 2, 2);
var imgData=faceContext.getImageData(0, 0, faceCanvas.width, faceCanvas.height);
var data=imgData.data;
var i;
var j;
for (i=2; i < faceCanvas.width - 2; i++){
for (j=0; j < 4; j++){
data[(i + faceCanvas.width) * 4 + j]=data[(i + faceCanvas.width * 2) * 4 + j];
data[(i + faceCanvas.width * (faceCanvas.height - 2)) * 4 + j]=data[(i + faceCanvas.width * (faceCanvas.height - 3)) * 4 + j];
}}
for (i=2; i < faceCanvas.height - 2; i++){
for (j=0; j < 4; j++){
data[(i * faceCanvas.width + 1) * 4 + j]=data[(i * faceCanvas.width + 2) * 4 + j];
data[((i + 1) * faceCanvas.width - 2) * 4 + j]=data[((i + 1) * faceCanvas.width - 3) * 4 + j];
}}
for (j=0; j < 4; j++){
data[(faceCanvas.width + 1) * 4 + j]=data[(faceCanvas.width * 2 + 2) * 4 + j];
data[(faceCanvas.width * 2 - 2) * 4 + j]=data[(faceCanvas.width * 3 - 3) * 4 + j];
data[(faceCanvas.width * (faceCanvas.height - 2) + 1) * 4 + j]=data[(faceCanvas.width * (faceCanvas.height - 3) + 2) * 4 + j];
data[(faceCanvas.width * (faceCanvas.height - 1) - 2) * 4 + j]=data[(faceCanvas.width * (faceCanvas.height - 2) - 3) * 4 + j];
}
for (i=1; i < faceCanvas.width - 1; i++){
for (j=0; j < 4; j++){
data[i * 4 + j]=data[(i + faceCanvas.width) * 4 + j];
data[(i + faceCanvas.width * (faceCanvas.height - 1)) * 4 + j]=data[(i + faceCanvas.width * (faceCanvas.height - 2)) * 4 + j];
}}
for (i=1; i < faceCanvas.height - 1; i++){
for (j=0; j < 4; j++){
data[(i * faceCanvas.width) * 4 + j]=data[(i * faceCanvas.width + 1) * 4 + j];
data[((i + 1) * faceCanvas.width - 1) * 4 + j]=data[((i + 1) * faceCanvas.width - 2) * 4 + j];
}}
for (j=0; j < 4; j++){
data[j]=data[(faceCanvas.width + 1) * 4 + j];
data[(faceCanvas.width - 1) * 4 + j]=data[(faceCanvas.width * 2 - 2) * 4 + j];
data[(faceCanvas.width * (faceCanvas.height - 1)) * 4 + j]=data[(faceCanvas.width * (faceCanvas.height - 2) + 1) * 4 + j];
data[(faceCanvas.width * faceCanvas.height - 1) * 4 + j]=data[(faceCanvas.width * (faceCanvas.height - 1) - 2) * 4 + j];
}
faceContext.putImageData(imgData, 0, 0);
incLoaded.call(this);
};
var incLoaded=function(){
if(this.width > 0){
if(fallbackImgSize===undefined)
fallbackImgSize=this.width;
if(fallbackImgSize!=this.width)
console.log('Fallback faces have inconsistent widths: ' + fallbackImgSize + ' vs. ' + this.width);
} else
faceMissing=true;
loaded++;
if(loaded==6){
fallbackImgSize=this.width;
container.appendChild(world);
callback();
}};
faceMissing=false;
for (s=0; s < 6; s++){
var faceImg=new Image();
faceImg.crossOrigin=globalParams.crossOrigin ? globalParams.crossOrigin:'anonymous';
faceImg.side=s;
faceImg.onload=onLoad;
faceImg.onerror=incLoaded;
if(imageType=='multires'){
faceImg.src=path.replace('%s', sides[s]) + '.' + image.extension;
}else{
faceImg.src=image[s].src;
}}
fillMissingFaces(fallbackImgSize);
return;
}else if(!gl){
console.log('Error: no WebGL support detected!');
throw {type: 'no webgl'};}
if(imageType=='cubemap')
fillMissingFaces(cubeImgWidth);
if(image.basePath){
image.fullpath=image.basePath + image.path;
}else{
image.fullpath=image.path;
}
image.invTileResolution=1 / image.tileResolution;
var vertices=createCube();
vtmps=[];
for (s=0; s < 6; s++){
vtmps[s]=vertices.slice(s * 12, s * 12 + 12);
vertices=createCube();
}
var maxWidth=0;
if(imageType=='equirectangular'){
maxWidth=gl.getParameter(gl.MAX_TEXTURE_SIZE);
if(Math.max(image.width / 2, image.height) > maxWidth){
console.log('Error: The image is too big; it\'s ' + image.width + 'px wide, '+
'but this device\'s maximum supported size is ' + (maxWidth * 2) + 'px.');
throw {type: 'webgl size error', width: image.width, maxWidth: maxWidth * 2};}}else if(imageType=='cubemap'){
if(cubeImgWidth > gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE)){
console.log('Error: The image is too big; it\'s ' + cubeImgWidth + 'px wide, ' +
'but this device\'s maximum supported size is ' + maxWidth + 'px.');
throw {type: 'webgl size error', width: cubeImgWidth, maxWidth: maxWidth};}}
if(params!==undefined&&(params.horizonPitch!==undefined||params.horizonRoll!==undefined))
pose=[params.horizonPitch==undefined ? 0:params.horizonPitch,
params.horizonRoll==undefined ? 0:params.horizonRoll];
var glBindType=gl.TEXTURE_2D;
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
if(gl.getShaderPrecisionFormat){
var precision=gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
if(precision&&precision.precision < 1){
fragEquiCubeBase=fragEquiCubeBase.replace('highp', 'mediump');
}}
vs=gl.createShader(gl.VERTEX_SHADER);
var vertexSrc=v;
if(imageType=='multires'){
vertexSrc=vMulti;
}
gl.shaderSource(vs, vertexSrc);
gl.compileShader(vs);
fs=gl.createShader(gl.FRAGMENT_SHADER);
var fragmentSrc=fragEquirectangular;
if(imageType=='cubemap'){
glBindType=gl.TEXTURE_CUBE_MAP;
fragmentSrc=fragCube;
}else if(imageType=='multires'){
fragmentSrc=fragMulti;
}
gl.shaderSource(fs, fragmentSrc);
gl.compileShader(fs);
program=gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if(!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
console.log(gl.getShaderInfoLog(vs));
if(!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
console.log(gl.getShaderInfoLog(fs));
if(!gl.getProgramParameter(program, gl.LINK_STATUS))
console.log(gl.getProgramInfoLog(program));
gl.useProgram(program);
program.drawInProgress=false;
var color=params.backgroundColor ? params.backgroundColor:[0, 0, 0];
gl.clearColor(color[0], color[1], color[2], 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
program.texCoordLocation=gl.getAttribLocation(program, 'a_texCoord');
gl.enableVertexAttribArray(program.texCoordLocation);
if(imageType!='multires'){
if(!texCoordBuffer)
texCoordBuffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,1,1,1,1,-1,-1,1,1,-1,-1,-1]), gl.STATIC_DRAW);
gl.vertexAttribPointer(program.texCoordLocation, 2, gl.FLOAT, false, 0, 0);
program.aspectRatio=gl.getUniformLocation(program, 'u_aspectRatio');
gl.uniform1f(program.aspectRatio, gl.drawingBufferWidth / gl.drawingBufferHeight);
program.psi=gl.getUniformLocation(program, 'u_psi');
program.theta=gl.getUniformLocation(program, 'u_theta');
program.f=gl.getUniformLocation(program, 'u_f');
program.h=gl.getUniformLocation(program, 'u_h');
program.v=gl.getUniformLocation(program, 'u_v');
program.vo=gl.getUniformLocation(program, 'u_vo');
program.rot=gl.getUniformLocation(program, 'u_rot');
gl.uniform1f(program.h, haov / (Math.PI * 2.0));
gl.uniform1f(program.v, vaov / Math.PI);
gl.uniform1f(program.vo, voffset / Math.PI * 2);
if(imageType=='equirectangular'){
program.backgroundColor=gl.getUniformLocation(program, 'u_backgroundColor');
gl.uniform4fv(program.backgroundColor, color.concat([1]));
}
program.texture=gl.createTexture();
gl.bindTexture(glBindType, program.texture);
if(imageType=='cubemap'){
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[1]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[3]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[4]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[5]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[0]);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[2]);
}else{
if(image.width <=maxWidth){
gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 0);
gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
}else{
gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 1);
var cropCanvas=document.createElement('canvas');
cropCanvas.width=image.width / 2;
cropCanvas.height=image.height;
var cropContext=cropCanvas.getContext('2d');
cropContext.drawImage(image, 0, 0);
var cropImage=cropContext.getImageData(0, 0, image.width / 2, image.height);
gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage);
program.texture2=gl.createTexture();
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(glBindType, program.texture2);
gl.uniform1i(gl.getUniformLocation(program, 'u_image1'), 1);
cropContext.drawImage(image, -image.width / 2, 0);
cropImage=cropContext.getImageData(0, 0, image.width / 2, image.height);
gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage);
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(glBindType, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.activeTexture(gl.TEXTURE0);
}}
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(glBindType, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(glBindType, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
}else{
program.vertPosLocation=gl.getAttribLocation(program, 'a_vertCoord');
gl.enableVertexAttribArray(program.vertPosLocation);
if(!cubeVertBuf)
cubeVertBuf=gl.createBuffer();
if(!cubeVertTexCoordBuf)
cubeVertTexCoordBuf=gl.createBuffer();
if(!cubeVertIndBuf)
cubeVertIndBuf=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertTexCoordBuf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,0,1,0,1,1,0,1]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertIndBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,1,2,0,2,3]), gl.STATIC_DRAW);
program.perspUniform=gl.getUniformLocation(program, 'u_perspMatrix');
program.cubeUniform=gl.getUniformLocation(program, 'u_cubeMatrix');
program.level=-1;
program.currentNodes=[];
program.nodeCache=[];
program.nodeCacheTimestamp=0;
}
var err=gl.getError();
if(err!==0){
console.log('Error: Something went wrong with WebGL!', err);
throw {type: 'webgl error'};}
callback();
};
this.destroy=function(){
if(container!==undefined){
if(canvas!==undefined&&container.contains(canvas)){
container.removeChild(canvas);
}
if(world!==undefined&&container.contains(world)){
container.removeChild(world);
}}
if(gl){
var extension=gl.getExtension('WEBGL_lose_context');
if(extension)
extension.loseContext();
}};
this.resize=function(){
var pixelRatio=window.devicePixelRatio||1;
canvas.width=canvas.clientWidth * pixelRatio;
canvas.height=canvas.clientHeight * pixelRatio;
if(gl){
if(gl.getError()==1286)
handleWebGLError1286();
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
if(imageType!='multires'){
gl.uniform1f(program.aspectRatio, canvas.clientWidth / canvas.clientHeight);
}}
};
this.resize();
this.setPose=function(horizonPitch, horizonRoll){
pose=[horizonPitch, horizonRoll];
};
this.render=function(pitch, yaw, hfov, params){
var focal, i, s, roll=0;
if(params===undefined)
params={};
if(params.roll)
roll=params.roll;
if(pose!==undefined){
var horizonPitch=pose[0],
horizonRoll=pose[1];
var orig_pitch=pitch,
orig_yaw=yaw,
x=Math.cos(horizonRoll) * Math.sin(pitch) * Math.sin(horizonPitch) +
Math.cos(pitch) * (Math.cos(horizonPitch) * Math.cos(yaw) +
Math.sin(horizonRoll) * Math.sin(horizonPitch) * Math.sin(yaw)),
y=-Math.sin(pitch) * Math.sin(horizonRoll) +
Math.cos(pitch) * Math.cos(horizonRoll) * Math.sin(yaw),
z=Math.cos(horizonRoll) * Math.cos(horizonPitch) * Math.sin(pitch) +
Math.cos(pitch) * (-Math.cos(yaw) * Math.sin(horizonPitch) +
Math.cos(horizonPitch) * Math.sin(horizonRoll) * Math.sin(yaw));
pitch=Math.asin(Math.max(Math.min(z, 1), -1));
yaw=Math.atan2(y, x);
var v=[Math.cos(orig_pitch) * (Math.sin(horizonRoll) * Math.sin(horizonPitch) * Math.cos(orig_yaw) -
Math.cos(horizonPitch) * Math.sin(orig_yaw)),
Math.cos(orig_pitch) * Math.cos(horizonRoll) * Math.cos(orig_yaw),
Math.cos(orig_pitch) * (Math.cos(horizonPitch) * Math.sin(horizonRoll) * Math.cos(orig_yaw) +
Math.sin(orig_yaw) * Math.sin(horizonPitch))],
w=[-Math.cos(pitch) * Math.sin(yaw), Math.cos(pitch) * Math.cos(yaw)];
var roll_adj=Math.acos(Math.max(Math.min((v[0]*w[0] + v[1]*w[1]) /
(Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]) *
Math.sqrt(w[0]*w[0]+w[1]*w[1])), 1), -1));
if(v[2] < 0)
roll_adj=2 * Math.PI - roll_adj;
roll +=roll_adj;
}
if(!gl&&(imageType=='multires'||imageType=='cubemap')){
s=fallbackImgSize / 2;
var transforms={
f: 'translate3d(-' + (s + 2) + 'px, -' + (s + 2) + 'px, -' + s + 'px)',
b: 'translate3d(' + (s + 2) + 'px, -' + (s + 2) + 'px, ' + s + 'px) rotateX(180deg) rotateZ(180deg)',
u: 'translate3d(-' + (s + 2) + 'px, -' + s + 'px, ' + (s + 2) + 'px) rotateX(270deg)',
d: 'translate3d(-' + (s + 2) + 'px, ' + s + 'px, -' + (s + 2) + 'px) rotateX(90deg)',
l: 'translate3d(-' + s + 'px, -' + (s + 2) + 'px, ' + (s + 2) + 'px) rotateX(180deg) rotateY(90deg) rotateZ(180deg)',
r: 'translate3d(' + s + 'px, -' + (s + 2) + 'px, -' + (s + 2) + 'px) rotateY(270deg)'
};
focal=1 / Math.tan(hfov / 2);
var zoom=focal * canvas.clientWidth / 2 + 'px';
var transform='perspective(' + zoom + ') translateZ(' + zoom + ') rotateX(' + pitch + 'rad) rotateY(' + yaw + 'rad) ';
var faces=Object.keys(transforms);
for (i=0; i < 6; i++){
var face=world.querySelector('.pnlm-' + faces[i] + 'face');
if(!face)
continue;
face.style.webkitTransform=transform + transforms[faces[i]];
face.style.transform=transform + transforms[faces[i]];
}
return;
}
if(imageType!='multires'){
var vfov=2 * Math.atan(Math.tan(hfov * 0.5) / (gl.drawingBufferWidth / gl.drawingBufferHeight));
focal=1 / Math.tan(vfov * 0.5);
gl.uniform1f(program.psi, yaw);
gl.uniform1f(program.theta, pitch);
gl.uniform1f(program.rot, roll);
gl.uniform1f(program.f, focal);
if(dynamic===true){
if(imageType=='equirectangular'){
gl.bindTexture(gl.TEXTURE_2D, program.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
}}
gl.drawArrays(gl.TRIANGLES, 0, 6);
}else{
var perspMatrix=makePersp(hfov, gl.drawingBufferWidth / gl.drawingBufferHeight, 0.1, 100.0);
checkZoom(hfov);
var matrix=identityMatrix3();
matrix=rotateMatrix(matrix, -roll, 'z');
matrix=rotateMatrix(matrix, -pitch, 'x');
matrix=rotateMatrix(matrix, yaw, 'y');
matrix=makeMatrix4(matrix);
gl.uniformMatrix4fv(program.perspUniform, false, new Float32Array(transposeMatrix4(perspMatrix)));
gl.uniformMatrix4fv(program.cubeUniform, false, new Float32Array(transposeMatrix4(matrix)));
var rotPersp=rotatePersp(perspMatrix, matrix);
program.nodeCache.sort(multiresNodeSort);
if(program.nodeCache.length > 200 &&
program.nodeCache.length > program.currentNodes.length + 50){
var removed=program.nodeCache.splice(200, program.nodeCache.length - 200);
for (var j=0; j < removed.length; j++){
gl.deleteTexture(removed[j].texture);
}}
program.currentNodes=[];
var sides=['f', 'b', 'u', 'd', 'l', 'r'];
for (s=0; s < 6; s++){
var ntmp=new MultiresNode(vtmps[s], sides[s], 1, 0, 0, image.fullpath);
testMultiresNode(rotPersp, ntmp, pitch, yaw, hfov);
}
program.currentNodes.sort(multiresNodeRenderSort);
for (i=pendingTextureRequests.length - 1; i >=0; i--){
if(program.currentNodes.indexOf(pendingTextureRequests[i].node)===-1){
pendingTextureRequests[i].node.textureLoad=false;
pendingTextureRequests.splice(i, 1);
}}
if(pendingTextureRequests.length===0){
for (i=0; i < program.currentNodes.length; i++){
var node=program.currentNodes[i];
if(!node.texture&&!node.textureLoad){
node.textureLoad=true;
setTimeout(processNextTile, 0, node);
break;
}}
}
multiresDraw();
}
if(params.returnImage!==undefined){
return canvas.toDataURL('image/png');
}};
this.isLoading=function(){
if(gl&&imageType=='multires'){
for(var i=0; i < program.currentNodes.length; i++){
if(!program.currentNodes[i].textureLoaded){
return true;
}}
}
return false;
};
this.getCanvas=function(){
return canvas;
};
function multiresNodeSort(a, b){
if(a.level==1&&b.level!=1){
return -1;
}
if(b. level==1&&a.level!=1){
return 1;
}
return b.timestamp - a.timestamp;
}
function multiresNodeRenderSort(a, b){
if(a.level!=b.level){
return a.level - b.level;
}
return a.diff - b.diff;
}
function multiresDraw(){
if(!program.drawInProgress){
program.drawInProgress=true;
gl.clear(gl.COLOR_BUFFER_BIT);
for(var i=0; i < program.currentNodes.length; i++){
if(program.currentNodes[i].textureLoaded > 1){
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertBuf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(program.currentNodes[i].vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(program.vertPosLocation, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertTexCoordBuf);
gl.vertexAttribPointer(program.texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.bindTexture(gl.TEXTURE_2D, program.currentNodes[i].texture);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}}
program.drawInProgress=false;
}}
function MultiresNode(vertices, side, level, x, y, path){
this.vertices=vertices;
this.side=side;
this.level=level;
this.x=x;
this.y=y;
this.path=path.replace('%s',side).replace('%l',level).replace('%x',x).replace('%y',y);
}
function testMultiresNode(rotPersp, node, pitch, yaw, hfov){
if(checkSquareInView(rotPersp, node.vertices)){
var v=node.vertices;
var x=v[0] + v[3] + v[6] + v[ 9];
var y=v[1] + v[4] + v[7] + v[10];
var z=v[2] + v[5] + v[8] + v[11];
var r=Math.sqrt(x*x + y*y + z*z);
var theta=Math.asin(z / r);
var phi=Math.atan2(y, x);
var ydiff=phi - yaw;
ydiff +=(ydiff > Math.PI) ? -2 * Math.PI:(ydiff < -Math.PI) ? 2 * Math.PI:0;
ydiff=Math.abs(ydiff);
node.diff=Math.acos(Math.sin(pitch) * Math.sin(theta) + Math.cos(pitch) * Math.cos(theta) * Math.cos(ydiff));
var inCurrent=false;
for (var k=0; k < program.nodeCache.length; k++){
if(program.nodeCache[k].path==node.path){
inCurrent=true;
program.nodeCache[k].timestamp=program.nodeCacheTimestamp++;
program.nodeCache[k].diff=node.diff;
program.currentNodes.push(program.nodeCache[k]);
break;
}}
if(!inCurrent){
node.timestamp=program.nodeCacheTimestamp++;
program.currentNodes.push(node);
program.nodeCache.push(node);
}
if(node.level < program.level){
var cubeSize=image.cubeResolution * Math.pow(2, node.level - image.maxLevel);
var numTiles=Math.ceil(cubeSize * image.invTileResolution) - 1;
var doubleTileSize=cubeSize % image.tileResolution * 2;
var lastTileSize=(cubeSize * 2) % image.tileResolution;
if(lastTileSize===0){
lastTileSize=image.tileResolution;
}
if(doubleTileSize===0){
doubleTileSize=image.tileResolution * 2;
}
var f=0.5;
if(node.x==numTiles||node.y==numTiles){
f=1.0 - image.tileResolution / (image.tileResolution + lastTileSize);
}
var i=1.0 - f;
var children=[];
var vtmp, ntmp;
var f1=f, f2=f, f3=f, i1=i, i2=i, i3=i;
if(lastTileSize < image.tileResolution){
if(node.x==numTiles&&node.y!=numTiles){
f2=0.5;
i2=0.5;
if(node.side=='d'||node.side=='u'){
f3=0.5;
i3=0.5;
}}else if(node.x!=numTiles&&node.y==numTiles){
f1=0.5;
i1=0.5;
if(node.side=='l'||node.side=='r'){
f3=0.5;
i3=0.5;
}}
}
if(doubleTileSize <=image.tileResolution){
if(node.x==numTiles){
f1=0;
i1=1;
if(node.side=='l'||node.side=='r'){
f3=0;
i3=1;
}}
if(node.y==numTiles){
f2=0;
i2=1;
if(node.side=='d'||node.side=='u'){
f3=0;
i3=1;
}}
}
vtmp=[           v[0],             v[1],             v[2],
v[0]*f1+v[3]*i1,    v[1]*f+v[4]*i,  v[2]*f3+v[5]*i3,
v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3,
v[0]*f+v[9]*i, v[1]*f2+v[10]*i2, v[2]*f3+v[11]*i3
];
ntmp=new MultiresNode(vtmp, node.side, node.level + 1, node.x*2, node.y*2, image.fullpath);
children.push(ntmp);
if(!(node.x==numTiles&&doubleTileSize <=image.tileResolution)){
vtmp=[v[0]*f1+v[3]*i1,    v[1]*f+v[4]*i,  v[2]*f3+v[5]*i3,
v[3],             v[4],             v[5],
v[3]*f+v[6]*i,  v[4]*f2+v[7]*i2,  v[5]*f3+v[8]*i3,
v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3
];
ntmp=new MultiresNode(vtmp, node.side, node.level + 1, node.x*2+1, node.y*2, image.fullpath);
children.push(ntmp);
}
if(!(node.x==numTiles&&doubleTileSize <=image.tileResolution) &&
!(node.y==numTiles&&doubleTileSize <=image.tileResolution)){
vtmp=[v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3,
v[3]*f+v[6]*i,  v[4]*f2+v[7]*i2,  v[5]*f3+v[8]*i3,
v[6],             v[7],             v[8],
v[9]*f1+v[6]*i1,   v[10]*f+v[7]*i, v[11]*f3+v[8]*i3
];
ntmp=new MultiresNode(vtmp, node.side, node.level + 1, node.x*2+1, node.y*2+1, image.fullpath);
children.push(ntmp);
}
if(!(node.y==numTiles&&doubleTileSize <=image.tileResolution)){
vtmp=[  v[0]*f+v[9]*i, v[1]*f2+v[10]*i2, v[2]*f3+v[11]*i3,
v[0]*f1+v[6]*i1,  v[1]*f2+v[7]*i2,  v[2]*f3+v[8]*i3,
v[9]*f1+v[6]*i1,   v[10]*f+v[7]*i, v[11]*f3+v[8]*i3,
v[9],            v[10],            v[11]
];
ntmp=new MultiresNode(vtmp, node.side, node.level + 1, node.x*2, node.y*2+1, image.fullpath);
children.push(ntmp);
}
for (var j=0; j < children.length; j++){
testMultiresNode(rotPersp, children[j], pitch, yaw, hfov);
}}
}}
function createCube(){
return [-1,  1, -1,  1,  1, -1,  1, -1, -1, -1, -1, -1,
1,  1,  1, -1,  1,  1, -1, -1,  1,  1, -1,  1,
-1,  1,  1,  1,  1,  1,  1,  1, -1, -1,  1, -1,
-1, -1, -1,  1, -1, -1,  1, -1,  1, -1, -1,  1,
-1,  1,  1, -1,  1, -1, -1, -1, -1, -1, -1,  1,
1,  1, -1,  1,  1,  1,  1, -1,  1,  1, -1, -1 
];
}
function identityMatrix3(){
return [
1, 0, 0,
0, 1, 0,
0, 0, 1
];
}
function rotateMatrix(m, angle, axis){
var s=Math.sin(angle);
var c=Math.cos(angle);
if(axis=='x'){
return [
m[0], c*m[1] + s*m[2], c*m[2] - s*m[1],
m[3], c*m[4] + s*m[5], c*m[5] - s*m[4],
m[6], c*m[7] + s*m[8], c*m[8] - s*m[7]
];
}
if(axis=='y'){
return [
c*m[0] - s*m[2], m[1], c*m[2] + s*m[0],
c*m[3] - s*m[5], m[4], c*m[5] + s*m[3],
c*m[6] - s*m[8], m[7], c*m[8] + s*m[6]
];
}
if(axis=='z'){
return [
c*m[0] + s*m[1], c*m[1] - s*m[0], m[2],
c*m[3] + s*m[4], c*m[4] - s*m[3], m[5],
c*m[6] + s*m[7], c*m[7] - s*m[6], m[8]
];
}}
function makeMatrix4(m){
return [
m[0], m[1], m[2],    0,
m[3], m[4], m[5],    0,
m[6], m[7], m[8],    0,
0,    0,    0,    1
];
}
function transposeMatrix4(m){
return [
m[ 0], m[ 4], m[ 8], m[12],
m[ 1], m[ 5], m[ 9], m[13],
m[ 2], m[ 6], m[10], m[14],
m[ 3], m[ 7], m[11], m[15]
];
}
function makePersp(hfov, aspect, znear, zfar){
var fovy=2 * Math.atan(Math.tan(hfov/2) * gl.drawingBufferHeight / gl.drawingBufferWidth);
var f=1 / Math.tan(fovy/2);
return [
f/aspect,   0,  0,  0,
0,   f,  0,  0,
0,   0,  (zfar+znear)/(znear-zfar), (2*zfar*znear)/(znear-zfar),
0,   0, -1,  0
];
}
function processLoadedTexture(img, tex){
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
}
var pendingTextureRequests=[];
var loadTexture=(function(){
var cacheTop=4;
var textureImageCache={};
var crossOrigin;
function TextureImageLoader(){
var self=this;
this.texture=this.callback=null;
this.image=new Image();
this.image.crossOrigin=crossOrigin ? crossOrigin:'anonymous';
var loadFn=(function(){
if(self.image.width > 0&&self.image.height > 0){
processLoadedTexture(self.image, self.texture);
self.callback(self.texture, true);
}else{
self.callback(self.texture, false);
}
releaseTextureImageLoader(self);
});
this.image.addEventListener('load', loadFn);
this.image.addEventListener('error', loadFn);
}
TextureImageLoader.prototype.loadTexture=function(src, texture, callback){
this.texture=texture;
this.callback=callback;
this.image.src=src;
};
function PendingTextureRequest(node, src, texture, callback){
this.node=node;
this.src=src;
this.texture=texture;
this.callback=callback;
}
function releaseTextureImageLoader(til){
if(pendingTextureRequests.length){
var req=pendingTextureRequests.shift();
til.loadTexture(req.src, req.texture, req.callback);
} else
textureImageCache[cacheTop++]=til;
}
for (var i=0; i < cacheTop; i++)
textureImageCache[i]=new TextureImageLoader();
return function(node, src, callback, _crossOrigin){
crossOrigin=_crossOrigin;
var texture=gl.createTexture();
if(cacheTop)
textureImageCache[--cacheTop].loadTexture(src, texture, callback);
else
pendingTextureRequests.push(new PendingTextureRequest(node, src, texture, callback));
return texture;
};})();
function processNextTile(node){
loadTexture(node, node.path + '.' + image.extension, function(texture, loaded){
node.texture=texture;
node.textureLoaded=loaded ? 2:1;
}, globalParams.crossOrigin);
}
function checkZoom(hfov){
var newLevel=1;
while(newLevel < image.maxLevel &&
gl.drawingBufferWidth > image.tileResolution *
Math.pow(2, newLevel - 1) * Math.tan(hfov / 2) * 0.707){
newLevel++;
}
program.level=newLevel;
}
function rotatePersp(p, r){
return [
p[ 0]*r[0], p[ 0]*r[1], p[ 0]*r[ 2],     0,
p[ 5]*r[4], p[ 5]*r[5], p[ 5]*r[ 6],     0,
p[10]*r[8], p[10]*r[9], p[10]*r[10], p[11],
-r[8],      -r[9],      -r[10],     0
];
}
function applyRotPerspToVec(m, v){
return [
m[ 0]*v[0] + m[ 1]*v[1] + m[ 2]*v[2],
m[ 4]*v[0] + m[ 5]*v[1] + m[ 6]*v[2],
m[11] + m[ 8]*v[0] + m[ 9]*v[1] + m[10]*v[2],
1/(m[12]*v[0] + m[13]*v[1] + m[14]*v[2])
];
}
function checkInView(m, v){
var vpp=applyRotPerspToVec(m, v);
var winX=vpp[0]*vpp[3];
var winY=vpp[1]*vpp[3];
var winZ=vpp[2]*vpp[3];
var ret=[0, 0, 0];
if(winX < -1)
ret[0]=-1;
if(winX > 1)
ret[0]=1;
if(winY < -1)
ret[1]=-1;
if(winY > 1)
ret[1]=1;
if(winZ < -1||winZ > 1)
ret[2]=1;
return ret;
}
function checkSquareInView(m, v){
var check1=checkInView(m, v.slice(0, 3));
var check2=checkInView(m, v.slice(3, 6));
var check3=checkInView(m, v.slice(6, 9));
var check4=checkInView(m, v.slice(9, 12));
var testX=check1[0] + check2[0] + check3[0] + check4[0];
if(testX==-4||testX==4)
return false;
var testY=check1[1] + check2[1] + check3[1] + check4[1];
if(testY==-4||testY==4)
return false;
var testZ=check1[2] + check2[2] + check3[2] + check4[2];
return testZ!=4;
}
function handleWebGLError1286(){
console.log('Reducing canvas size due to error 1286!');
canvas.width=Math.round(canvas.width / 2);
canvas.height=Math.round(canvas.height / 2);
}}
var v=[
'attribute vec2 a_texCoord;',
'varying vec2 v_texCoord;',
'void main(){',
'gl_Position=vec4(a_texCoord, 0.0, 1.0);',
'v_texCoord=a_texCoord;',
'}'
].join('');
var vMulti=[
'attribute vec3 a_vertCoord;',
'attribute vec2 a_texCoord;',
'uniform mat4 u_cubeMatrix;',
'uniform mat4 u_perspMatrix;',
'varying mediump vec2 v_texCoord;',
'void main(void){',
'gl_Position=u_perspMatrix * u_cubeMatrix * vec4(a_vertCoord, 1.0);',
'v_texCoord=a_texCoord;',
'}'
].join('');
var fragEquiCubeBase=[
'precision highp float;',
'uniform float u_aspectRatio;',
'uniform float u_psi;',
'uniform float u_theta;',
'uniform float u_f;',
'uniform float u_h;',
'uniform float u_v;',
'uniform float u_vo;',
'uniform float u_rot;',
'const float PI=3.14159265358979323846264;',
'uniform sampler2D u_image0;',
'uniform sampler2D u_image1;',
'uniform bool u_splitImage;',
'uniform samplerCube u_imageCube;',
'varying vec2 v_texCoord;',
'uniform vec4 u_backgroundColor;',
'void main(){',
'float x=v_texCoord.x * u_aspectRatio;',
'float y=v_texCoord.y;',
'float sinrot=sin(u_rot);',
'float cosrot=cos(u_rot);',
'float rot_x=x * cosrot - y * sinrot;',
'float rot_y=x * sinrot + y * cosrot;',
'float sintheta=sin(u_theta);',
'float costheta=cos(u_theta);',
'float a=u_f * costheta - rot_y * sintheta;',
'float root=sqrt(rot_x * rot_x + a * a);',
'float lambda=atan(rot_x / root, a / root) + u_psi;',
'float phi=atan((rot_y * costheta + u_f * sintheta) / root);',
].join('\n');
var fragCube=fragEquiCubeBase + [
'float cosphi=cos(phi);',
'gl_FragColor=textureCube(u_imageCube, vec3(cosphi*sin(lambda), sin(phi), cosphi*cos(lambda)));',
'}'
].join('\n');
var fragEquirectangular=fragEquiCubeBase + [
'lambda=mod(lambda + PI, PI * 2.0) - PI;',
'vec2 coord=vec2(lambda / PI, phi / (PI / 2.0));',
'if(coord.x < -u_h||coord.x > u_h||coord.y < -u_v + u_vo||coord.y > u_v + u_vo)',
'gl_FragColor=u_backgroundColor;',
'else {',
'if(u_splitImage){',
'if(coord.x < 0.0)',
'gl_FragColor=texture2D(u_image0, vec2((coord.x + u_h) / u_h, (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
'else',
'gl_FragColor=texture2D(u_image1, vec2((coord.x + u_h) / u_h - 1.0, (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
'}else{',
'gl_FragColor=texture2D(u_image0, vec2((coord.x + u_h) / (u_h * 2.0), (-coord.y + u_v + u_vo) / (u_v * 2.0)));',
'}',
'}',
'}'
].join('\n');
var fragMulti=[
'varying mediump vec2 v_texCoord;',
'uniform sampler2D u_sampler;',
'void main(void){',
'gl_FragColor=texture2D(u_sampler, v_texCoord);',
'}'
].join('');
return {
renderer: function(container, image, imagetype, dynamic){
return new Renderer(container, image, imagetype, dynamic);
}};})(window, document);
;(function($, window, document, undefined){
function Owl(element, options){
this.settings=null;
this.options=$.extend({}, Owl.Defaults, options);
this.$element=$(element);
this._handlers={};
this._plugins={};
this._supress={};
this._current=null;
this._speed=null;
this._coordinates=[];
this._breakpoint=null;
this._width=null;
this._items=[];
this._clones=[];
this._mergers=[];
this._widths=[];
this._invalidated={};
this._pipe=[];
this._drag={
time: null,
target: null,
pointer: null,
stage: {
start: null,
current: null
},
direction: null
};
this._states={
current: {},
tags: {
'initializing': [ 'busy' ],
'animating': [ 'busy' ],
'dragging': [ 'interacting' ]
}};
$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler){
this._handlers[handler]=$.proxy(this[handler], this);
}, this));
$.each(Owl.Plugins, $.proxy(function(key, plugin){
this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
= new plugin(this);
}, this));
$.each(Owl.Workers, $.proxy(function(priority, worker){
this._pipe.push({
'filter': worker.filter,
'run': $.proxy(worker.run, this)
});
}, this));
this.setup();
this.initialize();
}
Owl.Defaults={
items: 3,
loop: false,
center: false,
rewind: false,
checkVisibility: true,
mouseDrag: true,
touchDrag: true,
pullDrag: true,
freeDrag: false,
margin: 0,
stagePadding: 0,
merge: false,
mergeFit: true,
autoWidth: false,
startPosition: 0,
rtl: false,
smartSpeed: 250,
fluidSpeed: false,
dragEndSpeed: false,
responsive: {},
responsiveRefreshRate: 200,
responsiveBaseElement: window,
fallbackEasing: 'swing',
slideTransition: '',
info: false,
nestedItemSelector: false,
itemElement: 'div',
stageElement: 'div',
refreshClass: 'owl-refresh',
loadedClass: 'owl-loaded',
loadingClass: 'owl-loading',
rtlClass: 'owl-rtl',
responsiveClass: 'owl-responsive',
dragClass: 'owl-drag',
itemClass: 'owl-item',
stageClass: 'owl-stage',
stageOuterClass: 'owl-stage-outer',
grabClass: 'owl-grab'
};
Owl.Width={
Default: 'default',
Inner: 'inner',
Outer: 'outer'
};
Owl.Type={
Event: 'event',
State: 'state'
};
Owl.Plugins={};
Owl.Workers=[ {
filter: [ 'width', 'settings' ],
run: function(){
this._width=this.$element.width();
}}, {
filter: [ 'width', 'items', 'settings' ],
run: function(cache){
cache.current=this._items&&this._items[this.relative(this._current)];
}}, {
filter: [ 'items', 'settings' ],
run: function(){
this.$stage.children('.cloned').remove();
}}, {
filter: [ 'width', 'items', 'settings' ],
run: function(cache){
var margin=this.settings.margin||'',
grid = !this.settings.autoWidth,
rtl=this.settings.rtl,
css={
'width': 'auto',
'margin-left': rtl ? margin:'',
'margin-right': rtl ? '':margin
};
!grid&&this.$stage.children().css(css);
cache.css=css;
}}, {
filter: [ 'width', 'items', 'settings' ],
run: function(cache){
var width=(this.width() / this.settings.items).toFixed(3) - this.settings.margin,
merge=null,
iterator=this._items.length,
grid = !this.settings.autoWidth,
widths=[];
cache.items={
merge: false,
width: width
};
while (iterator--){
merge=this._mergers[iterator];
merge=this.settings.mergeFit&&Math.min(merge, this.settings.items)||merge;
cache.items.merge=merge > 1||cache.items.merge;
widths[iterator] = !grid ? this._items[iterator].width():width * merge;
}
this._widths=widths;
}}, {
filter: [ 'items', 'settings' ],
run: function(){
var clones=[],
items=this._items,
settings=this.settings,
view=Math.max(settings.items * 2, 4),
size=Math.ceil(items.length / 2) * 2,
repeat=settings.loop&&items.length ? settings.rewind ? view:Math.max(view, size):0,
append='',
prepend='';
repeat /=2;
while (repeat > 0){
clones.push(this.normalize(clones.length / 2, true));
$(items[clones[clones.length - 1]][0]).clone(true).addClass('cloned').appendTo(this.$stage);
clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
$(items[clones[clones.length - 1]][0]).clone(true).addClass('cloned').prependTo(this.$stage);
repeat -=1;
}
this._clones=clones;
}}, {
filter: [ 'width', 'items', 'settings' ],
run: function(){
var rtl=this.settings.rtl ? 1:-1,
size=this._clones.length + this._items.length,
iterator=-1,
previous=0,
current=0,
coordinates=[];
while (++iterator < size){
previous=coordinates[iterator - 1]||0;
current=this._widths[this.relative(iterator)] + this.settings.margin;
coordinates.push(previous + current * rtl);
}
this._coordinates=coordinates;
}}, {
filter: [ 'width', 'items', 'settings' ],
run: function(){
var padding=this.settings.stagePadding,
coordinates=this._coordinates,
css={
'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
'padding-left': padding||'',
'padding-right': padding||''
};
this.$stage.css(css);
}}, {
filter: [ 'width', 'items', 'settings' ],
run: function(cache){
var iterator=this._coordinates.length,
grid = !this.settings.autoWidth,
items=this.$stage.children();
if(grid&&cache.items.merge){
while (iterator--){
cache.css.width=this._widths[this.relative(iterator)];
items.eq(iterator).css(cache.css);
}}else if(grid){
cache.css.width=cache.items.width;
items.css(cache.css);
}}
}, {
filter: [ 'items' ],
run: function(){
this._coordinates.length < 1&&this.$stage.removeAttr('style');
}}, {
filter: [ 'width', 'items', 'settings' ],
run: function(cache){
cache.current=cache.current ? this.$stage.children().index(cache.current):0;
cache.current=Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
this.reset(cache.current);
}}, {
filter: [ 'position' ],
run: function(){
this.animate(this.coordinates(this._current));
}}, {
filter: [ 'width', 'position', 'items', 'settings' ],
run: function(){
var rtl=this.settings.rtl ? 1:-1,
padding=this.settings.stagePadding * 2,
begin=this.coordinates(this.current()) + padding,
end=begin + this.width() * rtl,
inner, outer, matches=[], i, n;
for (i=0, n=this._coordinates.length; i < n; i++){
inner=this._coordinates[i - 1]||0;
outer=Math.abs(this._coordinates[i]) + padding * rtl;
if((this.op(inner, '<=', begin)&&(this.op(inner, '>', end)))
|| (this.op(outer, '<', begin)&&this.op(outer, '>', end))){
matches.push(i);
}}
this.$stage.children('.active').removeClass('active');
this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
this.$stage.children('.center').removeClass('center');
if(this.settings.center){
this.$stage.children().eq(this.current()).addClass('center');
}}
} ];
Owl.prototype.initializeStage=function(){
this.$stage=this.$element.find('.' + this.settings.stageClass);
if(this.$stage.length){
return;
}
this.$element.addClass(this.options.loadingClass);
this.$stage=$('<' + this.settings.stageElement + '>', {
"class": this.settings.stageClass
}).wrap($('<div/>', {
"class": this.settings.stageOuterClass
}));
this.$element.append(this.$stage.parent());
};
Owl.prototype.initializeItems=function(){
var $items=this.$element.find('.owl-item');
if($items.length){
this._items=$items.get().map(function(item){
return $(item);
});
this._mergers=this._items.map(function(){
return 1;
});
this.refresh();
return;
}
this.replace(this.$element.children().not(this.$stage.parent()));
if(this.isVisible()){
this.refresh();
}else{
this.invalidate('width');
}
this.$element
.removeClass(this.options.loadingClass)
.addClass(this.options.loadedClass);
};
Owl.prototype.initialize=function(){
this.enter('initializing');
this.trigger('initialize');
this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
if(this.settings.autoWidth&&!this.is('pre-loading')){
var imgs, nestedSelector, width;
imgs=this.$element.find('img');
nestedSelector=this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector:undefined;
width=this.$element.children(nestedSelector).width();
if(imgs.length&&width <=0){
this.preloadAutoWidthImages(imgs);
}}
this.initializeStage();
this.initializeItems();
this.registerEventHandlers();
this.leave('initializing');
this.trigger('initialized');
};
Owl.prototype.isVisible=function(){
return this.settings.checkVisibility
? this.$element.is(':visible')
: true;
};
Owl.prototype.setup=function(){
var viewport=this.viewport(),
overwrites=this.options.responsive,
match=-1,
settings=null;
if(!overwrites){
settings=$.extend({}, this.options);
}else{
$.each(overwrites, function(breakpoint){
if(breakpoint <=viewport&&breakpoint > match){
match=Number(breakpoint);
}});
settings=$.extend({}, this.options, overwrites[match]);
if(typeof settings.stagePadding==='function'){
settings.stagePadding=settings.stagePadding();
}
delete settings.responsive;
if(settings.responsiveClass){
this.$element.attr('class',
this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
);
}}
this.trigger('change', { property: { name: 'settings', value: settings }});
this._breakpoint=match;
this.settings=settings;
this.invalidate('settings');
this.trigger('changed', { property: { name: 'settings', value: this.settings }});
};
Owl.prototype.optionsLogic=function(){
if(this.settings.autoWidth){
this.settings.stagePadding=false;
this.settings.merge=false;
}};
Owl.prototype.prepare=function(item){
var event=this.trigger('prepare', { content: item });
if(!event.data){
event.data=$('<' + this.settings.itemElement + '/>')
.addClass(this.options.itemClass).append(item)
}
this.trigger('prepared', { content: event.data });
return event.data;
};
Owl.prototype.update=function(){
var i=0,
n=this._pipe.length,
filter=$.proxy(function(p){ return this[p] }, this._invalidated),
cache={};
while (i < n){
if(this._invalidated.all||$.grep(this._pipe[i].filter, filter).length > 0){
this._pipe[i].run(cache);
}
i++;
}
this._invalidated={};
!this.is('valid')&&this.enter('valid');
};
Owl.prototype.width=function(dimension){
dimension=dimension||Owl.Width.Default;
switch (dimension){
case Owl.Width.Inner:
case Owl.Width.Outer:
return this._width;
default:
return this._width - this.settings.stagePadding * 2 + this.settings.margin;
}};
Owl.prototype.refresh=function(resizing){
resizing=resizing||false;
this.enter('refreshing');
this.trigger('refresh');
this.setup();
this.optionsLogic();
this.$element.addClass(this.options.refreshClass);
this.update();
if(!resizing){
this.onResize();
}
this.$element.removeClass(this.options.refreshClass);
this.leave('refreshing');
this.trigger('refreshed');
};
Owl.prototype.onThrottledResize=function(){
window.clearTimeout(this.resizeTimer);
this.resizeTimer=window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
};
Owl.prototype.onResize=function(){
var resizing=true;
if(!this._items.length){
return false;
}
if(this._width===this.$element.width()){
return false;
}
if(!this.isVisible()){
return false;
}
this.enter('resizing');
if(this.trigger('resize').isDefaultPrevented()){
this.leave('resizing');
return false;
}
this.invalidate('width');
this.refresh(resizing);
this.leave('resizing');
this.trigger('resized');
};
Owl.prototype.registerEventHandlers=function(){
if($.support.transition){
this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
}
if(this.settings.responsive!==false){
this.on(window, 'resize', this._handlers.onThrottledResize);
}
if(this.settings.mouseDrag){
this.$element.addClass(this.options.dragClass);
this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
this.$stage.on('dragstart.owl.core selectstart.owl.core', function(){ return false });
}
if(this.settings.touchDrag){
this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
}};
Owl.prototype.onDragStart=function(event){
var stage=null;
if(event.which===3){
return;
}
if($.support.transform){
stage=this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
stage={
x: stage[stage.length===16 ? 12:4],
y: stage[stage.length===16 ? 13:5]
};}else{
stage=this.$stage.position();
stage={
x: this.settings.rtl ?
stage.left + this.$stage.width() - this.width() + this.settings.margin :
stage.left,
y: stage.top
};}
if(this.is('animating')){
$.support.transform ? this.animate(stage.x):this.$stage.stop()
this.invalidate('position');
}
this.$element.toggleClass(this.options.grabClass, event.type==='mousedown');
this.speed(0);
this._drag.time=new Date().getTime();
this._drag.target=$(event.target);
this._drag.stage.start=stage;
this._drag.stage.current=stage;
this._drag.pointer=this.pointer(event);
$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event){
var delta=this.difference(this._drag.pointer, this.pointer(event));
$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
if(Math.abs(delta.x) < Math.abs(delta.y)&&this.is('valid')){
return;
}
event.preventDefault();
this.enter('dragging');
this.trigger('drag');
}, this));
};
Owl.prototype.onDragMove=function(event){
var minimum=null,
maximum=null,
pull=null,
delta=this.difference(this._drag.pointer, this.pointer(event)),
stage=this.difference(this._drag.stage.start, delta);
if(!this.is('dragging')){
return;
}
event.preventDefault();
if(this.settings.loop){
minimum=this.coordinates(this.minimum());
maximum=this.coordinates(this.maximum() + 1) - minimum;
stage.x=(((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
}else{
minimum=this.settings.rtl ? this.coordinates(this.maximum()):this.coordinates(this.minimum());
maximum=this.settings.rtl ? this.coordinates(this.minimum()):this.coordinates(this.maximum());
pull=this.settings.pullDrag ? -1 * delta.x / 5:0;
stage.x=Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
}
this._drag.stage.current=stage;
this.animate(stage.x);
};
Owl.prototype.onDragEnd=function(event){
var delta=this.difference(this._drag.pointer, this.pointer(event)),
stage=this._drag.stage.current,
direction=delta.x > 0 ^ this.settings.rtl ? 'left':'right';
$(document).off('.owl.core');
this.$element.removeClass(this.options.grabClass);
if(delta.x!==0&&this.is('dragging')||!this.is('valid')){
this.speed(this.settings.dragEndSpeed||this.settings.smartSpeed);
this.current(this.closest(stage.x, delta.x!==0 ? direction:this._drag.direction));
this.invalidate('position');
this.update();
this._drag.direction=direction;
if(Math.abs(delta.x) > 3||new Date().getTime() - this._drag.time > 300){
this._drag.target.one('click.owl.core', function(){ return false; });
}}
if(!this.is('dragging')){
return;
}
this.leave('dragging');
this.trigger('dragged');
};
Owl.prototype.closest=function(coordinate, direction){
var position=-1,
pull=30,
width=this.width(),
count=this.settings.items,
itemWidth=Math.round(width / count),
coordinates=this.coordinates();
if(!this.settings.freeDrag){
$.each(coordinates, $.proxy(function(index, value){
if(direction==='left'&&coordinate > value - pull&&coordinate < value + pull){
position=index;
}else if(direction==='right'&&coordinate > value - itemWidth - pull&&coordinate < value - itemWidth + pull){
position=index + 1;
}else if(this.op(coordinate, '<', value)
&& this.op(coordinate, '>', coordinates[index + 1]!==undefined ? coordinates[index + 1]:value - width)){
position=direction==='left' ? index + 1:index;
}
return position===-1;
}, this));
}
if(!this.settings.loop){
if(this.op(coordinate, '>', coordinates[this.minimum()])){
position=coordinate=this.minimum();
}else if(this.op(coordinate, '<', coordinates[this.maximum()])){
position=coordinate=this.maximum();
}}
return position;
};
Owl.prototype.animate=function(coordinate){
var animate=this.speed() > 0;
this.is('animating')&&this.onTransitionEnd();
if(animate){
this.enter('animating');
this.trigger('translate');
}
if($.support.transform3d&&$.support.transition){
this.$stage.css({
transform: 'translate3d(' + coordinate + 'px,0px,0px)',
transition: (this.speed() / 1000) + 's' + (
this.settings.slideTransition ? ' ' + this.settings.slideTransition:''
)
});
}else if(animate){
this.$stage.animate({
left: coordinate + 'px'
}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
}else{
this.$stage.css({
left: coordinate + 'px'
});
}};
Owl.prototype.is=function(state){
return this._states.current[state]&&this._states.current[state] > 0;
};
Owl.prototype.current=function(position){
if(position===undefined){
return this._current;
}
if(this._items.length===0){
return undefined;
}
position=this.normalize(position);
if(this._current!==position){
var event=this.trigger('change', { property: { name: 'position', value: position }});
if(event.data!==undefined){
position=this.normalize(event.data);
}
this._current=position;
this.invalidate('position');
this.trigger('changed', { property: { name: 'position', value: this._current }});
}
return this._current;
};
Owl.prototype.invalidate=function(part){
if($.type(part)==='string'){
this._invalidated[part]=true;
this.is('valid')&&this.leave('valid');
}
return $.map(this._invalidated, function(v, i){ return i });
};
Owl.prototype.reset=function(position){
position=this.normalize(position);
if(position===undefined){
return;
}
this._speed=0;
this._current=position;
this.suppress([ 'translate', 'translated' ]);
this.animate(this.coordinates(position));
this.release([ 'translate', 'translated' ]);
};
Owl.prototype.normalize=function(position, relative){
var n=this._items.length,
m=relative ? 0:this._clones.length;
if(!this.isNumeric(position)||n < 1){
position=undefined;
}else if(position < 0||position >=n + m){
position=((position - m / 2) % n + n) % n + m / 2;
}
return position;
};
Owl.prototype.relative=function(position){
position -=this._clones.length / 2;
return this.normalize(position, true);
};
Owl.prototype.maximum=function(relative){
var settings=this.settings,
maximum=this._coordinates.length,
iterator,
reciprocalItemsWidth,
elementWidth;
if(settings.loop){
maximum=this._clones.length / 2 + this._items.length - 1;
}else if(settings.autoWidth||settings.merge){
iterator=this._items.length;
if(iterator){
reciprocalItemsWidth=this._items[--iterator].width();
elementWidth=this.$element.width();
while (iterator--){
reciprocalItemsWidth +=this._items[iterator].width() + this.settings.margin;
if(reciprocalItemsWidth > elementWidth){
break;
}}
}
maximum=iterator + 1;
}else if(settings.center){
maximum=this._items.length - 1;
}else{
maximum=this._items.length - settings.items;
}
if(relative){
maximum -=this._clones.length / 2;
}
return Math.max(maximum, 0);
};
Owl.prototype.minimum=function(relative){
return relative ? 0:this._clones.length / 2;
};
Owl.prototype.items=function(position){
if(position===undefined){
return this._items.slice();
}
position=this.normalize(position, true);
return this._items[position];
};
Owl.prototype.mergers=function(position){
if(position===undefined){
return this._mergers.slice();
}
position=this.normalize(position, true);
return this._mergers[position];
};
Owl.prototype.clones=function(position){
var odd=this._clones.length / 2,
even=odd + this._items.length,
map=function(index){ return index % 2===0 ? even + index / 2:odd - (index + 1) / 2 };
if(position===undefined){
return $.map(this._clones, function(v, i){ return map(i) });
}
return $.map(this._clones, function(v, i){ return v===position ? map(i):null });
};
Owl.prototype.speed=function(speed){
if(speed!==undefined){
this._speed=speed;
}
return this._speed;
};
Owl.prototype.coordinates=function(position){
var multiplier=1,
newPosition=position - 1,
coordinate;
if(position===undefined){
return $.map(this._coordinates, $.proxy(function(coordinate, index){
return this.coordinates(index);
}, this));
}
if(this.settings.center){
if(this.settings.rtl){
multiplier=-1;
newPosition=position + 1;
}
coordinate=this._coordinates[position];
coordinate +=(this.width() - coordinate + (this._coordinates[newPosition]||0)) / 2 * multiplier;
}else{
coordinate=this._coordinates[newPosition]||0;
}
coordinate=Math.ceil(coordinate);
return coordinate;
};
Owl.prototype.duration=function(from, to, factor){
if(factor===0){
return 0;
}
return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor||this.settings.smartSpeed));
};
Owl.prototype.to=function(position, speed){
var current=this.current(),
revert=null,
distance=position - this.relative(current),
direction=(distance > 0) - (distance < 0),
items=this._items.length,
minimum=this.minimum(),
maximum=this.maximum();
if(this.settings.loop){
if(!this.settings.rewind&&Math.abs(distance) > items / 2){
distance +=direction * -1 * items;
}
position=current + distance;
revert=((position - minimum) % items + items) % items + minimum;
if(revert!==position&&revert - distance <=maximum&&revert - distance > 0){
current=revert - distance;
position=revert;
this.reset(current);
}}else if(this.settings.rewind){
maximum +=1;
position=(position % maximum + maximum) % maximum;
}else{
position=Math.max(minimum, Math.min(maximum, position));
}
this.speed(this.duration(current, position, speed));
this.current(position);
if(this.isVisible()){
this.update();
}};
Owl.prototype.next=function(speed){
speed=speed||false;
this.to(this.relative(this.current()) + 1, speed);
};
Owl.prototype.prev=function(speed){
speed=speed||false;
this.to(this.relative(this.current()) - 1, speed);
};
Owl.prototype.onTransitionEnd=function(event){
if(event!==undefined){
event.stopPropagation();
if((event.target||event.srcElement||event.originalTarget)!==this.$stage.get(0)){
return false;
}}
this.leave('animating');
this.trigger('translated');
};
Owl.prototype.viewport=function(){
var width;
if(this.options.responsiveBaseElement!==window){
width=$(this.options.responsiveBaseElement).width();
}else if(window.innerWidth){
width=window.innerWidth;
}else if(document.documentElement&&document.documentElement.clientWidth){
width=document.documentElement.clientWidth;
}else{
console.warn('Can not detect viewport width.');
}
return width;
};
Owl.prototype.replace=function(content){
this.$stage.empty();
this._items=[];
if(content){
content=(content instanceof jQuery) ? content:$(content);
}
if(this.settings.nestedItemSelector){
content=content.find('.' + this.settings.nestedItemSelector);
}
content.filter(function(){
return this.nodeType===1;
}).each($.proxy(function(index, item){
item=this.prepare(item);
this.$stage.append(item);
this._items.push(item);
this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1||1);
}, this));
this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition:0);
this.invalidate('items');
};
Owl.prototype.add=function(content, position){
var current=this.relative(this._current);
position=position===undefined ? this._items.length:this.normalize(position, true);
content=content instanceof jQuery ? content:$(content);
this.trigger('add', { content: content, position: position });
content=this.prepare(content);
if(this._items.length===0||position===this._items.length){
this._items.length===0&&this.$stage.append(content);
this._items.length!==0&&this._items[position - 1].after(content);
this._items.push(content);
this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1||1);
}else{
this._items[position].before(content);
this._items.splice(position, 0, content);
this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1||1);
}
this._items[current]&&this.reset(this._items[current].index());
this.invalidate('items');
this.trigger('added', { content: content, position: position });
};
Owl.prototype.remove=function(position){
position=this.normalize(position, true);
if(position===undefined){
return;
}
this.trigger('remove', { content: this._items[position], position: position });
this._items[position].remove();
this._items.splice(position, 1);
this._mergers.splice(position, 1);
this.invalidate('items');
this.trigger('removed', { content: null, position: position });
};
Owl.prototype.preloadAutoWidthImages=function(images){
images.each($.proxy(function(i, element){
this.enter('pre-loading');
element=$(element);
$(new Image()).one('load', $.proxy(function(e){
element.attr('src', e.target.src);
element.css('opacity', 1);
this.leave('pre-loading');
!this.is('pre-loading')&&!this.is('initializing')&&this.refresh();
}, this)).attr('src', (window.devicePixelRatio > 1) ? element.attr('data-src-retina'):element.attr('data-src')||element.attr('src'));
}, this));
};
Owl.prototype.destroy=function(){
this.$element.off('.owl.core');
this.$stage.off('.owl.core');
$(document).off('.owl.core');
if(this.settings.responsive!==false){
window.clearTimeout(this.resizeTimer);
this.off(window, 'resize', this._handlers.onThrottledResize);
}
for (var i in this._plugins){
this._plugins[i].destroy();
}
this.$stage.children('.cloned').remove();
this.$stage.unwrap();
this.$stage.children().contents().unwrap();
this.$stage.children().unwrap();
this.$stage.remove();
this.$element
.removeClass(this.options.refreshClass)
.removeClass(this.options.loadingClass)
.removeClass(this.options.loadedClass)
.removeClass(this.options.rtlClass)
.removeClass(this.options.dragClass)
.removeClass(this.options.grabClass)
.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
.removeData('owl.carousel');
};
Owl.prototype.op=function(a, o, b){
var rtl=this.settings.rtl;
switch (o){
case '<':
return rtl ? a > b:a < b;
case '>':
return rtl ? a < b:a > b;
case '>=':
return rtl ? a <=b:a >=b;
case '<=':
return rtl ? a >=b:a <=b;
default:
break;
}};
Owl.prototype.on=function(element, event, listener, capture){
if(element.addEventListener){
element.addEventListener(event, listener, capture);
}else if(element.attachEvent){
element.attachEvent('on' + event, listener);
}};
Owl.prototype.off=function(element, event, listener, capture){
if(element.removeEventListener){
element.removeEventListener(event, listener, capture);
}else if(element.detachEvent){
element.detachEvent('on' + event, listener);
}};
Owl.prototype.trigger=function(name, data, namespace, state, enter){
var status={
item: { count: this._items.length, index: this.current() }}, handler=$.camelCase($.grep([ 'on', name, namespace ], function(v){ return v })
.join('-').toLowerCase()
), event=$.Event([ name, 'owl', namespace||'carousel' ].join('.').toLowerCase(),
$.extend({ relatedTarget: this }, status, data)
);
if(!this._supress[name]){
$.each(this._plugins, function(name, plugin){
if(plugin.onTrigger){
plugin.onTrigger(event);
}});
this.register({ type: Owl.Type.Event, name: name });
this.$element.trigger(event);
if(this.settings&&typeof this.settings[handler]==='function'){
this.settings[handler].call(this, event);
}}
return event;
};
Owl.prototype.enter=function(name){
$.each([ name ].concat(this._states.tags[name]||[]), $.proxy(function(i, name){
if(this._states.current[name]===undefined){
this._states.current[name]=0;
}
this._states.current[name]++;
}, this));
};
Owl.prototype.leave=function(name){
$.each([ name ].concat(this._states.tags[name]||[]), $.proxy(function(i, name){
this._states.current[name]--;
}, this));
};
Owl.prototype.register=function(object){
if(object.type===Owl.Type.Event){
if(!$.event.special[object.name]){
$.event.special[object.name]={};}
if(!$.event.special[object.name].owl){
var _default=$.event.special[object.name]._default;
$.event.special[object.name]._default=function(e){
if(_default&&_default.apply&&(!e.namespace||e.namespace.indexOf('owl')===-1)){
return _default.apply(this, arguments);
}
return e.namespace&&e.namespace.indexOf('owl') > -1;
};
$.event.special[object.name].owl=true;
}}else if(object.type===Owl.Type.State){
if(!this._states.tags[object.name]){
this._states.tags[object.name]=object.tags;
}else{
this._states.tags[object.name]=this._states.tags[object.name].concat(object.tags);
}
this._states.tags[object.name]=$.grep(this._states.tags[object.name], $.proxy(function(tag, i){
return $.inArray(tag, this._states.tags[object.name])===i;
}, this));
}};
Owl.prototype.suppress=function(events){
$.each(events, $.proxy(function(index, event){
this._supress[event]=true;
}, this));
};
Owl.prototype.release=function(events){
$.each(events, $.proxy(function(index, event){
delete this._supress[event];
}, this));
};
Owl.prototype.pointer=function(event){
var result={ x: null, y: null };
event=event.originalEvent||event||window.event;
event=event.touches&&event.touches.length ?
event.touches[0]:event.changedTouches&&event.changedTouches.length ?
event.changedTouches[0]:event;
if(event.pageX){
result.x=event.pageX;
result.y=event.pageY;
}else{
result.x=event.clientX;
result.y=event.clientY;
}
return result;
};
Owl.prototype.isNumeric=function(number){
return !isNaN(parseFloat(number));
};
Owl.prototype.difference=function(first, second){
return {
x: first.x - second.x,
y: first.y - second.y
};};
$.fn.owlCarousel=function(option){
var args=Array.prototype.slice.call(arguments, 1);
return this.each(function(){
var $this=$(this),
data=$this.data('owl.carousel');
if(!data){
data=new Owl(this, typeof option=='object'&&option);
$this.data('owl.carousel', data);
$.each([
'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
], function(i, event){
data.register({ type: Owl.Type.Event, name: event });
data.$element.on(event + '.owl.carousel.core', $.proxy(function(e){
if(e.namespace&&e.relatedTarget!==this){
this.suppress([ event ]);
data[event].apply(this, [].slice.call(arguments, 1));
this.release([ event ]);
}}, data));
});
}
if(typeof option=='string'&&option.charAt(0)!=='_'){
data[option].apply(data, args);
}});
};
$.fn.owlCarousel.Constructor=Owl;
})(window.Zepto||window.jQuery, window, document);
(function (factory){
if(typeof define==='function'&&define.amd){
define(['jquery'], factory);
}else if(typeof exports==='object'){
factory(require('jquery'));
}else{
factory(jQuery);
}}(function ($){
var pluses=/\+/g;
function encode(s){
return config.raw ? s:encodeURIComponent(s);
}
function decode(s){
return config.raw ? s:decodeURIComponent(s);
}
function stringifyCookieValue(value){
return encode(config.json ? JSON.stringify(value):String(value));
}
function parseCookieValue(s){
if(s.indexOf('"')===0){
s=s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
s=decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s):s;
} catch(e){}}
function read(s, converter){
var value=config.raw ? s:parseCookieValue(s);
return $.isFunction(converter) ? converter(value):value;
}
var config=$.cookie=function (key, value, options){
if(value!==undefined&&!$.isFunction(value)){
options=$.extend({}, config.defaults, options);
if(typeof options.expires==='number'){
var days=options.expires, t=options.expires=new Date();
t.setTime(+t + days * 864e+5);
}
return (document.cookie=[
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString():'',
options.path    ? '; path=' + options.path:'',
options.domain  ? '; domain=' + options.domain:'',
options.secure  ? '; secure':''
].join(''));
}
var result=key ? undefined:{};
var cookies=document.cookie ? document.cookie.split('; '):[];
for (var i=0, l=cookies.length; i < l; i++){
var parts=cookies[i].split('=');
var name=decode(parts.shift());
var cookie=parts.join('=');
if(key&&key===name){
result=read(cookie, value);
break;
}
if(!key&&(cookie=read(cookie))!==undefined){
result[name]=cookie;
}}
return result;
};
config.defaults={};
$.removeCookie=function (key, options){
if($.cookie(key)===undefined){
return false;
}
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
};}));
(function($){
'use strict';
/**
* All of the code for your public-facing JavaScript source
* should reside in this file.
*
* Note: It has been assumed you will write jQuery code here, so the
* $ function reference has been prepared for usage within the scope
* of this function.
*
* This enables you to define handlers, for when the DOM is ready:
*
* $(function(){
*
* });
*
* When the window is loaded:
*
* $(window).load(function(){
*
* });
*
* ...and/or other possibilities.
*
* Ideally, it is not considered best practise to attach more than a
* single DOM-ready or window-load handler for a particular page.
* Although scripts in the WordPress core, Plugins and Themes may be
* practising this, we should strive to set a better example in our own work.
*/
})(jQuery);
function wpvrhotspot(hotSpotDiv, hotspotData){
const args=hotspotData.on_click_content;
if(args){
const hasTextContent=args.replace(/<[^>]*>/g, '').trim()!=='';
const hasMediaContent=/<(img|video|audio|iframe|embed|object)\b[^>]*>/i.test(args);
const hasOtherContent=args.replace(/<(p|br|div|span)\b[^>]*\/?>/gi, '').trim()!=='';
if(hasTextContent||hasMediaContent||hasOtherContent){
const cleanArgs=args.replace(/\\/g, '');
const $wrapper=jQuery(hotSpotDiv.target).parent().siblings(".custom-ifram-wrapper");
$wrapper.find('.custom-ifram').html(cleanArgs);
$wrapper.fadeIn();
jQuery(hotSpotDiv.target).closest(".pano-wrap").addClass("show-modal");
}}
}
function wpvrtooltip(hotSpotDiv, args){
if(args){
const hasTextContent=args.replace(/<[^>]*>/g, '').trim()!=='';
const hasMediaContent=/<(img|video|audio|iframe|embed|object)\b[^>]*>/i.test(args);
const hasOtherContent=args.replace(/<(p|br|div|span)\b[^>]*\/?>/gi, '').trim()!=='';
if(hasTextContent||hasMediaContent||hasOtherContent){
const cleanArgs=args.replace(/\\/g, '');
hotSpotDiv.classList.add('custom-tooltip');
const p=document.createElement('p');
p.innerHTML=cleanArgs;
hotSpotDiv.appendChild(p);
p.style.marginLeft=-(p.scrollWidth - hotSpotDiv.offsetWidth) / 2 + 'px';
p.style.marginTop=-p.scrollHeight - 12 + 'px';
if(!document.getElementById('wpvr-tooltip-style')){
const style=document.createElement('style');
style.id='wpvr-tooltip-style';
style.textContent=`
.table, .table td, .table th {
border: 1px solid #dee2e6;
border-collapse: collapse;
padding: 8px;
}
`;
document.head.appendChild(style);
}}
}}
jQuery(document).ready(function($){
$(".cross").on("click", function(e){
e.preventDefault();
$(this).parent(".custom-ifram-wrapper").fadeOut();
$(this).parents(".pano-wrap").removeClass("show-modal");
$('.vr-iframe').attr('src', '');
if($('#wpvr-video').length!=0){
$('#wpvr-video').get(0).pause();
}
$(this).parent(".custom-ifram-wrapper").find('.custom-ifram').empty();
});
});
jQuery(document).ready(function($){
var notice_active=wpvr_public.notice_active;
var notice=wpvr_public.notice;
if(notice_active=="true"){
if(!$.cookie("wpvr_mobile_notice")){
if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){
if($(".pano-wrap")[0]){
$('body').append("<div class='wpvr-mobile-notice'><p>" + notice + "</p> <span class='notice-close'><i class='fa fa-times'></i></span></div>");
}}
}}
$('.wpvr-mobile-notice .notice-close').on('click', function(){
$('.wpvr-mobile-notice').fadeOut();
$.cookie('wpvr_mobile_notice', 'true');
});
});
jQuery(document).ready(function($){
var isTouchDevice=("ontouchstart" in window)||(navigator.maxTouchPoints > 0);
var disOnHover=(typeof wpvr_public!=='undefined') ? wpvr_public.dis_on_hover:undefined;
var tipEnabled=(typeof wpvr_public!=='undefined') ? wpvr_public.mobile_hotspot_tip:undefined;
var shouldShowAlert=isTouchDevice&&(disOnHover!=="1");
if(shouldShowAlert){
setTimeout(function(){
if(!$('.pnlm-container').length){
return;
}
$('.pnlm-hotspot-base, .pnlm-hotspot').each(function(){
$(this).off('mouseenter mouseover mouseleave');
$(this).find('p').hide();
var longPressTimer;
var isLongPress=false;
$(this).off('click._wpvrHotspotFix').on('click._wpvrHotspotFix', function(e){
if($(this).data('wpvr-longpress')){
e.preventDefault();
e.stopImmediatePropagation();
$(this).data('wpvr-longpress', false);
return false;
}});
$(this).on('touchstart', function(e){
isLongPress=false;
var $hotspot=$(this);
$hotspot.find('p').hide();
longPressTimer=setTimeout(function(){
isLongPress=true;
$hotspot.data('wpvr-longpress', true);
$('.pnlm-hotspot-base p, .pnlm-hotspot p').hide();
$hotspot.find('p').show();
}, 600);
});
$(this).on('touchend', function(e){
clearTimeout(longPressTimer);
if(isLongPress){
e.preventDefault();
e.stopPropagation();
}else{
$(this).find('p').hide();
}});
$(this).on('touchmove', function(){
clearTimeout(longPressTimer);
isLongPress=false;
$(this).find('p').hide();
});
});
$(document).on('touchstart.wpvrHotspotOutside', function(e){
if(!$(e.target).closest('.pnlm-hotspot-base, .pnlm-hotspot').length){
$('.pnlm-hotspot-base p, .pnlm-hotspot p').hide();
}});
$('.pnlm-hotspot-base, .pnlm-hotspot').on('touchstart', function(e){
var $current=$(this);
$('.pnlm-hotspot-base, .pnlm-hotspot').not($current).find('p').hide();
});
if(tipEnabled=='1'){
function showHotspotTip(){
if(window.sessionStorage&&sessionStorage.getItem('wpvrHotspotTipShown')) return;
if(window.sessionStorage){
sessionStorage.setItem('wpvrHotspotTipShown', '1');
}
alert('Tip: On mobile devices, long-press a hotspot to show its hover content.');
}
$('.pnlm-container').on('touchstart.wpvrTip touchmove.wpvrTip', showHotspotTip);
$('.pnlm-hotspot-base, .pnlm-hotspot').on('touchstart.wpvrTip', showHotspotTip);
}}, 800);
}});