/* jQuery ColorPicker
   Written by Virgil Reboton(vreboton@gmail.com)
   
   ColorPicker function structures and attahcment is base on
   jQuery UI Date Picker v3.3beta
   by Marc Grabanski (m@marcgrabanski.com) and Keith Wood (kbwood@virginbroadband.com.au).
   
   ColorPicker render data is base on
   http://www.mattkruse.com/javascript/colorpicker/
   by Matt Kruse

*/
   
(function($) { // hide the namespace

function colorPicker()
{
	this._nextId = 0; // Next ID for a time picker instance
	this._inst = []; // List of instances indexed by ID
	this._curInst = null; // The current instance in use
	this._colorpickerShowing = false;
	this._colorPickerDiv = $('<div id="colorPickerDiv"></div>');
}
$.extend(colorPicker.prototype, {
	/* Class name added to elements to indicate already configured with a time picker. */
	markerClassName: 'hasColorPicker',

	/* Register a new time picker instance - with custom settings. */
	_register: function(inst) {
		var id = this._nextId++;
		this._inst[id] = inst;
		return id;
	},

	/* Retrieve a particular time picker instance based on its ID. */
	_getInst: function(id) {
		return this._inst[id] || id;
	},
	
	/* Handle keystrokes. */
	_doKeyDown: function(e) {
        var inst = $.colorPicker._getInst(this._colId);
		if ($.colorPicker._colorpickerShowing) {
			switch (e.keyCode) {
				case 9: 
				    // hide on tab out
				    $.colorPicker.hideColorPicker();
                    break; 

				case 27: 
				    // hide on escape
				    $.colorPicker.hideColorPicker();
					break;
            }
		}
		else if (e.keyCode == 40) { // display the time picker on down arrow key
			$.colorPicker.showFor(this);
		}
	},

/* Handle keystrokes. */
	_resetSample: function(e) {
        var inst = $.colorPicker._getInst(this._colId);
		inst._sampleSpan.css('background-color', inst._input.value);
		alert(inst._input.value);
	},
	
    /* Does this element have a particular class? */
	_hasClass: function(element, className) {
		var classes = element.attr('class');
		return (classes && classes.indexOf(className) > -1);
	},

    /* Pop-up the time picker for a given input field.
	   @param  control  element - the input field attached to the time picker or
	                    string - the ID or other jQuery selector of the input field or
	                    object - jQuery object for input field
	   @return the manager object */
	showFor: function(control) {
		control = (control.jquery ? control[0] :
			(typeof control == 'string' ? $(control)[0] : control));
		var input = (control.nodeName && control.nodeName.toLowerCase() == 'input' ? control : this);
		
		if ($.colorPicker._lastInput == input) { return; }
		if ($.colorPicker._colorpickerShowing) { return; }
		
		var inst = $.colorPicker._getInst(input._colId);
		
		$.colorPicker.hideColorPicker();
		$.colorPicker._lastInput = input;
		
		if (!$.colorPicker._pos) { // position below input
			$.colorPicker._pos = $.colorPicker._findPos(input);
			$.colorPicker._pos[1] += input.offsetHeight; // add the height			
		}
		
		var isFixed = false;
		$(input).parents().each(function() {
			isFixed |= $(this).css('position') == 'fixed';
		});
		
		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
			$.colorPicker._pos[0] -= document.documentElement.scrollLeft;
			$.colorPicker._pos[1] -= document.documentElement.scrollTop;
		}
	
	    inst._colorPickerDiv.css('position', ($.blockUI ? 'static' : (isFixed ? 'fixed' : 'absolute'))).css('left', $.colorPicker._pos[0] + 'px').css('top', $.colorPicker._pos[1]+1 + 'px');
	
		$.colorPicker._pos = null;
		$.colorPicker._showColorPicker(inst);

		return this;
	},

    /* Find an object's position on the screen. */
	_findPos: function(obj) {
		while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
			obj = obj.nextSibling;
		}
		var curleft = curtop = 0;
		if (obj && obj.offsetParent) {
			curleft = obj.offsetLeft;
			curtop = obj.offsetTop;
			while (obj = obj.offsetParent) {
				var origcurleft = curleft;
				curleft += obj.offsetLeft;
				if (curleft < 0) {
					curleft = origcurleft;
				}
				curtop += obj.offsetTop;
			}
		}
		return [curleft,curtop];
	},
	
	/* Close time picker if clicked elsewhere. */
	_checkExternalClick: function(event) {
		if (!$.colorPicker._curInst)
		{
			return;
		}
		var target = $(event.target);		
				
		if ((target.parents("#colorPickerDiv").length == 0) && $.colorPicker._colorpickerShowing && !($.blockUI))
		{
		    if (target.text() != $.colorPicker._curInst._colorPickerDiv.text())
		        $.colorPicker.hideColorPicker();
		}
	},

    /* Hide the time picker from view.
	   @param  speed  string - the speed at which to close the time picker
	   @return void */
	hideColorPicker: function(s) {
		var inst = this._curInst;
		if (!inst) {
			return;
		}		
 
		if (this._colorpickerShowing)
		{
			this._colorpickerShowing = false;
			this._lastInput = null;
			
			this._colorPickerDiv.css('position', 'absolute').css('left', '0px').css('top', '-1000px');
			
			if ($.blockUI)
			{
				$.unblockUI();
				$('body').append(this._colorPickerDiv);
			}
        
            this._curInst = null;        			
		}
		
		if (inst._input[0].value != $.css(inst._sampleSpan,'background-color'))
		{
		    inst._sampleSpan.css('background-color',inst._input[0].value);
		}
	},

	/* Attach the time picker to an input field. */
	_connectColorPicker: function(target, inst) {
		var input = $(target);
		if (this._hasClass(input, this.markerClassName)) { return; }
		
		$(input).attr('autocomplete', 'OFF'); // Disable browser autocomplete		
		inst._input = $(input);	
		
		// Create sample span
		inst._sampleSpan = $('<span class="ColorPickerDivSample" style="background-color:' + inst._input[0].value + ';height:' + inst._input[0].offsetHeight + ';">&nbsp;</span>');
		input.after(inst._sampleSpan);
		
		inst._sampleSpan.click(function() {
		    input.focus();
		});
								
		input.focus(this.showFor);
		
		input.addClass(this.markerClassName).keydown(this._doKeyDown);
		input[0]._colId = inst._id;		
	},
	
	
	/* Construct and display the time picker. */
	_showColorPicker: function(id) {
		var inst = this._getInst(id);
		this._updateColorPicker(inst);
		
        inst._colorPickerDiv.css('width', inst._startTime != null ? '10em' : '6em');
		
		inst._colorPickerDiv.show('fast');
		if (inst._input[0].type != 'hidden')
        {
		    inst._input[0].focus();
        }
		
		this._curInst = inst;
		this._colorpickerShowing = true;
	},

	/* Generate the time picker content. */
	_updateColorPicker: function(inst) {
		inst._colorPickerDiv.empty().append(inst._generateColorPicker());
		if (inst._input && inst._input[0].type != 'hidden')
		{
			inst._input[0].focus();
			
            $("td.color", inst._timePickerDiv).unbind().mouseover(function() {
                inst._sampleSpan.css('background-color', $.css(this,'background-color'));
            }).click(function() {
                inst._setValue(this);
            });
        }
    } 
	
});

/* Individualised settings for time picker functionality applied to one or more related inputs.
   Instances are managed and manipulated through the TimePicker manager. */
function ColorPickerInstance()
{
	this._id = $.colorPicker._register(this);
	this._input = null;
	this._colorPickerDiv = $.colorPicker._colorPickerDiv;
	this._sampleSpan = null;
}

$.extend(ColorPickerInstance.prototype, {
	/* Get a setting value, defaulting if necessary. */
	_get: function(name) {
		return (this._settings[name] != null ? this._settings[name] : $.colorPicker._defaults[name]);
	},
	
    _getValue: function () {
        if (this._input && this._input[0].type != 'hidden' && this._input[0].value != "")
		{
			return this._input[0].value;
        }
        return null;
    },
	
	_setValue: function (sel) {
        // Update input field
        if (this._input && this._input[0].type != 'hidden')
		{
		    this._input[0].value = $.attr(sel,'title');
			$(this._input[0]).change();
        }
        
        // Hide picker
        $.colorPicker.hideColorPicker();
    },
   	
	/* Generate the HTML for the current state of the time picker. */
	_generateColorPicker: function() {
        // Code to populate color picker window
        var colors  = new Array("000000","000033","000066","000099","0000CC","0000FF","330000","330033","330066","330099","3300CC",
                                "3300FF","660000","660033","660066","660099","6600CC","6600FF","990000","990033","990066","990099",
                                "9900CC","9900FF","CC0000","CC0033","CC0066","CC0099","CC00CC","CC00FF","FF0000","FF0033","FF0066",
							    "FF0099","FF00CC","FF00FF","003300","003333","003366","003399","0033CC","0033FF","333300","333333",
							    "333366","333399","3333CC","3333FF","663300","663333","663366","663399","6633CC","6633FF","993300",
							    "993333","993366","993399","9933CC","9933FF","CC3300","CC3333","CC3366","CC3399","CC33CC","CC33FF",
							    "FF3300","FF3333","FF3366","FF3399","FF33CC","FF33FF","006600","006633","006666","006699","0066CC",
							    "0066FF","336600","336633","336666","336699","3366CC","3366FF","666600","666633","666666","666699",
							    "6666CC","6666FF","996600","996633","996666","996699","9966CC","9966FF","CC6600","CC6633","CC6666",
							    "CC6699","CC66CC","CC66FF","FF6600","FF6633","FF6666","FF6699","FF66CC","FF66FF","009900","009933",
							    "009966","009999","0099CC","0099FF","339900","339933","339966","339999","3399CC","3399FF","669900",
							    "669933","669966","669999","6699CC","6699FF","999900","999933","999966","999999","9999CC","9999FF",
							    "CC9900","CC9933","CC9966","CC9999","CC99CC","CC99FF","FF9900","FF9933","FF9966","FF9999","FF99CC",
							    "FF99FF","00CC00","00CC33","00CC66","00CC99","00CCCC","00CCFF","33CC00","33CC33","33CC66","33CC99",
							    "33CCCC","33CCFF","66CC00","66CC33","66CC66","66CC99","66CCCC","66CCFF","99CC00","99CC33","99CC66",
							    "99CC99","99CCCC","99CCFF","CCCC00","CCCC33","CCCC66","CCCC99","CCCCCC","CCCCFF","FFCC00","FFCC33",
							    "FFCC66","FFCC99","FFCCCC","FFCCFF","00FF00","00FF33","00FF66","00FF99","00FFCC","00FFFF","33FF00",
							    "33FF33","33FF66","33FF99","33FFCC","33FFFF","66FF00","66FF33","66FF66","66FF99","66FFCC","66FFFF",
							    "99FF00","99FF33","99FF66","99FF99","99FFCC","99FFFF","CCFF00","CCFF33","CCFF66","CCFF99","CCFFCC",
							    "CCFFFF","FFFF00","FFFF33","FFFF66","FFFF99","FFFFCC","EEEEEE","111111","222222","333333","444444",
							    "555555","666666","777777","888888","999999","A5A5A5","AAAAAA","BBBBBB","C3C3C3","CCCCCC","D2D2D2",
							    "DDDDDD","E1E1E1","FFFFFF");
							    
        var total = colors.length;
        var width = 18;
	    var html = "<table border='1px' cellspacing='0' cellpadding='0'>";
	    
	    for (var i=0; i<total; i++)
	    {
		    if ((i % width) == 0) { html += "<tr>"; }
		    
		    html += '<td class="color" title="' + colors[i] + '" style="background-color:#' + colors[i] + '"><label>&nbsp;&nbsp;&nbsp;</label></td>';
		    
		    if ( ((i+1)>=total) || (((i+1) % width) == 0))
		    {
		        html += "</tr>";
            }
		}
		
		html += '<tr><td title="" style="background-color:#999" class="color" colspan="' + width + '" align="center"><label>No Color</label></td></tr>'
		
		html += "</table>";
    
        return html
	}
	
});


/* Attach the time picker to a jQuery selection.
   @param  settings  object - the new settings to use for this time picker instance (anonymous)
   @return jQuery object - for chaining further calls */
$.fn.attachColorPicker = function() {
	return this.each(function() {
		var nodeName = this.nodeName.toLowerCase();
		if (nodeName == 'input')
		{
			var inst = new ColorPickerInstance();
			$.colorPicker._connectColorPicker(this, inst);
		} 		
	});
};

$.fn.getValue = function() {
	var inst = (this.length > 0 ? $.colorPicker._getInst(this[0]._colId) : null);
	return (inst ? inst._getValue() : null);
};

$.fn.setValue = function(value) {
	var inst = (this.length > 0 ? $.colorPicker._getInst(this[0]._colId) : null);
	if (inst) inst._setValue(value);
};

/* Initialise the time picker. */
$(document).ready(function() {
	$.colorPicker = new colorPicker(); // singleton instance
	$(document.body).append($.colorPicker._colorPickerDiv).mousedown($.colorPicker._checkExternalClick);
});

})(jQuery);