function CSSWrap(options, element)
{
	for (var prop in options) $(element).css(prop, options[prop]);
}

/*
SNIPER PLUGIN
=============
Author:   Andrija Brljak (Binom)
Modified: 10.11.2010
Version:  1.0.1

OPTIONS PROPERTIES:
===================
.zoom      -> html element    -> container for magnified display
.bindEvent -> string          -> event name to be bound for triggering the plugin (e.g. "mouseover", "click")
.onOpen    -> function(thumb) -> event callback for open
.onClose   -> function(thumb) -> event callback for close
.onError   -> function(thumb) -> event callback for image load error

EXAMPLE USAGE:
==============
<a href="full.jpg" id="myThumb"><img src="thumb.jpg" alt="" /></a>
<div id="zoom"></div>
<script type="text/javascript">
$("#myThumb").sniper({ zoom:"#zoom", loading:"#loading", bindEvent:"mouseover" });
</script>
*/
function SniperPlugin(options, thumb)
{
	if ($(thumb).is("a"))
	{
		var Status = 0;
		var Img = $(document.createElement("img")).attr("src", $(thumb).attr("href")).css("position", "relative").error(function () { Status = -1; }).load(function () { Status = 1; });
		var Hide = function (e)
		{
			$(options.zoom).hide();
			if (options.onClose) options.onClose(thumb);
		}
		var Init = function (e)
		{
			if (Status >= 0)
			{
				$(options.zoom).children("img").remove();
				$(options.zoom).append(Img).show();
				if (options.onOpen) options.onOpen(thumb);
			}
			else
			{
				if (options.onError) options.onError(thumb);
			}
		};
		var ZoomAt = function (e)
		{
			if ($(options.zoom).is(":visible"))
			{
				var imgWidth = $(Img).width();
				var imgHeight = $(Img).height();
				var zoomWidth = $(options.zoom).width();
				var zoomHeight = $(options.zoom).height();
				var left = (imgWidth * (e.pageX - $(ThumbImg).offset().left) / $(ThumbImg).width() - (zoomWidth * 0.5)) * -1;
				var top = (imgHeight * (e.pageY - $(ThumbImg).offset().top) / $(ThumbImg).height() - (zoomHeight * 0.5)) * -1;
				if (left > 0) left = 0;
				if (top > 0) top = 0;
				if (left < (imgWidth - zoomWidth) * -1) left = (imgWidth - zoomWidth) * -1;
				if (top < (imgHeight - zoomHeight) * -1) top = (imgHeight - zoomHeight) * -1;
				var zoomImg = $(options.zoom).children("img");
				$(zoomImg).css("left", left).css("top", top);
			}
		};
		$(options.zoom).css("overflow", "hidden").css("position", "relative").hide();
		var ThumbImg = $(thumb).children("img").load(function ()
		{
			$(this).css("position", "relative").css("top", "50%").css("left", "50%").css("margin-left", $(this).width() * -0.5).css("margin-top", $(this).height() * -0.5);
		});
		$(ThumbImg).attr("src", $(ThumbImg).attr("src"));
		$(thumb).css("display", "block").css("overflow", "hidden").css("position", "relative").attr("href", "#").click(function () { return false; }).mousemove(ZoomAt).mouseout(Hide).bind(options.bindEvent != undefined ? options.bindEvent : "mouseover", function (e)
		{
			$(options.zoom).is(":visible") ? Hide(e) : Init(e);
		});
	}
}
(function ($)
{
	$.fn.extend(
	{
		sniper: function (options)
		{
			return this.each(function ()
			{
				$(this).data("sniper", new SniperPlugin(options, this));
			});
		}
	});
})(jQuery);

/*

SCROLLER PLUGIN
===============
Author:   Andrija Brljak (Binom)
Modified: 12.11.2010
Version:  0.9.1

*/
function ScrollerPlugin(options, container)
{
	if (options.grid)
	{
		if (!options.grid.spacing) options.grid.spacing = 0;
		if (isNaN(options.grid.x) || options.grid.x < 1) options.grid.x = 1;
		if (isNaN(options.grid.y) || options.grid.y < 1) options.grid.y = 1;
	}
	if (!options.speed) options.speed = 250;
	if (options.vertical == undefined) options.vertical = false;
	var offsetX = 0;
	var offsetY = 0;
	var jumpCount = 0;
	var currentItem = 0;
	var isStopped = true;
	var Canvas = $(container).children(":first").css("position", "absolute").css("width", 5000).css("height", 5000);
	var OriginalItems = $(Canvas).children();
	var CenterRelative = function (e)
	{
		$(e).cssWrap({ position: "relative", left: "50%", top: "50%" });
	}
	var CenterGridItem = function (e)
	{
		if ($(e).is("a"))
		{
			$(e).css("display", "block").css("overflow", "hidden").css("height", "100%").css("width", "100%").css("left", 0).css("top", 0);
			var a = $(e).children(":first").css("display", "block").css("margin-left", $(e).children(":first").width() * -0.5).css("margin-top", $(e).children(":first").height() * -0.5)
			CenterRelative(a);
		}
		else
		{
			$(e).css("margin-left", $(e).width() * -0.5).css("margin-top", $(e).height() * -0.5);
		}
	};
	if (options.grid)
	{
		var boxWidth = ($(container).width() - ((options.grid.x - 1) * options.grid.spacing)) / options.grid.x;
		var boxHeight = ($(container).height() - ((options.grid.y - 1) * options.grid.spacing)) / options.grid.y;
		$(OriginalItems).each(function (i)
		{
			var wrapper = $(document.createElement("div"));
			$(wrapper).css("overflow", "hidden").css("width", boxWidth).css("height", boxHeight).css("position", "relative");
			$(wrapper).css("margin-right", options.grid.spacing).css("margin-bottom", options.grid.spacing);
			if (!options.vertical) $(wrapper).css("float", "left");
			CenterRelative(this);
			if ($(this).is("img") && this.complete == false)
			{
				$(this).load(function () { CenterGridItem(this); });
			}
			else
			{
				CenterGridItem(this);
			}
			$(Canvas).append(wrapper);
			$(wrapper).append(this);
		});
	}
	var Size = function (element) { return { x: $(element).position().left, y: $(element).position().top, width: $(element).outerWidth(true), height: $(element).outerHeight(true) }; };
	var Tween = function (callback, tweenSpeed, tweenEase)
	{
		if (!options.vertical)
		{
			$(Canvas).animate({ marginLeft: offsetX }, options.speed, "swing", function ()
			{
				isStopped = true;
				if (callback) callback();
				E_OnScrollComplete();
			});
		}
		else
		{
			$(Canvas).animate({ marginTop: offsetY }, options.speed, "swing", function ()
			{
				isStopped = true;
				if (callback) callback();
				E_OnScrollComplete();
			});
		}
	};
	var E_OnBeforeScroll = function () { if (options.onBeforeScroll) options.onBeforeScroll(this); }
	var E_OnScrollComplete = function () { if (options.onScrollComplete) options.onScrollComplete(this); }
	var MovePrev = function (callback)
	{
		if (isStopped)
		{
			var doMove = false;
			var Items = $(Canvas).children();
			for (var i = 0; i < Items.length; i++)
			{
				if ((Size($(Items[i])).x >= $(container).width() && options.vertical == false) ||
                    (Size($(Items[i])).y >= $(container).height() && options.vertical == true))
				{
					doMove = true; break;
				}
			}
			if (doMove)
			{
				E_OnBeforeScroll();
				isStopped = false;
				var last = $(Canvas).children(":last");
				offsetX = 0;
				offsetY = 0;
				$(Canvas).css(options.vertical ? "margin-top" : "margin-left", options.vertical ? $(last).outerHeight(true) * -1 : $(last).outerWidth(true) * -1).prepend(last);
				SetCurrentItem(-1);
				Tween(callback);
			}
		}
		return false;
	};
	var MoveNext = function (callback)
	{
		if (isStopped)
		{
			var doMove = false;
			var Items = $(Canvas).children();
			for (var i = 0; i < Items.length; i++)
			{
				if ((Size($(Items[i])).x + offsetX >= $(container).width() && options.vertical == false) ||
                    (Size($(Items[i])).y + offsetY >= $(container).height() && options.vertical == true))
				{
					doMove = true;
					break;
				}
			}

			if (doMove)
			{
				E_OnBeforeScroll();
				isStopped = false;
				var first = $(Canvas).children(":first");
				var dim = Size(first);
				offsetX = (dim.width + dim.x) * -1;
				offsetY = (dim.height + dim.y) * -1;
				SetCurrentItem(1);
				Tween(function ()
				{
					$(Canvas).append(first).css(options.vertical ? "margin-top" : "margin-left", 0);
					offsetX = 0;
					offsetY = 0;
					if (callback) callback();
				});
			}
		}
		return false;
	};
	this.GetIndex = function () { return currentItem; };
	this.JumpBy = function (step)
	{
		if (step != 0)
		{
			jumpCount = 0;
			step > 0 ? JumpNext(step) : JumpPrev(Math.abs(step));
		}
		return false;
	};
	this.JumpTo = function (index) { return this.JumpBy(index - currentItem); };
	var JumpPrev = function (step) { MovePrev(function () { JumpStep(JumpPrev, step); }); };
	var JumpNext = function (step) { MoveNext(function () { JumpStep(JumpNext, step); }); };
	var JumpStep = function (closure, limit) { jumpCount++ < limit - 1 ? closure(limit) : jumpCount = 0; };
	var SetCurrentItem = function (increment)
	{
		currentItem += increment;
		var len = $(Canvas).children().length;
		if (currentItem == len) currentItem = 0;
		if (currentItem < 0) currentItem = len - 1;
	};
	$(options.prev).click(function () { return MovePrev(); });
	$(options.next).click(function () { return MoveNext(); });
	$(container).css("position", "relative").css("overflow", "hidden");
	if (options.onItemsReady) options.onItemsReady(this, options.grid ? $(Canvas).children("div").children() : $(Canvas).children());
}

/*

MAX.IMG PLUGIN
===============
Author:   Andrija Brljak (Binom)
Modified: 23.03.2011
Version:  1.0

*/

function ApplyMaxImg(selector)
{
	$(selector).each(function (i)
	{
		var child = $(this).children().remove();
		var wrapper = $(document.createElement("div")).append(child);
		$(this).append(wrapper);
		var img = null;
		if ($(child).is("img")) img = child[0];
		if ($(child).children("img").length == 1) img = $(child).children("img")[0];
		var maxWidth = $(this).width();
		var maxHeight = $(this).height();
		var center = function (w, h)
		{
			var left = Math.round((maxWidth - w) * 0.5);
			var top = Math.round((maxHeight - h) * 0.5);
			$(wrapper).css("position", "absolute").css("margin-top", top).css("margin-left", left);
			$(img).css("visibility", "visible");
		};
		var loadComplete = function ()
		{
			if (img.width == 0 || img.height == 0)
			{
				var fake = $(document.createElement("img")).load(function (e)
				{
					center(this.width, this.height);
					$(this).remove();
				}).attr("src", $(img).attr("src"));
			}
			else
			{
				center(img.width, img.height);
			}
		}
		img.complete ? loadComplete() : $(img).load(loadComplete);
	});
}

(function ($)
{
	$.fn.extend(
	{
		cssWrap: function (options)
		{
			return this.each(function ()
			{
				new CSSWrap(options, this);
			});
		},
		scroller: function (options)
		{
			return this.each(function ()
			{
				$(this).data("scroller", new ScrollerPlugin(options, this));
			});
		},
		maxImg: function (selector)
		{
			return this.each(function ()
			{
				new ApplyMaxImg(selector, this);
			});
		}
	});
})(jQuery);
