document.selectElement = {
    open: false,

    init: function() {
        $('select:not(.noreplace)').each(
            function(i,element) {
                document.selectElement.replaceElement(element);
            }
        );

        $('body').mousedown(this.closeList);

        if (document.lightbox) {
            document.lightbox.attachEvent('post-hide', document.selectElement.init);
        }
    },

    replaceElement: function(element) {
        var columnCount = 0;
        var optionIndex = 0;

        var bar       = $('<div></div>').addClass('select');
        var label     = $('<div></div>').addClass('select-label');
        var container = $('<div></div>').addClass('select-list').hide();
        var listBody  = $('<tbody></tbody>');
        var list      = $('<table></table>');

        if (id = $(element).attr('id')) {
            $(bar).attr('id', id + '-replace');
        }

        $(list).append(listBody);

        $(container).append($(list));
        $(container).mousedown(function(event) { return false });
        $(container).bind('mousewheel',     function(event) { return document.selectElement.scrollHandler(event, container); });
        $(container).bind('DOMMouseScroll', function(event) { return document.selectElement.scrollHandler(event, container); }); // Firefox

        $(bar).append(label);
        $(bar).append(container);
        $(bar).mousedown(function(event) { return document.selectElement.openList(event, container); });

        // children() only goes through the immediate children
        $(element).find('*').each(function (i, child) {
            var row = $('<tr></tr>');

            switch ($(child).context.nodeName) {
                case 'OPTION':
                    var contents = $(child).html().split('|');

                    if (contents.length > columnCount) {
                        columnCount = contents.length;
                    }

                    $(contents).each(function(i, string) {
                        if (optionIndex == element.selectedIndex && i == 0) {
                            document.selectElement.setLabel(label, string);
                        }

                        var column = $('<td></td>').addClass('option')
                                                   .addClass('col' + i)
                                                   .html(string);

                        if ($(child).attr('disabled')) $(column).addClass('disabled');

                        if (i == contents.length - 1 && columnCount - contents.length > 0) {
                            $(column).attr('colSpan', columnCount - contents.length + 1);
                        }

                        row.append(column);
                    });

                    if (! $(child).attr('disabled')) {
                        $(row).mousedown({optionIndex: optionIndex}, function(event) {
                            document.selectElement.pickOption(event, element, event.data.optionIndex);
                        });
                    }

                    optionIndex++;
                    break;
                case 'OPTGROUP':
                    if ($(child).attr('label').split('|').length > columnCount) {
                        columnCount = $(child).attr('label').split('|').length;
                    }

                    var column = $('<td></td>').attr('colSpan', columnCount)
                                               .addClass('optgroup')
                                               .html($(child).attr('label').replace('|', ''));

                    $(row).append($(column));
                    break;
            }

            $(listBody).append(row);
        });

        $(element).hide();
        $(element).addClass('noreplace');
        $(element).after($(bar));
    },

    openList: function(event, element) {
        // event.which = 1 = left mouse click
        if (event.which != 1) return;

        if (document.selectElement.open) return document.selectElement.closeList();

        $(element).show();

        document.selectElement.open = element;

        return false;
    },

    closeList: function(event) {
        // event.which = 1 = left mouse click
        if (typeof(event) != 'undefined' && event.which != 1) return;

        if (! document.selectElement.open) return;

        $(document.selectElement.open).hide();

        document.selectElement.open = false;
    },

    setLabel: function(element, label) {
        if (! $(element).hasClass('select-label')) {
            element = $(element).parents('.select-list').siblings('div.select-label');
        }
        $(element).html(label);
    },

    pickOption: function(event, element, index) {
        // event.which = 1 = left mouse click
        if (typeof(event) != 'undefined' && event.which != 1) return;

        element.selectedIndex = index;
        $(element).trigger('change');

        document.selectElement.setLabel(
            event.target,
            $(event.target).parent('tr').find('td.col0').html()
        );

        document.selectElement.closeList();
    },

    scrollHandler: function(event, element) {
        var scrollOffset   = event.detail ? event.detail * 40 : event.wheelDelta * -1;
        var scrollPosition = $(element).innerHeight() + $(element).scrollTop() + scrollOffset;

        if (scrollPosition > $(element)[0].scrollHeight) {
            $(element).scrollTop($(element)[0].scrollHeight - $(element).innerHeight());

            return false;
        } else if (scrollPosition < $(element).innerHeight()) {
            $(element).scrollTop(0);

            return false;
        }
    }
};

$(document).ready(function() {
    document.selectElement.init();
});
