[Ext JS 4] 實戰之 帶week(星期)的日期選擇控制元件
阿新 • • 發佈:2019-02-18
前言
Ext JS 3 和 Ext JS 4中都有提供日期選擇的元件(當然早期版本也有)。
但是有一些日期選擇的需求是要看到星期,就是日期中的哪一天是這一年的第幾周。
遺憾的是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 要給一個空函式,否則選日期的時候會執行兩次。