1 2/** 3 * jQuery Lightbox Plugin (balupton edition) - Lightboxes for jQuery 4 * Copyright (C) 2008 Benjamin Arthur Lupton 5 * http://jquery.com/plugins/project/jquerylightbox_bal 6 * 7 * This file is part of jQuery Lightbox (balupton edition). 8 * 9 * jQuery Lightbox (balupton edition) is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Affero General Public License as 11 * published by the Free Software Foundation, either version 3 of the 12 * License, or (at your option) any later version. 13 * 14 * jQuery Lightbox (balupton edition) is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Affero General Public License for more details. 18 * 19 * You should have received a copy of the GNU Affero General Public License 20 * along with jQuery Lightbox (balupton edition). If not, see <http://www.gnu.org/licenses/>. 21 * 22 * @name jquery_lightbox: jquery.lightbox.js 23 * @package jQuery Lightbox Plugin (balupton edition) 24 * @version 1.3.6-final 25 * @date March 08, 2009 26 * @category jQuery plugin 27 * @author Benjamin "balupton" Lupton {@link http://www.balupton.com} 28 * @copyright (c) 2008 Benjamin Arthur Lupton {@link http://www.balupton.com} 29 * @license GNU Affero General Public License - {@link http://www.gnu.org/licenses/agpl.html} 30 * @example Visit {@link http://jquery.com/plugins/project/jquerylightbox_bal} for more information. 31 */ 32 33// Start of our jQuery Plugin 34(function($) 35{ // Create our Plugin function, with $ as the argument (we pass the jQuery object over later) 36 // More info: http://docs.jquery.com/Plugins/Authoring#Custom_Alias 37 38 // Debug 39 if ( typeof $.log === 'undefined' ) { 40 if ( !$.browser.safari && typeof window.console !== 'undefined' && typeof window.console.log === 'function' ) 41 { // Use window.console 42 $.log = function(){ 43 var args = []; 44 for(var i = 0; i < arguments.length; i++) { 45 args.push(arguments[i]); 46 } 47 window.console.log.apply(window.console, args); 48 } 49 $.console = { 50 log: $.log, 51 debug: window.console.debug || $.log, 52 warn: window.console.warn || $.log, 53 error: window.console.error || $.log, 54 trace: window.console.trace || $.log 55 } 56 } 57 else 58 { // Don't use anything 59 $.log = function ( ) { }; 60 $.console = { 61 log: $.log, 62 debug: $.log, 63 warn: $.log, 64 error: alert, 65 trace: $.log 66 }; 67 } 68 } 69 70 // Pre-Req 71 $.params_to_json = $.params_to_json || function ( params ) 72 { // Turns a params string or url into an array of params 73 // Adjust 74 params = String(params); 75 // Remove url if need be 76 params = params.substring(params.indexOf('?')+1); 77 // params = params.substring(params.indexOf('#')+1); 78 // Change + to %20, the %20 is fixed up later with the decode 79 params = params.replace(/\+/g, '%20'); 80 // Do we have JSON string 81 if ( params.substring(0,1) === '{' && params.substring(params.length-1) === '}' ) 82 { // We have a JSON string 83 return eval(decodeURIComponent(params)); 84 } 85 // We have a params string 86 params = params.split(/\&|\&\;/); 87 var json = {}; 88 // We have params 89 for ( var i = 0, n = params.length; i < n; ++i ) 90 { 91 // Adjust 92 var param = params[i] || null; 93 if ( param === null ) { continue; } 94 param = param.split('='); 95 if ( param === null ) { continue; } 96 // ^ We now have "var=blah" into ["var","blah"] 97 98 // Get 99 var key = param[0] || null; 100 if ( key === null ) { continue; } 101 if ( typeof param[1] === 'undefined' ) { continue; } 102 var value = param[1]; 103 // ^ We now have the parts 104 105 // Fix 106 key = decodeURIComponent(key); 107 value = decodeURIComponent(value); 108 try { 109 // value can be converted 110 value = eval(value); 111 } catch ( e ) { 112 // value is a normal string 113 } 114 115 // Set 116 // console.log({'key':key,'value':value}, split); 117 var keys = key.split('.'); 118 if ( keys.length === 1 ) 119 { // Simple 120 json[key] = value; 121 } 122 else 123 { // Advanced 124 var path = ''; 125 for ( ii in keys ) 126 { // 127 key = keys[ii]; 128 path += '.'+key; 129 eval('json'+path+' = json'+path+' || {}'); 130 } 131 eval('json'+path+' = value'); 132 } 133 // ^ We now have the parts added to your JSON object 134 } 135 return json; 136 }; 137 138 // Declare our class 139 $.LightboxClass = function ( ) 140 { // This is the handler for our constructor 141 this.construct(); 142 }; 143 144 // Extend jQuery elements for Lightbox 145 $.fn.lightbox = function ( options ) 146 { // Init a el for Lightbox 147 // Eg. $('#gallery a').lightbox(); 148 149 // If need be: Instantiate $.LightboxClass to $.Lightbox 150 $.Lightbox = $.Lightbox || new $.LightboxClass(); 151 152 // Handle IE6 appropriatly 153 if ( $.Lightbox.ie6 && !$.Lightbox.ie6_support ) 154 { // We are IE6 and we want to ignore 155 return this; // chain 156 } 157 158 // Establish options 159 options = $.extend({start:false,events:true} /* default options */, options); 160 161 // Get group 162 var group = $(this); 163 164 // Events? 165 if ( options.events ) 166 { // Add events 167 $(group).unbind().click(function(){ 168 // Get obj 169 var obj = $(this); 170 // Get rel 171 // var rel = $(obj).attr('rel'); 172 // Init group 173 if ( !$.Lightbox.init($(obj)[0], group) ) 174 { return false; } 175 // Display lightbox 176 if ( !$.Lightbox.start() ) 177 { return false; } 178 // Cancel href 179 return false; 180 }); 181 // Add style 182 $(group).addClass('lightbox-enabled'); 183 } 184 185 // Start? 186 if ( options.start ) 187 { // Start 188 // Get obj 189 var obj = $(this); 190 // Get rel 191 // var rel = $(obj).attr('rel'); 192 // Init group 193 if ( !$.Lightbox.init($(obj)[0], group) ) 194 { return this; } 195 // Display lightbox 196 if ( !$.Lightbox.start() ) 197 { return this; } 198 } 199 200 // And chain 201 return this; 202 }; 203 204 // Define our class 205 $.extend($.LightboxClass.prototype, 206 { // Our LightboxClass definition 207 208 // ----------------- 209 // Everyting to do with images 210 211 images: { 212 213 // ----------------- 214 // Variables 215 216 // Our array of images 217 list:[], /* [ { 218 src: 'url to image', 219 link: 'a link to a page', 220 title: 'title of the image', 221 name: 'name of the image', 222 description: 'description of the image' 223 } ], */ 224 225 // The current active image 226 image: false, 227 228 // ----------------- 229 // Functions 230 231 prev: function ( image ) 232 { // Get previous image 233 234 // Get previous from current? 235 if ( typeof image === 'undefined' ) 236 { image = this.active(); 237 if ( !image ) { return image; } 238 } 239 240 // Is there a previous? 241 if ( this.first(image) ) 242 { return false; } 243 244 // Get the previous 245 return this.get(image.index-1); 246 }, 247 248 next: function ( image ) 249 { // Get next image 250 251 // Get next from current? 252 if ( typeof image === 'undefined' ) 253 { image = this.active(); 254 if ( !image ) { return image; } 255 } 256 257 // Is there a next? 258 if ( this.last(image) ) 259 { return false; } 260 261 // Get the next 262 return this.get(image.index+1); 263 }, 264 265 first: function ( image ) 266 { // 267 // Get the first image? 268 if ( typeof image === 'undefined' ) 269 { return this.get(0); } 270 271 // Are we the first? 272 return image.index === 0; 273 }, 274 275 last: function ( image ) 276 { // 277 // Get the last image? 278 if ( typeof image === 'undefined' ) 279 { return this.get(this.size()-1); } 280 281 // Are we the last? 282 return image.index === this.size()-1; 283 }, 284 285 single: function ( ) 286 { // Are we only one 287 return this.size() === 1; 288 }, 289 290 size: function ( ) 291 { // How many images do we have 292 return this.list.length; 293 }, 294 295 empty: function ( ) 296 { // Are we empty 297 return this.size() === 0; 298 }, 299 300 clear: function ( ) 301 { // Clear image arrray 302 this.list = []; 303 this.image = false; 304 }, 305 306 active: function ( image ) 307 { // Set or get the active image 308 // Use false to reset 309 310 // Get the active image? 311 if ( typeof image === 'undefined' ) 312 { return this.image; } 313 314 // Set the ative image 315 if ( image !== false ) 316 { // Make sure image exists 317 image = this.get(image); 318 if ( !image ) 319 { // Error 320 return image; 321 } 322 } 323 324 // Set the active image 325 this.image = image; 326 return true; 327 }, 328 329 add: function ( obj ) 330 { 331 // Do we need to recurse? 332 if ( obj[0] ) 333 { // We have a lot of images 334 for ( var i = 0; i < obj.length; i++ ) 335 { this.add(obj[i]); } 336 return true; 337 } 338 339 // Default image 340 341 // Try and create a image 342 var image = this.create(obj); 343 if ( !image ) { return image; } 344 345 // Set image index 346 image.index = this.size(); 347 348 // Push image 349 this.list.push(image); 350 351 // Success 352 return true; 353 }, 354 355 create: function ( obj ) 356 { // Create image 357 358 // Define 359 var image = { // default 360 src: '', 361 title: 'Untitled', 362 description: '', 363 name: '', 364 index: -1, 365 color: null, 366 width: null, 367 height: null, 368 image: true 369 }; 370 371 // Create 372 if ( obj.image ) 373 { // Already a image, so copy over values 374 image.src = obj.src || image.src; 375 image.title = obj.title || image.title; 376 image.description = obj.description || image.description; 377 image.name = obj.name || image.name; 378 image.color = obj.color || image.color; 379 image.width = obj.width || image.width; 380 image.height = obj.height || image.height; 381 image.index = obj.index || image.index; 382 } 383 else if ( obj.tagName ) 384 { // We are an element 385 obj = $(obj); 386 if ( obj.attr('src') || obj.attr('href') ) 387 { 388 image.src = obj.attr('src') || obj.attr('href'); 389 image.title = obj.attr('title') || obj.attr('alt') || image.title; 390 image.name = obj.attr('name') || ''; 391 image.color = obj.css('backgroundColor'); 392 // Extract description from title
393 var s = image.title.indexOf(': '); 394 if ( s > 0 ) 395 { // Description exists 396 image.description = image.title.substring(s+2) || image.description; 397 image.title = image.title.substring(0,s) || image.title; 398 } 399 } 400 else 401 { // Unsupported element 402 image = false; 403 } 404 } 405 else 406 { // Unknown 407 image = false; 408 } 409 410 if ( !image ) 411 { // Error 412 $.console.error('We dont know what we have:', obj); 413 return false; 414 } 415 416 // Success 417 return image; 418 }, 419 420 get: function ( image ) 421 { // Get the active, or specified image 422 423 // Establish image 424 if ( typeof image === 'undefined' || image === null ) 425 { // Get the active image 426 return this.active(); 427 } 428 else 429 if ( typeof image === 'number' ) 430 { // We have a index 431 432 // Get image 433 image = this.list[image] || false; 434 } 435 else 436 { // Create 437 image = this.create(image); 438 if ( !image ) { return false; } 439 440 // Find 441 var f = false; 442 for ( var i = 0; i < this.size(); i++ ) 443 { 444 var c = this.list[i]; 445 if ( c.src === image.src && c.title === image.title && c.description === image.description ) 446 { f = c; } 447 } 448 449 // Found? 450 image = f; 451 } 452 453 // Determine image 454 if ( !image ) 455 { // Image doesn't exist 456 $.console.error('The desired image doesn\'t exist: ', image, this.list); 457 return false; 458 } 459 460 // Return image 461 return image; 462 }, 463 464 debug: function ( ) 465 { 466 return $.Lightbox.debug(arguments); 467 } 468 469 }, 470 471 // ----------------- 472 // Variables 473 474 constructed: false, 475 compressed: null, 476 477 // ----------------- 478 // Options 479 480 src: null, // the source location of our js file 481 baseurl: null, 482 483 files: { 484 compressed: { 485 js: { 486 lightbox: '/js/ajax/lightbox/js/jquery.lightbox.min.js', 487 colorBlend: '/js/ajax/lightbox/js/jquery.color.min.js' 488 }, 489 css: { 490 lightbox: '/js/ajax/lightbox/css/jquery.lightbox.css' 491 } 492 }, 493 uncompressed: { 494 js: { 495 lightbox: '/js/ajax/lightbox/js/jquery.lightbox.js', 496 colorBlend: '/js/ajax/lightbox/js/jquery.color.js' 497 }, 498 css: { 499 lightbox: '/js/ajax/lightbox/css/jquery.lightbox.css' 500 } 501 }, 502 images: { 503 prev: '/js/ajax/lightbox/images/prev.gif', 504 next: '/js/ajax/lightbox/images/next.gif', 505 blank: '/js/ajax/lightbox/images/blank.gif', 506 loading: '/js/ajax/lightbox/images/loading.gif' 507 } 508 }, 509 510 text: { 511 // For translating 512 image: 'Image', 513 of: 'of', 514 close: 'Close X', 515 closeInfo: 'Ŭ¸¯ÇÏ½Ã¸é ´ÝÈü´Ï´Ù.', 516 download: 'Direct link to download the image.', 517 help: { 518 close: '', 519 interact: '' 520 }, 521 about: { 522 text: '', 523 title: '', 524 link: '' 525 } 526 }, 527 528 keys: { 529 close: 'c', 530 prev: 'p', 531 next: 'n' 532 }, 533 534 handlers: { 535 // For custom actions 536 show: null 537 }, 538 539 opacity: 0.5, 540 padding: null, // if null - autodetect 541 542 speed: 400, // Duration of effect, milliseconds 543 544 rel: 'lightbox', // What to look for in the rels 545 546 auto_relify: true, // should we automaticly do the rels? 547 548 auto_scroll: 'follow', // should the lightbox scroll with the page? follow, disabled, ignore 549 auto_resize: true, // true or false 550 551 ie6: null, // are we ie6? 552 ie6_support: true, // have ie6 support 553 ie6_upgrade: true, // show ie6 upgrade message 554 555 colorBlend: null, // null - auto-detect, true - force, false - no 556 557 download_link: true, // Display the download link 558 559 show_linkback: true, // true, false 560 show_info: 'auto', // auto - automaticly handle, true - force 561 show_extended_info: 'auto', // auto - automaticly handle, true - force 562 563 // names of the options that can be modified 564 options: ['auto_scroll', 'auto_resize', 'download_link', 'show_info', 'show_extended_info', 'ie6_support', 'ie6_upgrade', 'colorBlend', 'baseurl', 'files', 'text', 'show_linkback', 'keys', 'opacity', 'padding', 'speed', 'rel', 'auto_relify'], 565 566 // ----------------- 567 // Functions 568 569 construct: function ( options ) 570 { // Construct our Lightbox 571 572 // ------------------- 573 // Prepare 574 575 // Initial construct 576 var initial = typeof this.constructed === 'undefined' || this.constructed === false; 577 this.constructed = true; 578 579 // Perform domReady 580 var domReady = initial; 581 582 // Prepare options 583 options = options || {}; 584 585 // ------------------- 586 // Handle files 587 588 // Prepend function to use later 589 var prepend = function(item, value) { 590 if ( typeof item === 'object' ) { 591 for (var i in item) { 592 item[i] = prepend(item[i], value); 593 } 594 } else if ( typeof value === 'array' ) { 595 for (var i=0,n=item.length; i<n; ++i) { 596 item[i] = prepend(item[i], value); 597 } 598 } else { 599 item = value+item; 600 } 601 return item; 602 } 603 604 // Add baseurl 605 if ( initial && (typeof options.files === 'undefined') ) 606 { // Load the files like default 607 608 // Reset compressed 609 this.compressed = null; 610 611 // Get the src of the first script tag that includes our js file (with or without an appendix)
612 var $script = $('script[src*='+this.files.compressed.js.lightbox+']:first'); 613 if ( $script.length !== 0 ) { 614 // Compressed 615 $.extend(true, this.files, this.files.compressed); 616 this.compressed = true; 617 } else { 618 // Uncompressed 619 $script = $('script[src*='+this.files.uncompressed.js.lightbox+']:first'); 620 if ( $script.length !== 0 ) { 621 // Uncompressed 622 $.extend(true, this.files, this.files.uncompressed); 623 this.compressed = false; 624 } else { 625 // Nothing 626 } 627 } 628 629 // Make sure we found ourselves 630 if ( this.compressed === null ) 631 { // We didn't 632 $.console.error('Lightbox was not able to find it\'s javascript script tag necessary for auto-inclusion.'); 633 // We don't work with files anymore, so don't care for domReady 634 domReady = false; 635 } 636 else 637 { // We found ourself 638 639 // Grab the script src 640 this.src = $script.attr('src'); 641 642 // The baseurl is the src up until the start of our js file 643 this.baseurl = this.src.substring(0, this.src.indexOf(this.files.js.lightbox)); 644 645 // Prepend baseurl to files 646 this.files = prepend(this.files, this.baseurl); 647 648 // Now as we have source, we may have more params 649 options = $.extend(options, $.params_to_json(this.src)); 650 } 651 652 } 653 else 654 if ( typeof options.files === 'object' ) 655 { // We have custom files 656 // Prepend baseurl to files 657 options.files = prepend(options.files, this.baseurl); 658 } 659 else 660 { // Don't have any files, so no need to perform domReady 661 domReady = false; 662 } 663 664 // ------------------- 665 // Apply options 666 667 for ( var i in this.options ) 668 { // Cycle through the options 669 var name = this.options[i]; 670 if ( (typeof options[name] === 'object') && (typeof this[name] === 'object') ) 671 { // We have a group like text or files 672 this[name] = $.extend(true, this[name], options[name]); 673 } 674 else if ( typeof options[name] !== 'undefined' ) 675 { // We have that option, so apply it 676 this[name] = options[name]; 677 } 678 } delete i; 679 680 // ------------------- 681 // Figure out what to do 682 683 // Handle IE6 684 if ( initial && navigator.userAgent.indexOf('MSIE 6') >= 0 ) 685 { // Is IE6 686 this.ie6 = true; 687 } 688 else 689 { // We are not IE6 690 this.ie6 = false; 691 } 692 693 // ------------------- 694 // Handle our DOM 695 696 if ( domReady || typeof options.download_link !== 'undefined' || typeof options.colorBlend !== 'undefined' || typeof options.files === 'object' || typeof options.text === 'object' || typeof options.show_linkback !== 'undefined' || typeof options.scroll_with !== 'undefined' ) 697 { // We have reason to handle the dom 698 $(function() { 699 // DOM is ready, so fire our DOM handler 700 $.Lightbox.domReady(); 701 }); 702 } 703 704 // ------------------- 705 // Finish Up 706 707 // All good 708 return true; 709 }, 710 711 domReady: function ( ) 712 { 713 // ------------------- 714 // Include resources 715 716 // Grab resources 717 var bodyEl = document.getElementsByTagName($.browser.safari ? 'head' : 'body')[0]; 718 var stylesheets = this.files.css; 719 var scripts = this.files.js; 720 721 // Handle IE6 appropriatly 722 if ( this.ie6 && this.ie6_upgrade ) 723 { // Add the upgrade message 724 scripts.ie6 = 'http://www.savethedevelopers.org/say.no.to.ie.6.js'; 725 } 726 727 // colorBlend 728 if ( this.colorBlend === true && typeof $.colorBlend === 'undefined' ) 729 { // Force colorBlend 730 this.colorBlend = true; 731 // Leave file in place to be loaded 732 } 733 else 734 { // We either have colorBlend or we don't 735 this.colorBlend = typeof $.colorBlend !== 'undefined'; 736 // Remove colorBlend file 737 delete scripts.colorBlend; 738 } 739 740 // Include stylesheets 741 for ( stylesheet in stylesheets ) 742 { 743 var linkEl = document.createElement('link'); 744 linkEl.type = 'text/css'; 745 linkEl.rel = 'stylesheet'; 746 linkEl.media = 'screen'; 747 linkEl.href = stylesheets[stylesheet]; 748 linkEl.id = 'lightbox-stylesheet-'+stylesheet.replace(/[^a-zA-Z0-9]/g, ''); 749 $('#'+linkEl.id).remove(); 750 bodyEl.appendChild(linkEl); 751 } 752 753 // Include javascripts 754 for ( script in scripts ) 755 { 756 var scriptEl = document.createElement('script'); 757 scriptEl.type = 'text/javascript'; 758 scriptEl.src = scripts[script]; 759 scriptEl.id = 'lightbox-script-'+script.replace(/[^a-zA-Z0-9]/g, ''); 760 $('#'+scriptEl.id).remove(); 761 bodyEl.appendChild(scriptEl); 762 } 763 764 // Cleanup 765 delete scripts; 766 delete stylesheets; 767 delete bodyEl; 768 769 // -------------------
770 // Append display 771 772 // Append markup 773 $('#lightbox,#lightbox-overlay').remove(); 774 $('body').append('<div id="lightbox-overlay"><div id="lightbox-overlay-text">'+(this.show_linkback?'<p><span id="lightbox-overlay-text-about"><a href="#" title="'+this.text.about.title+'">'+this.text.about.text+'</a></span></p><p> </p>':'')+'<p><span id="lightbox-overlay-text-close">'+this.text.help.close+'</span><br/> <span id="lightbox-overlay-text-interact">'+this.text.help.interact+'</span></p></div></div><div id="lightbox"><div id="lightbox-imageBox"><div id="lightbox-imageContainer"><img id="lightbox-image" alt="lightbox-image" /><div id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + this.files.images.loading + '" alt="' + this.files.images.loading + '" /></a></div></div></div><div id="lightbox-infoBox"><div id="lightbox-infoContainer"><div id="lightbox-infoHeader"><span id="lightbox-caption">'+(this.download_link ? '<a href="#" title="' + this.text.download + '" id="lightbox-caption-title"></a>' : '<span id="lightbox-caption-title"></span>')+'<span id="lightbox-caption-seperator"></span><span id="lightbox-caption-description"></span></span></div><div id="lightbox-infoFooter"><span id="lightbox-currentNumber"></span><span id="lightbox-close"><a href="#" id="lightbox-close-button" title="'+this.text.closeInfo+'">' + this.text.close + '</a></span></div><div id="lightbox-infoContainer-clear"></div></div></div></div>'); 775 776 // Update Boxes - for some crazy reason this has to be before the hide in safari and konqueror 777 this.resizeBoxes(); 778 this.repositionBoxes(); 779 780 // Hide 781 $('#lightbox,#lightbox-overlay,#lightbox-overlay-text-interact').hide(); 782 783 // ------------------- 784 // Browser specifics 785 786 // Handle IE6 787 if ( this.ie6 && this.ie6_support ) 788 { // Support IE6 789 // IE6 does not support fixed positioning so absolute it 790 // ^ This is okay as we disable scrolling 791 $('#lightbox-overlay').css({ 792 position: 'absolute', 793 top: '0px', 794 left: '0px' 795 }); 796 } 797 798 // ------------------- 799 // Preload Images 800 801 // Cycle and preload 802 $.each(this.files.images, function() 803 { // Proload the image 804 var preloader = new Image(); 805 preloader.onload = function() { 806 preloader.onload = null; 807 preloader = null; 808 }; preloader.src = this; 809 }); 810 811 // ------------------- 812 // Apply events 813 814 // If the window resizes, act appropriatly 815 $(window).unbind().resize(function () 816 { // The window has been resized 817 $.Lightbox.resizeBoxes('resized'); 818 }); 819 820 // If the window scrolls, act appropriatly 821 if ( this.scroll === 'follow' ) 822 { // We want to 823 $(window).scroll(function () 824 { // The window has scrolled 825 $.Lightbox.repositionBoxes(); 826 }); 827 } 828 829 // Prev 830 $('#lightbox-nav-btnPrev').unbind().hover(function() { // over 831 $(this).css({ 'background' : 'url(' + $.Lightbox.files.images.prev + ') left 45% no-repeat' }); 832 },function() { // out 833 $(this).css({ 'background' : 'transparent url(' + $.Lightbox.files.images.blank + ') no-repeat' }); 834 }).click(function() { 835 $.Lightbox.showImage($.Lightbox.images.prev()); 836 return false; 837 }); 838 839 // Next 840 $('#lightbox-nav-btnNext').unbind().hover(function() { // over 841 $(this).css({ 'background' : 'url(' + $.Lightbox.files.images.next + ') right 45% no-repeat' }); 842 },function() { // out 843 $(this).css({ 'background' : 'transparent url(' + $.Lightbox.files.images.blank + ') no-repeat' }); 844 }).click(function() { 845 $.Lightbox.showImage($.Lightbox.images.next()); 846 return false; 847 }); 848 849 // Help 850 if ( this.show_linkback ) 851 { // Linkback exists so add handler 852 $('#lightbox-overlay-text-about a').click(function(){window.open($.Lightbox.text.about.link); return false;}); 853 } 854 $('#lightbox-overlay-text-close').unbind().hover( 855 function(){ 856 $('#lightbox-overlay-text-interact').fadeIn(); 857 }, 858 function(){ 859 $('#lightbox-overlay-text-interact').fadeOut(); 860 } 861 ); 862 863 // Image link 864 $('#lightbox-caption-title').click(function(){window.open($(this).attr('href')); return false;}); 865 866 // Assign close clicks 867 $('#lightbox-overlay, #lightbox, #lightbox-loading-link, #lightbox-btnClose').unbind().click(function() { 868 $.Lightbox.finish(); 869 return false; 870 }); 871 872 // -------------------
873 // Finish Up 874 875 // Relify 876 if ( this.auto_relify ) 877 { // We want to relify, no the user 878 this.relify(); 879 } 880 881 // All good 882 return true; 883 }, 884 885 relify: function ( ) 886 { // Create event 887 888 // 889 var groups = {}; 890 var groups_n = 0; 891 var orig_rel = this.rel; 892 // Create the groups 893 $.each($('[rel*='+orig_rel+']'), function(index, obj){ 894 // Get the group 895 var rel = $(obj).attr('rel'); 896 // Are we really a group 897 if ( rel === orig_rel ) 898 { // We aren't 899 rel = groups_n; // we are individual 900 } 901 // Does the group exist 902 if ( typeof groups[rel] === 'undefined' ) 903 { // Make the group 904 groups[rel] = []; 905 groups_n++; 906 } 907 // Append the image 908 groups[rel].push(obj); 909 }); 910 // Lightbox groups 911 $.each(groups, function(index, group){ 912 $(group).lightbox(); 913 }); 914 // Done 915 return true; 916 }, 917 918 init: function ( image, images ) 919 { // Init a batch of lightboxes 920 921 // Establish images 922 if ( typeof images === 'undefined' ) 923 { 924 images = image; 925 image = 0; 926 } 927 928 // Clear 929 this.images.clear(); 930 931 // Add images 932 if ( !this.images.add(images) ) 933 { return false; } 934 935 // Do we need to bother 936 if ( this.images.empty() ) 937 { // No images 938 $.console.warn('WARNING', 'Lightbox started, but no images: ', image, images); 939 return false; 940 } 941 942 // Set active 943 if ( !this.images.active(image) ) 944 { return false; } 945 946 // Done 947 return true; 948 }, 949 950 start: function ( ) 951 { // Display the lightbox 952 953 // We are alive 954 this.visible = true; 955 956 // Adjust scrolling 957 if ( this.scroll === 'disable' ) 958 { // 959 $(document.body).css('overflow', 'hidden'); 960 } 961 962 // Fix attention seekers 963 $('embed, object, select').css('visibility', 'hidden');//.hide(); - don't use this, give it a go, find out why! 964 965 // Resize the boxes appropriatly 966 this.resizeBoxes('general'); 967 968 // Reposition the Boxes 969 this.repositionBoxes({'speed':0}); 970 971 // Hide things 972 $('#lightbox-infoFooter').hide(); // we hide this here because it makes the display smoother 973 $('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-infoBox').hide(); 974 975 // Display the boxes 976 $('#lightbox-overlay').css('opacity',this.opacity).fadeIn(400, function(){ 977 // Show the lightbox 978 $('#lightbox').fadeIn(300); 979 980 // Display first image 981 if ( !$.Lightbox.showImage($.Lightbox.images.active()) ) 982 { $.Lightbox.finish(); return false; } 983 }); 984 985 // All done 986 return true; 987 }, 988 989 finish: function ( ) 990 { // Get rid of lightbox 991 992 // Hide lightbox 993 $('#lightbox').hide(); 994 $('#lightbox-overlay').fadeOut(function() { $('#lightbox-overlay').hide(); }); 995 996 // Fix attention seekers 997 $('embed, object, select').css({ 'visibility' : 'visible' });//.show(); 998 999 // Kill active image 1000 this.images.active(false); 1001 1002 // Adjust scrolling 1003 if ( this.scroll === 'disable' ) 1004 { // 1005 $(document.body).css('overflow', 'visible'); 1006 } 1007 1008 // We are dead 1009 this.visible = false; 1010 1011 }, 1012 1013 resizeBoxes: function ( type ) 1014 { // Resize the boxes 1015 // Used on transition or window resize 1016 1017 // Resize Overlay 1018 if ( type !== 'transition' ) 1019 { // We don't care for transition 1020 var $body = $(this.ie6 ? document.body : document); 1021 $('#lightbox-overlay').css({ 1022 width: $body.width(), 1023 height: $body.height()*1.5 1024 }); 1025 delete $body; 1026 } 1027 1028 // Handle cases 1029 switch ( type ) 1030 { 1031 case 'general': // general resize (start of lightbox) 1032 return true; 1033 break; 1034 case 'resized': // window was resized 1035 if ( this.auto_resize === false ) 1036 { // Stop 1037 // Reposition 1038 this.repositionBoxes({'nHeight':nHeight, 'speed':this.speed}); 1039 return true; 1040 } 1041 case 'transition': // transition between images 1042 default: // unknown 1043 break; 1044 } 1045 1046 // Get image 1047 var image = this.images.active(); 1048 if ( !image || !image.width || !this.visible ) 1049 { // No image or no visible lightbox, so we don't care 1050 $.console.warn('A resize occured while no image or no lightbox...'); 1051 return false; 1052 } 1053 1054 // Resize image box 1055 // i:image, w:window, b:box, c:current, n:new, d:difference 1056 1057 // Get image dimensions 1058 var iWidth = image.width; 1059 var iHeight = image.height; 1060 1061 // Get window dimensions 1062 var wWidth = $(window).width(); 1063 var wHeight = $(window).height(); 1064 1065 // Check if we are in size 1066 // Lightbox can take up 4/5 of size 1067 if ( this.auto_resize !== false ) 1068 { // We want to auto resize 1069 var maxWidth = Math.floor(wWidth*(4/5)); 1070 var maxHeight = Math.floor(wHeight*(4/5)); 1071 var resizeRatio; 1072 while ( iWidth > maxWidth || iHeight > maxHeight ) 1073 { // We need to resize 1074 if ( iWidth > maxWidth ) 1075 { // Resize width, then height proportionally 1076 resizeRatio = maxWidth/iWidth; 1077 iWidth = maxWidth; 1078 iHeight = Math.floor(iHeight*resizeRatio); 1079 } 1080 if ( iHeight > maxHeight ) 1081 { // Resize height, then width proportionally 1082 resizeRatio = maxHeight/iHeight; 1083 iHeight = maxHeight; 1084 iWidth = Math.floor(iWidth*resizeRatio); 1085 } 1086 } 1087 } 1088 1089 // Get current width and height 1090 var cWidth = $('#lightbox-imageBox').width(); 1091 var cHeight = $('#lightbox-imageBox').height(); 1092 1093 // Get the width and height of the selected image plus the padding 1094 // padding*2 for both sides (left+right || top+bottom) 1095 var nWidth = (iWidth + (this.padding * 2)); 1096 var nHeight = (iHeight + (this.padding * 2)); 1097 1098 // Diferences 1099 var dWidth = cWidth - nWidth; 1100 var dHeight = cHeight - nHeight; 1101 1102 // Set the overlay buttons height and the infobox width 1103 // Other dimensions specified by CSS 1104 $('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css('height', nHeight); 1105 $('#lightbox-infoBox').css('width', nWidth); 1106 1107 // Handle final action 1108 if ( type === 'transition' ) 1109 { // We are transition 1110 // Do we need to wait? (just a nice effect to counter the other 1111 if ( dWidth === 0 && dHeight === 0 ) 1112 { // We are the same size 1113 this.pause(this.speed/3); 1114 this.showImage(null, 3); 1115 } 1116 else 1117 { // We are not the same size 1118 // Animate 1119 $('#lightbox-image').width(iWidth).height(iHeight); 1120 $('#lightbox-imageBox').animate({width: nWidth, height: nHeight}, this.speed, function ( ) { $.Lightbox.showImage(null, 3); } ); 1121 } 1122 } 1123 else 1124 { // We are a resize 1125 // Animate Lightbox 1126 $('#lightbox-image').animate({width:iWidth, height:iHeight}, this.speed); 1127 $('#lightbox-imageBox').animate({width: nWidth, height: nHeight}, this.speed); 1128 } 1129 1130 // Reposition 1131 this.repositionBoxes({'nHeight':nHeight, 'speed':this.speed}); 1132 1133 // Done 1134 return true; 1135 }, 1136 1137 repositioning: false, // are we currently repositioning 1138 reposition_failsafe: false, // failsafe 1139 repositionBoxes: function ( options ) 1140 { 1141 // Prepare 1142 if ( this.repositioning ) 1143 { // Already here 1144 this.reposition_failsafe = true; 1145 return null; 1146 } 1147 this.repositioning = true; 1148 1149 // Options 1150 options = $.extend({}, options); 1151 options.callback = options.callback || null; 1152 options.speed = options.speed || 'slow'; 1153 1154 // Get page scroll 1155 var pageScroll = this.getPageScroll(); 1156 1157 // Figure it out 1158 // alert($(window).height()+"\n"+$(document.body).height()+"\n"+$(document).height()); 1159 // var nHeight = options.nHeight || parseInt($('#lightbox').height(),10) || $(document).height()/3; 1160 var nHeight = options.nHeight || parseInt($('#lightbox').height(),10); 1161 1162 // Display lightbox in center 1163 // var nTop = pageScroll.yScroll + ($(document.body).height() /*frame height*/ - nHeight) / 2.5; 1164 var nTop = pageScroll.yScroll + ($(window).height() /*frame height*/ - nHeight) / 2.5; 1165 var nLeft = pageScroll.xScroll; 1166 1167 // Animate 1168 var css = { 1169 left: nLeft, 1170 top: nTop 1171 }; 1172 if (options.speed) { 1173 $('#lightbox').animate(css, 'slow', function(){ 1174 if ( $.Lightbox.reposition_failsafe ) 1175 { // Fire again 1176 $.Lightbox.repositioning = $.Lightbox.reposition_failsafe = false; 1177 $.Lightbox.repositionBoxes(options); 1178 } 1179 else 1180 { // Done 1181 $.Lightbox.repositioning = false; 1182 if ( options.callback ) 1183 { // Call the user callback 1184 options.callback(); 1185 } 1186 } 1187 }); 1188 } 1189 else 1190 { 1191 $('#lightbox').css(css); 1192 if ( this.reposition_failsafe ) 1193 { // Fire again 1194 this.repositioning = this.reposition_failsafe = false; 1195 this.repositionBoxes(options); 1196 } 1197 else 1198 { // Done 1199 this.repositioning = false; 1200 } 1201 } 1202 1203 // Done 1204 return true; 1205 }, 1206 1207 visible: false, 1208 showImage: function ( image, step ) 1209 { 1210 // Establish image 1211 image = this.images.get(image); 1212 if ( !image ) { return image; } 1213 1214 // Default step 1215 step = step || 1; 1216 1217 // Split up below for jsLint compliance 1218 var skipped_step_1 = step > 1 && this.images.active().src !== image.src; 1219 var skipped_step_2 = step > 2 && $('#lightbox-image').attr('src') !== image.src; 1220 if ( skipped_step_1 || skipped_step_2 ) 1221 { // Force step 1 1222 $.console.info('We wanted to skip a few steps: ', image, step, skipped_step_1, skipped_step_2); 1223 step = 1; 1224 } 1225 1226 // What do we need to do 1227 switch ( step ) 1228 { 1229 // --------------------------------- 1230 // We need to preload 1231 case 1: 1232 1233 // Disable keyboard nav 1234 this.KeyboardNav_Disable(); 1235 1236 // Show the loading image 1237 $('#lightbox-loading').show(); 1238 1239 // Hide things 1240 $('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-infoBox').hide(); 1241 1242 // Remove show info events 1243 $('#lightbox-imageBox').unbind(); 1244 // ^ Why? Because otherwise when the image is changing, the info pops out, not good! 1245 1246 // Make the image the active image 1247 if ( !this.images.active(image) ) { return false; } 1248 1249 // Check if we need to preload 1250 if ( image.width && image.height ) 1251 { // We don't 1252 // Continue to next step 1253 this.showImage(null, 2); 1254 } 1255 else 1256 { // We do 1257 // Create preloader 1258 var preloader = new Image(); 1259 // Set callback 1260 preloader.onload = function() 1261 { // We have preloaded the image 1262 // Update image with our new info 1263 image.width = preloader.width; 1264 image.height = preloader.height; 1265 // Continue to next step 1266 $.Lightbox.showImage(null, 2); 1267 // Kill preloader 1268 preloader.onload = null; 1269 preloader = null; 1270 }; 1271 // Start preload 1272 preloader.src = image.src; 1273 } 1274 1275 // Done 1276 break; 1277 1278 1279 // --------------------------------- 1280 // Resize the container 1281 case 2: 1282 1283 // Apply image changes 1284 $('#lightbox-image').attr('src', image.src); 1285 $('#lightbox-image').attr('alt', image.title); 1286 1287 // Set container border (Moved here for Konqueror fix - Credits to Blueyed) 1288 if ( typeof this.padding === 'undefined' || this.padding === null || isNaN(this.padding) ) 1289 { // Autodetect 1290 this.padding = parseInt($('#lightbox-imageContainer').css('padding-left'), 10) || parseInt($('#lightbox-imageContainer').css('padding'), 10) || 0; 1291 } 1292 1293 // Use colorBlend? 1294 if ( this.colorBlend ) 1295 { // We have colorBlend
1296 // Background 1297 $('#lightbox-overlay').animate({'backgroundColor':image.color}, this.speed*2); 1298 // Border 1299 $('#lightbox-imageBox').css('borderColor', image.color); 1300 } 1301 1302 // Resize boxes 1303 this.resizeBoxes('transition'); 1304 // ^ contains callback to next step 1305 1306 // Done 1307 break; 1308 1309 1310 // --------------------------------- 1311 // Display the image 1312 case 3: 1313 1314 // Hide loading 1315 $('#lightbox-loading').hide(); 1316 1317 // Animate image 1318 $('#lightbox-image').fadeIn(this.speed*1.5, function() {$.Lightbox.showImage(null, 4); }); 1319 1320 // Start the proloading of other images 1321 this.preloadNeighbours(); 1322 1323 // Fire custom handler show 1324 if ( this.handlers.show !== null ) 1325 { // Fire it 1326 this.handlers.show(image); 1327 } 1328 1329 // Done 1330 break; 1331 1332 1333 // --------------------------------- 1334 // Set image info / Set navigation 1335 case 4: 1336 1337 // --------------------------------- 1338 // Set image info 1339 1340 // Hide and set image info 1341 var $title = $('#lightbox-caption-title').html(image.title || 'Untitled'); 1342 if ( this.download_link ) 1343 { $title.attr('href', this.download_link ? image.src : ''); } 1344 delete $title; 1345 $('#lightbox-caption-seperator').html(image.description ? ': ' : ''); 1346 $('#lightbox-caption-description').html(image.description || ' '); 1347 1348 // If we have a set, display image position 1349 if ( this.images.size() > 1 ) 1350 { // Display 1351 $('#lightbox-currentNumber').html(this.text.image + ' ' + ( image.index + 1 ) + ' ' + this.text.of + ' ' + this.images.size()); 1352 } else 1353 { // Empty 1354 $('#lightbox-currentNumber').html(' '); 1355 } 1356 1357 // --------------------------------- 1358 // Info events 1359 1360 // Apply event 1361 $('#lightbox-imageBox').unbind('mouseover').mouseover(function(){ 1362 $('#lightbox-infoBox').slideDown('fast'); 1363 }); 1364 1365 // Apply event 1366 $('#lightbox-infoBox').unbind('mouseover').mouseover(function(){ 1367 $('#lightbox-infoFooter').slideDown('fast'); 1368 }); 1369 1370 // Forced show? 1371 if ( this.show_extended_info === true ) 1372 { // Force show 1373 $('#lightbox-imageBox').trigger('mouseover'); 1374 $('#lightbox-infoBox').trigger('mouseover'); 1375 } 1376 else if ( this.show_info === true ) 1377 { // Force show 1378 $('#lightbox-imageBox').trigger('mouseover'); 1379 } 1380 1381 // --------------------------------- 1382 // Set navigation 1383 1384 // Instead to define this configuration in CSS file, we define here. And it's need to IE. Just. 1385 $('#lightbox-nav-btnPrev, #lightbox-nav-btnNext').css({ 'background' : 'transparent url(' + this.files.images.blank + ') no-repeat' }); 1386 1387 // If not first, show previous button 1388 if ( !this.images.first(image) ) { 1389 // Not first, show button 1390 $('#lightbox-nav-btnPrev').show(); 1391 } 1392 1393 // If not last, show next button 1394 if ( !this.images.last(image) ) { 1395 // Not first, show button 1396 $('#lightbox-nav-btnNext').show(); 1397 } 1398 1399 // Make navigation active / show it 1400 $('#lightbox-nav').show(); 1401 1402 // Enable keyboard navigation 1403 this.KeyboardNav_Enable(); 1404 1405 // Done 1406 break; 1407 1408 1409 // --------------------------------- 1410 // Error handling 1411 default: 1412 $.log('ERROR', 'Don\'t know what to do: ', image, step); 1413 return this.showImage(image, 1); 1414 // break; 1415 1416 } 1417 1418 // All done 1419 return true; 1420 }, 1421 1422 preloadNeighbours: function ( ) 1423 { // Preload all neighbour images 1424 1425 // Do we need to do this? 1426 if ( this.images.single() || this.images.empty() ) 1427 { return true; } 1428 1429 // Get active image 1430 var image = this.images.active(); 1431 if ( !image ) { return image; } 1432 1433 // Load previous 1434 var prev = this.images.prev(image); 1435 var objNext; 1436 if ( prev ) { 1437 objNext = new Image(); 1438 objNext.src = prev.src; 1439 } 1440 1441 // Load next 1442 var next = this.images.next(image); 1443 if ( next ) { 1444 objNext = new Image(); 1445 objNext.src = next.src; 1446 } 1447 }, 1448 1449 // -------------------------------------------------- 1450 // Things we don't really care about 1451 1452 KeyboardNav_Enable: function ( ) { 1453 $(document).keydown(function(objEvent) { 1454 $.Lightbox.KeyboardNav_Action(objEvent); 1455 }); 1456 }, 1457 1458 KeyboardNav_Disable: function ( ) { 1459 $(document).unbind(); 1460 }, 1461 1462 KeyboardNav_Action: function ( objEvent ) { 1463 // Prepare 1464 objEvent = objEvent || window.event; 1465 1466 // Get the keycode 1467 var keycode = objEvent.keyCode; 1468 var escapeKey = objEvent.DOM_VK_ESCAPE /* moz */ || 27; 1469 1470 // Get key 1471 var key = String.fromCharCode(keycode).toLowerCase(); 1472 1473 // Close? 1474 if ( key === this.keys.close || keycode === escapeKey ) 1475 { return $.Lightbox.finish(); } 1476 1477 // Prev? 1478 if ( key === this.keys.prev || keycode === 37 ) 1479 { // We want previous 1480 return $.Lightbox.showImage($.Lightbox.images.prev()); 1481 } 1482 1483 // Next? 1484 if ( key === this.keys.next || keycode === 39 ) 1485 { // We want next 1486 return $.Lightbox.showImage($.Lightbox.images.next()); 1487 } 1488 1489 // Unknown 1490 return true; 1491 }, 1492 1493 getPageScroll: function ( ) { 1494 var xScroll, yScroll; 1495 if (self.pageYOffset) 1496 { // Some browser 1497 yScroll = self.pageYOffset; 1498 xScroll = self.pageXOffset; 1499 } else if (document.documentElement && document.documentElement.scrollTop) 1500 { // Explorer 6 Strict 1501 yScroll = document.documentElement.scrollTop; 1502 xScroll = document.documentElement.scrollLeft; 1503 } else if (document.body) 1504 { // All other browsers 1505 yScroll = document.body.scrollTop; 1506 xScroll = document.body.scrollLeft; 1507 } 1508 var arrayPageScroll = {'xScroll':xScroll,'yScroll':yScroll}; 1509 return arrayPageScroll; 1510 }, 1511 1512 pause: function ( ms ) { 1513 var date = new Date(); 1514 var curDate = null; 1515 do { curDate = new Date(); } 1516 while ( curDate - date < ms); 1517 } 1518 1519 }); // We have finished extending/defining our LightboxClass 1520 1521 1522 // --------------------------------------------------
1523 // Finish up 1524 1525 // Instantiate 1526 if ( typeof $.Lightbox === 'undefined' ) 1527 { // 1528 $.Lightbox = new $.LightboxClass(); 1529 } 1530 1531// Finished definition 1532 1533})(jQuery); // We are done with our plugin, so lets call it with jQuery as the argument
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.