Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
View Larger plugin for Conde Nast Slideshow. (c) Conde Nast Publications, All Rights Reserved
/*global CN, console, window, alert, location, document, jQuery, setTimeout, clearTimeout, clearInterval, setInterval */ /* for jsLint */
CN.slideshow = CN.slideshow || {};
CN.slideshow.plugin = CN.slideshow.plugin || {};
/**
* Plugin to add support for View Larger to the MPP Slideshow.
* Encapsulates view larger creation, data population and destruction.
*
* @namespace CN.slideshow
* @class viewLarger
* @requires CN.slideshow
* @author Eric Shepherd
* @history 1.0.0 EBS 06.01.2009 Production
* 1.0.1 YC 03.20.2010 Added unbinding of history to fix bug with double counting
* 1.0.2 EBS 07.21.2010 Added config for width instead of hardcoded value
*/
CN.slideshow.plugin.viewLarger = (function() {
var build,
remove,
create,
destroyElements,
cleanupOriginatingSlideshow,
close,
setKeyEvents,
prepareDomElements,
$overlay,
$largerEl,
buildInstructions,
addExtraSlides,
insertInitialSlideMarkup,
createExtraControls,
createViewLargerObject,
elementResize;
/**
* Model helper which creates the slides for the View Larger module.
*
* @method build
* @private
* @param {Slides} slideshow A slideshow to build View Larger with
*/
build = function(slideshow) {
var i,
il;
for (i = 0, il = slideshow.data.length; i < il; i++) {
slideshow.append(new CN.slideshow.Slide(slideshow.data[i], 'enlargedItem'));
}
CN.slideshow.util.dataReady(slideshow);
};
/**
* Helper which removes the View Larger slideshow specified along
* with its navigation objects
*
* @method remove
* @private
* @param {Slides} slideshow A slideshow to remove
*/
remove = function(slideshow) {
// Calls the page method which can tap into the view larger instance
try {
CN.page.config.slideshowViewLargerCloseCallback(slideshow);
} catch(e) {
CN.debug.warn('Tried to call view larger close callback, perhaps no callback function exists at CN.page.config.slideshowViewLargerCloseCallback : ' + e.message);
}
jQuery(document).unbind('keydown');
destroyElements(slideshow);
CN.slideshow.util.removeNavigations(slideshow);
CN.slideshow.util.destroyTimer(slideshow);
slideshow = null;
};
/**
* Handles behaviors for a view larger instance
*
* @method create
* @public
* @param {Slides} slideshow The slideshow to build view larger for
* @param {Object} config The view larger configuration object
* @param {Object} oldCommands The command object from the original slideshow
*/
create = function(slideshow, config, oldCommands) {
var larger = createViewLargerObject(slideshow, config.transition || null),
viewLargerCommands;
cleanupOriginatingSlideshow(slideshow);
prepareDomElements(larger, oldCommands);
// Updates the slideshow when the history changes, only if view larger element is present
if (larger.useHistory) {
jQuery(window).bind('history', function(e, currentHash, previousHash) {
var dest = currentHash.split('=')[1];
close(larger, oldCommands, dest);
});
}
elementResize(); // Necessary to resize before showing overlay for it to fade in properly
jQuery(window).resize(function() {
elementResize();
});
jQuery('body').append($overlay);
$overlay.hide().fadeIn('slow', function() {
jQuery('body').append($largerEl);
buildInstructions();
// Recurses on the init function to initialize and get commands
viewLargerCommands = CN.slideshow.controller.init(larger, {
goForward : { container: '.slideshow-view-larger-util' },
goBackward : { container: '.slideshow-view-larger-util' },
stopSlideshow : { container: '.slideshow-view-larger-util' },
playSlideshow : { container: '.slideshow-view-larger-util', sliderEl: '.slideshow-control-stop' }
});
CN.slideshow.util.destroyTimer(slideshow);
createExtraControls(slideshow, viewLargerCommands);
setKeyEvents(larger, viewLargerCommands, oldCommands);
build(larger);
addExtraSlides(slideshow, larger);
insertInitialSlideMarkup(slideshow, larger);
elementResize();
// Calls the page method which can tap into the view larger instance for ad refreshing, etc.
try {
CN.page.config.slideshowViewLargerCallback(larger, viewLargerCommands);
} catch(e) {
CN.debug.warn('Tried to call view larger callback; perhaps no callback function exists at CN.page.config.slideshowViewLargerCallback : ' + e.message);
}
});
};
/**
* Removes view larger slideshow dom elements
*
* @method destroyElements
* @private
* @param {Slides} slideshow A slideshow object
*/
destroyElements = function(slideshow) {
CN.slideshow.view.removeSlide(slideshow.$el.find('.items').children());
slideshow.$el.remove();
jQuery('.slideshow-view-larger-overlay').fadeOut('slow', function() {
jQuery('.slideshow-view-larger-overlay').remove();
});
};
/**
* Cleans up the existing slideshow before creating its view larger instance
*
* @method cleanupOriginatingSlideshow
* @private
* @param {Slides} slideshow A slideshow object
*/
cleanupOriginatingSlideshow = function(slideshow) {
// In case slideshow is playing
CN.slideshow.view.hideSlider(slideshow, function() {
CN.slideshow.view.hideStopButton(slideshow);
});
// In case view all is open
if (slideshow.navigationItems.hasOwnProperty('navigationViewAll')) {
slideshow.navigationItems.navigationViewAll.hide();
}
};
/**
* Closes up shop, cleans up
*
* @method close
* @private
* @param {Slides} slideshow A view larger slideshow
* @param {Object} oldCommands A collection of commands for the originating slideshow
* @param {Number} destinationSlide An optional slide to jump to when closing the view larger slideshow
*/
close = function(slideshow, oldCommands, destinationSlide) {
// Communicates with originating slideshow on close
oldCommands.jumpToSlideCommand.execute(destinationSlide || slideshow.currentSlideIndex + 1);
jQuery(window).unbind('history');
remove(slideshow);
jQuery(window).bind('history', {
useIntro : slideshow.useIntro,
commands : oldCommands
}, CN.slideshow.util.bindHistory);
};
/**
* Sets the keyboard commands for view larger
*
* @method setKeyEvents
* @private
* @param {Sldies} larger A view larger slideshow
* @param {Object} commands A collection of commands for the larger slideshow
* @param {Object} oldCommands A collection of commands for the originating slideshow
*/
setKeyEvents = function(larger, commands, oldCommands) {
jQuery(document).keydown(function(e) {
switch(e.keyCode) {
case 27 :
close(larger, oldCommands);
break;
case 39 :
commands.goForwardCommand.execute();
break;
case 37 :
commands.goBackwardCommand.execute();
break;
case 32 :
if (larger.isAlreadyPlaying()) {
commands.stopSlideshowCommand.execute();
} else {
commands.playSlideshowCommand.execute();
}
break;
}
e.preventDefault();
return false;
});
};
/**
* Preps the document for view larger
*
* @method prepareDomElements
* @private
* @param {Slides} slideshow The view larger slideshow instance
* @param {Object} oldCommands A collection of commands for the original slideshow
*/
prepareDomElements = function(slideshow, oldCommands) {
var $closeBox = jQuery('<div class="slideshow-view-larger-close">Close</div>'),
$utilBox = jQuery('<div class="slideshow-view-larger-util"><div class="count">' + (slideshow.currentSlideIndex + 1) + ' / ' + slideshow.slides.length + '</div></div>');
$overlay = jQuery('<div class="slideshow-view-larger-overlay">');
$closeBox.click(function() {
close(slideshow, oldCommands);
});
slideshow.$el.addClass('slideshow-view-larger-container').prepend($closeBox).append($utilBox).append('<h1>' + jQuery('.list h1').eq(0).text() + '</h1>');
};
/**
* Creates additional controls not created by the shell
*
* @method createExtraControls
* @private
* @param {Slides} slideshow A view larger slideshow instance
* @param {Object} commands Commands for the view larger instance
*/
createExtraControls = function(slideshow, commands) {
var $previous,
$next;
$previous = jQuery('<div class="slideshow-view-larger-previous">').click(function() {
commands.goBackwardCommand.execute();
});
$next = jQuery('<div class="slideshow-view-larger-next">').click(function() {
commands.goForwardCommand.execute();
});
$largerEl.append($previous).append($next);
};
/**
* Recalculates the DOM element sizes
*
* @method elementResize
* @private
*/
elementResize = function() {
var topOffset = jQuery('body,html').scrollTop();
$overlay.css({
height : jQuery(document).height(),
width : jQuery(document).width()
});
$largerEl.css({
width : (CN.slideshow.config && CN.slideshow.config.viewLargerWidth) ?
CN.slideshow.config.viewLargerWidth :
990,
top : topOffset,
left : jQuery(document).width() / 2 - 475 - 20 // account for scrollbars on browser...
});
// Sets position fixed if the browser supports it and the window is big enough to see the entire slideshow.
if ((jQuery(window).height() < ($largerEl.height() + 50)) || (jQuery.browser.msie && jQuery.browser.version < 7) || (jQuery.browser.mozilla && jQuery.browser.version.substr(0, 3) < 1.9)) {
$largerEl.css('position', 'absolute');
$largerEl.css('top', topOffset);
} else {
$largerEl.css('position', 'fixed');
$largerEl.css('top', 0);
}
};
/**
* Creates the instruction box and handles the cookie for showing it
*
* @method buildInstructions
* @private
*/
buildInstructions = function() {
var $instructions = jQuery('<div class="slideshow-view-larger-instructions instructions-default"><strong>Press ESC to close</strong><b>Right Arrow</b> moves forward.<br /><b>Left Arrow</b> moves backward.<br /><b>Space Bar</b> starts and stops play.</p></div>').appendTo($largerEl),
$instructionsTrigger = jQuery('<div class="slideshow-view-larger-instructions-trigger">? <span>Help</span></div>').insertBefore($instructions),
$instructionsClose = jQuery('<div class="slideshow-view-larger-instructions-close">Close</div>').prependTo($instructions),
instructionsTimer,
repeatVisitor = CN.cookie.get('slideshow_repeat');
// Adds cookie for displaying instructions
if (repeatVisitor === 'yes') {
$instructions.hide();
$largerEl.hide().fadeIn('slow');
} else {
$largerEl.hide().fadeIn('slow', function() {
instructionsTimer = setTimeout(function() {
$instructions.fadeOut('slow');
}, 3000);
CN.cookie.set('slideshow_repeat', 'yes', { domain: CN.site.domain, path: '/' });
});
}
$instructionsClose.click(function() {
$instructions.fadeOut('fast');
clearTimeout(instructionsTimer);
});
$instructionsTrigger.css('display', 'block').click(function() {
$instructions.fadeIn('fast');
});
};
/**
* Adds extra slides that are not part of the data object
*
* @method addExtraSlides
* @private
* @param {Slides} slideshow The original slideshow object
* @param {Slides} larger The new view larger slideshow object
*/
addExtraSlides = function(slideshow, larger) {
var i,
il;
// Adds anything not of type 'slide' into the view larger slides array
for (i = 0, il = slideshow.slides.length; i < il; i++) {
if (slideshow.slides[i].getLabel() !== 'slide') {
larger.slides.splice(i, 0, slideshow.slides[i]);
larger.onSlideAppended.fire(); // Updates count and interstitial frequency
}
}
};
/**
* Creates the view larger object
*
* @method createViewLargerObject
* @private
* @param {Slides} slideshow A slideshow object to build view larger from
* @param {String} transition An optional transition
* @return {Slides} A view larger object
*/
createViewLargerObject = function(slideshow, transition) {
// Builds the new slideshow and copies over what we need from the old
var larger = new CN.slideshow.Slides(document.createElement('div'), {
transition : transition || 'standard',
useHistory : slideshow.useHistory
});
larger.data = slideshow.data;
larger.interstitialManager = slideshow.interstitialManager;
larger.currentSlideIndex = slideshow.currentSlideIndex;
$largerEl = larger.$el;
return larger;
};
/**
* Adds the items container and current slide markup for the initial view larger view
*
* @method insertInitialSlideMarkup
* @private
* @param {Slides} slideshow The originating slideshow for this view larger instance (only needed to accurately get the current slide number)
* @param {Slides} larger The current view larger slideshow instance
*/
insertInitialSlideMarkup = function(slideshow, larger) {
var $container = jQuery('<div class="items slideshow-items">');
$largerEl.find('.slideshow-view-larger-close').after($container);
// Note: using slideshow's index to find the slide because larger's index sometimes returns 0. Might be a timing issue,
// but it stabilizes things to use the slideshow's and they are always the same anyway.
$container.append(jQuery(larger.slides[slideshow.currentSlideIndex].getHtml())); // getHtml(), unintuitively, could return a jQuery selector
};
return {
create : create
};
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment