﻿/*	
A generic form skinning library
Created by Ryan Vettese
*/
(function ($) {
    $.fn.extend({
        fancyOver: function (options) {
            if ($.fancy.timeout != null)
                $.fancy.overField.fancyOut();

            clearTimeout($.fancy.timeout);

            if ($.fancy.focusedField != undefined && $.fancy.focusedField[0] == $(this)[0])
                return;

            options = $.extend({}, options);

            // hide any elements that are still showing - this fixes a Firefox issue
            $('.text-box-over input').each(function () {
                if ($.fancy.focusedField == undefined || !$.fancy.focusedField[0] == $(this)[0])
                    $(this).fancyOut();
            });

            return $.fancy.focusField(this, options.focus);
        },
        fancyOutDelayed: function () {
            $.fancy.overField = $(this);
            $.fancy.timeout = setTimeout(function () { $.fancy.overField.fancyOut() }, 100);
            return this;
        },
        fancyOut: function () {
            var inputElem = $(this);
            var elem = inputElem.data("type") == "select" ? inputElem.siblings(".ul-container") : inputElem;

            inputElem.data("parent").removeClass(inputElem.data("type") + '-box-over' + ((inputElem.data("parent").hasClass(elem.data("type") + '-error') ? '-error' : '')));

            if (inputElem.data('label').html() == '')
                return;

            inputElem.data('label').clearQueue().fadeTo("fast", (inputElem.val().length > 0 ? 0 : 1));

            //inputElem.data('label').css({ 'display': (inputElem.val().length > 0 ? 'none' : 'block') });

            //inputElem.fadeTo("fast", $.browser.safari ? 0.99 : 1);

            elem.css({ 'opacity': $.browser.safari ? 0.99 : 1 });

            if ($.fancy.focusedField)
                $.fancy.focusedField.fancyFocus({ focus: true });
            return this;
        },
        fancyCheckInput: function () {
            if ($(this).val().length < 2) {
                $.fancy.overField = $(this);
                $.fancy.timeout = setTimeout(function () { $.fancy.overField.fancyOut() }, 100);
            }
            return this;
        },
        fancyDisable: function () {
            return this.each(function () {
                var elem = $(this);
            });
        },
        fancyFocus: function (options) {
            options = $.extend({}, options);
            var elem = $(this);
            $.fancy.focusField($(this), true);
            if (options.focus)
                elem.focus();
            else
                $.fancy.focusedField = $(this);
            return this;
        },
        fancyBlur: function () {
            $.fancy.focusedField = undefined;
            $(this).fancyOut();
            return this;
        },
        fancySelect: function (selectedli, parent) {
            var elem = $(this);
            var ul = selectedli.parent();
            //if(slider) {
            //hide slider

            parent.removeClass('select-box-open')
            ul.css('top:0px');

            ul.children().each(function (index) {
                li = $(this);
                if (index != selectedli.data("selectedIndex")) {
                    li.removeClass('selected')
                      .unbind('click', $.fancy.selectedoptionclick)
                      .bind('click', { li: li, elem: elem }, $.fancy.selectoptionclick);
                } else {
                    elem.attr("selectedIndex", index);
                    li.addClass('selected')
                      .unbind('click', $.fancy.selectoptionclick)
                      .bind('click', { li: li, elem: elem }, $.fancy.selectedoptionclick);
                    //if (ul.customOnChange)
                    //    eval(ul.customOnChange);
                }
            });
            return this;
        },
        hideSelect: function () {
            var elem = $(this);
            var ul = elem.siblings(".ul-container");

            elem.data("parent").removeClass('select-box-open')
            ul.css('top:0px');

            elem.fancyOut();
            $.fancy.lastOption.unbind('click', $.fancy.selectoptionclick)
                              .bind('click', { li: li, elem: elem, parent: elem.data("parent") }, $.fancy.selectedoptionclick);
            delete $.fancy.lastSelect;
            delete $.fancy.lastOption;

            return this;
        }

    });

    $.fn.fancy = function (options) {
        //return $(this).hide().each(function () { $.fancy(this, options); }).show();
        return $(this).each(function () { $.fancy(this, options); });
    };

    $.fancy = function (elem, options) {
        var $e = $(elem);

        if ($e.data('inited')) {
            //$e.fancyOut();
            return;
        };

        options = $.extend(
            {
                type: ($e.is("input:text") || $e.is("input:password") ? "text" : ($e.is("input:checkbox") ? "checkbox" : ($e.is("select") ? "select" : ($e.is("textarea") ? "textarea" : "unknown"))))
                //get(0).nodeName.toLowerCase()
            },
            $.fancy.options,
            options
        );

        if (options.type == "text" || options.type == "textarea" || options.type == "select" || options.type == "checkbox") {

            options = $.extend(
                {
                    name: $e.attr("id")
                },
                options
            );

            $e.data("swapfancy", $e.hasClass('swapfancy'));
            $e.data("type", options.type);
            //move the label before the input element
            $('label[for=' + options.name + ']').insertBefore($e);
            $e.data("label", $e.prev("label"));
            $e.data("label").data("elem", $e);

            $e.data('label').andSelf().wrapAll("<div class=\"" + options.type + "-box " + ($e.data("swapfancy") ? "swapfancy" : "") + "\"></div>");
            $e.data("parent", $e.parent());
            //if (options.type == "select")
            //    $e.data("parent").prepend('<div class="left-input"/>');
            //$e.data("parent").append('<div class="right-input"/>');

            _setSize($e, options.type);

            if ($e.data("swapfancy")) {
                if (options.type == "select") {
                    $.fancy.drawOptions($e);
                    $e.blur(function () { $(this).fancyBlur(); })
                      .focus(function () { $(this).fancyFocus(); })
                      .change(function () { $.fancy.selectchange($(this)); })
                      .keypress(function () { $.fancy.selectchange($(this)); });
                } else if (options.type == "text" || options.type == "textarea") {
                    $e.mouseover(function () { $(this).fancyOver(); })
                      .mouseout(function () { $(this).fancyOutDelayed(); })
                      .blur(function () { $(this).fancyBlur(); })
                      .focus(function () { $(this).fancyFocus(); })
                      .keypress(function () { $(this).fancyCheckInput(); });
                    $e.data('label').mouseover(function () { $(this).data("elem").fancyOver(); })
                                    .mouseout(function () { $(this).data("elem").fancyOutDelayed(); });
                    $e.fancyOut();
                } else if (options.type == "checkbox") {
                    $e.change(function () { $.fancy.checkboxchange($(this)); })
                }
            }

            $e.addClass(options.type)
              .addClass('fancied') //to prevent multiple instances
              .data("inited", true);


            /*
            if ($e.attr('disabled'))
            $e.fancyDisable();

            if (options.type == "checkbox")
            $.fancy.checkboxchange($e);
            else
            $e.fancyOut();
            */
        };

        function _setSize(elem, type) {
            var widthToUse = elem.width();

            // reset the form element width in case it's being overridden from the <div>
            if (type == 'select') {
                //elem.css({ 'width': (widthToUse + 28) + 'px' })
                elem.css({ 'width': (widthToUse + 19) + 'px' })
                //.siblings(".left-input")
                //.css({ 'width': (widthToUse - 8) + 'px' })
                .parent()
                .css({ 'width': (widthToUse + 19) + 'px' });
            }
            else if (type == 'textarea') {
                //elem.css({ 'width': (widthToUse - 9) + 'px' }).data("parent").css({ 'width': (widthToUse) + 'px', 'height': (elem.height() + 6) + 'px' });
                elem.css({ 'width': (widthToUse - 9) + 'px' }).data("parent").css({ 'width': (widthToUse) + 'px' });
            }
            else if (type == 'checkbox') {
                elem.data("parent").css({ 'width': (widthToUse + 10) + 'px', 'height': (elem.data('label').height() + 8) + 'px' });
            }
            else {
                elem.data("parent").css({ 'width': (widthToUse + 10) + 'px' });
            }
        };

        return $e;
    };

    $.fancy.focusField = function (fancyElem, focus) {
        var inputElem = fancyElem.data("type") == "select" ? fancyElem.siblings(".ul-container") : fancyElem;

        fancyElem.data("parent").addClass(fancyElem.data("type") + '-box-over' + ((fancyElem.data("parent").hasClass(fancyElem.data("type") + '-error') ? '-error' : '')));

        if (fancyElem.data('label').clearQueue().html() == '')
            return;

        fancyElem.data('label').fadeTo("fast", (focus ? (inputElem.val().length > 0 ? 0 : 1) : 1));

        fancyElem.data('label').css({ 'display': (focus ? (inputElem.val().length > 0 ? 'none' : 'block') : 'block') });

        //inputElem.fadeTo("fast", (focus || fancyElem.data("parent").hasClass('select-box-open') ? ($.browser.safari ? 0.99 : 1) : 0.15));

        inputElem.css({ 'opacity': (focus || fancyElem.data("parent").hasClass('select-box-open') ? ($.browser.safari ? 0.99 : 1) : 0.15) });

        return fancyElem;
    };

    $.fancy.checkboxchange = function (elem) {
        elem.is(":checked") ? elem.data('label').addClass('selected') : elem.data('label').removeClass('selected');
    };

    $.fancy.selectchange = function (elem) {
        elem.fancySelect(elem.data("parent").find("div.ul-container ul li:eq(" + elem.attr("selectedIndex") + ")"), elem.data("parent"));
    };

    $.fancy.selectoptionclick = function (event) {
        event.data.elem.fancySelect(event.data.li, event.data.elem.data("parent")).fancyOut();
        event.data.elem.change();
    };

    $.fancy.selectedoptionclick = function (event) {
        $('div.select-box-open select').each(function () {
            $(this).hideSelect();
        });
        event.data.elem.data("parent").addClass('select-box-open');

        $.fancy.lastSelect = event.data.li.parent();
        $.fancy.lastOption = event.data.li;

        event.data.elem.fancyOver();

        event.data.li.unbind('click', $.fancy.selectedoptionclick)
                     .bind('click', { li: event.data.li, elem: event.data.elem }, $.fancy.selectoptionclick);

        /*
        if (parentDiv.slider) {
        parentDiv.sliderTrack.show();
        var elem = parentDiv.down('select');
        parentDiv.slider.setValue((elem.selectedIndex) / (elem.options.length - 1) * parentDiv.slider.maximum);
        }
        */
    };

    $.fancy.selectOptionOver = function (li, elem) {
        li.addClass('hover');
        elem.fancyOver();
    }
    $.fancy.selectOptionOut = function (li, elem) {
        li.removeClass('hover');
        elem.fancyOut();
    }

    $.fancy.drawOptions = function (elem) {
        var selectElem = elem[0];
        var width = elem.width();
        //var rightWidth = elem.next(".right-input").width();
        var rightWidth = 0;
        var options = selectElem.options.length;
        var ul;
        var sliderHandle, sliderTrack;
        var selectedOption = (!elem.attr("selectedIndex")) ? 0 : elem.attr("selectedIndex");

        if (elem.data("ul-container")) {
            ul = elem.data("ul-container")
            ul.find("li").remove();
        } else {
            ul = elem.data("parent")
                     .append('<div class="ul-container" style="z-index:' + ($.fancy.zIndexCounter--) + ';width:' + (width) + 'px;"><ul style="width:' + (width) + 'px;"></ul></div>')
                     .find('ul');
            elem.data("ul-container", ul);
        }


        //var customOnChange = inp.readAttribute('onchange');
        //if (customOnChange)
        //    ul.customOnChange = customOnChange;

        for (var index = 0; index < options; index++) {
            ul.append('<li>' + selectElem.options[index].text + '</li>');
            li = ul.find('li').last();
            li.css({ 'display': 'block' });
            li.data("selectedIndex", index);
            li.data("selectId", elem.attr("id"));
            if (index != selectedOption) {
                li.bind('click', { li: li, elem: elem, parent: elem.data("parent") }, $.fancy.selectoptionclick);
            } else {
                li.addClass('selected');
                li.bind('click', { li: li, elem: elem, parent: elem.data("parent") }, $.fancy.selectedoptionclick);
            }
            li.mouseenter(function () { $.fancy.selectOptionOver($(this), elem); })
              .mouseleave(function () { $.fancy.selectOptionOut($(this), elem); });
        }

        var scrollMin = 8;
        var optionHeight = 23;
        var scrollHeight = (optionHeight * scrollMin) + 1;


        // we have to draw the scroll bars if there are 9 or more options
        if (options > scrollMin) {
            elem.data("ul-container").parent().jScrollPane({ scrollbarWidth: 16, scrollbarMargin: 2 });
            elem.data("ul-container li:not(.selected").css({ 'display': 'none' });
        } else {
            elem.data("ul-container").parent().css('height:' + Math.max(25, ((options * optionHeight))) + 'px');
        }
    }

    //Defaults
    $.fancy.options = {
        inited: false
    };

    $.fancy.overField = null;
    $.fancy.focusedField = null;
    $.fancy.timeout = null;
    $.fancy.lastSelect = null;
    $.fancy.lastOption = null;
    $.fancy.zIndexCounter = 499;

    //Version
    $.fancy.version = "0.1";

    //Auto-run
    $(function () {
        $(":input:not(.markItUpEditor,.notfancy,:hidden,:image,:submit,:button,:radio)").fancy();
    });

})(jQuery);

