好了,铺垫工作做的差不多了,主角闪亮登场。让ExtJS炫起来吧~~!
ExtJS本质上也是一个AJAX的框架,但是它和DWR有很大不同,首先,DWR是JAVA世界的产物,而ExtJS是后台无关的。也就是说,ExtJS的后台可以是.NET,PHP或者JAVA都可以。其实我们在网上看到的大部分例子都是PHP或者.NET,后台的。这说明ExtJS在所有后台都很受青睐。其次,DWR只关注客户端与服务器端的交互,没有自己的界面组件,而ExtJS最让人惊叹的就是其丰富而强大的界面组件,除此以外,它自身也能轻松地异步访问后台组件。现如今,RIA(富客户端应用)已经成了不争的趋势。那我们现在还不赶紧学习,还更待何时?
我们知道,在WEB开发中有一些共同的开发重心,譬如登陆注册,CRUD(增,删,改,查),数据的分页,排序和过滤,数据的统计报表,数据的导入导出,Cookies和Sessions的管理等。我们在网上看到很多ExtJS的零零星星的应用,有人做了CRUD,有人做了登陆注册,有了做了复杂查询,还有人扩展了分页,做了服务器端的排序,数据的导出等等,但就是没有人提供一个强大而翔实的案例,把这些ExtJS的知识点统一到项目中,或者有的人已经做除了一些真实的项目,可是又不愿意拿出来分享。哎,有感于此,老许来了。
既然是实战,当然需要大家有一定的根基,我给大家提供的开发工具也好,开发文档也罢,都是来帮助大家高效地学习和开发。另外,大家要把网上零零星星的例子多跑几个,然后再进入我们项目的学习。
好啦,大家还是要快速搭建好ExtJS应用的环境。测试通过。在我们的整个项目应用中,就两张核心的JS文件,它完成了项目所需要的所有核心功能,具有很高的参考价值。当然代码量也是比较大的:
1. 首先是init-main.js,这里定义了整个应用的主体布局视图Viewport。它和我们HTML中的frameset有点类似。在我们的主显示区里还放了一个TabPanel,这就是我们桌面应用中常见的选项面板。要理解下面的JS呢,你必须先掌握JSON这种数据格式,这个格式我在前面的ExtJS应用中已经详细讲过,如果还不太清楚,到http://www.json.org/json-zh.html 去看看,JSON在整个ExtJS体系里占有重要地位,熟悉JSON格式的人会对名/值对,{},[]很敏感。大家看到,在Viewport类和TabPanel类里都传入一个JSON对象来初始化整个组件。其次,你还要有容器和组件的概念,每个容器组件(容器同时也是组件,这是相对的,它放东西的时候是容器,被放置其中的时候就是组件!)都有一个items参数指定一个JSON数组来表明自己容纳的组件。我们要完成的功能是上面放公司的LOGO信息,左边是导航菜单栏,右边是主显示区。代码如下:
// create main tabpanel
var contentPanel = new Ext.TabPanel({
id : "tabPanel",
region : 'center',
enableTabScroll : true,
resizeTabs : true, // turn on tab resizing
deferredRender : false,
minTabWidth : 115,
// tabWidth:135,
activeTab : 0,
iconCls : 'tabs',
items : [{
contentEl : 'center',
title : '主页',
autoScroll : true
}],
defaults : {
autoScroll : true
},
plugins : new Ext.ux.TabCloseMenu()
});
//ExtJs应用的入口
Ext.onReady(function() {
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
// init main page framework
var viewport = new Ext.Viewport({
layout : 'border',
items : [{
region : 'north',
html : '<img src="resources/images/dwr_logo.gif" width=210 height=100><img src="resources/images/struts.png" ><img src="resources/images/hibernate.gif" width=200 height=90 ><img src="resources/images/spring_logo.png" width=200 height=70><img src="resources/images/extjs_logo.gif" height=60>',
split : true,
height : 130,
minSize : 100,
maxSize : 200,
collapsible : true,
title : '房屋出租系统',
margin : '0 0 0 0'
// border: false,
// layout:"absolute"
}, {
region : 'west',
id : 'west-panel',
title : '菜单栏',
split : true,
width : 200,
minSize : 175,
maxSize : 400,
collapsible : true,
margins : '0 0 5 5',
cmargins : '0 5 5 5',
layout : 'accordion',
layoutConfig : {
animate : true
},
items : [{
title : '房屋管理',
html : Ext.getDom('userMenus').innerHTML,
autoScroll : true,
border : false,
iconCls : 'user'
}, {
title : '机构管理',
html : Ext.getDom('unitMenus').innerHTML,
border : false,
autoScroll : true,
iconCls : 'unit'
}, {
title : '系统设置',
html : Ext.getDom('settingMenus').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings'
}, {
title : '电子日历',
// html : Ext.getDom('settingMenus').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings',
items : [new Ext.form.DateField()]
}, {
title : '企业短信',
html : Ext.getDom('msg').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings'
}, {
title : '公文审批',
// html : Ext.getDom('msg').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings'
}, {
title : '电子会议',
html : Ext.getDom('eMeeting').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings'
}, {
title : '电子邮件',
// html : Ext.getDom('msg').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings'
}, {
title : '电子文档',
// html : Ext.getDom('msg').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings'
}, {
title : '个性化设置',
// html : Ext.getDom('msg').innerHTML,
border : false,
autoScroll : true,
iconCls : 'settings'
}]
}, contentPanel]
});
// init main page tables
var panel = new Ext.Panel({
id : 'main-panel',
baseCls : 'x-plain',
renderTo : Ext.get("center"),
layout : 'table',
layoutConfig : {
columns : 2
},
defaults : {
frame : true,
width : 395
},
items : [{
title : '公告信息',
colspan : 2,
collapsible : true,
width : 800,
height : 430,
contentEl : 'afficheDiv'
}]
});
// clear temp elements.
Ext.getDom("menus").innerHTML = "";
});
// 定义菜单导航函数
function onClickMenuItem(node) {
var n = contentPanel.getComponent(node.id);
if (!n) { // //判断是否已经打开该面板
n = contentPanel.add({
'id' : node.id,
'title' : node.innerHTML,
iconCls : 'tabs',
closable : true,
autoLoad : {
url : 'tabFrame.jsp?url=' + node.href,
callback : this.initSearch,
scope : this,
scripts : true
} // 通过autoLoad属性载入目标页,如果要用到脚本,必须加上scripts属性
});
}
contentPanel.setActiveTab(n);
}
2. 然后是init-house.js,这是最重要也是最复杂的一个JS文件了。这个JS里面涉及到Ext.Window, Ext.FormPanel,Ext.grid.CheckboxSelectionModel,Ext.data.Record,Ext.grid.ColumnModel,Ext.data.Store,Ext.PagingToolbar,Ext.grid.GridPanel,Ext.MessageBox,Ext.menu.Menu等众多重要的ExtJS控件,要知道它们之间的关系就要先了解我们要做的事!这个应用中,我们要完成的界面功能是在页面上显示一张表格(这张表格的列由ColumnModel决定,数据行由Store决定!),表格上方显示一排工具按钮,分别用来做添加,修改,删除,复制,导出等功能,下方显示分页栏来展现分页数据,表格里面还设置了行级的右键菜单,可以完成和上排工具按钮一样的功能。在表格之上,我们还放置了一个查询表单,来完成我们强大的信息检索功能。最后我们添加和修改数据的时候,都会弹出一个窗口,里面放置着添加或修改数据的表单。还有,当用户执行了不正确的操作时,要弹出相应的提示对话框。OK,怀着攻克难关的激情,我们来看看这1000行代码吧!
var ds;// 数据源
var grid;// 数据显示表格
var searchForm;// 查询表单
var form;//添加/修改的表单
var win;// 添加或修改窗口
var limit = 5;//每页显示的记录数
var ptb;// 分页控件
var TopicRecord;//记录对象
function getInsertForm() {
form = new Ext.FormPanel({
labelWidth : 100,
monitorValid : true,// 把有formBind:true的按钮和验证绑定
baseCls : 'x-plain',
defaults : {
width : 200
},
defaultType : 'textfield',// 默认字段类型
// 定义表单元素
items : [{
fieldLabel : '标题',
name : 'house.title',
allowBlank : false
}, {
fieldLabel : '租金',
name : 'house.hireprice'
}, {
fieldLabel : '联系人',
name : 'house.linkman'
}, {
fieldLabel : '联系电话',
name : 'house.linktel'
}, {
fieldLabel : '几室',
xtype : "combo",
hiddenName : "house.room",// 大家要注意的是hiddenName和name属性,name只是下拉列表的名称,作用是可通过,而hiddenName才是提交到后台的input的name。如果没有设置hiddenName,在后台是接收不到真正的值的。
store : new Ext.data.SimpleStore({
fields : ['a', 'b'],
data : [['1', '一'], ['2', '二'], ['3', '三']]
}),
valueField : 'a',
displayField : 'b',
mode : 'local',
triggerAction : 'all',
forceSelection : true,
selectOnFocus : true,
editable : false,
readOnly : true,
emptyText : "无限制!"
}, {
fieldLabel : '几厅',
xtype : "combo",
hiddenName : "house.ting",// 大家要注意的是hiddenName和name属性,name只是下拉列表的名称,作用是可通过,而hiddenName才是提交到后台的input的name。如果没有设置hiddenName,在后台是接收不到真正的值的。
store : new Ext.data.SimpleStore({
fields : ['a', 'b'],
data : [['1', '一'], ['2', '二'], ['3', '三']]
}),
valueField : 'a',
displayField : 'b',
mode : 'local',
triggerAction : 'all',
forceSelection : true,
selectOnFocus : true,
editable : false,
readOnly : true,
emptyText : "无限制!"
}, {
fieldLabel : "区域",
xtype : 'combo',
store : new Ext.data.SimpleStore({
fields : ['id', 'name'],
data : Ext.grid.areaComboBoxItems
}),
valueField : "id",
displayField : "name",
mode : 'local',
forceSelection : true,// 必须选择一项
emptyText : '请选择区域...',// 默认值
name : "area",
hiddenName : "house.areaId",// hiddenName才是提交到后台的input的name
editable : false,// 不允许输入
triggerAction : 'all',// 因为这个下拉是只能选择的,所以一定要设置属性triggerAction为all,不然当你选择了某个选项后,你的下拉将只会出现匹配选项值文本的选择项,其它选择项是不会再显示了,这样你就不能更改其它选项了。
id : 'parent_id1',
name : 'parent1',
listeners : {
select : function(combo, record, index) {
houseService.getAllStreets(combo.value, function(
data) {
if (data != null) {
var list2 = [];
for (var i = 0; i < data.length; i++) {
list2[i] = [data[i].sid, data[i].sname];
}
Ext.getCmp('child_id1').clearValue();
Ext.getCmp('child_id1').store
.loadData(list2);
}
});
}
}
}, {
fieldLabel : "街道",
xtype : 'combo',
store : new Ext.data.SimpleStore({
fields : ['id', 'name'],
data : []
}),
valueField : "id",
displayField : "name",
// 数据是在本地
mode : 'local',
forceSelection : true,// 必须选择一项
emptyText : '请选择街道...',// 默认值
editable : false,// 不允许输入
triggerAction : 'all',// 因为这个下拉是只能选择的,所以一定要设置属性triggerAction为all,不然当你选择了某个选项后,你的下拉将只会出现匹配选项值文本的选择项,其它选择项是不会再显示了,这样你就不能更改其它选项了。
allowBlank : false,// 该选项值不能为空
id : 'child_id1',
name : "child1",
hiddenName : "house.streetId"
}, {
fieldLabel : '房屋设施',
xtype : 'textarea',
name : 'house.housething'
}],
buttons : [{
text : '保存',
formBind : true,
type : 'submit',
// 定义表单提交事件
handler : function() {
if (form.form.isValid()) {// 验证合法后使用加载进度条
// 提交到服务器操作
form.form.doAction('submit', {
url : '../houseHandler.do?action=addHouse',// 文件路径
method : 'post',// 提交方法post或get
params : '',
// 提交成功的回调函数
failure : function(retForm, retAction) {
if (retAction.result
&& retAction.result == '1') {
Ext.MessageBox.alert('提示', '保存数据成功!');
win.hide();
ptb.cursor=ptb.store.getTotalCount()+1-ptb.pageSize;
ds.load({
params : {
start : ptb.cursor,
limit : ptb.pageSize
}
});
} else if (retAction.result
&& retAction.result == 'error') {
Ext.MessageBox.alert('提示', '保存数据失败!');
} else {
Ext.Msg.alert('错误', '服务器出现错误请稍后再试!');
}
},
waitMsg : '保存数据...'
});
}
}
}, {
text : '取消',
handler : function() {
form.form.reset();
}// 重置表单
}]
});
return form;
}
function getUpdateForm() {
form = new Ext.FormPanel({
labelWidth : 100,
monitorValid : true,// 把有formBind:true的按钮和验证绑定
baseCls : 'x-plain',
defaults : {
width : 200
},
defaultType : 'textfield',// 默认字段类型
// 定义表单元素
items : [{
fieldLabel : 'ID',
name : 'house.hid',
allowBlank : false,
readOnly : true
}, {
fieldLabel : '标题',
name : 'house.title',
allowBlank : false
}, {
fieldLabel : '租金',
name : 'house.hireprice'
}, {
fieldLabel : '联系人',
name : 'house.linkman'
}, {
fieldLabel : '联系电话',
name : 'house.linktel'
}, {
fieldLabel : '几室',
xtype : "combo",
hiddenName : "house.room",// 大家要注意的是hiddenName和name属性,name只是下拉列表的名称,作用是可通过,而hiddenName才是提交到后台的input的name。如果没有设置hiddenName,在后台是接收不到真正的值的。
store : new Ext.data.SimpleStore({
fields : ['a', 'b'],
data : [['1', '一'], ['2', '二'], ['3', '三']]
}),
valueField : 'a',
displayField : 'b',
mode : 'local',
triggerAction : 'all',
forceSelection : true,
selectOnFocus : true,
editable : false,
readOnly : true,
emptyText : "无限制!"
}, {
fieldLabel : '几厅',
xtype : "combo",
hiddenName : "house.ting",// 大家要注意的是hiddenName和name属性,name只是下拉列表的名称,作用是可通过,而hiddenName才是提交到后台的input的name。如果没有设置hiddenName,在后台是接收不到真正的值的。
store : new Ext.data.SimpleStore({
fields : ['a', 'b'],
data : [['1', '一'], ['2', '二'], ['3', '三']]
}),
valueField : 'a',
displayField : 'b',
mode : 'local',
triggerAction : 'all',
forceSelection : true,
selectOnFocus : true,
editable : false,
readOnly : true,
emptyText : "无限制!"
}, {
fieldLabel : "区域",
xtype : 'combo',
store : new Ext.data.SimpleStore({
fields : ['id', 'name'],
data : Ext.grid.areaComboBoxItems
}),
valueField : "id",
displayField : "name",
mode : 'local',
forceSelection : true,// 必须选择一项
emptyText : '请选择区域...',// 默认值
name : "area",
hiddenName : "house.areaId",// hiddenName才是提交到后台的input的name
editable : false,// 不允许输入
triggerAction : 'all',// 因为这个下拉是只能选择的,所以一定要设置属性triggerAction为all,不然当你选择了某个选项后,你的下拉将只会出现匹配选项值文本的选择项,其它选择项是不会再显示了,这样你就不能更改其它选项了。
id : 'parent_id2',
name : 'parent2',
listeners : {
select : function(combo, record, index) {
houseService.getAllStreets(combo.value, function(
data) {
if (data != null) {
var list2 = [];
for (var i = 0; i < data.length; i++) {
list2[i] = [data[i].sid, data[i].sname];
}
Ext.getCmp('child_id2').clearValue();
Ext.getCmp('child_id2').store
.loadData(list2);
}
});
}
}
}, {
fieldLabel : "街道",
xtype : 'combo',
store : new Ext.data.SimpleStore({
fields : ['id', 'name'],
data : []
}),
valueField : "id",
displayField : "name",
// 数据是在本地
mode : 'local',
forceSelection : true,// 必须选择一项
emptyText : '请选择街道...',// 默认值
editable : false,// 不允许输入
triggerAction : 'all',// 因为这个下拉是只能选择的,所以一定要设置属性triggerAction为all,不然当你选择了某个选项后,你的下拉将只会出现匹配选项值文本的选择项,其它选择项是不会再显示了,这样你就不能更改其它选项了。
allowBlank : false,// 该选项值不能为空
id : 'child_id2',
name : "child2",
hiddenName : "house.streetId"
}, {
fieldLabel : '房屋设施',
xtype : 'textarea',
name : 'house.housething'
}],
buttons : [{
text : '修改',
formBind : true,
type : 'submit',
// 定义表单提交事件
handler : function() {
if (form.form.isValid()) {// 验证合法后使用加载进度条
// 提交到服务器操作
form.form.doAction('submit', {
url : '../houseHandler.do?action=editHouse',// 文件路径
method : 'post',// 提交方法post或get
params : '',
// 提交成功的回调函数
failure : function(retForm, retAction) {
if (retAction.result
&& retAction.result == '1') {
Ext.MessageBox.alert('提示', '更新数据成功!');
win.hide();
ds.load({
params : {
start : ptb.cursor,
limit : ptb.pageSize
}
});
} else if (retAction.result
&& retAction.result == 'error') {
Ext.MessageBox.alert('提示', '更新数据失败!');
} else {
Ext.Msg.alert('错误', '服务器出现错误请稍后再试!');
}
},
waitMsg : '更新数据...'
});
}
}
}, {
text : '取消',
handler : function() {
form.form.reset();
}// 重置表单
}]
});
return form;
}
// 页面加载后执行的代码
Ext.onReady(function() {
// get All unit Name for comboBox.
houseService.getAllAreas(function(data) {
if (data != null) {
var list = [];
for (var i = 0; i < data.length; i++) {
list[i] = [data[i].aid, data[i].aname];
}
Ext.grid.areaComboBoxItems = list;
initData();
}
});
});
// 初始化数据
function initData() {
if (!searchForm) {
searchForm = new Ext.FormPanel({
collapsible : true,
autoHeight : true,
frame : true,
width : 800,
monitorValid : true,// 把有formBind:true的按钮和验证绑定
layout : "form",
labelWidth : 55,
title : "查询房屋信息",
renderTo : Ext.getBody(),
items : [{
xtype : "panel",// 默认就是它
layout : "column",
fieldLabel : "标题",
isFormField : true,
items : [{
columnWidth : 0.17,
xtype : "textfield",
name : "title",
anchor : "100%"
}, {
columnWidth : 0.4,
layout : "form",
labelWidth : 60,// 注意,这个参数在这里可以调整简单fieldLabel的布局位置
items : [{
xtype : "datefield",
fieldLabel : "发布日期",
name : "booktime",
anchor : "90%"
}]
}]
}, { // 上面是第一行
xtype : "panel",
layout : "column",
fieldLabel : "几室",
isFormField : true,
items : [{
columnWidth : 0.15,
xtype : "combo",
name : "room",
hiddenName : "room",// 大家要注意的是hiddenName和name属性,name只是下拉列表的名称,作用是可通过,而hiddenName才是提交到后台的input的name。如果没有设置hiddenName,在后台是接收不到真正的值的。
store : new Ext.data.SimpleStore({
fields : ['a', 'b'],
data : [['1', '一'], ['2', '二'],
['3', '三']]
}),
valueField : 'a',
displayField : 'b',
mode : 'local',
triggerAction : 'all',
// forceSelection : true,
// selectOnFocus : true,
editable : false,
emptyText : "无限制!",
anchor : "80%"
}, {
columnWidth : 0.2,
layout : "form",
labelWidth : 40,// 注意,这个参数在这里可以调整简单fieldLabel的布局位置
items : [{
xtype : "combo",
name : "ting",
hiddenName : "ting",
fieldLabel : "几厅",
store : new Ext.data.SimpleStore({
fields : ['a', 'b'],
data : [['1', '一'], ['2', '二'],
['3', '三']]
}),
valueField : 'a',
displayField : 'b',
allowBlank : true,
readOnly : true,
mode : 'local',
triggerAction : 'all',
selectOnFocus : true,
emptyText : "无限制!",
anchor : "80%"
}]
}, {
columnWidth : 0.15,
layout : "form",
labelWidth : 40,// 注意,这个参数在这里可以调整简单fieldLabel的布局位置
items : [{
fieldLabel : "租金",
xtype : "textfield",
vtype : "double",// 实数格式验证,自己扩展ExtJS
name : "priceStart",
anchor : "95%"
}]
}, {
columnWidth : 0.15,
layout : "form",
labelWidth : 10,// 注意,这个参数在这里可以调整简单fieldLabel的布局位置
items : [{
fieldLabel : "至",
labelSeparator : "",
xtype : "textfield",
vtype : "double",// 实数格式验证,自己扩展ExtJS
name : "priceEnd",
anchor : "80%"
}]
},
{
columnWidth : 0.2,
layout : "form",
labelWidth : 40,
items : [{
xtype : "radio",
fieldLabel : "排序",
boxLabel : "升序",
name : "sortCond",
checked : true,
inputValue : "asc",// 这里如果用value,值是on,所以用inputValue(出现这种情况的是radio,checkbox)
anchor : "80%"
}]
}, {
columnWidth : 0.15,
layout : "form",
labelWidth : 1,// 让标签宽度为很小的值(奇怪的是为0时反而不行)
items : [{
xtype : "radio",
boxLabel : "降序",
labelSeparator : "",// 去除分隔符“:”
name : "sortCond",
inputValue : "desc",
anchor : "80%"
}]
}
]
}, {
xtype : "panel",
layout : "column",
fieldLabel : "区域",
isFormField : true,
items : [{
columnWidth : 0.3,
xtype : 'combo',
store : new Ext.data.SimpleStore({
fields : ['id', 'name'],
data : Ext.grid.areaComboBoxItems
}),
valueField : "id",
displayField : "name",
mode : 'local',
// anchor : "60%",
forceSelection : true,// 必须选择一项
emptyText : '请选择区域...',// 默认值
name : "area",
hiddenName : "area",// hiddenName才是提交到后台的input的name
editable : false,// 不允许输入
triggerAction : 'all',// 因为这个下拉是只能选择的,所以一定要设置属性triggerAction为all,不然当你选择了某个选项后,你的下拉将只会出现匹配选项值文本的选择项,其它选择项是不会再显示了,这样你就不能更改其它选项了。
id : 'parent_id',
name : 'parent',
listeners : {
select : function(combo, record, index) {
houseService.getAllStreets(combo.value,
function(data) {
if (data != null) {
var list2 = [];
for (var i = 0; i < data.length; i++) {
list2[i] = [
data[i].sid,
data[i].sname];
}
Ext.grid.streetComboBoxItems = list2;
Ext.getCmp('child_id')
.clearValue();
Ext.getCmp('child_id').store
.loadData(list2);
}
});
}
}
}, {
fieldLabel : '街道',// 默认值
columnWidth : 0.3,
labelWidth : 40,
xtype : 'combo',
store : new Ext.data.SimpleStore({
fields : ['id', 'name'],
data : []
}),
valueField : "id",
displayField : "name",
// 数据是在本地
mode : 'local',
forceSelection : true,// 必须选择一项
emptyText : '请选择街道...',// 默认值
editable : false,// 不允许输入
triggerAction : 'all',// 因为这个下拉是只能选择的,所以一定要设置属性triggerAction为all,不然当你选择了某个选项后,你的下拉将只会出现匹配选项值文本的选择项,其它选择项是不会再显示了,这样你就不能更改其它选项了。
// allowBlank:false,//该选项值不能为空
fieldLabel : '选择',
id : 'child_id',
name : "street",
hiddenName : "street",
anchor : "60%"
}
]
}],
buttons : [{
text : "确定",
handler : query,
formBind : true
}, {
text : "取消",
handler : reset
}]
});
}
function query() {
// alert(DWRUtil.getValue("sortCond"));
// 这里是关键,重新载入数据源,并把搜索表单值提交
ds.load({
params : {
start : 0,
limit : ptb.getPageSize(),
'cond.title' : Ext.get('title').dom.value,
'cond.areaId' : Ext.get('area').dom.value,
'cond.streetId' : Ext.get('street').dom.value,
'cond.room' : Ext.get('room').dom.value,
'cond.ting' : Ext.get('ting').dom.value,
'cond.booktime' : Ext.get('booktime').dom.value,
'cond.priceStart' : Ext.get('priceStart').dom.value,
'cond.priceEnd' : Ext.get('priceEnd').dom.value,
'cond.sortCond' : DWRUtil.getValue("sortCond")
// 换一种方式获取radio里的值
// 取得搜索表单文本域的值,发送到服务端
}
})
}
function reset() {
searchForm.form.reset();
}
ds = new Ext.data.Store({
// proxy: new Ext.data.MemoryProxy(jsondata),
proxy : new Ext.data.HttpProxy({
url : '../house.do'
}),
reader : new Ext.data.JsonReader({
totalProperty : 'totalProperty',
root : 'root'
}, [{
name : 'hid'
}, {
name : 'title'
}, {
name : 'linkman'
}, {
name : 'linktel'
}, {
name : 'hireprice'
}, {
name : 'booktimeInfo'
}, {
name : 'roomTing'
}, {
name : 'areaStreet'
}])
});
ds.load({
params : {
start : 0,
limit : limit
}
});
// 这里很关键,如果不加,翻页后搜索条件就变没了,这里的意思是每次数据载入前先把搜索表单值加上去,
// 这样就做到了翻页保留搜索条件了.如果struts框架里的form放在session区域,就可以省略。
// ds.on('beforeload', function() {
// Ext.apply(this.baseParams, {
// 'cond.title' : Ext.get('title').dom.value,
// 'cond.area' : Ext.get('area').dom.value,
// 'cond.street' : Ext.get('street').dom.value,
// 'cond.room' : Ext.get('room').dom.value,
// 'cond.ting' : Ext.get('ting').dom.value,
// 'cond.booktime' : Ext.get('booktime').dom.value,
// 'cond.priceStart' : Ext.get('priceStart').dom.value,
// 'cond.priceEnd' : Ext.get('priceEnd').dom.value,
// // sortCond : Ext.get('sortCond').dom.value,
// 'cond.sortCond' : DWRUtil.getValue("sortCond")
// // 换一种方式获取radio里的值
// });
// });
initGrid();
}
// 初始化显示表格
function initGrid() {
Ext.QuickTips.init();
// //////////////////////////////////////////////////////////////////////////////////////
// win
// //////////////////////////////////////////////////////////////////////////////////////
if (!win) {
win = new Ext.Window({
el : 'add-window',
layout : 'fit', // 布局方式fit,自适应布局
width : 350,
height : 400,
modal : true,
plain : true,
bodyStyle : 'padding:5px;',
maximizable : false,// 禁止最大化
closable : true,// 禁止关闭
collapsible : true,// 可折叠
buttonAlign : 'center',
closeAction : 'hide'
});
}
var sm = new Ext.grid.CheckboxSelectionModel();
var cm = new Ext.grid.ColumnModel([sm, {
id : 'hid',
header : "房屋号",
width : 20,
sortable : true,
dataIndex : 'hid'
}, {
header : "房屋标题",
width : 40,
sortable : true,
dataIndex : 'title'
}, {
header : "联系人",
width : 20,
sortable : true,
dataIndex : 'linkman'
}, {
header : "联系电话",
width : 30,
sortable : true,
dataIndex : 'linktel'
}, {
header : "月租金",
width : 30,
sortable : true,
renderer : function(value) {
// Ext.util.Format.usMoney
if (value > 1000) {
return "<span style='color:red;font-weight:bold;'>"
+ value + "</span>元";
} else {
return "<span style='color:green;font-weight:bold;'>"
+ value + "</span>元";
}
},
dataIndex : 'hireprice'
}, {
header : "发布日期",
width : 30,
sortable : true,
// renderer: Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex : 'booktimeInfo'
}, {
header : "房屋格局",
width : 40,
sortable : true,
dataIndex : 'roomTing'
}, {
header : "街道地址",
width : 60,
sortable : true,
dataIndex : 'areaStreet'
}]);
//定义一个完整的记录对象
TopicRecord = Ext.data.Record.create([{
name : 'hid',
mapping : 'house.hid'
},{
name : 'title',
mapping : 'house.title'
}, {
name : 'hireprice',
mapping : 'house.hireprice'
}, {
name : 'linkman',
mapping : 'house.linkman'
}, {
name : 'linktel',
mapping : 'house.linktel'
},{
name : 'room',
mapping : 'house.room'
},{
name : 'ting',
mapping : 'house.ting'
},{
name : 'areaId',
mapping : 'house.areaId'
},{
name : 'streetId',
mapping : 'house.streetId'
},{
name : 'housething',
mapping : 'house.housething'
}]);
//工具栏对象
ptb = new Ext.PagingToolbar({
plugins : new Ext.ux.Andrie.pPageSize(),
pageSize : limit,
store : ds,
displayInfo : true,
displayMsg : '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg : "对不起,查询记录为空!"
});
grid = new Ext.grid.GridPanel({
id : 'button-grid',
border : false,
buttonAlign : 'right',
ds : ds,
cm : cm,
sm : sm,
stripeRows : true,
loadMask : true,
viewConfig : {
forceFit : true
},
// inline toolbars
tbar : [{
id : 'houseAddBtn',
text : '发布',
tooltip : '发布一条房屋信息',
iconCls : 'add',
onClick : function() {
// update form to insert form
win.title = '添加房屋信息';
form = getInsertForm();
var items = new Ext.util.MixedCollection();
items.add("form", form);
win.items = items;
win.show();
//form.getForm().reset();
}
}, '-', {
id : 'houseEditBtn',
text : '编辑',
tooltip : '修改一条房屋信息',
iconCls : 'option',
onClick : function() {
if (sm.getCount() == 1) {
// update form to edit form
win.title = '编辑房屋信息';
form = getUpdateForm();
var items = new Ext.util.MixedCollection();
items.add("form", form);
win.items = items;
win.show();
form.getForm().reset();
var hid = sm.getSelected().data.hid;
houseService.findById(hid, callback);
function callback(data) {
//列表影射,columnModelvar
var myNewRecord = new TopicRecord({'house.hid':data.hid, 'house.title': data.title, 'house.hireprice':data.hireprice
,'house.linkman':data.linkman,'house.linktel':data.linktel,'house.room':data.room,'house.ting':data.ting,'house.areaId':data.areaId,'house.streetId':data.streetId,'house.housething':data.housething});
houseService.getAllStreets(data.areaId, function(
data) {
if (data != null) {
var list2 = [];
for (var i = 0; i < data.length; i++) {
list2[i] = [data[i].sid, data[i].sname];
}
Ext.getCmp('child_id2').clearValue();
Ext.getCmp('child_id2').store
.loadData(list2);
// 实际的一条记录
form.getForm().loadRecord(myNewRecord);
}
});
}
} else {
Ext.MessageBox.alert('提示', '请选择一条记录!');
}
}
}, '-', {
id : 'houseDelBtn',
text : '删除',
tooltip : '删除选择的房屋信息',
iconCls : 'remove',
onClick : function() {
if (sm.hasSelection()) {
Ext.MessageBox.confirm('提示', '你确定要删除这些租房信息么?',
function(button) {
if (button == 'yes') {
var list = sm.getSelections();
var rList = [];
for (var i = 0; i < list.length; i++) {
rList[i] = list[i].data["hid"];
}
houseService.delHouse(rList,
function(data) {
if (data > 0) {
Ext.MessageBox
.alert(
'提示',
"删除"
+ data
+ '条数据成功!');
// 如果把当页数据删除完毕,则跳转到上一页!
if (data == ptb.store
.getTotalCount()
- ptb.cursor) {
ptb.cursor = ptb.cursor
- ptb.pageSize;
}
ds.load({
params : {
start : ptb.cursor,
limit : ptb.pageSize
}
});
} else {
Ext.MessageBox
.alert(
'提示',
"删除数据失败!");
}
});
}
});
} else {
Ext.MessageBox.alert('提示', "请至少选择一条记录!");
}
}
}, '-', {
id : 'houseRefreshBtn',
text : '刷新',
tooltip : '刷新房屋信息',
iconCls : 'refresh',
onClick : function() {
ds.load({
params : {
start : ptb.cursor,
limit : ptb.pageSize
}
});
}
}, '-', {
id : 'houseCopyBtn',
text : '复制',
tooltip : '复制添加选择的房屋信息',
iconCls : 'copy',
onClick : function() {
if (sm.getCount() == 1) {
// update form to edit form
form = getInsertForm();
var items = new Ext.util.MixedCollection();
items.add("form", form);
win.items = items;
win.show();
var hid = sm.getSelected().data.hid;
houseService.findById(hid, callback);
function callback(data) {
//列表影射,columnModelvar
var myNewRecord = new TopicRecord({'house.hid':data.hid, 'house.title': data.title, 'house.hireprice':data.hireprice
,'house.linkman':data.linkman,'house.linktel':data.linktel,'house.room':data.room,'house.ting':data.ting,'house.areaId':data.areaId,'house.streetId':data.streetId,'house.housething':data.housething});
houseService.getAllStreets(data.areaId, function(
data) {
if (data != null) {
var list2 = [];
for (var i = 0; i < data.length; i++) {
list2[i] = [data[i].sid, data[i].sname];
}
Ext.getCmp('child_id1').clearValue();
Ext.getCmp('child_id1').store
.loadData(list2);
// 实际的一条记录
form.getForm().loadRecord(myNewRecord);
}
});
}
} else {
Ext.MessageBox.alert('提示', "请选择一条记录!");
}
}
}, '-', {
id : 'houseImportBtn',
text : '导入',
tooltip : '批量导入房屋信息',
iconCls : 'import',
onClick : function() {
}
}, '-', {
id : 'houseExportExcelBtn',
text : '导出Excel',
tooltip : '导出房屋信息',
iconCls : 'export',
onClick : function() {
window.location = "../houseExport.do?type=excel&start="
+ ptb.cursor + "&limit=" + ptb.pageSize;
}
}, '-', {
id : 'houseExportPdfBtn',
text : '导出Pdf',
tooltip : '导出房屋信息',
iconCls : 'export',
onClick : function() {
window.location = "../houseExport.do?type=pdf&start="
+ ptb.cursor + "&limit=" + ptb.pageSize;
}
}, '-', {
id : 'housePrintBtn',
text : '打印',
tooltip : '打印房屋信息',
iconCls : 'print',
onClick : function() {
//利用IE的简单打印
self.print();
}
}, '-', {
id : 'houseDetailBtn',
text : '详情',
tooltip : '查看所选房屋信息详情',
iconCls : 'details',
onClick : function() {
Ext.MessageBox.alert("详细",'舞动绚丽的ExtJS吧!');
Ext.alert(333);
}
}],
bbar : ptb,
width : 800,
autoHeight : true,
// height : 250,
// frame : true,
title : '房屋信息列表',
iconCls : 'icon-grid',
renderTo : document.body
});
grid.on('rowcontextmenu', rightClickFn);// 右键菜单代码关键部分
var rightClick = new Ext.menu.Menu({
id : 'rightClickCont',
items : [{
id : 'rMenu1',
handler : Ext.getCmp('houseAddBtn').onClick,// 点击后触发的事件
text : '添加信息'
}, {
id : 'rMenu2',
handler : Ext.getCmp('houseEditBtn').onClick,
text : '编辑信息'
}, {
id : 'rMenu3',
handler : Ext.getCmp('houseDelBtn').onClick,// 点击后触发的事件
text : '删除信息'
}, {
id : 'rMenu4',
handler : Ext.getCmp('houseRefreshBtn').onClick,
text : '刷新数据'
}, {
id : 'rMenu5',
handler : Ext.getCmp('houseCopyBtn').onClick,// 点击后触发的事件
text : '复制数据'
}, {
id : 'rMenu6',
handler : Ext.getCmp('houseImportBtn').onClick,
text : '导入数据'
}, {
id : 'rMenu7',
handler : Ext.getCmp('houseExportExcelBtn').onClick,// 点击后触发的事件
text : '导出EXCEL数据'
}, {
id : 'rMenu8',
handler : Ext.getCmp('houseExportPdfBtn').onClick,
text : '导出PDF数据'
}, {
id : 'rMenu9',
handler : Ext.getCmp('housePrintBtn').onClick,// 点击后触发的事件
text : '打印数据'
}, {
id : 'rMenu10',
handler : Ext.getCmp('houseDetailBtn').onClick,
text : '查看详情'
}]
});
function rightClickFn(grid, rowindex, e) {
e.preventDefault();
rightClick.showAt(e.getXY());
}
// function rMenuFnAdd() {
// Ext.getCmp('houseAddBtn').onClick;
// }
// function rMenuFnEdit() {
//
// }
// function rMenuFnDel() {
//
// }
// function rMenuFnRefresh() {
//
// }
// function rMenuFnCopy() {
// alert(Ext.getCmp('houseCopyBtn').onClick);
// return Ext.getCmp('houseCopyBtn').onClick;
// }
// function rMenuFnImport() {
//
// }
// function rMenuFnExportExcel() {
//
// }
// function rMenuFnExcelPdf() {
//
// }
// function rMenuFnPrint() {
//
// }
// function rMenuFnDetail() {
// return Ext.getCmp('houseDetailBtn').onClick;
// }
}
// 扩展extjs的验证!
Ext.apply(Ext.form.VTypes, {
// 固定电话、传真
phone : function(v) {
var r = /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/;
return r.test(v);
},
// 移动电话
mobile : function(v) {
var r = /^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$/;
return r.test(v);
},
// 邮政编码
zip : function(v) {
var r = /^[1-9]\d{5}$/;
return r.test(v);
},
// 搜索关键字过滤
search : function(v) {
var r = /^[^`~!@#$%^&*()+=|\\\][\]\{\}:;'\,.<>/?]*$/;
return r.test(v);
},
// 简体中文
chinese : function(v) {
var r = /^[\u0391-\uFFE5]+$/;
return r.test(v);
},
// 非中文
noChinese : function(v) {
var r = /^^[\u0391-\uFFE5]+$/;
return r.test(v);
},
// 货币
currency : function(v) {
var r = /^\d+(\.\d+)?$/;
return r.test(v);
},
qq : function(v) {
var r = /^[1-9]\d{4,8}$/;
return r.test(v);
},
// 实数
double : function(v) {
var r = /^[-\+]?\d+(\.\d+)?$/;
return r.test(v);
},
// 安全密码
safe : function(v) {
var r = /^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\"]*)|.{0,5})$|\s/;
return !r.test(v);
},
phoneText : '请输入正确的电话或传真号码!<br />格式如:0000-XXXXXXXX',
mobileText : '请输入正确的移动电话号码!<br />格式如:13XXXXXXXXX',
zipText : '请输入正确的邮政编码!',
searchText : '请不要输入非法的搜索字符!',
chineseText : '您只能在这里输入中文字符!',
noChineseText : '您不能在这里输入中文字符!',
currencyText : '请输入货币值!<br />格式如:1.00',
qqText : '请输入合法的QQ号码!',
doubleText : '请输入实数值,可带+/-号!',
safeText : '请输入足够安全的字符,包含英文和数字货其他字符!'
});