/** * @fileoverview Site code for max99x.com. MIT license if you want to reuse it. * @preserve See static.max99x.com/scripts for uncompressed sources. */ (function($) { /** * The amount of time in milliseconds to delay functions which can't be run * immediately due to conflicts (e.g. animation). * @const * @type {number} */ var DELAY_FOR_CONFLICT = 200; /** * The amount of padding in pixels to add when calculating the size of newly * loaded contents. * @const * @type {number} */ var CONTENT_HEIGHT_PADDING = 22; /** * The width in pixels of a single album photo, including its frame. * @const * @type {number} */ var PHOTO_WIDTH = 152; /** * Whether the current browser is IE, version 7 or older. * @type {bool} */ var isOldIE = false; /** * Whether the current browser is IE, version 6 or older. * @type {bool} */ var isAncientIE = false; /** * Loads the content at a given page into the main content area. * @param {string} link The path of the page to load. Should be a local path * which accepts the "content" argument. */ var loadContent = function(link) { // Delay loading new content until a previous load operation is complete. if (loadContent.is_loading) { setTimeout(function() { loadContent(link); }, DELAY_FOR_CONFLICT); return; } // Setup shortcuts to common elements. var $content = $('#content'); var $wrapper = $('#wrapper'); var $loader = $('#loader'); // We're now loading. loadContent.is_loading = true; // Center and fade in the loading throbber. $loader.css({ left: ($(document).width() - $loader.width()) / 2 }); $loader.fadeIn('fast'); // Define a function fetch and load a page. var fetchContent = function() { // Query the server for the contents of the new page. $.get(link + '&content', function(response) { // Fade out the loading throbber. $loader.fadeOut('fast'); // Remember the original height of the page for animation. var orig_height = $wrapper.height(); // Insert the new page content. $content.html(response); // Update the window title to reflect the new content. setTitle(); // Initialized albums and photo colorboxes. initGallery(); // Calculate the height of the page with the new content. var new_height = $content.height() + CONTENT_HEIGHT_PADDING; // Show the content. if (isOldIE) { // On older IE, which has problems animating opacity, just show the // content without animation. $content.show(); } else { // Fade in the content. $content.animate({ opacity: 1 }, 'fast', function() { // Our dear friend IE fucks up ClearType when opacity is specified. $content.css({ 'filter': '' }); }); } // Animate the wrapper resizing to fit the new content. $wrapper.css({ 'overflow-y': 'hidden', height: orig_height }).animate({ height: new_height }, function() { $wrapper.css({ height: '' }); }); // We're done loading. loadContent.is_loading = false; }); }; // Initiate loading. if (isOldIE) { // Opacity animation is bad on old IE, so just hide the current content and // immediately load the new page. $content.hide(); fetchContent(); } else { // Fade out the current content and start loading the new. $content.animate({ opacity: 0 }, 'fast', fetchContent); } }; /** * Loads the sidebar menu appropriate for a given page. Keeps track of the last * loaded sidebar to avoid reloading the same sidebar twice. Assumes that any * two paths which share the first part/folder also share a menu. Calls * updateSidebarTab() when done to update the currently active item. * @param {string} link The path of the page whose sidebar is to be loaded. * Should be a local path which accepts the "menu" argument. */ var loadSidebar = function(link) { // Delay loading a new sidebar until a previous load operation is complete. if (loadSidebar.is_loading) { setTimeout(function() { loadSidebar(link); }, DELAY_FOR_CONFLICT); return; } // Don't do load a new sidebar when it is already loaded. That's redundant! if (link.split('/')[1] == loadSidebar.last_loaded) { // Updated the selected sidebar item. updateSidebarTab(); return; } // Setup element shortcut. var $sidebar = $('#sidebar'); // We're now loading. loadSidebar.is_loading = true; // Hide the old sidebar. $sidebar.fadeOut('fast', function() { // Once the old sidebar is hidden, load the new one from the server. $sidebar.load(link + '&menu', function() { // Fade in the new sidebar. $sidebar.fadeIn('fast', function() { // If possible, set up sidebar button blending animation. if (!isOldIE) $('#sidebar a').blend(400); // We're done loading. loadSidebar.is_loading = false; // Remember the last sidebar we've loaded. loadSidebar.last_loaded = link.split('/')[1]; // Updated the selected sidebar item. updateSidebarTab(); }); }); }); }; loadSidebar.last_loaded = window.location.pathname.split('/')[1]; /** * Sets the window title by joining the following parts with a spaced dash: * 1. The contents of the first H1 element on the current page. * 2. The current path, not including the last part. Dashes are replaced with * spaces and converted to title case. Slashes are replaced with spaced * dashes. * 3. The part of the current title following the last spaced dash. */ var setTitle = function() { var path = $.nav.getState().replace(/\w+/g, function(text) { return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); }).replace(/-/g, ' ').split('/').slice(0, -1); path.unshift($('h1:first').text()); path.push(document.title.split(' - ').pop()); document.title = path.join(' - '); }; /** * Updates all photos on the page (links inside element with classes * photo_album or photo_album_slider) by adding a link to the raw source image * to the title of their colorbox. */ window.addPhotoSources = function() { // Update each photo album image. $('.photo_album a, .photo_album_slider a').each(function() { // Construct a link to the original. var $this = $(this); var pic = $this.attr('href'); var src = pic.slice(0, -4) + '.src' + pic.slice(-4); var src_link = ' Raw Original'; // Update the colorbox options by adding the link. $this.colorbox({ title: $this.attr('title') + src_link }); }); }; /** * Converts album elements (ones with class .photo_album) into sliders and makes * all photos into colorboxes. */ var initGallery = function() { // The serial number of the current album. Used for grouping colorboxes. var album_number = 0; // Process each album. $('.photo_album').each(function() { // IE6- can't handle overflow hiding. if (!isAncientIE) { // Setup a shortcut to our album. var $album = $(this); // Create the slider and previous/next buttons. var $prev = $('
'); var $next = $(''); // The distance in pixels to traverse on every previous/next click. var step = $album.width() - PHOTO_WIDTH; // Fix possible bug in IE7- with width being reported negative. if (step < 0) step = PHOTO_WIDTH; // The leftmost position of the album slider. var lower_bound = 0; // The rightmost position of the album slider. var upper_bound = $('a', $album).length * PHOTO_WIDTH; // Wrap the photos in a slider and make the album into a container. $album.children().wrapAll(''); var $slider = $album.children(); $album.removeClass('photo_album').addClass('photo_album_container'); // Set up slider movement via previous/next buttons. $prev.appendTo($album).click(function() { if ($slider.is(':animated') || $(this).is('.disabled')) return; var left = $slider.position().left; var target_left = null; if (left > lower_bound - step) { target_left = lower_bound; } else { target_left = '+=' + step; } $slider.animate({ left: target_left }, updateButtons); }); $next.appendTo($album).click(function() { if ($slider.is(':animated') || $(this).is('.disabled')) return; var left = $slider.position().left; var width = $album.width() - $prev.width() - $next.width(); var target_left = null; if (left < -(upper_bound - width - step)) { target_left = width - upper_bound; } else { target_left = '-=' + step; } $slider.animate({ left: target_left }, updateButtons); }); // Determines whether the previous or the next button are disabled based // on slider position. function updateButtons() { var slider_pos = $slider.position().left; var width = $album.width() - $prev.width() - $next.width(); $prev.toggleClass('disabled', slider_pos >= 0); $next.toggleClass('disabled', slider_pos <= -(upper_bound - width)); } // Update buttons as soon as we're done with this function. // Can't do it immediately because we need to let the album auto-resize. setTimeout(updateButtons, 1); } // Make all photos in this album into a colorboxes, grouped by album number. $('a', $album).attr({ rel: 'photo_album_' + album_number, // NOTE: Returning focus lets IE users scroll the album container // horizontally which breaks our navigation. returnFocus: false }).colorbox(); // Update the album serial number. album_number++; }); // Make all orphan photos into ungrouped colorboxes. // NOTE: Returning focus lets IE users scroll the album container // horizontally which breaks our navigation. $('a.photo').colorbox({ returnFocus: false }); // Apply fake corners for main page photos on browsers that don't support // border-radius (at least not on images). $('a.main_photo').each(function() { // IE6 can't handle it. Webkit and Firefox 4 don't need this. if (isAncientIE || $.browser.webkit || $.browser.mozilla && parseFloat($.browser.version) < 2) return; $(this).css({ position: 'relative' }); var corner = $('