我开发了个人日期派克的代码,
但是当我测试我的代码时,我有这个错误:**
console.trace() engine.js:789
dwr.engine._debug engine.js:789
dwr.engine.defaultErrorHandler engine.js:180
(anonymous function) engine.js:627
(anonymous function) engine.js:519
Error: TypeError, Cannot call method 'select' of null engine.js:790
console.trace() engine.js:789
dwr.engine._debug engine.js:789
dwr.engine.defaultErrorHandler engine.js:180
(anonymous function) engine.js:627
(anonymous function) engine.js:519
Error: TypeError, Cannot read property 'firstDay' of null
**
注意,我已经更新了相同的代码以便在 extjs 4.2 中工作
这是我的 js 页面:
Ext.ux.DateHijriPicker.js
/**
* @class Ext.ux.DateHijriPicker
* @extends Ext.Component
* <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
* to allow browsing and selection of valid dates.</p>
* <p>All the string values documented below may be overridden by including an Ext locale file in
* your page.</p>
* @constructor
* Create a new DateHijriPicker
* @param {Object} config The config object
* @xtype datehijripicker
*/
//Ext.ux.DateHijriPicker = Ext.extend(Ext.BoxComponent, {
Ext.define('Ext.ux.DateHijriPicker', {
extend: 'Ext.Component',
alias: 'widget.datehijripickerr',
alternateClassName: 'Ext.DatePicker',
childEls: [
'innerEl', 'eventEl', 'prevEl', 'nextEl', 'middleBtnEl', 'footerEl'
],
border: true,
renderTpl: [
'<div id="{id}-innerEl" role="grid">',
'<div role="presentation" class="{baseCls}-header">',
// the href attribute is required for the :hover selector to work in IE6/7/quirks
'<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>',
// the href attribute is required for the :hover selector to work in IE6/7/quirks
'<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">',
'<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}',
'<td role="gridcell" id="{[Ext.id()]}">',
// the href attribute is required for the :hover selector to work in IE6/7/quirks
'<a role="button" 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) {
return Ext.picker.Date.prototype.getDayInitial(value);
},
isEndOfWeek: function(value) {
// convert from 1 based index to 0 based
// by decrementing value once.
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);
}
}
],
/**
* @cfg {String} todayText
* The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
*/
todayText : 'Today',
cancelText : 'Cancel',
todayTip : '{0} (Spacebar)',
minText : 'This date is before the minimum date',
maxText : 'This date is after the maximum date',
format : 'm/d/y',
disabledDaysText : 'Disabled',
disabledDatesText : 'Disabled',
monthNames : month_AR/*Date.monthNames*/,
dayNames : day_AR/*Date.dayNames*/,
nextText : 'Next Month (Control+Right)',
prevText : 'Previous Month (Control+Left)',
monthYearText : 'Choose a month (Control+Up/Down to move years)',
startDay : 0,
showToday : true,
// private
// Set by other components to stop the picker focus being updated when the value changes.
focusOnSelect: true,
// default value used to initialise each date in the DateHijriPicker
// (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
initHour: 12, // 24-hour format
// private
initComponent : function(){
Ext.ux.DateHijriPicker.superclass.initComponent.call(this);
this.value = this.value ?
this.value.clearTime(true) : new MyDate().clearTime();
this.addEvents(
/**
* @event select
* Fires when a date is selected
* @param {DateHijriPicker} this DateHijriPicker
* @param {Date} date The selected date
*/
'select'
);
if(this.handler){
this.on('select', this.handler, this.scope || this);
}
this.initDisabledDays();
},
// private
initDisabledDays : function(){
/*if(!this.disabledDatesRE && this.disabledDates){
var dd = this.disabledDates,
len = dd.length - 1,
re = '(?:';
Ext.each(dd, function(d, i){
re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
if(i != len){
re += '|';
}
}, this);
this.disabledDatesRE = new RegExp(re + ')');
}*/
},
setDisabledDates : function(dd){
/*if(Ext.isArray(dd)){
this.disabledDates = dd;
this.disabledDatesRE = null;
}else{
this.disabledDatesRE = dd;
}
this.initDisabledDays();
this.update(this.value, true);*/
},
setDisabledDays : function(dd){
/*this.disabledDays = dd;
this.update(this.value, true);*/
},
setMinDate : function(dt){
/*this.minDate = dt;
this.update(this.value, true);*/
},
setMaxDate : function(dt){
/*this.maxDate = dt;
this.update(this.value, true);*/
},
/**
* Sets the value of the date field
* @param {Date} value The date to set
*/
setValue : function(value){
this.value = value.clearTime(true);
this.update(this.value);
},
getValue : function(){
return this.value;
},
// private
focus : function(){
//this.update(this.activeDate);
},
// private
onEnable: function(initial){
},
// private
onDisable : function(){
Ext.ux.DateHijriPicker.superclass.onDisable.call(this);
this.doDisabled(true);
if(Ext.isIE && !Ext.isIE8){
Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
Ext.fly(el).repaint();
});
}
},
// private
doDisabled : function(disabled){
this.keyNav.setDisabled(disabled);
this.prevRepeater.setDisabled(disabled);
this.nextRepeater.setDisabled(disabled);
if(this.showToday){
this.todayKeyListener.setDisabled(disabled);
this.todayBtn.setDisabled(disabled);
}
},
onRender : function(container, position){
var me = this;
me.callParent(arguments);
me.cells = me.eventEl.select('tbody td');
me.textNodes = me.eventEl.query('tbody td a');
me.mon(me.eventEl, {
scope: me,
mousewheel: me.handleMouseWheel,
click: {
fn: me.handleDateClick,
delegate: 'a.' + me.baseCls + '-date'
}
});
},
initEvents: function(){
var me = this,
eDate = Ext.Date,
day = eDate.DAY;
me.callParent();
me.prevRepeater = new Ext.util.ClickRepeater(me.prevEl, {
handler: me.showPrevMonth,
scope: me,
preventDefault: true,
stopDefault: true
});
me.nextRepeater = new Ext.util.ClickRepeater(me.nextEl, {
handler: me.showNextMonth,
scope: me,
preventDefault:true,
stopDefault:true
});
me.keyNav = new Ext.util.KeyNav(me.eventEl, Ext.apply({
scope: me,
left : function(e){
if(e.ctrlKey){
me.showPrevMonth();
}else{
me.update(eDate.add(me.activeDate, day, -1));
}
},
right : function(e){
if(e.ctrlKey){
me.showNextMonth();
}else{
me.update(eDate.add(me.activeDate, day, 1));
}
},
up : function(e){
if(e.ctrlKey){
me.showNextYear();
}else{
me.update(eDate.add(me.activeDate, day, -7));
}
},
down : function(e){
if(e.ctrlKey){
me.showPrevYear();
}else{
me.update(eDate.add(me.activeDate, day, 7));
}
},
pageUp:function (e) {
if (e.altKey) {
me.showPrevYear();
} else {
me.showPrevMonth();
}
},
pageDown:function (e) {
if (e.altKey) {
me.showNextYear();
} else {
me.showNextMonth();
}
},
tab:function (e) {
me.doCancelFieldFocus = true;
me.handleTabClick(e);
delete me.doCancelFieldFocus;
return true;
},
enter : function(e){
e.stopPropagation();
return true;
},
//space: ???
home:function (e) {
me.update(eDate.getFirstDateOfMonth(me.activeDate));
},
end:function (e) {
me.update(eDate.getLastDateOfMonth(me.activeDate));
}
}, me.keyNavConfig));
if (me.showToday) {
me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday, me);
}
me.update(me.value);
},
createMonthPicker: function(){
var me = this,
picker = me.monthPicker;
if (!picker) {
me.monthPicker = picker = new Ext.picker.Month({
renderTo: me.el,
floating: true,
padding: me.padding,
shadow: false,
small: me.showToday === false,
listeners: {
scope: me,
cancelclick: me.onCancelClick,
okclick: me.onOkClick,
yeardblclick: me.onOkClick,
monthdblclick: me.onOkClick
}
});
if (!me.disableAnim) {
// hide the element if we're animating to prevent an initial flicker
picker.el.setStyle('display', 'none');
}
me.on('beforehide', Ext.Function.bind(me.hideMonthPicker, me, [false]));
}
return picker;
},
// private
showMonthPicker : function(){
if(!this.disabled){
this.createMonthPicker();
var size = this.el.getSize();
this.monthPicker.setSize(size);
this.monthPicker.child('table').setSize(size);
this.mpSelMonth = (this.activeDate || this.value).getMonth();
this.updateMPMonth(this.mpSelMonth-1);
this.mpSelYear = (this.activeDate || this.value).getYear();
this.updateMPYear(this.mpSelYear);
this.monthPicker.slideIn('t', {duration:0.2});
}
},
// private
updateMPYear : function(y){
this.mpyear = y;
var ys = this.mpYears.elements;
for(var i = 1; i <= 10; i++){
var td = ys[i-1], y2;
if((i%2) === 0){
y2 = y + Math.round(i * 0.5);
td.firstChild.innerHTML = y2;
td.xyear = y2;
}else{
y2 = y - (5-Math.round(i * 0.5));
td.firstChild.innerHTML = y2;
td.xyear = y2;
}
this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
}
},
// private
updateMPMonth : function(sm){
this.mpMonths.each(function(m, a, i){
m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
});
},
// private
selectMPMonth : function(m){
},
// private
onMonthClick : function(e, t){
e.stopEvent();
var el = new Ext.Element(t), pn;
if(el.is('button.x-date-mp-cancel')){
this.hideMonthPicker();
}
else if(el.is('button.x-date-mp-ok')){
var d = new MyDate(this.mpSelYear, (this.mpSelMonth+1), (this.activeDate || this.value).getDay());
if(d.getMonth() != (this.mpSelMonth+1)){
// 'fix' the JS rolling date conversion if needed
d = new MyDate(this.mpSelYear, (this.mpSelMonth+1), 1); //.getLastDateOfMonth();
}
this.update(d);
this.hideMonthPicker();
}
else if((pn = el.up('td.x-date-mp-month', 2))){
this.mpMonths.removeClass('x-date-mp-sel');
pn.addClass('x-date-mp-sel');
this.mpSelMonth = pn.dom.xmonth;
}
else if((pn = el.up('td.x-date-mp-year', 2))){
this.mpYears.removeClass('x-date-mp-sel');
pn.addClass('x-date-mp-sel');
this.mpSelYear = pn.dom.xyear;
}
else if(el.is('a.x-date-mp-prev')){
this.updateMPYear(this.mpyear-10);
}
else if(el.is('a.x-date-mp-next')){
this.updateMPYear(this.mpyear+10);
}
},
// private
onMonthDblClick : function(e, t){
e.stopEvent();
var el = new Ext.Element(t), pn;
if((pn = el.up('td.x-date-mp-month', 2))){
this.update(new MyDate(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDay()));
this.hideMonthPicker();
}
else if((pn = el.up('td.x-date-mp-year', 2))){
this.update(new MyDate(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDay()));
this.hideMonthPicker();
}
},
// private
hideMonthPicker : function(disableAnim){
if(this.monthPicker){
if(disableAnim === true){
this.monthPicker.hide();
}else{
this.monthPicker.slideOut('t', {duration:0.2});
}
}
},
// private
showPrevMonth : function(e){
this.update(this.activeDate.add('mo', -1));
},
// private
showNextMonth : function(e){
this.update(this.activeDate.add('mo', 1));
},
// private
showPrevYear : function(){
this.update(this.activeDate.add('y', -1));
},
// private
showNextYear : function(){
this.update(this.activeDate.add('y', 1));
},
// private
handleMouseWheel : function(e){
e.stopEvent();
if(!this.disabled){
var delta = e.getWheelDelta();
if(delta > 0){
this.showPrevMonth();
} else if(delta < 0){
this.showNextMonth();
}
}
},
// private
handleDateClick : function(e, t){
e.stopEvent();
if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
/*this.cancelFocus = this.focusOnSelect === false;
this.setValue(t.dateValue);
delete this.cancelFocus;
this.fireEvent('select', this, this.value);*/
this.setValue(t.dateValue);
this.fireEvent('select', this, this.value);
}
},
// private
selectToday : function(){
if(this.todayBtn && !this.todayBtn.disabled){
this.setValue(this.today/*new Date()*/.clearTime());
this.fireEvent('select', this, this.value);
}
},
// private
update : function(date, forceRefresh){
var objRef = this;
var dateHijri = date.getYear() + "/" + date.getMonth() + "/" + date.getDay();
registrationNewRequestService.getHijriPicker(dateHijri, {
callback:function(hijriPicker){
objRef.updatepicker(hijriPicker, date, forceRefresh);
}
});
},
//updatepicker
updatepicker : function(hijriPicker, date, forceRefresh){
if(this.rendered){
var vd = this.activeDate, vis = this.isVisible();
this.activeDate = date;
if(!forceRefresh && vd && this.el){
var t = date.getTime();
if(vd.getMonth() == date.getMonth() && vd.getYear() == date.getYear()){
this.cells.removeClass('x-date-selected');
this.cells.each(function(c){
if(c.dom.firstChild.dateValue.dateFormat() == t.dateFormat()){
c.addClass('x-date-selected');
if(vis && !this.cancelFocus){
Ext.fly(c.dom.firstChild).focus(50);
}
return false;
}
}, this);
return;
}
}
//this.today = new Date();
//this.today_h = gregorianToHijri(new MyDate(this.today.getDate(), (this.today.getMonth() + 1), this.today.getFullYear()));
//this.today = this.field.parseDate(this.today_h.getDate());
var field = this;
var date_h = new MyDate(date.getYear(), date.getMonth(), date.getDay());
var firstday_h = hijriPicker.firstDay; //getHijriFirstDay(date_h);
var monthdays_h = hijriPicker.monthDays; //getHijriMonthDays(date_h);
this.monthdays = monthdays_h;
var days = monthdays_h;
var startingPos = firstday_h; //-this.startDay;
/*if(startingPos < 0){
startingPos += 7;
}*/
days += startingPos;
var itemsPrev = hijriPicker.datePrevHijri.split("/");
var datePrevHijri = new MyDate(itemsPrev[0], itemsPrev[1], itemsPrev[1]);
var prevMonthFirstDay_h = datePrevHijri; //date_h.getPreviousMonthFirstDayDate();
var prevMonthdays_h = hijriPicker.monthPrevDays; //getHijriMonthDays(prevMonthFirstDay_h);
//alert(this.datePrevHijri + "::" + this.monthPrevDays);
this.bmonth = prevMonthFirstDay_h.month;
this.bmonthdays = prevMonthdays_h;
//var pm = this.parseDate(prevMonthFirstDay_h.getDate())/*date.add('mo', -1)*/,
var prevStart = prevMonthdays_h/*pm.getDaysInMonth()*/-startingPos,
cells = this.cells.elements,
textEls = this.textNodes,
// convert everything to numbers so it's fast
//d = (new Date(prevMonthFirstDay_h.year/*pm.getFullYear()*/, prevMonthFirstDay_h.month-1/*pm.getMonth()*/, prevStart, this.initHour)),
d = new MyDate(prevMonthFirstDay_h.year, prevMonthFirstDay_h.month, prevStart),
today = this.today/*new Date()*/.clearTime().getTime(),
sel = date.clearTime(true).getTime(),
min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
ddMatch = this.disabledDatesRE,
ddText = this.disabledDatesText,
ddays = this.disabledDays ? this.disabledDays.join('') : false,
ddaysText = this.disabledDaysText,
format = this.format;
//alert("d:" + d);
if(this.showToday){
var td = this.today/*new Date()*/.clearTime(),
disable = (td < min || td > max ||
(ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
(ddays && ddays.indexOf(td.getDay()) != -1));
/*if(!this.disabled){
this.todayBtn.setDisabled(disable);
this.todayKeyListener[disable ? 'disable' : 'enable']();
}*/
}
var setCellClass = function(cal, cell, day){
cell.title = '';
var t = d.clearTime(true).getTime();
cell.firstChild.dateValue = t;
if(field.today && t.dateFormat() == field.today.dateFormat()){
cell.className += ' x-date-today';
cell.title = cal.todayText;
}
//alert(t.dateFormat() +"=="+ sel.dateFormat() + "::" + (t.dateFormat() == sel.dateFormat()))
if(sel && t.dateFormat() == sel.dateFormat()){
cell.className += ' x-date-selected';
if(vis){
Ext.fly(cell.firstChild).focus(50);
}
}
};
var dd="";
var i = 0;
for(; i < startingPos; i++) {
textEls[i].innerHTML = (++prevStart);
d = this.nextDate(d); /*d.setDate(d.getDate()+1);*/
cells[i].className = 'x-date-prevday';
setCellClass(this, cells[i], (i%7));
dd+=i+","+d+","+textEls[i].innerHTML+"\n";
}
for(; i < days; i++){
var intDay = i - startingPos + 1;
textEls[i].innerHTML = (intDay);
d = this.nextDate(d); /*d.setDate(d.getDate()+1);*/
cells[i].className = 'x-date-active';
setCellClass(this, cells[i], (i%7));
dd+=i+","+d+","+textEls[i].innerHTML+"\n";
}
var extraDays = 0;
for(; i < 42; i++) {
textEls[i].innerHTML = (++extraDays);
d = this.nextDate(d); /*d.setDate(d.getDate()+1);*/
cells[i].className = 'x-date-nextday';
setCellClass(this, cells[i], (i%7));
dd+=i+","+d+","+textEls[i].innerHTML+"\n";
}
//alert(dd)
this.mbtn.setText(month_AR[date.getMonth()-1] + ' ' + date.getYear());
if(!this.internalRender){
var main = this.el.dom.firstChild,
w = main.offsetWidth;
this.el.setWidth(w + this.el.getBorderWidth('lr'));
Ext.fly(main).setWidth(w);
this.internalRender = true;
// opera does not respect the auto grow header center column
// then, after it gets a width opera refuses to recalculate
// without a second pass
if(Ext.isOpera && !this.secondPass){
main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
this.secondPass = true;
this.update.defer(10, this, [date]);
}
}
}
},
nextDate: function(date){
var myDate = new MyDate();
if(date.getDay() < this.bmonthdays){
myDate.setDay(date.getDay() + 1);
myDate.setMonth(date.getMonth());
myDate.setYear(date.getYear());
}else{
if(this.bmonth < 12){
myDate.setDay(1);
myDate.setMonth(date.getMonth()+1);
myDate.setYear(date.getYear());
}else{
myDate.setDay(1);
myDate.setMonth(1);
myDate.setYear(date.getYear() + 1);
}
this.bmonth = myDate.getMonth();
this.bmonthdays = this.monthdays;
}
return myDate;
},
// private
beforeDestroy : function() {
if(this.rendered){
Ext.destroy(
this.keyNav,
this.monthPicker,
this.eventEl,
this.mbtn,
this.nextRepeater,
this.prevRepeater,
this.cells.el,
this.todayBtn
);
delete this.textNodes;
delete this.cells.elements;
}
}
});