// bb_ext.js
// Extra bb widgets.
// Particularly editable combobox
// Eventually merge into app_common/browser/browser_base.js


if (window.bb && !window.bb.bbcombobox) {

    // derived http://www.quirksmode.org/js/findpos.html
    // Find x,y position of obj (a DOM Element) on page
    // Generally only reliable after onload().
    // Fails inside scrolling elements (scrollOffset not considered)
    window.bbtool.find_pos = function(obj) {
        var curleft = obj.offsetLeft;
        var curtop = obj.offsetTop;
        if (obj.offsetParent) {
            curleft = obj.offsetLeft;
            curtop = obj.offsetTop;
            obj = obj.offsetParent
            while (obj) {
                curleft += obj.offsetLeft;
                curtop += obj.offsetTop;
                obj = obj.offsetParent
            }
        }
        return [curleft,curtop];
    } // bbtool.find_pos

    // Shim to allow regular manipulation of the overlay edit box
    window.bb.bbcombobox_other = function(inWidgetElem, inModelID) {
        bb.bbwindow.apply(this, [inWidgetElem, inModelID]); // extends bbfield
        this.add_isa('bbcombobox_other');
    }

    // combobox Derived from http://particletree.com/features/combo-box

    // Editable ComboBox (editable DDL)
    // Counts as two bbfield instances
    // Causes an extra field to be returned with the form
    // containing the user entry.  In AJ, the extra field is queued
    // named after the control _other

    // Issues: most combo box sources on the net either assign
    //  the user input as the value of the box. Alternatively, they assign
    //  the DESCRIPTION of the select control as the value of the
    //  editable portion of the combo box.
    //  In the generic modular class environment, we would not be able to
    //  distinguish the user input from a regular option, and the user input
    //  will not conform to our data conventions (where the <option> value attrib
    //  is an integer or token, NEVER the label).  Generally another record must
    //  be created or the user input used once and discarded.
    /* Others on net use a DHTML menu + hidden input to do this.  Same issue as
     *  above with return value
     *
     * We expect <span style="position:relative;"><select>...</select></span>
     *  Stays close to browser native behavior., if we want, we can rip and
     *  mangle the <select> into something else
     */
    window.bb.bbcombobox = function(inWidgetElem, inModelID) {
        bb.bbfield.apply(this, [inWidgetElem, inModelID]); // extends bbfield
        this.add_isa('bbcombobox');

        // value that should be replaced with edit box.
        this.other_value = -1;

        this.initialize = function() {
            if (this.elem.hasAttribute('other_value')) {
                this.other_value = this.elem.getAttribute('other_value');
            }

            this.other_name = this.elem.getAttribute('name') + '_other';
            this.other_elem = document.createElement('div');
            this.other_elem.setAttribute('class', 'bbcombobox_other bbinvisible');
            this.other_elem.style.width = '' + (this.elem.style.width - 27) + 'px';

            this.other_elemi = document.createElement('input');
            this.other_elemi.setAttribute('type', 'text');
            this.other_elemi.setAttribute('name', this.other_name);
            this.other_elemi.setAttribute('value', '');
            this.other_elemi.setAttribute('class', 'bbfield');

            this.other_elem.appendChild(this.other_elemi);
            this.elem.parentNode.insertBefore(this.other_elem, this.elem);

            // widgetize.  Must be done before any post_widgetizing so
            // it can generate bbrecord events
            var x = new bb.bbfield(this.other_elemi, null);
            x = new bb.bbcombobox_other(this.other_elem, null);

            this.dispatcher.register('click', this.elem, this.handle_select_click, this, 'click_bbcombobox.'+this.elem.name);
            this.dispatcher.register('change', this.elem, this.handle_select_change, this, 'change_bbcombobox.'+this.elem.name);

            // seamonkey 1.0.6 makes div too large, intercepts clicks.
            // this.dispatcher.register('click', this.other_elem, this.handle_other_click, this, 'click_bbcombobox_other.'+this.elem.name);
            // this.debug('initialized bbcombobox');
        } // initialize

        this.post_widgetize = function() {
            // fixup other_elem
            var w = this;
            var p = bbtool.find_pos(w.elem);
            w.handle_select_change(w.elem, w, w);
        } // post_widgetize

        // move this.other_elem ontop of this.elem
        this.place_other_elem = function() {
            var w = this;
            var p = bbtool.find_pos(w.elem);
            //w.other_elem.widget.moveto(p[1], p[0]); // position: absolute

            // border thickness adjust. Probably FF specific
            w.other_elem.widget.moveto(w.elem.offsetTop, w.elem.offsetLeft); // inside position: relative
            var nsize = (w.elem.style.width - 27) ;
            if (nsize < 0) {
                nsize = '11em'; // 2 em less than standard select width
            } else {
                nsize = ''+nsize + 'px';
            }
            // alert ('size: '+nsize);
            w.other_elem.style.width = nsize;
            w.other_elemi.style.width = nsize;
            w.debug('other_elem size: '+nsize);


        }

        // Event click
        this.handle_select_click = function(inElement, inArgList, inEvent) {
            var w = inArgList;
            w.debug('bbcombobox.handle_select_click');
        }

        // Event click on the positioning div
        // delegate to click on select.
        this.handle_other_click = function(inElement, inArgList, inEvent) {
            var w = inArgList;
            w.debug('bbcombobox_other.handle_other_click');
            // w.handle_select_change();
            // seamonkey 1.0.6 makes the bbcombobox_other div bigger than the
            //
            w.elem.focus();
        }

        // Event change
        // if the 'other' item is selected, show the edit control
        this.handle_select_change = function(inElement, inArgList, inEvent) {
            var w = inArgList;
            w.debug('bbcombobox.handle_select_change');
            if (w.elem.getValue() == w.other_value) {
                // replace_class(w.other_elem, 'bbinvisible', 'bbvisible');
                w.other_elem.widget.show();
                w.place_other_elem();
                w.other_elem.focus();
            } else {
                w.other_elem.widget.hide();
                // replace_class(w.other_elem, 'bbvisible', 'bbinvisible');
            }
        }

        this.initialize();


        // create input elem
        // put on top of select
        // initially invisible ### unless the 'other' option is selected
    } // bb.bbcombobox


} else {
    if (!window.bb) {
        // alert("browser_base.js not included");
    }
}
