Commit f07ae0f4 authored by Michael Rose's avatar Michael Rose
Browse files

Add Magnific Popup

- Image links now display in a lightbox
parent 5ea0426b
This diff is collapsed.
......@@ -26,4 +26,27 @@ $('#site-nav').click(function(event){
// FitVids options
$(function() {
$("article").fitVids();
});
// Add lightbox class to all image links
$("a[href$='.jpg'],a[href$='.jpeg'],a[href$='.JPG'],a[href$='.png'],a[href$='.gif']").addClass("image-popup");
// Magnific-Popup options
$(document).ready(function() {
$('.image-popup').magnificPopup({
type: 'image',
tLoading: 'Loading image #%curr%...',
gallery: {
enabled: true,
navigateByImgClick: true,
preload: [0,1] // Will preload 0 - before current, and 1 after the current image
},
image: {
tError: '<a href="%url%">Image #%curr%</a> could not be loaded.',
},
removalDelay: 300, // Delay in milliseconds before popup is removed
// Class that is added to body when popup is open.
// make it unique to apply your CSS animations just to this exact popup
mainClass: 'mfp-fade'
});
});
\ No newline at end of file
/*! Magnific Popup - v0.8.9 - 2013-06-04
/*! Magnific Popup - v0.9.3 - 2013-07-16
* http://dimsemenov.com/plugins/magnific-popup/
* Copyright (c) 2013 Dmitry Semenov; */
;(function($) {
......@@ -15,6 +15,7 @@
* Private static constants
*/
var CLOSE_EVENT = 'Close',
BEFORE_CLOSE_EVENT = 'BeforeClose',
AFTER_CLOSE_EVENT = 'AfterClose',
BEFORE_APPEND_EVENT = 'BeforeAppend',
MARKUP_PARSE_EVENT = 'MarkupParse',
......@@ -76,7 +77,7 @@ var _mfpOn = function(name, f) {
}
},
_setFocus = function() {
(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).trigger('focus');
},
_getCloseBtn = function(type) {
if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
......@@ -116,13 +117,33 @@ var _mfpOn = function(name, f) {
// if click is outside the content
if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) {
if(closeOnBg) {
return true;
// last check, if the clicked element is in DOM, (in case it's removed onclick)
if( $.contains(document, target) ) {
return true;
}
}
} else if(closeOnContent) {
return true;
}
}
return false;
},
// CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
supportsTransitions = function() {
var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
v = ['ms','O','Moz','Webkit']; // 'v' for vendor
if( s['transition'] !== undefined ) {
return true;
}
while( v.length ) {
if( v.pop() + 'Transition' in s ) {
return true;
}
}
return false;
};
......@@ -146,6 +167,8 @@ MagnificPopup.prototype = {
mfp.isLowIE = mfp.isIE7 || mfp.isIE8;
mfp.isAndroid = (/android/gi).test(appVersion);
mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
mfp.supportsTransition = supportsTransitions();
// We disable fixed positioned lightbox on devices that don't handle it nicely.
// If you know a better way of detecting this - let me know.
mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
......@@ -193,7 +216,11 @@ MagnificPopup.prototype = {
mfp.types = [];
_wrapClasses = '';
mfp.ev = data.mainEl || _document;
if(data.mainEl && data.mainEl.length) {
mfp.ev = data.mainEl.eq(0);
} else {
mfp.ev = _document;
}
if(data.key) {
if(!mfp.popupsCache[data.key]) {
......@@ -208,7 +235,13 @@ MagnificPopup.prototype = {
mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data );
mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;
if(mfp.st.modal) {
mfp.st.closeOnContentClick = false;
mfp.st.closeOnBgClick = false;
mfp.st.showCloseBtn = false;
mfp.st.enableEscapeKey = false;
}
// Building markup
......@@ -245,14 +278,16 @@ MagnificPopup.prototype = {
_mfpTrigger('BeforeOpen');
// Close button
if(!mfp.st.closeBtnInside) {
mfp.wrap.append( _getCloseBtn() );
} else {
_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
values.close_replaceWith = _getCloseBtn(item.type);
});
_wrapClasses += ' mfp-close-btn-in';
if(mfp.st.showCloseBtn) {
// Close button
if(!mfp.st.closeBtnInside) {
mfp.wrap.append( _getCloseBtn() );
} else {
_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
values.close_replaceWith = _getCloseBtn(item.type);
});
_wrapClasses += ' mfp-close-btn-in';
}
}
if(mfp.st.alignTop) {
......@@ -282,12 +317,14 @@ MagnificPopup.prototype = {
// Close on ESC key
_document.on('keyup' + EVENT_NS, function(e) {
if(e.keyCode === 27) {
mfp.close();
}
});
if(mfp.st.enableEscapeKey) {
// Close on ESC key
_document.on('keyup' + EVENT_NS, function(e) {
if(e.keyCode === 27) {
mfp.close();
}
});
}
_window.on('resize' + EVENT_NS, function() {
mfp.updateSize();
......@@ -306,20 +343,20 @@ MagnificPopup.prototype = {
var windowHeight = mfp.wH = _window.height();
var bodyStyles = {};
var windowStyles = {};
if( mfp.fixedContentPos ) {
if(mfp._hasScrollBar(windowHeight)){
var s = mfp._getScrollbarSize();
if(s) {
bodyStyles.paddingRight = s;
windowStyles.paddingRight = s;
}
}
}
if(mfp.fixedContentPos) {
if(!mfp.isIE7) {
bodyStyles.overflow = 'hidden';
windowStyles.overflow = 'hidden';
} else {
// ie7 double-scroll bug
$('body, html').css('overflow', 'hidden');
......@@ -343,7 +380,7 @@ MagnificPopup.prototype = {
// remove scrollbar, add padding e.t.c
_body.css(bodyStyles);
$('html').css(windowStyles);
// add everything to DOM
mfp.bgOverlay.add(mfp.wrap).prependTo( document.body );
......@@ -384,10 +421,11 @@ MagnificPopup.prototype = {
*/
close: function() {
if(!mfp.isOpen) return;
_mfpTrigger(BEFORE_CLOSE_EVENT);
mfp.isOpen = false;
// for CSS3 animation
if(mfp.st.removalDelay && !mfp.isLowIE) {
if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition ) {
mfp._addClassToMFP(REMOVING_CLASS);
setTimeout(function() {
mfp._close();
......@@ -416,13 +454,13 @@ MagnificPopup.prototype = {
mfp._removeClassFromMFP(classesToRemove);
if(mfp.fixedContentPos) {
var bodyStyles = {paddingRight: ''};
var windowStyles = {paddingRight: ''};
if(mfp.isIE7) {
$('body, html').css('overflow', '');
} else {
bodyStyles.overflow = '';
windowStyles.overflow = '';
}
_body.css(bodyStyles);
$('html').css(windowStyles);
}
_document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
......@@ -434,14 +472,15 @@ MagnificPopup.prototype = {
mfp.container.attr('class', 'mfp-container');
// remove close button from target element
if(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true ) {
if(mfp.st.showCloseBtn &&
(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
if(mfp.currTemplate.closeBtn)
mfp.currTemplate.closeBtn.detach();
}
if(mfp._lastFocusedEl) {
$(mfp._lastFocusedEl).focus(); // put tab focus back
$(mfp._lastFocusedEl).trigger('focus'); // put tab focus back
}
mfp.currItem = null;
mfp.content = null;
......@@ -539,7 +578,8 @@ MagnificPopup.prototype = {
mfp.content = newContent;
if(newContent) {
if(mfp.st.closeBtnInside && mfp.currTemplate[type] === true) {
if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
mfp.currTemplate[type] === true) {
// if there is no markup, we just append close button element inside
if(!mfp.content.find('.mfp-close').length) {
mfp.content.append(_getCloseBtn());
......@@ -632,37 +672,41 @@ MagnificPopup.prototype = {
},
_openClick: function(e, el, options) {
var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;
if( midClick || e.which !== 2 ) {
var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;
if(disableOn) {
if($.isFunction(disableOn)) {
if( !disableOn.call(mfp) ) {
return true;
}
} else { // else it's number
if( _window.width() < disableOn ) {
return true;
}
}
}
if(e.type) {
e.preventDefault();
// This will prevent popup from closing if element is inside and popup is already opened
if(mfp.isOpen) {
e.stopPropagation();
if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) {
return;
}
var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;
if(disableOn) {
if($.isFunction(disableOn)) {
if( !disableOn.call(mfp) ) {
return true;
}
} else { // else it's number
if( _window.width() < disableOn ) {
return true;
}
}
}
if(e.type) {
e.preventDefault();
options.el = $(e.mfpEl);
if(options.delegate) {
options.items = el.find(options.delegate);
// This will prevent popup from closing if element is inside and popup is already opened
if(mfp.isOpen) {
e.stopPropagation();
}
mfp.open(options);
}
options.el = $(e.mfpEl);
if(options.delegate) {
options.items = el.find(options.delegate);
}
mfp.open(options);
},
......@@ -692,7 +736,7 @@ MagnificPopup.prototype = {
mfp.preloader.html(text);
mfp.preloader.find('a').click(function(e) {
mfp.preloader.find('a').on('click', function(e) {
e.stopImmediatePropagation();
});
......@@ -714,7 +758,7 @@ MagnificPopup.prototype = {
mfp.wrap.removeClass(cName);
},
_hasScrollBar: function(winHeight) {
return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) )
return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
},
_parseMarkup: function(template, values, item) {
var arr;
......@@ -826,6 +870,12 @@ $.magnificPopup = {
closeBtnInside: true,
showCloseBtn: true,
enableEscapeKey: true,
modal: false,
alignTop: false,
removalDelay: 0,
......@@ -1222,6 +1272,8 @@ $.magnificPopup.registerModule('image', {
item.hasSize = true;
item.loaded = true;
_mfpTrigger('ImageLoadComplete');
}
else {
......@@ -1265,6 +1317,9 @@ $.magnificPopup.registerModule('image', {
if(el.is('img')) {
item.img = item.img.clone();
}
if(item.img[0].naturalWidth > 0) {
item.hasSize = true;
}
}
mfp._parseMarkup(template, {
......@@ -1305,6 +1360,193 @@ $.magnificPopup.registerModule('image', {
/*>>image*/
/*>>zoom*/
var hasMozTransform,
getHasMozTransform = function() {
if(hasMozTransform === undefined) {
hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
}
return hasMozTransform;
};
$.magnificPopup.registerModule('zoom', {
options: {
enabled: false,
easing: 'ease-in-out',
duration: 300,
opener: function(element) {
return element.is('img') ? element : element.find('img');
}
},
proto: {
initZoom: function() {
var zoomSt = mfp.st.zoom,
ns = '.zoom';
if(!zoomSt.enabled || !mfp.supportsTransition) {
return;
}
var duration = zoomSt.duration,
getElToAnimate = function(image) {
var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
cssObj = {
position: 'fixed',
zIndex: 9999,
left: 0,
top: 0,
'-webkit-backface-visibility': 'hidden'
},
t = 'transition';
cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;
newImg.css(cssObj);
return newImg;
},
showMainContent = function() {
mfp.content.css('visibility', 'visible');
},
openTimeout,
animatedImg;
_mfpOn('BuildControls'+ns, function() {
if(mfp._allowZoom()) {
clearTimeout(openTimeout);
mfp.content.css('visibility', 'hidden');
// Basically, all code below does is clones existing image, puts in on top of the current one and animated it
image = mfp._getItemToZoom();
if(!image) {
showMainContent();
return;
}
animatedImg = getElToAnimate(image);
animatedImg.css( mfp._getOffset() );
mfp.wrap.append(animatedImg);
openTimeout = setTimeout(function() {
animatedImg.css( mfp._getOffset( true ) );
openTimeout = setTimeout(function() {
showMainContent();
setTimeout(function() {
animatedImg.remove();
image = animatedImg = null;
_mfpTrigger('ZoomAnimationEnded');
}, 16); // avoid blink when switching images
}, duration); // this timeout equals animation duration
}, 16); // by adding this timeout we avoid short glitch at the beginning of animation
// Lots of timeouts...
}
});
_mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
if(mfp._allowZoom()) {
clearTimeout(openTimeout);
mfp.st.removalDelay = duration;
if(!image) {
image = mfp._getItemToZoom();
if(!image) {
return;
}
animatedImg = getElToAnimate(image);
}
animatedImg.css( mfp._getOffset(true) );
mfp.wrap.append(animatedImg);
mfp.content.css('visibility', 'hidden');
setTimeout(function() {
animatedImg.css( mfp._getOffset() );
}, 16);
}
});
_mfpOn(CLOSE_EVENT+ns, function() {
if(mfp._allowZoom()) {
showMainContent();
if(animatedImg) {
animatedImg.remove();
}
}
});
},
_allowZoom: function() {
return mfp.currItem.type === 'image';
},
_getItemToZoom: function() {
if(mfp.currItem.hasSize) {
return mfp.currItem.img;
} else {
return false;
}
},
// Get element postion relative to viewport
_getOffset: function(isLarge) {
var el;
if(isLarge) {
el = mfp.currItem.img;
} else {
el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
}
var offset = el.offset();
var paddingTop = parseInt(el.css('padding-top'),10);
var paddingBottom = parseInt(el.css('padding-bottom'),10);
offset.top -= ( $(window).scrollTop() - paddingTop );
/*
Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.
*/
var obj = {
width: el.width(),
// fix Zepto height+padding issue
height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
};
// I hate to do this, but there is no another option
if( getHasMozTransform() ) {
obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
} else {
obj.left = offset.left;
obj.top = offset.top;
}
return obj;
}
}
});
/*>>zoom*/
/*>>iframe*/
var IFRAME_NS = 'iframe',
......@@ -1582,6 +1824,7 @@ $.magnificPopup.registerModule('gallery', {
}).on('error.mfploader', function() {
item.hasSize = true;
item.loadError = true;
_mfpTrigger('LazyLoadError', item);
}).attr('src', item.src);
}
......
This diff is collapsed.
/* Magnific Popup CSS */
// Modified by Michael Rose
.mfp-bg {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 502;
overflow: hidden;
position: fixed;
background: #0b0b0b;
opacity: 0.8;
filter: alpha(opacity=80); }
.mfp-wrap {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 503;
position: fixed;
outline: none !important;
-webkit-backface-visibility: hidden; }
.mfp-container {
height: 100%;