/*
Library for dealing with user generated content
*/
$(function () {
var imageViewRe = /^#image-view\[src="(([^"]|\")+)"\]/;
var $window = $(window);
var $body = $(document.body);
function ImageView() {
var $viewRoot, $view, $animImage, $panzoom;
var _open, _close, hashChange;
var toolbarHeight = 36;
var isOpen = false;
var self = this;
$viewRoot = $(
'
'
);
$view = {
image: $viewRoot.find('img'),
closeBtn: $viewRoot.find('.image-view-close, .image-view-close-icon'),
downloadBtn: $viewRoot.find('.image-view-download')
};
$body.append($viewRoot);
$viewRoot.hide();
$animImage = $('', {'class': 'image-view-anim-image'});
$body.append($animImage);
$animImage.hide();
$panzoom = $view.image.panzoom();
// Get the absolute geometry for an image, relative to the window.
var getGeometry = function (image) {
var offset = $(image).offset();
return {
top: offset.top - $window.scrollTop(),
left: offset.left - $window.scrollLeft(),
width: image.width,
height: image.height
};
};
// Get the absolute geometry of the initial image position on screen.
var getZoomedGeometry = function (imgElement) {
var winWidth = $window.width();
var winHeight = $window.height() - toolbarHeight;
var winRatio = winWidth / winHeight;
var imgRatio = imgElement.width / imgElement.height;
if (winRatio < imgRatio) {
return {
top: toolbarHeight + (winHeight - (winWidth / imgRatio))/2,
left: 0,
width: winWidth,
height: winWidth / imgRatio
};
} else {
return {
top: toolbarHeight,
left: (winWidth - (imgRatio * winHeight))/2,
width: imgRatio * winHeight,
height: winHeight
};
}
};
_open = function(image) {
var domGeometry, zoomGeometry;
// Ensure that we can actually use this image.
if (!image || image.src === undefined || image.width < 1)
return false;
// Handle openness state.
if (isOpen)
obj.close();
isOpen = true;
zoomGeometry = getZoomedGeometry(image);
domGeometry = getGeometry(image);
// Set up viewimage. We're using padding, because then our element's center remains the same.
$view.image.attr('src', image.src);
$view.image.css({
paddingTop: zoomGeometry.top,
paddingLeft: zoomGeometry.left,
width: zoomGeometry.width,
height: zoomGeometry.height
});
// Image in DOM? Perform fancy transition.
if ($.contains(document, image)) {
$view.image.hide();
$viewRoot.fadeIn(1000);
$animImage.attr('src', image.src);
$animImage.show();
$animImage.css(domGeometry);
$animImage.animate(zoomGeometry, 1000, 'swing', function() {
$animImage.hide();
$view.image.show();
$view.image.panzoom('reset');
$view.image.panzoom('resetDimensions');
});
} else {
$view.image.show();
$view.image.panzoom('reset');
$view.image.panzoom('resetDimensions');
$viewRoot.fadeIn(1000);
}
};
_close = function() {
isOpen = false;
$viewRoot.fadeOut(200);
};
this.open = function(img) {
var hash;
_open(img);
// Set up history: when possible, use pushState.
hash = 'image-view[src="' + img.src + '"]';
if (history && history.pushState)
history.pushState('', document.title, location.pathname + location.search + '#' + hash);
else
window.location.hash = hash;
};
this.close = function() {
if (isOpen)
history.back();
};
// Handles hash changes.
hashChange = function() {
var matches = imageViewRe.exec(window.location.hash);
if (isOpen) {
// If we're open and we move off of an image-view URL, close.
if (!matches)
_close();
} else {
// If we're closed and we move on an image-view URL, open.
if (matches && matches.length >= 2) {
var image = $('');
image.on('load', function () {
_open(image[0]);
});
image.attr('src', matches[1]);
}
}
};
// Event handling.
$panzoom.parent().on('mousewheel.focal', function(e) {
e.preventDefault();
var delta = e.delta || e.originalEvent.wheelDelta;
var zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0;
$panzoom.panzoom('zoom', zoomOut, {
increment: 0.025,
animate: false,
focal: e
});
});
$window.resize(function() { $view.image.panzoom('resetDimensions'); });
$window.on('hashchange', function () { return hashChange(); });
$view.closeBtn.click(function() { self.close(); });
$view.downloadBtn.click(function() { location.href = $view.image.attr('src'); });
hashChange();
}
var setupNaturalImageSize = function (image, callback) {
/* Polyfill for browsers that don't setup native image size properties
* @imgElement - Given image to setup native properties for
*/
var $image = $(image);
if ($image.prop('naturalWidth') === undefined) {
var $origImg = $('');
$origImg.on('load', function () {
$image.prop('naturalWidth', $origImg[0].width);
$image.prop('naturalHeight', $origImg[0].height);
callback($image[0]);
});
$origImg.attr('src', $image.attr('src'));
} else {
if ($image.prop('naturalWidth') !== 0) {
callback($image[0]);
} else {
$image.on('load', function () {
callback($image[0]);
});
}
}
};
/* Loop through all images in user-content
* If max-width: 100% is being used, make it clickable
*/
var userImages = $('.user-content img, .platform-content img');
var imageView = new ImageView();
if (userImages.length > 0) {
userImages.each(function () {
// Make images that are shrunken, bigger.
setupNaturalImageSize(this, function (image) {
var $image = $(image);
if ($image.width() < $image.prop('naturalWidth')) {
$image.css('cursor', 'pointer');
}
$image.on('click', function () {
imageView.open(image);
});
});
});
}
});