Hi everybody,
I'm working on an application based on Ext tree for few weeks. I've almost finish it, but it still remains problems on it.

1) The "tab" key in Firefox

In each branch of my tree i've got many inputs. With IE, when I've got the focus in one of the input, I can use the "tab" key to navigate in the others.
In Firefox it doesn't work. When I press tab the focus go outside the tree.

2) Select a value in a drop down reload the page in Firefox

A realy anoying issue with Firefox is about dropdowns. When I click on a value to select it, the page reload itself.
It's bizarre because I havn't any listener on my dropdown.

3) I can't insert "complex" html in each branch with IE

In each branch I insert some html.
Basically, it's a span which contains others span, dropdown, links, etc.
I tried to manualy add the html in the branch (all the html is contained in a variable which I insert), or to did it with "insertHtml" and "append" ext's methods, and the both works fine under Firefox, but not under IE.

If I use the "variable" solution, the content which must be in my main span is outside it.
If I use the ext's methods, I've got this error "Invalide html source code".

More infos in this thread.

Here is my code :

Code:
Ext.namespace('addRules');

addRules.line = function() {

   /**
    * Removes input(s) from the line
    */
    var removeInputClick = function() {
        var elementToDel;
        var parent = Ext.get(this.id).findParent('.line');
        var lineNbr = parent.id.substr(1, parent.id.length -1);

        if (this.id.indexOf("addValue") != -1) {
            var inputId = "valueTag" + lineNbr;
            elementToDel = Ext.get(inputId);
        }
        // if it's the attribute
        else if (this.id.indexOf("addAttribute") != -1) {
            var attributeNbr = this.id.charAt(12);
            elementToDel = "tag" + lineNbr + "Attribute" + attributeNbr;
        }

        Ext.get(elementToDel).remove();

        if (this.id.indexOf("addValue") != -1) {
            stopAndStartObserving('addValue' + lineNbr,
                                  removeInputClick,
                                     addRules.line.addInputClick);
        }
        else {
            stopAndStartObserving('addAttribute' + attributeNbr + 'Tag' + lineNbr,
                                  removeInputClick,
                                  addRules.line.addInputClick);
            // Decrementing the counter
            var value = parseFloat(Ext.get('attributeNbrLine' + lineNbr).getValue())-1;
            Ext.get('attributeNbrLine' + lineNbr).set({ value:  value});
        }
    }; // removeInputClick

    /**
     * Unload then load listener
     */
    var stopAndStartObserving = function(id, eventStop, eventStart) {
        Ext.get(id).un('click', eventStop);
        Ext.get(id).on('click', eventStart);
    }; // stopAndStartObserving

    return {

        /**
         * Update the "dropDown" div in adding a dropDown
         * generated in the controler.
         */
        addDropDown: function() {
            Ext.get('dropDown').load ({
                url: 'getTagsList',
                method: 'post',
                callback: function() {
                    Ext.get('tag').set({ name: 'tag' + addRules.app.getNbrLines() });
                    Ext.get('tag').set({ id: 'tag' + addRules.app.getNbrLines() });
                    Ext.get('dropDown').set({ id: 'dropDown' + addRules.app.getNbrLines() });
                }
            });
        }, //addDropDown

        /**
         * Add inputs on the line
         */
        addInputClick: function() {
            // Getting the parent div with class name 'line'
            var parent = Ext.get(this).findParent('.line');
            // The line's number is the number after "l" in the parent's id
            var lineNbr = parent.id.substr(1, parent.id.length -1);

            if (this.id.indexOf("addValue") != -1) {
                inputId = "valueTag" + lineNbr;
                divToInsertInto = "value"+ lineNbr;
                Ext.DomHelper.append(Ext.get(divToInsertInto), { tag: 'input',
                                                                 type: 'text',
                                                                 id: inputId,
                                                                 'name': inputId });
            }
            else {
                var attributeNbr = Ext.get('attributeNbrLine' + lineNbr).getValue();
                // int conversion
                attributeNbr = parseFloat(attributeNbr)+1;
                attributeNbr2 = attributeNbr + 1;

                inputId = "attribute"+ attributeNbr +"Tag"+ lineNbr;
                var linkId = "addAttribute"+ attributeNbr2 +"Tag"+ lineNbr;
                divToInsertInto = "l"+ lineNbr;
                var idDiv = 'tag'+ lineNbr +'Attribute'+ attributeNbr;

                Ext.DomHelper.append(Ext.get(divToInsertInto), { tag: 'div',
                                                                 id: idDiv,
                                                                 style: 'display: inline;' });
                Ext.DomHelper.append(Ext.get(idDiv), { tag: 'input',
                                                       type: 'text',
                                                       id: inputId,
                                                       'name': inputId });

                Ext.DomHelper.append(Ext.get(idDiv), ' Value : ');
                Ext.DomHelper.append(Ext.get(idDiv), { tag: 'input',
                                                       type: 'text',
                                                       id: inputId+'Value',
                                                       name: inputId+'Value' });
                Ext.DomHelper.append(Ext.get(idDiv), ' ');

                // We increment attributes'counter
                Ext.get('attributeNbrLine' + lineNbr).set({ value: attributeNbr });

                Ext.DomHelper.append(Ext.get(idDiv), { tag: 'a',
                                                       href: '#',
                                                       id: linkId,
                                                       html: "Attribute" });
                // We had a new listener on the link
                Ext.get(linkId).on('click', addRules.line.addInputClick);
            }

            if (this.id.indexOf("addValue") != -1) {
                stopAndStartObserving('addValue' + lineNbr,
                                      addRules.line.addInputClick, removeInputClick);
            }
            else {
                stopAndStartObserving('addAttribute' + attributeNbr + 'Tag' + lineNbr,
                                      addRules.line.addInputClick, removeInputClick);
            }
        }, // addInputClick

        /**
         * Used to insert some html in branches
         */
        lineContent: function() {
        var line = '<div id="l'+ addRules.app.getNbrLines() +'" class="line" style="display: inline;">';
            line += '<a href="#" id="parentLine'+ addRules.app.getNbrLines() +'">+</a> ';
            line += '<div id="dropDown" style="display: inline"></div>';
            line += ' <a href="#" id="addValue'+ addRules.app.getNbrLines() +'">Value</a>';
            line += '<div id="value'+ addRules.app.getNbrLines() +'" style="display: inline;">';
            line += '</div>';
            line += '<input type="hidden" value="0" id="attributeNbrLine'+ addRules.app.getNbrLines() +'">';
            line += ' <a href="#" id="addAttribute1Tag'+ addRules.app.getNbrLines() +'">Attribute</a>';
            line += '</div>';

            return line;
        }, // lineContent

        /**
         * Insert a new branch after the last one
         */
        addLine: function() {
            var tree = addRules.app.getTree();
            var node = tree.getSelectionModel().getSelectedNode();

            // Preventing that the link is clicked but the line is not selected
            if(node != null) {
                addRules.app.setNbrLines(addRules.app.getNbrLines() + 1);
                var nbrLines = addRules.app.getNbrLines();
                //alert(node.id);
                var newBranch = new Ext.tree.TreeNode({ text: addRules.line.lineContent(),
                                                        expanded: true,
                                                        draggable: true,
                                                        id: 'node'+ nbrLines });

                node.appendChild(newBranch);

                // Loading the listeners
                Ext.get('parentLine'+ nbrLines).on('click', addRules.line.addLine);
                Ext.get('addValue'+ nbrLines).on('click',
                                             addRules.line.addInputClick);
                Ext.get('addAttribute1Tag'+ nbrLines).on('click',
                                                         addRules.line.addInputClick);
                addRules.line.addDropDown();
            }
        } // addLine
    }; // return
}(); // addRules.line
Code:
Ext.namespace('addRules');

addRules.app = (function() {
    // private

    // the number of lines is also equal to the number of items
    var nbrLines = 2;
    var expanded = false;

    // set up the tree
    var tree = new Ext.tree.TreePanel({
        enableDD: true,
        animate: true
    });

    var root = new Ext.tree.TreeNode({
        text: 'fwkDetermineRouting',
        id: 'node1'
    });

    // We override the naviguation keyboard to disable it
    Ext.tree.DefaultSelectionModel.override({
        onKeyDown: Ext.emptyFn
    });

    return {
        //public

        /**
         * Called when the page is loaded.
         * Create the tree and adds listeners to the links.
         */
        init: function() {
            //Ext.get('set').on('click', addRules.app.serialize(tree.getRootNode(), 0));
            tree.setRootNode(root);

            root.appendChild(
            //new Ext.tree.TreeNode({ text: '<span id="l'+ addRules.app.getNbrLines() +'" class="line"></span>',
            new Ext.tree.TreeNode({ text: addRules.line.lineContent(),
                                    expanded: true,
                                    id: 'node2' })
            );

            tree.render('tree');

            // the "on load" event doesn't work, so we use expand with a boolean
            // to reproduce the same behavior
            root.on("expand", function() {
                if(!expanded) {
                    //addRules.line.lineContent();
                    addRules.line.addDropDown();
                    Ext.get('parentLine2').on('click', addRules.line.addLine);
                    Ext.get('addValue2').on('click', addRules.line.addInputClick);
                    Ext.get('addAttribute1Tag2').on('click', addRules.line.addInputClick);
                      expanded = true;
                }
            });

            Ext.get('tagSubmited').on('click', addRules.form.submitForm);
            Ext.get('fileTitle').on('blur', addRules.form.checkFileNameInput);

        }, // init

        /**
         * Serialize the tree.
         *
         * @ return Object
         */
        serialize: function(node, nbrChild) {
            var arr = new Object();

            for (var i=0; i<node.childNodes.length; i++) {
                var nodeNbr = node.childNodes[i].id.substr(4, node.childNodes[i].id.length -4);
                arr[i] = new Object();
                arr[i]['id'] = node.childNodes[i].id;
                arr[i]['parent'] = node.childNodes[i].parentNode.id;
                arr[i]['tag'] = Ext.get('tag'+nodeNbr).getValue();

                if(Ext.get('valueTag'+nodeNbr)) {
                    arr[i]['value'] = Ext.get('valueTag'+nodeNbr).getValue();
                }

                arr[i]['attributeNbr'] = Ext.get('attributeNbrLine'+nodeNbr).getValue();

                if(Ext.get('attribute1Tag'+nodeNbr)) {
                    for(var j=1; j<=arr[i]['attributeNbr']; j++) {
                        arr[i]['attribute'+j] = Ext.get('attribute'+j+'Tag'+nodeNbr).getValue();
                        arr[i]['attribute'+j+'Value'] = Ext.get('attribute'+j+'Tag'+nodeNbr+'Value').getValue();
                    }
                }

                if (node.childNodes[i].hasChildNodes() == true) {
                    arr[i]['children'] = addRules.app.serialize(node.childNodes[i], nbrChild+1);
                }
            }
            return arr;
        }, // serialize

        getNbrLines: function() {
            return nbrLines;
        },

        getTree: function() {
            return tree;
        },

        getExpanded: function() {
            return expanded;
        },

        setNbrLines: function(newNbrLines) {
            nbrLines = newNbrLines;
        }
    }; // return
})(); // addRules.app
These 3 issues must be solved, otherwise my application won't be used.