// MSDropDown - jquery.dd.js
// author: Marghoob Suleman (www.giftlelo.com | www.marghoobsuleman.com)
// Additional contributions: Nikos Dimitrakopoulos (os@nikosd.com | http://blog.nikosd.com)
// Date: 12th Aug, 2009
// Version: 2.2-pre {date: 16 Mar 2010}
// Revision: 27
/*
 // msDropDown is free jQuery Plugin: you can redistribute it and/or modify
 // it under the terms of the either the MIT License or the Gnu General Public License (GPL) Version 2
 */
(function ($) {
    var oldDiv = "";
    $.fn.dd = function (options) {
        $this = this;
        
		// Default options
        options = $.extend({
            height: 120,
            visibleRows: 7,
            rowHeight: 23,
            zIndex: 9999,
            style: '',
			/**
			* Overiding this gives you the opportunity to customize totally what
			* will be the inner html content of the selected <a> element.
			*/
			getTitleHtml: function(optionElement) {
				var imgSrc = $(optionElement).attr("title"),
					img = (imgSrc === undefined || imgSrc.length === 0) ? "" : '<img src="' + imgSrc + '" align="left" /> ',
					sText = $(optionElement).text();
					
				return img + sText;
			},
			/**
			* Overiding this gives you the opportunity to customize totally what
			* will be the inner html content of each <a> element (which represents
			* an <option> one).
			*/
			getElementHtml: function(optionElement) {
				var imgSrc = $(optionElement).attr("title"),
					img = (imgSrc === undefined || imgSrc.length === 0) ? "" : '<img src="' + imgSrc + '" align="left" /> ',
					sText = $(optionElement).text();
					
				return img + sText;
			}
        }, options);
        
		var selectedValue = "",
			actionSettings = { insideWindow: true, keyboardAction: false, currentKey: null },
			ddList = ($(this).attr("size") > 0 || $(this).attr("multiple") === true) ? true : false,
			elementid = $(this).attr("id"),
			inlineCSS = $(this).attr("style"),
			allOptions = $(this).children(),
			a_array = {} //stores id, html & value etc
		;

		options.style += (inlineCSS === undefined) ? "" : inlineCSS;
		if (ddList) {
			options.visibleRows = $(this).attr("size");
		}

        config = {
            postElementHolder: '_msddHolder',
            postID: '_msdd',
            postTitleID: '_title',
            postTitleTextID: '_titletext',
            postChildID: '_child',
            postAID: '_msa',
            postOPTAID: '_msopta',
            postInputID: '_msinput',
            postArrowID: '_arrow',
            postInputhidden: '_inp'
        };
		
        styles = {
            dd: 'dd',
            ddTitle: 'ddTitle',
            arrow: 'arrow',
            ddChild: 'ddChild',
            disbaled: 0.30
        };
        
		attributes = {
			actions: "",
            //actions: "onfocus,onblur,onchange,onclick,ondblclick,onmousedown,onmouseup,onmouseover,onmousemove,onmouseout,onkeypress,onkeydown,onkeyup",
            prop: "size,multiple,disabled,tabindex"
        };
        
		//create wrapper
        createDropDown();

        function getPostID(id) {
            return elementid + config[id];
        }

        function matchIndex(index) {
            var selectedIndex = $("#" + elementid + " option:selected");
            if (selectedIndex.length > 1) {
                for (var i = 0; i < selectedIndex.length; i++) {
                    if (index === selectedIndex[i].index) {
                        return true;
                    }
                }
            } else if (selectedIndex.length === 1) {
                if (selectedIndex[0].index === index) {
                    return true;
                }
            }
            return false;
        }

        function createATags() {
            var childnodes = allOptions,
				aTags = "",
				aidfix = getPostID("postAID"),
				aidoptfix = getPostID("postOPTAID");
			
			/**
			* Inner function that creates the <a> element for an <option> element
			*/
			var getATagForOption = function (current, aid, currentOption){
				var sValue = $(currentOption).val(),
					cssClassForDisabled = ($(currentOption).attr("disabled") === true) ? "disabled" : "enabled",
					cssClassForSelected = (matchIndex(currentOption.index) === true) ? "selected" : "",
					cssClassesCode = 'class="' + cssClassForSelected + ' ' + cssClassForDisabled + '"',
					innerStyle = $(currentOption).attr("style"),
					innerStyleCode = (innerStyle !== false) ? 'style="' + innerStyle + '"' : "",
					aTag = "";

				a_array[aid] = {
					html: options.getElementHtml(currentOption),
					titleHtml: options.getTitleHtml(currentOption),
					value: sValue,
					index: currentOption.index,
					id: aid
				};
				
				aTag += '<a href="javascript:void(0);" ' + cssClassesCode + ' ' + innerStyleCode + ' id="' + aid + '">' + a_array[aid].html + '</a>';
				return aTag;
			};

            childnodes.each(function (current) {
                var currentOption = childnodes[current];
                if (currentOption.nodeName === "OPTGROUP") {
					//OPTGROUP
                    aTags += "<div class='opta'>";
                    aTags += "<span style='font-weight:bold;font-style:italic; clear:both;'>" + $(currentOption).attr("label") + "</span>";
                    
					var optChild = $(currentOption).children();
                    optChild.each(function (currentopt) {
                        var aid = aidoptfix + "_" + (current) + "_" + (currentopt);
                        aTags += getATagForOption(current, aid, optChild[currentopt]);
                    });
					
                    aTags += "</div>";
                } else {
                    var aid = aidfix + "_" + (current);
					aTags += getATagForOption(current, aid, currentOption)
                }
            });
			
            return aTags;
        }

        function createChildDiv() {
            var id = getPostID("postID");
            var childid = getPostID("postChildID");
            var sStyle = options.style;
            sDiv = "";
            sDiv += '<div id="' + childid + '" class="' + styles.ddChild + '"';
            if (!ddList) {
                sDiv += (sStyle != "") ? ' style="' + sStyle + '"' : '';
            } else {
                sDiv += (sStyle != "") ? ' style="border-top:1px solid #c3c3c3;display:block;position:relative;' + sStyle + '"' : '';
            }
            sDiv += '>';
            return sDiv;
        }

        function createTitleDiv() {
            var titleid = getPostID("postTitleID");
            var arrowid = getPostID("postArrowID");
            var titletextid = getPostID("postTitleTextID");
            var inputhidden = getPostID("postInputhidden");
			var selectedOption = $("#" + elementid + " option:selected");
			var titleHtml = options.getTitleHtml(selectedOption);
            var sDiv = '<div id="' + titleid + '" class="' + styles.ddTitle + '"';
            sDiv += '>';
            sDiv += '<span id="' + arrowid + '" class="' + styles.arrow + '"></span><span class="textTitle" id="' + titletextid + '">' + titleHtml + '</span></div>';
            return sDiv;
        }
        
        /**
          * Binds the "fake" drop down's events          
          */
        function bindOpenCloseEvents() {
           var titleid = getPostID("postTitleID"),
               childid = getPostID("postChildID"),
               arrowid = getPostID("postArrowID");
            $("#" + childid + " a.enabled").bind("click", function (event) {
                   event.preventDefault();
                   manageSelection(this);
                   if (!ddList) {
                       $("#" + childid).unbind("mouseover");
                       setInsideWindow(false);
                       setTitleText(getById($(this).attr("id")).titleHtml);
                       closeMe();
                   }
                   setValue();
               });                
               $("#" + childid).bind("mouseout", function (event) {
                   setInsideWindow(false);
                   $(document).unbind("keydown");
                   actionSettings.keyboardAction = false;
                   actionSettings.currentKey = null;
               });
               if (!ddList) {
                   $("#" + titleid).bind("click", function (event) {
                       setInsideWindow(false);
                       if ($("#" + childid + ":visible").length == 1) {
                           $("#" + childid).unbind("mouseover");
                       } else {
                           $("#" + childid).bind("mouseover", function (event) {
                               setInsideWindow(true);
                           });
                           openMe();
                       }
                   });
               }
               $("#" + titleid).bind("mouseout", function (evt) {
                   setInsideWindow(false);
               });                
        }
        
        /**
         * Disables the "fake" drop down
         */
        function disable() {
            var id = getPostID("postID"),
                titleid = getPostID("postTitleID");
           
            //$("#" + id).addClass("disabled");
            $("#" + id).addClass("dddisabled");
            $("#" + titleid).unbind("mouseover").unbind("click").unbind("mouseout");
        }
        
        /**
         * Enables the "fake" drop down
         */
         function enable() {
            var id = getPostID("postID");
            
            $("#" + id).removeClass('dddisabled');
            bindOpenCloseEvents();
         }               

        function createDropDown() {
            var changeInsertionPoint = false;
            var id = getPostID("postID");
            var titleid = getPostID("postTitleID");
            var titletextid = getPostID("postTitleTextID");
            var childid = getPostID("postChildID");
            var arrowid = getPostID("postArrowID");
            var iWidth = $("#" + elementid).width();
            var sStyle = options.style;
            if ($("#" + id).length > 0) {
                $("#" + id).remove();
                changeInsertionPoint = true;
            }
            var sDiv = '<div id="' + id + '" class="' + styles.dd + '"';
            sDiv += (sStyle != "") ? ' style="' + sStyle + '"' : '';
            sDiv += '>';
            //create title bar
            if (!ddList) {
				sDiv += createTitleDiv();
			}
            //create child
            sDiv += createChildDiv();
            sDiv += createATags();
            sDiv += "</div>";
            sDiv += "</div>";
            if (changeInsertionPoint === true) {
                var sid = getPostID("postElementHolder");
                $("#" + sid).after(sDiv);
            } else {
                $("#" + elementid).after(sDiv);
            }
            $("#" + id).css("width", iWidth + "px");
            $("#" + childid).css("width", (iWidth - 2) + "px");
            if (allOptions.length > options.visibleRows) {
                var margin = parseInt($("#" + childid + " a:first").css("padding-bottom")) + parseInt($("#" + childid + " a:first").css("padding-top"));
                var iHeight = ((options.rowHeight) * options.visibleRows) - margin;
                $("#" + childid).css("height", iHeight + "px");
            }
            //set out of vision
            if (changeInsertionPoint === false) {
                setOutOfVision();
                addNewEvents(elementid);
            }
            if ($("#" + elementid).attr("disabled") === true) {
                $("#" + id).css("opacity", styles.disbaled);
            } else {
                applyEvents();
                //add events
                //arrow hightlight
                if (!ddList) {
                    $("#" + titleid).bind("mouseover", function (event) {
                        hightlightArrow(1);
                    });
                    $("#" + titleid).bind("mouseout", function (event) {
                        hightlightArrow(0);
                    });
                };
                /*
                //open close events
                $("#" + childid + " a.enabled").bind("click", function (event) {
                    event.preventDefault();
                    manageSelection(this);
                    if (!ddList) {
                        $("#" + childid).unbind("mouseover");
                        setInsideWindow(false);
                        setTitleText(getById($(this).attr("id")).titleHtml);
                        closeMe();
                    }
                    setValue();
                    //actionSettings.oldIndex = a_array[$(this).attr("id")].index;
                });
                $("#" + childid + " a.disabled").css("opacity", styles.disbaled);
                if (ddList) {
                    $("#" + childid).bind("mouseover", function (event) {
                        if (!actionSettings.keyboardAction) {
                            actionSettings.keyboardAction = true;
                            $(document).bind("keydown", function (event) {
                                var keyCode = event.keyCode;
                                actionSettings.currentKey = keyCode;
                                if (keyCode == 39 || keyCode == 40) {
                                    //move to next
                                    event.preventDefault();
                                    event.stopPropagation();
                                    next();
                                    setValue();
                                }
                                if (keyCode == 37 || keyCode == 38) {
                                    event.preventDefault();
                                    event.stopPropagation();
                                    //move to previous
                                    previous();
                                    setValue();
                                }
                            });
                        }
                    });
                }
                $("#" + childid).bind("mouseout", function (event) {
                    setInsideWindow(false);
                    $(document).unbind("keydown");
                    actionSettings.keyboardAction = false;
                    actionSettings.currentKey = null;
                });
                if (!ddList) {
                    $("#" + titleid).bind("click", function (event) {
                        setInsideWindow(false);
                        if ($("#" + childid + ":visible").length == 1) {
                            $("#" + childid).unbind("mouseover");
                        } else {
                            $("#" + childid).bind("mouseover", function (event) {
                                setInsideWindow(true);
                            });
                            openMe();
                        }
                    });
                }
                $("#" + titleid).bind("mouseout", function (evt) {
                    setInsideWindow(false);
                }); */
                bindOpenCloseEvents();
            }
            
            
            $this.bind("disable",disable);
            $this.bind("enable",enable);
        }

        function getByIndex(index) {
            for (var i in a_array) {
                if (a_array[i].index == index) {
                    return a_array[i];
                }
            }
        }
		
		function getById(id) {
            for (var i in a_array) {
                if (a_array[i].id == id) {
                    return a_array[i];
                }
            }
        }

        function manageSelection(obj) {
            var childid = getPostID("postChildID");
            if (!ddList) {
                $("#" + childid + " a.selected").removeClass("selected");
            }
            var selectedA = $("#" + childid + " a.selected").attr("id");
            if (selectedA !== undefined) {
                var oldIndex = (actionSettings.oldIndex === undefined || actionSettings.oldIndex === null) ? a_array[selectedA].index : actionSettings.oldIndex;
            }
            if (obj && !ddList) {
                $(obj).addClass("selected");
            }
            if (ddList) {
                var keyCode = actionSettings.currentKey;
                if ($("#" + elementid).attr("multiple") === true) {
                    if (keyCode == 17) {
                        //control
                        actionSettings.oldIndex = a_array[$(obj).attr("id")].index;
                        $(obj).toggleClass("selected");
                        //multiple
                    } else if (keyCode == 16) {
                        $("#" + childid + " a.selected").removeClass("selected");
                        $(obj).addClass("selected");
                        //shift
                        var currentSelected = $(obj).attr("id");
                        var currentIndex = a_array[currentSelected].index;
                        for (var i = Math.min(oldIndex, currentIndex); i <= Math.max(oldIndex, currentIndex); i++) {
                            $("#" + getByIndex(i).id).addClass("selected");
                        }
                    } else {
                        $("#" + childid + " a.selected").removeClass("selected");
                        $(obj).addClass("selected");
                        actionSettings.oldIndex = a_array[$(obj).attr("id")].index;
                    }
                } else {
                    $("#" + childid + " a.selected").removeClass("selected");
                    $(obj).addClass("selected");
                    actionSettings.oldIndex = a_array[$(obj).attr("id")].index;
                }
            }
        }

        function addNewEvents(id) {
            document.getElementById(id).refresh = function (e) {
                $("#" + this.id).dd(options);
            };
        }

        function setInsideWindow(val) {
            actionSettings.insideWindow = val;
        }

        function getInsideWindow() {
            return actionSettings.insideWindow;
        }

        function applyEvents() {
            var mainid = getPostID("postID");
            var actions_array = attributes.actions.split(",");
            for (var iCount = 0; iCount < actions_array.length; iCount++) {
                var action = actions_array[iCount];
                var actionFound = $("#" + elementid).attr(action);
                if (actionFound !== undefined) {
                    switch (action) {
                    case "onfocus":
                        $("#" + mainid).bind("mouseenter", function (event) {
                            document.getElementById(elementid).focus();
                        });
                        break;
                    case "onclick":
                        $("#" + mainid).bind("click", function (event) {
                            document.getElementById(elementid).onclick();
                        });
                        break;
                    case "ondblclick":
                        $("#" + mainid).bind("dblclick", function (event) {
                            document.getElementById(elementid).ondblclick();
                        });
                        break;
                    case "onmousedown":
                        $("#" + mainid).bind("mousedown", function (event) {
                            document.getElementById(elementid).onmousedown();
                        });
                        break;
                    case "onmouseup":
                        //has in closeMe mthod
                        $("#" + mainid).bind("mouseup", function (event) {
                            document.getElementById(elementid).onmouseup();
                            //setValue();
                        });
                        break;
                    case "onmouseover":
                        $("#" + mainid).bind("mouseover", function (event) {
                            document.getElementById(elementid).onmouseover();
                        });
                        break;
                    case "onmousemove":
                        $("#" + mainid).bind("mousemove", function (event) {
                            document.getElementById(elementid).onmousemove();
                        });
                        break;
                    case "onmouseout":
                        $("#" + mainid).bind("mouseout", function (event) {
                            document.getElementById(elementid).onmouseout();
                        });
                        break;
                    }
                }
            }
        }

        function setOutOfVision() {
            var sId = getPostID("postElementHolder");
            $("#" + elementid).after("<div style='height:0px;overflow:hidden;position:absolute;' id='" + sId + "'></div>");
            $("#" + elementid).appendTo($("#" + sId));
        }

        function setTitleText(sText) {
            var titletextid = getPostID("postTitleTextID");
            $("#" + titletextid).html(sText);
        }

        function next() {
            var titletextid = getPostID("postTitleTextID");
            var childid = getPostID("postChildID");
            var allAs = $("#" + childid + " a.enabled");
            for (var current = 0; current < allAs.length; current++) {
                var currentA = allAs[current];
                var id = $(currentA).attr("id");
                if ($(currentA).hasClass("selected") && current < allAs.length - 1) {
                    $("#" + childid + " a.selected").removeClass("selected");
                    $(allAs[current + 1]).addClass("selected");
                    //manageSelection(allAs[current+1]);
                    var selectedA = $("#" + childid + " a.selected").attr("id");
                    if (!ddList) {
                        setTitleText(a_array[selectedA].titleHtml);
                    }
                    if (parseInt(($("#" + selectedA).position().top + $("#" + selectedA).height())) >= parseInt($("#" + childid).height())) {
                        $("#" + childid).scrollTop(($("#" + childid).scrollTop()) + $("#" + selectedA).height() + $("#" + selectedA).height());
                    }
                    break;
                }
            }
        }

        function previous() {
            var titletextid = getPostID("postTitleTextID");
            var childid = getPostID("postChildID");
            var allAs = $("#" + childid + " a.enabled");
            for (var current = 0; current < allAs.length; current++) {
                var currentA = allAs[current];
                var id = $(currentA).attr("id");
                if ($(currentA).hasClass("selected") && current !== 0) {
                    $("#" + childid + " a.selected").removeClass("selected");
                    $(allAs[current - 1]).addClass("selected");
                    //manageSelection(allAs[current-1]);
                    var selectedA = $("#" + childid + " a.selected").attr("id");
                    if (!ddList) {
                        setTitleText(a_array[selectedA].titleHtml);
                    }
                    if (parseInt(($("#" + selectedA).position().top + $("#" + selectedA).height())) <= 0) {
                        $("#" + childid).scrollTop(($("#" + childid).scrollTop() - $("#" + childid).height()) - $("#" + selectedA).height());
                    }
                    break;
                }
            }
        }

        function setValue() {
            var childid = getPostID("postChildID");
            var allSelected = $("#" + childid + " a.selected");
            if (allSelected.length == 1) {
                var sText = $("#" + childid + " a.selected").text();
                var selectedA = $("#" + childid + " a.selected").attr("id");
                if (selectedA !== undefined) {
                    var sValue = a_array[selectedA].value;
                    document.getElementById(elementid).selectedIndex = a_array[selectedA].index;
                }
            } else if (allSelected.length > 1) {
                var alls = $("#" + elementid + " > option:selected").removeAttr("selected");
                for (var i = 0; i < allSelected.length; i++) {
                    var selectedA = $(allSelected[i]).attr("id");
                    var index = a_array[selectedA].index;
                    document.getElementById(elementid).options[index].selected = "selected";
                }
            }
        }

        function openMe() {
            var childid = getPostID("postChildID");
            if (oldDiv != "" && childid != oldDiv) {
                $("#" + oldDiv).slideUp("fast");
                $("#" + oldDiv).css({
                    zIndex: '0'
                });
            }
            if ($("#" + childid).css("display") == "none") {
                selectedValue = a_array[$("#" + childid + " a.selected").attr("id")].html;
                $(document).bind("keydown", function (event) {
                    var keyCode = event.keyCode;
                    if (keyCode == 39 || keyCode == 40) {
                        //move to next
                        event.preventDefault();
                        event.stopPropagation();
                        next();
                    }
                    if (keyCode == 37 || keyCode == 38) {
                        event.preventDefault();
                        event.stopPropagation();
                        //move to previous
                        previous();
                    }
                    if (keyCode == 27 || keyCode == 13) {
                        closeMe();
                        setValue();
                    }
                    if ($("#" + elementid).attr("onkeydown") !== undefined) {
                        document.getElementById(elementid).onkeydown();
                    }
                });
                $(document).bind("keyup", function (event) {
                    if ($("#" + elementid).attr("onkeyup") !== undefined) {
                        //$("#"+elementid).keyup();
                        document.getElementById(elementid).onkeyup();
                    }
                });
                $(document).bind("mouseup", function (evt) {
                    if (getInsideWindow() === false) {
                        closeMe();
                    }
                });
                $("#" + childid).css({
                    zIndex: options.zIndex
                });
                $("#" + childid).slideDown("fast");
                if (childid != oldDiv) {
                    oldDiv = childid;
                }
            }
        }

        function closeMe() {
            var childid = getPostID("postChildID");
            $(document).unbind("keydown");
            $(document).unbind("keyup");
            $(document).unbind("mouseup");
            $("#" + childid).slideUp("fast", function (event) {
                checkMethodAndApply();
                $("#" + childid).css({
                    zIndex: '0'
                });
            });
        }

        function checkMethodAndApply() {
            var childid = getPostID("postChildID");
            var currentSelectedValue = a_array[$("#" + childid + " a.selected").attr("id")].text;
            
			// We need the "change" event...
			if (selectedValue != currentSelectedValue) {
				setValue();
				$("#" + elementid).trigger("change");
            }
        }

        function hightlightArrow(ison) {
            var arrowid = getPostID("postArrowID");
            if (ison == 1) {
				$("#" + arrowid).css({ backgroundPosition: '0 100%' });
			} else {
				$("#" + arrowid).css({ backgroundPosition: '0 0' });
			}
        }
    };
	
    /**
     * Converts a collection of elements into msDropDowns.
     */
    $.fn.msDropDown = function (properties) {
        var dds = $(this);
        for (var iCount = 0; iCount < dds.length; iCount++) {
            var id = $(dds[iCount]).attr("id");
            if (properties === undefined) {
                $("#" + id).dd();
            } else {
                $("#" + id).dd(properties);
            }
        }
    };
    
})(jQuery);