1// wppa-flatpan.js 2// 3// contains wppa functions for flat panorama images 4// 5var wppaJsFlatPanVersion = '9.0.08.002'; 6 7 // The main proccedure 8 function wppaDoFlatPanorama(mocc, xdata) { 9 10 // Store the data 11 wppaFlatpanData[mocc] = xdata; 12 13 // Update data with image 14 var data = update(mocc,{image:document.getElementById( "wppa-"+xdata.itemId )}); 15 16 // Find additional data 17 data.ratio = data.slide ? ( 1 / wppaAspectRatio[mocc] ) : 2; 18 data.manualControl = false; 19 data.deltaY = 0; 20 data.deltaFactor = 1.0; 21 data.run = data.deltaX ? 5 : 4; 22 data.abort = false; 23 data.div = jQuery("#wppa-pan-div-"+mocc); 24 data.canvas = document.getElementById("wppa-pan-canvas-"+mocc); 25 data.prevCanvas = document.getElementById("wppa-pan-prev-canvas-"+mocc); 26 data.pctldiv = jQuery("#wppa-pctl-div-"+mocc); 27 data.left = jQuery("#wppa-pctl-left-"+mocc); 28 data.right = jQuery("#wppa-pctl-right-"+mocc); 29 data.up = jQuery("#wppa-pctl-up-"+mocc); 30 data.down = jQuery("#wppa-pctl-down-"+mocc); 31 data.zoomin = jQuery("#wppa-pctl-zoomin-"+mocc); 32 data.zoomout = jQuery("#wppa-pctl-zoomout-"+mocc); 33 data.prev = jQuery("#wppa-pctl-prev-"+mocc); 34 data.next = jQuery("#wppa-pctl-next-"+mocc); 35 data.canvasWidth = jQuery(data.div).parent().width(); 36 data.canvasHeight = data.canvasWidth / data.ratio; 37 data.savedCanvasX = 0; 38 data.savedCanvasY = 0; 39 data.fromHeight = data.image.height / data.ratio; 40 data.fromWidth = data.fromHeight * data.ratio; 41 data.fromX = ( data.image.width - data.fromWidth ) / data.ratio; 42 data.fromY = ( data.image.height - data.fromHeight ) / data.ratio; 43 data.centerX = data.fromX + data.fromWidth / data.ratio; 44 data.centerY = data.fromY + data.fromHeight / data.ratio; 45 data.wppaFlatLastRenderTime = 0; 46 47 // Install listeners 48 data.right.on("touchstart", function(e){rightDown(mocc, e)}); 49 data.right.on("touchend", function(e){buttonUp(mocc, e)}); 50 data.left.on("touchstart", function(e){leftDown(mocc, e)}); 51 data.left.on("touchend", function(e){buttonUp(mocc, e)}); 52 data.up.on("touchstart", function(e){upDown(mocc, e)}); 53 data.up.on("touchend", function(e){buttonUp(mocc, e)}); 54 data.down.on("touchstart", function(e){downDown(mocc, e)}); 55 data.down.on("touchend", function(e){buttonUp(mocc, e)}); 56 data.zoomin.on("touchstart", function(e){zoomInDown(mocc, e)}); 57 data.zoomin.on("touchend", function(e){buttonUp(mocc, e)}); 58 data.zoomout.on("touchstart", function(e){zoomOutDown(mocc, e)}); 59 data.zoomout.on("touchend", function(e){buttonUp(mocc, e)}); 60 61 if ( data.manual ) { 62 data.canvas.addEventListener("mousedown", function(e){onCanvasMouseDown(mocc, e)}); 63 data.canvas.addEventListener("mousemove", function(e){onCanvasMouseMove(mocc, e)}); 64 data.canvas.addEventListener("mouseup", function(e){onCanvasMouseUp(mocc, e)}); 65 data.canvas.addEventListener("mouseout", function(e){onCanvasMouseUp(mocc, e)}); 66 document.getElementById("wppa-pan-canvas-"+mocc).addEventListener("wheel", function(e){onDivWheel(mocc, e)}); 67 if ( data.prevCanvas ) { 68 data.prevCanvas.addEventListener("mousedown", function(e){onCanvasMouseDown(mocc, e)}); 69 data.prevCanvas.addEventListener("mousemove", function(e){onPrevCanvasMouseMove(mocc, e)}); 70 data.prevCanvas.addEventListener("mouseup", function(e){onCanvasMouseUp(mocc, e)}); 71 data.prevCanvas.addEventListener("mouseout", function(e){onCanvasMouseUp(mocc, e)}); 72 } 73 } 74 75 data.right.on("mousedown", function(e){rightDown(mocc, e)}); 76 data.right.on("mouseup", function(e){buttonUp(mocc, e)}); 77 data.left.on("mousedown", function(e){leftDown(mocc, e)}); 78 data.left.on("mouseup", function(e){buttonUp(mocc, e)}); 79 data.up.on("mousedown", function(e){upDown(mocc, e)}); 80 data.up.on("mouseup", function(e){buttonUp(mocc, e)}); 81 data.down.on("mousedown", function(e){downDown(mocc, e)}); 82 data.down.on("mouseup", function(e){buttonUp(mocc, e)}); 83 data.zoomin.on("mousedown", function(e){zoomInDown(mocc, e)}); 84 data.zoomin.on("mouseup", function(e){buttonUp(mocc, e)}); 85 data.zoomout.on("mousedown", function(e){zoomOutDown(mocc, e)}); 86 data.zoomout.on("mouseup", function(e){buttonUp(mocc, e)}); 87 88 // Common event handlers 89 jQuery("body").on("quitimage", function(e,arg){ 90 if ( typeof(arg) == 'undefined' || arg == mocc ) quitImage(mocc,e); 91 }); 92 93 if ( data.isLightbox ) { 94 jQuery("#wppa-pctl-div-"+data.itemId).on("click", function(e){wppaKillEvent(e)}); 95 } 96 97 // Install Resize handler 98 if ( data.isLightbox ) { 99 jQuery(window).off("resize",wppaOvlShowSame); 100 jQuery(window).on("resize",wppaOvlShowSame); 101 } 102 else { 103 jQuery(window).on("resize",function(e){resize(mocc,e)}); 104 } 105 106 // Store data 107 update(mocc,data); 108 109 // Resize 110 resize(mocc); 111 112 // Remove spinner 113 jQuery("#wppa-ovl-spin").hide(); 114 115 // Optionally disable rightclick 116 wppaProtect(); 117 118 // The render function 119 function render(mocc) { 120 121 var data = update(mocc); 122 123 if ( ! data.canvas ) { 124 return; 125 } 126 127 if ( data.isLightbox ) { 128 if (!wppaOvlOpen) { 129 data.abort=true; 130 } 131 } 132 else { 133 if (!wppaIsElementInViewport(data.canvas)) { 134 135 setTimeout(function(){render(mocc)},200); 136 return; 137 } 138 } 139 140 if ( data.abort ) { 141 update(mocc,{ 142 ctx :null, 143 prevctx :null 144 }); 145 return; 146 } 147 148 if (data.run==0) { 149 return; 150 } 151 152 // Duplicate loops? 153 var curTime = timnow(); 154 if ( data.autorun && curTime < data.wppaFlatLastRenderTime + 25 ) { 155 return; 156 } 157 data.wppaFlatLastRenderTime = curTime; 158 159 // manualControl is true when a drag on the canvas is being performed 160 if(!data.manualControl){ 161 162 // Panning 163 data.fromX += data.deltaX; 164 data.fromY += data.deltaY; 165 166 // Zooming 167 var newHeight = data.fromHeight / data.deltaFactor; 168 var newWidth = data.fromWidth / data.deltaFactor; 169 170 // Keep zooming in range 171 if ( data.deltaFactor != 1 && newHeight <= data.image.height && newHeight > 50 ) { 172 data.fromX -= ( newWidth - data.fromWidth ) / data.ratio; 173 data.fromY -= ( newHeight - data.fromHeight ) / data.ratio; 174 data.fromWidth = newWidth; 175 data.fromHeight = newHeight; 176 } 177 } 178 179 // Keep viewport within image boundaries 180 data.fromX = Math.max(0, Math.min(data.image.width - data.fromWidth, data.fromX)); 181 data.fromY = Math.max(0, Math.min(data.image.height - data.fromHeight, data.fromY)); 182 183 // Check for turningpoint in case autrun 184 if ( data.autorun ) { 185 if ( data.fromX == 0 || data.fromX == ( data.image.width - data.fromWidth ) ) { 186 data.deltaX *= -1; 187 } 188 } 189 190 // Draw the image 191 var ctx = data.canvas.getContext("2d"); 192 ctx.drawImage(data.image, data.fromX, data.fromY, data.fromWidth, data.fromHeight, 0, 0, data.canvas.width, data.canvas.height); 193 194 // Display the image 195 jQuery( data.canvas ).css({display:'inline'}); 196 197 // Draw the preview image 198 if ( data.prevCanvas ) { 199 var prevctx = data.prevCanvas.getContext("2d"); 200 prevctx.clearRect(0, 0, data.prevCanvas.width, data.prevCanvas.height); 201 prevctx.drawImage(data.image, 0, 0, data.image.width, data.image.height, 0, 0, data.prevCanvas.width, data.prevCanvas.height); 202 203 // Display the preview image 204 jQuery( data.prevCanvas ).css({display:'inline'}); 205 206 // Draw viewport rect on preview image 207 var factor = data.prevCanvas.width / data.image.width; 208 prevctx.strokeRect(factor * data.fromX, factor * data.fromY, factor * data.fromWidth, factor * data.fromHeight); 209 } 210 211 // Re-render if needed 212 if (data.run>0) { 213 timer = setTimeout(function(){render(mocc)},25); 214 } 215 if (data.run<5)data.run--; 216 217 // Make controlbar visible 218 wppaHasControlbar = true; 219 wppaAdjustControlbar(mocc);
220// setTimeout(function(){jQuery("#wppa-pctl-div-"+mocc).css({visibility:"visible"});}, 100); 221 222 update(mocc,data); 223 } 224 225 // When a (responsive) resize is required, we resize the wppaScene 226 function resize(mocc) { 227 228 var data = update(mocc); 229 230 if (data.abort) return; 231 232 // console.log('resizing flatpan '+mocc); 233 234 if ( data.isLightbox) { 235 236 // Show image container 237 jQuery("#wppa-overlay-fpc").css("display", ""); 238 239 // There are 4 possiblilities: all combi of 'Width is the limit or not' and 'Mode is normal or fullscreen' 240 var widthIsLim, 241 modeIsNormal = ! wppaIsFs(); 242 243 // First find container dimensions dependant of mode 244 var contWidth, contHeight; 245 246 if ( modeIsNormal ) { 247 contWidth = window.innerWidth ? window.innerWidth : screen.width; 248 contHeight = window.innerHeight ? window.innerHeight : screen.height; 249 } 250 else { 251 contWidth = screen.width; 252 contHeight = screen.height; 253 } 254 // newWidth = parseInt(newWidth); 255 // newHeight = parseInt(newHeight); 256 257 // Initialize new display sizes 258 var topMarg, 259 leftMarg, 260 extraX = 8, 261 extraY = 24 + ( data.controls ? data.icsize : 0 ) + contWidth * data.height / data.width + 40; 262 263 // Add borderwidth in case of mode == normal 264 if ( modeIsNormal ) { 265 extraX += 2 * data.padding; 266 extraY += 2 * data.padding; 267 } 268 269 // Find out if the width is the limitng dimension 270 widthIsLim = ( contHeight > ( ( contWidth / data.ratio ) + extraY ) ); 271 272 // Compute new sizes and margins 273 if ( widthIsLim ) { 274 newWidth = contWidth - extraX; 275 newHeight = newWidth / data.ratio; 276 topMarg = ( contHeight - newHeight - extraY ) / 2 + 20; 277 } 278 else { 279 newWidth = data.ratio * ( contHeight - ( data.controls ? data.icsize : 0 ) - 24 - 40 ) / ( 1 + 2 * data.height / data.width ); 280 newHeight = newWidth / data.ratio; 281 topMarg = 20; 282 } 283 284 // Set css common for all 4 situations 285 jQuery("#wppa-ovl-flatpan-container").css({top:topMarg,marginTop:0}); 286 287 data.canvas.width = newWidth; 288 data.canvas.height = newHeight; 289 if ( data.prevCanvas ) { 290 data.prevCanvas.width = newWidth; 291 data.prevCanvas.height = newWidth * data.height / data.width; 292 } 293 294 // Now set css for all 4 situations: Mode is normal 295 if ( modeIsNormal ) { 296 297 // Common for mode normal 298 jQuery("#wppa-ovl-flatpan-container").css({ 299 backgroundColor:data.backgroundColor, 300 padding:data.padding, 301 borderRadius:data.borderRadius, 302 width:newWidth, 303 marginLeft:0 304 }); 305 306 // Limit specific 307 if ( widthIsLim ) { 308 jQuery("#wppa-overlay-fpc").css({left:4});
309 } 310 else { 311 jQuery("#wppa-overlay-fpc").css({left:(contWidth-newWidth)/2}); 312 } 313 wppaAdjustControlbar(mocc); 314 } 315 316 // Mode is fullscreen 317 else { 318 319 // Common for mode fullscreen 320 jQuery("#wppa-overlay-fpc").css({marginLeft:0}); 321 jQuery("#wppa-ovl-flatpan-container").css({ 322 backgroundColor:"transparent", 323 padding:0, 324 borderRadius:0, 325 width:newWidth, 326 left:(contWidth-newWidth)/2 327 }); 328 wppaAdjustControlbar(mocc); 329 } 330 331 data.run=(data.autorun?5:4); 332 } 333 334 // Not lightbox 335 else { 336 if ( data.slide ) { 337 var cw = wppaGetContainerWidth(mocc); 338 var pch = data.pancontrolheight; 339 if ( pch > 0 ) pch += 5; 340 var frameRatio = wppaAspectRatio[mocc]; // aspect ratio of slideframe h / w 341 342 data.canvasWidth = cw; 343 data.canvasHeight = cw * frameRatio - pch; 344 jQuery(data.pctldiv).css({width:cw}); 345 jQuery('#slide_frame-'+mocc).css({height:(data.canvasHeight+pch)}); 346 } 347 else { 348 data.canvasWidth = jQuery(data.div).parent().width(); 349 data.canvasHeight = data.canvasWidth / data.ratio; 350 } 351 352 data.canvas.width = data.canvasWidth; 353 data.canvas.height = data.canvasHeight; 354 if ( data.prevCanvas ) { 355 data.prevCanvas.width = data.canvasWidth; 356 data.prevCanvas.height = data.canvasWidth * data.height / data.width; 357 } 358 data.run=(data.autorun?5:4); 359 } 360 361 update(mocc,data); 362 render(mocc); 363 } 364 365 // Horizontal movement by button 366 function rightDown(mocc,e) { 367 368 update(mocc, { 369 autorun :false, 370 run :5, 371 deltaX :3, 372 deltaY :0 373 }); 374 render(mocc); 375 } 376 377 function leftDown(mocc,e) { 378 379 update(mocc, { 380 autorun :false, 381 run :5, 382 deltaX :-3, 383 deltaY :0 384 }); 385 render(mocc); 386 } 387 388 // Vertical movement by button 389 function upDown(mocc,e) { 390 391 update(mocc, { 392 autorun :false, 393 run :5, 394 deltaX :0, 395 deltaY :-3 396 }); 397 render(mocc); 398 } 399 400 function downDown(mocc,e) { 401 402 update(mocc, { 403 autorun :false, 404 run :5, 405 deltaX :0, 406 deltaY :3 407 }); 408 render(mocc); 409 } 410 411 // Zooming 412 function zoomInDown(mocc,e) { 413 414 update(mocc, { 415 deltaX :0, 416 deltaY :0, 417 autorun :false, 418 run :5, 419 deltaFactor :1.005 420 }); 421 render(mocc); 422 } 423 424 function zoomOutDown(mocc,e) { 425 426 update(mocc, { 427 deltaX :0, 428 deltaY :0, 429 autorun :false, 430 run :5, 431 deltaFactor :0.995 432 }); 433 render(mocc); 434 } 435 436 // Mouse wheel 437 function onDivWheel(mocc,e) { 438 439 e.preventDefault(); 440 e.stopPropagation(); 441 442 var data = update(mocc); 443 444 update(mocc, { 445 deltaX :0, 446 deltaY :0, 447 autorun :false, 448 run :4, 449 deltaFactor :1 + e.deltaY * data.zoomsensitivity / 10000 450 }); 451 render(mocc); 452 453 setTimeout(function(){update(mocc, {deltaFactor:1});}, 25); 454 } 455 456 // When a navigation button is released, stop and reset all deltas 457 function buttonUp(mocc,e) { 458 459 e.preventDefault(); 460 update(mocc, { 461 autorun :false, 462 deltaX :0, 463 deltaY :0, 464 deltaFactor :1, 465 run :4 466 }); 467 } 468 469 // when the mouse is pressed on the canvas, we switch to manual control and save current coordinates 470 function onCanvasMouseDown(mocc,e) { 471 472 e.preventDefault(); 473 474 update(mocc, { 475 manualControl :true, 476 autorun :false, 477 deltaX :0, 478 savedCanvasX :e.offsetX, 479 savedCanvasY :e.offsetY, 480 run :5 481 }); 482 render(mocc); 483 } 484 485 function onCanvasMouseMove(mocc,e) { 486 487 var data = update(mocc); 488 489 if ( data.manualControl ) { 490 update(mocc, { 491 autorun :false, 492 deltaX :0 493 }); 494 495 var factor = data.canvas.width / data.fromWidth; 496 var x = ( data.savedCanvasX - e.offsetX ) / factor + data.fromX; 497 var y = ( data.savedCanvasY - e.offsetY ) / factor + data.fromY; 498 499 if ( x > 0 && y > 0 && ( x + data.fromWidth ) < data.image.width && ( y + data.fromHeight ) < data.image.height ) { 500 update(mocc, { 501 fromX :x, 502 fromY :y, 503 savedCanvasX :e.offsetX, 504 savedCanvasY :e.offsetY 505 }); 506 } 507 } 508 } 509 510 function onPrevCanvasMouseMove(mocc,e) { 511 512 var data = update(mocc); 513 514 var factor = data.prevCanvas.width / data.image.width; 515 516 if (e.offsetX > factor * data.fromX && 517 e.offsetX < factor * ( data.fromX + data.fromWidth ) && 518 e.offsetY > factor * data.fromY && 519 e.offsetY < factor * ( data.fromY + data.fromHeight ) ) { 520 jQuery(data.prevCanvas).css("cursor","grab"); 521 } 522 else { 523 jQuery(data.prevCanvas).css("cursor","default"); 524 } 525 526 if ( data.manualControl ){ 527 data.autorun=false; 528 data.deltaX=0; 529 if (e.offsetX > factor * data.fromX && 530 e.offsetX < factor * ( data.fromX + data.fromWidth ) && 531 e.offsetY > factor * data.fromY && 532 e.offsetY < factor * ( data.fromY + data.fromHeight ) ) { 533 data.fromX = ( e.offsetX - data.savedCanvasX ) / factor + data.fromX; 534 data.fromY = ( e.offsetY - data.savedCanvasY ) / factor + data.fromY; 535 data.savedCanvasX = e.offsetX; 536 data.savedCanvasY = e.offsetY; 537 } 538 } 539 update(mocc,data); 540 } 541 542 function onCanvasMouseUp(mocc,e) { 543 544 var data = update(mocc); 545 546 if ( data.manualControl ) { 547 update(mocc, { 548 run: 4, 549 manualControl: false 550 }); 551 } 552 } 553
554 // Update data 555 function update(mocc, data) { 556 557 if ( ! wppaFlatpanData[mocc] ) return false; 558 559 if (data) { 560 for (var property in data) { 561 wppaFlatpanData[mocc][property] = data[property]; 562 } 563 } 564 565 return wppaFlatpanData[mocc]; 566 } 567 568 function timnow() { 569 d = new Date(); 570 return d.getTime(); 571 } 572 573 // Clean up 574 function quitImage(mocc,e) { 575 576 // console.log('Quit flatpan '+mocc); 577 578 // Kill timer 579 clearTimeout(data.timer); 580 581 // Clear data 582 wppaFlatpanData[mocc] = []; 583 584 // Make sure procs do not run 585 data = update(mocc, { 586 abort :true, 587 run :0, 588 autorun :false 589 }); 590 591 // Clear html 592 jQuery(data.canvas).html(''); 593 jQuery(data.prevCanvas).html(''); 594 jQuery("#wppa-pctl-div-"+mocc).html(''); 595 } 596}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.