侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

一个被全世界错误使用的表单控件--日历控件

2022-06-28 星期二 / 0 评论 / 0 点赞 / 65 阅读 / 11672 字

日历就是日历,但它不是合适的时间选择器。 大部分的表单中凡是涉及时间选择的,都会采用日历选择器。大部分UI框架也会默认提供。在许多场景中使用这种控件并不合适,特别是一些二流的公司甚至没有和日历同步

日历就是日历,但它不是合适的时间选择器。

大部分的表单中凡是涉及时间选择的,都会采用日历选择器。大部分UI框架也会默认提供。在许多场景中使用这种控件并不合适,特别是一些二流的公司甚至没有和日历同步时间。

比如:

看起来挺炫,其实毫无意义。这个控件不会和字段内的时间同步,照理说控件显示的时候应该反应字段内的日期和时间。如果我幸幸苦苦选择到指定日期,不小心点错了一格,我必须重新来一遍。

再有一个情况是,如果是输入生日,那么必须在年份上下按钮点100次(如果100岁的话)。

采用html内置的选择器是更加合理的时间选择器。

以下是我写的控件:

{fieldName: "publishdAt",inputLabel: '发表日期',years:"-10,+10",ftype:'datetime'/*date*/,required:true,validators:{},gridSize:"1-2"},

配置很好理解,years以当前时间(不一定后面再说)为参考,-10,+10,当然是显示前后10年(根据需要),如果是编辑,字段本身已经有了值,那么这个前后是根据这个值的年份前后10年。

这样设计还有问题,如果年份超越了这个范围,不是无法输入了吗?当你点击日期select的时候,最下方有一个“其它”选项,当你选择这个值时,select会变成text字段,允许你输入任何年份,当你输入年份,text失去焦点之后,select字段又会回来。

还有一个隐藏的功能,就是当你改变年月或者月份的时候,这个控件的view会重画,何必呢?因为月份不同,日期的范围会变化。

外观:


最后是源代码:

var Lang = Y.Lang,    Ob = Y.Object,    fieldsViewNs = Y.namespace("M3958.CusFieldView");fieldsViewNs.CusDateTimeField = Y.Base.create('cusDateTimeField', Y.View, [], {    events: {        'input': {blur: 'onInputBlur'}    },    /**     * 控制input的宽度可以通过设置width style.     */    selectTpl: Y.Template.Micro.compile(            '<select class="<%= this.dmodel.type %>" style="display:inline;margin-left:2px;">' +                '<% for (var i=this.dmodel.range[0]; i<=this.dmodel.range[1];i++) { %>' +                    '<option value=<%= i %><%= (i == data.dmodel.cur) ? " selected" : "" %>><%= i + data.dmodel.postfix %></option>' +                '<% } %>' +           '</select>'            ),    template: Y.Template.Micro.compile(            '<label for="<%= this.guid %>"><%= this.fieldDescription.inputLabel %></label>' +            '<input type="text" placeholder="年份" style="width:50px;display:none;">'+            '<select id="<%= this.guid %>" class="<%= this.dmodel.type %>" style="display:inline;">' +                '<% for (var i=this.dmodel.range[0]; i<=this.dmodel.range[1];i++) { %>' +                    '<option value=<%= i %><%= (i == data.dmodel.cur) ? " selected" : "" %>><%= i + data.dmodel.postfix %></option>' +                '<% } %>' +                '<option value="otheryear">其它</option>' +            '</select>'    ),    initializer: function (){        var container = this.get('container'),            self = this,            model = this.get('model'),            fieldDescription = this.get('fieldDescription');                model.after('clientValidateErrorChange',function(e){            var validateResult = e.newVal;            if (!validateResult) {                return;            }            if (validateResult.isForField(fieldDescription.fieldName)) {                if (validateResult.msg) {                    container.addClass("validate-error");                } else {                    container.removeClass("validate-error");                }            }        },this);                this.on('destroy',function(e){            container.all('select').detachAll();        });    },    render: function () {        var container = this.get('container'),            fieldDescription = this.get('fieldDescription'),            formStyle = this.get('formStyle'),            label = fieldDescription.inputLabel,            tnum =  fieldDescription.ftype === 'datetime' ? 6 : 3,            helpInline = fieldDescription.helpInline,            self = this,            html,            yselect,            mselect,            dselect,            docfragment,            guid = Y.guid(),            dmodel,            idx = 1,            inputNode;                if (container.all('select')) {            container.all('select').detachAll();        }                if(Lang.isFunction(helpInline)){            helpInline = helpInline.call(this);        }                 if(Lang.isFunction(label)){            label = label.call(this);        }                if(fieldDescription.required && (Lang.isBoolean(fieldDescription.required) || Lang.isString(fieldDescription.required))){            label = '<strong>' + label + '</strong>';        }                dmodel = this.createDmodel();        html = this.template({                guid: guid,                dmodel: dmodel[0],                fieldDescription: fieldDescription            }        );                container.setHTML(html);                docfragment = Y.one(Y.config.doc.createDocumentFragment());                for (;idx < tnum;idx++) {            docfragment.append(this.selectTpl({                    dmodel: dmodel[idx]                }            ));        }                container.append(docfragment);                if (formStyle === 'aligned') {            container.addClass('pure-control-group');        } else {            if (fieldDescription.gridSize) {                container.addClass('pure-u-' + fieldDescription.gridSize);            } else {                container.addClass('pure-u-1');                            }        }                yselect = container.one('select.year');        mselect = container.one('select.month');        dselect = container.one('select.date');                yselect.after('change',function(){            self.afterSelectChange('y');        });                mselect.after('change',function(){            self.afterSelectChange('m');        });                dselect.after('change',function(){            self.afterSelectChange('d');        });                return this;    },    createDmodel: function(){        var container = this.get('container'),            fieldDescription = this.get('fieldDescription'),            years = fieldDescription.years,            model = this.get('model'),            value = model.get(fieldDescription.fieldName),            now = value ? new Date(value) : new Date(),            self = this,            yearstart,            yearend,            dmodel = [],            yearr = years.split(",");        if ((yearr[0].indexOf('-') === -1) && (yearr[0].indexOf('+') === -1)) { //没有加减号,值现在            yearstart = now.getFullYear();        } else {            yearstart = now.getFullYear() + parseInt(yearr[0]);        }                    if ((yearr[1].indexOf('-') === -1) && (yearr[1].indexOf('+') === -1)) { //没有加减号,值现在            yearend = now.getFullYear();        } else {            yearend = now.getFullYear() + parseInt(yearr[1]);        }                dmodel.push({range:[yearstart,yearend],cur:now.getFullYear(),type:'year',postfix:'年'});        dmodel.push({range:[1,12],cur:now.getMonth() + 1,type:'month',postfix:'月'});        dmodel.push({range:[1,Y.M3958.Util.DateTime.monthEnd(now.getFullYear(),now.getMonth())],cur:now.getDate(),type:'date',postfix:'日'});        dmodel.push({range:[0,23],cur:now.getHours(),type:'hour',postfix:'时'});        dmodel.push({range:[0,59],cur:now.getMinutes(),type:'minute',postfix:'分'});        dmodel.push({range:[0,59],cur:now.getSeconds(),type:'second',postfix:'秒'});                return dmodel;    },    getInputValue : function(){        var container = this.get('container'),            input = container.one('select');                return input.get('value');    },    getDateTimeLong : function(){        return Y.M3958.UtilsClass.DateUtils.tolong(this.getInputValue());    },    _getValue : function(){        var container = this.get('container'),            inputs = container.all('select'),            value = [];        inputs.each(function(nd){            value.push(parseInt(nd.get('value'),10));        });        return value;    },    saveValue : function(){        var fieldDescription = this.get('fieldDescription'),            model = this.get('model'),            v = this._getValue(),            dtv = new Date();                Y.Array.each(v,function(one,idx){            if (idx === 0) {                dtv.setFullYear(one);            } else if (idx === 1) {                dtv.setMonth(one - 1);            } else if (idx === 2) {                dtv.setDate(one);            } else if (idx === 3) {                dtv.setHours(one);            } else if (idx === 4) {                dtv.setMinutes(one);            } else if (idx === 5) {                dtv.setSeconds(one);            }        });                    if (model) {            model.set(fieldDescription.fieldName,dtv.getTime());         }    },    afterSelectChange: function(t){        var fieldDescription = this.get('fieldDescription'),            container = this.get('container'),            yselect = container.one('select.year'),            dinput = container.one('input'),            model = this.get('model');                    if (t === 'y' && yselect.get('value') === 'otheryear') {            dinput.setStyle('display','inline');            yselect.setStyle('display','none');            dinput.focus();            return;        }        this.saveValue();                if (model && model.validateOneField) {            model.validateOneField(fieldDescription);        }                if (t === 'm' || t === 'y') {            this.render();        }    },    onInputBlur: function() {        var fieldDescription = this.get('fieldDescription'),            container = this.get('container'),            yselect = container.one('select.year'),            dvalue = container.one('input').get('value'),            model = this.get('model'),            value = model.get(fieldDescription.fieldName),            d = new Date(value);        /**         * 只是改变year的值,其它的不变。         */        if (dvalue) {            d.setFullYear(parseInt(dvalue,10));            model.set(fieldDescription.fieldName,d.getTime());            this.render();        }            }},{    ATTRS: {        container: {            valueFn: function () {                return Y.Node.create('<div></div>');            }        },        fieldDescription : {            value : null        },        model: {            value: null        }    }});
这个select change事件不会冒泡(ie<10),所以必须拙劣的在每个select上面订阅事件,看官如果有办法,不要吝啬告诉我一声。

广告 广告

评论区