注:本人工作之前不会Ext, 现在多少懂得一点,完全是在工作中被练出来的. 这篇文章只为记录自己工作中学习到的点滴. 如果碰巧某条能对某位朋友有帮助,不胜欣慰。。
一、Ext 动态增删下拉列表项
如上图,做一个流量统计,选定一个日期范围后,可以在下拉列表中选择 按日或按年显示,但因为时间跨度很大时,数据量会很多,图表上的点会挤成一坨,所以要做如下限制:
1. 全部 和 本年,或手动输入日期查询,两个日期的间隔大于90天时, 只能按月显示,即这时下拉列表中只有 “按月显示” 这一条
2. 本月, 上个月, 最近三个月,及手动输入日期查询,两个日期的间隔大于90天时, 可以按日显示或按月显示
这就要求下拉列表的选项可以根据条件实时变动,但由于Ext的下拉列表组件的实现比较复杂,不能像操作原生select那样去操作。关于这个组件,是copy项目中其它地方的代码,如下:
//数据源
var data = [];
data.push(['day', ' 按日显示']);
data.push(['month', ' 按月显示']);
var activeBoxDS = new Ext.data.SimpleStore({
fields: ['value', 'label'],
data: data
});
//下拉菜单组件
var activeBox = new Ext.form.ComboBox({
id: 'showBy',
name: 'showBy',
value:'month',
store: activeBoxDS,
valueField: 'value', //下拉项的值是activeBoxDS的 value 域
displayField: 'label', //下拉项的显示的是activeBoxDS的 label 域
typeAhead: false,
mode: 'local',
triggerAction: 'all',
selectOnFocus: true,
editable: false,
width: 95,
listeners: {
'select': function(item, e){
if(queryParams.showBy != activeBox.getValue()) {//如果显示条件有变,则重新获取数据,queryParams.showBy存的是上一次的显示条件(day | month)
updateData();
}
}
}
});
关于如何动态实现增删,着实是费了一翻工夫才实现,这里也不废话了,直接说结果,下面红色为新增的代码:
//数据源
var activeBoxDS = new Ext.data.SimpleStore({
fields: ['value', 'label'],
data: data
});
//最开始要把这两个下拉项存起来
var dayRecord = activeBoxDS.getAt(0);
var monthRecord = activeBoxDS.getAt(1);
//初始时选中的是'全部',所以只有'按月显示',应删掉'按日显示'(这个我目前还没有更好的办法,只能定义时把两个都定义了,然后初始时先删一个)
activeBoxDS.remove(dayRecord);
//下拉菜单组件
var activeBox = new Ext.form.ComboBox({
id: 'showBy',
name: 'showBy',
value:'month',
store: activeBoxDS,
valueField: 'value', //下拉项的值是activeBoxDS的 value 域
displayField: 'label', //下拉项的显示的是activeBoxDS的 label 域
typeAhead: false,
mode: 'local',
triggerAction: 'all',
selectOnFocus: true,
editable: false,
width: 95,
listeners: {
'select': function(item, e){
if(queryParams.showBy != activeBox.getValue()) {//如果显示条件有变,则重新获取数据,queryParams.showBy存的是上一次的显示条件(day | month)
updateData();
}
}
}
});
然后在时间范围变动的监听器中添加处理代码:
//"全部",“本月”,“上个月”,“最近三个月” 及 “本年”的点击事件监听
$(".date-point").click(function() {
var $this = $(this),
type = $this.attr("data-type");
$this.addClass('current').siblings(".date-point").removeClass('current');
//先删除全部下拉项,再在下面按情况添加
activeBoxDS.removeAll();
switch(type) {
case 'all': //'全部'
case 'cur-year': //本年
//添加按月显示下拉项
activeBoxDS.add(monthRecord);
activeBox.setValue('month');
break;
case 'cur-month': //本月
case 'last-month': //上个月
case 'recent3month': //最近三个月,即本月,上月,上上月
//添加按月显示和按日显示下拉项
activeBoxDS.add(dayRecord);
activeBoxDS.add(monthRecord);
activeBox.setValue('day');
break;
}
//更新图表
updateData();
});
此外,也要给日期输入框添加事件:
var startField = new Ext.form.DateField({
readOnly: true,
hideLabel: true,
name: 'start_field',
style: 'overflow:visible',
id: 'start_field',
format: 'Y-m-d',
width: 142,
listeners:{ //给日期组件加事件监听
change: dateChangeHandler //虽然事件是change,可表现却跟blur相同,即只有在blur时才会触发监听器
}
});
var endField = new Ext.form.DateField({
readOnly: true,
hideLabel: true,
name: 'end_field',
style: 'overflow:visible',
id: 'end_field',
format: 'Y-m-d',
width: 142,
listeners:{
change: dateChangeHandler //虽然事件是change,可表现却跟blur相同,即只有在blur时才会触发监听器
}
});
function dateChangeHandler() {
var sd = startField.getRawValue();
var ed = endField.getRawValue();
if(sd != queryParams.startDate || ed != queryParams.endDate) { //当查询日期变动时才处理
if(getDayGap(sd,ed) > 90) {//当查询日期间隔大于90天时,只能按月显示
activeBoxDS.removeAll();
activeBoxDS.add(monthRecord);
activeBox.setValue('month');
//改变查询参数
queryParams.showBy = 'month';
} else {
activeBoxDS.removeAll();
activeBoxDS.add(dayRecord);
activeBoxDS.add(monthRecord);
activeBox.setValue('day');
//改变查询参数
queryParams.showBy = 'day';
}
//计算两个日期之间相差的天数
function getDayGap(strStartDate,strEndDate) {
//为了兼容IE7,string类型的日期得这么转,如果直接将其作为参数传给new Date(),在IE7下new出来的是一个NaN
var sArr = strStartDate.split('-'),
eArr = strEndDate.split('-'),
sd = new Date(),
ed = new Date(),
dayGap = 0;
sd.setFullYear(sArr[0]);
sd.setMonth(sArr[1]);
sd.setDate(sArr[2]);
ed.setFullYear(eArr[0]);
ed.setMonth(eArr[1]);
ed.setDate(eArr[2]);
dayGap = (ed.getTime() - sd.getTime())/24/3600/1000; //getTime()返回的值是毫秒,所以需要除以1000
return dayGap;
}
}
}
大意如此,上面并非项目中的完整代码,为了突出重点,将无关代码删减了.