(function($) { // Compliant with jquery.noConflict()

$.fn.jCarouselLite = function(o) { 
	o = $.extend({ 
		btnPrev: null, 
		btnNext: null, 
		btnGo: null, 
		mouseWheel: false, 
		auto: null,
		speed: 200, 
		easing: null, 
		vertical: false, 
		circular: true, 
		visible: 3, 
		start: 0, 
		scroll: 1, 
		rows: 1, //ADDED: Property to allow multiple rows
		beforeStart: null,
		afterEnd: null 
	}, o || {});
	
	return this.each(function() { // Returns the element collection. Chainable.
	
		var running = false,
		animCss = o.vertical ? "top" : "left",
		sizeCss = o.vertical ? "height" : "width";
		var div = $(this),
		ul = $("ul", div),
		tLi = $("li", ul),
		tl = tLi.size(),
		v = o.visible;
		var rowCss = o.vertical ? "width" : "height"; //ADDED: rowCss is used to set the height/width of the viewport based on how many rows are showing
	
		if (o.circular) {
			ul.prepend(tLi.slice(tl - v - 1 + 1).clone())
				.append(tLi.slice(0, v).clone());
				o.start += v;
		}
	
		var li = $("li", ul),
		itemLength = li.size(),
		curr = o.start;
		div.css("visibility", "visible");
	
		li.css({ overflow: "hidden", float: o.vertical ? "none" : "left" });
		ul.css({ margin: "0", padding: "0", position: "relative", "list-style-type": "none", "z-index": "1" });
		div.css({ overflow: "hidden", position: "relative", "z- index": "2", left: "0px" });
	
		var liSize = o.vertical ? height(li) : width(li); // Full li size(incl margin)-Used for animation
		var liRowSize = o.vertical ? width(li) : height(li); // ADDED: size of the li's row
		var ulSize = ((liSize * itemLength) / o.rows) + (liSize / 1.5); // size of full ul(total length, not just for the visible items)
		var divSize = liSize * v; // size of entire div(total length for just the visible items)
		var rowSize = liRowSize * o.rows; //ADDED: gets the size in pixels of the height/width of the viewport
	
		li.css({ width: li.width(), height: li.height() });
		ul.css(sizeCss, ulSize + "px").css(animCss, -(curr * liSize));
	
		div.css(sizeCss, divSize + "px"); // Width of the DIV. length of visible images
		div.css(rowCss, rowSize + "px"); // ADDED: Height of the DIV
	
		//ADDED: special consideration for vertical carousels with multiple rows
		if (o.vertical && o.rows > 1) {
			ul.children().filter(function(index) {
				return ((index + 1) % o.rows > 0);
			}).css({ float: "left", width: "" });
		}
	
		if (o.btnPrev) $(o.btnPrev).click(function() { return go(curr - (o.scroll)); });
	
		if (o.btnNext) $(o.btnNext).click(function() { return go(curr + (o.scroll)); });
		
		if (o.btnGo) $.each(o.btnGo, function(i, val) { $(val).click(function() { return go(o.circular ? o.visible + i : i); }); });
		
		if (o.mouseWheel && div.mousewheel) div.mousewheel(function(e, d) { return d > 0 ? go(curr - o.scroll) : go(curr + o.scroll); });
		
		if (o.auto) setInterval(function() { go(curr + o.scroll); }, o.auto + o.speed);
		
		function vis() {
			return li.slice(curr).slice(0, v);
		};
		
		function go(to) {
			if (!running) {
		
				if (o.beforeStart) o.beforeStart.call(this, vis());
		
				if (o.circular) { // If circular we are in first or last, then goto the other end
					if (to <= o.start - v - 1) { // If first, then goto last
						ul.css(animCss, -((itemLength - (v * 2)) * liSize) + "px"); // If "scroll" > 1, then the "to" might not be equal to the condition; it can be lesser depending on the number of elements.
						curr = to == o.start - v - 1 ? itemLength - (v * 2) - 1 : itemLength - (v * 2) - o.scroll;
					} else if (to >= itemLength - v + 1) { // If last, then goto first
						ul.css(animCss, -((v) * liSize) + "px"); // If "scroll" > 1, then the "to" might not be equal to the condition; it can be greater depending on the number of elements.
						curr = to == itemLength - v + 1 ? v + 1 : v + o.scroll;
					} else curr = to;
				} else { // If non-circular and to points to first or last, we just return. //ADDED: This determines when to stop scrolling when more than 1 row is viewable
					if (to < 0 || to > ((itemLength - v) / o.rows)) return true; else curr = to;
				} // If neither overrides it, the curr will still be "to" and we can proceed.
				
				running = true;
				
				ul.animate( animCss == "left" ? { left: -(curr * liSize)} : { top: -(curr * liSize) }, o.speed, o.easing, function() {
					if (o.afterEnd) o.afterEnd.call(this, vis()); running = false;
					}); // Disable buttons when the carousel reaches the last/first, and enable when not if (!o.circular) { $(o.btnPrev + "," + o.btnNext).removeClass("disabled"); //ADDED: This determines when to add the disabled class to the link when more than 1 row is viewable $((curr - o.scroll < 0 && o.btnPrev) || (curr + o.scroll > ((itemLength - v) / o.rows) && o.btnNext) || [] ).addClass("disabled"); }
			
			}
			return false;
		};
	});
};

	function css(el, prop) {
		return parseInt($.css(el[0], prop)) || 0;
	};
	
	function width(el) {
		return el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
	};
	
	function height(el) {
		return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom');
	};

})(jQuery);
