BootStrap中datepicker的使用和修改

笔者的应用场景是angular封装下的bootstrap中datepicker的使用。并一定程度上展示这个插件的diy修改.

这两天用到了bootstrap中的datepicker插件。然后查阅了一下各种资料,总的来说,这个插件还是很好用的。但是网上的示例多以自由情景下的使用,多配合jQuery或者js来使用,而像笔者这样使用angularJs下封装的datepicker还是比较少的。

惯例是先列出几个需要注意的点和可能遇到的坑
(1)注意,若是指定max-date,格式是这个的max-date=“‘2015-02-12’” , 是的,注意到双引号里面还有单引号(文中有详细说明)。建议缺省。

下面上干货
1.效果展示
为了给大家一个直观的印象,也方便下面讲解,我们一改惯例,这次先做效果的展示,然后再讲解实现和原理。
正常状态下
这里写图片描述

点击按钮后
这里写图片描述

2.代码部分

(1)html部分

<div ng-controller="DatepickerCtrl">
<p class="input-group">
    <input datepicker-popup type="text" class="form-control input-sm" ng-model="dt"  ng-model-options="{updateOn:'blur'}" is-open="opened" min-date="minDate" weekStart="0" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
    <span class="input-group-btn">
        <button type="button" class="btn btn-sm" ng click="open($event)">
                <i class="glyphicon glyphicon-calendar"></i>
        </button>
    </span>
</p>
</div>

简单解释一下,首先指定了一个controller,然后给定了一个input-group, 由一个输入框和一个图标按钮组成。这里有几个东西要说明一下。datepicker-popup是一个指令,这个指令已经由datepicker封装好,只管拿来用。ng-model是双向绑定了一个变量值,这里一定要给定一个参数(如:‘dt’), 不然无法传值,也没办法打开日期选择面板。min-date属性指定的是可选择的最小日期,其实还有一个max-date属性来指定可选择的最大日期,缺省情况下为当前日期加100年,在指定范围之外的日期不可选。
注意,若是指定max-date,格式是这个的max-date=“‘2015-02-12’” , 是的,注意到双引号里面还有单引号。且指定的日期一定要足够大,如果小于当下日期,则所有日期不可选,原理就是上面提到的指定范围之外的日期不可选。建议缺省。
这里有一个date-disabled属性,我们在后面修改datepicker插件的时候会提到它,它可以控制显示面板的部分日期不可选。
其他的参数和属性,读者如果有兴趣,笔者给出一个参考资料 http://www.bootcss.com/p/bootstrap-datetimepicker/

(2)controller部分

*控制Datapicker*/
Main.controller('DatepickerCtrl', ['$scope', function ($scope) {


    // Disable weekend selection
    $scope.disabled = function (date, mode) {
        return ( mode === 'day' && false);
    };

    $scope.toggleMin = function () {
        $scope.minDate = $scope.minDate ? null : new Date();
    };
    $scope.toggleMin();

    $scope.open = function ($event) {
        $event.preventDefault();
        $event.stopPropagation();

        $scope.opened = true;
    };

    $scope.dateOptions = {
        formatYear: 'yy',
        startingDay: 1,
        class: 'datepicker'
    };

    $scope.initDate = new Date('2016-15-20');
    $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
    $scope.format = $scope.formats[0];
}]);

至此,我们的日期选择器基本完成了。但是,接下来,我们会发现有些问题需要调整。因为angular封装了的bootstrap里的datepicker是有一定的限制的,比如它不可以选择周末。
下面以这个为例,来演示一下,具体的修改datepicker源码的方法和流程, 以实现我们自己想要的效果。

(3)DIY修改datepicker插件

(1)我们首先需要分析一下页面,即找出问题的原因在哪里
下面有两张图,一张是我们在firefox浏览器里的显示页面,另一张就是下面对应的开发者工具中显示的页面源码。
这里写图片描述

这里写图片描述

很明显,周末处于不可选择状态。经过分析源码,我们不难发现,在每一个td标签里有这样一个属性:aria-disabled,这个属性在对应的日期上取值是不完全相同的,很容易发现。可以选择的工作日状态,该属性都是false。不可选择的周末状态,该属性的值都是true。于是,基本确定了该属性控制了日期的可选状态。
事实上,aria-disabled属性是指定一个元素是不是出于active状态。该属性值为true时,表示element非响应状态。关于这个属性的具体解释,我们会在最后的参考资料中给出一个更为详细的介绍。
(2)然后我们需要看一下,这个模态框的构造代码写在了哪一个部分,又是怎样构造的
项目依赖的js和css还是很多的,但是从命名上我们可以比较容易筛选出一些更有可能的js. 最后我们定位到了ui-bootstrap-tpls.js这个js文件中。我们留意到,我们这个模态框的构造代码如下:

angular.module("template/datepicker/day.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/day.html",
    "<table role=\"grid\" aria-labelledby=\"{{uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
    "  <thead>\n" +
    "    <tr>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
    "      <th colspan=\"{{5 + showWeeks}}\"><button id=\"{{uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"toggleMode()\" tabindex=\"-1\" style=\"width:100%;\"><strong>{{title}}</strong></button></th>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
    "    </tr>\n" +
    "    <tr>\n" +
    "      <th ng-show=\"showWeeks\" class=\"text-center\"></th>\n" +
    "      <th ng-repeat=\"label in labels track by $index\" class=\"text-center\"><small aria-label=\"{{label.full}}\">{{label.abbr}}</small></th>\n" +
    "    </tr>\n" +
    "  </thead>\n" +
    "  <tbody>\n" +
    "    <tr ng-repeat=\"row in rows track by $index\">\n" +
    "      <td ng-show=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
    "      <td ng-repeat=\"dt in row track by dt.date\" class=\"text-center\" role=\"gridcell\" id=\"{{dt.uid}}\" aria-disabled=\"{{!!dt.disabled}}\">\n" +
    "        <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default btn-sm\" ng-class=\"{'btn-info': dt.selected, active: isActive(dt)}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\" tabindex=\"-1\"><span ng-class=\"{'text-muted': dt.secondary, 'text-info': dt.current}\">{{dt.label}}</span></button>\n" +
    "      </td>\n" +
    "    </tr>\n" +
    "  </tbody>\n" +
    "</table>\n" +
    "");
}]);

观察这段代码,我们可以找到刚才在浏览器的开发工具中看到的aria-disabled=\"{{!!dt.disabled}}\"
这句话是说,我们取一个变量值,传递给aria-disabled这个属性。
这里写图片描述
我们可以发现在这段源码中,this.disabled这个属性的值由,三个部分决定。
分别是

(this.minDate && this.compare(date, this.minDate) < 0)
 (this.maxDate && this.compare(date, this.maxDate) > 0) 
($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}))

前两个部分,是由最大时间和最小时间指定的控制逻辑,最后一个部分,我们留意到,是有$scope.dateDisabled指定的判断逻辑。继续跟踪。
下一个被依赖的js是bootstrap.js,我们跟踪到:
这里写图片描述

终于发现了限制其不显示周末的源头。

  $scope.disabled = function (date, mode) {
        return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
    };

这部分很明显显示了,如果是周六或者周日,就返回的是true, 进而抑制了元素为inactive状态。
修改如下:

  $scope.disabled = function (date, mode) {
        return ( mode === 'day' && false );
    };

ok,这样我们的小修改就完成了。

还有一个地方是调整模态框显示样式的,不知道刚才读者留意没有。
在ui-bootstrap-tpls.js中


angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/popup.html",
    "<ul class=\"dropdown-menu\" ng-style=\"{display: (isOpen && 'block') || 'none', top: position.top+'px', left: position.left+'px'}\" ng-keydown=\"keydown($event)\">\n" +
    "   <li ng-transclude></li>\n" +
    "   <li ng-if=\"showButtonBar\" style=\"padding:10px 9px 2px\">\n" +
    "       <span class=\"btn-group pull-left\">\n" +
    "           <button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"select('today')\">{{ getText('current') }}</button>\n" +
    "           <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"select(null)\">{{ getText('clear') }}</button>\n" +
    "       </span>\n" +
    "       <button type=\"button\" class=\"btn btn-sm btn-success pull-right\" ng-click=\"close()\">{{ getText('close') }}</button>\n" +
    "   </li>\n" +
    "</ul>\n" +
    "");
}]);

这个部分就留给有兴趣探索的朋友,自己练练手吧。

按照惯例,我们给出一些资料,供读者进一步学习。
https://msdn.microsoft.com/en-us/library/cc304077(VS.85).aspx
http://www.xuebuyuan.com/165295.html
http://v3.bootcss.com/components/#dropdowns
http://w3c.3306.biz/bootstrap_button_dropdowns/show-34-117-1.html
http://bootstrap.kinghack.com/components.html#buttonGroups
http://www.tuicool.com/articles/uyuuYz
http://www.cnblogs.com/iampoet/archive/2013/01/12/2857598.html
http://www.bootcss.com/p/bootstrap-datetimepicker/
http://www.eyecon.ro/bootstrap-datepicker/
http://www.oschina.net/p/datepicker-for-bootstrap
http://www.open-open.com/lib/view/open1337675959058.html
https://bootstrap-datepicker.readthedocs.org/en/latest/markup.html#input

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值