现在的位置: 首页 > easyui > 正文
将my97日期控件集成到easyui框架中
2013年02月28日 easyui, My97 ⁄ 共 10652字 评论数 17 ⁄ 被围观 20,725 views+
文章目录
[隐藏]

My97DatePicker控件的大名很多人都听过了,作为一款国产的日期时间控件,它的功能和性能各方面都是数一数二的。相对而言,jQuery Easyui的datebox和datetimebox的功能就有点捉襟见肘了。也因为如此,很多使用了Easyui框架的童鞋依旧会选择my97作为日期控件使用。

通常情况下,我们只要导入My97DatePicker的核心javascript文件就能在Easyui框架中使用my97了,而且用法也比较简单,比如以下代码就能轻松使用my97以及Easyui的validatebox组件:

  1. <input id="d411" class="Wdate easyui-validatebox" type="text" onfocus="WdatePicker({skin:'whyGreen',minDate:'2006-09-10',maxDate:'2008-12-20'})"/>

既然直接使用也很简单,为何还要集成?本文就针对直接使用my97的弊端以及如何集成my97到Easyui框架中做较为全面的描述。

直接使用my97的缺点:

my97编码方式与Easyui存在点差异

在Easyui的世界中,我们习惯了使用class来注册组件,或者是用jQuery来注册组件,而my97无法通过class注册。这一点很多人可能觉得吹毛求疵,不过对于我个人而已,同一项目中存在不同的组件编码风格总归让人觉得不舒服。

my97的DOM结构样式跟Easyui存在差异

这一点是毋庸置疑的了,my97的结构简单,只有一个文本框,其日期图标实际上只是文本框的背景图片。而easyui的对应组件却是一个文本框和一个span元素组成的。当然了,要解决这个问题也很简单,my97自身也是可以灵活设置触发点的,DOM结构可以模拟得跟easyui对应组件一样,然后再加以CSS就可基本解决问题。

my97样式与validatabox组件样式冲突

my97与validatebox样式的冲突的根本原因依然是DOM结构的差异,也可以通过问题二的同样方式去解决,而这样做的代价除了写css文件外,还要每个组件都要自己手动写较复杂的DOM,比如my97用以下DOM模拟datebox:

  1. <span class="my97-wrap">
  2.     <input id="my97_2" type="text" class="easyui-validatebox my97-text" data-options="required:true" onclick="WdatePicker();">
  3.     <span>
  4.         <span class="my97-arrow" onclick="WdatePicker({el:'my97_2'});"></span>
  5.     </span>
  6. </span>

我们来看一下我最终模拟的效果:
http://www.easyui.info/easyui/demo/my97/062.html

实现my97与EasyUI的集成:

集成二者其实也就是为了解决直接使用my97的不足之处,而我们做集成的思路也就是前面用my97模拟databox的思路,只不过我们把这种零碎的操场封装成为EasyUI的插件更为方便罢了,直接上代码:

jquery.my97.js文件:
  1. /**  
  2.  * my97 - jQuery EasyUI  
  3.  * Licensed under the GPL:  
  4.  * http://www.gnu.org/licenses/gpl.txt  
  5.  * Copyright 2013 小雪转中雪 [ caoguanghuicgh@163.com ] [http://www.easyui.info]  
  6.  */
  7. (function ($) {
  8.     //如果没有my97控件,则添加之。   
  9.     (function () {
  10.         var hasmy97 = false;
  11.         var plugins = $.parser.plugins;
  12.         for (var i = plugins.length - 1; i > -1; i--) {
  13.             if (plugins[i] === "my97") {
  14.                 hasmy97 = true;
  15.                 break;
  16.             }
  17.         }
  18.         if (hasmy97 == false) {
  19.             $.parser.plugins[$.parser.plugins.length] = "my97";
  20.         }
  21.     })();
  22.     function init(target) {
  23.         $(target).addClass("my97-text")
  24.         var wrap = $("<span class=\"my97-wrap\"></span>").insertBefore(target);
  25.         wrap[0].appendChild(target);
  26.         var arrow = $("<span class=\"my97-arrow\"></span>").insertAfter(target);
  27.         return wrap;
  28.     };
  29.     /**
  30.      * 绑定事件用以触发原生的my97控件  
  31.      * @param  {[type]} target [description]  
  32.      * @return {[type]}        [description]  
  33.      */
  34.     function bindEvents(target) {
  35.         var data = $.data(target, "my97");
  36.         var opts = data.options;
  37.         var wrap = $.data(target, "my97").my97;
  38.         var input = wrap.find(".my97-text");
  39.         var arrow = wrap.find(".my97-arrow");
  40.         input.unbind(".my97");
  41.         arrow.unbind(".my97");
  42.         if (!opts.disabled) {
  43.             input.bind("click.my97"function (e) {
  44.                 //TODO 触发my97   
  45.                 WdatePicker(opts);
  46.             });
  47.             arrow.bind("click.my97",function () {
  48.                 //TODO 触发my97   
  49.                 WdatePicker($.extend({}, opts, {el:opts.id}));
  50.             }).bind('mouseenter.my97',
  51.                 function (e) {
  52.                     $(this).addClass('my97-arrow-hover');
  53.                 }).bind('mouseout.my97',
  54.                 function (e) {
  55.                     $(this).removeClass('my97-arrow-hover');
  56.                 }
  57.             );
  58.         }
  59.     };
  60.     /**
  61.      * 销毁组件  
  62.      * @param  {document object} target 承载组件的输入框  
  63.      * @return {[type]}        [description]  
  64.      */
  65.     function destroy(target) {
  66.         var input = $.data(target, "my97").my97.find("input.my97-text");
  67.         input.validatebox("destroy");
  68.         $.data(target, "my97").my97.remove();
  69.         $(target).remove();
  70.     };
  71.     function validate(target, doit) {
  72.         var opts = $.data(target, "my97").options;
  73.         var input = $.data(target, "my97").my97.find("input.my97-text");
  74.         input.validatebox(opts);
  75.         if (doit) {
  76.             input.validatebox("validate");
  77.         }
  78.     };
  79.     function initValue(target) {
  80.         var opts = $.data(target, "my97").options;
  81.         var input = $.data(target, "my97").my97.find("input.my97-text");
  82.         input.val(opts.value);
  83.     }
  84.     function setDisabled(target, disabled) {
  85.         var ops = $.data(target, "my97").options;
  86.         var my97 = $.data(target, "my97").my97;
  87.         var arrow = my97.find('.my97-arrow');
  88.         if (disabled) {
  89.             ops.disabled = true;
  90.             $(target).attr("disabled"true);
  91.             arrow.unbind('click.my97');
  92.             arrow.unbind('hover.my97');
  93.         } else {
  94.             ops.disabled = false;
  95.             $(target).removeAttr("disabled");
  96.             arrow.unbind('click.my97').bind('click.my97', function () {
  97.                 WdatePicker(opts);
  98.             });
  99.             arrow.unbind('mouseenter.my97').unbind('mouseout').bind('mouseenter.my97',
  100.                 function (e) {
  101.                     this.addClass('my97-arrow-hover');
  102.                 }).bind('mouseenter.my97',
  103.                 function (e) {
  104.                     this.removeClass('my97-arrow-hover');
  105.                 }
  106.             );
  107.         }
  108.     };
  109.     /**
  110.      * 设置输入框宽度,主要这里是指box模型的width  
  111.      * @param {document object} target 承载控件的输入框  
  112.      * @param {number} width  宽度  
  113.      */
  114.     function setWidth(target, width) {
  115.         var opts = $.data(target, "my97").options;
  116.         opts.width = width;
  117.         $(target).width(width);
  118.     }
  119.     function setValue(target, value) {
  120.         $(target).val(value);
  121.     }
  122.     function getValue(target) {
  123.         return $(target).val();
  124.     }
  125.     /**
  126.      * 因为my97图片触发方式,必要id,所以在没有设置id的情况下,设置一个唯一ID  
  127.      * @param {[type]} target [description]  
  128.      */
  129.     function setId(target) {
  130.         var pre = "_easyui_my97_id_";
  131.         var opts = $.data(target, "my97").options;
  132.         opts.id = pre + $.fn.my97.defaults.count;
  133.         $(target).attr("id", opts.id);
  134.         $.fn.my97.defaults.count++;
  135.     }
  136.     $.fn.my97 = function (options, param) {
  137.         if (typeof options == 'string') {
  138.             return $.fn.my97.methods[options](this, param);
  139.         }
  140.         options = options || {};
  141.         return this.each(function () {
  142.             var state = $.data(this, 'my97');
  143.             var opts;
  144.             if (state) {
  145.                 opts = $.extend(state.options, options);
  146.             } else {
  147.                 opts = $.extend({}, $.fn.my97.defaults, $.fn.my97.parseOptions(this), options);
  148.                 var wrap = init(this);
  149.                 state = $.data(this, 'my97', {
  150.                     options:opts,
  151.                     my97:wrap
  152.                 });
  153.             }
  154.             if (opts.id == undefined) {
  155.                 setId(this);
  156.             }
  157.             setWidth(this, state.options.width);
  158.             setDisabled(this, state.options.disabled);
  159.             bindEvents(this);
  160.             validate(this);
  161.             initValue(this);
  162.         });
  163.     };
  164.     $.fn.my97.methods = {
  165.         options:function (jq) {
  166.             return $.data(jq[0], 'my97').options;
  167.         },
  168.         destroy:function (jq, param) {
  169.             return jq.each(function () {
  170.                 destroy(this, param);
  171.             });
  172.         },
  173.         setWidth:function (jq, param) {
  174.             return jq.each(function () {
  175.                 setWidth(this, param);
  176.             });
  177.         },
  178.         setValue:function (jq, param) {
  179.             setValue(jq[0], param);
  180.         },
  181.         getValue:function (jq, param) {
  182.             return getValue(jq[0]);
  183.         }
  184.     };
  185.     /**
  186.      * 属性转换器,继承validatebox组件属性  
  187.      * @param  {document object} target 承载my97的输入框  
  188.      * @return {object}        属性列表  
  189.      */
  190.     $.fn.my97.parseOptions = function (target) {
  191.         var t = $(target);
  192.         return $.extend({}, $.fn.validatebox.parseOptions(target), $.parser.parseOptions(target, ["width""height""weekMethod""lang""skin""dateFmt""realDateFmt", 'realTimeFmt', 'realFullFmt', 'minDate', 'maxDate', 'startDate',
  193.             {
  194.                 doubleCalendar:"boolean",
  195.                 enableKeyboard:"boolean",
  196.                 enableInputMask:"boolean",
  197.                 isShowWeek:"boolean",
  198.                 highLineWeekDay:"boolean",
  199.                 isShowClear:"boolean",
  200.                 isShowOthers:"boolean",
  201.                 readOnly:"boolean",
  202.                 qsEnabled:"boolean",
  203.                 autoShowQS:"boolean",
  204.                 opposite:"boolean"
  205.             }, {
  206.                 firstDayOfWeek:"number",
  207.                 errDealMode:"number"
  208.             }]),
  209.             {
  210.                 value:(t.val() || undefined),
  211.                 disabled:(t.attr("disabled") ? true : undefined),
  212.                 id:(t.attr("id") || undefined)
  213.             });
  214.     };
  215.     $.fn.my97.defaults = {
  216.         id:null,
  217.         count:0,
  218.         value:'',
  219.         width:109,
  220.         height:22,
  221.         disabled:false,
  222.         doubleCalendar:false,
  223.         enableKeyboard:true,
  224.         enableInputMask:true,
  225.         weekMethod:'ISO8601',
  226.         position:{},
  227.         lang:'auto',
  228.         skin:'default',
  229.         dateFmt:'yyyy-MM-dd',
  230.         realDateFmt:'yyyy-MM-dd',
  231.         realTimeFmt:'HH:mm:ss',
  232.         realFullFmt:'%Date %Time',
  233.         minDate:'1900-01-01 00:00:00',
  234.         maxDate:'2099-12-31 23:59:59',
  235.         startDate:'',
  236.         firstDayOfWeek:0,
  237.         isShowWeek:false,
  238.         highLineWeekDay:true,
  239.         isShowClear:true,
  240.         isShowOthers:true,
  241.         readOnly:false,
  242.         errDealMode:0,
  243.         qsEnabled:true,
  244.         autoShowQS:false,
  245.         opposite:false,
  246.         quickSel:[],
  247.         disabledDays:null,
  248.         disabledDates:null,
  249.         specialDates:null,
  250.         specialDays:null,
  251.         onpicking:function () {
  252.         },
  253.         onpicked:function () {
  254.         },
  255.         onclearing:function () {
  256.         },
  257.         oncleared:function () {
  258.         }
  259.     };
  260. })(jQuery);

注意:该文件放在themes下你要用到的皮肤下即可。

如何使用?

先引入javascript和css文件

javascript文件之间是有依赖关系的,先要引入EasyUi和my97的核心文件,然后再引入我扩展的名为"my97"的EasyUI组件的javascript文件,至于css文件,先后顺序则无影响,比如:

  1. <link rel="stylesheet" type="text/css" href="../../themes/default/easyui.css">
  2. <link rel="stylesheet" type="text/css" href="../../themes/default/my97.css">
  3. <link rel="stylesheet" type="text/css" href="../../themes/icon.css">
  4. <script type="text/javascript" src="../../jquery-1.8.0.min.js"></script>
  5. <script type="text/javascript" src="../../../third/My97DatePicker/WdatePicker.js"></script>
  6. <script type="text/javascript" src="../../jquery.easyui.min.js"></script>
  7. <script type="text/javascript" src="../../plugins/jquery.my97.js"></script>
像EasyUI的其它组件一样使用

到这里,你就可以跟使用EasyUI的datebox组件一样,用class或者jQuery注册my97组件了,例如使用class注册:

  1. <input type="text" class="easyui-my97" data-options="required:true,disabled:false,value:'2012-12-13',minDate:'2012-12-12',maxDate:'2012-12-25'">

又或者是使用jQuery注册:

  1. $('#dd').my97({});

使用场景:

暂未整理

效果演示:

http://www.easyui.info/easyui/demo/my97/061.html

接口文档:

暂未整理,属性基本与原生的my97属性一致,请查看my97官方的API文档

更新说明:

本篇文章写的扩展不适合1.4版本,适合1.4版本的扩展抽空会在此处补上!

目前有 17 条留言 其中:访客:11 条, 博主:6 条

  1. 蚂蚁哥哥 : 2013年06月25日16:44:01  -49楼 @回复 回复

    jquery.my97.js这个在ie中报”对象不支持此属性或方法”,我查看对应位置,是$.fn.my97 = function(options, param) { }中的return this.each(function() {});

    js文件引入顺序和你的要求一下,另外,你的示例在ie中也有问题

    我测试的欢迎是ie8

    希望能解释一下,另外解决一下


    • 管理员
      世纪之光 : 2013年06月26日09:16:45  地下1层 @回复 回复

      我的演示我用IE8再次测试了一下,没有发现任何问题啊,你能说得清楚一点吗?

  2. carry : 2013年08月04日15:29:32  -48楼 @回复 回复

    第195行 少了 return


    • 管理员
      世纪之光 : 2013年08月06日18:20:13  地下1层 @回复 回复

      谢谢提醒呀,已经更正了。

      • GLAN : 2013年12月11日20:23:45  地下2层 @回复 回复

        在easyui-dialog弹出窗口中加

        无法显示日期选择框

      • damon : 2015年06月25日15:15:01  地下2层 @回复 回复

        楼主 啥时候1.4的搞出来 不太会前端


        • 管理员
          世纪之光 : 2015年06月26日17:02:20  地下3层 @回复 回复

          尽量六月份做完,看来需要的人还是蛮多的。

  3. dengyong : 2014年10月13日14:05:04  -47楼 @回复 回复

    在data-options中设置required:true,并设置value值,初始时间控件背景显示为验证不通过的红色背景,希望能给予解答~

    代码:<input type=”text” class=”easyui-my97″ data-options=”value:’2014-10-13′, required:true, disabled:false” style=”width:160px;”>

    版本:
    easyui:1.4
    my97: 4.8 Beta4


    • 管理员
      世纪之光 : 2014年10月13日20:08:45  地下1层 @回复 回复

      你好,1.4版本除了新的组件textbox,本篇文章写的扩展已经不适合1.4,应该基于textbox去扩展。
      我周末抽空会重写一遍适合1.4的扩展。

    • 向阳 : 2015年11月25日11:49:01  地下1层 @回复 回复

      楼主,这个1.4以上的版本可以用了,现在继续这个

  4. 222 : 2015年01月08日11:03:14  -46楼 @回复 回复

    示例4-3-1 前面的日期不能大于后面的日期且两个日期都不能大于 2020-10-01

    这个怎么实现?


    • 管理员
      世纪之光 : 2015年01月08日12:33:47  地下1层 @回复 回复

      后面的日期设置maxDate为2020-10-01,前面的日期maxDate设置请参见my97官网demo和文档的“脚本自定义限制”

  5. 333 : 2015年02月04日17:30:48  -45楼 @回复 回复

    这个可编辑GRID里面怎么用不了啊!


    • 管理员
      世纪之光 : 2015年02月05日21:00:24  地下1层 @回复 回复

      你好,这个扩展不支持1.4以及更高的版本。如果是低版本的,用在可编辑表格中最好是扩展一个对应的编辑器类型使用。

  6. 向阳xlt : 2016年01月08日10:29:39  -44楼 @回复 回复

    支持easyui1.4.3版本的时候出来啊,现在有急用,谢谢

  7. 11 : 2017年03月31日16:54:33  -43楼 @回复 回复

    一步一步做得,出不来啊?求指教

  8. smf : 2017年04月24日09:32:40  -42楼 @回复 回复

    支持easyui1.4版本的在datagrid生成的表格内使用的啥时候出来啊,现在有急用,谢谢

给我留言

留言无头像?


×