﻿var SelectControl = Class.create({
    initialize: function(select, options) {
        if (typeof select == "string") {
            this.select = $(select);
        } else {
            this.select = select;
        }
        var elementId = this.select.id;
        this.viewElement = new Element("div", { id: elementId + "_view" }).addClassName('selectControlLabel');
        this.container = new Element("div").setStyle({ 'position': 'relative', padding: '1px 0' });

        if (this.select.getStyle('width')) {
            this.viewElement.setStyle({ width: this.select.getStyle('width') });
        }
        this.valueElement = new Element("input", { name: this.select.name, type: 'hidden', id: elementId });

        this.select.wrap(this.container);
        new Insertion.Before(this.select, this.viewElement);
        new Insertion.Before(this.select, this.valueElement);


        var listMouseover = function(e) {
            this.listActive = 1;
        };
        var listMouseout = function(e) {
            this.listActive = 0;
            this.hideTimeoutKey = setTimeout(this.timeoutHide.bind(this), 1500);
        };
        this.selectList = new Element("ul").addClassName('selectControlList');

        // apply positioning
        this.update = new Element('div').insert(this.selectList).setStyle({
            position: 'absolute',
            width: this.viewElement.getWidth() + 'px',
            top: this.viewElement.getHeight() + 'px',
            left: 0
        }); //, width: this.viewElement.getWidth() + 'px' });
        new Insertion.Before(this.select, this.update);
        this.update.hide();
        //setTimeout(this.setPosition.bind(this), 1000);

        // don't get in the way of other selectors
        this.sendToBack();

        this.options = Object.extend({
            autoStart: true
        }, options || {});

        this.optionalData = {};
        this.data = {};
        this.selectOptions = [];

        var optionList = this.select.getElementsByTagName('option');
        var nodes = $A(optionList);
        for (i = 0; i < nodes.length; i++) {
            this.data[nodes[i].value] = nodes[i].innerHTML;
        }

        // hide initial select box
        this.select.name += "__";
        this.select.id += "__";
        this.select.hide();

        // start
        if (this.options.autoStart == true) {
            this.start();
        }
    },
    setPosition: function() {
        new Insertion.Before(this.select, this.update);
        Position.clone(this.viewElement, this.update, {
            setHeight: false,
            offsetTop: this.viewElement.offsetHeight + (this.options.offsetListTop || 0),
            offsetLeft: (this.options.offsetListLeft || 0)
        });
        this.update.hide();
        this.update.setStyle({ left: 0, zoom: 1 });
        //alert(this.viewElement.getHeight());
    },
    start: function() {
        var optionList = this.select.getElementsByTagName('option');
        var selectedOptionValue = this.select.getValue();
        var nodes = $A(optionList);
        for (i = 0; i < nodes.length; i++) {
            this.selectList.insert(
                    new Element("li", { id: nodes[i].value, title: nodes[i].title })
                      .update(this.writeLabel(nodes[i].value))
                      .observe('mouseover', function() { $(this).addClassName("active"); })
                      .observe('mouseout', function() { $(this).removeClassName("active"); })
                      .observe('click', this.updateLabel.bindAsEventListener(this, nodes[i].value))
                );
            if (i == 0 || nodes[i].value == selectedOptionValue) {
                this.viewElement.update(this.writeLabel(nodes[i].value));
                this.valueElement.value = nodes[i].value;
            }
        }
        if (nodes.length > 1) {
            this.viewElement.observe("click", this.showList.bindAsEventListener(this));
        } else {
            this.viewElement.addClassName('inactiveSelectControlLabel');
        }
    },
    resetSelected: function(key) {
        this.selectList.select('li').each(function(el) {
            el.removeClassName('selected');
            if (el.id == key)
                el.addClassName('selected');
        });
    },
    writeLabel: function(key) {
        return new Element('span').insert(this.data[key]);
    },
    sendToBack: function() {
        this.update.setStyle({ zIndex: '500' });
        $(this.container).setStyle({ 'zIndex': '499' });
    },
    bringToFront: function() {
        this.update.setStyle({ zIndex: '600' });
        $(this.container).setStyle({ 'zIndex': '599' });
    },
    hideList: function(options) {
        var duration = 0.35;
        if (options && options.duration) {
            duration = options.duration;
        }
        this.fade = Effect.Fade(this.update, { duration: duration });
        this.sendToBack();
        this.userWantsList = 0;
    },
    showList: function(e, options) {
        this.appear = Effect.Appear(this.update, { duration: 0.35 });
        this.bringToFront();
        //this.hideTimeoutKey = setTimeout(this.timeoutHide.bind(this), 1500);
        this.userWantsList = 1;
        var foo = function(e) {
            var elt = $(Event.element(e));
            if (!elt.descendantOf(this.container)) {
                this.hideList();
            }
        };
        Event.observe(document, 'click', foo.bind(this));
    },
    timeoutHide: function() {
        if (!this.userWantsList) return;
        if (!this.listActive) this.hideList();
    },
    updateLabel: function(e, key) {
        this.updateLabelBase(e, key);
    },
    updateLabelBase: function(e, key) {
        var label = this.data[key];
        this.viewElement.update(this.writeLabel(key));
        this.valueElement.value = key;
        this.resetSelected(key);
        this.hideList();
    }
});

