// Author: Alex Littlejohn

(function ($) {

    var methods = {
        init: function () {

            return this.each(function () {

                if (!$(this).is("select")) {
                    // this will only work with select elements
                    return
                }

                var $se = $(this);


                var data = $se.data("dropdown")

                if (!data) {
                    $se.data("dropdown", { processed: true })
                } else {
                    return;
                }



                var selectedElement = $se.find('option:selected');
                var optionElements = $se.find("option");

                var dropDown = $('<dl class="dropdown" tabindex="1"></dl>')

                var sourceWidth;

                $se.outerWidth() == 0 ? sourceWidth = $se.css("width") : sourceWidth = $se.outerWidth();

                dropDown.width(sourceWidth)
                dropDown.append('<dt><a href="#">' + selectedElement.text() +
                    '<span class="value">' + selectedElement.val() +
                    '</span></a></dt><dd><ul></ul></dd>')
                var listElement = dropDown.find("dd ul");

                listElement.width(parseInt(sourceWidth) - 2)

                populate($se, optionElements, selectedElement, listElement, dropDown)
            });

            function populate($se, optionElements, selectedElement, listElement, dropDown) {

                optionElements.each(function () {
                    if ($(this).text() == selectedElement.text()) {
                        listElement.append('<li class="selected"><a href="#"><span class="normaltext">' +
				            $(this).text() + '</span><span class="value">' +
				            $(this).val() + '</span></a></li>');
                    } else {
                        listElement.append('<li><a href="#"><span class="normaltext">' +
				            $(this).text() + '</span><span class="value">' +
				            $(this).val() + '</span></a></li>');
                    }
                });

                dropDown.data("oSelect", { mCurrent: 0, mTotal: 0, keyString: '' })

                $se.after(dropDown);
                dropDown.append($se);
                $se.hide();

                dropDown.find("dt a").bind("click", dropDownClick);
                dropDown.find("dd ul li a").unbind("click").bind("click", dropDownItemClick)
                $se.bind("change", function () { $(this).dropdown("update") })
            }

            function dropDownClick() {

                $d = $(this).parents(".dropdown").focus();
                $u = $d.find("dd ul").toggle();

                var y = $d.offset().top + $d.height();
                var h = $u.outerHeight(true);
                var wh = $(window).height();
                var wst = $(window).scrollTop();

                if (((y - wst) + h) > wh) {
                    if (h > wh) {
                        $u.css("top", 0 - (y - wst))
                    } else {
                        $u.css("top", 0 - (((y - wst) + h) - wh))
                    }
                } else {
                    $u.css("top", -1)
                }

                $(".dropdown dd ul").not($(this).parents(".dropdown").find("dd ul")).hide();
                return false;
            }

            function dropDownItemClick(e) {
                e.preventDefault();
                e.stopPropagation();
                e.stopImmediatePropagation();
                var textObject = $(this).find("span.normaltext").text()
                var dropDown = $(this).parents(".dropdown");

                dropDown.find("dt a").html(textObject);
                dropDown.find("dd ul").hide();

                dropDown.focus();

                dropDown.find("dd ul li").removeClass("selected");
                $(this).parent("li").addClass("selected");

                var source = $(this).parents(".dropdown").find("select");

                var value = $(this).find("span.value").html()

                if (value.length <= 0) {
                    value = $("dd ul li").index($(this).parent());
                    source[0].selectedIndex = value;
                } else {
                    source.val(value)
                }

                dropDown.data("oSelect").mCurrent = source[0].selectedIndex;
                source.trigger("change")

                return false;
            }
        },
        update: function () {
            return this.each(function () {
                var si = $(this)[0].selectedIndex;
                var dropDown = $(this).parents(".dropdown");

                dropDown
					.find("dt a")
					.html(
						dropDown
						.find("dd ul li:eq(" + si + ")")
						.addClass("selected")
						.find("span.normaltext")
						.text()
					);
                dropDown
					.find("dd ul li")
					.not("dd ul li:eq(" + si + ")")
					.removeClass("selected")
            });
        }
    };

    // Method calling logic
    $.fn.dropdown = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.dropdown');
        }
    }



    // hides the dropdowns when the user clicks outside of 1;
    $(document).bind('click', function (e) {
        var targetElement = $(e.target);
        if (!targetElement.parents().hasClass("dropdown")) {
            $(".dropdown dd ul").hide();
        }
    });

    //==== Treating keys pressed - except ie7...
    if ($.browser.msie && parseInt($.browser.version) < 8) {

    } else {
        $(document).keydown(function (e) {


            var targetElement = $(e.target);
            var focusElement = $(":focus");

            if (focusElement.hasClass("dropdown")) {
                dropDownKeyEvent(focusElement, e)
            }
            function dropDownKeyEvent(dropDown, e) {
                // get keyCode (window.event is for IE) 
                var sKey = e.keyCode || window.event.keyCode;
                var $select = dropDown.find("select");

                dropDown.data("oSelect").mTotal = dropDown.find("select option").length;

                if (sKey == 40 || sKey == 38) {
                    e.preventDefault();
                    if (sKey == 38) { // keyUp
                        if (dropDown.data("oSelect").mCurrent == 0 || dropDown.data("oSelect").mCurrent == -1) {
                            dropDown.data("oSelect").mCurrent = dropDown.data("oSelect").mTotal - 1;
                        } else {
                            dropDown.data("oSelect").mCurrent--;
                        }
                    } else { // keyDown 
                        if (dropDown.data("oSelect").mCurrent == dropDown.data("oSelect").mTotal - 1) {
                            dropDown.data("oSelect").mCurrent = 0;
                        } else {
                            dropDown.data("oSelect").mCurrent++;
                        }
                    }

                    $ul = dropDown.find("ul");
                    $ul.children().each(function (i) {
                        if (i == dropDown.data("oSelect").mCurrent) {
                            $select[0].selectedIndex = dropDown.data("oSelect").mCurrent;
                            $(this).addClass("selected");
                        } else {
                            $(this).removeClass("selected");
                        }
                    });
                    $select[0].selectedIndex = dropDown.data("oSelect").mCurrent;

                    dropDown.find('a:first').html(dropDown.find("ul li.selected a span.normaltext").text());
                } else if (sKey == 13) {
                    e.preventDefault()
                    dropDown.find("ul:visible").toggle();
                    var value = dropDown.find("dd ul li.selected").find("span.value").html()
                    if (value.length <= 0) {
                        value = $("dd ul li").index(dropDown.find("dd ul li.selected"));
                        $select[0].selectedIndex = value;
                    } else {
                        $select.val(value)
                    }
                    dropDown.data("oSelect").mCurrent = $select[0].selectedIndex;
                    $select.trigger("change")
                }
            }
        });

    }

})(jQuery);














