1var popupviewer = function(showContent, isImage, width, height) { 2 3 if ( jQuery ) { 4 var $ = jQuery; 5 } 6 7 this.screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; 8 this.screenHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; 9 this.contentDiv = null; 10 this.controlDiv = null; 11 this.maxWidthFactor = 0.7; 12 this.maxHeightFactor = 0.8; 13 this.maxWidth = null; 14 this.maxHeight = null; 15 this.endWidth = 0; 16 this.endHeight = 0; 17 this.endMarginTop = 0; 18 this.endMarginLeft = 0; 19 this.isImage = false; 20 this.additionalContent = null; 21 this.additionalContentID = null; 22 this.page = null; 23 this.event = null; 24 this.wasError = false; 25 this.popupImageStack = null; 26 27 this.showContent = null; 28 29 var self = this; 30 31 this.getFirst = function() { /* To be implemented */ 32 if (!this.popupImageStack) { 33 return false; 34 } 35 return this.popupImageStack[0].id == this.page; 36 }; 37 38 this.getLast = function() { /* To be implemented */ 39 if (!this.popupImageStack) { 40 return false; 41 } 42 return this.popupImageStack[this.popupImageStack.length - 1].id == this.page; 43 }; 44 45 this.skipToImage = function(itemNr) { 46 47 var previous = null; 48 var elem = null; 49 for ( var item in this.popupImageStack) { 50 51 if ( !this.popupImageStack.hasOwnProperty(item) ) 52 { 53 continue; 54 } 55 56 var check = this.popupImageStack[item]; 57 58 // previous was inpoint 59 if (previous && previous.id == this.page) { 60 elem = check; 61 break; 62 } 63 64 // Found + must go 65 if (check.id == this.page && itemNr < 0) { 66 elem = previous; 67 break; 68 } 69 70 previous = check; 71 elem = check; 72 } 73 74 if (elem) { 75 this.dispatchClick(elem); 76 } 77 }; 78 79 this.dispatchClick = function(elem) { 80 if (elem == null) { 81 return; 82 } 83 84 $(elem).trigger('click'); 85 }; 86 87 this.setContentSize = function(width, height, offsetHeight, offsetElement) { 88 89 if (!this.contentDiv || !this.controlDiv) { 90 return; 91 } 92 93 if (!width || width === 0) { 94 width = this.screenWidth * this.maxWidthFactor; 95 } 96 97 if (!height || height === 0) { 98 height = this.screenHeight * this.maxHeightFactor; 99 } 100 101 // If given, we want the optimal size 102 if ( offsetElement ) 103 { 104 offsetElement = $(offsetElement); 105 offsetElement.css({ 106 position: 'fixed', 107 visibility: 'hidden', 108 width: 'auto', 109 height: 'auto' 110 }); 111 112 height = $(offsetElement).height(); 113 width = $(offsetElement).width(); 114 115 offsetElement.css({ 116 position: '', 117 visibility: 'visible', 118 }); 119 } 120 121 width = parseFloat(width); 122 height = parseFloat(height); 123 offsetHeight = typeof offsetHeight == "undefined" || isNaN(parseFloat(offsetHeight)) ? 0 : parseFloat(offsetHeight); // may be undefined 124 var ratio = width / height; 125 126 height += offsetHeight; 127 128 if (height > (this.screenHeight * 0.99) - 60) { 129 height = (this.screenHeight * 0.99) - 60; 130 131 if (this.isImage) { // If this is an image we will have to fix the size 132 width = (height - offsetHeight) * ratio; 133 } else { 134 width += 20; // For the scroller Bar that will apear; 135 } 136 } 137 138 if (width > (this.screenWidth * 0.99) - 40) { 139 width = (this.screenWidth * 0.99) - 40; 140 141 if (this.isImage) { // If Image is defined then we will have to fix it 142 height = (width / ratio) + offsetHeight; 143 } 144 } 145 146 this.endWidth = width + (this.isImage ? 0 : 24); // 24 Px for padding + Border if is Image 147 this.endHeight = height; 148 149 var xOffset = $(document).scrollLeft() || 0; 150 var yOffset = $(document).scrollTop() || 0; 151 152 this.endMarginTop = (this.screenHeight - height) * 0.5 + yOffset; 153 if (this.endMarginTop < 5) { 154 this.endMarginTop = 5; 155 } 156 157 this.endMarginLeft = (this.screenWidth - width) * 0.5 + xOffset; 158 this.setSize(); 159 if ( !$('#popupviewer_loader_div').size() > 0 ) this.addNextAndPrevious(); 160 }; 161 162 this.setSize = function() { 163 164 $(this.contentDiv).css({ 165 'width' : this.endWidth, 166 'height' : !this.isImage ? this.endHeight : 'auto' 167 }); 168 169 $(this.controlDiv).css({ 170 'top' : this.endMarginTop, 171 'left' : this.endMarginLeft, 172 }); 173 }; 174 175 this.addNextAndPrevious = function() { 176 177 // If not already defined, do so now 178 if (!this.popupImageStack) { 179 this.popupImageStack = $(document).find('img.popupimage'); 180 } 181 182 if (this.popupImageStack && this.popupImageStack.length > 1) { 183 184 var previousImage = document.createElement('a'); 185 previousImage.id = 'popupviewer_control_prevoiusImage'; 186 187 var nextImage = document.createElement('a'); 188 nextImage.id = 'popupviewer_control_nextImage'; 189 190 var selfNAP = this; 191 var skipEvent = function(event) { /* To be implemented */ 192 193 if (!event) { 194 var event = window.event; 195 } 196 197 var target = ((event.target) ? event.target : event.srcElement).id.indexOf("next") > 0 ? 1 : -1; 198 selfNAP.skipToImage(target); 199 }; 200 201 // If this is not the last image - set inactive 202 if (!this.getLast()) { 203 $(nextImage).click(skipEvent); 204 } else { 205 nextImage.className = "inactive"; 206 } 207 208 // If this is not the first image - set inactive 209 if (!this.getFirst()) { 210 $(previousImage).click(skipEvent); 211 } else { 212 previousImage.className = "inactive"; 213 } 214 215 if ( $('#'+nextImage.id).size() > 0 ) { $('#'+nextImage.id).remove(); } 216 if ( $('#'+previousImage.id).size() > 0 ) { $('#'+previousImage.id).remove(); } 217 218 this.controlDiv.appendChild(nextImage); 219 this.controlDiv.appendChild(previousImage); 220 } 221 }; 222 223 this.getIntValue = function(value) { 224 return parseInt(value.substr(0, value.indexOf('px')), 10); 225 }; 226 227 this.buildViewerWithLoader = function() { 228 229 this.removeOldViewer(); 230 this.contentDiv = document.createElement('div'); 231 this.contentDiv.id = 'popupviewer_content'; 232 this.contentDiv.className = 'isImage'; 233 234 this.controlDiv = document.createElement('div'); 235 this.controlDiv.id = 'popupviewer_control'; 236 237 this.controlDiv.appendChild(this.contentDiv); 238 239 var loaderDiv = document.createElement('div'); 240 loaderDiv.id = 'popupviewer_loader_div'; 241 242 this.contentDiv.appendChild(loaderDiv); 243 244 var closeImage = document.createElement('a'); 245 closeImage.id = 'popupviewer_control_closeImage'; 246 247 this.controlDiv.appendChild(closeImage); 248 249 var sampleDiv = document.createElement('div'); 250 sampleDiv.id = 'popupviewer'; 251 252 var overlayDiv = document.createElement('div'); 253 overlayDiv.id = 'popupviewer_overlay'; 254 255 overlayDiv.style.height = (document.body.offsetHeight -1 ) + 'px'; 256 overlayDiv.style.width = (document.body.offsetWidth -1 ) + 'px'; 257 258 sampleDiv.appendChild(overlayDiv); 259 260 /* IE 6 Crasher */ 261 sampleDiv.appendChild(this.controlDiv); 262 263 $(overlayDiv).click(self.removeOldViewer); 264 $(closeImage).click(self.removeOldViewer); 265 $(document).bind('keydown', self.globalEvent); 266 267 // window.scrollTo(0, 0); 268 document.getElementsByTagName('body')[0].style.overflow = 'hidden'; 269 document.getElementsByTagName('body')[0].appendChild(sampleDiv); 270 271 this.setContentSize(210, 20); 272 }; 273 274 this.removeOldViewer = function() 275 { 276 if ($('#popupviewer').size() > 0) { 277 $('#popupviewer').remove(); 278 $(document).unbind('keydown', self.globalEvent); 279 } 280 document.getElementsByTagName('body')[0].style.overflow = 'auto'; 281 }; 282 283 this.displayContent = function(showContent, isImage, width, height) { 284 285 this.isImage = isImage; 286 287 if (!$('#popupviewer').size() > 0) { 288 this.buildViewerWithLoader(); 289 } 290 if (!showContent || showContent === null) { 291 if (typeof (showContent) != 'undefined') { 292 this.setContentSize(width, height); 293 } 294 return this; 295 } 296 297 if (isImage) { 298 299 var img = new Image(); 300 img.src = showContent; 301 img.className = "imageContent"; 302 303 if (this.event) { 304 var elem = (this.event.target) ? this.event.target : this.event.srcElement; 305 this.page = elem.id; 306 } 307 308 var check = new checkImageRoutine(img); 309 var selfIR = this; 310 var callback = { 311 312 image : img, 313 error : function() { 314 selfIR.removeOldViewer(); 315 }, 316 finalize : function() { 317 318 // var height = this.image.height; 319 var selfCallback = this; 320 321 // self.setContentSize(this.image.width, height, true); 322 var callback = function(response) { 323 324 var container = document.createElement('div'); 325 container.className = 'additionalContent dokuwiki'; 326 container.innerHTML = response; 327 328 $('#popupviewer_loader_div').remove(); 329 $('#popupviewer_content').append(selfCallback.image); 330 selfIR.contentDiv.className = 'dokuwiki'; 331 selfIR.contentDiv.className = 'isImage'; 332 $('#popupviewer_content').append(container); 333 334 selfIR.setContentSize(selfCallback.image.offsetWidth,selfCallback.image.offsetHeight,container.offsetHeight); 335 $(selfCallback.image).css({ 336 'width':self.endWidth, 337 'height':self.endHeight, 338 }) 339 }; 340 341 var errorCallback = function() { 342 $('#popupviewer_loader_div').remove(); 343 $('#popupviewer_content').append(selfCallback.image); 344 selfIR.contentDiv.className = 'dokuwiki'; 345 selfIR.contentDiv.className = 'isImage'; 346 347 selfIR.setContentSize(selfCallback.image.offsetWidth, selfCallback.image.offsetHeight); 348 $(selfCallback.image).css({ 349 'width':selfIR.endWidth, 350 'height':selfIR.endHeight, 351 }) 352 353 }; 354 355 if (selfIR.additionalContent) { 356 callback(selfIR.additionalContent); 357 } else { 358 selfIR.runAJAX(callback, { 359 'call' : '_popup_load_image_meta', 360 'id' : selfIR.additionalContentID 361 }, errorCallback); 362 } 363 364 } 365 }; 366 367 check.checkLoadImage(50, callback); 368 } else { 369 this.contentDiv.className = 'dokuwiki'; 370 this.contentDiv.innerHTML = showContent; 371 372 var images = $(this.contentDiv).find('img').each(function(){ 373 (new checkImageRoutine(this)).checkLoadImage(50, { 374 finalize: function() { 375 self.setContentSize(width, height, null, self.contentDiv); 376 } 377 }); 378 }); 379 380 this.setContentSize(width, height, null, this.contentDiv); 381 } 382 }; 383 384 this.linkReplacer = function(matches, depth) { 385 386 var schema = matches[1]; 387 var urlpart = matches[2]; 388 389 if (urlpart.match(/^#(.*?)$/)) { 390 // ScrollToDiv 391 urlpart += "\" onclick=\"if(!event){var event=window.event;}if(event){event.cancelBubble=true;event.returnValue=false;}if(event&&event.stopPropagation){event.stopPropagation();}if(event&&event.preventDefault){event.preventDefault();}jQuery('#popupviewer_content').scrollTop=jQuery('#" 392 + ((urlpart == "#") ? "popupviewer_content" : urlpart 393 .substr(1)) + "').offsetTop;return false;"; 394 } else if (!urlpart.match(new RegExp("^(https?:\/\/|mailto:|" 395 + escape(DOKU_BASE) + ")"))) { 396 urlpart = depth + urlpart; 397 } 398 399 return schema + '="' + urlpart + '"'; 400 }; 401 402 this.callback = function(data) { 403 404 /* Reset Init Events */ 405 window.oninit = function() { 406 }; 407 408 /* check for script to be executed */ 409 var script = ""; 410 if (typeof data == "string" && data !== '') { 411 data = data.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, 412 function() { 413 if (data !== null) { 414 script += arguments[1].replace(new RegExp("(<!--\/\/--><!\\[CDATA\\[\/\/><!--|\/\/--><!\\]\\]>)", "gi"), "") + '\n'; 415 } 416 return ''; 417 }); 418 419 } 420 421 try { 422 data = self.preg_replace_callback( '/(href|src|action)="([^"]*)"/ig', self.linkReplacer, data); 423 self.displayContent(data, false, self.endWidth, self.endHeight); 424 } catch (e) { 425 alert(e); 426 return self.removeOldViewer(); 427 } 428 try { 429 eval(script + "window.oninit();"); 430 } catch (scriptE) { 431 alert("A script error occurred in PopUpViewer. This problem may not be as problematic and the site will run fine. But please get in contact with the sites owner and tell them what you did.\n\n" + scriptE); 432 } 433 }; 434 435 // lets try iframe on an error 436 // This relies on the postMessage function of newer browsers 437 // and needs: if ( typeof parent != 'undefined' && parent.postMessage) { 438 // parent.postMessage(document.body.scrollHeight, '*'); } 439 // on the onload function of the loaded pages body. 440 this.errorCallback = function(successaction) { 441 442 // Build Frame 443 var iframe = document.createElement("iframe"); 444 iframe.id = "__contentIFrame"; 445 iframe.name = "__contentIFrame"; 446 iframe.setAttribute('scrolling', 'no'); 447 iframe.style.display = "none"; 448 449 var finished = false; 450 var messageFunction = function(event) { 451 452 finished = true; 453 var data = event.data || event.originalEvent.data; 454 // If this message does not come with what we want, discard it. 455 if ((typeof data).toLowerCase() == "string" || !data.message 456 || data.message != 'frameContent') { 457 alert("Could not load page via popupviewer. The page responded with a wrong message."); 458 return; 459 } 460 461 successaction(data.body); 462 463 $(iframe).remove(); 464 465 // Clear the window Event after we are done! 466 $(window).unbind("message", messageFunction); 467 }; 468 469 // load event for the iframe to display the content 470 $(iframe).bind('load', function() { 471 472 // Check If we can send a postMessage 473 if (iframe.contentWindow.postMessage) { 474 475 // Register the Message Event for PostMessage receival 476 $(window).bind("message", messageFunction); 477 478 // Send a message 479 var message = "getFrameContent"; 480 iframe.contentWindow.postMessage(message, "*"); 481 } 482 }); 483 484 window.setTimeout(function() { 485 if (!finished) { 486 $(iframe).remove(); 487 alert("Could not load page via popupviewer. The page is not available."); 488 } 489 }, 30000); 490 491 iframe.src = self.page; 492 document.getElementsByTagName('body')[0].appendChild(iframe); 493 }; 494 495 this.loadAndDisplayPage = function(page, width, height, id, params) { 496 497 if (self.event) { 498 var elem = (self.event.target) ? self.event.target : self.event.srcElement; 499 self.page = elem.href == page ? elem.getAttribute('href') : ""; 500 } 501 502 self.endWidth = width; 503 self.endHeight = height; 504 505 // Set custom params 506 if ( (typeof params).toLowerCase() != "object" ) { params = {}; } 507 if ( !params.call ) { params.call = '_popup_load_file'; } 508 if ( !params.id ) { params.id = id; } 509 this.runAJAX(self.callback, params, self.errorCallback); 510 }; 511 512 this.globalEvent = function(e) { 513 514 e = e||window.event; 515 516 if ( e.keyCode ) { 517 switch( e.keyCode ) { 518 case 39: // Right 519 if ( $('#popupviewer_control_nextImage').size() > 0 && !self.getLast() ) { 520 self.dispatchClick($('popupviewer_control_nextImage')); 521 } 522 break; 523 case 37: // Left 524 if ( $('#popupviewer_control_prevoiusImage').size() > 0 && !self.getFirst() ) { 525 self.dispatchClick($('#popupviewer_control_prevoiusImage')); 526 } 527 break; 528 case 27: // Escape 529 self.removeOldViewer(); 530 break; 531 } 532 } 533 return; 534 }; 535 536 this.runAJAX = function(callback, options, errorCallback, url) { 537 538 var trackLink = url; 539 if (typeof url == "undefined") { 540 url = DOKU_BASE + 'lib/exe/ajax.php'; 541 } 542 543 var success = function (data) { 544 545 // Google Ping 546 if ( typeof googleanalytics_trackLink != "undefined" ) { 547 googleanalytics_trackLink(trackLink); 548 } 549 if ( typeof callback == "function" ) { 550 callback(data); 551 } 552 }; 553 554 $('#popupviewer_content').load(url, options, function( response, status, xhr ) { 555 556 if ( status == "error" ) { 557 // Retry 558 errorCallback(success); 559 } else { 560 success(response); 561 } 562 563 }); 564 565 }; 566 567 this.preg_replace_callback = function(pattern, callback, subject, limit) { 568 // Perform a regular expression search and replace using a callback 569 // 570 // discuss at: http://geekfg.net/ 571 // + original by: Francois-Guillaume Ribreau (http://fgribreau) 572 // * example 1: 573 // preg_replace_callback("/(\\@[^\\s,\\.]*)/ig",function(matches){return 574 // matches[0].toLowerCase();},'#FollowFriday @FGRibreau @GeekFG',1); 575 // * returns 1: "#FollowFriday @fgribreau @GeekFG" 576 // * example 2: 577 // preg_replace_callback("/(\\@[^\\s,\\.]*)/ig",function(matches){return 578 // matches[0].toLowerCase();},'#FollowFriday @FGRibreau @GeekFG'); 579 // * returns 2: "#FollowFriday @fgribreau @geekfg" 580 581 limit = !limit ? -1 : limit; 582 583 var _check = pattern.substr(0, 1), _flag = pattern.substr(pattern 584 .lastIndexOf(_check) + 1), _pattern = pattern.substr(1, pattern 585 .lastIndexOf(_check) - 1), reg = new RegExp(_pattern, _flag), rs = null, res = [], x = 0, list = [], depth = "", ret = subject; 586 587 String.prototype.repeat = function(num) { 588 return new Array(num + 1).join(this); 589 }; 590 591 // This may generate urls like "../test/../test" 592 if ( !this.page ) { this.page = ""; } 593 depth = this.page.substr(0, this.page.lastIndexOf("/") + 1); 594 595 if (limit === -1) { 596 var tmp = []; 597 598 do { 599 tmp = reg.exec(subject); 600 if (tmp !== null) { 601 res.push(tmp); 602 } 603 } while (tmp !== null && _flag.indexOf('g') !== -1); 604 } else { 605 res.push(reg.exec(subject)); 606 } 607 608 for (x = res.length - 1; x > -1; x--) {// explore match 609 if (!list[res[x][0]]) { 610 ret = ret.replace(new RegExp(res[x][0], "g"), callback(res[x], 611 depth)); 612 list[res[x][0]] = true; 613 } 614 } 615 return ret; 616 }; 617 618 this.init = function(event) { 619 if (!event) { 620 var event = window.event; 621 } 622 if (event) { 623 event.cancelBubble = true; 624 event.returnValue = false; 625 if (event.stopPropagation) { 626 event.stopPropagation(); 627 } 628 if (event.preventDefault) { 629 event.preventDefault(); 630 } 631 } 632 this.event = event; 633 }; 634 635 this.removeOldViewer(); 636 this.displayContent(showContent, isImage, width, height); 637}; 638 639(function($){ 640 $(window).bind("message", function(event){ 641 642 var data = event.data || event.originalEvent.data; 643 var source = event.source || event.originalEvent.source; 644 if (data != "getFrameContent") { 645 return; 646 } 647 648 try { 649 source.postMessage({ 650 message : "frameContent", 651 body : jQuery('html').html() 652 }, "*"); 653 } catch (e) { 654 alert("Fatal Exception! Could not load page via popupviewer.\n" + e); 655 } 656 }); 657})(jQuery); 658 659var checkImageRoutine = function(inputImage) { 660 661 this.image = null; 662 this.counter = 500; 663 this.isFinished = false; 664 665 this.checkImages = function() { 666 667 var isOK = this.isImageOk(); 668 if (!isOK && this.counter > 0) { 669 this.counter--; 670 return false; 671 } 672 673 if (isOK) { 674 this.isFinished = true; 675 } 676 return true; 677 }; 678 679 this.isImageOk = function(img) { 680 681 if (this.isFinished) { 682 return true; 683 } 684 685 if (!img) { 686 img = this.image; 687 } 688 // During the onload event, IE correctly identifies any images 689 // that weren't downloaded as not complete. Others should too. 690 // Gecko-based browsers act like NS4 in that they imageflow this 691 // incorrectly: they always return true. 692 if (!img.complete) { 693 return false; 694 } 695 696 // However, they do have two very useful properties: naturalWidth 697 // and naturalHeight. These give the true size of the image. If 698 // it failed to load, either of these should be zero. 699 if (typeof img.naturalWidth != "undefined" && img.naturalWidth === 0) { 700 return false; 701 } 702 703 // No other way of checking: assume it's ok. 704 return true; 705 }; 706 707 this.checkLoadImage = function(count, callback) { 708 709 if (!count || count === 0) { 710 if (callback && callback.error) { 711 callback.error(); 712 } 713 return false; 714 } 715 if (!this.isImageOk()) { 716 var selfCLI = this; 717 setTimeout(function() { 718 selfCLI.checkLoadImage(count - 1, callback); 719 }, 100); 720 return; 721 } 722 723 if (callback && callback.finalize) { 724 callback.finalize(); 725 } 726 return true; 727 }; 728 729 this.finish = function() { 730 this.counter = 0; 731 }; 732 733 this.image = inputImage; 734 this.image.onload = this.finish; 735 this.image.onabord = this.finish; 736};