jQuery.fn.psq_popbox = function(params) {
	var dimmerAnimateMseconds = 1500;
	var popupAnimateMseconds = 800;

	function popImgRemove(params) {
		var $o = $(params.orig);	// original image to pop up

		// animate dimmer to transparency and hide it
		$('#' +  params.dimmer).animate({'opacity': 0.0}, dimmerAnimateMseconds, 
		 function() {$(this).css({'visibility': 'hidden'});});

		// animate popup to original small size and location, remove popup and 
		// display original image
		$('.' + params.sourceClass).animate({
			'width': params.width, 'height': params.height,
			'left': params.left, 'top': params.top
			}, popupAnimateMseconds, function() {
				$('.' + params.sourceClass).remove();
				$o.css({'visibility': 'visible'});
				});
	}

	function getOffset($jqObj) {
		var offset = $jqObj.offset();
		// loop through all of the parents until we get to the top
		while(!$jqObj.offsetParent().is('body')) {
			$jqObj = $jqObj.offsetParent();
			offset.left += $jqObj.offset().left;
			offset.top += $jqObj.offset().top;
		}
		return offset;
	}

	function popImgDo(params, curDomObj) {
		// source of big popup image: 
		// either given with params or source of small original image
		var source = params.source == undefined ? curDomObj.src : params.source;	
		var parent = $("body");
		var str = "<img class='" + params.sourceClass + "' src='" + source + "' />";
		parent.prepend(str);

		var $w = $(window);
		var $d = $(document);
		var $p = $("." + params.sourceClass);	// popup image
		var $o = $(curDomObj);	// original small image to pop up
		var orgWidth = $o.width();
		var orgHeight = $o.height();

		var offset = getOffset($o);
		var left = offset.left;
		var top = offset.top;
		// popup location for big image
		var popupLeft, popupTop, popupWidth, popupHeight;
		popupWidth = $p.width();
		popupHeight = $p.height();
		popupLeft = ($w.width() - popupWidth) / 2;
		popupTop = ($w.height() - popupHeight) / 2;
		
		// take care of possible window scroll
		popupTop += $w.scrollTop();
		popupLeft += $w.scrollLeft();

		// show dimmer division section and animate it to popup opacity
		$('#' + params.dimmer).css({
				'width': $d.width(), 'height': $d.height(),
				'opacity': 0, 'visibility': 'visible'})
			.animate({'opacity': 0.85}, dimmerAnimateMseconds);

		// hide original image
		$o.css({'visibility': 'hidden'});

		// show new popup image in place of original image
		$p.css({'visibility': 'visible',
			'width': orgWidth, 'height': orgHeight,
			'left': left, 'top': top})
			.click(function() {
				popImgRemove({
					'sourceClass': params.sourceClass,
					'orig': curDomObj,
					'width': orgWidth, 'height': orgHeight,
					'left': left, 'top': top,
					'dimmer': params.dimmer
					});
			});

		// display popup image centered to browser at its full resolution through animation
		$p.animate({
			'width': popupWidth, 'height': popupHeight,
			'left': popupLeft, 'top': popupTop
			}, popupAnimateMseconds);
	}

	var default_params = {source: undefined, sourceClass: 'popImg', dimmer: 'dimmer'};
	params = jQuery.extend(default_params, params);

	// if windows resized, resize dimmer too
	$(window).resize(function() {
		$('#' + params.dimmer).css({
			'width': $(document).width(), 'height': $(document).height()});
	});

	return this.each(function() {
		var curDomObj = this;
 		$(curDomObj).click(function() {
 			// If source of popup is not the image already in DOM then 
 			// pre-load an image and wait till loaded.
 			// If already loaded then do not load again.
 			// (undefined = use source of DOM object)
			if (params.source != undefined && params.source != curDomObj.src && !curDomObj.bigImgLoaded) {
				var aux_img = new Image();
				aux_img.src = params.source; 
				$(aux_img).load(function() {
					curDomObj.bigImgLoaded = 1;
					popImgDo(params, curDomObj);
				});
			} 
			else
 				popImgDo(params, curDomObj);
    	});
    });
}

