0

我开发了个人日期派克的代码,

但是当我测试我的代码时,我有这个错误:**

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;
        }
    }


});
4

0 回答 0