亚洲成a人片毛片在线,亚洲va无码va在线va天堂,亚洲日韩精品A∨片无码http://www.tkk7.com/fuhoujun/category/34936.htmlzh-cnTue, 20 Jan 2009 14:57:37 GMTTue, 20 Jan 2009 14:57:37 GMT60Ext框架的Grid使用介紹http://www.tkk7.com/fuhoujun/archive/2008/11/02/238151.html付厚俊付厚俊Sun, 02 Nov 2008 03:05:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/11/02/238151.htmlhttp://www.tkk7.com/fuhoujun/comments/238151.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/11/02/238151.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/238151.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/238151.htmlExt2.0是一個JS框架,它的Grid控件和其它可以顯示數據的控件,能夠支持多種數據類型,如二維數組、Json數據和XML數據,甚至包括我們自定義的數據類型。Ext為我們提供了一個橋梁Ext.data.Store,通過它我們可以把任何格式的數據轉化成grid可以使用的形式,這樣就不需要為每種數據格式寫一個grid的實現了。

首先,一個表格應該有列定義,即定義表頭ColumnModel:
// 定義一個ColumnModel,表頭中有四列
var cm = new Ext.grid.ColumnModel([
     {header:
'編號',dataIndex:'id'
},
     {header:
'性別',dataIndex:'sex'
},
     {header:
'名稱',dataIndex:'name'
},
     {header:
'描述',dataIndex:'descn'
}
]);
cm.defaultSortable
= true
;
    該ColumnModel定義了表格的四個列,其每列的名稱和對應的數據鍵。請注意defaultSortable屬性,即為每個列都安上一個可以排序的功能。如果只想某些列舉有該功能,可以設置:
{header:'編號',dataIndex:'id',Sortable:true},

現在就來看看這個Ext.data.Store是如何轉換三種數據的。

1.二維數組:
// ArrayData
var data = [
     [
'1','male','name1','descn1'
],
     [
'2','male','name1','descn2'
],
     [
'3','male','name3','descn3'
],
     [
'4','male','name4','descn4'
],
     [
'5','male','name5','descn5'
]
];
// ArrayReader
var ds = new Ext.data.Store({
     proxy:
new
Ext.data.MemoryProxy(data),
     reader:
new
Ext.data.ArrayReader({}, [
        {name:
'id',mapping: 0
},
         {name:
'sex',mapping: 1
},
         {name:
'name',mapping: 2
},
         {name:
'descn',mapping: 3
}
     ])
});
ds.load();
ds要對應兩個部分:proxy和reader。proxy告訴我們從哪里獲得數據,reader告訴我們如何解析這個數據。
現在用的是Ext.data.MemoryProxy,它將內存中的數據data作為參數傳遞。Ext.data.ArrayReader專門用來解析數組,并且告訴我們它會按照定義的規范進行解析,每行按順序讀取四個數據,第一個叫id,第二個叫sex,第三個叫name,第四個descn。這些是跟cm定義中的dataIndex對應的。這樣cm就知道哪列應該顯示那條數據了。
mapping屬性用于標記data中的讀取后的數據與標頭的映射關系,一般是不用設置的。但如果我們想讓sex的數據中name欄中出現,可以設置mapping值。即id的mapping為2,后者為0。
記得要執行一次ds.load(),對數據進行初始化。

數據的顯示顯得非常簡單:
HTML文件:
<div id='grid'></div>
JS文件:
var grid = new Ext.grid.GridPanel({
     el:
'grid'
,
     ds: ds,
     cm: cm
});
grid.render();

其顯示結果為:

2.如何在表格中添加CheckBox呢?

var sm = new Ext.grid.CheckboxSelectionModel();
var cm = new Ext.grid.ColumnModel([
    new Ext.grid.RowNumberer(),//自動行號
    sm,//添加的地方

    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex'},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

var grid = new Ext.grid.GridPanel({
    el: 'grid3',
    ds: ds,
    cm: cm,
    sm: sm,//添加的地方
    title: 'HelloWorld'
});

3. 如何做Grid上觸發事件呢?
下面是一個cellclick事件
grid.addListener('cellclick', cellclick);
function cellclick(grid, rowIndex, columnIndex, e) {
    var record = grid.getStore().getAt(rowIndex);   //Get the Record
    var fieldName = grid.getColumnModel().getDataIndex(columnIndex); //Get field name
    var data = record.get(fieldName);
    Ext.MessageBox.alert('show','當前選中的數據是'+data);
}

4.如何做Grid中做出快捷菜單效果:
grid.addListener('rowcontextmenu', rightClickFn);//右鍵菜單代碼關鍵部分
var rightClick = new Ext.menu.Menu({
    id:'rightClickCont', //在HTML文件中必須有個rightClickCont的DIV元素
    items: [
        {
            id: 'rMenu1',
            handler: rMenu1Fn,//點擊后觸發的事件
            text: '右鍵菜單1'
        },
        {
            //id: 'rMenu2',
            //handler: rMenu2Fn,
            text: '右鍵菜單2'
        }
    ]
});
function rightClickFn(grid,rowindex,e){
    e.preventDefault();
    rightClick.showAt(e.getXY());
}
function rMenu1Fn(){
   Ext.MessageBox.alert('right','rightClick');
}
其Grid如下:

5.如何將一列中的數據根據要求進行改變呢?
比如說性別字段根據其male或female改變顯示的顏色,這種ColumnMode中設計:
var cm = new Ext.grid.ColumnModel([
    new Ext.grid.RowNumberer(),
    sm,
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex',renderer:changeSex},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);
cm.defaultSortable = true;

function changeSex(value){
    if (value == 'male') {
        return "<span style='color:red;font-weight:bold;'>紅男</span>";
    } else {
        return "<span style='color:green;font-weight:bold;'>綠女</span>";
    }
}

其它兩種數據的Grid顯示是相同的,其不同之處在于數據獲取的過程:

6.Json數據
至于這種數據的類型請大家自己看Ajax的書籍:

//JsonData
var data = {
    'coders': [
        { 'id': '1', 'sex': 'male', 'name':'McLaughlin', 'descn': 'brett@newInstance.com' },
        { 'id': '2', 'sex': 'male','name':'Hunter', 'descn': 'jason@servlets.com' },
        { 'id': '3', 'sex': 'female','name':'Harold', 'descn': 'elharo@macfaq.com' },
        { 'id': '4', 'sex': 'male','name':'Harolds', 'descn': 'elhaross@macfaq.com' }
    ],
    'musicians': [
        { 'id': '1', 'name': 'Clapton', 'descn': 'guitar' },
        { 'id': '2', 'name': 'Rachmaninoff', 'descn': 'piano' }
    ]
}
//ds使用的MemoryProxy對象和JsonReader對象
var ds = new Ext.data.Store({
        proxy: new Ext.data.MemoryProxy(data),
        reader: new Ext.data.JsonReader({root: 'coders'}, [
            {name: 'id'},
            {name: 'sex'},
            {name: 'name'},
            {name: 'descn'}
        ])
    });
ds.load();

var grid = new Ext.grid.GridPanel({
    el: 'grid3',
    ds: ds,
    cm: cm,
    sm: sm,
    title: 'HelloWorld',
    autoHeight: true//一定要寫,否則顯示的數據會少一行
});
grid.render();

7.使用XML數據:
注意,讀取XML數據必須在服務器上進行。
XML數據test.xml的內容:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
     <results>2</results>
     <item>
           <id>1</id>
           <sex>male</sex>
           <name>Taylor</name>
           <descn>Coder</descn>
     </item>
</dataset>var ds3 = new Ext.data.Store({
    url: 'test.xml',   //XML數據
    reader: new Ext.data.XmlReader({record: 'item'}, [ //使用XmlReader對象
        {name: 'id'},
        {name: 'sex'},
        {name: 'name'},
        {name: 'descn'}
    ])
});

8.從服務器獲取數據和數據翻頁控件
從一個服務器文件,如ASP、JSP或Servlet中獲得數據二維Array、JSON或XML數據,也可以被Ext讀取,并被Grid顯示:
服務器文件data.asp:
<%
    start = cint(request("start"))
    limit = cint(request("limit"))

    dim json
    json=cstr("{totalProperty:100,root:[")
   
    for i = start to limit + start-1
        json =json + cstr("{'id':'") +cstr(i) + cstr("','name':'name") + cstr(i) + cstr("','descn':'descn") + cstr(i) + cstr("'}")
        if i <> limit + start - 1 then
            json =json + ","
        end if
    next
    json = json +"]}"
    response.write(json)
%>

我們可以看到,這個頁面會根據傳入的start和limit的不同,返回不同的數據,其實質是個分頁的代碼。下面是start=0,limit=10的JSON數據:
{totalProperty:100,root:[{'id':'0','name':'name0','descn':'descn0'},{'id':'1','name':'name1','descn':'descn1'},{'id':'2','name':'name2','descn':'descn2'},{'id':'3','name':'name3','descn':'descn3'},{'id':'4','name':'name4','descn':'descn4'},{'id':'5','name':'name5','descn':'descn5'},{'id':'6','name':'name6','descn':'descn6'},{'id':'7','name':'name7','descn':'descn7'},{'id':'8','name':'name8','descn':'descn8'},{'id':'9','name':'name9','descn':'descn9'}]}

我們使用分頁控件來控制Grid的數據:
Ext.onReady(function(){
    var sm = new Ext.grid.CheckboxSelectionModel();
   
    var cm = new Ext.grid.ColumnModel([
        new Ext.grid.RowNumberer(),
        sm,
        {header:'編號',dataIndex:'id'},
        {header:'性別',dataIndex:'sex'},
        {header:'名稱',dataIndex:'name'},
        {header:'描述',dataIndex:'descn'}
    ]);
    cm.defaultSortable = true;

    var ds = new Ext.data.Store({
        proxy: new Ext.data.HttpProxy({url:'data.asp'}),
        reader: new Ext.data.JsonReader({
            totalProperty: 'totalProperty',
            root: 'root'
        }, [
            {name: 'id'},
            {name: 'name'},
            {name: 'descn'}
        ])
    });
    ds.load({params:{start:0,limit:10}});
   
    var grid = new Ext.grid.GridPanel({
        el: 'grid3',
        ds: ds,
        cm: cm,
        sm: sm,
        title: 'ASP->JSON',
        bbar: new Ext.PagingToolbar({
            pageSize: 10,
            store: ds,
            displayInfo: true,
            displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
            emptyMsg: "沒有記錄"
        }),
        tbar: new Ext.PagingToolbar({
            pageSize: 10,
            store: ds,
            displayInfo: true,
            displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
            emptyMsg: "沒有記錄"
        })
    });
    grid.render();

})

10.如何在Grid的上方添加按鈕呢?
添加按鈕的關鍵之處在于tbar或bbar屬性設置Toolbar工具條:
var grid = new Ext.grid.GridPanel({
    el: 'grid3',
    ds: ds,
    cm: cm,
    sm: sm,
    title: 'HelloWorld',
    tbar: new Ext.Toolbar({
        items:[
                {
                    id:'buttonA'
                    ,text:"Button A"
                    ,handler: function(){ alert("You clicked Button A"); }
                }
                ,
                new Ext.Toolbar.SplitButton({})
                ,{
                    id:'buttonB'
                    ,text:"Button B"
                    ,handler: function(){ alert("You clicked Button B"); }
                }
                ,
                '-'
                ,{
                    id:'buttonc'
                    ,text:"Button c"
                }
            ]
        })

});

11.將GridPanel放入一個Panel或TabPanel中
var tabs = new Ext.TabPanel({
    collapsible: true
    ,renderTo: 'product-exceptions'
    ,width: 450
    ,height:400
    ,activeTab: 0
    ,items:[
        {
            title: 'Unmatched'
        },{
            title: 'Matched'
        }
    ]
});
tabs.doLayout();

var panel = new Ext.Panel({
    renderTo: 'panel',
    title:'panel',
    collapsible:true,
    width:450,
    height:400,
    items:[grid] //管理grid
});

Panel必須有DIV存在。其包含的Component有items管理。



付厚俊 2008-11-02 11:05 發表評論
]]>
Ext中FormPanel面板及Form控件橫排測試(CSS) http://www.tkk7.com/fuhoujun/archive/2008/10/15/234416.html付厚俊付厚俊Wed, 15 Oct 2008 05:03:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/15/234416.htmlhttp://www.tkk7.com/fuhoujun/comments/234416.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/15/234416.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/234416.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/234416.html

在實際的網頁開發中,大部分時間都要涉及到Form表單的處理。在Ext框架中也提供了很多這方面的控件,而且還有一個專門的FormPanel布 局,該布局默認為放在面板上面的所有控件都是換行放置,而在實際應用中為了美觀,有些需要橫排,特別是Radio控件,這個時候就需要我們重新定制這些控 件的布局了,該例子中使用CSS來實現這些功能,先貼出一張效果圖。



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Ext中FormPanel面板及Form控件橫排測試(CSS)</title>
<link rel="stylesheet" type="text/css" media="all" href="../ext/resources/css/ext-all.css" />
<style type="text/css" media="all">
.allow-float {clear:none!important;} /* 允許該元素浮動 */
.stop-float {clear:both!important;} /* 阻止該元素浮動 */
.sex-male {float:left;}
.sex-female {float:left;padding:0 0 0 20px;}
.age-field {float:left;padding:0 0 0 58px;*padding:0 0 0 50px!important;*padding:0 0 0 50px;}
</style>
</head>
<body>
<script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext/ext-all.js"></script>
<script type="text/javascript" src="../ext/build/locale/ext-lang-zh_CN.js"></script>
<script type="text/javascript">Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';</script>
<script type="text/javascript">
Ext.onReady(function() {
//創建Form面板
var fp = new Ext.form.FormPanel({
buttonAlign:'center',
labelAlign:'right',
labelWidth:40,
frame:true,
bodyStyle:'padding:8px 0 0 0;',
items:[{
xtype:'textfield',
fieldLabel:'姓名',
name:'n_username',
id:'i_username',
width:320
},{
xtype:'radio',
fieldLabel:'性別',
boxLabel:'男',
name:'sex',
id:'male',
itemCls:'sex-male', //向左邊浮動,處理控件橫排
clearCls:'allow-float', //允許兩邊浮動,在實際生成的HTML結構中有專門的DIV阻斷浮動
checked:true
},{
xtype:'radio',
boxLabel:'女',
name:'sex',
id:'female',
itemCls:'sex-female', //向左浮動,處理控件橫排
clearCls:'allow-float', //允許兩邊浮動
hideLabel:true //不顯示前面"性別"的標簽
},{
xtype:'textfield',
fieldLabel:'年齡',
name:'n_age',
id:'i_age',
itemCls:'age-field', //向左浮動,處理控件橫排
width:133
},{
xtype:'textfield',
fieldLabel:'住址',
name:'n_address',
id:'i_address',
itemCls:'stop-float', //不允許浮動,結束控件橫排
width:320
}],
buttons:[{
text:'確定',
handler:onOK //實際應用一般是處理fp.getForm.submit()事件
}, {
text:'重置',
handler:function(){ fp.getForm().reset(); }
}],
keys:[{ //處理鍵盤回車事件
key:Ext.EventObject.ENTER,
fn:onOK,
scope:this
}]
});

//確定按鈕事件,這里只是簡單獲取各控件值,實際應用一般和后臺腳本結合
function onOK() {
var strMsg;
strMsg = ‘姓名:’ + fp.getComponent(’i_username’).getValue() + ‘,性別:’;
if (fp.getComponent(’male’).checked) strMsg += ‘男’;
if (fp.getComponent(’female’).checked) strMsg += ‘女’;
strMsg += ‘,年齡:’ + fp.getComponent(’i_age’).getValue();
strMsg += ‘,住址:’ + fp.getComponent(’i_address’).getValue();
alert(strMsg);
}

//創建主窗口
new Ext.Window({
title:’Ext中FormPanel面板及Form控件橫排測試(CSS)’,
width:400,
closable:false,
collapsible:true,
draggable:false,
resizable:false,
modal:true,
border:false,
items:[fp],
buttons:[]
}).show();
});
</script>
</body>
</html>



付厚俊 2008-10-15 13:03 發表評論
]]>
EXT樹重新加載http://www.tkk7.com/fuhoujun/archive/2008/10/15/234413.html付厚俊付厚俊Wed, 15 Oct 2008 04:52:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/15/234413.htmlhttp://www.tkk7.com/fuhoujun/comments/234413.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/15/234413.html#Feedback1http://www.tkk7.com/fuhoujun/comments/commentRss/234413.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/234413.html
Js代碼 復制代碼
  1. var Tree = Ext.tree;   
  2.       
  3.   deptTree = new Tree.TreePanel({   
  4.       el : elementId,   
  5.       autoScroll:true,   
  6.       animate:true,   
  7.       enableDD:true,   
  8.       containerScroll: true,    
  9.       loader: new Tree.TreeLoader({   
  10.           dataUrl: CONTEXT_PATH + "/depts/deptTree.do",   
  11.           baseParams: filter   
  12.       })   
  13.   });      
  14.      
  15.   // set the root node   
  16.   root = new Tree.AsyncTreeNode({   
  17.       text: rootDesc,   
  18.       draggable:false,   
  19.       id:'-1'  
  20.   });   
  21.   deptTree.setRootNode(root);   
  22.      
  23.   // render the deptTree   
  24.   deptTree.render();   
  25.   root.expand();      


ext js 重新加載樹
Js代碼 復制代碼
  1.   /**  
  2.  * 重新加載樹  
  3.  *   
  4.  * @param {f}  
  5.  *          f 過濾樹的條件 如:{placeid:'xxxxx'}  
  6.  */            
  7. reload : function (f){   
  8.     filter = f;   
  9.   
  10.     var loader = deptTree.getLoader();   
  11.     deptTree.on('beforeload'function(){    
  12.             loader.dataUrl = loader.dataUrl ;   
  13.             loader.baseParams = filter;   
  14.     });   
  15.     root.reload();     
  16. }  


付厚俊 2008-10-15 12:52 發表評論
]]>
ext中樹結構帶復選框的處理http://www.tkk7.com/fuhoujun/archive/2008/10/10/233673.html付厚俊付厚俊Fri, 10 Oct 2008 13:43:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/10/233673.htmlhttp://www.tkk7.com/fuhoujun/comments/233673.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/10/233673.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/233673.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/233673.html 關于Struts-Menu,Dtree的處理,在我早期的博客中都有描述.

帶有復選框的樹,在實際的項目中,特別是授權結構中,有大量的使用.我們來看一下Faceye中如何處理這種帶復選框的樹形結構.

首先,Faceye使用了Ext的樹解決方案,所以,所有的數據結構,均轉化為Ext中樹解決方案的數據結構.在這里,我們可以很方便的把這一結構轉化為其它樹支持的數據結構,比如Strus-menu,dtreee等.
下面是對樹完整的腳本處理代碼.
[code]
/**
*RoleController
* 角色訪問權限管理
* 管理角色對模塊的訪問權限
* www.faceye.com網絡支持系統
* 作者:宋海鵬 ecsun@sohu.com/myecsun@hotmail.com
*/
Ext.BLANK_IMAGE_URL = 'scripts/ext/resources/images/vista/s.gif';
com.faceye.compoents.core.security.RoleVisiteModelPermission={
init:function(roleId){
Ext.QuickTips.init();
if(Ext.getCmp('tree')){
Ext.get('tree-viewer').remove(true);
// Ext.getCmp('tree').destroy(this);
Ext.getBody().createChild({tag:'div',id:'tree-viewer'});
}
var tree;
var root;
// if(!tree){
var Tree = Ext.tree;
tree = new Ext.tree.TreePanel(
{
el:'tree-viewer',
id:'tree',
autoScroll:true,
animate:true,
border:false,
enableDD:true,
containerScroll: true,
rootVisible:false,
loader: new Ext.tree.TreeLoader({
dataUrl:'/faceye/treeAction.do?method=treeWithCheckBoxForPermission&roleId='+roleId
// uiProviders:{
// 'col': Ext.ux.CheckColumnNodeUI
// }
})
// columns:[{
//// header:'node',
// dataIndex:'name'
// }]
//
}
);
//Defint node click event,when node is clicked,send data to inner 'div' and show data in
// set the root node
root = new Tree.AsyncTreeNode({
text: 'Common Platform',
draggable:false,
id:'source',
checked:true
// uiProvider: Ext.tree.CheckboxNodeUI
});
tree.setRootNode(root);
/**
*Open node URL in a target contanier
*/
//全部展開
tree.expandAll();
tree.on('checkchange',function(node){
if(!node.isLeaf()){
node.toggle();
}
fireCheckChange(node);
// node.cascade(function(n){
// n.getUI().toggleCheck();
// });

});

/**
* 當fire checkchange時執行
*/
function fireCheckChange(node){
if(node.getUI().isChecked()){
checkedChildrenNodes(node);
checkedParentNodes(node);
}else{
//取得當前節點的所有子節點,包括當前節點
var allChildrenNodes=getAllChildrenNodes(node);
//如果當前節點的所有子節點中,不存在checked=true的節點,那么將當前節點置為checked=false.
//
//如果當前節點有子節點,同時,當前節點checked=false,那么將其所有子節點置為checked=false
for(var i=0;i<allChildrenNodes.length;i++){
if(allChildrenNodes[i].getUI().isChecked()){
allChildrenNodes[i].getUI().toggleCheck();

}
}
unCheckedParentNode(node);
}
}

/**
* 當點擊父節點時
* 將其所有子節點選中
*/
function checkedChildrenNodes(node){
//取得本節點的所有子節點,子節點中包括其自己
var allChildrenNodes=getAllChildrenNodes(node);
if(allChildrenNodes.length>1){
for(var i=0;i<allChildrenNodes.length;i++){
if(!allChildrenNodes[i].getUI().isChecked()){
allChildrenNodes[i].getUI().toggleCheck();
}
}
}
}

/**
* 當當前子節點的父節點的所有子節點中
* 不存在checked=true的子節點時,父節點不被選中
*/
function unCheckedParentNode(currentChildNode){
if(currentChildNode.parentNode){
var parentNode=currentChildNode.parentNode;
//取得本父節點下所有被選中的子節點
//包括本父節點本身
var allCheckedChildrenNodes=getCheckedNodes(parentNode);
if(allCheckedChildrenNodes.length === 1){
parentNode.getUI().toggleCheck();
parentNode.attributes.checked=false;
}
if(parentNode.parentNode){
unCheckedParentNode(parentNode);
}
}
}
/**
* 當點擊子節點時
* 將父節點選中
*/
function checkedParentNodes(node){
//取得本節點的所有父節點,父節點中包括其自己
var allParentNodes=getAllParentNodes(node);
if(allParentNodes.length>1){
for(var i=0;i<allParentNodes.length;i++){
if(!allParentNodes[i].getUI().isChecked()){
allParentNodes[i].getUI().toggleCheck();
}
}
}
}
/**
* 取得所有子節點中checked 為true的節點ID
* 包括本節點
*/
function getCheckedNodesId(node){
var checked = [];
if( node.getUI().isChecked() || node.attributes.checked ) {
// alert('dfdf'+node.childNodes.length);
checked.push(node.id);
if( !node.isLeaf() ) {
for(var i = 0; i < node.childNodes.length; i++ ) {
checked = checked.concat( getCheckedNodesId(node.childNodes[i]) );
}
}
}
return checked;
};
/**
* 取得所有子節點中checked為true的節點(TreeNode)
* 包括本節點
*/
function getCheckedNodes(node){
var checked = [];
if( node.getUI().isChecked() ) {
checked.push(node);
if( !node.isLeaf() ) {
for(var i = 0; i < node.childNodes.length; i++ ) {
checked = checked.concat( getCheckedNodes(node.childNodes[i]) );
}
}
}
return checked;
};

/**
* 取得一個節點的所有子節點
* 包括本節點
*/
function getAllChildrenNodes(node){
var children = [];
children.push(node);
if(!node.isLeaf()){
for(var i=0;i<node.childNodes.length;i++){
children = children.concat(getAllChildrenNodes(node.childNodes[i]));
}
}
return children;
};
/**
* 取得一個節點的所有父節點
*
*/
function getAllParentNodes(node){
var parentNodes=[];
parentNodes.push(node);
if(node.parentNode){
parentNodes = parentNodes.concat(getAllParentNodes(node.parentNode));
}
return parentNodes;
};
/**
* 取得所有checked=true的節點ID
*/

function getAllChecked(){
return getCheckedNodesId(root);
}
tree.on('click', function (node){
if(node.isLeaf()){
// Ext.get('content-iframe').dom.src = node.attributes.link+'&node='+node.id;
//define grid;
return true;
}else{
/**
*open node by single click,not double click.
*/
node.toggle();
}
});

tree.on('dblclick',function(node){
if(node.isLeaf()){
return true;
}else{
node.toggle();
fireCheckChange(node);
// this.fireEvent('checkchange', this.node, true);
}
});
// render the tree
// }

tree.render();
root.expand();
var win=new Ext.Window({
layout:'fit',
//模式窗口
modal:true,
width:450,
height:300,
closeAction:'hide',
plain: true,
// margins:'5 5 5 5',

title:'為角色授權',
buttonAlign:'center',
buttons: [{
text:'確定',
scope:com.faceye.compoents.core.security.SelectRoles,
type:'submit',
disabled:false,
handler:function(){
var checked=getAllChecked().join(',');
Ext.Ajax.request({
url:'/faceye/roleAction.do?method=permission',
failure:function(){
Ext.Msg.alert('角色授權','角色授權失敗!');
win.hide();
},
success:function(){
Ext.Msg.alert('角色授權','角色授權成功!');
win.hide();
},
params:{
treeIds:checked,
roleId:roleId
}
});

}
},{
text: '放棄',
handler: function(){
//   formItemSelector.getForm().reset();
if(win.getComponent('tree')){
// Ext.get('tree-viewer').remove();
// win.destroy();
// win.remove(tree);

}
win.hide();
// win.disable();
// tree.disable();
}
}
]
});

win.add(tree);
win.show();
}
};

[/code]

在帶有復選框的樹形結構處理中,主要需要解決這么幾個問題:
1.我們的樹,是無限級別的
2.當選中父節點時,其所有子節點,包括直接子節點和間接子節點,一并選中
3.當一個節點的所有子節點被取消選中狀態時,其父節點要處于未被選中的狀態.

因為樹向來是子子孫孫無窮盡的一個東西,所以在這里,需要用到比較多的遞歸處理,不管是在腳本方面,還是在后臺代碼里,都需要用到一些遞歸處理,比如我們所提供的方法中:
[code] /** * 取得一個節點的所有父節點 * */ function getAllParentNodes(node){ var parentNodes=[]; parentNodes.push(node); if(node.parentNode){ parentNodes = parentNodes.concat(getAllParentNodes(node.parentNode)); } return parentNodes; }; [/code]
在這里,提供了這樣一樣功能,既:取得當前點擊(選中)節點的所有父節點,這些父節點中,包括直接父節點和間接父節點,也就是說,在這里,會取得當前選中節點的父親節點,父親節點的父親節點....一直到根節點為止.

類似的方法有:
[code] /** * 取得一個節點的所有子節點 * 包括本節點 */ function getAllChildrenNodes(node){ var children = []; children.push(node); if(!node.isLeaf()){ for(var i=0;i<node.childNodes.length;i++){ children = children.concat(getAllChildrenNodes(node.childNodes[i])); } } return children; }; [/code]

這是取得一個節點所有子節點的方法.處理跟上面類似.

通過以上這些處理,我們就可以很方便的處理帶復選框的樹形結構.
而在這里,我們最終真正關心的,是那些被我們選中的節點,于是,我們需要取得所有被選中的節點,在這里我們需要使用另外一個方法:
[code]
/**
* 取得所有子節點中checked為true的節點(TreeNode)
* 包括本節點
*/
function getCheckedNodes(node){
var checked = [];
if( node.getUI().isChecked() ) {
checked.push(node);
if( !node.isLeaf() ) {
for(var i = 0; i < node.childNodes.length; i++ ) {
checked = checked.concat( getCheckedNodes(node.childNodes[i]) );
}
}
}
return checked;
};
[/code]
在這里,我們同樣使用到了遞歸.

同時,我們可以看到,在生成樹的時候,我們使用了這樣一個loader:
[code]
loader: new Ext.tree.TreeLoader({
dataUrl:'/faceye/treeAction.do?method=treeWithCheckBoxForPermission&roleId='+roleId
// uiProviders:{
// 'col': Ext.ux.CheckColumnNodeUI
// }
})
[/code]
這是我們從后臺取數據的方法,同時,要在前臺加入check column
要加入check column,我們需要看以下代碼:
在方法:treeWithCheckBoxForPermission中,我們做了以下操作:
[code]
/**
* 構造帶有checkbox的tree,為角色進行節點授權做準備
* @param mapping
* @param form
* @param request
* @param response
* @return
*/
public ActionForward treeWithCheckBoxForPermission(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
String json = "";
// JSONArray ja=new JSONArray();
String roleId=this.getHttp().getParameter(request, "roleId");
if (super.getHttp().getParameter(request, "node").equals("source")) {
json = this.getTreeService().treeJSONWithCheckBox(roleId);
} else {
String currentNode = super.getHttp().getParameter(request, "node");
json = this.getTreeService().treeJSONWithCheckBox(
this.getTreeService().getTransedTrees(),
currentNode,roleId);
}
super.jsonPrint(response, json);
// return mapping.findForward("system.admin.face");
return null;
}
[/code]
在這里,我們主要對原始的樹形結構進行了處理,在每個節點上面,打上了checkbox標識:
[code] public String treeJSONWithCheckBox(Serializable roleId) { // TODO Auto-generated method stub try { List trees = this.getTransedTrees(); String result = this.treeJSONWithCheckBox(trees, roleId); return result; } catch (Exception e) { log.info(">>>>faceye error in method:treeJSON() is" + e.toString()); return null; } } [/code]

這里最主要的一個方法是:
[code] public String treeJSONWithCheckBox(List source, Serializable roleId) { // TODO Auto-generated method stub if (source == null || source.isEmpty()) { return null; } List roots = this.getRoots(source); Iterator it = roots.iterator(); StringBuffer json = new StringBuffer(); json.append("["); while (it.hasNext()) { Map item = (Map) it.next(); json.append(this.transTree2JSONWithCheckBox(source, item, roleId)); json.append(","); } json.deleteCharAt(json.lastIndexOf(",")); json.append("]"); return json.toString(); } [/code]

在這里,我們調用了最終方法:
[code]
transTree2JSONWithCheckBox
[/code]
對樹結構進行最終處理
[code]
private String transTree2JSONWithCheckBox(List source, Map tree,
Serializable roleId) {
StringBuffer json = new StringBuffer();
json.append("{");
json.append("\"text\":");
json.append("\"");
json.append(tree.get(StringPool.TREE_NAME).toString());
json.append("\"");
json.append(",");
json.append("\"id\":");
json.append("\"");
json.append(tree.get(StringPool.TREE_ID).toString());
json.append("\"");
json.append(",");
json.append("\"leaf\":");
if (this
.isHaveChildren(source, tree.get(StringPool.TREE_ID).toString())) {
json.append("false");
} else {
json.append("true");
}
json.append(",");
json.append("\"cls\":");
json.append("\"file\"");
if (tree.containsKey(StringPool.TREE_ACTION)
&& null != tree.get(StringPool.TREE_ACTION)) {
json.append(",");
json.append("\"link\":");
json.append("\"");
json.append(tree.get(StringPool.TREE_ACTION).toString());
json.append("\"");
} else {
json.append(",");
json.append("\"link\":");
json.append("\"");
json.append("#");
json.append("\"");
}

json.append(",");
json.append("\"checked\":");
// json.append("true");
json.append(this.isNodeChecked(tree.get(StringPool.TREE_ID).toString(),
roleId));

json.append("}");
return json.toString();
}
[/code]
可以看到,我們在這里,加入了:[code]checked:true[/code]這樣的屬性.
至此,可以看到完整的帶有復選框的樹形結構的處理流程,完整代碼,請從 http://code.google.com/p/faceye下載.


付厚俊 2008-10-10 21:43 發表評論
]]>
使用Eclipse+spket開發Spket的安裝http://www.tkk7.com/fuhoujun/archive/2008/10/07/232881.html付厚俊付厚俊Tue, 07 Oct 2008 04:11:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/07/232881.htmlhttp://www.tkk7.com/fuhoujun/comments/232881.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/07/232881.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232881.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232881.html1、Plugin:
最低要求: eclipse平臺運行時3.2.x ,
文件為: spket-1.6.4.1.zip(與別的插件的安裝無異,相信不用我多說了吧
2、Spket IDE:
最低要求:你需要java 1.5或更高版本運行安裝程序,可獨立使用(不用裝Eclipse
文件為:spket-1.6.4.1.jar
安裝步驟:1、打開cmd,2、在spket-1.6.4.1.jar文件目錄下輸入java -jar spket-1.6.4.1.jar2、Spket IDE:
最低要求:你需要java 1.5或更高版本運行安裝程序,可獨立使用(不用裝Eclipse
文件為:spket-1.6.4.1.jar
安裝步驟:1、打開cmd,2、在spket-1.6.4.1.jar文件目錄下輸入java -jar spket-1.6.4.1.jar

二、使用

安裝完后你去試,發現沒有用,其實還有一些操作如下:

1、執行這個操作:Window → Preferences → Spket → JavaScript Profiles → New

2、在彈出框中輸入ExtJs,然后點OK。

3、然后選擇ExtJs點Add Library,把你下載的ext包中找到/source/ext.jsb加載進來

4、然后先中ExtJs點擊右邊的default按鈕.

5、然后點擊確定就搞定。你現在有eclipse中建立一個JS用Ext.就會出現提示咯!!!



付厚俊 2008-10-07 12:11 發表評論
]]>
Ext Form布局http://www.tkk7.com/fuhoujun/archive/2008/10/07/232879.html付厚俊付厚俊Tue, 07 Oct 2008 03:51:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/07/232879.htmlhttp://www.tkk7.com/fuhoujun/comments/232879.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/07/232879.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232879.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232879.html
現在我們要實現的效果是:點擊確定,把值傳到另一頁面!,如下:

原頁面js代碼為:
Ext.onReady(function(){
  Ext.QuickTips.init();
 
var form=new Ext.FormPanel({
    frame:
true,
    width:
300,
   
//monitorValid:true,//綁定驗證
    layout:"form",
    labelWidth:
70,
    title:
"添加個人信息",
    labelAlign:
"left",
    renderTo:Ext.getBody(),
    submit:
function(){
                   
this.getEl().dom.action =
'GetForm.aspx',
                   
this.getEl().dom.method='POST',
                   
this.getEl().dom.submit();
              },
    items:[{
              xtype:
"textfield",
              fieldLabel:
"用戶名",
             
//id:"UserName",
              allowBlank:false,
              blankText:
"不能為空,請正確填寫",
              name:
"UserName",
              anchor:
"90%"
          },{
              xtype:
"textfield",
              fieldLabel:
"昵稱",
             
//id:"SmallName",
              name:"SmallName",
              anchor:
"90%"
          },{
              xtype:
"datefield",
              fieldLabel:
"注冊日期",
             
//id:"RegDate",
              name:"RegDate",
              anchor:
"90%"
          }],
     
});
接受頁面GetForm.aspx的cs代碼為:
protected
void Page_Load(object sender, EventArgs e)
    {
       
string UserName = Request.Form["UserName"];
       
string SmallName = Request.Form["SmallName"];
       
string RegDate = Request.Form["RegDate"];

        Response.Write(UserName
+
"<br/>"
+ SmallName +
"<br/>"
+ RegDate);
    }

因為很簡單,我做個簡要說明: //幾點說明
1.首先定義submit參數的執行函數,即:
  submit:
function(){
                   
this.getEl().dom.action =
'GetForm.aspx',//轉向頁面地址

this.getEl().dom.method='POST',//方式

this.getEl().dom.submit();//提交!
              },
2.為按鈕添加觸發相應的提交(取消)事件(這樣就不是默認的ajax提交):
  buttons:[{text:
"確定",handler:login,formBind:true},{text:"取消",handler:reset}]
  });
 
function login(){
        form.form.submit();
//提交
  }
 
function reset(){
        form.form.reset();
//取消
  }
3.如果你想綁定驗證,在form表單添加參數monitorValid:true,然后在按鈕配置參數中添加formBind:true,如
      buttons:[{text:
"確定",handler:login,formBind:true},{text:"取消",handler:reset}]
則只有所有的填寫字段都滿足條件時,
"確定"方可提交!如下圖,


好了,一個簡單的formpanel的提交的原理弄清楚啦!
有關form提交數據的方法有多種,大家可以參考http://www.17ext.com/showtopic-55.aspx(三種ext提交數據的方式),
以后有機會我們再討論!
下面我們來做個復雜點(只是樣子)的form,示例一下(還是上面的原理)!
效果圖:

傳到GetForm.aspx頁面后顯示:

不過在傳過來的頁面要記得ValidateRequest="false",安全編碼我就暫且不討論了!
js代碼:

Ext.onReady(function(){
  Ext.QuickTips.init();
 
var form=new Ext.FormPanel({
    frame:
true,
    width:
500,
    monitorValid:
true,//把有formBind:true的按鈕和驗證綁定
    layout:"form",
    labelWidth:
55,
    title:
"添加個人信息",
    labelAlign:
"right",
    renderTo:Ext.getBody(),
    submit:
function(){
                   
this.getEl().dom.action =
'GetForm.aspx',
                   
this.getEl().dom.method='POST',
                   
this.getEl().dom.submit();
              },
    items:[{
              xtype:
"panel",
              layout:
"column",
              fieldLabel:
"用戶名",
              isFormField:
true,
              items:[{
                        columnWidth:.
5,
                        xtype:
"textfield",
                        allowBlank:
false,
                        blankText:
"不能為空,請填寫",
                        name:
"UserName",
                        anchor:
"90%"
              },{
                        columnWidth:.
20,
                        layout:
"form",
                        labelWidth:
40,
                        labelAlign:
"right",
                        items:[{
                                  xtype:
"radio",
                                  fieldLabel:
"性別",
                                  boxLabel:
"",
                                  name:
"Sex",
                                  checked:
true,
                                  inputValue:
"man",//這里如果用value,值是on,所以用inputValue(出現這種情況的是radio,checkbox)
                                  anchor:"95%"
                        }]
              },{
                        columnWidth:.
30,
                        layout:
"form",
                        labelWidth:
1,//讓標簽寬度為很小的值(奇怪的是為0時反而不行)
                        items:[{
                                  xtype:
"radio",
                                  boxLabel:
"",
                                  labelSeparator:
"",//去除分隔符“:”
                                  name:"Sex",
                                  inputValue:
"woman",
                                  anchor:
"95%"
                        }]
              }]
    },{
//上面是第一行
              xtype:"panel",
              layout:
"column",
              fieldLabel:
"出生日期",
              isFormField:
true,
              items:[{
                        columnWidth:.
5,
                        xtype:
"datefield",
                        name:
"BirthDate",
                        anchor:
"90%"
              },{
                        columnWidth:.
5,
                        layout:
"form",
                        labelWidth:
40,//注意,這個參數在這里可以調整簡單fieldLabel的布局位置
                        items:[{
                                  xtype:
"combo",
                                  name:
"Degree",
                                  fieldLabel:
"學位",
                                  store:[
"小學","初中","高中","專科","本科","碩士","博士"],
                                  emptyText:
"請選擇適合你的學歷",
                                  anchor:
"90%"
                        }]
              }]
    },{
//上面是第二行
              xtype:"panel",
              layout:
"column",
              isFormField:
true,
              fieldLabel:
"使用框架",
              items:[{
                        columnWidth:.
2,
                        xtype:
"checkbox",
                        boxLabel:
"Spring.net",
                        name:
"SpringNet",
                        inputValue:
"spring"//這里如果用value,值是on,所以用inputValue
              },{
                        columnWidth:.
2,
                        layout:
"form",
                        labelWidth:
1,
                        items:[{
                                  xtype:
"checkbox",
                                  boxLabel:
"Nhibernate",
                                  labelSeparator:
"",
                                  name:
"NHibernate",
                                  inputValue:
"nhibernate",
                                  anchor:
"95%"
                        }]
              },{
                        columnWidth:.
6,
                        layout:
"form",
                        labelWidth:
1,
                        items:[{
                                  xtype:
"checkbox",
                                  boxLabel:
"Linq",
                                  labelSeparator:
"",
                                  name:
"Linq",
                                  inputValue:
"linq",
                                  anchor:
"95%"
                        }]
              }]
             
    },{
//上面是第三行
              xtype:"textfield",
              fieldLabel:
"Email",
              name:
"Email",
              vtype:
"email",//email驗證,如果想自定義驗證的話,請參見前面的文章
              vtypeText:"email格式錯誤!",
              anchor:
"56%"//控制文本框的長度
             
    },{
//上面是第四行
              xtype:"textarea",
              fieldLabel:
"個性簽名",
              name:
"OneWord",
              height:
50,
              anchor:
"95%"
    },{
//上面是第五行
              xtype:"htmleditor",
              fieldLabel:
"想說的話",
              name:
"WantToSay",
              anchor:
"95%",
              enableAlignments:
false,//去除左右對齊工具欄
              enableLists:false//去除列表工具欄
    }],
      buttons:[{text:
"確定",handler:login,formBind:true},{text:"取消",handler:reset}]
  });
 
function login(){
        form.form.submit();
  }
 
function reset(){
        form.form.reset();
  }
});



付厚俊 2008-10-07 11:51 發表評論
]]>
Ext2 常見界面界面(grid分頁、窗口布局、下拉框級聯) http://www.tkk7.com/fuhoujun/archive/2008/10/05/232437.html付厚俊付厚俊Sat, 04 Oct 2008 19:00:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/05/232437.htmlhttp://www.tkk7.com/fuhoujun/comments/232437.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/05/232437.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232437.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232437.html閱讀全文

付厚俊 2008-10-05 03:00 發表評論
]]>
帶復選框(checkbox)的樹http://www.tkk7.com/fuhoujun/archive/2008/10/04/232378.html付厚俊付厚俊Sat, 04 Oct 2008 12:22:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232378.htmlhttp://www.tkk7.com/fuhoujun/comments/232378.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232378.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232378.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232378.html官方實例中有介紹如何將json數據變成一棵樹的簡單例子
該例子可以滿足我們的一般需求。很多時候我們需要用到帶checkbox的樹。
其實加個checkbox框先簡單,只需要在返回來的json數據中加上 checked 項(為true/false)。要實現我們想要的選中父節點的checkbox后,自動選中子節點也很簡單,只需要加上下面這一段代碼就可以了。

  1. tree.on('checkchange'function(node, checked) {      
  2.         node.expand();      
  3.         node.attributes.checked = checked;      
  4.         node.eachChild(function(child) {      
  5.             child.ui.toggleCheck(checked);      
  6.             child.attributes.checked = checked;      
  7.             child.fireEvent('checkchange', child, checked);      
  8.         });      
  9.     }, tree);   

 

演示(demo)地址在文章最后.

效果圖如下:

源代碼包括 0005_checkbox_reorder.html,0005_checkbox_reorder_tree.php.

0005_checkbox_reorder.html

  1. <html>   
  2. <head>   
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">   
  4. <title>帶復選框(checkbox)的樹</title>   
  5. <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />   
  6. <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>   
  7. <script type="text/javascript" src="../../ext-all.js"></script>   
  8. <link rel="stylesheet" type="text/css" href="../../examples/examples.css" />   
  9. <script type="text/javascript" src="../../examples.js"></script>   
  10. <script type="text/javascript">   
  11. Ext.onReady(function(){   
  12.     Ext.BLANK_IMAGE_URL = "../../resources/images/default/s.gif"       
  13.     // shorthand   
  14.     var Tree = Ext.tree;   
  15.        
  16.     var tree = new Tree.TreePanel({   
  17.         el:'tree-div',   
  18.         useArrows:true,   
  19.         autoScroll:true,   
  20.         animate:true,   
  21.         enableDD:true,   
  22.         containerScroll: true,    
  23.         loader: new Tree.TreeLoader({   
  24.             dataUrl:'0005_checkbox_reorder_tree.php'  
  25.         })   
  26.     });   
  27.        
  28.     tree.on('checkchange'function(node, checked) {      
  29.         node.expand();      
  30.         node.attributes.checked = checked;      
  31.         node.eachChild(function(child) {      
  32.             child.ui.toggleCheck(checked);      
  33.             child.attributes.checked = checked;      
  34.             child.fireEvent('checkchange', child, checked);      
  35.         });      
  36.     }, tree);     
  37.   
  38.     // set the root node   
  39.     var root = new Tree.AsyncTreeNode({   
  40.         text: 'Ext JS',   
  41.         draggable:false,   
  42.         id:'source'  
  43.     });   
  44.     tree.setRootNode(root);   
  45.   
  46.     // render the tree   
  47.     tree.render();   
  48.     root.expand();   
  49. });   
  50. </script>   
  51.   
  52. </head>   
  53. <body>   
  54. <h1>帶復選框(checkbox)的樹</h1>   
  55. <p></p>   
  56. <p>改編自ExtJs 自帶的tree例子,選中父節點后,所有子節點會自動選上。</p>   
  57.   
  58. <p>該例子點擊父節點如果速度過快,有時候不會自動選中子節點! </p>   
  59.   
  60. <div id="tree-div" style="overflow:auto; height:300px;width:250px;border:1px solid #c3daf9;"></div>   
  61.   
  62. </body>   
  63. </html>  


付厚俊 2008-10-04 20:22 發表評論
]]>
EXT2.0 checkbox樹的擴展(支持單選,級聯多選,只選葉子等)http://www.tkk7.com/fuhoujun/archive/2008/10/04/232363.html付厚俊付厚俊Sat, 04 Oct 2008 11:32:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232363.htmlhttp://www.tkk7.com/fuhoujun/comments/232363.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232363.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232363.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232363.html在ext1.x里,樹是沒有checkbox的, 幸好在2.X版本里提供了這個功能, 在許多應用里, 帶有checkbox的樹使用還是很常見的

 

Ext2.X提供了簡單的checkbox實現,但對于一些復雜的需求,如: 級聯多選(選中父結點,自選中其所有子結點和所有父結點) , 單選等等, Ext2.X并沒有幫我們實現

 

還有最難解決的情況, 當樹是異步的時候, 要想級聯多選, 實現起來有些難度

 

在此, 通過對Ext.tree.TreeNodeUI進行擴展,這些問題都得到很好的解決

 

Js代碼 復制代碼
  1. /**  
  2.  * @class Ext.tree.TreeCheckNodeUI  
  3.  * @extends Ext.tree.TreeNodeUI  
  4.  *   
  5.  * 對 Ext.tree.TreeNodeUI 進行checkbox功能的擴展,后臺返回的結點信息不用非要包含checked屬性  
  6.  *   
  7.  * 擴展的功能點有:  
  8.  * 一、支持只對樹的葉子進行選擇  
  9.  *    只有當返回的樹結點屬性leaf = true 時,結點才有checkbox可選  
  10.  *    使用時,只需在聲明樹時,加上屬性 onlyLeafCheckable: true 既可,默認是false  
  11.  *   
  12.  * 二、支持對樹的單選  
  13.  *    只允許選擇一個結點  
  14.  *    使用時,只需在聲明樹時,加上屬性 checkModel: "single" 既可  
  15.  *   
  16.  * 二、支持對樹的級聯多選   
  17.  *    當選擇結點時,自動選擇該結點下的所有子結點,以及該結點的所有父結點(根結點除外),特別是支持異步,當子結點還沒顯示時,會從后臺取得子結點,然后將其選中/取消選中  
  18.  *    使用時,只需在聲明樹時,加上屬性 checkModel: "cascade" 既可  
  19.  *   
  20.  * 三、添加"check"事件  
  21.  *    該事件會在樹結點的checkbox發生改變時觸發  
  22.  *    使用時,只需給樹注冊事件,如:  
  23.  *    tree.on("check",function(node,checked){...});  
  24.  *   
  25.  * 默認情況下,checkModel為'multiple',也就是多選,onlyLeafCheckable為false,所有結點都可選  
  26.  *   
  27.  * 使用方法:在loader里加上 baseAttrs:{uiProvider:Ext.tree.TreeCheckNodeUI} 既可.  
  28.  * 例如:  
  29.  *   var tree = new Ext.tree.TreePanel({  
  30.  *      el:'tree-ct',  
  31.  *      width:568,  
  32.  *      height:300,  
  33.  *      checkModel: 'cascade',   //對樹的級聯多選  
  34.  *      onlyLeafCheckable: false,//對樹所有結點都可選  
  35.  *      animate: false,  
  36.  *      rootVisible: false,  
  37.  *      autoScroll:true,  
  38.  *      loader: new Ext.tree.DWRTreeLoader({  
  39.  *          dwrCall:Tmplt.getTmpltTree,  
  40.  *          baseAttrs: { uiProvider: Ext.tree.TreeCheckNodeUI } //添加 uiProvider 屬性  
  41.  *      }),  
  42.  *      root: new Ext.tree.AsyncTreeNode({ id:'0' })  
  43.  *  });  
  44.  *  tree.on("check",function(node,checked){alert(node.text+" = "+checked)}); //注冊"check"事件  
  45.  *  tree.render();  
  46.  *   
  47.  */  
  48.   
  49. Ext.tree.TreeCheckNodeUI = function() {   
  50.     //'multiple':多選; 'single':單選; 'cascade':級聯多選   
  51.     this.checkModel = 'multiple';   
  52.        
  53.     //only leaf can checked   
  54.     this.onlyLeafCheckable = false;   
  55.        
  56.     Ext.tree.TreeCheckNodeUI.superclass.constructor.apply(this, arguments);   
  57. };   
  58.   
  59. Ext.extend(Ext.tree.TreeCheckNodeUI, Ext.tree.TreeNodeUI, {   
  60.   
  61.     renderElements : function(n, a, targetNode, bulkRender){   
  62.         var tree = n.getOwnerTree();   
  63.         this.checkModel = tree.checkModel || this.checkModel;   
  64.         this.onlyLeafCheckable = tree.onlyLeafCheckable || false;   
  65.            
  66.         // add some indent caching, this helps performance when rendering a large tree   
  67.         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';   
  68.   
  69.     var cb = (!this.onlyLeafCheckable || a.leaf);   
  70.         var href = a.href ? a.href : Ext.isGecko ? "" : "#";   
  71.         var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',   
  72.             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",   
  73.             '<img src="'this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',   
  74.             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',   
  75.             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',   
  76.             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',   
  77.              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : ""'><span unselectable="on">',n.text,"</span></a></div>",   
  78.             '<ul class="x-tree-node-ct" style="display:none;"></ul>',   
  79.             "</li>"].join('');   
  80.   
  81.         var nel;   
  82.         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){   
  83.             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);   
  84.         }else{   
  85.             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);   
  86.         }   
  87.            
  88.         this.elNode = this.wrap.childNodes[0];   
  89.         this.ctNode = this.wrap.childNodes[1];   
  90.         var cs = this.elNode.childNodes;   
  91.         this.indentNode = cs[0];   
  92.         this.ecNode = cs[1];   
  93.         this.iconNode = cs[2];   
  94.         var index = 3;   
  95.         if(cb){   
  96.             this.checkbox = cs[3];   
  97.             Ext.fly(this.checkbox).on('click'this.check.createDelegate(this,[null]));   
  98.             index++;   
  99.         }   
  100.         this.anchor = cs[index];   
  101.         this.textNode = cs[index].firstChild;   
  102.     },   
  103.        
  104.     // private   
  105.     check : function(checked){   
  106.         var n = this.node;   
  107.         var tree = n.getOwnerTree();   
  108.         this.checkModel = tree.checkModel || this.checkModel;   
  109.            
  110.         if( checked === null ) {   
  111.             checked = this.checkbox.checked;   
  112.         } else {   
  113.             this.checkbox.checked = checked;   
  114.         }   
  115.            
  116.         n.attributes.checked = checked;   
  117.         tree.fireEvent('check', n, checked);   
  118.            
  119.         if(!this.onlyLeafCheckable && this.checkModel == 'cascade'){   
  120.             var parentNode = n.parentNode;   
  121.             if(parentNode !== null) {   
  122.                 this.parentCheck(parentNode,checked);   
  123.             }   
  124.             if( !n.expanded && !n.childrenRendered ) {   
  125.                 n.expand(false,false,this.childCheck);   
  126.             }   
  127.             else {   
  128.                 this.childCheck(n);   
  129.             }   
  130.         }else if(this.checkModel == 'single'){   
  131.             var checkedNodes = tree.getChecked();   
  132.             for(var i=0;i<checkedNodes.length;i++){   
  133.                 var node = checkedNodes[i];   
  134.                 if(node.id != n.id){   
  135.                     node.getUI().checkbox.checked = false;   
  136.                     node.attributes.checked = false;   
  137.                     tree.fireEvent('check', node, false);   
  138.                 }   
  139.             }   
  140.         }   
  141.            
  142.     },   
  143.        
  144.     // private   
  145.     childCheck : function(node){   
  146.         var a = node.attributes;   
  147.         if(!a.leaf) {   
  148.             var cs = node.childNodes;   
  149.             var csui;   
  150.             for(var i = 0; i < cs.length; i++) {   
  151.                 csui = cs[i].getUI();   
  152.                 if(csui.checkbox.checked ^ a.checked)   
  153.                     csui.check(a.checked);   
  154.             }   
  155.         }   
  156.     },   
  157.        
  158.     // private   
  159.     parentCheck : function(node ,checked){   
  160.         var checkbox = node.getUI().checkbox;   
  161.         if(typeof checkbox == 'undefined')return ;   
  162.         if(!(checked ^ checkbox.checked))return;   
  163.         if(!checked && this.childHasChecked(node))return;   
  164.         checkbox.checked = checked;   
  165.         node.attributes.checked = checked;   
  166.         node.getOwnerTree().fireEvent('check', node, checked);   
  167.            
  168.         var parentNode = node.parentNode;   
  169.         if( parentNode !== null){   
  170.             this.parentCheck(parentNode,checked);   
  171.         }   
  172.     },   
  173.        
  174.     // private   
  175.     childHasChecked : function(node){   
  176.         var childNodes = node.childNodes;   
  177.         if(childNodes || childNodes.length>0){   
  178.             for(var i=0;i<childNodes.length;i++){   
  179.                 if(childNodes[i].getUI().checkbox.checked)   
  180.                     return true;   
  181.             }   
  182.         }   
  183.         return false;   
  184.     },   
  185.        
  186.     toggleCheck : function(value){   
  187.         var cb = this.checkbox;   
  188.         if(cb){   
  189.             var checked = (value === undefined ? !cb.checked : value);   
  190.             this.check(checked);   
  191.         }   
  192.     }   
  193. });  
/**
* @class Ext.tree.TreeCheckNodeUI
* @extends Ext.tree.TreeNodeUI
*
* 對 Ext.tree.TreeNodeUI 進行checkbox功能的擴展,后臺返回的結點信息不用非要包含checked屬性
*
* 擴展的功能點有:
* 一、支持只對樹的葉子進行選擇
*    只有當返回的樹結點屬性leaf = true 時,結點才有checkbox可選
*    使用時,只需在聲明樹時,加上屬性 onlyLeafCheckable: true 既可,默認是false
*
* 二、支持對樹的單選
*    只允許選擇一個結點
*    使用時,只需在聲明樹時,加上屬性 checkModel: "single" 既可
*
* 二、支持對樹的級聯多選
*    當選擇結點時,自動選擇該結點下的所有子結點,以及該結點的所有父結點(根結點除外),特別是支持異步,當子結點還沒顯示時,會從后臺取得子結點,然后將其選中/取消選中
*    使用時,只需在聲明樹時,加上屬性 checkModel: "cascade" 既可
*
* 三、添加"check"事件
*    該事件會在樹結點的checkbox發生改變時觸發
*    使用時,只需給樹注冊事件,如:
*    tree.on("check",function(node,checked){...});
*
* 默認情況下,checkModel為'multiple',也就是多選,onlyLeafCheckable為false,所有結點都可選
*
* 使用方法:在loader里加上 baseAttrs:{uiProvider:Ext.tree.TreeCheckNodeUI} 既可.
* 例如:
*   var tree = new Ext.tree.TreePanel({
*  el:'tree-ct',
*  width:568,
*  height:300,
*  checkModel: 'cascade',   //對樹的級聯多選
*  onlyLeafCheckable: false,//對樹所有結點都可選
*  animate: false,
*  rootVisible: false,
*  autoScroll:true,
*  loader: new Ext.tree.DWRTreeLoader({
*   dwrCall:Tmplt.getTmpltTree,
*   baseAttrs: { uiProvider: Ext.tree.TreeCheckNodeUI } //添加 uiProvider 屬性
*  }),
*  root: new Ext.tree.AsyncTreeNode({ id:'0' })
* });
* tree.on("check",function(node,checked){alert(node.text+" = "+checked)}); //注冊"check"事件
* tree.render();
*
*/
Ext.tree.TreeCheckNodeUI = function() {
//'multiple':多選; 'single':單選; 'cascade':級聯多選
this.checkModel = 'multiple';
//only leaf can checked
this.onlyLeafCheckable = false;
Ext.tree.TreeCheckNodeUI.superclass.constructor.apply(this, arguments);
};
Ext.extend(Ext.tree.TreeCheckNodeUI, Ext.tree.TreeNodeUI, {
renderElements : function(n, a, targetNode, bulkRender){
var tree = n.getOwnerTree();
this.checkModel = tree.checkModel || this.checkModel;
this.onlyLeafCheckable = tree.onlyLeafCheckable || false;
// add some indent caching, this helps performance when rendering a large tree
this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
var cb = (!this.onlyLeafCheckable || a.leaf);
var href = a.href ? a.href : Ext.isGecko ? "" : "#";
var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
'<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
'<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
'<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
'<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
'<ul class="x-tree-node-ct" style="display:none;"></ul>',
"</li>"].join('');
var nel;
if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
}else{
this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
}
this.elNode = this.wrap.childNodes[0];
this.ctNode = this.wrap.childNodes[1];
var cs = this.elNode.childNodes;
this.indentNode = cs[0];
this.ecNode = cs[1];
this.iconNode = cs[2];
var index = 3;
if(cb){
this.checkbox = cs[3];
Ext.fly(this.checkbox).on('click', this.check.createDelegate(this,[null]));
index++;
}
this.anchor = cs[index];
this.textNode = cs[index].firstChild;
},
// private
check : function(checked){
var n = this.node;
var tree = n.getOwnerTree();
this.checkModel = tree.checkModel || this.checkModel;
if( checked === null ) {
checked = this.checkbox.checked;
} else {
this.checkbox.checked = checked;
}
n.attributes.checked = checked;
tree.fireEvent('check', n, checked);
if(!this.onlyLeafCheckable && this.checkModel == 'cascade'){
var parentNode = n.parentNode;
if(parentNode !== null) {
this.parentCheck(parentNode,checked);
}
if( !n.expanded && !n.childrenRendered ) {
n.expand(false,false,this.childCheck);
}
else {
this.childCheck(n);
}
}else if(this.checkModel == 'single'){
var checkedNodes = tree.getChecked();
for(var i=0;i<checkedNodes.length;i++){
var node = checkedNodes[i];
if(node.id != n.id){
node.getUI().checkbox.checked = false;
node.attributes.checked = false;
tree.fireEvent('check', node, false);
}
}
}
},
// private
childCheck : function(node){
var a = node.attributes;
if(!a.leaf) {
var cs = node.childNodes;
var csui;
for(var i = 0; i < cs.length; i++) {
csui = cs[i].getUI();
if(csui.checkbox.checked ^ a.checked)
csui.check(a.checked);
}
}
},
// private
parentCheck : function(node ,checked){
var checkbox = node.getUI().checkbox;
if(typeof checkbox == 'undefined')return ;
if(!(checked ^ checkbox.checked))return;
if(!checked && this.childHasChecked(node))return;
checkbox.checked = checked;
node.attributes.checked = checked;
node.getOwnerTree().fireEvent('check', node, checked);
var parentNode = node.parentNode;
if( parentNode !== null){
this.parentCheck(parentNode,checked);
}
},
// private
childHasChecked : function(node){
var childNodes = node.childNodes;
if(childNodes || childNodes.length>0){
for(var i=0;i<childNodes.length;i++){
if(childNodes[i].getUI().checkbox.checked)
return true;
}
}
return false;
},
toggleCheck : function(value){
var cb = this.checkbox;
if(cb){
var checked = (value === undefined ? !cb.checked : value);
this.check(checked);
}
}
});

 



付厚俊 2008-10-04 19:32 發表評論
]]>
ext2的樹組件的使用(從底層到表現層,異步加載)http://www.tkk7.com/fuhoujun/archive/2008/10/04/232360.html付厚俊付厚俊Sat, 04 Oct 2008 11:28:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232360.htmlhttp://www.tkk7.com/fuhoujun/comments/232360.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232360.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232360.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232360.htmljs 代碼
  1. var Tree = Ext.tree;   
  2.       
  3.    var tree = new Tree.TreePanel({   
  4.        el:'tree',   
  5.        autoScroll:true,   
  6.        animate:true,   
  7.        enableDD:true,   
  8.        containerScroll: true,    
  9.        loader: new Tree.TreeLoader({   
  10.            dataUrl:'moduletree.do'   
  11.        })   
  12.    });   
  13.   
  14.    // set the root node   
  15.    var root = new Tree.AsyncTreeNode({   
  16.        text: '管轄單位',   
  17.        draggable:false,   
  18.        id:'source'   
  19.    });   
  20.    tree.setRootNode(root);   
  21.   
  22.    // render the tree   
  23.    tree.render();   
  24.    root.expand();  

el決定了樹的顯示位置,一般是個div例如

 

dataUrl決定了樹的json數據來源,我這里是一個struts的action,這個action會輸出json數據

 

在服務層要提供一個可以生成json格式數據的service,struts的任務是獲取傳來的參數調用service方法輸出json

我在服務層生成json數據用的是jsonlib包,論壇有詳細介紹的帖子,就不多說了

數據庫有兩個表來構建樹,一個是樹的節點表,至少包括樹的id name 我這里還有一個haschild,代表有沒有子節點。

另一個是節點關系表,兩列分別是父節點和他對應的子節點。

service層調用dao的方法將結果集組裝成List或者Map,再用jsonlib包提供的api將list轉化成json,例如

js 代碼
  1. //根據用戶的角色和id生成用戶的管轄單位樹   
  2. public List getsubdept(String userid,Long roleid){   
  3.         try{   
  4. //調用dao的方法查找到結果集   
  5.         List list=roledeptdao.findRoledept(userid, roleid);   
  6. //生成json所使用的單位list   
  7.         List deptlist=new ArrayList();   
  8.         Iterator it=list.iterator();   
  9.         while(it.hasNext()){   
  10.             Ruledept rd=(Ruledept) it.next();   
  11.             Map tree = new HashMap();   
  12. //節點顯示單位名              
  13. tree.put("text", rd.getId().getTYwxtDept().getDeptName());   
  14. //節點的id    
  15.         tree.put("id", rd.getId().getTYwxtDept().getDeptId());   
  16.             Object value = new Object();   
  17.             value = Boolean.TRUE;   
  18.             tree.put("cls""file");   
  19. //是否是葉子節點,我這里只有一層所以直接寫的TRUE   
  20.             tree.put("leaf", value);   
  21. //將這個生成葉子節點對應的MAP加到單位list里   
  22.             deptlist.add(tree);   
  23.         }   
  24.            
  25.         return deptlist;   
  26.         }catch(Exception e){   
  27.             log.error("獲取單位列表失敗"+e.getMessage());   
  28.             return null;   
  29.         }   
  30.            
  31.     }   
  32.   
  33.     public JSONArray getmoduletree(String userid, String roleid) {   
  34.         List list=this.getsubdept(userid, new Long(roleid));   
  35.         if(list==null){   
  36.             return null;   
  37.         }   
  38. //轉換這個list讓他變成json格式       
  39.     JSONArray jsonArray = JSONArray.fromObject(list);   
  40.         return jsonArray;   
  41.     }  

在action里面調用這個service方法:

java 代碼
  1. public ActionForward execute(ActionMapping mapping, ActionForm form,   
  2.             HttpServletRequest request, HttpServletResponse response) {   
  3.   
  4.         HttpSession httpsession=request.getSession();   
  5.         String roleid=(String) httpsession.getAttribute("role");   
  6.         UserInfo userinfo=(UserInfo)httpsession.getAttribute("userinfo");   
  7.         String userid=userinfo.getUserID();   
  8.         JSONArray jsonArray=this.getRoledeptservice().getmoduletree(userid, roleid);   
  9.         response.setContentType("text/json; charset=GBK");    
  10.             try {   
  11.                 response.getWriter().print(jsonArray);   
  12.             } catch (IOException e) {   
  13.                 log.error("輸出json失敗"+e.getMessage());   
  14.                 return null;   
  15.             }   
  16.        
  17.     return null;   
  18.     }  

 

這樣一個完整的樹就生成了,現在這個樹是只有兩層,如果是多層的就需要修改service方法來遞歸構造一個樹的list再轉化成json。

異步讀取節點:首先,底層的service方法要做到每次生成的是傳入參數的下一級節點的list,然后在js的 tree.setRootNode(root);下面加上這句:js 代碼

  1. tree.on('beforeload', function(node){   
  2. tree.loader.dataUrl = 'createTree.do?id='+node.id;   
  3. });  

 

tree.loader.dataUrl 的值需要返回的就是該節點id的下一級的json數據

數據量大的時候異步加載要好的多,服務層也代碼比起一次性全部加載的反復遞歸調用省不少。



付厚俊 2008-10-04 19:28 發表評論
]]>
用Ext做的后臺操作(包括,增,刪,改,查)和一個異步加載的Ext樹http://www.tkk7.com/fuhoujun/archive/2008/10/04/232357.html付厚俊付厚俊Sat, 04 Oct 2008 11:12:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232357.htmlhttp://www.tkk7.com/fuhoujun/comments/232357.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232357.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232357.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232357.html
  •     
  • function createField(fieldLabel, id, name1, value) {   
  •   
  •     var field = new Ext.form.TextField({   
  •         fieldLabel : fieldLabel,   
  •         width : 380,   
  •         itemCls : 'all-field',   
  •         clearCls : 'allow-float',   
  •         allowBlank : false,   
  •         name : name1,   
  •         value : value   
  •     });   
  •   
  •     return field;   
  •   
  • }   
  • function saveHandler(win, requestUrl, node, formPanel, isUpdate) {   
  •     /*  
  •      * Ext.MessageBox.show({ title:'請稍候', msg:'保存中,請稍后...', progress:true,  
  •      * buttons: {cancel:'取消'} });  
  •      */  
  •   
  •     var form = formPanel.getForm();   
  •     form.submit({   
  •         url : requestUrl,   
  •         waitMsg : '保存中,請稍候...',   
  •         params : {},   
  •         success : function(response, request) {   
  •             if (!isUpdate) {   
  •                 Ext.MessageBox.confirm("狀態""保存成功,繼續添加嗎?", function(btn) {   
  •                     if (btn != 'yes') {   
  •                         win.close();   
  •                     }   
  •   
  •                 });   
  •             } else {   
  •                 Ext.MessageBox.alert('狀態''保存成功!');   
  •                 win.close();   
  •             }   
  •   
  •             if (node.isLeaf()) {   
  •                 var root = node.getOwnerTree().root;   
  •                 root.reload();   
  •                 root.expand(truetrue);   
  •             } else {   
  •                 var root = node.getOwnerTree().root;   
  •                 root.reload();   
  •                 root.expand(truetrue);   
  •             }   
  •         },   
  •         failure : function() {   
  •             Ext.MessageBox.alert('狀態''保存失敗!');   
  •             if (node.isLeaf()) {   
  •                 var root = node.getOwnerTree().root;   
  •                 root.reload();   
  •                 root.expand(truetrue);   
  •             } else {   
  •                 var root = node.getOwnerTree().root;   
  •                 root.reload();   
  •                 root.expand(truetrue);   
  •             }   
  •         }   
  •   
  •     });   
  • }   
  • // 修改form   
  • function updateForm(node, id, title, win, requestUrl, value, isUpdate) {   
  •     var form0 = new Ext.FormPanel({   
  •         id : id,   
  •         labelWidth : 75// label settings here cascade unless overridden   
  •         frame : true,   
  •         title : title,   
  •         bodyStyle : 'padding:5px 5px 0',   
  •         width : 350,   
  •         defaults : {   
  •             width : 230  
  •         }   
  •   
  •     });   
  •     var nameField = createField('章節名稱''createItemText' + id + node.id,   
  •             'name', value);   
  •   
  •     form0.add(nameField);   
  •     form0.addButton({   
  •         text : '保存',   
  •         handler : function() {   
  •             saveHandler(win, requestUrl, node, form0, isUpdate);   
  •         }   
  •     });   
  •     return form0;   
  • }   
  • // 創建form   
  • function createForm(node, id, title, win, requestUrl, value, isUpdate) {   
  •     var form0 = new Ext.FormPanel({   
  •         id : id,   
  •         labelWidth : 75// label settings here cascade unless overridden   
  •         frame : true,   
  •         title : title,   
  •         bodyStyle : 'padding:5px 5px 0',   
  •         width : 500  
  •             // defaults : {   
  •             // width : 230   
  •             // }   
  •   
  •     });   
  •     var nameField = createField('章節名稱''createItemText' + id + node.id,   
  •             'name', value);   
  •     var unitField = createField('組織名稱''createItemText' + id + node.id,   
  •             'unit', value);   
  •     var areaField = new Ext.form.TextArea({   
  •         fieldLabel : '章節編輯',   
  •         // width:980,   
  •         // x:400,   
  •         // y:400,   
  •         // itemCls:'all-field',   
  •         // clearCls:'allow-float',   
  •         // allowBlank:true,   
  •         // style:"width:100px;height:60px;",   
  •         // autocomplete: "off",   
  •         // height:400,   
  •         height : 400,   
  •         width : 500,   
  •         grow : false,   
  •         name : 'sectionText'  
  •     });   
  •     form0.add(nameField);   
  •     form0.add(unitField);   
  •     form0.add(areaField);   
  •     form0.addButton({   
  •         text : '保存',   
  •         handler : function() {   
  •             saveHandler(win, requestUrl, node, form0, isUpdate);   
  •         }   
  •     });   
  •     return form0;   
  • }   
  • // 編輯form   
  • function editorForm(node, id, title, win, requestUrl, value, isUpdate) {   
  •     var form0 = new Ext.FormPanel({   
  •         id : id,   
  •         labelWidth : 75// label settings here cascade unless overridden   
  •         frame : true,   
  •         title : title,   
  •         bodyStyle : 'padding:5px 5px 0',   
  •         width : 500,   
  •         // defaults : {   
  •         // width : 1230   
  •         // },   
  •         reader : new Ext.data.JsonReader({   
  •             root : 'list',   
  •             fields : [{   
  •                 name : 'sectionText'  
  •             }]   
  •         })   
  •   
  •     });   
  •     // var   
  •     // nameField=createField('章節名稱','createItemText'+id+node.id,'sectionText',value   
  •     // );   
  •     var nameField = new Ext.form.TextArea({   
  •         fieldLabel : '章節編輯',   
  •         grow : false,   
  •         // inputType : 'textarea',   
  •         height : 450,   
  •         width : 500,   
  •         // labelWidth : 1000,   
  •         // growMin : 5,   
  •         // labelStyle : 'width:1000px;height:1000px',   
  •         // growMax:true,   
  •         // width:980,   
  •         // x:400,   
  •         // y:400,   
  •         // itemCls:'all-field',   
  •         // clearCls:'allow-float',   
  •         // allowBlank:false,   
  •   
  •         // style:"width:300px;overflow-y:visible",   
  •         name : 'sectionText'  
  •     });   
  •     form0.add(nameField);   
  •     form0.addButton({   
  •         text : '保存',   
  •         handler : function() {   
  •             saveHandler(win, requestUrl, node, form0, isUpdate);   
  •         }   
  •     });   
  •     var id = node.id;   
  •     form0.getForm().load({   
  •         url : '/getSectionText/?id=' + id,   
  •         waitMsg : 'Loading'  
  •     });   
  •     return form0;   
  • }   
  •   
  • // 2 創建 tab panel   
  • function createTabPanel(node, e, type, win) {   
  •   
  •     var createUrl = '/createSection/?id=' + node.attributes.id;   
  •     var updateUrl = '/updateSection/?id=' + node.attributes.id;   
  •     var editorUrl = '/editorSection/?id=' + node.attributes.id;   
  •   
  •     var panel = new Ext.TabPanel({   
  •         // el: 'hello-tabs',   
  •         autoTabs : true,   
  •         activeTab : 0,   
  •         deferredRender : false,   
  •         border : false  
  •     });   
  •   
  •     var form0 = createForm(node, 'form0' + node.id, '新建子章節', win, createUrl,   
  •             ''false);   
  •     var form1 = updateForm(node, 'form1' + node.id, '修改章節名稱', win, updateUrl,   
  •             node.text, true);   
  •     var form2 = editorForm(node, 'form2' + node.id, '章節編輯', win, editorUrl, '',   
  •             true);   
  •     panel.add(form2);   
  •     panel.add(form0);   
  •     panel.add(form1);   
  •   
  •     return panel;   
  • }   
  • // 組裝   
  • function itemManage(node, e) {   
  •     var type = "電子書章節管理"  
  •     // create the window on the first click and reuse on subsequent clicks   
  •     var win = Ext.getCmp('win' + type + node.id);   
  •     if (!win) {   
  •         win = new Ext.Window({   
  •             title : type,   
  •             id : 'win' + type + node.id,   
  •             layout : 'fit',   
  •             maximizable : true,// 最大化   
  •             collapsible : true,// 可折疊   
  •             width : 800,   
  •             height : 600,   
  •             // closeAction:'hide',   
  •             plain : true  
  •         });   
  •         var tab = createTabPanel(node, e, type, win);   
  •         win.add(tab);   
  •     }   
  •     win.show();   
  •   
  • }   
  •   
  • // grid.addListener('rowdbclick',function(){   
  • // alert("123");   
  • // });   
  • Ext.ux.makeMenu = function(node, event, title, requestUrl) {   
  •     var rightClick = new Ext.menu.Menu({   
  •         id : 'rightClickCont' + node.id,   
  •         items : [{   
  •             id : node.id + "menu",   
  •             text : title,   
  •             // 增加菜單點擊事件   
  •             handler : function() {   
  •                 Ext.Ajax.request({   
  •                     url : requestUrl,   
  •                     params : {   
  •   
  •                     },   
  •                     success : function(response, request) {   
  •                         Ext.MessageBox.alert("狀態""刪除成功", function() {   
  •                         });   
  •                         if (node.isLeaf()) {   
  •                             var root = node.getOwnerTree().root;   
  •                             root.reload();   
  •                             root.expand(truetrue);   
  •                         } else {   
  •                             var root = node.getOwnerTree().root;   
  •                             root.reload();   
  •                             root.expand(truetrue);   
  •                         }   
  •                     },   
  •                     failure : function() {   
  •                         // Ext.MessageBox.hide();   
  •                         Ext.MessageBox.alert('狀態''刪除失敗!');   
  •                         if (node.isLeaf()) {   
  •                             var root = node.getOwnerTree().root;   
  •                             root.reload();   
  •                             root.expand(truetrue);   
  •                         } else {   
  •                             var root = node.getOwnerTree().root;   
  •                             root.reload();   
  •                             root.expand(truetrue);   
  •                         }   
  •                     }   
  •                 });   
  •             }   
  •         }]   
  •     });   
  •     event.preventDefault();   
  •     rightClick.showAt(event.getXY());// 取得鼠標點擊坐標,展示菜單   
  •   
  • };  


  • 付厚俊 2008-10-04 19:12 發表評論
    ]]>
    extjs+struts2+spring例子http://www.tkk7.com/fuhoujun/archive/2008/10/04/232319.html付厚俊付厚俊Sat, 04 Oct 2008 06:35:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232319.htmlhttp://www.tkk7.com/fuhoujun/comments/232319.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232319.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232319.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232319.htmlstruts2的json plugin的位置在:http://code.google.com/p/jsonplugin/
    下載json plugin的jar包,放到/WEB-INF/lib/目錄下就可以了

    Spring + Struts + JPA的項目結構如其他例子中的一致
    首先是web.xml
    xml 代碼
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <web-app id="WebApp_ID" version="2.4"  
    3.     xmlns="http://java.sun.com/xml/ns/j2ee"  
    4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
    6.     <display-name>quickstart</display-name>  
    7.     <filter>  
    8.         <filter-name>struts2</filter-name>  
    9.         <filter-class>  
    10.             org.apache.struts2.dispatcher.FilterDispatcher  
    11.         </filter-class>  
    12.     </filter>  
    13.     <filter>  
    14.         <filter-name>jpaFilter</filter-name>  
    15.         <filter-class>  
    16.             org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter  
    17.         </filter-class>  
    18.         <init-param>  
    19.             <param-name>entityManagerFactory</param-name>  
    20.             <param-value>entityManagerFactory</param-value>  
    21.         </init-param>  
    22.     </filter>  
    23.     <filter-mapping>  
    24.         <filter-name>jpaFilter</filter-name>  
    25.         <url-pattern>*.action</url-pattern>  
    26.     </filter-mapping>  
    27.     <filter-mapping>  
    28.         <filter-name>struts2</filter-name>  
    29.         <url-pattern>/*</url-pattern>  
    30.     </filter-mapping>  
    31.     <welcome-file-list>  
    32.         <welcome-file>index.jsp</welcome-file>  
    33.     </welcome-file-list>  
    34.     <listener>  
    35.         <listener-class>  
    36.             org.springframework.web.context.ContextLoaderListener  
    37.         </listener-class>  
    38.     </listener>  
    39. </web-app>  

    加入jpaFilter,是為了不讓hibernate的session過早關閉,因為有的action會通過ajax動態調用。
    下面是struts.xml,注意struts.xml需要放在源代碼目錄下面:

    xml 代碼
     
    1. <?xml version="1.0" encoding="UTF-8" ?>  
    2. <!DOCTYPE struts PUBLIC  
    3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
    4.     "http://struts.apache.org/dtds/struts-2.0.dtd">  
    5. <struts>  
    6.     <constant name="struts.objectFactory" value="spring" />  
    7.     <constant name="struts.devMode" value="true" />  
    8.     <constant name="struts.i18n.encoding" value="UTF-8"/>  
    9.     <package name="person" extends="json-default">  
    10.         <action name="list" method="execute" class="personaction">  
    11.             <result type="json"/>  
    12.         </action>         
    13.     </package>  
    14. </struts>  

    這里注意,
    struts.objectFactory告訴struts所有的action都到spring的上下文里面去找,另外還需要注意,我們自己的包要繼承自json-default,這樣才可以在result的type屬性中使用json
    下面是spring的配置文件applicationContext.xml:
    xml 代碼
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.     xmlns:aop="http://www.springframework.org/schema/aop"  
    5.     xmlns:tx="http://www.springframework.org/schema/tx"  
    6.     xsi:schemaLocation="  
    7.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
    8.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd  
    9.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
    10.     <bean  
    11.         class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />  
    12.     <bean id="entityManagerFactory"  
    13.         class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">  
    14.         <property name="dataSource" ref="dataSource" />  
    15.         <property name="jpaVendorAdapter">  
    16.             <bean  
    17.                 class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">  
    18.                 <property name="database" value="MYSQL" />  
    19.                 <property name="showSql" value="true" />  
    20.             </bean>  
    21.         </property>  
    22.     </bean>  
    23.     <bean id="dataSource"  
    24.         class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    25.         <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
    26.         <property name="url" value="jdbc:mysql://localhost/extjs" />  
    27.         <property name="username" value="root" />  
    28.         <property name="password" value="" />  
    29.     </bean>  
    30.   
    31.       
    32.     <bean id="transactionManager"  
    33.         class="org.springframework.orm.jpa.JpaTransactionManager">  
    34.         <property name="entityManagerFactory"  
    35.             ref="entityManagerFactory" />  
    36.     </bean>  
    37.     <tx:annotation-driven transaction-manager="transactionManager" />  
    38.     <!--Service 開始 -->  
    39.     <bean id="personService" class="com.myext.service.impl.PersonServiceJpaImpl"/>  
    40.     <bean id="personaction" class="com.myext.action.PersonPageAction">  
    41.         <property name="person" ref="personService"/>  
    42.     </bean>  
    43. </beans>  

    這里的bean personaction和strutx.xml中的action class一致就可以了,下面是代碼:
    action:
    java 代碼
    1. package com.myext.action;
    2. import java.util.ArrayList;
    3. import java.util.List;
    4. import com.myext.service.PersonService;
    5. public class PersonPageAction {
    6. private int limit=10;
    7. private int start=0;
    8. private PersonService person;
    9. private int total=0;
    10. private List persons = new ArrayList();
    11. private boolean success=true;
    12. public boolean getSuccess(){
    13. return this.success;
    14. }
    15. public void setLimit(int limit) {
    16. this.limit = limit;
    17. }
    18. public void setStart(int start) {
    19. this.start = start;
    20. }
    21. public void setPerson(PersonService person) {
    22. this.person = person;
    23. }
    24. public int getTotal() {
    25. return total;
    26. }
    27. public void setTotal(int total) {
    28. this.total = total;
    29. }
    30. public List getPersons() {
    31. return persons;
    32. }
    33. public void setPersons(List persons) {
    34. this.persons = persons;
    35. }
    36. public String execute(){
    37. this.total = person.getTotal();
    38. this.persons = person.getPage(this.start, this.limit);
    39. return "success";
    40. }
    41. }
    service:
    java 代碼
    1. package com.myext.service.impl;
    2. import java.util.List;
    3. import javax.persistence.EntityManager;
    4. import javax.persistence.PersistenceContext;
    5. import javax.persistence.Query;
    6. import com.myext.model.Person;
    7. import com.myext.service.PersonService;
    8. public class PersonServiceJpaImpl implements PersonService {
    9. private EntityManager em;
    10. private static String poname = Person.class.getName();
    11. @PersistenceContext
    12. public void setEntityManager(EntityManager em){
    13. this.em = em;
    14. }
    15. @SuppressWarnings("unchecked")
    16. @Override
    17. public List getPage( int start, int limit) {
    18. Query q = this.em.createQuery("from " + poname );
    19. q.setFirstResult(start);
    20. q.setMaxResults(limit);
    21. return q.getResultList();
    22. }
    23. @Override
    24. public int getTotal() {
    25. return this.em.createQuery("from " + poname).getResultList().size();
    26. }
    27. }
    頁面的代碼:
    xml 代碼
    1. xml version="1.0" encoding="UTF-8" ?>
    2. <%@ page language="java" contentType="text/html; charset=UTF-8"
    3. pageEncoding="UTF-8"%>
    4. >
    5. <html xmlns="http://www.w3.org/1999/xhtml">
    6. <head>
    7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    8. <title>Grid3title>
    9. <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />
    10. <script type="text/javascript" src="extjs/adapter/ext/ext-base.js">script>
    11. <script type="text/javascript" src="extjs/ext-all.js">script>
    12. <script type="text/javascript" src="extjs/ext-lang-zh_CN.js">script>
    13. head>
    14. <body>
    15. <script type="text/javascript" src="grid3.js">script>
    16. <div id="grid3" >
    17. div>
    18. body>
    19. html>
    grid3.js代碼
    js 代碼
    1. /**
    2. * @author fox
    3. */
    4. Ext.onReady(function(){
    5. Ext.BLANK_IMAGE_URL = 'extjs/resources/images/default/s.gif';
    6. Ext.QuickTips.init();
    7. var sm = new Ext.grid.CheckboxSelectionModel(); //CheckBox選擇列
    8. var cm = new Ext.grid.ColumnModel([
    9. new Ext.grid.RowNumberer(), //行號列
    10. sm,
    11. {header:'編號',dataIndex:'id'},
    12. {header:'性別',dataIndex:'sex',renderer:function(value){
    13. if(value=='male'){
    14. return "";
    15. }else{
    16. return "";
    17. }
    18. }}, //增加性別,自定義renderer,即顯示的樣式,可以加html代碼,來顯示圖片等。
    19. {header:'名稱',dataIndex:'name'},
    20. {header:'描述',dataIndex:'descn'}
    21. ]);
    22. var ds = new Ext.data.Store({
    23. proxy: new Ext.data.HttpProxy({url:'list.action'}),//調用的動作
    24. reader: new Ext.data.JsonReader({
    25. totalProperty: 'total',
    26. root: 'persons',
    27. successProperty :'success'
    28. }, [
    29. {name: 'id',mapping:'id',type:'int'},
    30. {name: 'sex',mapping:'sex',type:'string'},
    31. {name: 'name',mapping:'name',type:'string'},
    32. {name: 'descn',mapping:'descn',type:'string'} //列的映射
    33. ])
    34. });
    35. var grid = new Ext.grid.GridPanel({
    36. el: 'grid3',
    37. ds: ds,
    38. sm: sm,
    39. cm: cm,
    40. width:700,
    41. height:280,
    42. bbar: new Ext.PagingToolbar({
    43. pageSize: 10,
    44. store: ds,
    45. displayInfo: true,
    46. displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
    47. emptyMsg: "沒有記錄"
    48. }) //頁腳顯示分頁
    49. });
    50. //el:指定html元素用于顯示grid
    51. grid.render();//渲染表格
    52. ds.load({params:{start:0, limit:10}}); //加載數據
    53. });
    注意,這里的gridpanel一定要設置高度,否則數據是顯示不出來的。
    最后啟動tomcat,在瀏覽器里輸入http://localhost:8080/extjs/grid3.jsp,就可以看到效果


    付厚俊 2008-10-04 14:35 發表評論
    ]]>
    ext在線API http://www.ajaxjs.com/docs/http://www.tkk7.com/fuhoujun/archive/2008/10/03/232155.html付厚俊付厚俊Thu, 02 Oct 2008 18:22:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/03/232155.htmlhttp://www.tkk7.com/fuhoujun/comments/232155.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/03/232155.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232155.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232155.html

    付厚俊 2008-10-03 02:22 發表評論
    ]]>
    Panel遲加載的方法(基本解決)http://www.tkk7.com/fuhoujun/archive/2008/10/03/232154.html付厚俊付厚俊Thu, 02 Oct 2008 18:20:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/03/232154.htmlhttp://www.tkk7.com/fuhoujun/comments/232154.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/03/232154.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232154.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232154.html     var title = _records[0].get('n_ttitle');
        var content = _records[0].get('n_content');
        p.setTitle(title);
        p.html = content;
        p.doLayout();
    });

    付厚俊 2008-10-03 02:20 發表評論
    ]]>
    ExtJs + Struts2 + JSON http://www.tkk7.com/fuhoujun/archive/2008/10/02/232050.html付厚俊付厚俊Wed, 01 Oct 2008 16:37:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/02/232050.htmlhttp://www.tkk7.com/fuhoujun/comments/232050.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/02/232050.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232050.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232050.html閱讀全文

    付厚俊 2008-10-02 00:37 發表評論
    ]]>
    主站蜘蛛池模板: 国产亚洲综合精品一区二区三区| 亚洲性色成人av天堂| 亚洲国产精品嫩草影院在线观看 | 欧美a级成人网站免费| 精品国产精品久久一区免费式| 免费夜色污私人影院在线观看| 亚洲小说区图片区另类春色| 亚洲蜜芽在线精品一区| 国产精品无码亚洲精品2021| 和老外3p爽粗大免费视频| 91精品国产免费入口| 毛片网站免费在线观看| 亚洲精品久久久www| 亚洲国产精品一区| 亚洲欧美国产国产综合一区| 一级一片免费视频播放| 91精品免费不卡在线观看| 日韩免费一级毛片| 亚洲AV无码不卡无码| 亚洲欧美日韩自偷自拍| 中国一级特黄的片子免费 | 亚洲国产精品成人精品无码区| 亚洲精品mv在线观看| 真人无码作爱免费视频| 久久成人免费大片| 日本无卡码免费一区二区三区| 亚洲色大成网站WWW久久九九| 亚洲一区二区三区深夜天堂| 一道本不卡免费视频| 免费成人福利视频| 亚洲中文字幕无码爆乳av中文| 亚洲成人黄色网址| gogo免费在线观看| 成人免费淫片在线费观看| 亚洲色婷婷综合久久| 亚洲欧洲免费无码| 久久国产精品一区免费下载| 国产无遮挡色视频免费视频| 久久夜色精品国产噜噜噜亚洲AV| 最新亚洲人成无码网站| 免费视频爱爱太爽了|