1/** 2 * jQuery Lightbox Plugin (balupton edition) - Lightboxes for jQuery 3 * Copyright (C) 2008 Benjamin Arthur Lupton 4 * http://jquery.com/plugins/project/jquerylightbox_bal 5 * 6 * This file is part of jQuery Lightbox (balupton edition). 7 * 8 * jQuery Lightbox (balupton edition) is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Affero General Public License as 10 * published by the Free Software Foundation, either version 3 of the 11 * License, or (at your option) any later version. 12 * 13 * jQuery Lightbox (balupton edition) is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Affero General Public License for more details. 17 * 18 * You should have received a copy of the GNU Affero General Public License 19 * along with jQuery Lightbox (balupton edition). If not, see <http://www.gnu.org/licenses/>. 20 * 21 * @name jquery_lightbox: jquery.lightbox.js 22 * @package jQuery Lightbox Plugin (balupton edition) 23 * @version 1.3.7-final 24 * @date April 25, 2009 25 * @category jQuery plugin 26 * @author Benjamin "balupton" Lupton {@link http://www.balupton.com} 27 * @copyright (c) 2008 Benjamin Arthur Lupton {@link http://www.balupton.com} 28 * @license GNU Affero General Public License - {@link http://www.gnu.org/licenses/agpl.html} 29 * @example Visit {@link http://jquery.com/plugins/project/jquerylightbox_bal} for more information. 30 */ 31 32// Start of our jQuery Plugin 33(function($) 34{ // Create our Plugin function, with $ as the argument (we pass the jQuery object over later) 35 // More info: http://docs.jquery.com/Plugins/Authoring#Custom_Alias 36 37 // Debug 38 if ( typeof $.log === 'undefined' ) { 39 if ( !$.browser.safari && typeof window.console !== 'undefined' && typeof window.console.log === 'function' ) 40 { // Use window.console 41 $.log = function(){ 42 var args = []; 43 for(var i = 0; i < arguments.length; i++) { 44 args.push(arguments[i]); 45 } 46 window.console.log.apply(window.console, args); 47 } 48 $.console = { 49 log: $.log, 50 debug: window.console.debug || $.log, 51 warn: window.console.warn || $.log, 52 error: window.console.error || $.log, 53 trace: window.console.trace || $.log 54 } 55 } 56 else 57 { // Don't use anything 58 $.log = function ( ) { }; 59 $.console = { 60 log: $.log, 61 debug: $.log, 62 warn: $.log, 63 error: alert, 64 trace: $.log 65 }; 66 } 67 } 68 69 // Pre-Req 70 $.params_to_json = $.params_to_json || function ( params ) 71 { // Turns a params string or url into an array of params 72 // Adjust 73 params = String(params); 74 // Remove url if need be 75 params = params.substring(params.indexOf('?')+1); 76 // params = params.substring(params.indexOf('#')+1); 77 // Change + to %20, the %20 is fixed up later with the decode 78 params = params.replace(/\+/g, '%20'); 79 // Do we have JSON string 80 if ( params.substring(0,1) === '{' && params.substring(params.length-1) === '}' ) 81 { // We have a JSON string 82 return eval(decodeURIComponent(params)); 83 } 84 // We have a params string 85 params = params.split(/\&|\&\;/); 86 var json = {}; 87 // We have params 88 for ( var i = 0, n = params.length; i < n; ++i ) 89 { 90 // Adjust 91 var param = params[i] || null; 92 if ( param === null ) { continue; } 93 param = param.split('='); 94 if ( param === null ) { continue; } 95 // ^ We now have "var=blah" into ["var","blah"] 96 97 // Get 98 var key = param[0] || null; 99 if ( key === null ) { continue; } 100 if ( typeof param[1] === 'undefined' ) { continue; } 101 var value = param[1]; 102 // ^ We now have the parts 103 104 // Fix 105 key = decodeURIComponent(key); 106 value = decodeURIComponent(value); 107 try { 108 // value can be converted 109 value = eval(value); 110 } catch ( e ) { 111 // value is a normal string 112 } 113 114 // Set 115 // console.log({'key':key,'value':value}, split); 116 var keys = key.split('.'); 117 if ( keys.length === 1 ) 118 { // Simple 119 json[key] = value; 120 } 121 else 122 { // Advanced 123 var path = ''; 124 for ( ii in keys ) 125 { // 126 key = keys[ii]; 127 path += '.'+key; 128 eval('json'+path+' = json'+path+' || {}'); 129 } 130 eval('json'+path+' = value'); 131 } 132 // ^ We now have the parts added to your JSON object 133 } 134 return json; 135 }; 136 137 // Declare our class 138 $.LightboxClass = function ( ) 139 { // This is the handler for our constructor 140 this.construct(); 141 }; 142 143 // Extend jQuery elements for Lightbox 144 $.fn.lightbox = function ( options ) 145 { // Init a el for Lightbox 146 // Eg. $('#gallery a').lightbox(); 147 148 // If need be: Instantiate $.LightboxClass to $.Lightbox 149 $.Lightbox = $.Lightbox || new $.LightboxClass(); 150 151 // Handle IE6 appropriatly 152 if ( $.Lightbox.ie6 && !$.Lightbox.ie6_support ) 153 { // We are IE6 and we want to ignore 154 return this; // chain 155 } 156 157 // Establish options 158 options = $.extend({start:false,events:true} /* default options */, options); 159 160 // Get group 161 var group = $(this); 162 163 // Events? 164 if ( options.events ) 165 { // Add events 166 $(group).unbind('click').click(function(){ 167 // Get obj 168 var obj = $(this); 169 // Get rel 170 // var rel = $(obj).attr('rel'); 171 // Init group 172 if ( !$.Lightbox.init($(obj)[0], group) ) 173 { return false; } 174 // Display lightbox 175 if ( !$.Lightbox.start() ) 176 { return false; } 177 // Cancel href 178 return false;
179 }); 180 // Add style 181 $(group).addClass('lightbox-enabled'); 182 } 183 184 // Start? 185 if ( options.start ) 186 { // Start 187 // Get obj 188 var obj = $(this); 189 // Get rel 190 // var rel = $(obj).attr('rel'); 191 // Init group 192 if ( !$.Lightbox.init($(obj)[0], group) ) 193 { return this; } 194 // Display lightbox 195 if ( !$.Lightbox.start() ) 196 { return this; } 197 } 198 199 // And chain 200 return this; 201 }; 202 203 // Define our class 204 $.extend($.LightboxClass.prototype, 205 { // Our LightboxClass definition 206 207 // ----------------- 208 // Everyting to do with images 209 210 images: { 211 212 // ----------------- 213 // Variables 214 215 // Our array of images 216 list:[], /* [ { 217 src: 'url to image', 218 link: 'a link to a page', 219 title: 'title of the image', 220 name: 'name of the image', 221 description: 'description of the image' 222 } ], */ 223 224 // The current active image 225 image: false, 226 227 // ----------------- 228 // Functions 229 230 prev: function ( image ) 231 { // Get previous image 232 233 // Get previous from current? 234 if ( typeof image === 'undefined' ) 235 { image = this.active(); 236 if ( !image ) { return image; } 237 } 238 239 // Is there a previous? 240 if ( this.first(image) ) 241 { return false; } 242 243 // Get the previous 244 return this.get(image.index-1); 245 }, 246 247 next: function ( image ) 248 { // Get next image 249 250 // Get next from current? 251 if ( typeof image === 'undefined' ) 252 { image = this.active(); 253 if ( !image ) { return image; } 254 } 255 256 // Is there a next? 257 if ( this.last(image) ) 258 { return false; } 259 260 // Get the next 261 return this.get(image.index+1); 262 }, 263 264 first: function ( image ) 265 { // 266 // Get the first image? 267 if ( typeof image === 'undefined' ) 268 { return this.get(0); } 269 270 // Are we the first? 271 return image.index === 0; 272 }, 273 274 last: function ( image ) 275 { // 276 // Get the last image? 277 if ( typeof image === 'undefined' ) 278 { return this.get(this.size()-1); } 279 280 // Are we the last? 281 return image.index === this.size()-1; 282 }, 283 284 single: function ( ) 285 { // Are we only one 286 return this.size() === 1; 287 }, 288 289 size: function ( ) 290 { // How many images do we have 291 return this.list.length; 292 }, 293 294 empty: function ( ) 295 { // Are we empty 296 return this.size() === 0; 297 }, 298 299 clear: function ( ) 300 { // Clear image arrray 301 this.list = []; 302 this.image = false; 303 }, 304 305 active: function ( image ) 306 { // Set or get the active image 307 // Use false to reset 308 309 // Get the active image? 310 if ( typeof image === 'undefined' ) 311 { return this.image; } 312 313 // Set the ative image 314 if ( image !== false ) 315 { // Make sure image exists 316 image = this.get(image); 317 if ( !image ) 318 { // Error 319 return image; 320 } 321 } 322 323 // Set the active image 324 this.image = image; 325 return true; 326 }, 327 328 add: function ( obj ) 329 { 330 // Do we need to recurse? 331 if ( obj[0] ) 332 { // We have a lot of images 333 for ( var i = 0; i < obj.length; i++ ) 334 { this.add(obj[i]); } 335 return true; 336 } 337 338 // Default image 339 340 // Try and create a image 341 var image = this.create(obj); 342 if ( !image ) { return image; } 343 344 // Set image index 345 image.index = this.size(); 346 347 // Push image 348 this.list.push(image); 349 350 // Success 351 return true; 352 }, 353 354 create: function ( obj ) 355 { // Create image 356 357 // Define 358 var image = { // default 359 src: '', 360 title: 'Untitled', 361 description: '', 362 name: '', 363 index: -1, 364 color: null, 365 width: null, 366 height: null, 367 image: true 368 }; 369 370 // Create 371 if ( obj.image ) 372 { // Already a image, so copy over values 373 image.src = obj.src || image.src; 374 image.title = obj.title || image.title; 375 image.description = obj.description || image.description; 376 image.name = obj.name || image.name; 377 image.color = obj.color || image.color; 378 image.width = obj.width || image.width; 379 image.height = obj.height || image.height; 380 image.index = obj.index || image.index; 381 } 382 else if ( obj.tagName ) 383 { // We are an element 384 obj = $(obj); 385 if ( obj.attr('src') || obj.attr('href') ) 386 { 387 image.src = obj.attr('src') || obj.attr('href'); 388 image.title = obj.attr('title') || obj.attr('alt') || image.title; 389 image.name = obj.attr('name') || ''; 390 image.color = obj.css('backgroundColor'); 391 // Extract description from title
392 var s = image.title.indexOf(': '); 393 if ( s > 0 ) 394 { // Description exists 395 image.description = image.title.substring(s+2) || image.description; 396 image.title = image.title.substring(0,s) || image.title; 397 } 398 } 399 else 400 { // Unsupported element 401 image = false; 402 } 403 } 404 else 405 { // Unknown 406 image = false; 407 } 408 409 if ( !image ) 410 { // Error 411 $.console.error('We dont know what we have:', obj); 412 return false; 413 } 414 415 // Success 416 return image; 417 }, 418 419 get: function ( image ) 420 { // Get the active, or specified image 421 422 // Establish image 423 if ( typeof image === 'undefined' || image === null ) 424 { // Get the active image 425 return this.active(); 426 } 427 else 428 if ( typeof image === 'number' ) 429 { // We have a index 430 431 // Get image 432 image = this.list[image] || false; 433 } 434 else 435 { // Create 436 image = this.create(image); 437 if ( !image ) { return false; } 438 439 // Find 440 var f = false; 441 for ( var i = 0; i < this.size(); i++ ) 442 { 443 var c = this.list[i]; 444 if ( c.src === image.src && c.title === image.title && c.description === image.description ) 445 { f = c; } 446 } 447 448 // Found? 449 image = f; 450 } 451 452 // Determine image 453 if ( !image ) 454 { // Image doesn't exist 455 $.console.error('The desired image does not exist: ', image, this.list); 456 return false; 457 } 458 459 // Return image 460 return image; 461 }, 462 463 debug: function ( ) 464 { 465 return $.Lightbox.debug(arguments); 466 } 467 468 }, 469 470 // ----------------- 471 // Variables 472 473 constructed: false, 474 compressed: null, 475 476 // ----------------- 477 // Options 478 479 src: null, // the source location of our js file 480 baseurl: null, 481 482 files: { 483 compressed: { 484 js: { 485 lightbox: '/js/jquery.lightbox.min.js', 486 colorBlend: '/js/jquery.color.min.js' 487 }, 488 css: { 489 lightbox: '/css/jquery.lightbox.css' 490 } 491 }, 492 uncompressed: { 493 js: { 494 lightbox: '/js/jquery.lightbox.js', 495 colorBlend: '/js/jquery.color.js' 496 }, 497 css: { 498 lightbox: '/css/jquery.lightbox.css' 499 } 500 }, 501 images: { 502 prev: '/img/prev.gif', 503 next: '/img/next.gif', 504 blank: '/img/blank.gif', 505 loading: '/img/loading.gif' 506 } 507 }, 508 509 text: { 510 // For translating 511 image: 'Image', 512 of: 'of', 513 close: 'Close X', 514 closeInfo: '', 515 download: 'Download.', 516 help: { 517 close: 'Click to close', 518 interact: 'Hover to interact' 519 }, 520 about: { 521 text: '', 522 title: '', 523 link: '' 524 } 525 }, 526 527 keys: { 528 close: 'c', 529 prev: 'p', 530 next: 'n' 531 }, 532 533 handlers: { 534 // For custom actions 535 show: null 536 }, 537 538 opacity: 0.9, 539 padding: null, // if null - autodetect 540 541 speed: 400, // Duration of effect, milliseconds 542 543 rel: 'lightbox', // What to look for in the rels 544 545 auto_relify: true, // should we automaticly do the rels? 546 547 auto_scroll: 'follow', // should the lightbox scroll with the page? follow, disabled, ignore 548 auto_resize: true, // true or false 549 550 ie6: null, // are we ie6? 551 ie6_support: true, // have ie6 support 552 ie6_upgrade: true, // show ie6 upgrade message 553 554 colorBlend: null, // null - auto-detect, true - force, false - no 555 556 download_link: true, // Display the download link 557 558 show_helper_text: true, // Display the helper text up the top right 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: ['show_helper_text', '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>':'')+(this.show_helper_text?'<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" /><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 + '" /></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').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() 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 1286 // Set container border (Moved here for Konqueror fix - Credits to Blueyed) 1287 if ( typeof this.padding === 'undefined' || this.padding === null || isNaN(this.padding) ) 1288 { // Autodetect 1289 this.padding = parseInt($('#lightbox-imageContainer').css('padding-left'), 10) || parseInt($('#lightbox-imageContainer').css('padding'), 10) || 0; 1290 } 1291 1292 // Use colorBlend? 1293 if ( this.colorBlend ) 1294 { // We have colorBlend 1295 // Background 1296 $('#lightbox-overlay').animate({'backgroundColor':image.color}, this.speed*2); 1297 // Border 1298 $('#lightbox-imageBox').css('borderColor', image.color); 1299 } 1300 1301 // Resize boxes 1302 this.resizeBoxes('transition'); 1303 // ^ contains callback to next step 1304 1305 // Done 1306 break; 1307 1308 1309 // --------------------------------- 1310 // Display the image 1311 case 3: 1312 1313 // Hide loading 1314 $('#lightbox-loading').hide(); 1315 1316 // Animate image 1317 $('#lightbox-image').fadeIn(this.speed*1.5, function() {$.Lightbox.showImage(null, 4); }); 1318 1319 // Start the proloading of other images 1320 this.preloadNeighbours(); 1321 1322 // Fire custom handler show 1323 if ( this.handlers.show !== null ) 1324 { // Fire it 1325 this.handlers.show(image); 1326 } 1327 1328 // Done 1329 break; 1330 1331 1332 // --------------------------------- 1333 // Set image info / Set navigation 1334 case 4: 1335 1336 // --------------------------------- 1337 // Set image info 1338 1339 // Hide and set image info 1340 var $title = $('#lightbox-caption-title').html(image.title || 'Untitled'); 1341 if ( this.download_link ) 1342 { $title.attr('href', this.download_link ? image.src : ''); } 1343 delete $title; 1344 $('#lightbox-caption-seperator').html(image.description ? ': ' : ''); 1345 $('#lightbox-caption-description').html(image.description || ' '); 1346 1347 // If we have a set, display image position 1348 if ( this.images.size() > 1 ) 1349 { // Display 1350 $('#lightbox-currentNumber').html(this.text.image + ' ' + ( image.index + 1 ) + ' ' + this.text.of + ' ' + this.images.size()); 1351 } else 1352 { // Empty 1353 $('#lightbox-currentNumber').html(' '); 1354 } 1355 1356 // --------------------------------- 1357 // Info events 1358 1359 // Apply event 1360 $('#lightbox-imageBox').unbind('mouseover').mouseover(function(){ 1361 $('#lightbox-infoBox:not(:visible)').stop().slideDown('fast'); 1362 }); 1363 1364 // Apply event 1365 $('#lightbox-infoBox').unbind('mouseover').mouseover(function(){ 1366 $('#lightbox-infoFooter:not(:visible)').stop().slideDown('fast'); 1367 }); 1368 1369 // Forced show? 1370 if ( this.show_extended_info === true ) 1371 { // Force show 1372 $('#lightbox-imageBox').trigger('mouseover'); 1373 $('#lightbox-infoBox').trigger('mouseover'); 1374 } 1375 else if ( this.show_info === true ) 1376 { // Force show 1377 $('#lightbox-imageBox').trigger('mouseover'); 1378 } 1379 1380 // --------------------------------- 1381 // Set navigation 1382 1383 // Instead to define this configuration in CSS file, we define here. And it's need to IE. Just. 1384 $('#lightbox-nav-btnPrev, #lightbox-nav-btnNext').css({ 'background' : 'transparent url(' + this.files.images.blank + ') no-repeat' }); 1385 1386 // If not first, show previous button 1387 if ( !this.images.first(image) ) { 1388 // Not first, show button 1389 $('#lightbox-nav-btnPrev').show(); 1390 } 1391 1392 // If not last, show next button 1393 if ( !this.images.last(image) ) { 1394 // Not first, show button 1395 $('#lightbox-nav-btnNext').show(); 1396 } 1397 1398 // Make navigation active / show it 1399 $('#lightbox-nav').show(); 1400 1401 // Enable keyboard navigation 1402 this.KeyboardNav_Enable(); 1403 1404 // Done 1405 break; 1406 1407 1408 // --------------------------------- 1409 // Error handling 1410 default: 1411 $.console.error('Don\'t know what to do: ', image, step); 1412 return this.showImage(image, 1); 1413 // break; 1414 1415 } 1416 1417 // All done 1418 return true; 1419 }, 1420 1421 preloadNeighbours: function ( ) 1422 { // Preload all neighbour images 1423 1424 // Do we need to do this? 1425 if ( this.images.single() || this.images.empty() ) 1426 { return true; } 1427 1428 // Get active image 1429 var image = this.images.active(); 1430 if ( !image ) { return image; } 1431 1432 // Load previous 1433 var prev = this.images.prev(image); 1434 var objNext; 1435 if ( prev ) { 1436 objNext = new Image(); 1437 objNext.src = prev.src; 1438 } 1439 1440 // Load next 1441 var next = this.images.next(image); 1442 if ( next ) { 1443 objNext = new Image(); 1444 objNext.src = next.src; 1445 } 1446 }, 1447 1448 // -------------------------------------------------- 1449 // Things we don't really care about 1450 1451 KeyboardNav_Enable: function ( ) { 1452 $(document).keydown(function(objEvent) { 1453 $.Lightbox.KeyboardNav_Action(objEvent); 1454 }); 1455 }, 1456 1457 KeyboardNav_Disable: function ( ) { 1458 $(document).unbind('keydown'); 1459 }, 1460 1461 KeyboardNav_Action: function ( objEvent ) { 1462 // Prepare 1463 objEvent = objEvent || window.event; 1464 1465 // Get the keycode 1466 var keycode = objEvent.keyCode; 1467 var escapeKey = objEvent.DOM_VK_ESCAPE /* moz */ || 27; 1468 1469 // Get key 1470 var key = String.fromCharCode(keycode).toLowerCase(); 1471 1472 // Close? 1473 if ( key === this.keys.close || keycode === escapeKey ) 1474 { return $.Lightbox.finish(); } 1475 1476 // Prev? 1477 if ( key === this.keys.prev || keycode === 37 ) 1478 { // We want previous 1479 return $.Lightbox.showImage($.Lightbox.images.prev()); 1480 } 1481 1482 // Next? 1483 if ( key === this.keys.next || keycode === 39 ) 1484 { // We want next 1485 return $.Lightbox.showImage($.Lightbox.images.next()); 1486 } 1487 1488 // Unknown 1489 return true; 1490 }, 1491 1492 getPageScroll: function ( ) { 1493 var xScroll, yScroll; 1494 if (self.pageYOffset) 1495 { // Some browser 1496 yScroll = self.pageYOffset; 1497 xScroll = self.pageXOffset; 1498 } else if (document.documentElement && document.documentElement.scrollTop) 1499 { // Explorer 6 Strict 1500 yScroll = document.documentElement.scrollTop; 1501 xScroll = document.documentElement.scrollLeft; 1502 } else if (document.body) 1503 { // All other browsers 1504 yScroll = document.body.scrollTop; 1505 xScroll = document.body.scrollLeft; 1506 } 1507 var arrayPageScroll = {'xScroll':xScroll,'yScroll':yScroll}; 1508 return arrayPageScroll; 1509 }, 1510 1511 pause: function ( ms ) { 1512 var date = new Date(); 1513 var curDate = null; 1514 do { curDate = new Date(); } 1515 while ( curDate - date < ms); 1516 } 1517 1518 }); // We have finished extending/defining our LightboxClass 1519 1520 1521 // --------------------------------------------------
1522 // Finish up 1523 1524 // Instantiate 1525 if ( typeof $.Lightbox === 'undefined' ) 1526 { // 1527 $.Lightbox = new $.LightboxClass(); 1528 } 1529 1530// Finished definition 1531 1532})(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.