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