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 $(this.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 return; 537 }; 538 539 this.runAJAX = function(callback, options, errorCallback, url) { 540 541 var trackLink = url; 542 if (typeof url == "undefined") { 543 url = DOKU_BASE + 'lib/exe/ajax.php'; 544 } 545 546 var success = function (data) { 547 548 // Google Ping 549 if ( typeof googleanalytics_trackLink != "undefined" ) { 550 googleanalytics_trackLink(trackLink); 551 } 552 if ( typeof callback == "function" ) { 553 callback(data); 554 } 555 }; 556 557 $('#popupviewer_content').load(url, options, function( response, status, xhr ) { 558 559 if ( status == "error" ) { 560 // Retry 561 errorCallback(success); 562 } else { 563 success(response); 564 } 565 566 }); 567 568 }; 569 570 this.preg_replace_callback = function(pattern, callback, subject, limit) { 571 // Perform a regular expression search and replace using a callback 572 // 573 // discuss at: http://geekfg.net/ 574 // + original by: Francois-Guillaume Ribreau (http://fgribreau) 575 // * example 1: 576 // preg_replace_callback("/(\\@[^\\s,\\.]*)/ig",function(matches){return 577 // matches[0].toLowerCase();},'#FollowFriday @FGRibreau @GeekFG',1); 578 // * returns 1: "#FollowFriday @fgribreau @GeekFG" 579 // * example 2: 580 // preg_replace_callback("/(\\@[^\\s,\\.]*)/ig",function(matches){return 581 // matches[0].toLowerCase();},'#FollowFriday @FGRibreau @GeekFG'); 582 // * returns 2: "#FollowFriday @fgribreau @geekfg" 583 584 limit = !limit ? -1 : limit; 585 586 var _check = pattern.substr(0, 1), _flag = pattern.substr(pattern 587 .lastIndexOf(_check) + 1), _pattern = pattern.substr(1, pattern 588 .lastIndexOf(_check) - 1), reg = new RegExp(_pattern, _flag), rs = null, res = [], x = 0, list = [], depth = "", ret = subject; 589 590 String.prototype.repeat = function(num) { 591 return new Array(num + 1).join(this); 592 }; 593 594 // This may generate urls like "../test/../test" 595 if ( !this.page ) { this.page = ""; } 596 depth = this.page.substr(0, this.page.lastIndexOf("/") + 1); 597 598 if (limit === -1) { 599 var tmp = []; 600 601 do { 602 tmp = reg.exec(subject); 603 if (tmp !== null) { 604 res.push(tmp); 605 } 606 } while (tmp !== null && _flag.indexOf('g') !== -1); 607 } else { 608 res.push(reg.exec(subject)); 609 } 610 611 for (x = res.length - 1; x > -1; x--) {// explore match 612 if (!list[res[x][0]]) { 613 ret = ret.replace(new RegExp(res[x][0], "g"), callback(res[x], 614 depth)); 615 list[res[x][0]] = true; 616 } 617 } 618 return ret; 619 }; 620 621 this.init = function(event) { 622 if (!event) { 623 var event = window.event; 624 } 625 if (event) { 626 event.cancelBubble = true; 627 event.returnValue = false; 628 if (event.stopPropagation) { 629 event.stopPropagation(); 630 } 631 if (event.preventDefault) { 632 event.preventDefault(); 633 } 634 } 635 this.event = event; 636 }; 637 638 this.removeOldViewer(); 639 this.displayContent(showContent, isImage, width, height); 640}; 641 642(function($){ 643 $(window).bind("message", function(event){ 644 645 var data = event.data || event.originalEvent.data; 646 var source = event.source || event.originalEvent.source; 647 if (data != "getFrameContent") { 648 return; 649 } 650 651 try { 652 source.postMessage({ 653 message : "frameContent", 654 body : jQuery('html').html() 655 }, "*"); 656 } catch (e) { 657 alert("Fatal Exception! Could not load page via popupviewer.\n" + e); 658 } 659 }); 660})(jQuery); 661 662var checkImageRoutine = function(inputImage) { 663 664 this.image = null; 665 this.counter = 500; 666 this.isFinished = false; 667 668 this.checkImages = function() { 669 670 var isOK = this.isImageOk(); 671 if (!isOK && this.counter > 0) { 672 this.counter--; 673 return false; 674 } 675 676 if (isOK) { 677 this.isFinished = true; 678 } 679 return true; 680 }; 681 682 this.isImageOk = function(img) { 683 684 if (this.isFinished) { 685 return true; 686 } 687 688 if (!img) { 689 img = this.image; 690 } 691 // During the onload event, IE correctly identifies any images 692 // that weren't downloaded as not complete. Others should too. 693 // Gecko-based browsers act like NS4 in that they imageflow this 694 // incorrectly: they always return true. 695 if (!img.complete) { 696 return false; 697 } 698 699 // However, they do have two very useful properties: naturalWidth 700 // and naturalHeight. These give the true size of the image. If 701 // it failed to load, either of these should be zero. 702 if (typeof img.naturalWidth != "undefined" && img.naturalWidth === 0) { 703 return false; 704 } 705 706 // No other way of checking: assume it's ok. 707 return true; 708 }; 709 710 this.checkLoadImage = function(count, callback) { 711 712 if (!count || count === 0) { 713 if (callback && callback.error) { 714 callback.error(); 715 } 716 return false; 717 } 718 if (!this.isImageOk()) { 719 var self = this; 720 setTimeout(function() { 721 self.checkLoadImage(count - 1, callback); 722 }, 100); 723 return; 724 } 725 726 if (callback && callback.finalize) { 727 callback.finalize(); 728 } 729 return true; 730 }; 731 732 this.finish = function() { 733 this.counter = 0; 734 }; 735 736 this.image = inputImage; 737 this.image.onload = this.finish; 738 this.image.onabord = this.finish; 739};