A keyboard- or mouse-navigated dropdown menu for a text field or other input method. Runs on jQuery.

Usage

Initially, the dropdown has to be set up, as such:

$("input.dropdown").dropdown({
    objects: [], // this is a textual list of each of the items in the list to begin with
    maxitems: 10, // maximum number of items to display
    listclass: 'textDropdown', // the class of the list
    objclass: 'textDropdownElement', // the class of each list element
    containerclass: 'textDropdownContainer', // the class of the container wrapping around the list
    selectedclass: 'textDropdownSelected', // the class of the selected item
    onrender: function(item, listclass) {
        // item is a passed list object; listclass is the class that the renderer is using for it
        // should return a string, using an <li> tag as a wrapper
    },
    onclick: function($item) {
        // $item is the item clicked, as a jQuery object
    }
});

When the list is to be updated, it can be called using $("input.dropdown").dropdown('update',data);, where data is a variable array containing the list elements. You can also call to show or hide the list as-is, using $("input.dropdown").dropdown('show'); or $("input.dropdown").dropdown('hide');.

A CSS file also has to be set up with a code to manage the classes for the lists. Here is the example a previous website of mine used for its AJAX search:

div.textDropdownContainer {
    background:#a39c8f;
    padding:1px;
}
ul.textDropdown {
    background:transparent;
    margin:0;
    padding:0;
}
li.textDropdownSelected {
    background:#99ee99 !important;
    color:#116611 !important;
}
li.textDropdownElementBest {
    background:#dce4dc;
}
li.textDropdownElementGood {
    background:#e4e3dc;
}
li.textDropdownElementPoor {
    background:#e4dcdc;
}
li.textDropdownElement {
    color:#6b614f;
    cursor:pointer;
    cursor:hand;
    font-size:80%;
    list-style-type:none;
    margin-top:1px;
    padding:2px 4px;
    text-align:left;
}
li.textDropdownElement:hover {
    background:#f0efed;
}

Code

(function($){
    var t = undefined;
    var $element = undefined;
    var $node = undefined;
    var settings = {
        objects: [],
        maxitems: 10,
        listclass: 'textDropdown',
        objclass: 'textDropdownElement',
        containerclass: 'textDropdownContainer',
        selectedclass: 'textDropdownSelected',
        onrender: undefined,
        onclick: undefined
    };
    var selected = 0;
    var lastupdate = "";

    var methods = {
        init: function() {
            methods.move.apply(t);

            $(window).resize(function() {
                methods.move.apply(t);
            });
            $element.blur(function() {
                setTimeout(function() { methods.hide.apply(t); },250);
            });
            $element.keyup(function(event) {
                if (event.which == 38) {
                    selected--;
                    if (selected < 0) selected = 0;
                } else if (event.which == 40) {
                    selected++;
                    if (selected > settings.maxitems+1) selected = settings.maxitems+1;
                } else if (event.which == 13) {
                    if (selected > 0 && selected <= settings.maxitems)
                        methods.click.apply(t,[$node.find("li:nth-child("+selected+")")]);
                } else {
                    return;
                }
                $node.find("li").not(":nth-child("+selected+")").each(function() {
                    $(this).removeClass(settings.selectedclass);
                });
                $node.find("li:nth-child("+selected+")").each(function() {
                    $(this).addClass(settings.selectedclass);
                });
            });

            methods.hide.apply(t);

            return t.each(function() {});
        },
        show: function() {
            $node.show();
            methods.move.apply(t);

            return t.each(function() {});
        },
        hide: function() {
            selected = 0;
            $node.hide();

            return t.each(function() {});
        },
        click: function($item) {
            if (settings.onclick && typeof settings.onclick == "function")
                return settings.onclick.apply(t,[$item]);
            $element.val($item.html());
            methods.hide.apply(t);

            return t.each(function() {});
        },
        render: function(item) {
            if (settings.onrender && typeof settings.onrender == "function")
                return settings.onrender.apply(t,[item,settings.objclass]);
            return "<li class='"+settings.objclass+"'>"+item+"</li>";
        },
        update: function(newobjs) {
            if (newobjs.length <= 0 || newobjs[0].length <= 0) {
                methods.hide.apply(t);
                return t.each(function() {});
            }
            var text = "";
            text += "<ul class='"+settings.listclass+"'>";
            for (i = 0; i < newobjs.length && i < settings.maxitems; i++) {
                text += methods.render.apply(t,[newobjs[i]]);
            }
            text += "</ul>";
            if (text != lastupdate) {
                selected = 0;
                $node.empty();
                lastupdate = text;
                $node.html(text);
                $node.find("ul > li").each(function() {
                    $(this).click(function() {
                        methods.click.apply(t,[$(this)]);
                    });
                });
            }
            methods.show.apply(t);

            return t.each(function() {});
        },
        move: function() {
            var offset = $element.offset();
            offset.top += $element.height()
                        + parseInt ($element.css("padding-top"))
                        + parseInt ($element.css("border-top-width"))
                        + parseInt ($element.css("border-bottom-width"));
            $node.offset(offset);

            return t.each(function() {});
        }
    }

    $.fn.dropdown = function(options) {
        t = this;

        if (options && typeof options == "string" && methods[options]) {
            return methods[options].apply(t,Array.prototype.slice.call(arguments,1));
        } else {
            if (options) 
                $.extend(settings,options);

            $element = $(this);
            $node = $("<div></div>",{
                id: 'dropdownObj',
                style: 'position:absolute;top:-999px;left:-999px;width:'+$element.width()+'px'
            }).addClass(settings.containerclass);
            $node.appendTo($("body"));

            methods.init.apply(t);
        }

        return t.each(function() {});
    };
})(jQuery);

Next Post Previous Post