/** * ContentONE Lightbox * * Opens a lightbox container and does one of the following: * - displays thumbnails and large images determined from href of provided links. * - displays href of provided links in an iframe. * * The height of the content in the lightbox is dynamically determined based on * the available screen real estate. * * Lightbox based off jquery-lightbox plugin by Leandro Vieira Pinho - http://leandrovieira.com. * * @version 1.2 * @date April 26, 2012 * @copyright (c) World Web Management Services (http://www.worldwebms.com/) */ (function($) { var no_refresh = false; /** * Create C1 jQuery extension. */ if( !$.fn.c1 ) { $.fn.c1 = function( name, options ) { if( this.c1[name] ) return this.c1[name].call( this, options ); return this; } } /** * Create C1 Lightbox jQuery extension. */ $.fn.c1.lightbox = function( options ) { var t = this; // If the options is a string, then execute a function if( typeof options == 'string' ) { switch( options ) { case 'close': no_refresh = false; var close = $('#c1-lightbox-close a'); close.click(); return close.length > 0; case 'close-noRefresh': no_refresh = true; var close = $('#c1-lightbox-close a'); close.click(); return close.length > 0; } return this; } // Setup the default options options = $.extend( { // Lightbox settings speed: 'normal', // Animation speed thumbs: true, // True to display thumbnail images thumbWidth: 90, // Width of lightbox thumbnail images thumbHeight: 60, // Height of lightbox thumbnail images captions: true, // True to display image captions html: false, // True to indicate captions are html based download: false, // True to display "Download Image" link in caption area imageMode: '', // Mode for images (use crop for full screen) track: '', // Enable tracking by default hide: 'embed, object, select, iframe', // Elements to hide when the lightbox is opened type: 'normal', // Type of gallery behaviour // Custom content settings api: false, // If supplied, then contains profile of api call close: true, // If supplied, then true shows close button, false hides close button inline: false, // If supplied, the selector for inline content iframe: false, // If true then the links will be opened in an iframe load: false, // If supplied, a function to generate the content with upon load unload: false, // If supplied, a callback function before the lightbox is closed map: false, // If supplied, the map information width: false, // If supplied, this is the maximum width of the lightbox height: false, // If supplied, this is the maximum height of the lightbox minWidth: false, // If supplied, this is the minimum width of the lightbox minHeight: false, // If supplied, this is the maximum height of the lightbox fixedWidth: false, // If supplied, then the width of the lightbox will match the width fixedHeight: false, // If supplied, then the height of the lightbox will match the height // Overlay settings overlayBgColor: '#000', // Background colour of overlay overlayOpacity: 0.75 // Overlay opacity }, options ); // If there is a map if( options.map ) { // Ensure the C1 maps api has been loaded if( $.fn.c1.maps ) { // Used to intercept close events var closeMap = true; var unloadMap = function() { GUnload(); }; // Setup the lightbox options.inline = true; // Set default zoom level if( options.map.zoom == null ) options.map.zoom = 13; // Add callback to generate the map options.onopen = function() { $(this).c1( 'maps', options.map ); } // Display error } else { alert('Lightbox: Please load the c1.maps API'); } // If there is inline content } else if( options.api || options.inline ) { // Set inline flag if( options.api && options.inline == false ) options.inline = true; // Add placeholder function so the lightbox behaves in custom content mode if( !options.onopen ) { options.onopen = function() { // Load content from an API call if( options.api ) { $.c1.api( { 'module': options.api.module, 'controller': options.api.controller, 'method': options.api.method, 'data': jQuery.isFunction( options.api.params ) ? options.api.params.call( options._source ) : options.api.params, 'success': function( data ) { if( options.api.result ) data.html = options.api.result( data ); if( data.html ) { $('#c1-lightbox-content').html( data.html ); $('#c1-lightbox')[ options.touch ? 'show' : 'fadeIn' ](); _resize_interface(); return; } $('#c1-lightbox-close a').click(); } }); // Display video. // Remove instance of video to ensure it doesn't open again. } else if( options.video ) { $('#' + options.video.id).c1('video', options.video); options.video = null; } }; } // Add the content only after the lightbox is fully visible options.onafterfadein = function() { // As we hide embedded content in the _start function, we want // to show the embedded content that is in the inline element if( !options.api ) { if( options.autoHeight ) $('#c1-lightbox-images').css('height', 'auto'); $(options.hide, options.inline).css( 'visibility', 'visible' ); $('#c1-lightbox-content').append( $(options.inline).children() ); $(options.inline).trigger( 'c1.lightbox.open' ); } }; // Add callback to revert the content if( options.onclose ) options._onclose = options.onclose; options.onclose = function() { if( options._onclose ) options._onclose.call( this ); if( !options.api ) $(options.inline).append( $('#c1-lightbox-content').children() ); }; // If a sprite based 360 gallery } else if( options.type == 'sprite' ) { options._sprite = { 'start': function( event ) { options._sprite.x = event.pageX; options._sprite.p = options.position; $('body') .bind( 'mousemove', options._sprite.update ) .bind( 'mouseup', options._sprite.finish ); }, 'update': function( event ) { var diff = options._sprite.x - event.pageX; var shift = Math.floor( diff / 10 ) % options.images.length; var pos = options._sprite.p + shift; if( pos < 0 ) pos += options.images.length; else if( pos >= options.images.length ) pos -= options.images.length; _show_image( pos ); }, 'finish': function() { $('body') .unbind( 'mousemove', options._sprite.update ) .unbind( 'mouseup', options._sprite.finish ); } }; options.thumbs = false; } // If in iframe or custom content mode, ensure there is a width and height if( options.iframe || options.onopen ) { if( !options.width ) options.width = 1000; else if( !options.resize ) options.fixedWidth = true; if( !options.height ) options.height = 750; options.thumbs = false; if( options.onopen ) options.captions = false; } // Declare variables var preloader, preloadNext, preloadPrev, loadingTimeout = null; // Get the image urls var captions = false; if( !options.iframe && !options.onopen && !options.inline ) { if( options.images == null ) { options.images = []; options.imageCaptions = []; for( var i = 0; i < this.length; i++ ) { options.images.push( $(this[i]).attr( 'href' ) ); options.imageCaptions.push( this[i].title ); if( this[i].title ) captions = true; } if( options.images.length <= 1 ) options.thumbs = false; } // Get the urls } else { options.urls = []; options.urlCaptions = []; for( var i = 0; i < this.length; i++ ) { options.urls.push( $(this[i]).attr( 'href' ) ); options.urlCaptions.push( this[i].title ); if( this[i].title ) captions = true; } } // Remove captions if there are none if( captions == false ) options.captions = false; // Remove padding if there are no thumbs or captions if( !options.inline && !options.thumbs && !options.captions && !options.images ) options.className = ( options.className || '' ) + ' nopadding'; // Add default tracking if( options.track === '' ) { if( options.map ) options.track = 'Map'; else if( options.images ) options.track = 'Gallery'; else options.track = 'General'; } /** * Sends out all queued events. */ var track_queue = []; var track_timeout = null; function _track_send() { clearTimeout( track_queue ); for( var i = 0; i < track_queue.length; i++ ) $(document).c1( 'analytics', track_queue[i] ); track_queue = []; } /** * Records an event. */ function _track_event( action, url, position, clear ) { clearTimeout( track_timeout ); if( options.track ) { // Remove all existing events if( clear ) track_queue = []; // Queue the event track_queue.push( { 'type': 'lightbox', 'action': action, 'track': options.track, 'target': t, 'position': position, 'url': url } ); // Send the event instantly if required if( action == 'Open' || action == 'Close' ) _track_send(); else track_timeout = setTimeout( _track_send, 500 ); } } /** * Closes the window when back button is pressed. */ function _hash_change() { if (window.location.hash == '') { $('#c1-lightbox-close a').click(); } } /** * Starts the lightbox effect * @param object objClicked The element that was clicked to open the lightbox */ function _start( objClicked ) { // Hide some elements to avoid conflict with overlay in IE. These elements appear above the overlay. $(options.hide).css( {'visibility': 'hidden'} ); // If a mobile device, remove most animations options.touch = window.C1Device && window.C1Device.touch; // Check if lightbox should not be opened. // There are issues on touch devices with scrolling the contents // of iframes, especially PDF documents. If found to be a // touch device and linking to any file then the lightbox // will be cancelled. if( options.iframe && options.touch ) { var extension = $(objClicked).attr( 'href' ).match( /\.[a-z]+$/ ); if( extension ) return true; } // Force full screen if touch capable device if( options.touch && ( options.images || options.map ) ) options.fullscreen = true; // Force dark display if images else if( options.images && options.className == null ) options.className = 'dark'; // Fullscreen mode if( options.fullscreen ) { options.className = ( options.className || '' ) + ' dark'; if( options.touch ) options.download = '[full size]'; options.count = true; } // Create the interface options.position = null; options._source = objClicked; _create_interface(); options._init = true; // Remove preload variables preload = null; // Display the selected image var position = 0; if( options.images ) { var href = $(objClicked).attr( 'href' ); for( var i = options.images.length - 1; i >= 0; i-- ) { if( options.images[i] == href ) { position = i; break; } } _show_image( position ); // Display the selected link in an iframe } else if( options.iframe ) { var href = $(objClicked).attr( 'href' ); for( var i = options.urls.length - 1; i >= 0; i-- ) { if( options.urls[i] == href ) { position = i; break; } } _show_iframe( position ); // Display the custom content } else if( options.onopen ) { options.onopen.call( $('#c1-lightbox-content').get( 0 ), options ); } // Track opens $(this).c1( 'analytics', { 'tracked': objClicked } ); _track_event( 'Open', '', position ); // Detect if hashchange is available if (options.close && window.addEventListener) { window.addEventListener('hashchange', _hash_change, false); window.location.hash = 'lightbox-open'; } return false; }; /** * Determines the thumb and image sizes based on the current screen resolution. */ function _detect_sizes( hide ) { // Reset the content size var pageSizes = ___getPageSize(); var pageScroll = ___getPageScroll(); // Determine content size and detect automatic height options.contentSize = ( options.images ? _get_url_dimensions( options.images[0] ) : { width: options.width, height: options.height } ); options.autoHeight = options.contentSize.height == 'auto'; if( options.autoHeight ) options.contentSize.height = 0; // Convert percentage based heights var perc_regex = /^(\d+)\%$/; var perc_width = false; if( result = perc_regex.exec( '' + options.contentSize.width ) ) { options.contentSize.width = Math.floor( pageSizes[2] * ( result[1] / 100 ) ); perc_width = true; } var perc_height = false; if( result = perc_regex.exec( '' + options.contentSize.height ) ) { options.contentSize.height = Math.floor( pageSizes[3] * ( result[1] / 100 ) ); perc_height = true; } // Determine size of padding surrounding lightbox for larger resolutions if( pageSizes[2] >= 500 ) { options._rounding = 50; options._padding = Math.round( pageSizes[3] / 320 ) * ( options._rounding / 2 ); // Determine size of padding surrounding lightbox for smaller resolutions } else { options._rounding = 10; options._padding = 10; } // Ensure padding is not too low if( options._padding < options._rounding ) options._padding = options._rounding; // If full screen if( options.fullscreen ) { // Fill the screen options.contentSize.width = pageSizes[2] - options._lightboxSize.width; options.contentSize.height = pageSizes[3] - options._lightboxSize.height; // If not full screen } else { // If the resulting lightbox is higher than the allowed size if( !options.autoHeight && ( options.contentSize.height + options._lightboxSize.height + ( options._padding * 2 ) ) >= pageSizes[3] ) { var newHeight = Math.ceil( Math.ceil( ( pageSizes[3] - ( options._padding * 2 ) - options._lightboxSize.height ) / options._rounding ) * options._rounding ); if( !perc_width && !options.fixedWidth ) options.contentSize.width = Math.ceil( options.contentSize.width * ( newHeight / options.contentSize.height ) ); if( !options.fixedHeight ) options.contentSize.height = newHeight; } // If the resulting lightbox is wider than the allowed size if( ( !options.fixedWidth || options.fixedWidth && options.width > ( pageSizes[2] - options._padding * 2 ) ) && ( options.contentSize.width + options._lightboxSize.width + ( options._padding * 2 ) ) >= pageSizes[2] ) { var newWidth = Math.ceil( Math.ceil( ( pageSizes[2] - ( options._padding * 2 ) - options._lightboxSize.width ) / options._rounding ) * options._rounding ); if( !perc_height && !options.fixedHeight && !options.autoHeight ) options.contentSize.height = Math.ceil( options.contentSize.height * ( newWidth / options.contentSize.width ) ); options.contentSize.width = newWidth; } // Ensure width is above the minimum if( !options.fixedWidth && options.minWidth && options.contentSize.width < options.minWidth ) options.contentSize.width = options.minWidth; // If height should be automatically determined then move the // content in to the container and snap shot the size if( options.autoHeight && typeof options.inline === 'string' ) { $('#c1-lightbox').css('width', options.contentSize.width + options._lightboxSize.width + 'px'); var move_content = $('#c1-lightbox-content').children().length == 0; if( move_content ) $('#c1-lightbox-content').append( $(options.inline).children() ); options.contentSize.height = $('#c1-lightbox-content').height(); if( move_content ) $(options.inline).append( $('#c1-lightbox-content').children() ); } // Ensure height is above minimum if( !options.fixedHeight && !options.autoHeight && options.minHeight && options.contentSize.height < options.minHeight ) options.contentSize.height = options.minHeight; } // Determine new height var width = options.contentSize.width + options._lightboxSize.width; var height = options.contentSize.height + options._lightboxSize.height; // Style content if( options.contentSize.height > 0 ) { $('#c1-lightbox-images').css( { // width: options.contentSize.width + 'px', - disabled as sometimes lightbox width is calculated differently height: options.contentSize.height + 'px' } ); } // Calculate offset and width of the lightbox and show it $('#c1-lightbox').css( { top: pageScroll[1] + ( pageSizes[3] / 2 ) - ( height / 2 ), left: pageScroll[0] + ( pageSizes[2] / 2 ) - ( width / 2 ), width: width + 'px', // height: height + 'px' - disabled as IE calculates lightbox height bigger than FF display: hide ? 'none' : 'block' } ); }; var prevPosition = null; /** * Resizes the interface. */ function _resize_interface() { // Determine screen size var pageSizes = ___getPageSize(); var pageScroll = ___getPageScroll(); var lightbox = $('#c1-lightbox'); // Proceed if values have changed. // The iPhone was triggering resize events even when nothing changed. var pos = pageSizes[2] + 'x' + pageSizes[3] + ' ' + pageScroll[0] + ', ' + pageScroll[1]; if( pos == prevPosition ) return; prevPosition = pos; // Reset lightbox if full screen or if lightbox is now outside the screen boundaries if( options.fullscreen || ( pageSizes[2] < lightbox.width() ) || ( pageSizes[3] < lightbox.height() ) ) { _detect_sizes(); if( options.images ) _show_image( options.position, true ); // Move the lightbox into the middle of the screen } else { lightbox.css( { top: pageScroll[1] + ( pageSizes[3] / 2 ) - ( lightbox.height() / 2 ), left: pageScroll[0] + ( pageSizes[2] / 2 ) - ( lightbox.width() / 2 ) } ); } // Change the dimensions of the overlay $('#c1-lightbox-overlay').css( { width: pageSizes[0], height: pageSizes[1] } ); }; /** * Builds the interface. * @param integer The */ function _create_interface() { // Add the HTML $('body').append( '
' + '
' + '
' + ( options.thumbs ? '
' : '' ) + '
' + '
' + '' + '' + '
' + ( ( options.captions || options.download ) ? ( '
' + ( options.count ? '
' : '' ) + ( options.download ? '' : '' ) + '
' ) : '' ) + '
' ); // Get page sizes var pageSizes = ___getPageSize(); // Style overlay and show it $('#c1-lightbox-overlay').css( { backgroundColor: options.overlayBgColor, opacity: options.overlayOpacity, width: pageSizes[0], height: pageSizes[1] } )[ options.touch ? 'show' : 'fadeIn' ](); // Hide close button if( options.close == false ) $('#c1-lightbox-close').hide(); // Force the width of the content to be zero // Sometimes IE was making the content be full screen width (inRent Redemptions). // @todo The cause is unknown so this is added as a workaround. if( !options.images ) $('#c1-lightbox-content').css( 'width', '0px' ); // Adjust the height of thumbnails if screen resolution is too small if( !options._init && pageSizes[2] < 500 ) { options.thumbWidth = Math.floor( options.thumbWidth * 0.5 ); options.thumbHeight = Math.floor( options.thumbHeight * 0.5 ); } // Get a handle on the lightbox var lightbox = $('#c1-lightbox'); if( options.images ) $('#c1-lightbox-thumbs ul li a').height( options.thumbHeight ).width( 1 ); options._lightboxSize = { width: lightbox.width() - ( options.images ? 1 : 0 ), height: lightbox.height() }; lightbox.addClass( 'init' ); // Reset the width of the content if( !options.images ) $('#c1-lightbox-content').css( 'width', 'auto' ); // Detect content size _detect_sizes( true ); if( !options.api ) { if( options.touch ) { $('#c1-lightbox').show(); if( options.onafterfadein ) options.onafterfadein.call( $('#c1-lightbox-content').get( 0 ), options ); } else { $('#c1-lightbox').fadeIn( function() { if( options.onafterfadein ) options.onafterfadein.call( $('#c1-lightbox-content').get( 0 ), options ); } ); } } // Add thumbnails if( options.thumbs ) _create_thumbs(); // Add show/hide thumbs event $('#c1-lightbox-thumbs-icon').click( function() { var thumbs = $('#c1-lightbox-thumbs'); $('#c1-lightbox-thumbs').toggleClass( 'hidden' ); } ); // Add next and previous thumbs events $('#c1-lightbox-thumbs-prev').click( function() { _scroll_thumbs( -1 ); return false; } ); $('#c1-lightbox-thumbs-next').click( function() { _scroll_thumbs( 1 ); return false; } ); // Add next and previous button event $('#c1-lightbox-image-prev').click( function() { if( options.images ) _show_image( options.position - 1 ); else if( options.iframe ) _show_iframe( options.position - 1 ); _track_event( 'Prev', '', options.position + 1 ); return false; } ); $('#c1-lightbox-image-next').click( function() { if( options.images ) _show_image( options.position + 1 ); else if( options.iframe ) _show_iframe( options.position + 1 ); _track_event( 'Next', '', options.position + 1 ); return false; } ); // Do not close the lightbox when download link clicked $('#c1-lightbox-download').click( function() { var href = this.href; if( options.download == 'original' ) href = _get_media_url( href ); if( options.touch ) window.location = href; else window.open( href ); return false; } ).show(); // Close lightbox on click $('#c1-lightbox-close a' + (options.close ? ', #c1-lightbox-overlay' : '')).click( function() { if( options.cancelClose ) { options.cancelClose = null; return false; } // Track close stats only if close was successful if( _finish() ) _track_event( 'Close' ); return false; } ); // Add touch gesture support to change images if( options.images && $.fn.c1.touch ) { // Add touch support to the lightbox container $('#c1-lightbox').c1( 'touch', { 'options': { 'prevent_default': true, // Stop scrolling of content 'swipe_velocity': 0.3 // Make swipes detected better }, // Handle swipes 'swipeleft swiperight swipeup swipedown': function( e ) { // Determine direction var dir = 0; if( e.type == 'swipeleft' || e.type == 'swipedown' ) dir = 1; else if( e.type == 'swiperight' || e.type == 'swipeup' ) dir = -1; // Show next image if( dir != 0 ) { if( options.images ) _show_image( options.position + dir ); else if( options.iframe ) _show_iframe( options.position + dir ); } }, // As preventing default events then need to convert tap events // to click events 'tap': function( e ) { var el = $(e.target); if( el.is( 'a' ) ) { el.click(); return false; } }, // Force double click events anything that isn't an anchor // as users might double click a link to perform an action. 'doubletap': function( e ) { if( !$(e.target).is( 'a' ) ) { $('#c1-lightbox-close a').click(); return false; } } } ); } // If inline content is shown, then stop clicking within the content to close the lightbox if( options.inline ) { $('#c1-lightbox-content').click( function( event ) { event.stopPropagation(); } ); } // If window was resized, calculate the new overlay dimensions $(window).resize( _resize_interface ).scroll( _resize_interface ); }; /** * Creates the thumbnails. */ function _create_thumbs() { // If there are no thumbnails, bomb out if( !options.images ) return; // Add thumbnail elements var list = $('#c1-lightbox-thumbs ul').empty(); for( var i = 0; i < options.images.length; i++ ) { var url = _get_thumb_url( options.images[i], options.thumbWidth, options.thumbHeight, 'crop' ); $( '
  • ' ).appendTo( list ).find( 'a' ).css( { 'background-image': 'url(' + url + ')', 'width': options.thumbWidth + 'px', 'height': options.thumbHeight + 'px' } ).data( 'pos', i ); } // Determine thumbnail scroll width options.thumbsListWidth = 0; $('li', list).each( function() { options.thumbsListWidth += $(this).outerWidth(); } ); // If scrolling should be enabled options.thumbsScrollWidth = $('#c1-lightbox-thumbs-scroll').width(); if( options.thumbsScrollWidth < options.thumbsListWidth ) { list.width( options.thumbsListWidth ); var listOffset = $('#c1-lightbox-thumbs-scroll ul').offset(); var itemOffset = $('#c1-lightbox-thumbs-scroll li:first-child').offset(); options.thumbsBounds = {left: listOffset.left - itemOffset.left}; options.thumbsBounds.right = options.thumbsBounds.left - options.thumbsListWidth + options.thumbsScrollWidth; list.css( 'left', options.thumbsBounds.left + 'px' ); } // Add click events to show the image $('li a', list).click( function() { var position = $(this).data( 'pos' ); _show_image( position ); _track_event( 'Thumbnail', '', position + 1 ); return false; } ); // Add mouse over event to track when cursor if over top 25% of interface $('#c1-lightbox').mousemove(function(event) { var offset = $(this).offset(); var height = $(this).outerHeight(); var chunk = height / 3; var classname = ''; if (event.pageY < (offset.top + chunk)) { classname = 'hover-top'; } else if (event.pageY < (offset.top + (chunk * 2))) { classname = 'hover-middle'; } else { classname = 'hover-bottom'; } $('#c1-lightbox').removeClass('hover-top hover-middle hover-bottom').addClass(classname); }); }; /** * Scrolls the thumbnail area by half. * @param integer direction The direction to scroll */ function _scroll_thumbs( direction ) { var list = $('#c1-lightbox-thumbs-scroll ul'); var pos = Math.floor( parseInt( list.css( 'left' ) ) - ( options.thumbsScrollWidth / 2 * direction ) ); if( pos < options.thumbsBounds.right ) pos = options.thumbsBounds.right; else if( pos > options.thumbsBounds.left ) pos = options.thumbsBounds.left; list.animate( {left: pos + 'px'}, 'slow' ); $('#c1-lightbox-thumbs-prev')[pos == options.thumbsBounds.left ? 'hide' : 'show'](); $('#c1-lightbox-thumbs-next')[pos == options.thumbsBounds.right ? 'hide' : 'show'](); } /** * Shows a link within an iframe. * @param integer position The position to show */ function _show_iframe( position ) { // Get the url if( position < 0 || position == null || position >= options.urls.length ) position = 0; url = options.urls[position]; if( !url ) return; // Add URL suffix if required if( options.suffix ) { if( options.suffix.substr( 0, 1 ) == '?' && url.indexOf( '?' ) >= 0 ) url += '&' + options.suffix.substr( 1 ); else url += options.suffix; } // Allow scrolling of content within iframe if a touch device if( options.touch ) { $('#c1-lightbox-content').css( { 'overflow': 'auto', '-webkit-overflow-scrolling': 'touch' } ); } // Get the iframe var iframe = $('#c1-lightbox-content iframe'); if( iframe.length == 0 ) iframe = $( '' ).appendTo( '#c1-lightbox-content' ); // Change the src attribute of the iframe iframe.attr( 'src', url ); // Update the caption if( options.html ) $('#c1-lightbox-caption > span').html( options.urlCaptions[position] ); else $('#c1-lightbox-caption > span').text( options.urlCaptions[position] ); // Update the next/previous links if( options.urls.length > 1 ) { $('#c1-lightbox-image-prev')[position == 0 ? 'hide' : 'show'](); $('#c1-lightbox-image-next')[position == ( options.urls.length - 1 ) ? 'hide' : 'show'](); } // Update the position count options.position = position; // Track the open _track_event( 'URL', url, position + 1, true ); }; /** * Preloads the images. */ function _preload_images() { // Preload all images for sprite animations. if( options._sprite ) { if( options._sprite.p == null ) { options._sprite.p = []; // To ensure images are loaded in the order they are displayed // load images from the start and end at the same time. var first = 0; var last = options.images.length - 1; for (var i = 0; i < last; i++) { options._sprite.p[first] = new Image(); options._sprite.p[first].src = _get_thumb_url( options.images[first], options.contentSize.width, options.contentSize.height, options.imageMode ); options._sprite.p[last] = new Image(); options._sprite.p[last].src = _get_thumb_url( options.images[last], options.contentSize.width, options.contentSize.height, options.imageMode ); first++; last--; } } // Preload neighbours } else { if( preloadPrev == null ) preloadPrev = new Image(); if( options.position > 0 ) preloadPrev.src = _get_thumb_url( options.images[options.position - 1], options.contentSize.width, options.contentSize.height, options.imageMode ); if( preloadNext == null ) preloadNext = new Image(); if( options.position < ( options.images.length - 1 ) ) preloadNext.src = _get_thumb_url( options.images[options.position + 1], options.contentSize.width, options.contentSize.height, options.imageMode ); } }; /** * Displays loading screen. */ function _loading_screen() { var existing = $('#c1-lightbox-image div'); var image = $('').appendTo('#c1-lightbox-image'); if( existing.length != 0 ) { existing.stop(); image.fadeIn( options.speed, function() { existing.remove(); } ); } else { image.show(); } } /** * Shows a specific image. * @param integer position The position to show */ function _show_image( position, force ) { // Fix out of bounds if( position < 0 ) position = options.images.length - 1; else if( position >= options.images.length ) position = 0; // Do not show existing image if( options.position == position && !force ) return; // Determine source of next image var src = _get_thumb_url( options.images[position], options.contentSize.width, options.contentSize.height, options.imageMode ); // If displaying a sprite then instantly display the image if( options._sprite ) { var container = $('#c1-lightbox-image div'); if( container.length == 0 ) { container = $('
    ').appendTo( '#c1-lightbox-image' ).css( { 'cursor': 'move' } ); container.mousedown( options._sprite.start ); } container.css( 'background-image', 'url(' + src + ')' ); if( position == 0 ) _preload_images(); // Display next image with the potential for a loading screen } else { // Set a timeout to display the loading screen clearTimeout( loadingTimeout ); loadingTimeout = window.setTimeout( _loading_screen, 250 ); // Initialize preloaders if( preloader == null ) { preloader = new Image(); preloader.onload = function() { // Stop loading screen from showing window.clearTimeout( loadingTimeout ); // Display the image var existing = $('#c1-lightbox-image div'); var image = $('
    ').appendTo( '#c1-lightbox-image' ).css( 'background-image', 'url(' + this.src + ')' ); if( existing.length == 0 || options.touch ) { existing.remove(); image.show(); _preload_images(); } else { existing.stop(); image.fadeIn( options.speed, function() { existing.remove(); _preload_images(); } ); } } } // Load the image if( preloader.src == src ) preloader.onload(); else preloader.src = src; // Update the count if( options.count ) $('#c1-lightbox-count').text( ( position + 1 ) + ' of ' + options.imageCaptions.length ); // Update the caption. // If there is no caption we need to add a non breaking space to ensure // the caption block is rendered correctly in "dark" mode. if( options.html || options.imageCaptions[position] == '' ) $('#c1-lightbox-caption > span').html( options.imageCaptions[position] ? options.imageCaptions[position] : ' ' ); else $('#c1-lightbox-caption > span').text( options.imageCaptions[position] ); // Update the download link $('#c1-lightbox-download').attr( 'href', options.images[position] ); // Highlight the thumbnail if( $('#c1-lightbox-thumbs:visible').length > 0 ) { $('#c1-lightbox-thumbs li.active').removeClass( 'active' ); var thumb = $($('#c1-lightbox-thumbs li').get( position )).addClass( 'active' ); if( thumb.length > 0 && options.thumbsBounds ) { // Get the scrolling details var scroll = $('#c1-lightbox-thumbs-scroll').offset(); scroll.right = scroll.left + $('#c1-lightbox-thumbs-scroll').width(); var bounds = thumb.offset(); // Ensure the thumbnail is in the center of the lightbox var shift = Math.floor( scroll.left + ( ( scroll.right - scroll.left ) / 2 ) - ( thumb.width() / 2 ) ) - bounds.left; // If the list needs to be shifted var left = ( parseInt( $('#c1-lightbox-thumbs ul').css( 'left' ) ) + shift ); if( shift != 0 ) { if( options.position != null ) $('#c1-lightbox-thumbs ul').animate( {left: left + 'px'}, options.speed ); else $('#c1-lightbox-thumbs ul').css( 'left', left + 'px' ); } // Update thumbnail controls $('#c1-lightbox-thumbs-prev')[position == 0 || left >= options.thumbsBounds.left ? 'hide' : 'show'](); $('#c1-lightbox-thumbs-next')[left <= options.thumbsBounds.right ? 'hide' : 'show'](); } } // Update the next/previous links if( options.images.length > 1 ) { $('#c1-lightbox-image-prev')[position == 0 ? 'hide' : 'show'](); $('#c1-lightbox-image-next')[position == ( options.images.length - 1 ) ? 'hide' : 'show'](); } // Track the event _track_event( 'Image', src, position + 1, true ); } // Update the position count options.position = position; }; /** * Returns the width and height from the url. * @param string url The url to process * @return object An object with width and height properties */ function _get_url_dimensions( url ) { if( url.match( /-(\d+)x(\d+)/ ) ) return {width: parseInt( RegExp.$1 ), height: parseInt( RegExp.$2 )}; return null; }; /** * Returns the thumbnail url for the specified width and height. * @param string url The url to process * @param integer width The new width * @param integer height The new height */ function _get_thumb_url( url, width, height, mode ) { url = url.replace( /([a-z]+)?(-)\d+x\d+([^\/]+)$/, '$2' + width + 'x' + height + '$3' ); if( mode ) url = url.replace( '-' + width + 'x' + height, '-' + mode + '-' + width + 'x' + height ); return url; }; /** * Returns the media url for the specified url. * @param string url The url to process * @return string The media url */ function _get_media_url( url ) { url = url .replace( '/thumbnail/', '/media/' ) .replace( new RegExp( '(/media/)\\d+/\\d+/', 'i' ), '$1' ) .replace( new RegExp( '(/media/r\\d+/)\\d+/\\d+/', 'i' ), '$1' ); return url; } /** * Remove jQuery lightBox plugin HTML markup */ function _finish() { // Run any custom close functions var result = true; if( options.onclose ) result = options.onclose.call( $('#c1-lightbox-' + ( options.images ? 'image' : 'content' ) ).get( 0 ) ); // If the close should be cancelled if( result == false ) return false; // Remove hash functionality and remove hash if (options.close && window.removeEventListener) { window.removeEventListener('hashchange', _hash_change, false); if (window.location.hash == '#lightbox-open') { if (no_refresh) window.location.hash=''; else window.history.back(); } } // Trigger any events if( options.inline ) { $( options.inline ).trigger( 'c1.lightbox.close' ); // Remove any iframes by setting url before removing. // This is to address a problem in IE where iframe is not removed // unless page is unloaded. // http://drupal.org/node/1777238 } else if( options.iframe ) { $('#c1-lightbox iframe').attr('src', 'about:blank').remove(); } // Remove the lightbox $('#c1-lightbox').remove(); if( options.touch ) { $('#c1-lightbox-overlay').remove(); } else { $('#c1-lightbox-overlay').fadeOut( function() { $(this).remove(); } ); } // Reset variables prevPosition = null; // Show some elements to avoid conflict with overlay in IE. These elements appear above the overlay. $(options.hide).css( { 'visibility' : 'visible' } ); // Unbind the resize and scroll method $(window).unbind( 'resize', _resize_interface ).unbind( 'scroll', _resize_interface ); return true; }; /** * @return Array Return an array with page width, height and window width, height */ function ___getPageSize() { return [ $(document).width(), $(document).height(), window.innerWidth, window.innerHeight ]; }; /** * getPageScroll() by quirksmode.com * @return Array Return an array with x,y page scroll values. */ function ___getPageScroll() { var xScroll, yScroll; if (self.pageYOffset || self.pageYOffset == 0) { yScroll = self.pageYOffset; xScroll = self.pageXOffset; } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict yScroll = document.documentElement.scrollTop; xScroll = document.documentElement.scrollLeft; } else if (document.body) {// all other Explorers yScroll = document.body.scrollTop; xScroll = document.body.scrollLeft; } arrayPageScroll = new Array(xScroll,yScroll); return arrayPageScroll; }; // Add custom click handler that opens the lightbox this.click( function() { return _start( this ); } ); return this; }; })(jQuery);