SQL在线查询设计器

HTML我帮您
//http://www.html580.com  
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLTableSprite', {  
        extend: 'Ext.draw.Sprite',  
        alias: ['widget.sqltablesprite'],  
        bConnections: false,  
        startDrag: function(id){  
            var me = this, win, sqlTablePanel, xyParentPos, xyChildPos;  
              
            // get a reference to a sqltable  
            win = Ext.getCmp(id);  
              
            // get the main sqlTablePanel  
            sqlTablePanel = Ext.getCmp('SQLTablePanel');  
              
            // get the main sqlTablePanel position  
            xyParentPos = sqlTablePanel.el.getXY();  
              
            // get the size of the previously added sqltable  
            xyChildPos = win.el.getXY();  
              
            me.prev = me.surface.transformToViewBox(xyChildPos[0] - xyParentPos[0] + 2, xyChildPos[1] - xyParentPos[1] + 2);  
        },  
          
        onDrag: function(relPosMovement){  
            var xy, me = this, attr = this.attr, newX, newY;  
            // move the sprite  
            // calculate new x and y position  
            newX = me.prev[0] + relPosMovement[0];  
            newY = me.prev[1] + relPosMovement[1];  
            // set new x and y position and redraw sprite  
            me.setAttributes({  
                x: newX,  
                y: newY  
              
            }, true);  
        }  
    });   
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLTableModel', {  
        extend: 'Ext.data.Model',  
        fields: [{  
            name: 'id',  
            type: 'string'  
        }, {  
            name: 'tableName',  
            type: 'string'  
        }, {  
            name: 'tableAlias',  
            type: 'string'  
        }]  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLTableStore', {  
        extend: 'Ext.data.Store',  
        autoSync: true,  
        model: 'Ext.ux.window.visualsqlquerybuilder.SQLTableModel',  
        proxy: {  
            type: 'memory'  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLJoin', {  
        extend: 'Ext.data.Model',  
        fields: [{  
            name: 'id',  
            type: 'string'  
        }, {  
            name: 'leftTableId',  
            type: 'string'  
        }, {  
            name: 'rightTableId',  
            type: 'string'  
        }, {  
            name: 'leftTableField',  
            type: 'string'  
        }, {  
            name: 'rightTableField',  
            type: 'string'  
        }, {  
            name: 'joinCondition',  
            type: 'string'  
        }, {  
            name: 'joinType',  
            type: 'string'  
        }],  
        createUUID: function(){  
            // http://www.ietf.org/rfc/rfc4122.txt  
            var s = [];  
            var hexDigits = "0123456789abcdef";  
            for (var i = 0; i < 36; i++) {  
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);  
            }  
            s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010  
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01  
            s[8] = s[13] = s[18] = s[23] = "-";  
              
            var uuid = s.join("");  
            return uuid;  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.JoinStore', {  
        extend: 'Ext.data.Store',  
        autoSync: true,  
        model: 'Ext.ux.window.visualsqlquerybuilder.SQLJoin',  
        proxy: {  
            type: 'memory'  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLFieldsModel', {  
        extend: 'Ext.data.Model',  
        fields: [{  
            name: 'id',  
            type: 'string'  
        }, {  
            name: 'tableName',  
            type: 'string'  
        }, {  
            name: 'tableId',  
            type: 'string'  
        }, {  
            name: 'extCmpId',  
            type: 'string'  
        }, {  
            name: 'tableAlias',  
            type: 'string'  
        }, {  
            name: 'field',  
            type: 'string'  
        }, {  
            name: 'output',  
            type: 'boolean'  
        }, {  
            name: 'expression',  
            type: 'string'  
        }, {  
            name: 'aggregate',  
            type: 'string'  
        }, {  
            name: 'alias',  
            type: 'string'  
        }, {  
            name: 'sortType',  
            type: 'string'  
        }, {  
            name: 'sortOrder',  
            type: 'int'  
        }, {  
            name: 'grouping',  
            type: 'boolean'  
        }, {  
            name: 'criteria',  
            type: 'string'  
        }]  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLFieldsStore', {  
        extend: 'Ext.data.Store',  
        autoSync: true,  
        model: 'Ext.ux.window.visualsqlquerybuilder.SQLFieldsModel',  
        proxy: {  
            type: 'memory'  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLSelect', {  
        config: {  
            tables: '',  
            fields: '',  
            joins: ''  
        },  
        constructor: function(){  
          
            this.tables = Ext.create('Ext.ux.window.visualsqlquerybuilder.SQLTableStore', {  
                storeId: 'SQLTableStore'  
            });  
              
            // handle all updates on sql tables  
            this.tables.on('update', this.handleSQLTableUpdate, this);  
            this.tables.on('add', this.handleSQLTableAdd, this);  
            this.tables.on('remove', this.handleSQLTableRemove, this);  
              
            this.fields = Ext.create('Ext.ux.window.visualsqlquerybuilder.SQLFieldsStore', {  
                storeId: 'SQLFieldsStore'  
            });  
              
            this.fields.on('update', this.handleSQLFieldChanges, this);  
            this.fields.on('remove', this.handleSQLFieldRemove, this);  
              
            this.joins = Ext.create('Ext.ux.window.visualsqlquerybuilder.JoinStore', {  
                storeId: 'JoinStore'  
            });  
              
            // this.joins.on('update', this.handleSQLJoinChanges, this);  
            this.joins.on('add', this.handleSQLJoinChanges, this);  
            this.joins.on('remove', this.handleSQLJoinChanges, this);  
              
            this.callParent(arguments);  
        },  
        handleSQLTableUpdate: function(tableStore, table, operation){  
            if (operation == 'commit') {  
                this.updateFieldTableData(table);  
                this.updateJoinTableData(table);  
                this.updateSQLOutput();  
            }  
        },  
        handleSQLTableAdd: function(tableStore, table, index){  
            this.updateSQLOutput();  
        },  
        handleSQLTableRemove: function(tableStore, table, index){  
            var aJoins = [];  
            // get table joins and remove them  
            aJoins = this.getJoinsByTableId(table.get('id'));  
            // loop over the joins array  
            for (var i = 0, l = aJoins.length; i < l; i++) {  
                // remove join from store  
                this.removeJoinById(aJoins[i].get('id'));  
            }  
            this.updateSQLOutput();  
        },  
        handleSQLJoinChanges: function(joinStore, join){  
            this.updateSQLOutput();  
        },  
        updateFieldTableData: function(table){  
            var tableId, expression, tableAlias, tableName;  
            tableId = table.get('id');  
            tableAlias = table.get('tableAlias');  
            tableName = table.get('tableName');  
            // loop over all fields of the fields store  
            this.fields.each(function(field){  
                // check if current field belongs to sql table  
                if (field.get('tableId') == tableId) {  
                    if (tableAlias != '') {  
                        // we have a table alias  
                        expression = tableAlias + '.' + field.get('field');  
                    }  
                    else {  
                        // no table alias  
                        expression = tableName + '.' + field.get('field');  
                    };  
                    field.beginEdit();  
                    // update the field table alias  
                    field.set('tableAlias', tableAlias);  
                    // update the field expression  
                    field.set('expression', expression);  
                    field.commit(true);  
                    field.endEdit();  
                }  
            });  
            return;  
        },  
        updateJoinTableData: function(table){  
            var joins, tableId;  
            tableId = table.get('id');  
            joins = this.getJoinsByTableId(tableId);  
            for (var i = 0, rightTable, leftTable, joinCondition = '',l = joins.length; i < l; i++) {  
                leftTable = this.getTableById(joins[i].get('leftTableId'));  
                rightTable = this.getTableById(joins[i].get('rightTableId'));  
                  
                if (leftTable.get('tableAlias') != '') {  
                    joinCondition = joinCondition + leftTable.get('tableAlias') + '.' + joins[i].get('leftTableField') + '=';  
                }  
                else {  
                    joinCondition = joinCondition + leftTable.get('tableName') + '.' + joins[i].get('leftTableField') + '=';  
                }  
                  
                if (rightTable.get('tableAlias') != '') {  
                    joinCondition = joinCondition + rightTable.get('tableAlias') + '.' + joins[i].get('rightTableField');  
                }  
                else {  
                    joinCondition = joinCondition + rightTable.get('tableName') + '.' + joins[i].get('rightTableField');  
                }  
                joins[i].beginEdit();  
                joins[i].set('joinCondition', joinCondition);  
                joins[i].commit(true);  
                joins[i].endEdit();  
            }  
        },  
        handleSQLFieldChanges: function(fieldStore, model, operation){  
            if (operation == 'commit') {  
                this.updateSQLOutput();  
            }  
        },  
        handleSQLFieldRemove: function(fieldStore){  
            this.updateSQLOutput();  
        },  
        updateSQLOutput: function(){  
            var sqlOutput, sqlHTML, sqlQutputPanel;  
            sqlOutput = this.toString();  
            sqlHTML = '<pre class="brush: sql">' + sqlOutput + '</pre>';  
            sqlQutputPanel = Ext.getCmp('SQLOutputPanel');  
              
            sqlQutputPanel.update(sqlHTML);  
        },  
        sortTablesByJoins: function(tables, oUsedTables){  
            var aTables = [], aJoins = [], oUsedTables = oUsedTables ||  
            {};  
            // loop over tables  
            for (var i = 0, aCondition = [], aJoin, l = tables.length; i < l; i++) {  
                // check if current table is a new one  
                if (!oUsedTables.hasOwnProperty(tables[i].get('id'))) {  
                    // it is a new one  
                    aTables.push(tables[i]);  
                    // mark table as used  
                    oUsedTables[tables[i].get('id')] = true;  
                    // get any joins for the current table  
                    aJoin = this.getJoinsByTableId(tables[i].get('id'));  
                    // loop over the join tables  
                    for (var j = 0, joinTable, len = aJoin.length; j < len; j++) {  
                        // check if it is a new join  
                        if (!oUsedTables.hasOwnProperty(aJoin[j].get('id'))) {  
                            // mark join as used  
                            oUsedTables[aJoin[j].get('id')] = true;  
                            if (tables[i].get('id') != aJoin[j].get('leftTableId')) {  
                                joinTable = this.getTableById(aJoin[j].get('leftTableId'));  
                                this.changeLeftRightOnJoin(aJoin[j]);  
                            }  
                            else {  
                                joinTable = this.getTableById(aJoin[j].get('rightTableId'));  
                            }  
                            oTemp = this.sortTablesByJoins([joinTable], oUsedTables);  
                            oUsedTables = oTemp.oUsedTables;  
                            aTables = aTables.concat(oTemp.aTables);  
                        }  
                    }  
                }  
            }  
              
            return {  
                aTables: aTables,  
                oUsedTables: oUsedTables  
            };  
        },  
        changeLeftRightOnJoin: function(join){  
            var leftTable, leftTableField, rightTable, rightTableField, joinCondition = '';  
            // prepare new data  
            leftTable = this.getTableById(join.get('rightTableId'));  
            leftTableField = join.get('rightTableField');  
            rightTable = this.getTableById(join.get('leftTableId'));  
            rightTableField = join.get('leftTableField');  
              
            // construct new joinCondition  
            if (leftTable.get('tableAlias') != '') {  
                joinCondition = joinCondition + leftTable.get('tableAlias') + '.' + join.get('rightTableField') + '=';  
            }  
            else {  
                joinCondition = joinCondition + leftTable.get('tableName') + '.' + join.get('rightTableField') + '=';  
            }  
              
            if (rightTable.get('tableAlias') != '') {  
                joinCondition = joinCondition + rightTable.get('tableAlias') + '.' + join.get('leftTableField');  
            }  
            else {  
                joinCondition = joinCondition + rightTable.get('tableName') + '.' + join.get('leftTableField');  
            }  
              
            // start transaction  
            join.beginEdit();  
            // change left and right join table data  
            join.set('leftTableId', leftTable.get('id'));  
            join.set('leftTableField', leftTableField);  
            join.set('rightTableId', rightTable.get('id'));  
            join.set('rightTableField', rightTableField);  
            join.set('joinCondition', joinCondition);  
            // silent commit without firing store events  
            // this prevents endless loop  
            join.commit(true);  
            join.endEdit();  
            // end transaction  
            return;  
        },  
        toString: function(){  
            var sqlOutput = 'SELECT ', aJoins = [], aOutputFields = [], oJoinTables = {}, aTables = [], aJoinTables = [], aCriteriaFields = [], aGroupFields = [], aOrderFields = [], selectFieldsSQL = '', fromSQL = '', aFromSQL = [], criteriaSQL = '', orderBySQL = '', groupBySQL = '', fieldSeperator = ', ', joinSQL = '', bFirst = true, bPartOfJoin = false;  
            this.fields.each(function(field){  
                // should the field be a part of the output  
                if (field.get('output')) {  
                    aOutputFields.push(field);  
                }  
                // any criteria  
                if (field.get('criteria') != '') {  
                    aCriteriaFields.push(field);  
                }  
                // check for grouping  
                if (field.get('grouping')) {  
                    aGroupFields.push(field);  
                }  
                // check for sorting  
                if (field.get('sortType') != '') {  
                    aOrderFields.push(field);  
                }  
            });  
              
            // tables  
            // sorting of tables  
            this.tables.each(function(table){  
                aTables.push(table);  
            });  
              
            aTables = this.sortTablesByJoins(aTables).aTables;  
              
              
            this.joins.each(function(join){  
                aJoins.push(join);  
            });  
              
            //create fromSQL  
            for (var k = 0, aJoin = [], oJoinTables = {}, joinCondition = '', joinType, leftTable, rightTable, l = aTables.length; k < l; k++) {  
                if (k == aTables.length - 1) {  
                    fieldSeperator = '';  
                }  
                else {  
                    fieldSeperator = ', ';  
                };  
                  
                // is the current table the first one  
                if (bFirst) {  
                    // yes it is the first  
                      
                    // table id merken  
                    oJoinTables[aTables[k].get('id')] = true;  
                      
                    bFirst = false;  
                      
                    // check if current table is not the last one in the loop   
                    if ((k + 1) < aTables.length) {  
                        // get joins where joins leftTableID is a property of oJoinTables and joins rightTableID equal to aTables[i+1].get('id')  
                        for (var h = 0, len = aJoins.length; h < len; h++) {  
                            if (oJoinTables.hasOwnProperty(aJoins[h].get('leftTableId')) && aJoins[h].get('rightTableId') == aTables[k + 1].get('id')) {  
                                aJoin.push(aJoins[h]);  
                            }  
                            if (oJoinTables.hasOwnProperty(aJoins[h].get('rightTableId')) && aJoins[h].get('leftTableId') == aTables[k + 1].get('id')) {  
                                this.changeLeftRightOnJoin(aJoins[h]);  
                                aJoin.push(aJoins[h]);  
                            }  
                        }  
                          
                        // check if we have a join  
                        if (aJoin.length > 0) {  
                            // yes we have a join between aTables[k] and aTables[k+1] with at least one join condition  
                              
                            leftTable = aTables[k];  
                            rightTable = aTables[k + 1];  
                              
                            // table id merken  
                            oJoinTables[rightTable.get('id')] = true;  
                              
                            for (var j = 0, fieldSeperator = '', ln = aJoin.length; j < ln; j++) {  
                                if (j == aJoin.length - 1) {  
                                    fieldSeperator = '';  
                                }  
                                else {  
                                    fieldSeperator = '\nAND ';  
                                };  
                                joinType = aJoin[j].get('joinType');  
                                joinCondition = joinCondition + aJoin[j].get('joinCondition') + fieldSeperator;  
                            }  
                              
                            // reset the join array   
                            aJoin = [];  
                              
                            if (joinSQL != '') {  
                                joinSQL = joinSQL + ',\n';  
                            }  
                              
                            if (leftTable.get('tableAlias') != '') {  
                                // we have an leftTable alias  
                                joinSQL = joinSQL + leftTable.get('tableName') + ' ' + leftTable.get('tableAlias') + ' ' + joinType + ' JOIN ';  
                            }  
                            else {  
                                //no alias  
                                joinSQL = joinSQL + leftTable.get('tableName') + ' ' + joinType + ' JOIN ';  
                            }  
                              
                            if (rightTable.get('tableAlias') != '') {  
                                // we have an rightTable alias  
                                joinSQL = joinSQL + rightTable.get('tableName') + ' ' + rightTable.get('tableAlias') + ' ON ' + joinCondition;  
                            }  
                            else {  
                                //no alias  
                                joinSQL = joinSQL + rightTable.get('tableName') + ' ON ' + joinCondition;  
                            }  
                              
                            // clear joinCondition  
                            joinCondition = '';  
                              
                        }  
                        else {  
                            // no join between aTables[i+1] and the one before  
                            bFirst = true;  
                            oJoinTables = {};  
                            // check for tableAlias  
                            if (aTables[k].get('tableAlias') != '') {  
                                fromSQL = aTables[k].get('tableName') + ' ' + aTables[k].get('tableAlias');  
                            }  
                            else {  
                                fromSQL = aTables[k].get('tableName');  
                            }  
                            aFromSQL.push(fromSQL);  
                        }  
                    }  
                    else {  
                        // its the last and only one in the loop  
                        // check for tableAlias  
                        if (aTables[k].get('tableAlias') != '') {  
                            fromSQL = aTables[k].get('tableName') + ' ' + aTables[k].get('tableAlias');  
                        }  
                        else {  
                            fromSQL = aTables[k].get('tableName');  
                        }  
                        aFromSQL.push(fromSQL);  
                    }  
                }  
                else {  
                    // no, it is not the first table  
                      
                    bFirst = true;  
                      
                    // check if current table is not the last one in the loop   
                    if ((k + 1) < aTables.length) {  
                        // get joins where joins leftTableID is a property of oJoinTables and joins rightTableID equal to aTables[i+1].get('id')  
                        for (var h = 0, len = aJoins.length; h < len; h++) {  
                            if (oJoinTables.hasOwnProperty(aJoins[h].get('leftTableId')) && aJoins[h].get('rightTableId') == aTables[k + 1].get('id')) {  
                                aJoin.push(aJoins[h]);  
                            }  
                            if (oJoinTables.hasOwnProperty(aJoins[h].get('rightTableId')) && aJoins[h].get('leftTableId') == aTables[k + 1].get('id')) {  
                                this.changeLeftRightOnJoin(aJoins[h]);  
                                aJoin.push(aJoins[h]);  
                            }  
                        }  
                          
                        // check if we have a join  
                        if (aJoin.length > 0) {  
                            // yes we have a join between aTables[k] and aTables[k+1] with at least one join condition  
                              
                            rightTable = aTables[k + 1];  
                              
                            // table id merken  
                            oJoinTables[rightTable.get('id')] = true;  
                              
                            for (var j = 0, fieldSeperator = '', ln = aJoin.length; j < ln; j++) {  
                                if (j == aJoin.length - 1) {  
                                    fieldSeperator = '';  
                                }  
                                else {  
                                    fieldSeperator = '\nAND ';  
                                };  
                                joinType = aJoin[j].get('joinType');  
                                joinCondition = joinCondition + aJoin[j].get('joinCondition') + fieldSeperator;  
                            }  
                              
                            // reset the join array   
                            aJoin = [];  
                              
                            bFirst = false;  
                              
                            if (rightTable.get('tableAlias') != '') {  
                                // we have an rightTable alias  
                                joinSQL = joinSQL + '\n' + joinType + ' JOIN ' + rightTable.get('tableName') + ' ' + rightTable.get('tableAlias') + ' ON ' + joinCondition;  
                            }  
                            else {  
                                //no alias  
                                joinSQL = joinSQL + '\n' + joinType + ' JOIN ' + rightTable.get('tableName') + ' ON ' + joinCondition;  
                            }  
                              
                            // clear joinCondition  
                            joinCondition = '';  
                        }  
                        else {  
                            bFirst = true;  
                            oJoinTables = {};  
                        }  
                    }  
                    else {  
                        // its the last and only one  
                        // check for tableAlias  
                        oJoinTables = {};  
                    }  
                }  
            }  
              
            fromSQL = aFromSQL.join(', ');  
              
            if (joinSQL != '' && fromSQL != '') {  
                joinSQL = joinSQL + ', ';  
            }  
              
            fromSQL = '\nFROM ' + joinSQL + fromSQL;  
              
            // output fields  
            for (var i = 0, l = aOutputFields.length; i < l; i++) {  
                // check if it is the last array member  
                if (i == aOutputFields.length - 1) {  
                    fieldSeperator = '';  
                }  
                else {  
                    fieldSeperator = ', ';  
                };  
                // yes, output  
                // check alias  
                if (aOutputFields[i].get('alias') != '') {  
                    // yes, we have an field alias  
                    selectFieldsSQL = selectFieldsSQL + aOutputFields[i].get('expression') + ' AS ' + aOutputFields[i].get('alias') + fieldSeperator;  
                }  
                else {  
                    // no field alias  
                    selectFieldsSQL = selectFieldsSQL + aOutputFields[i].get('expression') + fieldSeperator;  
                }  
            }  
              
            // criteria  
            for (var i = 0, l = aCriteriaFields.length; i < l; i++) {  
                if (i == 0) {  
                    criteriaSQL = criteriaSQL + '\nWHERE ';  
                }  
                else {  
                    criteriaSQL = criteriaSQL + 'AND ';  
                }  
                if (i == aCriteriaFields.length - 1) {  
                    fieldSeperator = '';  
                }  
                else {  
                    fieldSeperator = '\n';  
                }  
                criteriaSQL = criteriaSQL + aCriteriaFields[i].get('expression') + ' ' + aCriteriaFields[i].get('criteria') + fieldSeperator;  
            }  
              
            // group by  
            for (var i = 0, l = aGroupFields.length; i < l; i++) {  
                // check if it is the last array member  
                if (i == aGroupFields.length - 1) {  
                    fieldSeperator = '';  
                }  
                else {  
                    fieldSeperator = ', ';  
                }  
                if (i == 0) {  
                    groupBySQL = '\nGROUP BY ';  
                }  
                groupBySQL = groupBySQL + aGroupFields[i].get('expression') + fieldSeperator;  
            }  
              
            // order by  
            for (var i = 0, l = aOrderFields.length; i < l; i++) {  
                // check if it is the last array member  
                if (i == aOrderFields.length - 1) {  
                    fieldSeperator = '';  
                }  
                else {  
                    fieldSeperator = ', ';  
                }  
            }  
              
            return sqlOutput + selectFieldsSQL + fromSQL + criteriaSQL + groupBySQL + orderBySQL;  
        },  
        getJoinsByTableId: function(tableId){  
            var aReturn = [];  
            this.joins.each(function(join){  
                if (join.get('leftTableId') == tableId || join.get('rightTableId') == tableId) {  
                    aReturn.push(join);  
                }  
            });  
            return aReturn;  
        },  
        removeTableById: function(tableID){  
            var table;  
            table = this.tables.getById(tableID);  
            this.tables.remove(table);  
        },  
        getTableById: function(tableID){  
            return this.tables.getById(tableID);  
        },  
        removeFieldById: function(id){  
            var field;  
            field = this.fields.getById(id);  
            this.fields.remove(field);  
        },  
        removeFieldsByTableId: function(tableId){  
            var aRecords = [];  
            this.fields.each(function(model){  
                if (model.get('tableId') == tableId) {  
                    aRecords.push(model);  
                }  
            });  
            this.fields.remove(aRecords);  
        },  
        addTable: function(table){  
            this.tables.add(table);  
        },  
        addFieldRecord: function(record, bOutput){  
            var tableAlias, model, expression;  
            // get the tableAlias  
            tableAlias = this.getTableById(record.get('tableId')).get('tableAlias');  
            // build the expression  
            // check if the tableAlias is not an empty string  
            if (tableAlias != '') {  
                // alias is not an empty string  
                expression = tableAlias + '.' + record.get('field');  
            }  
            else {  
                // alias is an empty string  
                expression = record.get('tableName') + '.' + record.get('field');  
            };  
            // get a new field instance  
            model = this.getNewField();  
            // set the expression  
            model.set('expression', expression);  
            // set output to false per default  
            model.set('output', bOutput);  
            // set an id, so it is possible to remove rows if the associated table is removed  
            model.set('id', record.get('id'));  
            // set the field  
            model.set('field', record.get('field'));  
            // copy tableId to the new model instance  
            model.set('tableId', record.get('tableId'));  
            // copy cmp id of origin sqltable to the new model instance  
            model.set('extCmpId', record.get('extCmpId'));  
            this.addField(model);  
        },  
        addField: function(field){  
            this.fields.add(field);  
        },  
        getNewField: function(){  
            return Ext.create('Ext.ux.window.visualsqlquerybuilder.SQLFieldsModel');  
        },  
        removeJoinById: function(joinID){  
            var join;  
            join = this.joins.getById(joinID);  
            this.joins.remove(join);  
        },  
        addJoin: function(join){  
            this.joins.add(join);  
        },  
        arrayRemove: function(array, filterProperty, filterValue){  
            var aReturn;  
            aReturn = Ext.Array.filter(array, function(item){  
                var bRemove = true;  
                if (item[filterProperty] == filtervalue) {  
                    bRemove = false;  
                }  
                return bRemove;  
            });  
            return aReturn  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLTablePanel', {  
        extend: 'Ext.panel.Panel',  
        alias: ['widget.sqltablepanel'],  
        id: 'SQLTablePanel',  
        items: [{  
            xtype: 'draw',  
            listeners: {  
                afterrender: function(){  
                    this.initDropTarget();  
                }  
            },  
            initDropTarget: function(){  
                // init draw component inside qbwindow as a DropTarget  
                this.dropTarget = Ext.create('Ext.dd.DropTarget', this.el, {  
                    ddGroup: 'sqlDDGroup',  
                    notifyDrop: function(source, event, data){  
                        var sqlTablePanel;  
                        // add a sqltable to the sqlTablePanel component  
                        sqlTablePanel = Ext.getCmp('SQLTablePanel');  
                        sqlTablePanel.add({  
                            xtype: 'sqltable',  
                            constrain: true,  
                            title: data.records[0].get('text')  
                        }).show();  
                        return true;  
                    }  
                });  
            }  
        }]  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLOutputPanel', {  
        extend: 'Ext.panel.Panel',  
        alias: ['widget.sqloutputpanel'],  
        id: 'SQLOutputPanel',  
        listeners: {  
            afterlayout: function(){  
                SyntaxHighlighter.highlight();  
            }  
        },  
        initComponent: function(){  
            this.callParent(arguments);  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLFieldsGrid', {  
        requires: ['Ext.ux.CheckColumn'],  
        extend: 'Ext.grid.Panel',  
        alias: ['widget.sqlfieldsgrid'],  
        id: 'SQLFieldsGrid',  
        store: 'SQLFieldsStore',  
        columnLines: true,  
        plugins: [Ext.create('Ext.grid.plugin.CellEditing', {  
            clicksToEdit: 1  
        })],  
        viewConfig: {  
            listeners: {  
                render: function(view){  
                    this.dd = {};  
                    this.dd.dropZone = new Ext.grid.ViewDropZone({  
                        view: view,  
                        ddGroup: 'SQLTableGridDDGroup',  
                        handleNodeDrop: function(data, record, position){  
                            // Was soll nach dem Drop passieren?  
                        }  
                    });  
                },  
                drop: function(node, data, dropRec, dropPosition){  
                    // add new rows to the SQLFieldsGrid after a drop  
                    for (var i = 0, l = data.records.length; i < l; i++) {  
                        ux.vqbuilder.sqlSelect.addFieldRecord(data.records[i], false);  
                    }  
                }  
            }  
        },  
        columns: [{  
            xtype: 'actioncolumn',  
            menuDisabled: true,  
            text: 'Action',  
            width: 60,  
            moveGridRow: function(grid, record, index, direction){  
                var store = grid.getStore();  
                if (direction < 0) {  
                    index--;  
                    if (index < 0) {  
                        return;  
                    }  
                }  
                else {  
                    index++;  
                    if (index >= grid.getStore().getCount()) {  
                        return;  
                    }  
                }  
                // prepare manual syncing  
                store.suspendAutoSync();  
                // disable firing store events  
                store.suspendEvents();  
                // remove record and insert record at new index  
                store.remove(record);  
                store.insert(index, record);  
                // enable firing store events  
                store.resumeEvents();  
                store.resumeAutoSync();  
                // manual sync the store  
                store.sync();  
            },  
            items: [{  
                icon: 'resources/images/up_arrow.gif',  
                tooltip: 'Move Column Up',  
                getClass: function(value, metadata, record){  
                    var store, index;  
                    store = record.store;  
                    index = store.indexOf(record);  
                    if (index == 0) {  
                        return 'x-action-icon-disabled';  
                    }  
                    else {  
                        return 'x-grid-center-icon';  
                    }  
                },  
                handler: function(grid, rowIndex, colIndex){  
                    var rec = grid.getStore().getAt(rowIndex);  
                    this.moveGridRow(grid, rec, rowIndex, -1);  
                }  
            }, {  
                icon: 'resources/images/down_arrow.gif',  
                getClass: function(value, metadata, record){  
                    var store, index;  
                    store = record.store;  
                    index = store.indexOf(record);  
                    if ((index + 1) == store.getCount()) {  
                        return 'x-action-icon-disabled';  
                    }  
                    else {  
                        return 'x-grid-center-icon';  
                    }  
                },  
                tooltip: 'Move Column Down',  
                handler: function(grid, rowIndex, colIndex){  
                    var rec = grid.getStore().getAt(rowIndex);  
                    this.moveGridRow(grid, rec, rowIndex, 1);  
                }  
            }, {  
                icon: 'resources/images/remove.gif',  
                iconCls: 'x-grid-center-icon',  
                tooltip: 'Delete Column',  
                handler: function(grid, rowIndex, colIndex){  
                    var rec = grid.getStore().getAt(rowIndex), store, tableId, tableGrid, selectionModel, bDel = true;  
                    // rec contains column grid model, the one to remove  
                    // get tableId of original sqltable  
                    tableId = rec.get('extCmpId');  
                    // get the sql tables grid and its selection  
                    tableGrid = Ext.getCmp(tableId).down('gridpanel');  
                    selectionModel = tableGrid.getSelectionModel();  
                    Ext.Array.each(selectionModel.getSelection(), function(selection){  
                        // deselect the selection wich corresponds to the column   
                        // we want to remove from the column grid  
                        if (rec.get('id') == selection.get('id')) {  
                            // deselect current selection  
                            // deselection will lead to removal, look for method deselect at the SQLTableGrid  
                            selectionModel.deselect(selection);  
                            bDel = false;  
                        }  
                    });  
                    if (bDel) {  
                        store = grid.getStore();  
                        store.remove(rec);  
                    }  
                }  
            }]  
        }, {  
            xtype: 'checkcolumn',  
            sortable: false,  
            text: 'Output',  
            flex: 0.075,  
            menuDisabled: true,  
            dataIndex: 'output',  
            align: 'center'  
        }, {  
            xtype: 'gridcolumn',  
            text: 'Expression',  
            sortable: false,  
            menuDisabled: true,  
            flex: 0.225,  
            dataIndex: 'expression',  
            editor: 'textfield'  
        }, {  
            xtype: 'gridcolumn',  
            text: 'Aggregate',  
            flex: 0.125,  
            sortable: false,  
            menuDisabled: true,  
            dataIndex: 'aggregate',  
            editor: 'textfield'  
        }, {  
            xtype: 'gridcolumn',  
            text: 'Alias',  
            flex: 0.125,  
            sortable: false,  
            menuDisabled: true,  
            dataIndex: 'alias',  
            editor: 'textfield'  
        }, {  
            xtype: 'gridcolumn',  
            text: 'Sort Type',  
            flex: 0.125,  
            sortable: false,  
            menuDisabled: true,  
            dataIndex: 'sorttype'  
        }, {  
            xtype: 'gridcolumn',  
            text: 'Sort Order',  
            flex: 0.125,  
            sortable: false,  
            menuDisabled: true,  
            dataIndex: 'sortorder'  
        }, {  
            xtype: 'checkcolumn',  
            text: 'Grouping',  
            flex: 0.075,  
            sortable: false,  
            menuDisabled: true,  
            dataIndex: 'grouping',  
            align: 'center'  
        }, {  
            xtype: 'gridcolumn',  
            text: 'Criteria',  
            flex: 0.125,  
            sortable: false,  
            menuDisabled: true,  
            dataIndex: 'criteria',  
            editor: 'textfield'  
        }],  
        initComponent: function(){  
            this.callParent(arguments);  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLTableTree', {  
        extend: 'Ext.tree.Panel',  
        alias: ['widget.sqltabletree'],  
        id: 'SQLTableTree',  
        listeners: {  
            afterrender: function(){  
                this.initTreeDragZone();  
            },  
            itemdblclick: function(view, record, el, index, event){  
                var sqlTablePanel;  
                // add a sqltable to the sqlTablePanel component  
                sqlTablePanel = Ext.getCmp('SQLTablePanel');  
                sqlTablePanel.add({  
                    xtype: 'sqltable',  
                    constrain: true,  
                    title: record.get('text')  
                }).show();  
                  
            }  
        },  
        initTreeDragZone: function(){  
            // init tree view as a ViewDragZone  
            this.view.dragZone = new Ext.tree.ViewDragZone({  
                view: this.view,  
                ddGroup: 'sqlDDGroup',  
                dragText: '{0} ausgew盲hlte Tabelle{1}',  
                repairHighlightColor: 'c3daf9',  
                repairHighlight: Ext.enableFx  
            });  
        },  
        initComponent: function(){  
          
            this.store = Ext.create('Ext.data.TreeStore', {  
                root: {  
                    text: 'Tables',  
                    expanded: true  
                },  
                proxy: {  
                    type: 'ajax',  
                    url: 'data/database.cfc?method=getTables'  
                }  
            });  
              
            this.callParent(arguments);  
        }  
    });  
      
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLTableGrid', {  
        extend: 'Ext.grid.Panel',  
        alias: ['widget.sqltablegrid'],  
        border: false,  
        hideHeaders: true,  
        viewConfig: {  
            listeners: {  
                bodyscroll: function(){  
                    var scrollOffset, sqlTable;  
                    // the bodyscroll event of the view was fired  
                    // get scroll information  
                    scrollOffset = this.el.getScroll();  
                    // get the parent sqltable  
                    sqlTable = this.up('sqltable');  
                    // change shadowSprites scrollTop property  
                    sqlTable.shadowSprite.scrollTop = scrollOffset.top;  
                    // redraw all connections to reflect scroll action  
                    for (var i = ux.vqbuilder.connections.length; i--;) {  
                        sqlTable.connection(ux.vqbuilder.connections[i]);  
                    }  
                },  
                render: function(view){  
                    this.dd = {};  
                    // init the view as a DragZone  
                    this.dd.dragZone = new Ext.view.DragZone({  
                        view: view,  
                        ddGroup: 'SQLTableGridDDGroup',  
                        dragText: '{0} selected table column{1}',  
                        onInitDrag: function(x, y){  
                            var me = this, data = me.dragData, view = data.view, selectionModel = view.getSelectionModel(), record = view.getRecord(data.item), e = data.event;  
                            data.records = [record];  
                            me.ddel.update(me.getDragText());  
                            me.proxy.update(me.ddel.dom);  
                            me.onStartDrag(x, y);  
                            return true;  
                        }  
                    });  
                    // init the view as a DropZone  
                    this.dd.dropZone = new Ext.grid.ViewDropZone({  
                        view: view,  
                        ddGroup: 'SQLTableGridDDGroup',  
                        handleNodeDrop: function(data, record, position){  
                            // Was soll nach dem Drop passieren?  
                        },  
                        onNodeOver: function(node, dragZone, e, data){  
                            var me = this, view = me.view, pos = me.getPosition(e, node), overRecord = view.getRecord(node), draggingRecords = data.records;  
                              
                            if (!Ext.Array.contains(data.records, me.view.getRecord(node))) {  
                                if (!Ext.Array.contains(draggingRecords, overRecord) && data.records[0].get('field') != '*') {  
                                    me.valid = true;  
                                    // valid drop target  
                                    // todo show drop invitation  
                                }  
                                else {  
                                    // invalid drop target  
                                    me.valid = false;  
                                }  
                            }  
                            return me.valid ? me.dropAllowed : me.dropNotAllowed;  
                        },  
                        onContainerOver: function(dd, e, data){  
                            var me = this;  
                            // invalid drop target  
                            me.valid = false;  
                            return me.dropNotAllowed;  
                        }  
                    });  
                },  
                drop: function(node, data, dropRec, dropPosition){  
                    var sqlTable1, sqlTable2, showJoinCM, connection, aBBPos, join, joinCondition = '', dropTable, targetTable;  
                      
                    showJoinCM = function(event, el){  
                        var cm;  
                        // stop the browsers event bubbling  
                        event.stopEvent();  
                        // create context menu  
                        cm = Ext.create('Ext.menu.Menu', {  
                            items: [{  
                                text: 'Edit Join',  
                                icon: 'resources/images/document_edit16x16.gif',  
                                handler: Ext.Function.bind(function(){  
                                  
                                }, this)  
                            }, {  
                                text: 'Remove Join',  
                                icon: 'resources/images/remove.gif',  
                                handler: Ext.Function.bind(function(){  
                                    // remove any connection lines from surface and from array ux.vqbuilder.connections  
                                    ux.vqbuilder.connections = Ext.Array.filter(ux.vqbuilder.connections, function(connection){  
                                        var bRemove = true;  
                                        if (this.uuid == connection.uuid) {  
                                            this.line.remove();  
                                            this.bgLine.remove();  
                                            this.miniLine1.remove();  
                                            this.miniLine2.remove();  
                                            bRemove = false;  
                                        }  
                                        return bRemove;  
                                    }, this);  
                                    ux.vqbuilder.sqlSelect.removeJoinById(this.uuid);  
                                }, this)  
                            }, {  
                                text: 'Close Menu',  
                                icon: 'resources/images/cross.gif',  
                                handler: Ext.emptyFn  
                            }]  
                        });  
                        // show the contextmenu next to current mouse position  
                        cm.showAt(event.getXY());  
                    };  
                      
                    if (node.boundView) {  
                        sqlTable1 = data.view.up('window');  
                        sqlTable1.shadowSprite.bConnections = true;  
                          
                        sqlTable2 = Ext.getCmp(node.boundView).up('window');  
                        sqlTable2.shadowSprite.bConnections = true;  
                          
                        dropTable = ux.vqbuilder.sqlSelect.getTableById(sqlTable1.tableId);  
                        targetTable = ux.vqbuilder.sqlSelect.getTableById(sqlTable2.tableId);  
                          
                        aBBPos = [data.item.viewIndex, node.viewIndex];  
                          
                        connection = sqlTable2.connection(sqlTable1.shadowSprite, sqlTable2.shadowSprite, "#000", aBBPos);  
                          
                        sqlTable1.connectionUUIDs.push(connection.uuid);  
                        sqlTable2.connectionUUIDs.push(connection.uuid);  
                          
                        ux.vqbuilder.connections.push(connection);  
                          
                        // bgLine is white(invisble) and its stroke-width is 10  
                        // so it is easier to capture the dblclick event  
                        connection.bgLine.el.on('contextmenu', showJoinCM, connection);  
                          
                        // line is black and its stroke-width is 1  
                        connection.line.el.on('contextmenu', showJoinCM, connection);  
                          
                        // create an instance of the join model  
                        join = Ext.create('Ext.ux.window.visualsqlquerybuilder.SQLJoin');  
                        // set join id  
                        join.set('id', connection.uuid);  
                        // sqlTable1 is the left table  
                        join.set('leftTableId', sqlTable1.tableId);  
                        // data.records[0] represents the model of the dragged node  
                        join.set('leftTableField', data.records[0].get('field'));  
                        // sqlTable1 is the left table  
                        join.set('rightTableId', sqlTable2.tableId);  
                        // node.viewIndex is the index of the target node  
                        join.set('rightTableField', sqlTable2.down('grid').store.getAt(node.viewIndex).get('field'));  
                        // set the defaul join type to INNER  
                        join.set('joinType', 'INNER');  
                          
                        if (dropTable.get('tableAlias') != '') {  
                            joinCondition = joinCondition + dropTable.get('tableAlias') + '.' + join.get('leftTableField') + '=';  
                        }  
                        else {  
                            joinCondition = joinCondition + dropTable.get('tableName') + '.' + join.get('leftTableField') + '=';  
                        }  
                          
                        if (targetTable.get('tableAlias') != '') {  
                            joinCondition = joinCondition + targetTable.get('tableAlias') + '.' + join.get('rightTableField');  
                        }  
                        else {  
                            joinCondition = joinCondition + targetTable.get('tableName') + '.' + join.get('rightTableField');  
                        }  
                          
                        join.set('joinCondition', joinCondition);  
                        ux.vqbuilder.sqlSelect.addJoin(join);  
                    }  
                      
                }  
            }  
        },  
        initComponent: function(){  
          
            this.columns = [{  
                xtype: 'gridcolumn',  
                width: 16,  
                dataIndex: 'key',  
                renderer: function(val, meta, model){  
                    if (val == 'PRI') {  
                        meta.style = 'background-image:url(resources/images/key.gif) !important;background-position:2px 3px;background-repeat:no-repeat;';  
                    }  
                    return ' ';  
                }  
            }, {  
                xtype: 'gridcolumn',  
                flex: 1,  
                dataIndex: 'field',  
                renderer: function(val, meta, model){  
                    if (model.get('key') == 'PRI') {  
                        return '<span style="font-weight: bold;">' + val + '</span>  <span style="color:#aaa;">' + model.get('type') + '</span>';  
                    }  
                    return val + '  <span style="color:#999;">' + model.get('type') + '</span>';  
                      
                }  
            }];  
              
            this.selModel = Ext.create('Ext.selection.CheckboxModel', {  
                mode: 'SIMPLE',  
                checkOnly: true,  
                listeners: {  
                    select: function(selModel, data){  
                        // add new rows to the SQLFieldsGrid after a selection change  
                        ux.vqbuilder.sqlSelect.addFieldRecord(data, true);  
                    },  
                    deselect: function(selModel, data){  
                        var store, model;  
                        // remove row from SQLFieldsGrid after deselection  
                        ux.vqbuilder.sqlSelect.removeFieldById(data.get('id'));  
                    }  
                }  
            });  
              
            this.callParent(arguments);  
        }  
    });  
      
    Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLTable', {  
        extend: 'Ext.window.Window',  
        minWidth: 120,  
        alias: ['widget.sqltable'],  
        cascadeOnFirstShow: 20,  
        height: 180,  
        width: 140,  
        shadowSprite: {},  
        layout: {  
            type: 'fit'  
        },  
        closable: true,  
        listeners: {  
            show: function(){  
                this.initSQLTable();  
            },  
            beforeclose: function(){  
                this.closeSQLTable();  
            }  
        },  
        closeSQLTable: function(){  
            // remove fields / columns from sqlFieldsStore  
            ux.vqbuilder.sqlSelect.removeFieldsByTableId(this.tableId);  
              
            // remove table from sqlTables store inside ux.vqbuilder.sqlSelect  
            ux.vqbuilder.sqlSelect.removeTableById(this.tableId);  
              
            // unregister mousedown event  
            this.getHeader().el.un('mousedown', this.regStartDrag, this);  
            // unregister mousemove event  
            Ext.EventManager.un(document, 'mousemove', this.moveWindow, this);  
            // remove sprite from surface  
            Ext.getCmp('SQLTablePanel').down('draw').surface.remove(this.shadowSprite, false);  
            // remove any connection lines from surface and from array ux.vqbuilder.connections  
            ux.vqbuilder.connections = Ext.Array.filter(ux.vqbuilder.connections, function(connection){  
                var bRemove = true;  
                for (var j = 0, l = this.connectionUUIDs.length; j < l; j++) {  
                    if (connection.uuid == this.connectionUUIDs[j]) {  
                        connection.line.remove();  
                        connection.bgLine.remove();  
                        connection.miniLine1.remove();  
                        connection.miniLine2.remove();  
                        bRemove = false;  
                    }  
                }  
                return bRemove;  
            }, this);  
              
        },  
        initSQLTable: function(){  
            var sqlTablePanel, xyParentPos, xyChildPos, childSize, sprite;  
              
            // get the main sqlTablePanel  
            sqlTablePanel = Ext.getCmp('SQLTablePanel');  
              
            // get the main sqlTablePanel position  
            xyParentPos = sqlTablePanel.el.getXY();  
              
            // get position of the previously added sqltable  
            xyChildPos = this.el.getXY();  
              
            // get the size of the previously added sqltable  
            childSize = this.el.getSize();  
              
            // create a sprite of type rectangle and set its position and size   
            // to position and size of the the sqltable   
            sprite = Ext.create('Ext.ux.window.visualsqlquerybuilder.SQLTableSprite', {  
                type: 'rect',  
                stroke: '#fff',  
                height: childSize.height - 4,  
                width: childSize.width - 4,  
                x: xyChildPos[0] - xyParentPos[0] + 2,  
                y: xyChildPos[1] - xyParentPos[1] + 2,  
                scrollTop: 0  
            });  
              
            // add the sprite to the surface of the sqlTablePanel  
            this.shadowSprite = sqlTablePanel.down('draw').surface.add(sprite).show(true);  
              
            // handle resizeing of sqltabel  
            this.resizer.on('resize', function(resizer, width, height, event){  
                this.shadowSprite.setAttributes({  
                    width: width - 6,  
                    height: height - 6  
                }, true);  
                // also move the associated connections   
                for (var i = ux.vqbuilder.connections.length; i--;) {  
                    this.connection(ux.vqbuilder.connections[i]);  
                }  
            }, this);  
              
            // register a function for the mousedown event on the previously added sqltable and bind to this scope  
            this.getHeader().el.on('mousedown', this.regStartDrag, this);  
              
            this.getHeader().el.on('contextmenu', this.showSQLTableCM, this);  
              
            this.getHeader().el.on('dblclick', this.showTableAliasEditForm, this);  
              
            this.getHeader().origValue = '';  
              
            // register method this.moveWindow for the mousemove event on the document and bind to this scope  
            Ext.EventManager.on(document, 'mousemove', this.moveWindow, this);  
              
            // register a function for the mouseup event on the document and add the this scope  
            Ext.EventManager.on(document, 'mouseup', function(){  
                // save the mousedown state  
                this.bMouseDown = false;  
            }, this);  
              
              
        },  
        showSQLTableCM: function(event, el){  
            var cm;  
            // stop the browsers event bubbling  
            event.stopEvent();  
            // create context menu  
            cm = Ext.create('Ext.menu.Menu', {  
                items: [{  
                    text: 'Add/Edit Alias',  
                    icon: 'resources/images/document_edit16x16.gif',  
                    handler: Ext.Function.bind(function(){  
                        this.showTableAliasEditForm();  
                    }, this)  
                }, {  
                    text: 'Remove Table',  
                    icon: 'resources/images/delete.gif',  
                    handler: Ext.Function.bind(function(){  
                        // remove the sqltable  
                        this.close();  
                    }, this)  
                }, {  
                    text: 'Close Menu',  
                    icon: 'resources/images/cross.gif',  
                    handler: Ext.emptyFn  
                }]  
            });  
            // show the contextmenu next to current mouse position  
            cm.showAt(event.getXY());  
        },  
        showTableAliasEditForm: function(event, el){  
            var table, header, title, titleId;  
            table = ux.vqbuilder.sqlSelect.getTableById(this.tableId);  
            header = this.getHeader();  
            titleId = '#' + header.getId() + '_hd';  
            title = this.down(titleId);  
            header.remove(title);  
            header.insert(0, [{  
                xtype: 'textfield',  
                flex: 0.95,  
                parentCmp: header,  
                parentTableModel: table,  
                initComponent: function(){  
                  
                    this.setValue(this.parentTableModel.get('tableAlias'));  
                      
                    this.on('render', function(field, event){  
                        // set focus to the textfield Benutzerkennung  
                        field.focus(true, 200);  
                    }, this);  
                      
                    this.on('specialkey', function(field, event){  
                        if (event.getKey() == event.ENTER) {  
                            if (field.getValue() != this.parentCmp.origValue) {  
                                this.parentTableModel.set('tableAlias', field.getValue());  
                                this.parentCmp.origValue = field.getValue();  
                            }  
                            this.removeTextField();  
                            this.addTitle();  
                        }  
                    }, this);  
                      
                    this.on('blur', function(field, event){  
                        if (field.getValue() != this.parentCmp.origValue) {  
                            this.parentTableModel.set('tableAlias', field.getValue());  
                            this.parentCmp.origValue = field.getValue();  
                        }  
                        this.removeTextField();  
                        this.addTitle();  
                    }, this);  
                      
                    this.callParent(arguments);  
                },  
                removeTextField: function(){  
                    var next;  
                    next = this.next();  
                    this.parentCmp.remove(next);  
                    this.parentCmp.remove(this);  
                },  
                addTitle: function(){  
                    var titleText;  
                    if (this.parentTableModel.get('tableAlias') != '') {  
                        titleText = this.parentTableModel.get('tableAlias') + ' ( ' + this.parentTableModel.get('tableName') + ' )';  
                    }  
                    else {  
                        titleText = this.parentTableModel.get('tableName');  
                    }  
                    this.parentCmp.insert(0, {  
                        xtype: 'component',  
                        ariaRole: 'heading',  
                        focusable: false,  
                        noWrap: true,  
                        flex: 1,  
                        id: this.parentCmp.id + '_hd',  
                        style: 'text-align:' + this.parentCmp.titleAlign,  
                        cls: this.parentCmp.baseCls + '-text-container',  
                        renderTpl: this.parentCmp.getTpl('headingTpl'),  
                        renderData: {  
                            title: titleText,  
                            cls: this.parentCmp.baseCls,  
                            ui: this.parentCmp.ui  
                        },  
                        childEls: ['textEl']  
                    });  
                }  
            }, {  
                xtype: 'component',  
                flex: 0.05  
            }]);  
        },  
        regStartDrag: function(){  
            // save the mousedown state  
            this.bMouseDown = true;  
            // start the drag of the sprite  
            this.shadowSprite.startDrag(this.getId());  
        },  
        moveWindow: function(event, domEl, opt){  
            var relPosMovement;  
            // check mousedown  
            if (this.bMouseDown) {  
                // get relative x and y values (offset)  
                relPosMovement = this.getOffset('point');  
                // move the sprite to the position of the window  
                this.shadowSprite.onDrag(relPosMovement);  
                // check if the sprite has any connections  
                if (this.shadowSprite.bConnections) {  
                    // also move the associated connections   
                    for (var i = ux.vqbuilder.connections.length; i--;) {  
                        this.connection(ux.vqbuilder.connections[i]);  
                    }  
                }  
            }  
        },  
        getLeftRightCoordinates: function(obj1, obj2, aBBPos){  
            var bb1, bb2, p = [], dx, leftBoxConnectionPoint, rightBoxConnectionPoint, dis, columHeight = 21, headerHeight = 46, LeftRightCoordinates = {};  
              
            // BoundingBox Koordinaten f眉r beide Sprites abrufen  
              
            bb1 = obj1.getBBox();  
            // y Wert f眉r connection Points auf der linken und rechten Seite von bb1  
            bb1.pY = bb1.y + headerHeight + ((aBBPos[0] - 1) * columHeight) + (columHeight / 2) - obj1.scrollTop;  
              
            bb2 = obj2.getBBox();  
            // y Wert f眉r connection Points auf der linken und rechten Seite von bb2  
            bb2.pY = bb2.y + headerHeight + ((aBBPos[1] - 1) * columHeight) + (columHeight / 2) - obj2.scrollTop;  
              
            // code f眉r linke boundingBox  
            if (bb1.pY > (bb1.y + 4) && bb1.pY < (bb1.y + bb1.height - 4)) {  
                p.push({  
                    x: bb1.x - 1, // Punkt auf linker Seite auf H枚he der verkn眉pften Spalte  
                    y: bb1.pY  
                });  
                p.push({  
                    x: bb1.x + bb1.width + 1, // Punkt auf rechter Seite auf H枚he der verkn眉pften Spalte  
                    y: bb1.pY  
                });  
            }  
            else {  
                if (bb1.pY < (bb1.y + 4)) {  
                    p.push({  
                        x: bb1.x - 1, // Punkt auf linker Seite max. obere Position  
                        y: bb1.y + 4  
                    });  
                    p.push({  
                        x: bb1.x + bb1.width + 1, // Punkt auf rechter Seite max. obere Position  
                        y: bb1.y + 4  
                    });  
                }  
                else {  
                    p.push({  
                        x: bb1.x - 1, // Punkt auf linker Seite max. untere Position  
                        y: bb1.y + bb1.height - 4  
                    });  
                    p.push({  
                        x: bb1.x + bb1.width + 1, // Punkt auf rechter Seite max. untere Position  
                        y: bb1.y + bb1.height - 4  
                    });  
                };  
                        };  
              
            //  code f眉r rechte boundingBox  
            if (bb2.pY > (bb2.y + 4) && bb2.pY < (bb2.y + bb2.height - 4)) {  
                p.push({  
                    x: bb2.x - 1, // Punkt auf linker Seite auf H枚he der verkn眉pften Spalte  
                    y: bb2.pY  
                });  
                p.push({  
                    x: bb2.x + bb2.width + 1, // Punkt auf rechter Seite auf H枚he der verkn眉pften Spalte  
                    y: bb2.pY  
                });  
            }  
            else {  
                if (bb2.pY < (bb2.y + 4)) {  
                    p.push({  
                        x: bb2.x - 1, // Punkt auf linker Seite max. obere Position  
                        y: bb2.y + 4  
                    });  
                    p.push({  
                        x: bb2.x + bb2.width + 1, // Punkt auf rechter Seite max. obere Position  
                        y: bb2.y + 4  
                    });  
                }  
                else {  
                    p.push({  
                        x: bb2.x - 1, // Punkt auf linker Seite max. untere Position  
                        y: bb2.y + bb2.height - 4  
                    });  
                      
                    p.push({  
                        x: bb2.x + bb2.width + 1, // Punkt auf rechter Seite max. untere Position  
                        y: bb2.y + bb2.height - 4  
                    });  
                }  
            };  
              
            // Schleife 眉ber die Punkte der ersten BoundingBox  
            for (var i = 0; i < 2; i++) {  
                // Schleife 眉ber die Punkte der zweiten BoundingBox  
                for (var j = 2; j < 4; j++) {  
                    // Berechnung der Offsets zwischen den jeweils vier Punkten beider BoundingBoxes  
                    dx = Math.abs(p[i].x - p[j].x), dy = Math.abs(p[i].y - p[j].y);  
                    // bb1 links mit bb2 rechts  
                    if (((i == 0 && j == 3) && dx < Math.abs(p[1].x - p[2].x)) || ((i == 1 && j == 2) && dx < Math.abs(p[0].x - p[3].x))) {  
                        leftBoxConnectionPoint = p[i];  
                        rightBoxConnectionPoint = p[j];  
                    }  
                }  
            };  
              
            return {  
                leftBoxConnectionPoint: leftBoxConnectionPoint,  
                rightBoxConnectionPoint: rightBoxConnectionPoint  
            };  
              
        },  
        connection: function(obj1, obj2, line, aBBPos){  
            var LeftRightCoordinates, line1, line2, miniLine1, miniLine2, path, surface, color = typeof line == "string" ? line : "#000";  
              
            if (obj1.line && obj1.from && obj1.to && obj1.aBBPos) {  
                line = obj1;  
                obj1 = line.from;  
                obj2 = line.to;  
                aBBPos = line.aBBPos;  
            }  
              
            // set reference to the wright surface  
            surface = obj1.surface;  
              
            // get coordinates for the left and right box  
            LeftRightCoordinates = this.getLeftRightCoordinates(obj1, obj2, aBBPos);  
              
            // check if the LeftBox is still on the left side or not  
            if (LeftRightCoordinates.leftBoxConnectionPoint.x - LeftRightCoordinates.rightBoxConnectionPoint.x < 0) {  
                line1 = 12;  
                line2 = 12;  
            }  
            else {  
                line1 = -12;  
                line2 = -12;  
            }  
            // define the path between the left and the right box  
            path = ["M", LeftRightCoordinates.leftBoxConnectionPoint.x, LeftRightCoordinates.leftBoxConnectionPoint.y, "H", LeftRightCoordinates.leftBoxConnectionPoint.x + line1, "L", LeftRightCoordinates.rightBoxConnectionPoint.x - line2, LeftRightCoordinates.rightBoxConnectionPoint.y, "H", LeftRightCoordinates.rightBoxConnectionPoint.x].join(",");  
              
            miniLine1 = ["M", LeftRightCoordinates.leftBoxConnectionPoint.x, LeftRightCoordinates.leftBoxConnectionPoint.y, "H", LeftRightCoordinates.leftBoxConnectionPoint.x + line1].join(",");  
              
            miniLine2 = ["M", LeftRightCoordinates.rightBoxConnectionPoint.x - line2, LeftRightCoordinates.rightBoxConnectionPoint.y, "H", LeftRightCoordinates.rightBoxConnectionPoint.x].join(",");  
              
            //check if it is a new connection or not  
            if (line && line.line) {  
                // old connection, only change path  
                line.bgLine &&  
                line.bgLine.setAttributes({  
                    path: path  
                }, true);  
                line.line.setAttributes({  
                    path: path  
                }, true);  
                line.miniLine1.setAttributes({  
                    path: miniLine1  
                }, true);  
                line.miniLine2.setAttributes({  
                    path: miniLine2  
                }, true);  
            }  
            else {  
                // new connction, return new connection object  
                return {  
                    line: Ext.create('Ext.draw.Sprite', {  
                        type: 'path',  
                        path: path,  
                        stroke: color,  
                        fill: 'none',  
                        'stroke-width': 1,  
                        surface: surface  
                    }).show(true),  
                    miniLine1: Ext.create('Ext.draw.Sprite', {  
                        type: 'path',  
                        path: miniLine1,  
                        stroke: color,  
                        fill: 'none',  
                        'stroke-width': 2,  
                        surface: surface  
                    }).show(true),  
                    miniLine2: Ext.create('Ext.draw.Sprite', {  
                        type: 'path',  
                        path: miniLine2,  
                        stroke: color,  
                        fill: 'none',  
                        'stroke-width': 2,  
                        surface: surface  
                    }).show(true),  
                    bgLine: Ext.create('Ext.draw.Sprite', {  
                        type: 'path',  
                        path: path,  
                        opacity: 0,  
                        stroke: '#fff',  
                        fill: 'none',  
                        'stroke-width': 10,  
                        surface: surface  
                    }).show(true),  
                    from: obj1,  
                    to: obj2,  
                    aBBPos: aBBPos,  
                    uuid: this.createUUID()  
                };  
            }  
        },  
        initComponent: function(){  
            var store, tableModel;  
              
            this.connectionUUIDs = [];  
            this.bMouseDown = false;  
              
            // asign a uuid to the window, this builds relationship with sqlTable  
            this.tableId = this.createUUID();  
              
              
            store = Ext.create('Ext.data.Store', {  
                autoLoad: true,  
                fields: [{  
                    name: 'id',  
                    type: 'string'  
                }, {  
                    name: 'tableName',  
                    type: 'string'  
                }, {  
                    name: 'tableId',  
                    type: 'string',  
                    defaultValue: this.tableId  
                }, {  
                    name: 'field',  
                    type: 'string'  
                }, {  
                    name: 'extCmpId',  
                    type: 'string',  
                    defaultValue: this.id  
                }, {  
                    name: 'type',  
                    type: 'string'  
                }, {  
                    name: 'null',  
                    type: 'string'  
                }, {  
                    name: 'key',  
                    type: 'string'  
                }, {  
                    name: 'default',  
                    type: 'string'  
                }, {  
                    name: 'extra',  
                    type: 'string'  
                }],  
                proxy: {  
                    type: 'ajax',  
                    url: 'data/database.cfc?method=getTableInfo',  
                    extraParams: {  
                        tablename: this.title  
                    },  
                    reader: {  
                        type: 'json'  
                    }  
                }  
            });  
              
            // add sql table to ux.vqbuilder.sqlSelect tables store  
            // also asign same id as stores uuid  
            tableModel = Ext.create('Ext.ux.window.visualsqlquerybuilder.SQLTableModel', {  
                id: this.tableId,  
                tableName: this.title,  
                tableAlias: ''  
            });  
            ux.vqbuilder.sqlSelect.addTable(tableModel);  
              
            this.items = [{  
                xtype: 'sqltablegrid',  
                store: store  
            }];  
              
            this.callParent(arguments);  
        },  
        getOffset: function(constrain){  
            var xy = this.dd.getXY(constrain), s = this.dd.startXY;  
            // return the the difference between the current and the drag&drop start position  
            return [xy[0] - s[0], xy[1] - s[1]];  
        },  
        createUUID: function(){  
            // http://www.ietf.org/rfc/rfc4122.txt  
            var s = [];  
            var hexDigits = "0123456789abcdef";  
            for (var i = 0; i < 36; i++) {  
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);  
            }  
            s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010  
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01  
            s[8] = s[13] = s[18] = s[23] = "-";  
              
            var uuid = s.join("");  
            return uuid;  
        },  
        beforeShow: function(){  
            var aWin, prev, o;  
            // cascading window positions  
            if (this.cascadeOnFirstShow) {  
                o = (typeof this.cascadeOnFirstShow == 'number') ? this.cascadeOnFirstShow : 20;  
                // get all instances from xtype sqltable  
                aWin = Ext.ComponentQuery.query('sqltable');  
                // start position if there is only one table  
                if (aWin.length == 1) {  
                    this.x = o;  
                    this.y = o;  
                }  
                else {  
                    // loop through all instances from xtype sqltable  
                    for (var i = 0, l = aWin.length; i < l; i++) {  
                        if (aWin[i] == this) {  
                            if (prev) {  
                                this.x = prev.x + o;  
                                this.y = prev.y + o;  
                            }  
                        }  
                        if (aWin[i].isVisible()) {  
                            prev = aWin[i];  
                        }  
                    }  
                }  
                this.setPosition(this.x, this.y);  
            }  
        }  
    });  
      
    Ext.define('Ext.ux.window.VisualSQLQueryBuilder', {  
        extend: 'Ext.window.Window',  
        alias: ['widget.qbwindow'],  
        height: 620,  
        width: 1000,  
        layout: {  
            type: 'border'  
        },  
        title: 'Visual SQL Query Builder',  
        items: [{  
            xtype: 'sqloutputpanel',  
            border: false,  
            region: 'center',  
            autoScroll: true,  
            html: '<pre class="brush: sql">SQL Output Window</pre>',  
            margin: 5,  
            height: 150,  
            split: true  
        }, {  
            xtype: 'panel',  
            border: false,  
            height: 400,  
            margin: 5,  
            layout: {  
                type: 'border'  
            },  
            region: 'north',  
            split: true,  
            items: [{  
                xtype: 'sqltablepanel',  
                border: false,  
                region: 'center',  
                height: 280,  
                split: true,  
                layout: 'fit'  
            }, {  
                xtype: 'sqlfieldsgrid',  
                border: false,  
                region: 'south',  
                height: 120,  
                split: true  
            }, {  
                xtype: 'sqltabletree',  
                border: false,  
                region: 'west',  
                width: 200,  
                height: 400,  
                split: true  
            }]  
        }],  
        initComponent: function(){  
          
            // create user extension namespace ux.vqbuilder  
            Ext.namespace('ux.vqbuilder');  
              
            // disable gutter (linenumbers) and toolbar for SyntaxHighlighter  
            SyntaxHighlighter.defaults['gutter'] = false;  
            SyntaxHighlighter.defaults['toolbar'] = false;  
              
            ux.vqbuilder.connections = [];  
              
            ux.vqbuilder.sqlSelect = Ext.create('Ext.ux.window.visualsqlquerybuilder.SQLSelect');  
              
            // add toolbar to the dockedItems  
            this.dockedItems = [{  
                xtype: 'toolbar',  
                dock: 'top',  
                items: [{  
                    xtype: 'tbfill'  
                }, {  
                    text: "Save",  
                    icon: "resources/images/icon-save.gif"  
                }, {  
                    text: "Run",  
                    icon: "resources/images/run.png"  
                }]  
            }];  
              
            this.callParent(arguments);  
        }  
    });

转载于:https://my.oschina.net/u/256857/blog/98451

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值