ExtJS 4 带星期的日期选择控件

前言


ExtJS 3 和 ExtJS 4中都有提供日期选择的组件(当然早期版本也有)。
但是有一些日期选择的需求是要看到星期,就是日期中的哪一天是这一年的第几周。
遗憾的是ExtJS 并没有提供这样的配置。
(针对ExtJS 4来说,理想的相法是在Ext.picker.Date有一个 类似showWeek这样的配置项)

现有的解法


到网络上去看看基于Ext js 的解法:有找到两个
http://enikao.NET/extjs/weeknumber/weeknumber.html

http://www.lubber.de/extjs/datepickerplus/
第一种解法在IE上work, 在其他浏览器上显示不出来, 直接忽视。
第二种解法支持 ExtJS 2 和 ExtJS 3 版本,但是不支持ExtJS 4。凭着个人在ExtJS 升级上的一些经验,一开始觉得把这个扩展升级到ExtJS 4应该没有什么问题。鼓捣了半天,放弃了。 ExtJS 3 升级到ExtJS 4后, 日期页面的显示元素也做了修改, 旧版本用 tr td 居多,新版本中多了一些 div 和 a 元素。而且class 的名字也换掉了。这样看起来,升级阻力较大。只能自己来实现这个扩展了。

ExtJS 4 日期控件扩展


先贴上代码:
/********************************* 
 * @author: oscar999 
 * @Description: New Widgets Extend from Ext 
 * @verion: V1.0 
 **********************************/  
  
/** 
 * Date Picker with Week 
 */  
Ext.define('Ext.ux.DatePickerWithWeek',{  
    extend: "Ext.picker.Date",  
    alias : "widget.datepickerwithweek",  
    width: 197,  
    numWeeks: 6,      
    renderTpl:[  
                '<div id="{id}-innerEl" role="grid">',  
                '<div role="presentation" class="{baseCls}-header">',  
                       
                    '<a id="{id}-prevEl" class="{baseCls}-prev {baseCls}-arrow" href="#" role="button" title="{prevText}" hidefocus="on" ></a>',  
                    '<div class="{baseCls}-month" id="{id}-middleBtnEl">{%this.renderMonthBtn(values, out)%}</div>',  
                       
                    '<a id="{id}-nextEl" class="{baseCls}-next {baseCls}-arrow" href="#" role="button" title="{nextText}" hidefocus="on" ></a>',  
                '</div>',  
                '<table id="{id}-eventEl" class="{baseCls}-inner" cellspacing="0" role="grid">',  
                    '<thead role="presentation"><tr role="row">',  
                        '<th role="columnheader" class="{parent.baseCls}-column-header" title="{.}">',  
                            '<div class="{parent.baseCls}-column-header-inner">Wk</div>',  
                        '</th>',      
                        '<tpl for="dayNames">',  
                            '<th role="columnheader" class="{parent.baseCls}-column-header" title="{.}">',  
                                '<div class="{parent.baseCls}-column-header-inner">{.:this.firstInitial}</div>',  
                            '</th>',  
                        '</tpl>',  
  
                    '</tr></thead>',  
                    '<tbody role="presentation"><tr role="row">',  
                        '<tpl for="days">',                             
                            '{#:this.isEndOfWeek}',  
                            '{#:this.isBeginOfWeek}',  
                            '<td role="gridcell" id="{[Ext.id()]}">',                               
                                '<a role="presentation" hidefocus="on" class="{parent.baseCls}-date" href="#"></a>',  
                            '</td>',  
                        '</tpl>',  
                    '</tr></tbody>',  
                '</table>',  
                '<tpl if="showToday">',  
                    '<div id="{id}-footerEl" role="presentation" class="{baseCls}-footer">{%this.renderTodayBtn(values, out)%}</div>',  
                '</tpl>',  
            '</div>',  
            {  
                firstInitial: function(value) {  
                    //alert(value);  
                    return Ext.picker.Date.prototype.getDayInitial(value);  
                },  
                isBeginOfWeek: function(value){  
                    //value--;  
                    //value--;  
                    var end = (value === 1 || (value-1)%7 === 0);  
                    return end ? '<td role="weekcell" id="{[Ext.id()]}"><a role="presentation"></a></td>' : '';  
  
                },  
                isEndOfWeek: function(value) {                                        
                    value--;  
                    var end = value % 7 === 0 && value !== 0;  
                    return end ? '</tr><tr role="row">' : '';  
                },                
                renderTodayBtn: function(values, out) {  
                    Ext.DomHelper.generateMarkup(values.$comp.todayBtn.getRenderTree(), out);  
                },  
                renderMonthBtn: function(values, out) {  
                    Ext.DomHelper.generateMarkup(values.$comp.monthBtn.getRenderTree(), out);  
                }  
            }  
        ],  
        fullUpdate: function(date){           
            this.callParent([date]);              
  
            var me = this;  
            var weekNodes = me.weekNodes;  
            var curWeekStart = Ext.Date.clearTime(new Date(date.getFullYear(), date.getMonth(), 1));      
            var begMonWeek = Ext.Date.getWeekOfYear(curWeekStart);  
            var firstDayOfMonth = Ext.Date.getFirstDayOfMonth(curWeekStart);  
            if(firstDayOfMonth===0)  
            {  
                begMonWeek +=1;  
            }  
            for(j=0;j<me.numWeeks;j++)  
            {                 
                weekNodes[j].innerHTML = begMonWeek.toString();  
                begMonWeek++;  
            }    
        },  
        onRender : function(container, position){             
            var me = this;  
            me.callParent(arguments);  
            me.cells = me.eventEl.select('tbody td[role="gridcell"]');  
            me.textNodes = me.eventEl.query('tbody td[role="gridcell"] a');  
              
            //begin extend  
            me.weekcells= me.eventEl.select('tbody td[role="weekcell"]');  
            me.weekNodes= me.eventEl.query('tbody td[role="weekcell"] a');  
            //end extend  
            me.mon(me.eventEl, {  
                scope: me,  
                mousewheel: me.handleMouseWheel,  
                click: {  
                    //fn: me.handleDateClick,  
                    fn: function(){},  
                    delegate: 'a.' + me.baseCls + '-date'  
                }  
            });  
        }  
        /*,initComponent: function(){ 
            this.callParent(); 
        }*/  
});  
  
/* 
* Date Form field use Date Picker with Week 
*/  
Ext.define('Ext.ux.DateFieldWithWeek',{  
    extend: "Ext.form.field.Date",  
    alias : "widget.datefieldwithweek",  
    /*initComponent: function(){ 
        this.callParent(); 
    },*/  
    createPicker : function(){  
        var me = this  
        format = Ext.String.format;  
        return new Ext.ux.DatePickerWithWeek({  
            pickerField: me,  
            ownerCt: me.ownerCt,  
            renderTo: document.body,  
            floating: true,  
            hidden: true,  
            focusOnShow: true,  
            minDate: me.minValue,  
            maxDate: me.maxValue,  
            disabledDatesRE: me.disabledDatesRE,  
            disabledDatesText: me.disabledDatesText,  
            disabledDays: me.disabledDays,  
            disabledDaysText: me.disabledDaysText,  
            format: me.format,  
            showToday: me.showToday,  
            startDay: me.startDay,  
            minText: format(me.minText, me.formatDate(me.minValue)),  
            maxText: format(me.maxText, me.formatDate(me.maxValue)),  
            listeners: {  
                scope: me,  
                select: me.onSelect  
            },  
            keyNavConfig: {  
                esc: function() {  
                    me.collapse();  
                }  
            }  
        });  
    }  
});  

原理很简单:
1. 改写 renderTpl, 增加星期显示的列
2. 改写fullUpdate, 设置星期的值。 Ext 有提供getWeekOfYear这个方法可以获取星期
3. onRender。 这里需要特别注意的就是click 中的fn: me.handleDateClick 要给一个空函数,否则选日期的时候会执行两次。

作者: oscar999
原文: http://blog.csdn.net/oscar999/article/details/9984679