Ext框架的Grid使用介绍

Ext2.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': '[email protected]' },
        { 'id': '2', 'sex': 'male','name':'Hunter', 'descn': '[email protected]' },
        { 'id': '3', 'sex': 'female','name':'Harold', 'descn': '[email protected]' },
        { 'id': '4', 'sex': 'male','name':'Harolds', 'descn': '[email protected]' }
    ],
    '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管理。

posted @ 2008-11-02 11:05 付厚俊 阅读(116) | 评论 (0) |  编辑  收藏
  2008年10月21日
java NIO
     摘要: java nio的全称是java new I/O,即一个全新的I/O控制系统,它的API的包名为java.nio,是在jdk1.4后引入的。 nio之所以为为新,在于它并没在原来I/O的基础上进行开发,而是提供了全新的类和接口,除了原来的基本功能之外,它还提供了以下新的特征:         ► 多路选择的非封锁式...   阅读全文
posted @ 2008-10-21 17:44 付厚俊 阅读(31) | 评论 (0) |  编辑  收藏
  2008年10月20日
轻松实现Apache,Tomcat集群和负载均衡
 作者:罗代均 ldj_work#126.com,转载请保持完整性
环境说明

       Apache  :apache_2.0.55     1 个

       Tomcat:  apache-tomcat-5.5.17 (zip版) 2个

       mod_jk:: mod_jk-apache-2.0.55.so  1个

第一部分:负载均衡

    负载均衡,就是apache将客户请求均衡的分给tomcat1,tomcat2....去处理

   1.安装apche,tomcat

   http://httpd.apache.org/ 下载Apache 2.0.55

    http://tomcat.apache.org/download-55.cgi 下载tomcat5.5 zip版本(解压即可,绿色版)

   http://apache.justdn.org/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.15/  下载mod_jk,注意和  apache版本匹配

   按照jdk,我的路径为:E:/ide/apache/Apache2

   解压两份Tomcat, 路径分别为 E:/ide/tomcat1,E:/ide/tomcat2

Ext框架的Grid使用介绍_第1张图片

下载mod_jk

Ext框架的Grid使用介绍_第2张图片
Ext框架的Grid使用介绍_第3张图片

2.修改Apache配置文件http.conf

   在apache安装目录下conf目录中找到http.conf

   在文件最后加上下面一句话就可以了

  include "E:/ide/apache/Apache2/conf/mod_jk.conf"

Ext框架的Grid使用介绍_第4张图片
2. http.conf 同目录下新建mod_jk.conf文件,内容如下
  
#加载mod_jk Module
LoadModule jk_module modules/mod_jk-apache-2.0.55.so
#指定 workers.properties文件路径
JkWorkersFile conf/workers.properties
#指定那些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器
JkMount /*.jsp controller
3.在http.conf同目录下新建 workers.properties文件,内容如下
 
worker.list = controller,tomcat1,tomcat2  #server 列表
#========tomcat1========
worker.tomcat1.port=8009         #ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat1.host=localhost  #tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat1.type=ajp13
worker.tomcat1.lbfactor = 1   #server的加权比重,值越高,分得的请求越多
#========tomcat2========
worker.tomcat2.port=9009       #ajp13 端口号,在tomcat下server.xml配置,默认8009
worker.tomcat2.host=localhost  #tomcat的主机地址,如不为本机,请填写ip地址
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor = 1   #server的加权比重,值越高,分得的请求越多

#========controller,负载均衡控制器========
worker.controller.type=lb
worker.controller.balanced_workers=tomcat1,tomcat2   #指定分担请求的tomcat
worker.controller.sticky_session=1
4.修改tomcat配置文件server.xml
如果你在不同电脑上安装tomcat,tomcat的安装数量为一个,可以不必修改tomcat配置文件
我这里是在同一台电脑上安装两个tomcat,所以需要更改其中一个的设置
打开tomcat2/conf/server.xml文件
Ext框架的Grid使用介绍_第5张图片
Ext框架的Grid使用介绍_第6张图片
Ext框架的Grid使用介绍_第7张图片
5.编写一个测试jsp
建立一个目录test.里面新建一个test.jsp,内容为
<%
   System.out.println("===========================");
%>
把test放到tomcat1,tomcat2的webapps下
6.启动apache,tomcat1,tomcat2,进行测试
通过 http://localhost/test/test.jsp 访问,查看tomcat1的窗口,可以看到打印了一行"=========="
再刷新一次,tomcat2也打印了一条,再刷新,可以看到请求会被tomcat1,tomcat2轮流处理,实现了负载均衡
Ext框架的Grid使用介绍_第8张图片
第二部分,配置集群
   只配置负载均衡还不行,还要session复制,也就是说其中任何一个tomcat的添加的session,是要同步复制到其它tomcat, 集群内的tomcat都有相同的session
1. 修改tomcat1, tomcat2的server.xml,将集群部分配置的在注释符删掉,并将tomcat2的4001端口改为4002,以避免与tomcat冲突,当然,如果是两台电脑,是不用改端口的,去掉注释符即可
  
Ext框架的Grid使用介绍_第9张图片
Ext框架的Grid使用介绍_第10张图片
Ext框架的Grid使用介绍_第11张图片
Ext框架的Grid使用介绍_第12张图片
2,修改测试项目test
修改test.jsp,内容如下
  <%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
  out.println("<br> ID " + session.getId()+"<br>");
  // 如果有新的 Session 属性设置
  String dataName = request.getParameter("dataName");
  if (dataName != null && dataName.length() > 0) {
     String dataValue = request.getParameter("dataValue");
     session.setAttribute(dataName, dataValue);
  }
  out.print("<b>Session 列表</b>");
  Enumeration e = session.getAttributeNames();
  while (e.hasMoreElements()) {
     String name = (String)e.nextElement();
     String value = session.getAttribute(name).toString();
     out.println( name + " = " + value+"<br>");
         System.out.println( name + " = " + value);
   }
%>
  <form action="index.jsp" method="POST">
    名称:<input type=text size=20 name="dataName">
     <br>
    值:<input type=text size=20 name="dataValue">
     <br>
    <input type=submit>
   </form>
</body>
</html>
然后在test 新建WEB-INF目录,WEB-INF下新建web.xml,内容如下
<web-app xmlns=" http://java.sun.com/xml/ns/j2ee" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
       <display-name>TomcatDemo</display-name>
       <distributable/>
</web-app>
注意:在你的应用的web.xml加入  <distributable/> 即可
ok,讲test复制到tomcat1,tomcat2的webapps下,重启apache,tomcat1,tomcat2,
输入网址 http://localhost/test/test.jsp  
新建一个 名称为 xiaoluo  ,值为 cdut 的session,提交查询,新开一个ie窗口,再提交查询,如图,可以看到,两个tomcat 是负载均衡,并且session同步的
Ext框架的Grid使用介绍_第13张图片
posted @ 2008-10-20 08:49 付厚俊 阅读(17) | 评论 (0) |  编辑  收藏
  2008年10月15日
Ext中FormPanel面板及Form控件横排测试(CSS)

在实际的网页开发中,大部分时间都要涉及到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>

posted @ 2008-10-15 13:03 付厚俊 阅读(37) | 评论 (0) |  编辑  收藏
EXT树重新加载
ext js 创建树
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. }  
posted @ 2008-10-15 12:52 付厚俊 阅读(172) | 评论 (1) |  编辑  收藏
  2008年10月10日
ext中树结构带复选框的处理
在Faceye基础版(开源)中,使用了大量的树结构,比如台台管理树,用户RSS订阅及分类树,用户博客分类对,网址导航分类树,开源项目分类树,博客 管理树等大量的树形结构,甚至在用户授权,用户分组,资料分类等也都使用了树结构,树结构的处理,在Faceye中相比比较成熟,这些,是基于前期项目中 对Struts-menu,Dtree等处理
关于Struts-Menu,Dtree的处理,在我早期的博客中都有描述.

带有复选框的树,在实际的项目中,特别是授权结构中,有大量的使用.我们来看一下Faceye中如何处理这种带复选框的树形结构.

首先,Faceye使用了Ext的树解决方案,所以,所有的数据结构,均转化为Ext中树解决方案的数据结构.在这里,我们可以很方便的把这一结构转化为其它树支持的数据结构,比如Strus-menu,dtreee等.
下面是对树完整的脚本处理代码.
[code]
/**
*RoleController
* 角色访问权限管理
* 管理角色对模块的访问权限
* www.faceye.com网络支持系统
* 作者:宋海鹏 [email protected]/[email protected]
*/
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下载.
posted @ 2008-10-10 21:43 付厚俊 阅读(168) | 评论 (0) |  编辑  收藏
  2008年10月8日
Java下的框架编程之cglib的应用
Java下的框架编程之cglib的应用

 

Proxy 可以看作是微型的AOP,明白提供了在继承和委托之外的第三个代码封装途径,只要有足够的想象力,可以做得非常好玩,Spring的源码里用Proxy就 用得很随便,看得我非常眼红。可惜Proxy必须基于接口。因此Spring的做法,基于接口的用proxy,否则就用cglib。AOP么,一般小事非 compoent一级的就不麻烦AspectJ出手了。

cglib的Enhancer说起来神奇,用起来一页纸不到就讲完了。

它的原理就是用Enhancer生成一个原有类的子类,并且设置好callback到proxy, 则原有类的每个方法调用都会转为调用实现了MethodInterceptor接口的proxy的intercept() 函数:

                        

public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy)


在intercept()函数里,你可以在执行Object result=proxy.invokeSuper(o,args);来执行原有函数,在执行前后加入自己的东西,改变它的参数值,也可以瞒天过海,完全 干别的。说白了,就是AOP中的around advice。

AOP没有出现以前,该领域经典的设计模式是Decorator,像Java IO Stream的设计就是如此。不过,如果为每个DAO, 每个方法的写Decorator函数会写死人的,所以用上cglib的好处是一次过拦截所有方法。 

另外,cglib除了Enhancer之外,还有BulkBean和Transform,都是Hibernate持久化的基础,但文档贫乏,一时还没去看怎么用。

1.AOP里讲了一百遍啊一百遍的log aspect在cglib是这样做的:

                        

public class LogDAOProxy implements MethodInterceptor

   {

       
private Logger log=Logger.getLogger(LogDAOProxy.class);

       
private Enhancer enhancer=new Enhancer();

        
//返回DAO的子类

       public Object getDAO(Class clz)

       {

           enhancer.setSuperclass(clz);

           enhancer.setCallback(
this);

           
return enhancer.create();

       }

       
//默认的拦截方法

      public Object intercept(Object o,Method method,Object[] args,


MethodProxy proxy) throws Throwable

      {

           log.info(
"调用日志方法"+method.getName());

           Object result
=proxy.invokeSuper(o,args);

           
return result;

      }

   }



应用的代码:

                        

LogDAOProxy proxy = new LogDAOProxy();

  GoodsDAO  dao 
= (GoodsDAO)proxy.getDAO(GoodsDAO.class);

  dao.insert(goods);



2.而在Spring的管理下应该略加修改的高级Decorator

上面的例子用return enhancer.create();创建子类实例,但在Spring管理下,一些Bean的实例必须由Spring来创建和管理,而不由enhancer来创建的。所以我对上述用法略加修改,使它真正当一个Proxy的角色,请对比黑体字的部分。

                        

public class LogDAOProxy implements MethodInterceptor

  {

       
private Logger log=Logger.getLogger(LogDAOProxy.class);

       
private Object dao=null;

       
private Enhancer enhancer=new Enhancer();

        
//返回DAO的子类

       public Object getDAO(Class clz,Object dao)

       {

           
this.dao = dao;

           enhancer.setSuperclass(clz);

           enhancer.setCallback(
this);

           
return enhancer.create();

       }      

       
//默认的拦截方法

      public Object intercept(Object o,Method method,Object[] args,


MethodProxy proxy) throws Throwable

      {

           log.info(
"调用日志方法"+method.getName());

           Object result
=proxy.invoke(dao, args);

           
return result;

      }

}



可见,原来模式里在getDao()时由enhancer创建dao,而 调用intercept时则将enhancer创建的dao以Object o参数传回。
而新模式里,dao在getDao()时从外面传入,enhancer.create()返回的是一个proxy. 而调用intercept时,实际会用之前传入的dao进行操作,而忽略Object o参数传入的proxy。

有点遗憾, intercept函数里MethodProxy的Signature是固定的,即客户如果调用foo(String),你不可以用proxy.invoke偷换成foo(String,String);

posted @ 2008-10-08 10:38 付厚俊 阅读(23) | 评论 (0) |  编辑  收藏
  2008年10月7日
使用Eclipse+spket开发Spket的安装

1、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.就会出现提示咯!!!

posted @ 2008-10-07 12:11 付厚俊 阅读(266) | 评论 (0) |  编辑  收藏
Ext Form布局

Ext框架的Grid使用介绍_第14张图片
现在我们要实现的效果是: 点击确定,把值传到另一页面!,如下:
Ext框架的Grid使用介绍_第15张图片
原页面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}]
则只有所有的填写字段都满足条件时,"确定"方可提交!如下图,

Ext框架的Grid使用介绍_第16张图片
好了,一个简单的formpanel的提交的原理弄清楚啦!
有关form提交数据的方法有多种,大家可以参考http://www.17ext.com/showtopic-55.aspx(三种ext提交数据的方式),
以后有机会我们再讨论!
下面我们来做个复杂点(只是样子)的form,示例一下(还是上面的原理)!
效果图:
Ext框架的Grid使用介绍_第17张图片
传到GetForm.aspx页面后显示:
Ext框架的Grid使用介绍_第18张图片
不过在传过来的页面要记得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();
  }
});

你可能感兴趣的:(tomcat,框架,String,function,ext,header)