$(function(){ var $next, $prev, touchX, touchY; // Prevent scrolling the page (used with CSS no-scroll class) function lockScrolling(bool) { $('html').toggleClass('no-scroll', bool); } // Generate the HTML for the zoomed in preview function makePreview(element) { if (!element) return false; // Previous and next elements get tracked in the JS enclosure $prev = $('img', $(element).prev('.zoom')); $next = $('img', $(element).next('.zoom')); // Grab the description var desc = $('img', element).attr('alt'); // Format next/previous links when they're relevant var prev = $prev.length ? '' : ''; var next = $next.length ? '' : ''; // Generate jQuery document fragment based on the generated HTML var $html = $('
' + prev + '' + next + '

' + desc + "

"); return $html; } // Show the preview function showPreview(element) { var preview = makePreview(element); $('body').append(preview); lockScrolling(true); } // Hotswap the preview for the next or previous function switchPreview(direction) { var $element = (direction == "next") ? $next : $prev; if (!$element) return false; var code = makePreview($element.parent()[0]); if (!code) return false; // We're transplanting the contents inside the container, to prevent an animation $('#imagePreview').addClass('no-anim').html($(code).children()); // Add a pulse class, to make the arrow react to a switch $('.' + direction, '#imagePreview').addClass('pulse'); } // Close the preview (with a fade and removal) function closePreview(element) { var $element = $('#imagePreview'); $element.fadeOut(200, function(){ $element.remove(); lockScrolling(false); }); } function previewIsVisible() { return $('#imagePreview').is(':visible'); } // Bind actions to the document; bubbling up events, handled in specific cases $(document).on('click', 'a.screenshot.zoom, .screenshot.zoom a', function(ev){ // Generate a screenshot preview when clicking on a screenshot thumbnail showPreview(this); ev.preventDefault(); }).on('click', '#imagePreview', function(ev){ // Close, unless clicking on a link if (ev.target.nodeName !== 'A') { closePreview(); } }).on('click', '.screenshot-next, .screenshot-prev', function(ev){ // Switch to the next or previous, when clicking on an link arrow switchPreview(this.getAttribute('data-direction')); ev.preventDefault(); }).on('keydown', function(ev) { // Handle keyboard shortcuts var action; if (previewIsVisible()) { switch (ev.key) { // arrows case 'ArrowLeft': action = "prev"; break; case 'ArrowRight': action = "next"; break; case 'ArrowUp': action = "prev"; break; case 'ArrowDown': action = "next"; break; // Page up / down case 'PageUp': action = "prev"; break; case 'PageDown': action = "next"; break; // Space, shift+space, and backspace case ' ': if (ev.shiftKey) { action = "prev"; } else { action = "next"; } break; case 'Backspace': action = "prev"; break; // vi keys case 'h': action = "prev"; break; case 'j': action = "next"; break; case 'k': action = "prev"; break; case 'l': action = "next"; break; // wasd case 'w': action = "prev"; break; case 's': action = "next"; break; case 'a': action = "prev"; break; case 'd': action = "next"; break; // Escape case 'Escape': action = "close"; break; } if (!action) return true; if (action == "close") { closePreview(); } else { switchPreview(action); } ev.preventDefault(); } }).on('wheel', function(ev){ // Handle mouse scroll events var action = (ev.originalEvent.deltaY > 0) ? 'next' : 'prev'; switchPreview(action); }); });