Develop Log - Qooxdoo Widget

Basic Review
    qooxdoo is an open-source javascript library (framework).  it is totally browser compatable, it is sophisticated and strong enough to implement your own web UI based on it. at last and the most important is, it's free :-) i'm not an expert. i've just played with qooxdoo for some time and wana share some of my development experience with you dude. i'll list some features of qooxdoo at first, and some of the out-of-shelf widgets which are qooxdoo based will be introduced later. 

Features
    Out-standings
  • highly browser compatibility
believe it or not, qooxdoo is totally browser compatable. you could build some widget or even applications on top of qooxdoo and let them run smoothly on any kind of popular browser, like Firefox, M$IE, safari, opera, ect. this feature is so cool, even remind me of the java technology, say write once, run everywhere!    
  • sophisticated development framework
as i see it, qooxdoo is a sophisticated development framework. you could build your own web UI widget based on it, or even a complete web UI could be built totally on qooxdoo.      
               
    Short-Backs
  • Performance issue
as about 1M bytes of data must be transferred to a browser for each http request, the performance of applications built on top of qooxdoo could certainly be an issue, especially the initial time cost could be high. however, if AJAX is also used in this application, time cost would be acceptable after the period of UI initialization.  
  • style restriction to windows alike
this is even not a short-back for qooxdoo, because qooxdoo is designed to restrict its style to windows alike.  but as for me, i would rather take it as one short-back because in my mind, isn't it be so great if i could integrate some cool widget built on top of qooxdoo with one of my project? however i failed at last because it is so hard to tune the style of these widget to fit with other part of the web page.  I've found some discussions on web just about this issue, and we are hopefully could get some enhancement from next released versions.  
  • extra development risk introduced
once qooxdoo is introduced into your project, it will certainly change some style of your development. even NOT saying about AJAX, building a little qooxdoo based widget could be defferenct from the way you build a original web component. you just write some javascript and "BANG" your widget is out there. this is some kind of cool, i should say. however, it must introduce some extra risk into your project. so please think twice before you decide to use qooxdoo at last.         

out-of-shelf widgets
here some qooxdoo based widgets are demonstrated. i'll first show you how i organized all the resources to start building our widget. next let's begin with a little tiny select widget, then some more complicated widget, like table and pup-up select window, will be described. 
    resource construction
        i was taking qooxdoo v0.6.2 to build my widget. after the compressed file has been downloaded and extracted,  you will find all the fundamental resources in ${qooxdoo_home}/frontend/framework. yes, that would be the materials we are starting to work with. What i was doing then is to copy the qx.js file under   ${qooxdoo_home}/frontend/framework/script into my web app project, say ${webapp_root}/js, and also some of the resources under ${qooxdoo_home}/frontend/framework/resource should be copied to the project, say ${webapp_root} /resource. you're never required to put all these resources into your project, only use the needed resources is fine. then i generated one file called my_widget.js which is under ${webapp_root}/js. that is the place where we're going to write the javascript code and develop our own widget:-)
    code organization in my_widget.js
        basically i separated the js code into several parts. as you see it below. it includes the logger switch, the shortcut/global var definition, the util function, and the class definition which is also the main part because each qooxdoo widget is supposed to be defined as a class, pretty like what we deed using java.

/** =========================================================
 * MYWidget - web UI widget suite.
 * Author: jeffmsu
 * =========================================================
*/


/**
 * logger switch. unmark in production env.
 
*/

//qx.dev.log.Logger.ROOT_LOGGER.removeAllAppenders();


/** --------------------------------------------------------
 * shortcut,global var
 * ---------------------------------------------------------
*/

var arrayUtil = qx.lang.Array;


/** --------------------------------------------------------
 * util function
 * ---------------------------------------------------------
*/

 
var mywidget_main = function(funMain){
    qx.core.Init.getInstance().defineMain(funMain);
}
;


/** --------------------------------------------------------
 * class define
 * ---------------------------------------------------------
*/
 
  

    select
  • definition code  
        let's start with a simple select widget. here is the js code:      
// define my_select -----------------------------------------
qx.OO.defineClass("my_select",qx.ui.core.Widget,function(options,selValue){
    qx.ui.core.Widget.call(
this);
    
var sel = new qx.ui.form.ComboBox();
    
var item = null;
    
for(var i=0,j=options.length; i<=j; i++){
        item 
= new qx.ui.form.ListItem(options[i]);     
        sel.add(item);
    }
   
    sel.setSelected(
new qx.ui.form.ListItem(selValue));
    
this._sel = sel;
}
);
qx.Proto.setEditable 
= function(editable){
    
this._sel.setEditable(editable);
}
;
qx.Proto.setSelected 
= function(selValue){
    
this._sel.setSelected(new qx.ui.form.ListItem(selValue));
}
;
qx.Proto.getSelected 
= function(){
    
return this._sel.getManager().getSelectedItem().getLabel();
}
;   

you could define a class using a statement like this:
qx.OO.defineClass("class_name",baseClass,function(parameters){function body});

    as you can see, i defined a class named "my_select", and it extended from the class of qx.ui..core.Widget, plus we must provide 2 parameters: options and seleced value to generate a instance of "my_select". here i've also added some functions as setEditable(), setSelected() and getSelected() to this class.
  • How to use it
             it is very simple to generate a widget on the web page, and here is a sample:         
<script type="text/javascript" src="../../js/qx.js"></script>
<script type="text/javascript" src="../../js/my_widget.js"></script>
...
mywidget_main( 
function(){
    
var sel_values = ["firefox","m$ie","safari","opera"];
    
var selectedValue = "firefox";       
    widget_select 
= new my_select(sel_values,selectedValue);              
}
);          
  
             here is what it looks like on a browser
             my_select pic
             and here is the debugging log window which is generated by qooxdoo
             debugging log window pic
    table
  • definition code
// define my_table ------------------------------------------
qx.OO.defineClass("my_table",qx.ui.core.Widget,function(t_width,t_height,t_cols,t_data,flag_forsel){
    qx.ui.core.Widget.call(
this);
            
    
this._t_width = t_width;
    
this._t_height = t_height;
    
this._t_cols = t_cols;
    
this._t_data = t_data;
    
this._t_forsel = flag_forsel;
   
    
this._selected_item = [];
   
    
var t_xBox = null;    
    
if(this._t_forsel==true){
        t_xBox 
= new qx.ui.groupbox.CheckGroupBox("All");
        
with(t_xBox){    
            getLegendObject().setChecked(
false);        
            getLegendObject().addEventListener(qx.constant.Event.CLICK,
function(){
                
var selAll = getLegendObject().getChecked();
                
this.debug("xBox checked. selAll:"+ selAll);
                
for(var i=0,j=t_data.length;i<j;i++){
                    t_tblModel.setValue(
0,i,selAll);
                }

            }
);
        }

    }

    
else{
        t_xBox 
= new qx.ui.groupbox.GroupBox(null"icon/16/view-text.png");
    }
    
    
with(t_xBox){
        auto();    
    }

    
var t_layout = new qx.ui.layout.VerticalBoxLayout();            
    t_layout.set(
{ height:this._t_height,width:this._t_width});
    t_xBox.add(t_layout);         
   
    arrayUtil.insertBefore(
this._t_cols,"Item",this._t_cols[0]);
    
if(this._t_forsel==true){
        arrayUtil.insertBefore(
this._t_cols,"*",this._t_cols[0]);            
    }

    
for(var i=0,j=this._t_data.length;i<j;i++){
        arrayUtil.insertBefore(
this._t_data[i],i+1,this._t_data[i][0]);
        
if(this._t_forsel==true){
            arrayUtil.insertBefore(
this._t_data[i],false,this._t_data[i][0]);
        }

    }
     
    
var t_tblModel = new qx.ui.table.SimpleTableModel();        
    t_tblModel.setColumns(
this._t_cols);
    t_tblModel.setData(
this._t_data);    
    
var t_table = new qx.ui.table.Table(t_tblModel);
    
with (t_table) {
          set(
{ width:"100%", height:"100%", border:qx.renderer.border.BorderPresets.getInstance().thinInset,statusBarVisible:false });
          setFocusedCell(
1,0,false);                                       
    }
;
    
if(this._t_forsel==true){
        
with(t_table){
            setMetaColumnCounts([
2,-1]);
            getSelectionModel().setSelectionMode(qx.ui.table.SelectionModel.MULTIPLE_INTERVAL_SELECTION);
            getTableColumnModel().setDataCellRenderer(
0new qx.ui.table.BooleanDataCellRenderer());          
            setColumnWidth(
020);
            setColumnWidth(
150);
        
            addEventListener(qx.constant.Event.MOUSEUP,
function(){                                
                
this.debug("cell focused col="+ t_table.getFocusedColumn()+" row="+ t_table.getFocusedRow());                    
                
var tarCol = t_table.getFocusedColumn();
                
var tarRow = t_table.getFocusedRow();    
                
if(tarCol == 0){                            
                    t_tblModel.setValue(
0,tarRow,(!t_tblModel.getValue(0,tarRow)));
                    
if(t_tblModel.getValue(0,tarRow)==false){
                        t_xBox.getLegendObject().setChecked(
false);
                    }

                    
else{
                        
var cnt = 0;
                        
var rowCnt = t_tblModel.getRowCount();
                        
for(var i=0;i<rowCnt;i++){
                            
if(t_tblModel.getValue(0,i)==true){
                                cnt
++;
                            }

                        }
    
                        
if(cnt == rowCnt){
                            t_xBox.getLegendObject().setChecked(
true);
                        }

                    }

                    setFocusedCell(
1,tarRow,false);
                }
                                                    
            }
);        
        }
                                            
    }

    
else{
        t_table.setMetaColumnCounts([
1,-1]);
          t_table.setColumnWidth(
050);
    }
        
    t_layout.add(t_table);
   
    
this._t_xBox =     t_xBox;
    
this._t_layout = t_layout;
    
this._t_table = t_table;
    
this._t_tblModel = t_tblModel;    
}
);
qx.Proto.getSelectedItem 
= function(){
    arrayUtil.removeAll(
this._selected_item);
    
for(var i=0,j=this._t_tblModel.getRowCount();i<j;i++){
        
if(this._t_tblModel.getValue(0,i)==true){
            
this._selected_item.push(this._t_tblModel.getValue(1,i));
        }

    }
    
    
return this._selected_item;
}
;
qx.Proto.getCellValue 
= function(item,colName){
    
var rowIndex = 0;
    
for(var i=0,j=this._t_tblModel.getRowCount();i<j;i++){
        
if(this._t_tblModel.getValue(1,i)==item){
            rowIndex 
= i;
        }

    }

    
return this._t_tblModel.getValueById(colName,rowIndex);
}
;
qx.Proto.setCellValue 
= function(item,colName,value){
    
var rowIndex = 0;
    
for(var i=0,j=this._t_tblModel.getRowCount();i<j;i++){
        
if(this._t_tblModel.getValue(1,i)==item){
            rowIndex 
= i;
        }

    }

    
this._t_tblModel.setValueById(colName,rowIndex,value);
}
      

        if you could ever notice it, one must provide a boolean flag indicating whether this very "my_table" instance is selectable or not. you could get it clearer after you've seen the sample picture shown later. i'v also defined some functions to this class, like getSelectedItem(), getCellValue(), ect.
  • How to use it
        to use the "my_table" widget is very similar with what we've done using the "my_select" widget, and it is also very simple.       
<script type="text/javascript" src="../../js/qx.js"></script>
<script type="text/javascript" src="../../js/my_widget.js"></script>
...
mywidget_main( 
function(){
        
var cols = ["ID","Name","Description"];
        
var raw_data = [
            [
"057","jeffrey","master"],
            [
"007","james","spy"],
            [
"911","laden","abrabian"]         
        ];      
        table_for_sel 
= new my_table(300,200,cols,raw_data,true);            
}
);          

       and here is what we get in the browser
      
      
       my_table_nosel pic
   
    pub-up select
  •        definition code
// define my_pupsel ------------------------------------------
qx.OO.defineClass("my_pupsel",qx.ui.core.Widget,function(sel_cols,sel_data,seleted_index){
   
    qx.ui.core.Widget.call(
this);
   
    
var xlayout = new qx.ui.layout.HorizontalBoxLayout();                         
    
var tipLabel = "";
    
if(seleted_index.length>0){
        tipLabel 
= "item selected..."
    }

    
var field = new qx.ui.form.TextField(tipLabel);
    field.setUserData(
"seleted_index",seleted_index);
    
with(field){
        set(
{height:25});
        setReadOnly(
true);            
    }

                
    
var btn = new qx.ui.form.Button(null,"icon/16/file-find.png");     
    btn.addEventListener(
"execute"function() {
        pupup.open(btn);
    }
);
    
var btn_tip = new qx.ui.popup.ToolTip("go to select");
    btn.setToolTip(btn_tip);   
    xlayout.add(field,btn);
           
        
//define pupup window
        var pupup = new qx.ui.window.Window("Please Select""icon/16/view-text.png");
        
with(pupup){
            setSpace(
300400100300);
            set(
{ showClose:false, showMaximize:false, showMinimize:false, modal:true,resizeable:false });
            addToDocument();                    
        }
                     
           
var inW= new qx.ui.layout.VerticalBoxLayout();
        
with(inW){
            set(
{ height:"100%", width:"100%" });
        }
           
        pupup.add(inW);
                       
        
var innerTable = new my_table(400,250,sel_cols,sel_data,true);        
        inW.add(innerTable._t_xBox);
        
if(seleted_index==null){
            seleted_index 
= [];    
        }

        
for(var i=0,j=sel_data.length;i<j;i++){
            
if(arrayUtil.contains(seleted_index,i)){
                innerTable._t_tblModel.setValue(
0,i,true);
            }

        }

                              
        
var btn_box = new qx.ui.layout.HorizontalBoxLayout();
        
with(btn_box){
            set(
{ width:"100%", height:"auto", spacing:20, horizontalChildrenAlign:"center" });    
        }

        inW.add(btn_box);                    
        
var bOK = new qx.ui.form.Button("OK");
        
with(bOK){
            set(
{ width:60});
            addEventListener(
"execute",function(){               
                seleted_index 
= innerTable.getSelectedItem();
                field.setUserData(
"seleted_index",seleted_index);
                
if(seleted_index.length>0){
                    tipLabel 
= "item selected...";
                }

                
else{
                    tipLabel 
= "";
                }

                field.setValue(tipLabel);                
                pupup.close();
            }
);
        }

        btn_box.add(bOK);                
        
var bCancel = new qx.ui.form.Button("Cancel");
        
with(bCancel){
            set(
{ width:60});
            addEventListener(
"execute",function(e){
                pupup.close();
            }
);
        }

        btn_box.add(bCancel);
        
        
this._p_xlayout = xlayout;
        
this._field = field;
        
this._innerTable = innerTable;
}
);
qx.Proto.getSelectedItem 
= function(){
    
return this._field.getUserData("seleted_index");
}
;
qx.Proto.getSelectedColValue 
= function(colName){
    
var colValue = [];
    
var selItem = this._field.getUserData("seleted_index");
    
for(var i=0,j=selItem.length;i<j;i++){
        colValue.push(
this._innerTable.getCellValue(selItem[i],colName));
    }

    
return colValue;
}
;     
 
       as the statement  
var innerTable = new my_table(400,250,sel_cols,sel_data,true);
        indicated, i integrated my_table class into this new class which is called my_pupsel,so that i could use the features of my_table directly in the class of my_pupsel. and i really feel it interesting!
  • How to use it
           sample code again
<script type="text/javascript" src="../../js/qx.js"></script>
<script type="text/javascript" src="../../js/my_widget.js"></script>
...
mywidget_main( 
function(){
        
var cols = ["ID","Name","Description"];
        
var raw_data = [
            [
"057","jeffrey","master"],
            [
"007","james","spy"],
            [
"911","laden","abrabian"]         
        ];      
        
var seletedIndex = [0];
        pupup_sel 
= new my_pupsel(cols,raw_data,seletedIndex);           
}
);         

       some screen shot during running the sample code
       my_pupsel pic

Conclusion
   i've already listed some features of qooxdoo plus several widgets built on top of it. basically speaking, qooxdoo is worthy of keeping an eye on it. the current version of qooxdoo is 0.6.3 and it's strong enough to start our project with it,  it could only be stronger in the next released versions and we are looking foward to it. i hope you will like qooxdoo, just as what i feel about it. having fun!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章