/*
 * UPDATED: 12.19.07
 *
 * jNice
 * by Sean Mooney (sean@whitespace-creative.com)
 *
 * To Use: place in the head
 *  <link href="inc/style/jNice.css" rel="stylesheet" type="text/css" />
 *  <script type="text/javascript" src="inc/js/jquery.jNice.js"></script>
 *
 * And apply the jNice class the form you want to style
 *
 * To Do: Add textareas, Add File upload
 *
 ******************************************** */
(function($){
	$.fn.jNice = function(settings){
		var self = this;
		var safari = $.browser.safari; /* We need to check for safari to fix the input:text problem */

		// don't confuse safari with chrome
		//if (safari && navigator.userAgent.indexOf('Chrome') != -1) {
		//    safari = false;
		//}

		// The fix for Safari below doesn't apply to recent versions
		safari = false;

		var thisWidth = '';
		settings = jQuery.extend({
		    selectOffset: '4',
		    selectMinWidth: '65',
		    removeInputClass: '',
		    enableButtons: true,
		    enableTextFields: true,
		    enableSelectFields: true,
		    enableCheckboxes: false,
		    enableRadios: false
		}, settings);

		/* each form */
		this.each(function(){
			/***************************
			  Buttons
			 ***************************/
			if(settings.enableButtons) {
    			var setButton = function(){

    			    //$(this).after('<button id="'+ this.id +'" title="'+ this.title +'" rel="'+ this.rel +'" name="'+ this.name +'" type="'+ this.type +'" class="jNiceButton '+ this.className +'" value="'+ this.value +'"><span><span>'+ $(this).attr('value') +'</span></span></button>').remove();

    				// IE posts the innerHTML of a button as its value
    				// so create a hidden element (onclick... removing others) to pass the real value
    				var btn = $('<button id="'+ this.id +'" title="'+ this.title +'" rel="'+ this.rel +'" name="'+ this.name +'" type="'+ this.type +'" class="jNiceButton '+ this.className +'" value="'+ this.value +'"><span><span>'+ $(this).attr('value') +'</span></span></button>');
    				btn.click(function(){
    				    // parse the value assuming it is the inner text of the button
    				    var val = $(this).attr('value');
    				    var tmp = $(val).text();
    				    var name = $(this).attr('name');

    				    // if the value is not wrapped by an element tmp will be empty
    				    // so val should be the correct value attribute
    				    val = tmp ? tmp : val;

    				    // remove previously added submitValue hidden elements
    				    if (typeof val != 'undefined' && typeof name != 'undefined') {
        				    $('.jNiceTempSubmitValue').remove();

        				    // IE6 posts the value of all buttons on a form
        				    // so make this buttons value teh last element on the form
        				    // to overwrite previous elements
        				    $(this).parents('form:eq(0)').append('<span class="jNiceTempSubmitValue" style="display: none;"><input type="hidden" name="'+ name +'" value="'+ val +'" /></span>');
    				    }
    				});
    				$(this).after(btn).remove();

    				//alert('<button id="'+ this.id +'" title="'+ this.title +'" rel="'+ this.rel +'" name="'+ this.name +'" type="'+ this.type +'" class="jNiceButton '+ this.className +'" value="'+ this.value +'"><span><span>'+ $(this).attr('value') +'</span></span></button>');

    				if (typeof $('#' + this.id)[0] != 'undefined') {
    				    $('#' + this.id)[0].onclick = $(this)[0].onclick;
    				}
    				$('button.jNiceButton').hover(function() {
    				    $(this).children('span').addClass('hover');
    				},function() {
    				    $(this).children('span').removeClass('hover');
    				});
    			};
    			$('input:submit, input:reset, input:button', this).each(setButton);
		    }

			/***************************
			  Text Fields
			 ***************************/
			if(settings.enableTextFields) {
    			var setText = function(){
    				var $input = $(this);
    				var $inputclass = $(this).attr('class');
    				if(settings.removeInputClass && $inputclass) {
    				    $(this).attr('class',$(this).attr('class').replace(settings.removeInputClass, ''));
    				}
    				$input.addClass("jNiceInput").wrap('<div class="jNiceInputWrapper"><div class="jNiceInputInner"><div></div></div></div>');
    				var $wrapper = $input.parents('div.jNiceInputWrapper');
    				thisWidth = jnice_get_real_width($(this));
    				$wrapper.css("width", thisWidth+10);
    				if($inputclass) {
    				    $wrapper.addClass($inputclass);
    				}
    				$input.focus(function(){
    					$wrapper.addClass("jNiceInputWrapper_hover");
    				}).blur(function(){
    					$wrapper.removeClass("jNiceInputWrapper_hover");
    				});
    			};
    			$('input:text, input:password', this).each(setText);
    			/* If this is safari we need to add an extra class */
    			if (safari){
    			    $('.jNiceInputWrapper').each(function(){
    			        thisWidth = jnice_get_real_width($(this));
    			        $(this).addClass('jNiceSafari').find('input').css('width', thisWidth+11);
    			    });
    			}
		    }

			/***************************
			  Selects
			 ***************************/
			if(settings.enableSelectFields) {
    			$('select:visible', this).not('select[multiple]').each(function(index){
    				var $select = $(this);
    				thisWidth = jnice_get_real_width($select);
    				thisMinWidth = parseInt(settings.selectMinWidth);
    				/* First thing we do is Wrap it */
    				$(this).addClass('jNiceHidden').wrap('<div class="jNiceSelectWrapper"></div>');
    				var $wrapper = $(this).parent().css({zIndex: 100-index});
    				/* Now add the html for the select */
    				$wrapper.prepend('<div><span></span><a href="#" class="jNiceSelectOpen"></a></div><ul></ul>');
    				var $ul = $('ul', $wrapper);
    				/* Check width before continuing */
    				if(thisWidth <= thisMinWidth) {
    			        var thisOpenWidth = jnice_get_real_width($wrapper.find('.jNiceSelectOpen'));
    			        thisWidth = thisMinWidth+thisOpenWidth;
    			    }
    			    $wrapper.css({width: thisWidth});
    				/* Now we add the options */
    				$('option', this).each(function(i){
    				    // UDI: replace < and > with entities
    				    var optionTxt = this.text.replace(/</, '&lt;').replace(/>/, '&gt;');
    					$ul.append('<li><a href="#" index="'+ i +'">'+ optionTxt +'</a></li>');
    				});

    				// UDI - 2008-10-09 - Move guts of "click" action to auxiliary function
    				// so that default can be selected using it, rather than by triggering
    				// the jQuery click() event.
                    function updateSelection(selectedElement, fireChange) {
                        $('a.selected', $wrapper).removeClass('selected');
                        $(selectedElement).addClass('selected');
                        /* Fire the onchange event */
                        // UDI: Updated 4/16/2008 so that onchange is called with the new selection, not the old.
                        // modified 11/25/2007 to fire the jQuery change() event as opposed to the HTML onchange event
                        $select[0].selectedIndex = $(selectedElement).attr('index');
                        if (fireChange) {
                            $($select[0]).change();
                        }

                        $('span:eq(0)', $wrapper).html($(selectedElement).html());
                        $ul.hide();
                    }

    				/* Hide the ul and add click handler to the a */
    				$ul.hide().find('a').click(function(){
    				        updateSelection(this, true);
    						return false;
    				});

    				/* Set the default */
    				// UDI - 2008-10-09 - use updateSelection() rather than jQuery click()
    				// event to select default - this prevents the select's onchange event
    				// from being fired in this case.
    				updateSelection($('a:eq('+ this.selectedIndex +')', $ul)[0], false);
    			});/* End select each */
				
				
				
				/* Make sure IE6 doesn't get too tall */
				if($.browser.msie) {
					var $ul_ie6 = $('div.jNiceSelectWrapper ul');
					if($ul_ie6.find('li').length > 8) {
						$ul_ie6.addClass('maxHeight');
					}
				}

    			/* Apply the click handler to the Open */
    			$('a.jNiceSelectOpen , div.jNiceSelectWrapper > div > span').unbind('click').click(function(){
					var $ul = $(this).parent().siblings('ul');
    				if ($ul.css('display')=='none'){hideSelect();}
    				$ul.slideToggle();
    				return false;
    			});

    			/* Re-adjust width of options and hit region */
    			$('.jNiceSelectWrapper').each(function() {
    			    var ulWidth = jnice_get_real_width($(this));
    			    var ulMinWidth = parseInt(settings.selectMinWidth)+10;
    			    if(ulWidth <= ulMinWidth) {
    			        var ulOpenWidth = jnice_get_real_width($(this).find('.jNiceSelectOpen'));
    			        ulWidth = ulMinWidth + ulOpenWidth;
    			    }
    			    var ulOffset = parseInt(settings.selectOffset) + 2;
    			    ulWidth = ulWidth - ulOffset;
    			    $(this).find('ul').width(ulWidth);
    			    $(this).children('div').children('span').width(ulWidth-7);
    			    $(this).width(ulWidth+ulOffset);
    			});
    			$('.jNiceSelectWrapper ul li:first-child').addClass('first-child');
    			$('.jNiceSelectWrapper ul li:last-child').addClass('last-child');
    			
    			/* Make sure the first option is selected */
    			$('.jNiceSelectWrapper ul li:first-child a').trigger('click');
		    }

			/***************************
			  Check Boxes
			 ***************************/
			if(settings.enableCheckboxes) {
    			$('input:checkbox', this).each(function(){
    				$(this).addClass('jNiceHidden').wrap('<span></span>');
    				var $wrapper = $(this).parent();
    				$wrapper.prepend('<a href="#" class="jNiceCheckbox"></a>');
    				/* Click Handler */
    				$(this).siblings('a.jNiceCheckbox').click(function(){
						var $a = $(this);
						var input = $a.siblings('input')[0];
						if (input.checked===true){
							input.checked = false;
							$a.removeClass('jNiceChecked');
						}
						else {
							input.checked = true;
							$a.addClass('jNiceChecked');
						}
						return false;
    				});
    				/* set the default state */
    				if (this.checked){$('a.jNiceCheckbox', $wrapper).addClass('jNiceChecked');}
    			});
			}

			/***************************
			  Radios
			 ***************************/
			if(settings.enabledRadios) {
    			$('input:radio', this).each(function(){
    				$input = $(this);
    				$input.addClass('jNiceHidden').wrap('<span class="jRadioWrapper"></span>');
    				var $wrapper = $input.parent();
    				$wrapper.prepend('<a href="#" class="jNiceRadio" rel="'+ this.name +'"></a>');
    				/* Click Handler */
    				$('a.jNiceRadio', $wrapper).click(function(){
    						var $a = $(this);
    						$a.siblings('input')[0].checked = true;
    						$a.addClass('jNiceChecked');
    						/* uncheck all others of same name */
    						$('a[rel="'+ $a.attr('rel') +'"]').not($a).each(function(){
    							$(this).removeClass('jNiceChecked').siblings('input')[0].checked=false;
    						});
    						return false;
    				});
    				/* set the default state */
    				if (this.checked){$('a.jNiceRadio', $wrapper).addClass('jNiceChecked');}
    			});
			}

		}); /* End Form each */

		/* Hide all open selects */
		var hideSelect = function(){
			$('.jNiceSelectWrapper ul:visible').hide();
		};

		/* Check for an external click */
		var checkExternalClick = function(event) {
			if ($(event.target).parents('.jNiceSelectWrapper').length === 0) { hideSelect(); }
		};

		/* Apply document listener */
		$(document).mousedown(checkExternalClick);


		/* Add a new handler for the reset action */
		var jReset = function(f){
			var sel;
			$('.jNiceSelectWrapper select', f).each(function(){sel = (this.selectedIndex<0) ? 0 : this.selectedIndex; $('ul', $(this).parent()).each(function(){$('a:eq('+ sel +')', this).click();});});
		};
		this.bind('reset',function(){var action = function(){jReset(this);}; window.setTimeout(action, 10);});

	};/* End the Plugin */

	/* Automatically apply to any forms with class jNice */
	$(function(){$('form.jNice').jNice();});

})(jQuery);

function jnice_get_real_width( obj ) {
    var realWidth = '';
    if( $(obj).width() == 0 ) {
        var offender = $(obj).parents(':hidden');
        if(offender.length > 0) {
            $(offender).show();
            realWidth = $(obj).width();
            $(offender).hide();
        }
    }
    else {
        realWidth = $(obj).width();
    }
    return realWidth;
}
