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
- sophisticated development framework
Short-Backs
- Performance issue
- style restriction to windows alike
- extra development risk introduced
out-of-shelf widgets
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
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();
};
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
<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);
});
and here is the debugging log window which is generated by qooxdoo
table
- definition code
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(0, new qx.ui.table.BooleanDataCellRenderer());
setColumnWidth(0, 20);
setColumnWidth(1, 50);
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(0, 50);
}
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);
}
- How to use it
<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);
});
pub-up select
- definition code
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(300, 400, 100, 300);
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;
};
- How to use it
<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);
});
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!