Ext JS 4实现带week(星期)的日期选择控件(实战一)

前言

  Ext JS 3 和 Ext JS 4中都有提供日期选择的组件(当然早期版本也有)。

Ext JS 4实现带week(星期)的日期选择控件(实战一)

  但是有一些日期选择的需求是要看到星期,就是日期中的哪一天是这一年的第几周。

  遗憾的是Ext js 并没有提供这样的配置。

  (针对Ext js 4来说,理想的相法是在Ext.picker.Date有一个 类似showWeek这样的配置项)

  现有的解法

  到网络上去看看基于Ext js 的解法:有找到两个

  http://enikao.net/extjs/weeknumber/weeknumber.html

  和

  http://www.lubber.de/extjs/datepickerplus/

  第一种解法在IE上work, 在其他浏览器上显示不出来, 直接忽视。

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

  Ext JS 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 要给一个空函数,否则选日期的时候会执行两次。