/*
 *
 * jqTransform
 * by mathieu vilaplana mvilaplana@dfc-e.com
 * Designer ghyslain armand garmand@dfc-e.com
 * modified by thomas.jakobi@partout.info
 *
 * Version 1.0 25.09.08
 * Version 1.1 06.08.09
 * Version 1.2 12.04.10
 *
 * Add event click on Checkbox and Radio
 * Auto calculate the size of a select element
 * Can now, disabled the elements
 * Correct bug in ff if click on select (overflow=hidden)
 * No need any more preloading !!
 * 
 ******************************************** */
 
(function($){
    var defaultOptions = {
        preloadImg: false
    };
    
    /***************************
     Labels
     ***************************/
    var jqTransformGetLabel = function(objfield){
        var selfForm = $(objfield.get(0).form);
        var oLabel = objfield.next();
        if (!oLabel.is('label')) {
            oLabel = objfield.prev();
            if (oLabel.is('label')) {
                var inputname = objfield.attr('id');
                if (inputname) {
                    oLabel = selfForm.find('label[for="' + inputname + '"]');
                }
            }
        }
        if (oLabel.is('label')) {
            return oLabel.css('cursor', 'pointer');
        }
        return false;
    };
    
    /* Hide all open selects */
    var jqTransformHideSelect = function(oTarget){
        var ulVisible = $('.jqTransformSelectWrapper ul:visible');
        ulVisible.each(function(){
            var oSelect = $(this).parents(".jqTransformSelectWrapper:first").find("select").get(0);
            // do not hide if click on the label object associated to the select
            if (!(oTarget && oSelect.oLabel && oSelect.oLabel.get(0) == oTarget.get(0))) {
                $(this).hide();
            }
        });
    };
    /* Check for an external click */
    var jqTransformCheckExternalClick = function(event){
        if ($(event.target).parents('.jqTransformSelectWrapper').length === 0) {
            jqTransformHideSelect($(event.target));
        }
    };
    
    /* Apply document listener */
    var jqTransformAddDocumentListener = function(){
        $(document).mousedown(jqTransformCheckExternalClick);
    };
    
    /* Add a new handler for the reset action */
    var jqTransformReset = function(f){
        var sel;
        $('.jqTransformSelectWrapper select', f).each(function(){
            sel = (this.selectedIndex < 0) ? 0 : this.selectedIndex;
            $('ul', $(this).parent()).each(function(){
                $('a:eq(' + sel + ')', this).click();
            });
        });
        $('a.jqTransformCheckbox, a.jqTransformRadio', f).removeClass('jqTransformChecked');
        $('input:checkbox, input:radio', f).each(function(){
            if (this.checked) {
                $('a', $(this).parent()).addClass('jqTransformChecked');
            }
        });
    };
    
    /***************************
     Buttons
     ***************************/
    $.fn.jqTransInputButton = function(){
        return this.each(function(){
            var button = $(this);
            var newButton = $('<div class="jqTransformButtonWrapper"><button id="' + this.id + '" name="' + this.name + '" type="' + this.type + '" class="' + this.className + ' jqTransformButton">' + $(this).attr('value') + '</button>').css('width', button.outerWidth()).hover(function(){
                newButton.addClass('jqTransformButton-hover');
            }, function(){
                newButton.removeClass('jqTransformButton-hover')
            }).mousedown(function(){
                newButton.addClass('jqTransformButton-click')
            }).mouseup(function(){
                newButton.removeClass('jqTransformButton-click')
            });
            newButton.find('button').css('width', button.outerWidth());
            $(this).replaceWith(newButton);
        });
    };
    
    /***************************
     Text Fields
     ***************************/
    $.fn.jqTransInputText = function(){
        return this.each(function(){
            var input = $(this);
            var width = input.outerWidth();
            var required = input.hasClass('required') ? 'required' : '';
            var id = input.attr('id');
            var readonly = (input.attr("readonly") == true) ? 'readonly' : '';
            
            if (input.hasClass('jqtranformdone') || !input.is('input')) {
                return;
            }
            input.addClass('jqtranformdone');
            
            var oLabel = jqTransformGetLabel($(this));
            oLabel && oLabel.bind('click', function(){
                input.focus();
            });
            
            input.addClass("jqTransformInput").wrap('<div class="jqTransformInputWrapper"><div></div></div>');
            var wrapper = input.parent().css('width', width).parent().css('width', width);
            input.focus(function(){
                wrapper.addClass("jqTransformInputWrapper-focus");
            }).blur(function(){
                wrapper.removeClass("jqTransformInputWrapper-focus");
            }).hover(function(){
                wrapper.addClass("jqTransformInputWrapper-hover");
            }, function(){
                wrapper.removeClass("jqTransformInputWrapper-hover");
            });
            
            this.wrapper = wrapper.addClass(required).addClass(readonly).attr('id', id);
            
        });
    };
    
    /***************************
     Check Boxes
     ***************************/
    $.fn.jqTransCheckBox = function(){
        return this.each(function(){
            if ($(this).hasClass('jqTransformHidden')) {
                return;
            }
            
            var input = $(this);
            var inputSelf = this;
            
            //set the click on the label
            var oLabel = jqTransformGetLabel(input);
            oLabel && oLabel.click(function(){
                aLink.trigger('click');
            });
            
            var aLink = $('<a href="#" class="jqTransformCheckbox"></a>');
            //wrap and add the link
            input.addClass('jqTransformHidden').wrap('<span class="jqTransformCheckboxWrapper"></span>').parent().prepend(aLink);
            //on change, change the class of the link
            input.change(function(){
                this.checked && aLink.addClass('jqTransformChecked') || aLink.removeClass('jqTransformChecked');
                return true;
            });
            var wrapper = input.parent();
            wrapper.hover(function(){
                wrapper.addClass("jqTransformCheckboxWrapper-hover");
            }, function(){
                wrapper.removeClass("jqTransformCheckboxWrapper-hover");
            });
            // Click Handler, trigger the click and change event on the input
            aLink.click(function(){
                //do nothing if the original input is disabled
                if (input.attr('disabled')) {
                    return false;
                }
                //trigger the envents on the input object
                input.trigger('click').trigger("change");
                return false;
            });
            
            // set the default state
            this.checked && aLink.addClass('jqTransformChecked');
        });
    };
    
    /***************************
     Radio Buttons
     ***************************/
    $.fn.jqTransRadio = function(){
        return this.each(function(){
            if ($(this).hasClass('jqTransformHidden')) {
                return;
            }
            
            var input = $(this);
            var inputSelf = this;
            
            oLabel = jqTransformGetLabel(input);
            oLabel &&
            oLabel.click(function(){
                aLink.trigger('click');
            });
            
            var aLink = $('<a href="#" class="jqTransformRadio" rel="' + this.name + '"></a>');
            input.addClass('jqTransformHidden').wrap('<span class="jqTransformRadioWrapper"></span>').parent().prepend(aLink);
            
            input.change(function(){
                inputSelf.checked && aLink.addClass('jqTransformChecked') || aLink.removeClass('jqTransformChecked');
                return true;
            });
            var wrapper = input.parent();
            wrapper.hover(function(){
                wrapper.addClass("jqTransformRadioWrapper-hover");
            }, function(){
                wrapper.removeClass("jqTransformRadioWrapper-hover");
            });
            // Click Handler
            aLink.click(function(){
                if (input.attr('disabled')) {
                    return false;
                }
                input.trigger('click').trigger('change');
                
                // uncheck all others of same name input radio elements
                $('input[name="' + input.attr('name') + '"]', inputSelf.form).not(input).each(function(){
                    $(this).attr('type') == 'radio' && $(this).trigger('change');
                });
                
                return false;
            });
            // set the default state
            inputSelf.checked && aLink.addClass('jqTransformChecked');
        });
    };
    
    /***************************
     TextArea
     ***************************/
    $.fn.jqTransTextarea = function(){
        return this.each(function(){
            var textarea = $(this);
            var width = textarea.outerWidth();
            var height = textarea.outerHeight();
            var required = textarea.hasClass('required') ? 'required' : '';
            
            if (textarea.hasClass('jqtransformdone')) {
                return;
            }
            textarea.addClass('jqtransformdone');
            
            oLabel = jqTransformGetLabel(textarea);
            oLabel &&
            oLabel.click(function(){
                textarea.focus();
            });
            
            var strDiv = '<div class="jqTransformTextarea"><div class="jqTransformTextarea-tr"><div class="jqTransformTextarea-tl"></div></div>';
            strDiv += '<div class="jqTransformTextarea-r"><div class="jqTransformTextarea-l"></div></div>';
            strDiv += '<div class="jqTransformTextarea-br"><div class="jqTransformTextarea-bl"></div></div></div>';
            
            var oDiv = $(strDiv).insertAfter(textarea).hover(function(){
                !oDiv.hasClass('jqTransformTextarea-focus') && oDiv.addClass('jqTransformTextarea-hover');
            }, function(){
                oDiv.removeClass('jqTransformTextarea-hover');
            });
            
            textarea.focus(function(){
                oDiv.removeClass('jqTransformTextarea-hover').addClass('jqTransformTextarea-focus');
            }).blur(function(){
                oDiv.removeClass('jqTransformTextarea-focus');
            }).appendTo($('.jqTransformTextarea-r', oDiv.parent()));
            this.oDiv = oDiv;
            
            var tlWidth = $('.jqTransformTextarea-tl', oDiv.parent()).width();
            var tlHeight = $('.jqTransformTextarea-tl', oDiv.parent()).height();

            $('.jqTransformTextarea-tr', oDiv.parent()).css('width', width - tlWidth);
            $('.jqTransformTextarea-br', oDiv.parent()).css('width', width - tlWidth);
            $('.jqTransformTextarea-l', oDiv.parent()).css('height', height - tlHeight);
            $('.jqTransformTextarea-r', oDiv.parent()).css('height', height - tlHeight).css('width', width - tlWidth);
            $('.jqtransformdone', oDiv.parent()).css('width', textarea.innerWidth() - (tlWidth * 2));
            $('.jqTransformTextarea', oDiv.parent()).addClass(required);
            
            if ($.browser.safari) {
                $('.jqtransformdone', oDiv.parent()).addClass('jqTransformSafariTextarea').css('height', height - tlHeight);
            }
        });
    };
    
    /***************************
     Select
     ***************************/
    $.fn.jqTransSelect = function(){
        return this.each(function(index){
            var select = $(this);
            var required = select.hasClass('required') ? 'required' : '';
            
            if (select.hasClass('jqTransformHidden')) {
                return;
            }
            if (select.attr('multiple')) {
                return;
            }
            
            var oLabel = jqTransformGetLabel(select);
            
            /* First thing we do is Wrap it */
            var $wrapper = select.addClass('jqTransformHidden').wrap('<div class="jqTransformSelectWrapper"></div>').parent().css({
                zIndex: 10 - index
            });
            
            /* Now add the html for the select */
            $wrapper.prepend('<div><span></span><a href="#" class="jqTransformSelectOpen"></a></div><ul></ul>');
            var $ul = $('ul', $wrapper).css('width', select.outerWidth()).hide();
            /* Now we add the options */
            $('option', this).each(function(i){
                var oLi = $('<li><a href="#" index="' + i + '">' + $(this).html() + '</a></li>');
                $ul.append(oLi);
            });
            
            /* Add click handler to the a */
            $ul.find('a').click(function(){
                $('a.selected', $wrapper).removeClass('selected');
                $(this).addClass('selected');
                /* Fire the onchange event */
                if (select[0].selectedIndex != $(this).attr('index') && select[0].onchange) {
                    select[0].selectedIndex = $(this).attr('index');
                    select[0].onchange();
                }
                select[0].selectedIndex = $(this).attr('index');
                $('span:eq(0)', $wrapper).html($(this).html());
                $ul.hide();
                return false;
            });
            
            /* Set the default */
            $('a:eq(' + this.selectedIndex + ')', $ul).click();
            $('span:first', $wrapper).click(function(){
                $("a.jqTransformSelectOpen", $wrapper).trigger('click');
            });
            oLabel &&
            oLabel.click(function(){
                $("a.jqTransformSelectOpen", $wrapper).trigger('click');
            });
            this.oLabel = oLabel;
            
            /* Apply the click handler to the Open */
            var oLinkOpen = $('a.jqTransformSelectOpen', $wrapper).click(function(){
                //Check if box is already open to still allow toggle, but close all other selects
                if ($ul.css('display') == 'none') {
                    jqTransformHideSelect();
                }
                if (select.attr('disabled')) {
                    return false;
                }
                $ul.slideToggle('fast', function(){
                    var offSet = ($('a.selected', $ul).offset().top - $ul.offset().top);
                    $ul.animate({
                        scrollTop: offSet
                    });
                }).parent().toggleClass("jqTransformSelectWrapper-focus");
                return false;
            });
            
            // Set the new width
            var iSelectWidth = select.outerWidth();
            var oSpan = $('span:first', $wrapper);
            var newWidth = (iSelectWidth > oSpan.innerWidth()) ? iSelectWidth : $wrapper.width();
            $wrapper.css('width', newWidth);
            $ul.css('width', newWidth - 2);
            oSpan.css({
                width: iSelectWidth
            });
            
            // Calculate the height if necessary, less elements that the default height
            // Show the ul to calculate the block, if ul is not displayed li height value is 0
            $ul.css({
                display: 'block',
                visibility: 'hidden'
            });
            var iSelectHeight = ($('li', $ul).length) * ($('li:first', $ul).height());
            (iSelectHeight < $ul.height()) &&
            $ul.css({
                height: iSelectHeight,
                overflow: 'hidden'
            });
            $ul.css({
                display: 'none',
                visibility: 'visible'
            });
            
            $wrapper.addClass(required).hover(function(){
                $wrapper.addClass("jqTransformSelectWrapper-hover");
            }, function(){
                $wrapper.removeClass("jqTransformSelectWrapper-hover");
            });

        });
    };
    
    /***************************
     Transform Form
     ***************************/
    $.fn.jqTransform = function(options){
        var opt = $.extend({}, defaultOptions, options);
        
        /* each form */
        return this.each(function(){
            var selfForm = $(this);
            if (selfForm.hasClass('jqtransformdone')) {
                return;
            }
            selfForm.addClass('jqtransformdone');
            
            $('input:submit, input:reset, input[type="button"]', this).jqTransInputButton();
            $('input:text, input:password', this).jqTransInputText();
            $('input:checkbox', this).jqTransCheckBox();
            $('input:radio', this).jqTransRadio();
            $('textarea', this).jqTransTextarea();
            
            if ($('select', this).jqTransSelect().length > 0) {
                jqTransformAddDocumentListener();
            }
            selfForm.bind('reset', function(){
                var action = function(){
                    jqTransformReset(this);
                };
                window.setTimeout(action, 10);
            });
        });
    };
})(jQuery);