/*
 * jQuery Linear Gradient 2.1
 * http://bram.us/
 *
 * Copyright 2011 Bramus! <bramus@bram.us>
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 * 
 * Version History
 * v2.1 - 2011.07.13 - First proper packing as a releasable jQuery plugin (Still quick and dirty though – signature of the function still needs to change ... once)
 * v2.0 - 2011.07.12 - Re-imagined (and less intensive) algorithm (Eureka!) - Reduced code by 25%
 *                     Fiddle at http://jsfiddle.net/bramus/bgvf7/ (non-jQuery plugin version though)
 * v1.1 - 2011.07.12 - Code Cleanup + Extensive comments
 *                     Added jQuery.round
 * v1.0 - 2011.07.11 - Initial Release
 * v0.x - 2011.07.11 - See some (incorrectly working!) fiddles at http://jsfiddle.net/bramus/sTP34/7/
 */

(function( jQuery, undefined ){

	// Helper Function: jQuery.round
	// v1 - by Bramus!
	jQuery.extend({
	    round: function(number, digits) {
	        return Math.round(number * Math.pow(10, digits), 10) / Math.pow(10, digits);
	    }
	});

	// The real deal
	//
	// @note: Syntax should change to
	// function("left|right|top|bottom", [perc color, perc color, (perc color)], numBoxes) { ... }
	// That is ... once (I feel like doing so)
	jQuery.fn.linearGradient = function(type, colors, steppings, numBoxes, flip) {
	
		return this.each(function() {
	
			// cast some vars and stuff
			var $this = jQuery(this);
			type = jQuery.inArray(type, ['horizontal', 'vertical']) ? type : 'horizontal';
			      
			// Calc width/height per box
			// Could also be done in % (jQuery.round(100 / numBoxes,2)), but Chrome & Safari have issues with this :-S
			var boxSize = ((type == 'horizontal')
						? 'width: ' + Math.max(1, jQuery.round($this.width() / numBoxes, 2)) + 'px; height: 100%;'
						: 'height: ' + Math.max(1, jQuery.round($this.height() / numBoxes, 2)) + 'px; width: 100%;');
			var boxFloat = ((type == 'horizontal') ? 'float: ' + (flip ? 'right' : 'left') + ';' : '');

			// inject boxes
			for (var i = 0; i < numBoxes; i++) {
				$this.append('<div class="box" style="' + boxSize + ' ' + boxFloat + '"></div>');
			}
	  			      
			jQuery(this).find('.box').each(function(x) {
			
				var colorFrom, 					// Start color of current (sub)gradient
					colorTo, 					// End color of current (sub)gradient
					stepFrom,					// Start stepping value of current (sub)gradient
					stepTo,						// End stepping value of current (sub)gradient
					curBox,						// The current box we're processing (percentage)
					curBoxInGradient,			// The current box in the (sub)gradient we're processing
					numBoxesInGradient,			// The number of boxes in the (sub)gradient
					percentageInGradient;		// How far advanced (percentage-wise) we are in the (sub)gradient
				
				// Calculate which box (out of the total) we're at, as a percentage 
				// (example: box 51 (index 50) out of 100 = 51% or 0.51 down the line)
				curBox = (x+1) / numBoxes;
				
				// Calculate where we are in the gradient (locate curBox in the steppings)
				// stepFrom <-- curBox --> stepTo
				// (example: a gradient is defined to go from 0.3 to 0.7: box 51 (at 0.51) falls between those two values)
				for (var i = 0; i < steppings.length; i++) {
				
					// Aha, we've located the two values curBox falls in between	
					if (curBox <= steppings[i]) {
					
						// Get the from stepping value
						// (example: 0.3)
						stepFrom = steppings[i-1]  || steppings[0];
						
						// Get the to stepping value
						// (example: 0.7)
						stepTo = steppings[i] || steppings[steppings.length-1];
							            
						// Get the starting color (example: #FFFFFF)
						colorFrom = colors[i-1] || colors[0];
						
						// Get the ending color (example: #000000)
						colorTo = colors[i] || colors[steppings.length-1];
						
						// Calculate the number of boxes in the current gradient
						// Example: 100 boxes in total with a difference in stepping of 0.4 = 100 * 0.4 = 40% of all the boxes (which is 100) = 40 boxes the current subgradient should take
						// Example2: 50 boxes in total with a difference in stepping of 0.4 = 50 * 0.4 = 20 boxes in the current gradient
						numBoxesInGradient = (stepTo - stepFrom) * numBoxes;
						
						// the percentage we're at in the current gradient
						// Example:
						// Box 0.51 (curBox) is at 0.21 in the gradient/range which goes from 0.30 (stepFrom) to 0.70
						// 0.21 (or 21%) out of 100 (numBoxes) = 21st box in the current subgradient
						// The 21st box out of a 40 in total for this subgradient (numBoxesInGradient) is 52.5%
						percentageInGradient = (curBox - stepFrom) * numBoxes / numBoxesInGradient;
						
						// jQuery(this).html(curBox + ' > ' + numBoxesInGradient + '<br />');
						
						break;
					
					}
				}
				
				// now apply the correct color (start at colorFrom and transition it towards colorTo, at the correct percentage (curBoxInGradient))
				jQuery(this).css({backgroundColor: jQuery.Color(colorFrom).transition(colorTo, percentageInGradient)});
			
			});
		});
	};

})( jQuery );

