基于extjs6 的带时分秒的datetimefield

基于Extjs6 的带时分秒的日期选择框

首先实现一个带时分秒的picker
/**
 * author fencho
 * date: 2020-11-17
 */
Ext.define('W.picker.DateTime', {
    extend: 'Ext.picker.Date',
    alias: 'widget.w.datetimepicker',
    alternateClassName : 'Ext.DateTimePicker',
    // <locale>
    okText: 'ok',
    // </locale>
    /**
     * @cfg
     * @inheritdoc
     */
    renderTpl: [
        '<div id="{id}-innerEl" data-ref="innerEl" role="presentation">',
        '<div class="{baseCls}-header">',
        '<div id="{id}-prevEl" data-ref="prevEl" class="{baseCls}-prev {baseCls}-arrow" role="presentation" title="{prevText}"></div>',
        '<div id="{id}-middleBtnEl" data-ref="middleBtnEl" class="{baseCls}-month" role="heading">{%this.renderMonthBtn(values, out)%}</div>',
        '<div id="{id}-nextEl" data-ref="nextEl" class="{baseCls}-next {baseCls}-arrow" role="presentation" title="{nextText}"></div>',
        '</div>',
        '<table role="grid" id="{id}-eventEl" data-ref="eventEl" class="{baseCls}-inner" cellspacing="0" tabindex="0" aria-readonly="true">',
        '<thead>',
        '<tr role="row">',
        '<tpl for="dayNames">',
        '<th role="columnheader" class="{parent.baseCls}-column-header" aria-label="{.}">',
        '<div role="presentation" class="{parent.baseCls}-column-header-inner">{.:this.firstInitial}</div>',
        '</th>',
        '</tpl>',
        '</tr>',
        '</thead>',
        '<tbody>',
        '<tr role="row">',
        '<tpl for="days">',
        '{#:this.isEndOfWeek}',
        '<td role="gridcell">',
        '<div hidefocus="on" class="{parent.baseCls}-date"></div>',
        '</td>',
        '</tpl>',
        '</tr>',
        '</tbody>',
        '</table>',

        // 指定时分秒渲染框架
        '<table id="{id}-timeEl" style="table-layout:auto;margin:0 auto;width:90%;text-align:center;" class="x-datepicker-inner" cellspacing="0">',
        '<tbody><tr>',
        '<td width="30%">{%this.renderHourField(values,out)%}</td>',
        '<td width="35%">{%this.renderMinuteField(values,out)%}</td>',
        '<td width="35%">{%this.renderSecondField(values,out)%}</td>',
        '</tr></tbody>',
        '</table>',
        //

        '<tpl if="showToday">',
        '<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">',
        '{%this.renderTodayBtn(values, out)%}',

        // 增加了确认按钮
        '{%this.renderOkBtn(values, out)%}',
        //

        '</div>',
        '</tpl>',
        // These elements are used with Assistive Technologies such as screen readers
        '<div id="{id}-todayText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{todayText}.</div>',
        '<div id="{id}-ariaMinText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMinText}.</div>',
        '<div id="{id}-ariaMaxText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMaxText}.</div>',
        '<div id="{id}-ariaDisabledDaysText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDaysText}.</div>',
        '<div id="{id}-ariaDisabledDatesText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDatesText}.</div>',
        '</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);
            },

            // 指定渲染方法调用
            renderHourField : function(values, out) {
                Ext.DomHelper.generateMarkup(values.$comp.hourField
                    .getRenderTree(), out);
            },
            renderMinuteField : function(values, out) {
                Ext.DomHelper.generateMarkup(values.$comp.minuteField
                    .getRenderTree(), out);
            },
            renderSecondField : function(values, out) {
                Ext.DomHelper.generateMarkup(values.$comp.secondField
                    .getRenderTree(), out);
            },
            renderOkBtn : function(values, out) {
                Ext.DomHelper.generateMarkup(values.$comp.okBtn
                    .getRenderTree(), out);
            }
            //

        }
    ],
    beforeRender : function() {
        /*
         * days array for looping through 6 full weeks (6 weeks * 7 days)
         * Note that we explicitly force the size here so the template
         * creates all the appropriate cells.
         */
        var me = this,
            encode = Ext.String.htmlEncode,
            days = new Array(me.numDays),
            today = Ext.Date.format(new Date(), me.format);

        if (me.padding && !me.width) {
            me.cacheWidth();
        }

        // 支持时分秒
        me.hourField = new Ext.form.field.Number({
            ownerCt : me,
            ownerLayout : me.getComponentLayout(),
            editable: true,
            allowDecimals: false,
            minValue : 0,
            maxValue : 23,
            step : 1,
            width : '100%',
            fieldCls : Ext.baseCSSPrefix + 'form-field w-datetime',
            enableKeyEvents : true,
            listeners : {
                specialkey : function(field, e) {
                    if (e.getKey() == e.ENTER) {
                        e.stopEvent();
                        me.minuteField.focus(true);
                    }
                },
                afterrender: function (field, e) {
                    field.getEl().on('click', function (a, b) {
                        if (!field.hasFocus) {
                            // field.focus();
                        }
                    });
                }
            }
        });
        me.minuteField = new Ext.form.field.Number({
            ownerCt : me,
            ownerLayout : me.getComponentLayout(),
            editable: true,
            minValue : 0,
            maxValue : 59,
            allowDecimals: false,
            fieldCls : Ext.baseCSSPrefix + 'form-field w-datetime',
            step : 1,
            width : '100%',
            labelWidth : 5,
            fieldLabel : '&nbsp;',
            enableKeyEvents : true,
            listeners : {
                specialkey : function(field, e) {
                    if (e.getKey() == e.ENTER) {
                        e.stopEvent();
                        me.secondField.focus(true);
                    }
                },
                afterrender: function (field, e) {
                    field.getEl().on('click', function (a, b) {
                        a.stopPropagation()
                        // a.preventDefault();
                        // a.stopEvent();
                        if (!field.hasFocus) {
                            // field.focus();
                        }
                    });
                }
            }
        });
        me.secondField = new Ext.form.field.Number({
            ownerCt : me,
            ownerLayout : me.getComponentLayout(),
            editable: true,
            minValue : 0,
            maxValue : 59,
            allowDecimals: false,
            step : 1,
            width : '100%',
            labelWidth : 5,
            fieldLabel : '&nbsp;',
            fieldCls : Ext.baseCSSPrefix + 'form-field w-datetime',
            enableKeyEvents : true,
            listeners : {
                specialkey : function(field, e) {
                    if (e.getKey() == e.ENTER) {
                        e.stopEvent();
                        me.okBtn.focus(true);
                    }
                },
                afterrender: function (field, e) {
                    field.getEl().on('click', function (a, b) {
                        if (!field.hasFocus) {
                            // field.focus();
                        }
                    });
                }
            }
        });
        //

        me.monthBtn = new Ext.button.Split({
            ownerCt : me,
            ownerLayout : me.getComponentLayout(),
            text : '',
            tooltip : me.monthYearText,
            tabIndex : -1,
            ariaRole : 'presentation',
            listeners : {
                click : me.doShowMonthPicker,
                arrowclick : me.doShowMonthPicker,
                scope : me
            }
        });

        if (me.showToday) {

            // 自己加的
            me.okBtn = new Ext.button.Button({
                ui : me.footerButtonUI,
                ownerCt : me,
                ownerLayout : me.getComponentLayout(),
                text : me.okText,
                handler : me.okHandler, // 确认按钮的事件委托
                scope : me
            });
            //

            me.todayBtn = new Ext.button.Button({
                ui : me.footerButtonUI,
                ownerCt : me,
                ownerLayout : me.getComponentLayout(),
                tooltipType : 'title',
                tabIndex : -1,
                ariaRole : 'presentation',
                handler : me.selectToday,
                scope : me
            });
        }

        me.callParent();

        Ext.applyIf(me, {
            renderData : {}
        });

        Ext.apply(me.renderData, {
            dayNames : me.dayNames,
            showToday : me.showToday,
            prevText : encode(me.prevText),
            nextText : encode(me.nextText),
            todayText : encode(me.todayText),
            ariaMinText : encode(me.ariaMinText),
            ariaMaxText : encode(me.ariaMaxText),
            ariaDisabledDaysText : encode(me.ariaDisabledDaysText),
            ariaDisabledDatesText : encode(me.ariaDisabledDatesText),
            days : days
        });

        me.protoEl.unselectable();
    },

    handleDateClick: function(e, t) {
        var me = this;

        e.stopEvent();

        if (!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) {
            var hours = me.value.getHours(),
                minutes = me.value.getMinutes(),
                seconds = me.value.getSeconds(),
                selectedDate = new Date(t.dateValue);

            selectedDate.setHours(hours);
            selectedDate.setMinutes(minutes);
            selectedDate.setSeconds(seconds);
            me.setValue(selectedDate);
            me.update(selectedDate, true);
            /*me.setValue(new Date(t.dateValue));
            me.fireEvent('select', me, me.value);

            if (handler) {
                Ext.callback(handler, me.scope, [me, me.value], null, me, me);
            }

            // event handling is turned off on hide
            // when we are using the picker in a field
            // therefore onSelect comes AFTER the select
            // event.
            me.onSelect();*/
        }
    },
    onSelect: function() {
        if (this.hideOnSelect) {
            this.hide();
        }
    },
    /**
     * 确认 按钮触发的调用
     */
    okHandler : function() {
        var me = this,
            btn = me.okBtn,
            handler = me.handler;

        if (btn && !btn.disabled) {
            me.setValue(this.getValue());
            me.fireEvent('select', me, me.value);
            me.onSelect();

            if (handler) {
                Ext.callback(handler, me.scope, [me, me.value], null, me, me);
            }
        }
    },

    fullUpdate: function(date) {
        this.callParent(arguments);
        this.hourField.setValue(date.getHours());
        this.minuteField.setValue(date.getMinutes());
        this.secondField.setValue(date.getSeconds());
    },
    selectToday: function() {
        var me = this,
            btn = me.todayBtn,
            handler = me.handler;

        if (btn && !btn.disabled) {
            var date = new Date();
            me.hourField.setValue(date.getHours());
            me.minuteField.setValue(date.getMinutes());
            me.secondField.setValue(date.getSeconds());
            me.setValue(date);
            me.fireEvent('select', me, me.value);
            if (handler) {
                Ext.callback(handler, me.scope, [me, me.value], null, me, me);
            }
            me.onSelect();
        }
        return me;
    },
    update: function(date, forceRefresh) {
        this.hourField.setValue(date.getHours());
        this.minuteField.setValue(date.getMinutes());
        this.secondField.setValue(date.getSeconds());
        this.callParent(arguments);
    },

    setValue : function(value, isfixed) {
        // If passed a null value just pass in a new date object.

        var me = this;
        // 这里一定要用 Ext.Date.clone ,不然不会触发 isDirty事件
        this.value = Ext.Date.clone(value || new Date());
        if (isfixed !== true) {
            this.value.setHours(me.hourField.getValue());
            this.value.setMinutes(me.minuteField.getValue());
            this.value.setSeconds(me.secondField.getValue());
        }
        return this.update(this.value, true);
    },
    onMouseDown: function(e) {
        console.log(e);
        if (e.target.tagName === 'INPUT' && e.target.id.startsWith('numberfield')) {
            //时分秒 不处理
        } else {
            e.preventDefault();
        }
    },
    privates: {
        finishRenderChildren : function() {
            var me = this;

            me.callParent();

            me.hourField.finishRender();
            me.minuteField.finishRender();
            me.secondField.finishRender();

            if (me.showToday) {
                me.okBtn.finishRender();
            }
        },
    }
});

然后实现field

/**
 * author: fencho
 * date: 2020-11-17
 */
Ext.define('W.form.field.DateTime', {
	extend : 'Ext.form.field.Date',
	alias : 'widget.datetimefield',
	requires : [ 'W.picker.DateTime' ],

	createPicker : function() {
		var me = this, format = Ext.String.format;
		return new W.picker.DateTime({
			pickerField : me,
			floating : true,
			preventRefocus : true,
			hidden : true,
			minDate : me.minValue,
			maxDate : me.maxValue,
			disabledDatesRE : me.disabledDatesRE,
			disabledDatesText : me.disabledDatesText,
			ariaDisabledDatesText : me.ariaDisabledDatesText,
			disabledDays : me.disabledDays,
			disabledDaysText : me.disabledDaysText,
			ariaDisabledDaysText : me.ariaDisabledDaysText,
			format : me.format,
			showToday : me.showToday,
			startDay : me.startDay,
			minText : format(me.minText, me.formatDate(me.minValue)),
			ariaMinText : format(me.ariaMinText, me.formatDate(me.minValue,
					me.ariaFormat)),
			maxText : format(me.maxText, me.formatDate(me.maxValue)),
			ariaMaxText : format(me.ariaMaxText, me.formatDate(me.maxValue,
					me.ariaFormat)),
			listeners : {
				scope : me,
				select : me.onSelect,
				tabout : me.onTabOut
			},
			keyNavConfig : {
				esc : function() {
					me.inputEl.focus();
					me.collapse();
				}
			}
		});
	},

	onExpand : function() {
		var value = this.rawDate;
		this.picker.setValue(Ext.isDate(value) ? value : new Date(), true);
	}
})
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值