From 65c3d1bf3868ad3e1caec9fc77021735df53f989 Mon Sep 17 00:00:00 2001 From: laf Date: Mon, 13 Apr 2015 15:48:29 +0100 Subject: [PATCH] Squashed 'html/js/datetime/' changes from 5b3fc61..e750af7 e750af7 Update README.md 805bcc3 Update CONTRIBUTING.md 613a583 Update CONTRIBUTING.md 31e50cc Update bootstrap-datetimepicker-build.less d004434 Merge pull request #891 from Eonasdan/development adc8a68 fixes #867 8e16324 fixing locale formatting dfe5657 patch #752 b2a71de fixes #874 d00e39d version bump 762a90d couple of fixes d072d92 added keepInvalid 8eae1a4 Fixes and some new features 7f7dff4 Merge pull request #802 from zpaulovics/development 28699b6 Merge pull request #818 from mcarepa/improv-picker-placement 0abdcb1 Merge pull request #828 from ahmader/development a9744c5 Merge pull request #831 from admackin/development 86b49cb Update package.json ea501fa Fixes #793 0c5ad39 quick typo fixs 1cff47b picker placement conditions updated 6d245c9 version bump a4e7201 fixes and new features a865edf Revert "flipping events again" 78e28f5 Revert "tests" b7ae1e3 Fixed the options handling for componets 197647d tests 8d0fef8 flipping events again 8daa2b2 fix for #794 0221cb4 Merge pull request #778 from davidrojo/iss777 c11f3be Merge pull request #789 from comerc/patch-5 159d29e Update bootstrap-datetimepicker.js b545f2a Fixed coding style 19b485a Fixed coding style 6066555 Update CONTRIBUTING.md 1b2fe6e Update CONTRIBUTING.md 8d5b40a Fixes #777 37d8ce1 fix for #760 1cae292 fix for #761 499f619 fixing less 557b657 updating to v4 d9560b3 Update CONTRIBUTING.md 29b397d Update README.md 29cd87f Update bower.json fc56ea1 fixes #664 4c74e82 Merge pull request #635 from PeterDaveHello/patch-1 d756797 fix indent in package.json git-subtree-dir: html/js/datetime git-subtree-split: e750af7a4a65870030056a83fd1b52fc7b343246 --- .jscs.json | 1 - CONTRIBUTING.md | 8 +- Gruntfile.js | 53 +- LICENSE | 2 +- README.md | 22 +- bower.json | 8 +- build/css/bootstrap-datetimepicker.css | 362 +- build/css/bootstrap-datetimepicker.min.css | 367 +- build/js/bootstrap-datetimepicker.min.js | 9 +- .../Bootstrap.v3.Datetimepicker.4.0.0.nupkg | Bin 0 -> 23451 bytes ...ootstrap.v3.Datetimepicker.CSS.4.0.0.nupkg | Bin 0 -> 24328 bytes component.json | 5 +- composer.json | 7 +- package.json | 16 +- src/js/bootstrap-datetimepicker.js | 3081 ++++++++++------- src/less/_bootstrap-datetimepicker.less | 343 ++ src/less/bootstrap-datetimepicker-build.less | 16 +- src/less/bootstrap-datetimepicker.less | 294 -- .../Bootstrap.v3.Datetimepicker.CSS.nuspec | 6 +- src/nuget/Bootstrap.v3.Datetimepicker.nuspec | 6 +- src/nuget/install.ps1 | 2 +- test/publicApiSpec.js | 700 ++++ 22 files changed, 3643 insertions(+), 1665 deletions(-) create mode 100644 build/nuget/Bootstrap.v3.Datetimepicker.4.0.0.nupkg create mode 100644 build/nuget/Bootstrap.v3.Datetimepicker.CSS.4.0.0.nupkg create mode 100644 src/less/_bootstrap-datetimepicker.less delete mode 100755 src/less/bootstrap-datetimepicker.less create mode 100644 test/publicApiSpec.js diff --git a/.jscs.json b/.jscs.json index 1ce31f827..8af2b6139 100644 --- a/.jscs.json +++ b/.jscs.json @@ -54,7 +54,6 @@ "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", "disallowKeywords": ["with"], "disallowMultipleLineStrings": true, - "validateLineBreaks": "LF", "validateIndentation": 4, "disallowTrailingWhitespace": true, "disallowTrailingComma": true, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 461fef02d..6b319c1f6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,9 @@ Submitting Issues ================= -If you are submitting a bug, please test and/or fork [this jsfiddle](http://jsfiddle.net/kmbo576p/) demonstrating the issue. Code issues and fringe case bugs that do not include a jsfiddle (or similar) will be closed. +If you are submitting a bug, please test and/or fork [this jsfiddle](http://jsfiddle.net/Eonasdan/0Ltv25o8/) demonstrating the issue. Code issues and fringe case bugs that do not include a jsfiddle (or similar) will be closed. + +Issues that are submitted without a description (title only) will be closed with no further explanation. Contributing code ================= @@ -22,6 +24,9 @@ Very important notes * **Pull requests to the `master` branch will be closed.** Please submit all pull requests to the `development` branch. * **Do not include the minified files in your pull request.** Don't worry, we'll build them when we cut a release. + * Pull requests that do not include a description (title only) and the following will be closed: + * What the change does + * A use case (for new features or enhancements) Grunt tasks =========== @@ -30,3 +35,4 @@ We use Grunt for managing the build. Here are some useful Grunt tasks: * `grunt` The default task lints the code and runs the tests. You should make sure you do this before submitting a PR. * `grunt build` Compiles the less stylesheet and minifies the javascript source in build directory. + * `grunt build:travis` Compliles and runs the jasmine/travis tests. **All PR's MUST pass tests in place** diff --git a/Gruntfile.js b/Gruntfile.js index cf1ade14c..9aa026ca4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -24,11 +24,12 @@ module.exports = function (grunt) { jshint: { all: [ - 'Gruntfile.js', 'src/js/*.js' + 'Gruntfile.js', 'src/js/*.js', 'test/*.js' ], options: { 'browser' : true, 'node' : true, + 'jquery' : true, 'boss' : false, 'curly' : true, 'debug' : false, @@ -57,15 +58,24 @@ module.exports = function (grunt) { 'quotmark' : 'single', 'globals': { 'define': false, - 'jQuery': false, - 'moment': false + 'moment': false, + // Jasmine + 'jasmine': false, + 'describe': false, + 'xdescribe': false, + 'expect': false, + 'it': false, + 'xit': false, + 'spyOn': false, + 'beforeEach': false, + 'afterEach': false } } }, jscs: { all: [ - 'Gruntfile.js', 'src/js/*.js' + 'Gruntfile.js', 'src/js/*.js', 'test/*.js' ], options: { config: '.jscs.json' @@ -86,22 +96,49 @@ module.exports = function (grunt) { 'build/css/bootstrap-datetimepicker.css': 'src/less/bootstrap-datetimepicker-build.less' } } + }, + + jasmine: { + customTemplate: { + src: 'src/js/*.js', + options: { + specs: 'test/*Spec.js', + helpers: 'test/*Helper.js', + styles: [ + 'node_modules/bootstrap/dist/css/bootstrap.min.css', + 'build/css/bootstrap-datetimepicker.min.css' + ], + vendor: [ + 'node_modules/jquery/dist/jquery.min.js', + 'node_modules/moment/min/moment-with-locales.min.js', + 'node_modules/bootstrap/dist/js/bootstrap.min.js' + ], + display: 'none', + summary: 'true' + } + } } }); grunt.loadTasks('tasks'); + grunt.loadNpmTasks('grunt-contrib-jasmine'); + // These plugins provide necessary tasks. require('load-grunt-tasks')(grunt); // Default task. - grunt.registerTask('default', ['jshint', 'jscs']); + grunt.registerTask('default', ['jshint', 'jscs', 'less', 'jasmine']); // travis build task grunt.registerTask('build:travis', [ // code style - 'jshint', 'jscs' + 'jshint', 'jscs', + // build + 'uglify', 'less', + // tests + 'jasmine' ]); // Task to be run when building @@ -131,7 +168,7 @@ module.exports = function (grunt) { done(); }); } - else { + else { //--target=css grunt.util.spawn({ cmd: 'src/nuget/nuget.exe', args: [ @@ -152,4 +189,6 @@ module.exports = function (grunt) { }); } }); + + grunt.registerTask('test', ['jshint', 'jscs', 'uglify', 'less', 'jasmine']); }; diff --git a/LICENSE b/LICENSE index 47f5de70e..f8071d73e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Eonasdan, nikoskalogridis +Copyright (c) 2015 Jonathan Peterson (@Eonasdan) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index dbe1d698a..3b4df255f 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,25 @@ -# Bootstrap v3 datetimepicker widget ![GitHub version](https://badge.fury.io/gh/Eonasdan%2Fbootstrap-datetimepicker.png)   ![Travis](https://travis-ci.org/Eonasdan/bootstrap-datetimepicker.svg?branch=development) +# Bootstrap 3 Date/Time Picker +![GitHub version](https://badge.fury.io/gh/Eonasdan%2Fbootstrap-datetimepicker.png)   ![Travis](https://travis-ci.org/Eonasdan/bootstrap-datetimepicker.svg?branch=development) ![DateTimePicker](http://i.imgur.com/nfnvh5g.png) ## [View the manual and demos](http://eonasdan.github.io/bootstrap-datetimepicker/) +#v4 +v4 is out now! For v4 related bugs and issues see: /Eonasdan/bootstrap-datetimepicker/labels/v4. + +v3 is going into an archive state. Please be sure to check the documents. v4 has breaking changes and is a major rewrite. + ## Submitting Issues -Please test and/or fork [this jsfiddle](http://jsfiddle.net/kmbo576p/) with an example of your issue before you post an issue here. +If you have issues, please check the following first: +* Have you read the docs? +* Do you have the latest version of momentjs? +* Do you have the latest version of jQuery? +* Please test and/or fork [this jsfiddle](http://jsfiddle.net/Eonasdan/0Ltv25o8/) with an example of your issue before you post an issue here. ## Where do you use this? -I'd love to know if your public site is using this plugin and list your logo on the documentation site. Please email me `eonasdan at outlook dot com`. Do not submit issue/feature request to this email, they will be ignored. +I'd love to know if your public site is using this plugin and list your logo on the documentation site. Please email me `eonasdan at outlook dot com`. Do not submit issue/feature request to this email, they will be **ignored**. -## [Installation instructions](https://github.com/Eonasdan/bootstrap-datetimepicker/wiki/Installation) -Installation instructions has been moved to the wiki +## [Installation instructions](http://eonasdan.github.io/bootstrap-datetimepicker/Installing/) -## [Change Log](https://github.com/Eonasdan/bootstrap-datetimepicker/wiki/Change-Log) -The change log has moved to the wiki +## [Change Log](http://eonasdan.github.io/bootstrap-datetimepicker/Version%204%20Changelog/) diff --git a/bower.json b/bower.json index aaf6fcb12..34ab9314c 100644 --- a/bower.json +++ b/bower.json @@ -1,13 +1,15 @@ { "name": "eonasdan-bootstrap-datetimepicker", - "version": "3.1.3", + "version": "4.7.14", "main": [ "build/css/bootstrap-datetimepicker.min.css", - "build/js/bootstrap-datetimepicker.min.js" + "build/js/bootstrap-datetimepicker.min.js", + "src/less/_bootstrap-datetimepicker.less", + "src/less/bootstrap-datetimepicker-build.less", + "src/js/bootstrap-datetimepicker.js" ], "dependencies": { "jquery": ">=1.8.3", - "bootstrap": ">= 3.0", "moment": ">=2.8.0" }, "homepage": "https://github.com/Eonasdan/bootstrap-datetimepicker", diff --git a/build/css/bootstrap-datetimepicker.css b/build/css/bootstrap-datetimepicker.css index bd37b08b3..c70216196 100644 --- a/build/css/bootstrap-datetimepicker.css +++ b/build/css/bootstrap-datetimepicker.css @@ -1,75 +1,76 @@ /*! - * Datetimepicker for Bootstrap v3 -//! version : 3.1.3 + * Datetimepicker for Bootstrap 3 + * ! version : 4.7.14 * https://github.com/Eonasdan/bootstrap-datetimepicker/ */ .bootstrap-datetimepicker-widget { - top: 0; - left: 0; - width: 250px; + list-style: none; +} +.bootstrap-datetimepicker-widget.dropdown-menu { + margin: 2px 0; padding: 4px; - margin-top: 1px; - z-index: 99999 !important; - border-radius: 4px; + width: 19em; } -.bootstrap-datetimepicker-widget.timepicker-sbs { - width: 600px; +@media (min-width: 768px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } } -.bootstrap-datetimepicker-widget.bottom:before { +@media (min-width: 992px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 1200px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +.bootstrap-datetimepicker-widget.dropdown-menu:before, +.bootstrap-datetimepicker-widget.dropdown-menu:after { content: ''; display: inline-block; + position: absolute; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { border-left: 7px solid transparent; border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; + border-bottom: 7px solid #cccccc; border-bottom-color: rgba(0, 0, 0, 0.2); - position: absolute; top: -7px; left: 7px; } -.bootstrap-datetimepicker-widget.bottom:after { - content: ''; - display: inline-block; +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid white; - position: absolute; top: -6px; left: 8px; } -.bootstrap-datetimepicker-widget.top:before { - content: ''; - display: inline-block; +.bootstrap-datetimepicker-widget.dropdown-menu.top:before { border-left: 7px solid transparent; border-right: 7px solid transparent; - border-top: 7px solid #ccc; + border-top: 7px solid #cccccc; border-top-color: rgba(0, 0, 0, 0.2); - position: absolute; bottom: -7px; left: 6px; } -.bootstrap-datetimepicker-widget.top:after { - content: ''; - display: inline-block; +.bootstrap-datetimepicker-widget.dropdown-menu.top:after { border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 6px solid white; - position: absolute; bottom: -6px; left: 7px; } -.bootstrap-datetimepicker-widget .dow { - width: 14.2857%; -} -.bootstrap-datetimepicker-widget.pull-right:before { +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { left: auto; right: 6px; } -.bootstrap-datetimepicker-widget.pull-right:after { +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { left: auto; right: 7px; } -.bootstrap-datetimepicker-widget > ul { - list-style-type: none; +.bootstrap-datetimepicker-widget .list-unstyled { margin: 0; } .bootstrap-datetimepicker-widget a[data-action] { @@ -89,82 +90,238 @@ .bootstrap-datetimepicker-widget button[data-action] { padding: 6px; } -.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator { - width: 4px; +.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; padding: 0; - margin: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Hours"; } -.bootstrap-datetimepicker-widget .datepicker > div { - display: none; +.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle AM/PM"; +} +.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Clear the picker"; +} +.bootstrap-datetimepicker-widget .btn[data-action="today"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Set the date to today"; } .bootstrap-datetimepicker-widget .picker-switch { text-align: center; } +.bootstrap-datetimepicker-widget .picker-switch::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle Date and Time Screens"; +} +.bootstrap-datetimepicker-widget .picker-switch td { + padding: 0; + margin: 0; + height: auto; + width: auto; + line-height: inherit; +} +.bootstrap-datetimepicker-widget .picker-switch td span { + line-height: 2.5; + height: 2.5em; + width: 100%; +} .bootstrap-datetimepicker-widget table { width: 100%; margin: 0; } -.bootstrap-datetimepicker-widget td, -.bootstrap-datetimepicker-widget th { +.bootstrap-datetimepicker-widget table td, +.bootstrap-datetimepicker-widget table th { text-align: center; border-radius: 4px; } -.bootstrap-datetimepicker-widget td { - height: 54px; - line-height: 54px; - width: 54px; -} -.bootstrap-datetimepicker-widget td.cw { - font-size: 10px; - height: 20px; - line-height: 20px; - color: #777777; -} -.bootstrap-datetimepicker-widget td.day { +.bootstrap-datetimepicker-widget table th { height: 20px; line-height: 20px; width: 20px; } -.bootstrap-datetimepicker-widget td.day:hover, -.bootstrap-datetimepicker-widget td.hour:hover, -.bootstrap-datetimepicker-widget td.minute:hover, -.bootstrap-datetimepicker-widget td.second:hover { +.bootstrap-datetimepicker-widget table th.picker-switch { + width: 145px; +} +.bootstrap-datetimepicker-widget table th.disabled, +.bootstrap-datetimepicker-widget table th.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table th.prev::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Previous Month"; +} +.bootstrap-datetimepicker-widget table th.next::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Next Month"; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th { + cursor: pointer; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td { + height: 54px; + line-height: 54px; + width: 54px; +} +.bootstrap-datetimepicker-widget table td.cw { + font-size: .8em; + height: 20px; + line-height: 20px; + color: #777777; +} +.bootstrap-datetimepicker-widget table td.day { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table td.day:hover, +.bootstrap-datetimepicker-widget table td.hour:hover, +.bootstrap-datetimepicker-widget table td.minute:hover, +.bootstrap-datetimepicker-widget table td.second:hover { background: #eeeeee; cursor: pointer; } -.bootstrap-datetimepicker-widget td.old, -.bootstrap-datetimepicker-widget td.new { +.bootstrap-datetimepicker-widget table td.old, +.bootstrap-datetimepicker-widget table td.new { color: #777777; } -.bootstrap-datetimepicker-widget td.today { +.bootstrap-datetimepicker-widget table td.today { position: relative; } -.bootstrap-datetimepicker-widget td.today:before { +.bootstrap-datetimepicker-widget table td.today:before { content: ''; display: inline-block; - border-left: 7px solid transparent; - border-bottom: 7px solid #428bca; + border: 0 0 7px 7px solid transparent; + border-bottom-color: #337ab7; border-top-color: rgba(0, 0, 0, 0.2); position: absolute; bottom: 4px; right: 4px; } -.bootstrap-datetimepicker-widget td.active, -.bootstrap-datetimepicker-widget td.active:hover { - background-color: #428bca; +.bootstrap-datetimepicker-widget table td.active, +.bootstrap-datetimepicker-widget table td.active:hover { + background-color: #337ab7; color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } -.bootstrap-datetimepicker-widget td.active.today:before { +.bootstrap-datetimepicker-widget table td.active.today:before { border-bottom-color: #fff; } -.bootstrap-datetimepicker-widget td.disabled, -.bootstrap-datetimepicker-widget td.disabled:hover { +.bootstrap-datetimepicker-widget table td.disabled, +.bootstrap-datetimepicker-widget table td.disabled:hover { background: none; color: #777777; cursor: not-allowed; } -.bootstrap-datetimepicker-widget td span { +.bootstrap-datetimepicker-widget table td span { display: inline-block; width: 54px; height: 54px; @@ -173,66 +330,37 @@ cursor: pointer; border-radius: 4px; } -.bootstrap-datetimepicker-widget td span:hover { +.bootstrap-datetimepicker-widget table td span:hover { background: #eeeeee; } -.bootstrap-datetimepicker-widget td span.active { - background-color: #428bca; +.bootstrap-datetimepicker-widget table td span.active { + background-color: #337ab7; color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } -.bootstrap-datetimepicker-widget td span.old { +.bootstrap-datetimepicker-widget table td span.old { color: #777777; } -.bootstrap-datetimepicker-widget td span.disabled, -.bootstrap-datetimepicker-widget td span.disabled:hover { +.bootstrap-datetimepicker-widget table td span.disabled, +.bootstrap-datetimepicker-widget table td span.disabled:hover { background: none; color: #777777; cursor: not-allowed; } -.bootstrap-datetimepicker-widget th { - height: 20px; - line-height: 20px; - width: 20px; +.bootstrap-datetimepicker-widget.usetwentyfour td.hour { + height: 27px; + line-height: 27px; } -.bootstrap-datetimepicker-widget th.picker-switch { - width: 145px; -} -.bootstrap-datetimepicker-widget th.next, -.bootstrap-datetimepicker-widget th.prev { - font-size: 21px; -} -.bootstrap-datetimepicker-widget th.disabled, -.bootstrap-datetimepicker-widget th.disabled:hover { - background: none; - color: #777777; - cursor: not-allowed; -} -.bootstrap-datetimepicker-widget thead tr:first-child th { +.input-group.date .input-group-addon { cursor: pointer; } -.bootstrap-datetimepicker-widget thead tr:first-child th:hover { - background: #eeeeee; -} -.input-group.date .input-group-addon span { - display: block; - cursor: pointer; - width: 16px; - height: 16px; -} -.bootstrap-datetimepicker-widget.left-oriented:before { - left: auto; - right: 6px; -} -.bootstrap-datetimepicker-widget.left-oriented:after { - left: auto; - right: 7px; -} -.bootstrap-datetimepicker-widget ul.list-unstyled li div.timepicker div.timepicker-picker table.table-condensed tbody > tr > td { - padding: 0px !important; -} -@media screen and (max-width: 767px) { - .bootstrap-datetimepicker-widget.timepicker-sbs { - width: 283px; - } +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; } diff --git a/build/css/bootstrap-datetimepicker.min.css b/build/css/bootstrap-datetimepicker.min.css index cf838a3c2..c70216196 100644 --- a/build/css/bootstrap-datetimepicker.min.css +++ b/build/css/bootstrap-datetimepicker.min.css @@ -1,5 +1,366 @@ /*! - * Datetimepicker for Bootstrap v3 -//! version : 3.1.3 + * Datetimepicker for Bootstrap 3 + * ! version : 4.7.14 * https://github.com/Eonasdan/bootstrap-datetimepicker/ - */.bootstrap-datetimepicker-widget{top:0;left:0;width:250px;padding:4px;margin-top:1px;z-index:99999!important;border-radius:4px}.bootstrap-datetimepicker-widget.timepicker-sbs{width:600px}.bootstrap-datetimepicker-widget.bottom:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);position:absolute;top:-7px;left:7px}.bootstrap-datetimepicker-widget.bottom:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:8px}.bootstrap-datetimepicker-widget.top:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,.2);position:absolute;bottom:-7px;left:6px}.bootstrap-datetimepicker-widget.top:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;position:absolute;bottom:-6px;left:7px}.bootstrap-datetimepicker-widget .dow{width:14.2857%}.bootstrap-datetimepicker-widget.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget>ul{list-style-type:none;margin:0}.bootstrap-datetimepicker-widget a[data-action]{padding:6px 0}.bootstrap-datetimepicker-widget a[data-action]:active{box-shadow:none}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:54px;font-weight:700;font-size:1.2em;margin:0}.bootstrap-datetimepicker-widget button[data-action]{padding:6px}.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator{width:4px;padding:0;margin:0}.bootstrap-datetimepicker-widget .datepicker>div{display:none}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget td,.bootstrap-datetimepicker-widget th{text-align:center;border-radius:4px}.bootstrap-datetimepicker-widget td{height:54px;line-height:54px;width:54px}.bootstrap-datetimepicker-widget td.cw{font-size:10px;height:20px;line-height:20px;color:#777}.bootstrap-datetimepicker-widget td.day{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget td.day:hover,.bootstrap-datetimepicker-widget td.hour:hover,.bootstrap-datetimepicker-widget td.minute:hover,.bootstrap-datetimepicker-widget td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget td.old,.bootstrap-datetimepicker-widget td.new{color:#777}.bootstrap-datetimepicker-widget td.today{position:relative}.bootstrap-datetimepicker-widget td.today:before{content:'';display:inline-block;border-left:7px solid transparent;border-bottom:7px solid #428bca;border-top-color:rgba(0,0,0,.2);position:absolute;bottom:4px;right:4px}.bootstrap-datetimepicker-widget td.active,.bootstrap-datetimepicker-widget td.active:hover{background-color:#428bca;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget td.active.today:before{border-bottom-color:#fff}.bootstrap-datetimepicker-widget td.disabled,.bootstrap-datetimepicker-widget td.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget td span{display:inline-block;width:54px;height:54px;line-height:54px;margin:2px 1.5px;cursor:pointer;border-radius:4px}.bootstrap-datetimepicker-widget td span:hover{background:#eee}.bootstrap-datetimepicker-widget td span.active{background-color:#428bca;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget td span.old{color:#777}.bootstrap-datetimepicker-widget td span.disabled,.bootstrap-datetimepicker-widget td span.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget th{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget th.picker-switch{width:145px}.bootstrap-datetimepicker-widget th.next,.bootstrap-datetimepicker-widget th.prev{font-size:21px}.bootstrap-datetimepicker-widget th.disabled,.bootstrap-datetimepicker-widget th.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget thead tr:first-child th:hover{background:#eee}.input-group.date .input-group-addon span{display:block;cursor:pointer;width:16px;height:16px}.bootstrap-datetimepicker-widget.left-oriented:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.left-oriented:after{left:auto;right:7px}.bootstrap-datetimepicker-widget ul.list-unstyled li div.timepicker div.timepicker-picker table.table-condensed tbody>tr>td{padding:0!important}@media screen and (max-width:767px){.bootstrap-datetimepicker-widget.timepicker-sbs{width:283px}} \ No newline at end of file + */ +.bootstrap-datetimepicker-widget { + list-style: none; +} +.bootstrap-datetimepicker-widget.dropdown-menu { + margin: 2px 0; + padding: 4px; + width: 19em; +} +@media (min-width: 768px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 992px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 1200px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +.bootstrap-datetimepicker-widget.dropdown-menu:before, +.bootstrap-datetimepicker-widget.dropdown-menu:after { + content: ''; + display: inline-block; + position: absolute; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #cccccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + top: -7px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + top: -6px; + left: 8px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #cccccc; + border-top-color: rgba(0, 0, 0, 0.2); + bottom: -7px; + left: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid white; + bottom: -6px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { + left: auto; + right: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { + left: auto; + right: 7px; +} +.bootstrap-datetimepicker-widget .list-unstyled { + margin: 0; +} +.bootstrap-datetimepicker-widget a[data-action] { + padding: 6px 0; +} +.bootstrap-datetimepicker-widget a[data-action]:active { + box-shadow: none; +} +.bootstrap-datetimepicker-widget .timepicker-hour, +.bootstrap-datetimepicker-widget .timepicker-minute, +.bootstrap-datetimepicker-widget .timepicker-second { + width: 54px; + font-weight: bold; + font-size: 1.2em; + margin: 0; +} +.bootstrap-datetimepicker-widget button[data-action] { + padding: 6px; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle AM/PM"; +} +.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Clear the picker"; +} +.bootstrap-datetimepicker-widget .btn[data-action="today"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Set the date to today"; +} +.bootstrap-datetimepicker-widget .picker-switch { + text-align: center; +} +.bootstrap-datetimepicker-widget .picker-switch::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle Date and Time Screens"; +} +.bootstrap-datetimepicker-widget .picker-switch td { + padding: 0; + margin: 0; + height: auto; + width: auto; + line-height: inherit; +} +.bootstrap-datetimepicker-widget .picker-switch td span { + line-height: 2.5; + height: 2.5em; + width: 100%; +} +.bootstrap-datetimepicker-widget table { + width: 100%; + margin: 0; +} +.bootstrap-datetimepicker-widget table td, +.bootstrap-datetimepicker-widget table th { + text-align: center; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table th { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table th.picker-switch { + width: 145px; +} +.bootstrap-datetimepicker-widget table th.disabled, +.bootstrap-datetimepicker-widget table th.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table th.prev::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Previous Month"; +} +.bootstrap-datetimepicker-widget table th.next::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Next Month"; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th { + cursor: pointer; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td { + height: 54px; + line-height: 54px; + width: 54px; +} +.bootstrap-datetimepicker-widget table td.cw { + font-size: .8em; + height: 20px; + line-height: 20px; + color: #777777; +} +.bootstrap-datetimepicker-widget table td.day { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table td.day:hover, +.bootstrap-datetimepicker-widget table td.hour:hover, +.bootstrap-datetimepicker-widget table td.minute:hover, +.bootstrap-datetimepicker-widget table td.second:hover { + background: #eeeeee; + cursor: pointer; +} +.bootstrap-datetimepicker-widget table td.old, +.bootstrap-datetimepicker-widget table td.new { + color: #777777; +} +.bootstrap-datetimepicker-widget table td.today { + position: relative; +} +.bootstrap-datetimepicker-widget table td.today:before { + content: ''; + display: inline-block; + border: 0 0 7px 7px solid transparent; + border-bottom-color: #337ab7; + border-top-color: rgba(0, 0, 0, 0.2); + position: absolute; + bottom: 4px; + right: 4px; +} +.bootstrap-datetimepicker-widget table td.active, +.bootstrap-datetimepicker-widget table td.active:hover { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td.active.today:before { + border-bottom-color: #fff; +} +.bootstrap-datetimepicker-widget table td.disabled, +.bootstrap-datetimepicker-widget table td.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table td span { + display: inline-block; + width: 54px; + height: 54px; + line-height: 54px; + margin: 2px 1.5px; + cursor: pointer; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table td span:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td span.active { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td span.old { + color: #777777; +} +.bootstrap-datetimepicker-widget table td span.disabled, +.bootstrap-datetimepicker-widget table td span.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget.usetwentyfour td.hour { + height: 27px; + line-height: 27px; +} +.input-group.date .input-group-addon { + cursor: pointer; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} diff --git a/build/js/bootstrap-datetimepicker.min.js b/build/js/bootstrap-datetimepicker.min.js index cdba4b105..a60af89d8 100644 --- a/build/js/bootstrap-datetimepicker.min.js +++ b/build/js/bootstrap-datetimepicker.min.js @@ -1 +1,8 @@ -!function(a,b){"use strict";if("function"==typeof define&&define.amd)define(["jquery","moment"],b);else if("object"==typeof exports)b(require("jquery"),require("moment"));else{if(!jQuery)throw new Error("bootstrap-datetimepicker requires jQuery to be loaded first");if(!moment)throw new Error("bootstrap-datetimepicker requires moment.js to be loaded first");b(a.jQuery,moment)}}(this,function(a,b){"use strict";if("undefined"==typeof b)throw new Error("momentjs is required");var c=0,d=function(d,e){var f,g=a.fn.datetimepicker.defaults,h={time:"glyphicon glyphicon-time",date:"glyphicon glyphicon-calendar",up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down"},i=this,j=!1,k=function(){var f,j,k=!1;if(i.options=a.extend({},g,e),i.options.icons=a.extend({},h,i.options.icons),i.element=a(d),m(),!i.options.pickTime&&!i.options.pickDate)throw new Error("Must choose at least one picker");if(i.id=c++,b.locale(i.options.language),i.date=b(),i.unset=!1,i.isInput=i.element.is("input"),i.component=!1,i.element.hasClass("input-group")&&(i.component=i.element.find(0===i.element.find(".datepickerbutton").size()?'[class^="input-group-"]':".datepickerbutton")),i.format=i.options.format,f=b().localeData(),i.format||(i.format=i.options.pickDate?f.longDateFormat("L"):"",i.options.pickDate&&i.options.pickTime&&(i.format+=" "),i.format+=i.options.pickTime?f.longDateFormat("LT"):"",i.options.useSeconds&&(-1!==f.longDateFormat("LT").indexOf(" A")?i.format=i.format.split(" A")[0]+":ss A":i.format+=":ss")),i.use24hours=i.format.toLowerCase().indexOf("a")<0&&i.format.indexOf("h")<0,i.component&&(k=i.component.find("span")),i.options.pickTime&&k&&k.addClass(i.options.icons.time),i.options.pickDate&&k&&(k.removeClass(i.options.icons.time),k.addClass(i.options.icons.date)),i.options.widgetParent="string"==typeof i.options.widgetParent&&i.options.widgetParent||i.element.parents().filter(function(){return"scroll"===a(this).css("overflow-y")}).get(0)||"body",i.widget=a(Q()).appendTo(i.options.widgetParent),i.minViewMode=i.options.minViewMode||0,"string"==typeof i.minViewMode)switch(i.minViewMode){case"months":i.minViewMode=1;break;case"years":i.minViewMode=2;break;default:i.minViewMode=0}if(i.viewMode=i.options.viewMode||0,"string"==typeof i.viewMode)switch(i.viewMode){case"months":i.viewMode=1;break;case"years":i.viewMode=2;break;default:i.viewMode=0}i.viewMode=Math.max(i.viewMode,i.minViewMode),i.options.disabledDates=O(i.options.disabledDates),i.options.enabledDates=O(i.options.enabledDates),i.startViewMode=i.viewMode,i.setMinDate(i.options.minDate),i.setMaxDate(i.options.maxDate),r(),s(),u(),v(),w(),q(),E(),l().prop("disabled")||F(),""!==i.options.defaultDate&&""===l().val()&&i.setValue(i.options.defaultDate),1!==i.options.minuteStepping&&(j=i.options.minuteStepping,i.date.minutes(Math.round(i.date.minutes()/j)*j%60).seconds(0))},l=function(){var a;if(i.isInput)return i.element;if(a=i.element.find(".datepickerinput"),0===a.size())a=i.element.find("input");else if(!a.is("input"))throw new Error('CSS class "datepickerinput" cannot be applied to non input element');return a},m=function(){var a;a=i.element.is("input")?i.element.data():i.element.find("input").data(),void 0!==a.dateFormat&&(i.options.format=a.dateFormat),void 0!==a.datePickdate&&(i.options.pickDate=a.datePickdate),void 0!==a.datePicktime&&(i.options.pickTime=a.datePicktime),void 0!==a.dateUseminutes&&(i.options.useMinutes=a.dateUseminutes),void 0!==a.dateUseseconds&&(i.options.useSeconds=a.dateUseseconds),void 0!==a.dateUsecurrent&&(i.options.useCurrent=a.dateUsecurrent),void 0!==a.calendarWeeks&&(i.options.calendarWeeks=a.calendarWeeks),void 0!==a.dateMinutestepping&&(i.options.minuteStepping=a.dateMinutestepping),void 0!==a.dateMindate&&(i.options.minDate=a.dateMindate),void 0!==a.dateMaxdate&&(i.options.maxDate=a.dateMaxdate),void 0!==a.dateShowtoday&&(i.options.showToday=a.dateShowtoday),void 0!==a.dateCollapse&&(i.options.collapse=a.dateCollapse),void 0!==a.dateLanguage&&(i.options.language=a.dateLanguage),void 0!==a.dateDefaultdate&&(i.options.defaultDate=a.dateDefaultdate),void 0!==a.dateDisableddates&&(i.options.disabledDates=a.dateDisableddates),void 0!==a.dateEnableddates&&(i.options.enabledDates=a.dateEnableddates),void 0!==a.dateIcons&&(i.options.icons=a.dateIcons),void 0!==a.dateUsestrict&&(i.options.useStrict=a.dateUsestrict),void 0!==a.dateDirection&&(i.options.direction=a.dateDirection),void 0!==a.dateSidebyside&&(i.options.sideBySide=a.dateSidebyside),void 0!==a.dateDaysofweekdisabled&&(i.options.daysOfWeekDisabled=a.dateDaysofweekdisabled)},n=function(){var b,c="absolute",d=i.component?i.component.offset():i.element.offset(),e=a(window);i.width=i.component?i.component.outerWidth():i.element.outerWidth(),d.top=d.top+i.element.outerHeight(),"up"===i.options.direction?b="top":"bottom"===i.options.direction?b="bottom":"auto"===i.options.direction&&(b=d.top+i.widget.height()>e.height()+e.scrollTop()&&i.widget.height()+i.element.outerHeight()"),e=b.weekdaysMin();if(i.options.calendarWeeks===!0&&d.append('#'),0===b().localeData()._week.dow)for(c=0;7>c;c++)d.append(''+e[c]+"");else for(c=1;8>c;c++)d.append(7===c?''+e[0]+"":''+e[c]+"");i.widget.find(".datepicker-days thead").append(d)},s=function(){b.locale(i.options.language);var a,c="",d=b.monthsShort();for(a=0;12>a;a++)c+=''+d[a]+"";i.widget.find(".datepicker-months td").append(c)},t=function(){if(i.options.pickDate){b.locale(i.options.language);var c,d,e,f,g,h,j,k,l,m=i.viewDate.year(),n=i.viewDate.month(),o=i.options.minDate.year(),p=i.options.minDate.month(),q=i.options.maxDate.year(),r=i.options.maxDate.month(),s=[],t=b.months();for(i.widget.find(".datepicker-days").find(".disabled").removeClass("disabled"),i.widget.find(".datepicker-months").find(".disabled").removeClass("disabled"),i.widget.find(".datepicker-years").find(".disabled").removeClass("disabled"),i.widget.find(".datepicker-days th:eq(1)").text(t[n]+" "+m),d=b(i.viewDate,i.format,i.options.useStrict).subtract(1,"months"),j=d.daysInMonth(),d.date(j).startOf("week"),(m===o&&p>=n||o>m)&&i.widget.find(".datepicker-days th:eq(0)").addClass("disabled"),(m===q&&n>=r||m>q)&&i.widget.find(".datepicker-days th:eq(2)").addClass("disabled"),e=b(d).add(42,"d");d.isBefore(e);){if(d.weekday()===b().startOf("week").weekday()&&(f=a(""),s.push(f),i.options.calendarWeeks===!0&&f.append(''+d.week()+"")),g="",d.year()m||d.year()===m&&d.month()>n)&&(g+=" new"),d.isSame(b({y:i.date.year(),M:i.date.month(),d:i.date.date()}))&&(g+=" active"),(M(d,"day")||!N(d))&&(g+=" disabled"),i.options.showToday===!0&&d.isSame(b(),"day")&&(g+=" today"),i.options.daysOfWeekDisabled)for(h=0;h'+d.date()+""),c=d.date(),d.add(1,"d"),c===d.date()&&d.add(1,"d")}for(i.widget.find(".datepicker-days tbody").empty().append(s),l=i.date.year(),t=i.widget.find(".datepicker-months").find("th:eq(1)").text(m).end().find("span").removeClass("active"),l===m&&t.eq(i.date.month()).addClass("active"),o>m-1&&i.widget.find(".datepicker-months th:eq(0)").addClass("disabled"),m+1>q&&i.widget.find(".datepicker-months th:eq(2)").addClass("disabled"),h=0;12>h;h++)m===o&&p>h||o>m?a(t[h]).addClass("disabled"):(m===q&&h>r||m>q)&&a(t[h]).addClass("disabled");for(s="",m=10*parseInt(m/10,10),k=i.widget.find(".datepicker-years").find("th:eq(1)").text(m+"-"+(m+9)).parents("table").find("td"),i.widget.find(".datepicker-years").find("th").removeClass("disabled"),o>m&&i.widget.find(".datepicker-years").find("th:eq(0)").addClass("disabled"),m+9>q&&i.widget.find(".datepicker-years").find("th:eq(2)").addClass("disabled"),m-=1,h=-1;11>h;h++)s+='m||m>q?" disabled":"")+'">'+m+"",m+=1;k.html(s)}},u=function(){b.locale(i.options.language);var a,c,d,e=i.widget.find(".timepicker .timepicker-hours table"),f="";if(e.parent().hide(),i.use24hours)for(a=0,c=0;6>c;c+=1){for(f+="",d=0;4>d;d+=1)f+=''+P(a.toString())+"",a++;f+=""}else for(a=1,c=0;3>c;c+=1){for(f+="",d=0;4>d;d+=1)f+=''+P(a.toString())+"",a++;f+=""}e.html(f)},v=function(){var a,b,c=i.widget.find(".timepicker .timepicker-minutes table"),d="",e=0,f=i.options.minuteStepping;for(c.parent().hide(),1===f&&(f=5),a=0;ab;b+=1)60>e?(d+=''+P(e.toString())+"",e+=f):d+="";d+=""}c.html(d)},w=function(){var a,b,c=i.widget.find(".timepicker .timepicker-seconds table"),d="",e=0;for(c.parent().hide(),a=0;3>a;a++){for(d+="",b=0;4>b;b+=1)d+=''+P(e.toString())+"",e+=5;d+=""}c.html(d)},x=function(){if(i.date){var a=i.widget.find(".timepicker span[data-time-component]"),b=i.date.hours(),c=i.date.format("A");i.use24hours||(0===b?b=12:12!==b&&(b%=12),i.widget.find(".timepicker [data-action=togglePeriod]").text(c)),a.filter("[data-time-component=hours]").text(P(b)),a.filter("[data-time-component=minutes]").text(P(i.date.minutes())),a.filter("[data-time-component=seconds]").text(P(i.date.second()))}},y=function(c){c.stopPropagation(),c.preventDefault(),i.unset=!1;var d,e,f,g,h=a(c.target).closest("span, td, th"),j=b(i.date);if(1===h.length&&!h.is(".disabled"))switch(h[0].nodeName.toLowerCase()){case"th":switch(h[0].className){case"picker-switch":E(1);break;case"prev":case"next":f=R.modes[i.viewMode].navStep,"prev"===h[0].className&&(f=-1*f),i.viewDate.add(f,R.modes[i.viewMode].navFnc),t()}break;case"span":h.is(".month")?(d=h.parent().find("span").index(h),i.viewDate.month(d)):(e=parseInt(h.text(),10)||0,i.viewDate.year(e)),i.viewMode===i.minViewMode&&(i.date=b({y:i.viewDate.year(),M:i.viewDate.month(),d:i.viewDate.date(),h:i.date.hours(),m:i.date.minutes(),s:i.date.seconds()}),K(),o(j,c.type)),E(-1),t();break;case"td":h.is(".day")&&(g=parseInt(h.text(),10)||1,d=i.viewDate.month(),e=i.viewDate.year(),h.is(".old")?0===d?(d=11,e-=1):d-=1:h.is(".new")&&(11===d?(d=0,e+=1):d+=1),i.date=b({y:e,M:d,d:g,h:i.date.hours(),m:i.date.minutes(),s:i.date.seconds()}),i.viewDate=b({y:e,M:d,d:Math.min(28,g)}),t(),K(),o(j,c.type))}},z={incrementHours:function(){L("add","hours",1)},incrementMinutes:function(){L("add","minutes",i.options.minuteStepping)},incrementSeconds:function(){L("add","seconds",1)},decrementHours:function(){L("subtract","hours",1)},decrementMinutes:function(){L("subtract","minutes",i.options.minuteStepping)},decrementSeconds:function(){L("subtract","seconds",1)},togglePeriod:function(){var a=i.date.hours();a>=12?a-=12:a+=12,i.date.hours(a)},showPicker:function(){i.widget.find(".timepicker > div:not(.timepicker-picker)").hide(),i.widget.find(".timepicker .timepicker-picker").show()},showHours:function(){i.widget.find(".timepicker .timepicker-picker").hide(),i.widget.find(".timepicker .timepicker-hours").show()},showMinutes:function(){i.widget.find(".timepicker .timepicker-picker").hide(),i.widget.find(".timepicker .timepicker-minutes").show()},showSeconds:function(){i.widget.find(".timepicker .timepicker-picker").hide(),i.widget.find(".timepicker .timepicker-seconds").show()},selectHour:function(b){var c=parseInt(a(b.target).text(),10);i.use24hours||(i.date.hours()>=12?12!==c&&(c+=12):12===c&&(c=0)),i.date.hours(c),z.showPicker.call(i)},selectMinute:function(b){i.date.minutes(parseInt(a(b.target).text(),10)),z.showPicker.call(i)},selectSecond:function(b){i.date.seconds(parseInt(a(b.target).text(),10)),z.showPicker.call(i)}},A=function(c){var d=b(i.date),e=a(c.currentTarget).data("action"),f=z[e].apply(i,arguments);return B(c),i.date||(i.date=b({y:1970})),K(),x(),o(d,c.type),f},B=function(a){a.stopPropagation(),a.preventDefault()},C=function(a){27===a.keyCode&&i.hide()},D=function(c){b.locale(i.options.language);var d=a(c.target),e=b(i.date),f=b(d.val(),i.format,i.options.useStrict);f.isValid()&&!M(f)&&N(f)?(q(),i.setValue(f),o(e,c.type),K()):(i.viewDate=e,i.unset=!0,o(e,c.type),p(f))},E=function(a){a&&(i.viewMode=Math.max(i.minViewMode,Math.min(2,i.viewMode+a))),i.widget.find(".datepicker > div").hide().filter(".datepicker-"+R.modes[i.viewMode].clsName).show()},F=function(){var b,c,d,e,f;i.widget.on("click",".datepicker *",a.proxy(y,this)),i.widget.on("click","[data-action]",a.proxy(A,this)),i.widget.on("mousedown",a.proxy(B,this)),i.element.on("keydown",a.proxy(C,this)),i.options.pickDate&&i.options.pickTime&&i.widget.on("click.togglePicker",".accordion-toggle",function(g){if(g.stopPropagation(),b=a(this),c=b.closest("ul"),d=c.find(".in"),e=c.find(".collapse:not(.in)"),d&&d.length){if(f=d.data("collapse"),f&&f.transitioning)return;d.collapse("hide"),e.collapse("show"),b.find("span").toggleClass(i.options.icons.time+" "+i.options.icons.date),i.component&&i.component.find("span").toggleClass(i.options.icons.time+" "+i.options.icons.date)}}),i.isInput?i.element.on({click:a.proxy(i.show,this),focus:a.proxy(i.show,this),change:a.proxy(D,this),blur:a.proxy(i.hide,this)}):(i.element.on({change:a.proxy(D,this)},"input"),i.component?(i.component.on("click",a.proxy(i.show,this)),i.component.on("mousedown",a.proxy(B,this))):i.element.on("click",a.proxy(i.show,this)))},G=function(){a(window).on("resize.datetimepicker"+i.id,a.proxy(n,this)),i.isInput||a(document).on("mousedown.datetimepicker"+i.id,a.proxy(i.hide,this))},H=function(){i.widget.off("click",".datepicker *",i.click),i.widget.off("click","[data-action]"),i.widget.off("mousedown",i.stopEvent),i.options.pickDate&&i.options.pickTime&&i.widget.off("click.togglePicker"),i.isInput?i.element.off({focus:i.show,change:D,click:i.show,blur:i.hide}):(i.element.off({change:D},"input"),i.component?(i.component.off("click",i.show),i.component.off("mousedown",i.stopEvent)):i.element.off("click",i.show))},I=function(){a(window).off("resize.datetimepicker"+i.id),i.isInput||a(document).off("mousedown.datetimepicker"+i.id)},J=function(){if(i.element){var b,c=i.element.parents(),d=!1;for(b=0;b0?d:!1},P=function(a){return a=a.toString(),a.length>=2?a:"0"+a},Q=function(){var a='‹›',b='',c='
'+a+'
'+a+b+'
'+a+b+"
",d="";return i.options.pickDate&&i.options.pickTime?(d='
',d+=i.options.sideBySide?'
'+c+'
'+S.getTemplate()+"
":'
    '+c+'
  • '+S.getTemplate()+"
",d+="
"):i.options.pickTime?'":'"},R={modes:[{clsName:"days",navFnc:"month",navStep:1},{clsName:"months",navFnc:"year",navStep:1},{clsName:"years",navFnc:"year",navStep:10}]},S={hourTemplate:'',minuteTemplate:'',secondTemplate:''};S.getTemplate=function(){return'
"+(i.options.useSeconds?'':"")+(i.use24hours?"":'')+" "+(i.options.useSeconds?'":"")+(i.use24hours?"":'')+'"+(i.options.useSeconds?'':"")+(i.use24hours?"":'')+'
'+(i.options.useMinutes?'':"")+"
"+S.hourTemplate+' :'+(i.options.useMinutes?S.minuteTemplate:'00')+":'+S.secondTemplate+"
'+(i.options.useMinutes?'':"")+"
'+(i.options.useSeconds?'
':"")},i.destroy=function(){H(),I(),i.widget.remove(),i.element.removeData("DateTimePicker"),i.component&&i.component.removeData("DateTimePicker")},i.show=function(a){if(!l().prop("disabled")){if(i.options.useCurrent&&""===l().val()){if(1!==i.options.minuteStepping){var c=b(),d=i.options.minuteStepping;c.minutes(Math.round(c.minutes()/d)*d%60).seconds(0),i.setValue(c.format(i.format))}else i.setValue(b().format(i.format));o("",a.type)}a&&"click"===a.type&&i.isInput&&i.widget.hasClass("picker-open")||(i.widget.hasClass("picker-open")?(i.widget.hide(),i.widget.removeClass("picker-open")):(i.widget.show(),i.widget.addClass("picker-open")),i.height=i.component?i.component.outerHeight():i.element.outerHeight(),n(),i.element.trigger({type:"dp.show",date:b(i.date)}),G(),a&&B(a))}},i.disable=function(){var a=l();a.prop("disabled")||(a.prop("disabled",!0),H())},i.enable=function(){var a=l();a.prop("disabled")&&(a.prop("disabled",!1),F())},i.hide=function(){var a,c,d=i.widget.find(".collapse");for(a=0;a1)throw new TypeError("isEnabled expects a single character string parameter");switch(a){case"y":return-1!==g.indexOf("Y");case"M":return-1!==g.indexOf("M");case"d":return-1!==g.toLowerCase().indexOf("d");case"h":case"H":return-1!==g.toLowerCase().indexOf("h");case"m":return-1!==g.indexOf("m");case"s":return-1!==g.indexOf("s");default:return!1}},y=function(){return x("h")||x("m")||x("s")},z=function(){return x("y")||x("M")||x("d")},A=function(){var b=a("").append(a("").append(a("").addClass("prev").attr("data-action","previous").append(a("").addClass(d.icons.previous))).append(a("").addClass("picker-switch").attr("data-action","pickerSwitch").attr("colspan",d.calendarWeeks?"6":"5")).append(a("").addClass("next").attr("data-action","next").append(a("").addClass(d.icons.next)))),c=a("").append(a("").append(a("").attr("colspan",d.calendarWeeks?"8":"7")));return[a("
").addClass("datepicker-days").append(a("").addClass("table-condensed").append(b).append(a(""))),a("
").addClass("datepicker-months").append(a("
").addClass("table-condensed").append(b.clone()).append(c.clone())),a("
").addClass("datepicker-years").append(a("
").addClass("table-condensed").append(b.clone()).append(c.clone()))]},B=function(){var b=a(""),c=a(""),e=a("");return x("h")&&(b.append(a("
").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","incrementHours").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-hour").attr("data-time-component","hours").attr("data-action","showHours"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","decrementHours").append(a("").addClass(d.icons.down))))),x("m")&&(x("h")&&(b.append(a("").addClass("separator")),c.append(a("").addClass("separator").html(":")),e.append(a("").addClass("separator"))),b.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","incrementMinutes").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-minute").attr("data-time-component","minutes").attr("data-action","showMinutes"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","decrementMinutes").append(a("").addClass(d.icons.down))))),x("s")&&(x("m")&&(b.append(a("").addClass("separator")),c.append(a("").addClass("separator").html(":")),e.append(a("").addClass("separator"))),b.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","incrementSeconds").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-second").attr("data-time-component","seconds").attr("data-action","showSeconds"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1"}).addClass("btn").attr("data-action","decrementSeconds").append(a("").addClass(d.icons.down))))),f||(b.append(a("").addClass("separator")),c.append(a("").append(a("").addClass("separator"))),a("
").addClass("timepicker-picker").append(a("").addClass("table-condensed").append([b,c,e]))},C=function(){var b=a("
").addClass("timepicker-hours").append(a("
").addClass("table-condensed")),c=a("
").addClass("timepicker-minutes").append(a("
").addClass("table-condensed")),d=a("
").addClass("timepicker-seconds").append(a("
").addClass("table-condensed")),e=[B()];return x("h")&&e.push(b),x("m")&&e.push(c),x("s")&&e.push(d),e},D=function(){var b=[];return d.showTodayButton&&b.push(a("
").append(a("").attr("data-action","today").append(a("").addClass(d.icons.today)))),!d.sideBySide&&z()&&y()&&b.push(a("").append(a("").attr("data-action","togglePicker").append(a("").addClass(d.icons.time)))),d.showClear&&b.push(a("").append(a("").attr("data-action","clear").append(a("").addClass(d.icons.clear)))),d.showClose&&b.push(a("").append(a("").attr("data-action","close").append(a("").addClass(d.icons.close)))),a("").addClass("table-condensed").append(a("").append(a("").append(b)))},E=function(){var b=a("
").addClass("bootstrap-datetimepicker-widget dropdown-menu"),c=a("
").addClass("datepicker").append(A()),e=a("
").addClass("timepicker").append(C()),g=a("
    ").addClass("list-unstyled"),h=a("
  • ").addClass("picker-switch"+(d.collapse?" accordion-toggle":"")).append(D());return d.inline&&b.removeClass("dropdown-menu"),f&&b.addClass("usetwentyfour"),d.sideBySide&&z()&&y()?(b.addClass("timepicker-sbs"),b.append(a("
    ").addClass("row").append(c.addClass("col-sm-6")).append(e.addClass("col-sm-6"))),b.append(h),b):("top"===d.toolbarPlacement&&g.append(h),z()&&g.append(a("
  • ").addClass(d.collapse&&y()?"collapse in":"").append(c)),"default"===d.toolbarPlacement&&g.append(h),y()&&g.append(a("
  • ").addClass(d.collapse&&z()?"collapse":"").append(e)),"bottom"===d.toolbarPlacement&&g.append(h),b.append(g))},F=function(){var b,e={};return b=c.is("input")||d.inline?c.data():c.find("input").data(),b.dateOptions&&b.dateOptions instanceof Object&&(e=a.extend(!0,e,b.dateOptions)),a.each(d,function(a){var c="date"+a.charAt(0).toUpperCase()+a.slice(1);void 0!==b[c]&&(e[a]=b[c])}),e},G=function(){var b,e=(n||c).position(),f=(n||c).offset(),g=d.widgetPositioning.vertical,h=d.widgetPositioning.horizontal;if(d.widgetParent)b=d.widgetParent.append(o);else if(c.is("input"))b=c.parent().append(o);else{if(d.inline)return void(b=c.append(o));b=c,c.children().first().after(o)}if("auto"===g&&(g=f.top+1.5*o.height()>=a(window).height()+a(window).scrollTop()&&o.height()+c.outerHeight()a(window).width()?"right":"left"),"top"===g?o.addClass("top").removeClass("bottom"):o.addClass("bottom").removeClass("top"),"right"===h?o.addClass("pull-right"):o.removeClass("pull-right"),"relative"!==b.css("position")&&(b=b.parents().filter(function(){return"relative"===a(this).css("position")}).first()),0===b.length)throw new Error("datetimepicker component should be placed within a relative positioned container");o.css({top:"top"===g?"auto":e.top+c.outerHeight(),bottom:"top"===g?e.top+c.outerHeight():"auto",left:"left"===h?b.css("padding-left"):"auto",right:"left"===h?"auto":b.width()-c.outerWidth()})},H=function(a){"dp.change"===a.type&&(a.date&&a.date.isSame(a.oldDate)||!a.date&&!a.oldDate)||c.trigger(a)},I=function(a){o&&(a&&(i=Math.max(p,Math.min(2,i+a))),o.find(".datepicker > div").hide().filter(".datepicker-"+q[i].clsName).show())},J=function(){var b=a("
"),c=l.clone().startOf("w");for(d.calendarWeeks===!0&&b.append(a(""),d.calendarWeeks&&e.append('"),i.push(e)),f="",c.isBefore(l,"M")&&(f+=" old"),c.isAfter(l,"M")&&(f+=" new"),c.isSame(k,"d")&&!m&&(f+=" active"),M(c,"d")||(f+=" disabled"),c.isSame(b(),"d")&&(f+=" today"),(0===c.day()||6===c.day())&&(f+=" weekend"),e.append('"),c.add(1,"d");g.find("tbody").empty().append(i),O(),P()}},R=function(){var b=o.find(".timepicker-hours table"),c=l.clone().startOf("d"),d=[],e=a("");for(l.hour()>11&&!f&&c.hour(12);c.isSame(l,"d")&&(f||l.hour()<12&&c.hour()<12||l.hour()>11);)c.hour()%4===0&&(e=a(""),d.push(e)),e.append('"),c.add(1,"h");b.empty().append(d)},S=function(){for(var b=o.find(".timepicker-minutes table"),c=l.clone().startOf("h"),e=[],f=a(""),g=1===d.stepping?5:d.stepping;l.isSame(c,"h");)c.minute()%(4*g)===0&&(f=a(""),e.push(f)),f.append('"),c.add(g,"m");b.empty().append(e)},T=function(){for(var b=o.find(".timepicker-seconds table"),c=l.clone().startOf("m"),d=[],e=a("");l.isSame(c,"m");)c.second()%20===0&&(e=a(""),d.push(e)),e.append('"),c.add(5,"s");b.empty().append(d)},U=function(){var a=o.find(".timepicker span[data-time-component]");f||o.find(".timepicker [data-action=togglePeriod]").text(k.format("A")),a.filter("[data-time-component=hours]").text(k.format(f?"HH":"hh")),a.filter("[data-time-component=minutes]").text(k.format("mm")),a.filter("[data-time-component=seconds]").text(k.format("ss")),R(),S(),T()},V=function(){o&&(Q(),U())},W=function(a){var b=m?null:k;return a?(a=a.clone().locale(d.locale),1!==d.stepping&&a.minutes(Math.round(a.minutes()/d.stepping)*d.stepping%60).seconds(0),void(M(a)?(k=a,l=k.clone(),e.val(k.format(g)),c.data("date",k.format(g)),V(),m=!1,H({type:"dp.change",date:k.clone(),oldDate:b})):(d.keepInvalid||e.val(m?"":k.format(g)),H({type:"dp.error",date:a})))):(m=!0,e.val(""),c.data("date",""),H({type:"dp.change",date:null,oldDate:b}),void V())},X=function(){var b=!1;return o?(o.find(".collapse").each(function(){var c=a(this).data("collapse");return c&&c.transitioning?(b=!0,!1):!0}),b?j:(n&&n.hasClass("btn")&&n.toggleClass("active"),o.hide(),a(window).off("resize",G),o.off("click","[data-action]"),o.off("mousedown",!1),o.remove(),o=!1,H({type:"dp.hide",date:k.clone()}),j)):j},Y=function(){W(null)},Z={next:function(){l.add(q[i].navStep,q[i].navFnc),Q()},previous:function(){l.subtract(q[i].navStep,q[i].navFnc),Q()},pickerSwitch:function(){I(1)},selectMonth:function(b){var c=a(b.target).closest("tbody").find("span").index(a(b.target));l.month(c),i===p?(W(k.clone().year(l.year()).month(l.month())),d.inline||X()):(I(-1),Q())},selectYear:function(b){var c=parseInt(a(b.target).text(),10)||0;l.year(c),i===p?(W(k.clone().year(l.year())),d.inline||X()):(I(-1),Q())},selectDay:function(b){var c=l.clone();a(b.target).is(".old")&&c.subtract(1,"M"),a(b.target).is(".new")&&c.add(1,"M"),W(c.date(parseInt(a(b.target).text(),10))),y()||d.keepOpen||d.inline||X()},incrementHours:function(){W(k.clone().add(1,"h"))},incrementMinutes:function(){W(k.clone().add(d.stepping,"m"))},incrementSeconds:function(){W(k.clone().add(1,"s"))},decrementHours:function(){W(k.clone().subtract(1,"h"))},decrementMinutes:function(){W(k.clone().subtract(d.stepping,"m"))},decrementSeconds:function(){W(k.clone().subtract(1,"s"))},togglePeriod:function(){W(k.clone().add(k.hours()>=12?-12:12,"h"))},togglePicker:function(b){var c,e=a(b.target),f=e.closest("ul"),g=f.find(".in"),h=f.find(".collapse:not(.in)");if(g&&g.length){if(c=g.data("collapse"),c&&c.transitioning)return;g.collapse?(g.collapse("hide"),h.collapse("show")):(g.removeClass("in"),h.addClass("in")),e.is("span")?e.toggleClass(d.icons.time+" "+d.icons.date):e.find("span").toggleClass(d.icons.time+" "+d.icons.date)}},showPicker:function(){o.find(".timepicker > div:not(.timepicker-picker)").hide(),o.find(".timepicker .timepicker-picker").show()},showHours:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-hours").show()},showMinutes:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-minutes").show()},showSeconds:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-seconds").show()},selectHour:function(b){var c=parseInt(a(b.target).text(),10);f||(k.hours()>=12?12!==c&&(c+=12):12===c&&(c=0)),W(k.clone().hours(c)),Z.showPicker.call(j)},selectMinute:function(b){W(k.clone().minutes(parseInt(a(b.target).text(),10))),Z.showPicker.call(j)},selectSecond:function(b){W(k.clone().seconds(parseInt(a(b.target).text(),10))),Z.showPicker.call(j)},clear:Y,today:function(){W(b())},close:X},$=function(b){return a(b.currentTarget).is(".disabled")?!1:(Z[a(b.currentTarget).data("action")].apply(j,arguments),!1)},_=function(){var c,f={year:function(a){return a.month(0).date(1).hours(0).seconds(0).minutes(0)},month:function(a){return a.date(1).hours(0).seconds(0).minutes(0)},day:function(a){return a.hours(0).seconds(0).minutes(0)},hour:function(a){return a.seconds(0).minutes(0)},minute:function(a){return a.seconds(0)}};return e.prop("disabled")||!d.ignoreReadonly&&e.prop("readonly")||o?j:(d.useCurrent&&m&&(e.is("input")&&0===e.val().trim().length||d.inline)&&(c=b(),"string"==typeof d.useCurrent&&(c=f[d.useCurrent](c)),W(c)),o=E(),J(),N(),o.find(".timepicker-hours").hide(),o.find(".timepicker-minutes").hide(),o.find(".timepicker-seconds").hide(),V(),I(),a(window).on("resize",G),o.on("click","[data-action]",$),o.on("mousedown",!1),n&&n.hasClass("btn")&&n.toggleClass("active"),o.show(),G(),e.is(":focus")||e.focus(),H({type:"dp.show"}),j)},ab=function(){return o?X():_()},bb=function(a){return a=b.isMoment(a)||a instanceof Date?b(a):b(a,h,d.useStrict),a.locale(d.locale),a},cb=function(a){var b,c,e,f,g=null,h=[],i={},k=a.which,l="p";w[k]=l;for(b in w)w.hasOwnProperty(b)&&w[b]===l&&(h.push(b),parseInt(b,10)!==k&&(i[b]=!0));for(b in d.keyBinds)if(d.keyBinds.hasOwnProperty(b)&&"function"==typeof d.keyBinds[b]&&(e=b.split(" "),e.length===h.length&&v[k]===e[e.length-1])){for(f=!0,c=e.length-2;c>=0;c--)if(!(v[e[c]]in i)){f=!1;break}if(f){g=d.keyBinds[b];break}}g&&(g.call(j,o),a.stopPropagation(),a.preventDefault())},db=function(a){w[a.which]="r",a.stopPropagation(),a.preventDefault()},eb=function(b){var c=a(b.target).val().trim(),d=c?bb(c):null;return W(d),b.stopImmediatePropagation(),!1},fb=function(){e.on({change:eb,blur:d.debug?"":X,keydown:cb,keyup:db}),c.is("input")?e.on({focus:_}):n&&(n.on("click",ab),n.on("mousedown",!1))},gb=function(){e.off({change:eb,blur:X,keydown:cb,keyup:db}),c.is("input")?e.off({focus:_}):n&&(n.off("click",ab),n.off("mousedown",!1))},hb=function(b){var c={};return a.each(b,function(){var a=bb(this);a.isValid()&&(c[a.format("YYYY-MM-DD")]=!0)}),Object.keys(c).length?c:!1},ib=function(){var a=d.format||"L LT";g=a.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){var b=k.localeData().longDateFormat(a)||a;return b.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){return k.localeData().longDateFormat(a)||a})}),h=d.extraFormats?d.extraFormats.slice():[],h.indexOf(a)<0&&h.indexOf(g)<0&&h.push(g),f=g.toLowerCase().indexOf("a")<1&&g.indexOf("h")<1,x("y")&&(p=2),x("M")&&(p=1),x("d")&&(p=0),i=Math.max(p,i),m||W(k)};if(j.destroy=function(){X(),gb(),c.removeData("DateTimePicker"),c.removeData("date")},j.toggle=ab,j.show=_,j.hide=X,j.disable=function(){return X(),n&&n.hasClass("btn")&&n.addClass("disabled"),e.prop("disabled",!0),j},j.enable=function(){return n&&n.hasClass("btn")&&n.removeClass("disabled"),e.prop("disabled",!1),j},j.ignoreReadonly=function(a){if(0===arguments.length)return d.ignoreReadonly;if("boolean"!=typeof a)throw new TypeError("ignoreReadonly () expects a boolean parameter");return d.ignoreReadonly=a,j},j.options=function(b){if(0===arguments.length)return a.extend(!0,{},d);if(!(b instanceof Object))throw new TypeError("options() options parameter should be an object");return a.extend(!0,d,b),a.each(d,function(a,b){if(void 0===j[a])throw new TypeError("option "+a+" is not recognized!");j[a](b)}),j},j.date=function(a){if(0===arguments.length)return m?null:k.clone();if(!(null===a||"string"==typeof a||b.isMoment(a)||a instanceof Date))throw new TypeError("date() parameter must be one of [null, string, moment or Date]");return W(null===a?null:bb(a)),j},j.format=function(a){if(0===arguments.length)return d.format;if("string"!=typeof a&&("boolean"!=typeof a||a!==!1))throw new TypeError("format() expects a sting or boolean:false parameter "+a);return d.format=a,g&&ib(),j},j.dayViewHeaderFormat=function(a){if(0===arguments.length)return d.dayViewHeaderFormat;if("string"!=typeof a)throw new TypeError("dayViewHeaderFormat() expects a string parameter");return d.dayViewHeaderFormat=a,j},j.extraFormats=function(a){if(0===arguments.length)return d.extraFormats;if(a!==!1&&!(a instanceof Array))throw new TypeError("extraFormats() expects an array or false parameter");return d.extraFormats=a,h&&ib(),j},j.disabledDates=function(b){if(0===arguments.length)return d.disabledDates?a.extend({},d.disabledDates):d.disabledDates;if(!b)return d.disabledDates=!1,V(),j;if(!(b instanceof Array))throw new TypeError("disabledDates() expects an array parameter");return d.disabledDates=hb(b),d.enabledDates=!1,V(),j},j.enabledDates=function(b){if(0===arguments.length)return d.enabledDates?a.extend({},d.enabledDates):d.enabledDates;if(!b)return d.enabledDates=!1,V(),j;if(!(b instanceof Array))throw new TypeError("enabledDates() expects an array parameter");return d.enabledDates=hb(b),d.disabledDates=!1,V(),j},j.daysOfWeekDisabled=function(a){if(0===arguments.length)return d.daysOfWeekDisabled.splice(0);if(!(a instanceof Array))throw new TypeError("daysOfWeekDisabled() expects an array parameter");return d.daysOfWeekDisabled=a.reduce(function(a,b){return b=parseInt(b,10),b>6||0>b||isNaN(b)?a:(-1===a.indexOf(b)&&a.push(b),a)},[]).sort(),V(),j},j.maxDate=function(a){if(0===arguments.length)return d.maxDate?d.maxDate.clone():d.maxDate;if("boolean"==typeof a&&a===!1)return d.maxDate=!1,V(),j;"string"==typeof a&&("now"===a||"moment"===a)&&(a=b());var c=bb(a);if(!c.isValid())throw new TypeError("maxDate() Could not parse date parameter: "+a);if(d.minDate&&c.isBefore(d.minDate))throw new TypeError("maxDate() date parameter is before options.minDate: "+c.format(g));return d.maxDate=c,d.maxDate.isBefore(a)&&W(d.maxDate),l.isAfter(c)&&(l=c.clone()),V(),j},j.minDate=function(a){if(0===arguments.length)return d.minDate?d.minDate.clone():d.minDate;if("boolean"==typeof a&&a===!1)return d.minDate=!1,V(),j;"string"==typeof a&&("now"===a||"moment"===a)&&(a=b());var c=bb(a);if(!c.isValid())throw new TypeError("minDate() Could not parse date parameter: "+a);if(d.maxDate&&c.isAfter(d.maxDate))throw new TypeError("minDate() date parameter is after options.maxDate: "+c.format(g));return d.minDate=c,d.minDate.isAfter(a)&&W(d.minDate),l.isBefore(c)&&(l=c.clone()),V(),j},j.defaultDate=function(a){if(0===arguments.length)return d.defaultDate?d.defaultDate.clone():d.defaultDate;if(!a)return d.defaultDate=!1,j;"string"==typeof a&&("now"===a||"moment"===a)&&(a=b());var c=bb(a);if(!c.isValid())throw new TypeError("defaultDate() Could not parse date parameter: "+a);if(!M(c))throw new TypeError("defaultDate() date passed is invalid according to component setup validations");return d.defaultDate=c,d.defaultDate&&""===e.val().trim()&&void 0===e.attr("placeholder")&&W(d.defaultDate),j},j.locale=function(a){if(0===arguments.length)return d.locale;if(!b.localeData(a))throw new TypeError("locale() locale "+a+" is not loaded from moment locales!");return d.locale=a,k.locale(d.locale),l.locale(d.locale),g&&ib(),o&&(X(),_()),j},j.stepping=function(a){return 0===arguments.length?d.stepping:(a=parseInt(a,10),(isNaN(a)||1>a)&&(a=1),d.stepping=a,j)},j.useCurrent=function(a){var b=["year","month","day","hour","minute"];if(0===arguments.length)return d.useCurrent;if("boolean"!=typeof a&&"string"!=typeof a)throw new TypeError("useCurrent() expects a boolean or string parameter");if("string"==typeof a&&-1===b.indexOf(a.toLowerCase()))throw new TypeError("useCurrent() expects a string parameter of "+b.join(", "));return d.useCurrent=a,j},j.collapse=function(a){if(0===arguments.length)return d.collapse;if("boolean"!=typeof a)throw new TypeError("collapse() expects a boolean parameter");return d.collapse===a?j:(d.collapse=a,o&&(X(),_()),j)},j.icons=function(b){if(0===arguments.length)return a.extend({},d.icons);if(!(b instanceof Object))throw new TypeError("icons() expects parameter to be an Object");return a.extend(d.icons,b),o&&(X(),_()),j},j.useStrict=function(a){if(0===arguments.length)return d.useStrict;if("boolean"!=typeof a)throw new TypeError("useStrict() expects a boolean parameter");return d.useStrict=a,j},j.sideBySide=function(a){if(0===arguments.length)return d.sideBySide;if("boolean"!=typeof a)throw new TypeError("sideBySide() expects a boolean parameter");return d.sideBySide=a,o&&(X(),_()),j},j.viewMode=function(a){if(0===arguments.length)return d.viewMode;if("string"!=typeof a)throw new TypeError("viewMode() expects a string parameter");if(-1===r.indexOf(a))throw new TypeError("viewMode() parameter must be one of ("+r.join(", ")+") value");return d.viewMode=a,i=Math.max(r.indexOf(a),p),I(),j},j.toolbarPlacement=function(a){if(0===arguments.length)return d.toolbarPlacement;if("string"!=typeof a)throw new TypeError("toolbarPlacement() expects a string parameter");if(-1===u.indexOf(a))throw new TypeError("toolbarPlacement() parameter must be one of ("+u.join(", ")+") value");return d.toolbarPlacement=a,o&&(X(),_()),j},j.widgetPositioning=function(b){if(0===arguments.length)return a.extend({},d.widgetPositioning);if("[object Object]"!=={}.toString.call(b))throw new TypeError("widgetPositioning() expects an object variable");if(b.horizontal){if("string"!=typeof b.horizontal)throw new TypeError("widgetPositioning() horizontal variable must be a string");if(b.horizontal=b.horizontal.toLowerCase(),-1===t.indexOf(b.horizontal))throw new TypeError("widgetPositioning() expects horizontal parameter to be one of ("+t.join(", ")+")");d.widgetPositioning.horizontal=b.horizontal}if(b.vertical){if("string"!=typeof b.vertical)throw new TypeError("widgetPositioning() vertical variable must be a string");if(b.vertical=b.vertical.toLowerCase(),-1===s.indexOf(b.vertical))throw new TypeError("widgetPositioning() expects vertical parameter to be one of ("+s.join(", ")+")");d.widgetPositioning.vertical=b.vertical}return V(),j},j.calendarWeeks=function(a){if(0===arguments.length)return d.calendarWeeks;if("boolean"!=typeof a)throw new TypeError("calendarWeeks() expects parameter to be a boolean value");return d.calendarWeeks=a,V(),j},j.showTodayButton=function(a){if(0===arguments.length)return d.showTodayButton;if("boolean"!=typeof a)throw new TypeError("showTodayButton() expects a boolean parameter");return d.showTodayButton=a,o&&(X(),_()),j},j.showClear=function(a){if(0===arguments.length)return d.showClear;if("boolean"!=typeof a)throw new TypeError("showClear() expects a boolean parameter");return d.showClear=a,o&&(X(),_()),j},j.widgetParent=function(b){if(0===arguments.length)return d.widgetParent;if("string"==typeof b&&(b=a(b)),null!==b&&"string"!=typeof b&&!(b instanceof a))throw new TypeError("widgetParent() expects a string or a jQuery object parameter");return d.widgetParent=b,o&&(X(),_()),j},j.keepOpen=function(a){if(0===arguments.length)return d.keepOpen;if("boolean"!=typeof a)throw new TypeError("keepOpen() expects a boolean parameter");return d.keepOpen=a,j},j.inline=function(a){if(0===arguments.length)return d.inline;if("boolean"!=typeof a)throw new TypeError("inline() expects a boolean parameter");return d.inline=a,j},j.clear=function(){return Y(),j},j.keyBinds=function(a){return d.keyBinds=a,j},j.debug=function(a){if("boolean"!=typeof a)throw new TypeError("debug() expects a boolean parameter");return d.debug=a,j},j.showClose=function(a){if(0===arguments.length)return d.showClose;if("boolean"!=typeof a)throw new TypeError("showClose() expects a boolean parameter");return d.showClose=a,j},j.keepInvalid=function(a){if(0===arguments.length)return d.keepInvalid;if("boolean"!=typeof a)throw new TypeError("keepInvalid() expects a boolean parameter");return d.keepInvalid=a,j},j.datepickerInput=function(a){if(0===arguments.length)return d.datepickerInput;if("string"!=typeof a)throw new TypeError("datepickerInput() expects a string parameter");return d.datepickerInput=a,j},c.is("input"))e=c;else if(e=c.find(d.datepickerInput),0===e.size())e=c.find("input");else if(!e.is("input"))throw new Error('CSS class "'+d.datepickerInput+'" cannot be applied to non input element');if(c.hasClass("input-group")&&(n=c.find(0===c.find(".datepickerbutton").size()?'[class^="input-group-"]':".datepickerbutton")),!d.inline&&!e.is("input"))throw new Error("Could not initialize DateTimePicker without an input element");return a.extend(!0,d,F()),j.options(d),ib(),fb(),e.prop("disabled")&&j.disable(),e.is("input")&&0!==e.val().trim().length?W(bb(e.val().trim())):d.defaultDate&&void 0===e.attr("placeholder")&&W(d.defaultDate),d.inline&&_(),j};a.fn.datetimepicker=function(b){return this.each(function(){var d=a(this);d.data("DateTimePicker")||(b=a.extend(!0,{},a.fn.datetimepicker.defaults,b),d.data("DateTimePicker",c(d,b)))})},a.fn.datetimepicker.defaults={format:!1,dayViewHeaderFormat:"MMMM YYYY",extraFormats:!1,stepping:1,minDate:!1,maxDate:!1,useCurrent:!0,collapse:!0,locale:b.locale(),defaultDate:!1,disabledDates:!1,enabledDates:!1,icons:{time:"glyphicon glyphicon-time",date:"glyphicon glyphicon-calendar",up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down",previous:"glyphicon glyphicon-chevron-left",next:"glyphicon glyphicon-chevron-right",today:"glyphicon glyphicon-screenshot",clear:"glyphicon glyphicon-trash",close:"glyphicon glyphicon-remove"},useStrict:!1,sideBySide:!1,daysOfWeekDisabled:[],calendarWeeks:!1,viewMode:"days",toolbarPlacement:"default",showTodayButton:!1,showClear:!1,showClose:!1,widgetPositioning:{horizontal:"auto",vertical:"auto"},widgetParent:null,ignoreReadonly:!1,keepOpen:!1,inline:!1,keepInvalid:!1,datepickerInput:".datepickerinput",keyBinds:{up:function(a){if(a){var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().subtract(7,"d"):c.clone().add(1,"m"))}},down:function(a){if(!a)return void this.show();var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().add(7,"d"):c.clone().subtract(1,"m"))},"control up":function(a){if(a){var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().subtract(1,"y"):c.clone().add(1,"h"))}},"control down":function(a){if(a){var c=this.date()||b();this.date(a.find(".datepicker").is(":visible")?c.clone().add(1,"y"):c.clone().subtract(1,"h"))}},left:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().subtract(1,"d"))}},right:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().add(1,"d"))}},pageUp:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().subtract(1,"M"))}},pageDown:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().add(1,"M"))}},enter:function(){this.hide()},escape:function(){this.hide()},"control space":function(a){a.find(".timepicker").is(":visible")&&a.find('.btn[data-action="togglePeriod"]').click()},t:function(){this.date(b())},"delete":function(){this.clear()}},debug:!1}}); \ No newline at end of file diff --git a/build/nuget/Bootstrap.v3.Datetimepicker.4.0.0.nupkg b/build/nuget/Bootstrap.v3.Datetimepicker.4.0.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..f38538a53e8a2a2f3bfc726c119340192c96fed1 GIT binary patch literal 23451 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 literal 0 HcmV?d00001 diff --git a/build/nuget/Bootstrap.v3.Datetimepicker.CSS.4.0.0.nupkg b/build/nuget/Bootstrap.v3.Datetimepicker.CSS.4.0.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..d10e267cfcd686ecaf8318f1ad27aa7f48f48bf4 GIT binary patch literal 24328 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 V)lkO5J{g9KdhMY~bjRrA>>op--F5%~ literal 0 HcmV?d00001 diff --git a/component.json b/component.json index fbaa84016..184d37480 100644 --- a/component.json +++ b/component.json @@ -1,10 +1,9 @@ { "name": "bootstrap-datetimepicker", - "version": "3.1.3", - "main": ["build/css/bootstrap-datetimepicker.min.css","build/js/bootstrap-datetimepicker.min.js"], + "version": "4.7.14", + "main": ["build/css/bootstrap-datetimepicker.min.css","build/js/bootstrap-datetimepicker.min.js","src/less/_bootstrap-datetimepicker.less","src/less/bootstrap-datetimepicker-build.less","src/js/bootstrap-datetimepicker.js"], "dependencies": { "jquery" : ">=1.8.3", - "bootstrap" : ">=3.0", "moment": ">=2.8.0" } } diff --git a/composer.json b/composer.json index cf5646145..f5d733ef4 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "eonasdan/bootstrap-datetimepicker", "type": "component", - "version": "3.1.3", + "version": "4.7.14", "description": "Date/time picker widget based on twitter bootstrap", "keywords": [ "bootstrap", @@ -12,7 +12,6 @@ "require": { "robloach/component-installer": "*", "components/jquery": ">=1.9.1", - "components/bootstrap": "3.*", "moment/moment": ">=2.8" }, "extra": { @@ -23,7 +22,9 @@ "files": [ "build/js/bootstrap-datetimepicker.min.js", "build/css/bootstrap-datetimepicker.css", - "build/css/bootstrap-datetimepicker.min.css" + "build/css/bootstrap-datetimepicker.min.css", + "src/less/_bootstrap-datetimepicker.less", + "src/less/bootstrap-datetimepicker-build.less" ] } } diff --git a/package.json b/package.json index 3c2afba97..512d4f0e1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bootstrap-datetimepicker", "main": "src/js/bootstrap-datetimepicker.js", - "version": "3.1.3", + "version": "4.7.14", "repository": { "type": "git", "url": "https://github.com/eonasdan/bootstrap-datetimepicker.git" @@ -15,21 +15,21 @@ "datepicker", "datetimepicker", "timepicker", - "moment" + "moment" ], "dependencies": { - "moment": "~2.8.1", - "bootstrap": "^3.0", - "jquery": "^1.8.3" + "moment": "~2.8.2", + "bootstrap": "^3.0", + "jquery": "latest" }, "devDependencies": { "grunt": "latest", + "grunt-contrib-jasmine": "^0.7.0", "grunt-contrib-jshint": "latest", + "grunt-contrib-less": "latest", "grunt-contrib-uglify": "latest", "grunt-jscs": "latest", - "load-grunt-tasks": "latest", "grunt-string-replace": "latest", - "grunt-contrib-less": "latest", - "bootstrap": "latest" + "load-grunt-tasks": "latest" } } diff --git a/src/js/bootstrap-datetimepicker.js b/src/js/bootstrap-datetimepicker.js index 44abcc1fe..034cf5d8c 100644 --- a/src/js/bootstrap-datetimepicker.js +++ b/src/js/bootstrap-datetimepicker.js @@ -1,1384 +1,2051 @@ +/*! version : 4.7.14 + ========================================================= + bootstrap-datetimejs + https://github.com/Eonasdan/bootstrap-datetimepicker + Copyright (c) 2015 Jonathan Peterson + ========================================================= + */ /* -//! version : 3.1.3 -========================================================= -bootstrap-datetimepicker.js -https://github.com/Eonasdan/bootstrap-datetimepicker -========================================================= -The MIT License (MIT) + The MIT License (MIT) -Copyright (c) 2014 Jonathan Peterson + Copyright (c) 2015 Jonathan Peterson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -;(function (root, factory) { + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +/*global define:false */ +/*global exports:false */ +/*global require:false */ +/*global jQuery:false */ +/*global moment:false */ +(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // AMD is used - Register as an anonymous module. define(['jquery', 'moment'], factory); } else if (typeof exports === 'object') { factory(require('jquery'), require('moment')); - } - else { - // Neither AMD or CommonJS used. Use global variables. - if (!jQuery) { - throw new Error('bootstrap-datetimepicker requires jQuery to be loaded first'); + } else { + // Neither AMD nor CommonJS used. Use global variables. + if (typeof jQuery === 'undefined') { + throw 'bootstrap-datetimepicker requires jQuery to be loaded first'; } - if (!moment) { - throw new Error('bootstrap-datetimepicker requires moment.js to be loaded first'); + if (typeof moment === 'undefined') { + throw 'bootstrap-datetimepicker requires Moment.js to be loaded first'; } - factory(root.jQuery, moment); + factory(jQuery, moment); } -}(this, function ($, moment) { +}(function ($, moment) { 'use strict'; - if (typeof moment === 'undefined') { - throw new Error('momentjs is required'); + if (!moment) { + throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first'); } - var dpgId = 0, + var dateTimePicker = function (element, options) { + var picker = {}, + date = moment().startOf('d'), + viewDate = date.clone(), + unset = true, + input, + component = false, + widget = false, + use24Hours, + minViewModeNumber = 0, + actualFormat, + parseFormats, + currentViewMode, + datePickerModes = [ + { + clsName: 'days', + navFnc: 'M', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'y', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'y', + navStep: 10 + } + ], + viewModes = ['days', 'months', 'years'], + verticalModes = ['top', 'bottom', 'auto'], + horizontalModes = ['left', 'right', 'auto'], + toolbarPlacements = ['default', 'top', 'bottom'], + keyMap = { + 'up': 38, + 38: 'up', + 'down': 40, + 40: 'down', + 'left': 37, + 37: 'left', + 'right': 39, + 39: 'right', + 'tab': 9, + 9: 'tab', + 'escape': 27, + 27: 'escape', + 'enter': 13, + 13: 'enter', + 'pageUp': 33, + 33: 'pageUp', + 'pageDown': 34, + 34: 'pageDown', + 'shift': 16, + 16: 'shift', + 'control': 17, + 17: 'control', + 'space': 32, + 32: 'space', + 't': 84, + 84: 't', + 'delete': 46, + 46: 'delete' + }, + keyState = {}, - DateTimePicker = function (element, options) { - var defaults = $.fn.datetimepicker.defaults, - - icons = { - time: 'glyphicon glyphicon-time', - date: 'glyphicon glyphicon-calendar', - up: 'glyphicon glyphicon-chevron-up', - down: 'glyphicon glyphicon-chevron-down' + /******************************************************************************** + * + * Private functions + * + ********************************************************************************/ + isEnabled = function (granularity) { + if (typeof granularity !== 'string' || granularity.length > 1) { + throw new TypeError('isEnabled expects a single character string parameter'); + } + switch (granularity) { + case 'y': + return actualFormat.indexOf('Y') !== -1; + case 'M': + return actualFormat.indexOf('M') !== -1; + case 'd': + return actualFormat.toLowerCase().indexOf('d') !== -1; + case 'h': + case 'H': + return actualFormat.toLowerCase().indexOf('h') !== -1; + case 'm': + return actualFormat.indexOf('m') !== -1; + case 's': + return actualFormat.indexOf('s') !== -1; + default: + return false; + } }, - picker = this, - errored = false, - dDate, + hasTime = function () { + return (isEnabled('h') || isEnabled('m') || isEnabled('s')); + }, - init = function () { - var icon = false, localeData, rInterval; - picker.options = $.extend({}, defaults, options); - picker.options.icons = $.extend({}, icons, picker.options.icons); + hasDate = function () { + return (isEnabled('y') || isEnabled('M') || isEnabled('d')); + }, - picker.element = $(element); + getDatePickerTemplate = function () { + var headTemplate = $('') + .append($('') + .append($('') + .append($('') + .append($('
").addClass("cw").text("#"));c.isBefore(l.clone().endOf("w"));)b.append(a("").addClass("dow").text(c.format("dd"))),c.add(1,"d");o.find(".datepicker-days thead").append(b)},K=function(a){return d.disabledDates[a.format("YYYY-MM-DD")]===!0},L=function(a){return d.enabledDates[a.format("YYYY-MM-DD")]===!0},M=function(a,b){return a.isValid()?d.disabledDates&&K(a)&&"M"!==b?!1:d.enabledDates&&!L(a)&&"M"!==b?!1:d.minDate&&a.isBefore(d.minDate,b)?!1:d.maxDate&&a.isAfter(d.maxDate,b)?!1:"d"===b&&-1!==d.daysOfWeekDisabled.indexOf(a.day())?!1:!0:!1},N=function(){for(var b=[],c=l.clone().startOf("y").hour(12);c.isSame(l,"y");)b.push(a("").attr("data-action","selectMonth").addClass("month").text(c.format("MMM"))),c.add(1,"M");o.find(".datepicker-months td").empty().append(b)},O=function(){var b=o.find(".datepicker-months"),c=b.find("th"),d=b.find("tbody").find("span");b.find(".disabled").removeClass("disabled"),M(l.clone().subtract(1,"y"),"y")||c.eq(0).addClass("disabled"),c.eq(1).text(l.year()),M(l.clone().add(1,"y"),"y")||c.eq(2).addClass("disabled"),d.removeClass("active"),k.isSame(l,"y")&&d.eq(k.month()).addClass("active"),d.each(function(b){M(l.clone().month(b),"M")||a(this).addClass("disabled")})},P=function(){var a=o.find(".datepicker-years"),b=a.find("th"),c=l.clone().subtract(5,"y"),e=l.clone().add(6,"y"),f="";for(a.find(".disabled").removeClass("disabled"),d.minDate&&d.minDate.isAfter(c,"y")&&b.eq(0).addClass("disabled"),b.eq(1).text(c.year()+"-"+e.year()),d.maxDate&&d.maxDate.isBefore(e,"y")&&b.eq(2).addClass("disabled");!c.isAfter(e,"y");)f+=''+c.year()+"",c.add(1,"y");a.find("td").html(f)},Q=function(){var c,e,f,g=o.find(".datepicker-days"),h=g.find("th"),i=[];if(z()){for(g.find(".disabled").removeClass("disabled"),h.eq(1).text(l.format(d.dayViewHeaderFormat)),M(l.clone().subtract(1,"M"),"M")||h.eq(0).addClass("disabled"),M(l.clone().add(1,"M"),"M")||h.eq(2).addClass("disabled"),c=l.clone().startOf("M").startOf("week");!l.clone().endOf("M").endOf("w").isBefore(c,"d");)0===c.weekday()&&(e=a("
'+c.week()+"'+c.date()+"
'+c.format(f?"HH":"hh")+"
'+c.format("mm")+"
'+c.format("ss")+"
').addClass('prev').attr('data-action', 'previous') + .append($('').addClass(options.icons.previous)) + ) + .append($('').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5'))) + .append($('').addClass('next').attr('data-action', 'next') + .append($('').addClass(options.icons.next)) + ) + ), + contTemplate = $('
').attr('colspan', (options.calendarWeeks ? '8' : '7'))) + ); - dataToOptions(); + return [ + $('
').addClass('datepicker-days') + .append($('').addClass('table-condensed') + .append(headTemplate) + .append($('')) + ), + $('
').addClass('datepicker-months') + .append($('
').addClass('table-condensed') + .append(headTemplate.clone()) + .append(contTemplate.clone()) + ), + $('
').addClass('datepicker-years') + .append($('
').addClass('table-condensed') + .append(headTemplate.clone()) + .append(contTemplate.clone()) + ) + ]; + }, - if (!(picker.options.pickTime || picker.options.pickDate)) { - throw new Error('Must choose at least one picker'); - } + getTimePickerMainTemplate = function () { + var topRow = $(''), + middleRow = $(''), + bottomRow = $(''); - picker.id = dpgId++; - moment.locale(picker.options.language); - picker.date = moment(); - picker.unset = false; - picker.isInput = picker.element.is('input'); - picker.component = false; - - if (picker.element.hasClass('input-group')) { - if (picker.element.find('.datepickerbutton').size() === 0) {//in case there is more then one 'input-group-addon' Issue #48 - picker.component = picker.element.find('[class^="input-group-"]'); + if (isEnabled('h')) { + topRow.append($('
') + .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementHours') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-hour').attr('data-time-component', 'hours').attr('data-action', 'showHours'))); + bottomRow.append($('') + .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementHours') + .append($('').addClass(options.icons.down)))); } - else { - picker.component = picker.element.find('.datepickerbutton'); - } - } - picker.format = picker.options.format; - - localeData = moment().localeData(); - - if (!picker.format) { - picker.format = (picker.options.pickDate ? localeData.longDateFormat('L') : ''); - if (picker.options.pickDate && picker.options.pickTime) { - picker.format += ' '; - } - picker.format += (picker.options.pickTime ? localeData.longDateFormat('LT') : ''); - if (picker.options.useSeconds) { - if (localeData.longDateFormat('LT').indexOf(' A') !== -1) { - picker.format = picker.format.split(' A')[0] + ':ss A'; + if (isEnabled('m')) { + if (isEnabled('h')) { + topRow.append($('').addClass('separator')); + middleRow.append($('').addClass('separator').html(':')); + bottomRow.append($('').addClass('separator')); } - else { - picker.format += ':ss'; + topRow.append($('') + .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementMinutes') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-minute').attr('data-time-component', 'minutes').attr('data-action', 'showMinutes'))); + bottomRow.append($('') + .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementMinutes') + .append($('').addClass(options.icons.down)))); + } + if (isEnabled('s')) { + if (isEnabled('m')) { + topRow.append($('').addClass('separator')); + middleRow.append($('').addClass('separator').html(':')); + bottomRow.append($('').addClass('separator')); } + topRow.append($('') + .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementSeconds') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-second').attr('data-time-component', 'seconds').attr('data-action', 'showSeconds'))); + bottomRow.append($('') + .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementSeconds') + .append($('').addClass(options.icons.down)))); } - } - picker.use24hours = (picker.format.toLowerCase().indexOf('a') < 0 && picker.format.indexOf('h') < 0); - if (picker.component) { - icon = picker.component.find('span'); - } - - if (picker.options.pickTime) { - if (icon) { - icon.addClass(picker.options.icons.time); + if (!use24Hours) { + topRow.append($('').addClass('separator')); + middleRow.append($('') + .append($('').addClass('separator')); } - } - if (picker.options.pickDate) { - if (icon) { - icon.removeClass(picker.options.icons.time); - icon.addClass(picker.options.icons.date); + + return $('
').addClass('timepicker-picker') + .append($('').addClass('table-condensed') + .append([topRow, middleRow, bottomRow])); + }, + + getTimePickerTemplate = function () { + var hoursView = $('
').addClass('timepicker-hours') + .append($('
').addClass('table-condensed')), + minutesView = $('
').addClass('timepicker-minutes') + .append($('
').addClass('table-condensed')), + secondsView = $('
').addClass('timepicker-seconds') + .append($('
').addClass('table-condensed')), + ret = [getTimePickerMainTemplate()]; + + if (isEnabled('h')) { + ret.push(hoursView); } - } - - picker.options.widgetParent = - typeof picker.options.widgetParent === 'string' && picker.options.widgetParent || - picker.element.parents().filter(function () { - return 'scroll' === $(this).css('overflow-y'); - }).get(0) || - 'body'; - - picker.widget = $(getTemplate()).appendTo(picker.options.widgetParent); - - picker.minViewMode = picker.options.minViewMode || 0; - if (typeof picker.minViewMode === 'string') { - switch (picker.minViewMode) { - case 'months': - picker.minViewMode = 1; - break; - case 'years': - picker.minViewMode = 2; - break; - default: - picker.minViewMode = 0; - break; + if (isEnabled('m')) { + ret.push(minutesView); } - } - picker.viewMode = picker.options.viewMode || 0; - if (typeof picker.viewMode === 'string') { - switch (picker.viewMode) { - case 'months': - picker.viewMode = 1; - break; - case 'years': - picker.viewMode = 2; - break; - default: - picker.viewMode = 0; - break; + if (isEnabled('s')) { + ret.push(secondsView); } - } - picker.viewMode = Math.max(picker.viewMode, picker.minViewMode); + return ret; + }, - picker.options.disabledDates = indexGivenDates(picker.options.disabledDates); - picker.options.enabledDates = indexGivenDates(picker.options.enabledDates); + getToolbar = function () { + var row = []; + if (options.showTodayButton) { + row.push($('
').append($('').attr('data-action', 'today').append($('').addClass(options.icons.today)))); + } + if (!options.sideBySide && hasDate() && hasTime()) { + row.push($('').append($('').attr('data-action', 'togglePicker').append($('').addClass(options.icons.time)))); + } + if (options.showClear) { + row.push($('').append($('').attr('data-action', 'clear').append($('').addClass(options.icons.clear)))); + } + if (options.showClose) { + row.push($('').append($('').attr('data-action', 'close').append($('').addClass(options.icons.close)))); + } + return $('').addClass('table-condensed').append($('').append($('').append(row))); + }, - picker.startViewMode = picker.viewMode; - picker.setMinDate(picker.options.minDate); - picker.setMaxDate(picker.options.maxDate); - fillDow(); - fillMonths(); - fillHours(); - fillMinutes(); - fillSeconds(); - update(); - showMode(); - if (!getPickerInput().prop('disabled')) { - attachDatePickerEvents(); - } - if (picker.options.defaultDate !== '' && getPickerInput().val() === '') { - picker.setValue(picker.options.defaultDate); - } - if (picker.options.minuteStepping !== 1) { - rInterval = picker.options.minuteStepping; - picker.date.minutes((Math.round(picker.date.minutes() / rInterval) * rInterval) % 60).seconds(0); - } - }, + getTemplate = function () { + var template = $('
').addClass('bootstrap-datetimepicker-widget dropdown-menu'), + dateView = $('
').addClass('datepicker').append(getDatePickerTemplate()), + timeView = $('
').addClass('timepicker').append(getTimePickerTemplate()), + content = $('
    ').addClass('list-unstyled'), + toolbar = $('
  • ').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar()); - getPickerInput = function () { - var input; + if (options.inline) { + template.removeClass('dropdown-menu'); + } - if (picker.isInput) { - return picker.element; - } - input = picker.element.find('.datepickerinput'); - if (input.size() === 0) { - input = picker.element.find('input'); - } - else if (!input.is('input')) { - throw new Error('CSS class "datepickerinput" cannot be applied to non input element'); - } - return input; - }, + if (use24Hours) { + template.addClass('usetwentyfour'); + } + if (options.sideBySide && hasDate() && hasTime()) { + template.addClass('timepicker-sbs'); + template.append( + $('
    ').addClass('row') + .append(dateView.addClass('col-sm-6')) + .append(timeView.addClass('col-sm-6')) + ); + template.append(toolbar); + return template; + } - dataToOptions = function () { - var eData; - if (picker.element.is('input')) { - eData = picker.element.data(); - } - else { - eData = picker.element.find('input').data(); - } - if (eData.dateFormat !== undefined) { - picker.options.format = eData.dateFormat; - } - if (eData.datePickdate !== undefined) { - picker.options.pickDate = eData.datePickdate; - } - if (eData.datePicktime !== undefined) { - picker.options.pickTime = eData.datePicktime; - } - if (eData.dateUseminutes !== undefined) { - picker.options.useMinutes = eData.dateUseminutes; - } - if (eData.dateUseseconds !== undefined) { - picker.options.useSeconds = eData.dateUseseconds; - } - if (eData.dateUsecurrent !== undefined) { - picker.options.useCurrent = eData.dateUsecurrent; - } - if (eData.calendarWeeks !== undefined) { - picker.options.calendarWeeks = eData.calendarWeeks; - } - if (eData.dateMinutestepping !== undefined) { - picker.options.minuteStepping = eData.dateMinutestepping; - } - if (eData.dateMindate !== undefined) { - picker.options.minDate = eData.dateMindate; - } - if (eData.dateMaxdate !== undefined) { - picker.options.maxDate = eData.dateMaxdate; - } - if (eData.dateShowtoday !== undefined) { - picker.options.showToday = eData.dateShowtoday; - } - if (eData.dateCollapse !== undefined) { - picker.options.collapse = eData.dateCollapse; - } - if (eData.dateLanguage !== undefined) { - picker.options.language = eData.dateLanguage; - } - if (eData.dateDefaultdate !== undefined) { - picker.options.defaultDate = eData.dateDefaultdate; - } - if (eData.dateDisableddates !== undefined) { - picker.options.disabledDates = eData.dateDisableddates; - } - if (eData.dateEnableddates !== undefined) { - picker.options.enabledDates = eData.dateEnableddates; - } - if (eData.dateIcons !== undefined) { - picker.options.icons = eData.dateIcons; - } - if (eData.dateUsestrict !== undefined) { - picker.options.useStrict = eData.dateUsestrict; - } - if (eData.dateDirection !== undefined) { - picker.options.direction = eData.dateDirection; - } - if (eData.dateSidebyside !== undefined) { - picker.options.sideBySide = eData.dateSidebyside; - } - if (eData.dateDaysofweekdisabled !== undefined) { - picker.options.daysOfWeekDisabled = eData.dateDaysofweekdisabled; - } - }, + if (options.toolbarPlacement === 'top') { + content.append(toolbar); + } + if (hasDate()) { + content.append($('
  • ').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView)); + } + if (options.toolbarPlacement === 'default') { + content.append(toolbar); + } + if (hasTime()) { + content.append($('
  • ').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView)); + } + if (options.toolbarPlacement === 'bottom') { + content.append(toolbar); + } + return template.append(content); + }, - place = function () { - var position = 'absolute', - offset = picker.component ? picker.component.offset() : picker.element.offset(), - $window = $(window), - placePosition; + dataToOptions = function () { + var eData, + dataOptions = {}; - picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth(); - offset.top = offset.top + picker.element.outerHeight(); - - if (picker.options.direction === 'up') { - placePosition = 'top'; - } else if (picker.options.direction === 'bottom') { - placePosition = 'bottom'; - } else if (picker.options.direction === 'auto') { - if (offset.top + picker.widget.height() > $window.height() + $window.scrollTop() && picker.widget.height() + picker.element.outerHeight() < offset.top) { - placePosition = 'top'; + if (element.is('input') || options.inline) { + eData = element.data(); } else { - placePosition = 'bottom'; + eData = element.find('input').data(); } - } - if (placePosition === 'top') { - offset.bottom = $window.height() - offset.top + picker.element.outerHeight() + 3; - picker.widget.addClass('top').removeClass('bottom'); - } else { - offset.top += 1; - picker.widget.addClass('bottom').removeClass('top'); - } - if (picker.options.width !== undefined) { - picker.widget.width(picker.options.width); - } + if (eData.dateOptions && eData.dateOptions instanceof Object) { + dataOptions = $.extend(true, dataOptions, eData.dateOptions); + } - if (picker.options.orientation === 'left') { - picker.widget.addClass('left-oriented'); - offset.left = offset.left - picker.widget.width() + 20; - } - - if (isInFixed()) { - position = 'fixed'; - offset.top -= $window.scrollTop(); - offset.left -= $window.scrollLeft(); - } - - if ($window.width() < offset.left + picker.widget.outerWidth()) { - offset.right = $window.width() - offset.left - picker.width; - offset.left = 'auto'; - picker.widget.addClass('pull-right'); - } else { - offset.right = 'auto'; - picker.widget.removeClass('pull-right'); - } - - if (placePosition === 'top') { - picker.widget.css({ - position: position, - bottom: offset.bottom, - top: 'auto', - left: offset.left, - right: offset.right + $.each(options, function (key) { + var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); + if (eData[attributeName] !== undefined) { + dataOptions[key] = eData[attributeName]; + } }); - } else { - picker.widget.css({ - position: position, - top: offset.top, - bottom: 'auto', - left: offset.left, - right: offset.right - }); - } - }, + return dataOptions; + }, - notifyChange = function (oldDate, eventType) { - if (moment(picker.date).isSame(moment(oldDate)) && !errored) { - return; - } - errored = false; - picker.element.trigger({ - type: 'dp.change', - date: moment(picker.date), - oldDate: moment(oldDate) - }); + place = function () { + var position = (component || element).position(), + offset = (component || element).offset(), + vertical = options.widgetPositioning.vertical, + horizontal = options.widgetPositioning.horizontal, + parent; - if (eventType !== 'change') { - picker.element.change(); - } - }, - - notifyError = function (date) { - errored = true; - picker.element.trigger({ - type: 'dp.error', - date: moment(date, picker.format, picker.options.useStrict) - }); - }, - - update = function (newDate) { - moment.locale(picker.options.language); - var dateStr = newDate; - if (!dateStr) { - dateStr = getPickerInput().val(); - if (dateStr) { - picker.date = moment(dateStr, picker.format, picker.options.useStrict); + if (options.widgetParent) { + parent = options.widgetParent.append(widget); + } else if (element.is('input')) { + parent = element.parent().append(widget); + } else if (options.inline) { + parent = element.append(widget); + return; + } else { + parent = element; + element.children().first().after(widget); } - if (!picker.date) { - picker.date = moment(); - } - } - picker.viewDate = moment(picker.date).startOf('month'); - fillDate(); - fillTime(); - }, - fillDow = function () { - moment.locale(picker.options.language); - var html = $('
'), weekdaysMin = moment.weekdaysMin(), i; - if (picker.options.calendarWeeks === true) { - html.append(''); - } - if (moment().localeData()._week.dow === 0) { // starts on Sunday - for (i = 0; i < 7; i++) { - html.append(''); - } - } else { - for (i = 1; i < 8; i++) { - if (i === 7) { - html.append(''); + // Top and bottom logic + if (vertical === 'auto') { + if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && + widget.height() + element.outerHeight() < offset.top) { + vertical = 'top'; } else { - html.append(''); + vertical = 'bottom'; } } - } - picker.widget.find('.datepicker-days thead').append(html); - }, - fillMonths = function () { - moment.locale(picker.options.language); - var html = '', i, monthsShort = moment.monthsShort(); - for (i = 0; i < 12; i++) { - html += '' + monthsShort[i] + ''; - } - picker.widget.find('.datepicker-months td').append(html); - }, - - fillDate = function () { - if (!picker.options.pickDate) { - return; - } - moment.locale(picker.options.language); - var year = picker.viewDate.year(), - month = picker.viewDate.month(), - startYear = picker.options.minDate.year(), - startMonth = picker.options.minDate.month(), - endYear = picker.options.maxDate.year(), - endMonth = picker.options.maxDate.month(), - currentDate, - prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = moment.months(); - - picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled'); - picker.widget.find('.datepicker-months').find('.disabled').removeClass('disabled'); - picker.widget.find('.datepicker-years').find('.disabled').removeClass('disabled'); - - picker.widget.find('.datepicker-days th:eq(1)').text( - months[month] + ' ' + year); - - prevMonth = moment(picker.viewDate, picker.format, picker.options.useStrict).subtract(1, 'months'); - days = prevMonth.daysInMonth(); - prevMonth.date(days).startOf('week'); - if ((year === startYear && month <= startMonth) || year < startYear) { - picker.widget.find('.datepicker-days th:eq(0)').addClass('disabled'); - } - if ((year === endYear && month >= endMonth) || year > endYear) { - picker.widget.find('.datepicker-days th:eq(2)').addClass('disabled'); - } - - nextMonth = moment(prevMonth).add(42, 'd'); - while (prevMonth.isBefore(nextMonth)) { - if (prevMonth.weekday() === moment().startOf('week').weekday()) { - row = $(''); - html.push(row); - if (picker.options.calendarWeeks === true) { - row.append(''); + // Left and right logic + if (horizontal === 'auto') { + if (parent.width() < offset.left + widget.outerWidth() / 2 && + offset.left + widget.outerWidth() > $(window).width()) { + horizontal = 'right'; + } else { + horizontal = 'left'; } } - clsName = ''; - if (prevMonth.year() < year || (prevMonth.year() === year && prevMonth.month() < month)) { - clsName += ' old'; - } else if (prevMonth.year() > year || (prevMonth.year() === year && prevMonth.month() > month)) { - clsName += ' new'; + + if (vertical === 'top') { + widget.addClass('top').removeClass('bottom'); + } else { + widget.addClass('bottom').removeClass('top'); } - if (prevMonth.isSame(moment({y: picker.date.year(), M: picker.date.month(), d: picker.date.date()}))) { - clsName += ' active'; + + if (horizontal === 'right') { + widget.addClass('pull-right'); + } else { + widget.removeClass('pull-right'); } - if (isInDisableDates(prevMonth, 'day') || !isInEnableDates(prevMonth)) { - clsName += ' disabled'; + + // find the first parent element that has a relative css positioning + if (parent.css('position') !== 'relative') { + parent = parent.parents().filter(function () { + return $(this).css('position') === 'relative'; + }).first(); } - if (picker.options.showToday === true) { - if (prevMonth.isSame(moment(), 'day')) { + + if (parent.length === 0) { + throw new Error('datetimepicker component should be placed within a relative positioned container'); + } + + widget.css({ + top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(), + bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto', + left: horizontal === 'left' ? parent.css('padding-left') : 'auto', + right: horizontal === 'left' ? 'auto' : parent.width() - element.outerWidth() + }); + }, + + notifyEvent = function (e) { + if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) { + return; + } + element.trigger(e); + }, + + showMode = function (dir) { + if (!widget) { + return; + } + if (dir) { + currentViewMode = Math.max(minViewModeNumber, Math.min(2, currentViewMode + dir)); + } + widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show(); + }, + + fillDow = function () { + var row = $(''), + currentDate = viewDate.clone().startOf('w'); + + if (options.calendarWeeks === true) { + row.append($(''); + if (options.calendarWeeks) { + row.append(''); + } + html.push(row); + } + clsName = ''; + if (currentDate.isBefore(viewDate, 'M')) { + clsName += ' old'; + } + if (currentDate.isAfter(viewDate, 'M')) { + clsName += ' new'; + } + if (currentDate.isSame(date, 'd') && !unset) { + clsName += ' active'; + } + if (!isValid(currentDate, 'd')) { + clsName += ' disabled'; + } + if (currentDate.isSame(moment(), 'd')) { clsName += ' today'; } - } - if (picker.options.daysOfWeekDisabled) { - for (i = 0; i < picker.options.daysOfWeekDisabled.length; i++) { - if (prevMonth.day() === picker.options.daysOfWeekDisabled[i]) { - clsName += ' disabled'; - break; - } + if (currentDate.day() === 0 || currentDate.day() === 6) { + clsName += ' weekend'; } + row.append(''); + currentDate.add(1, 'd'); } - row.append(''); - currentDate = prevMonth.date(); - prevMonth.add(1, 'd'); + daysView.find('tbody').empty().append(html); - if (currentDate === prevMonth.date()) { - prevMonth.add(1, 'd'); + updateMonths(); + + updateYears(); + }, + + fillHours = function () { + var table = widget.find('.timepicker-hours table'), + currentHour = viewDate.clone().startOf('d'), + html = [], + row = $(''); + + if (viewDate.hour() > 11 && !use24Hours) { + currentHour.hour(12); } - } - picker.widget.find('.datepicker-days tbody').empty().append(html); - currentYear = picker.date.year(); - months = picker.widget.find('.datepicker-months').find('th:eq(1)').text(year).end().find('span').removeClass('active'); - if (currentYear === year) { - months.eq(picker.date.month()).addClass('active'); - } - if (year - 1 < startYear) { - picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled'); - } - if (year + 1 > endYear) { - picker.widget.find('.datepicker-months th:eq(2)').addClass('disabled'); - } - for (i = 0; i < 12; i++) { - if ((year === startYear && startMonth > i) || (year < startYear)) { - $(months[i]).addClass('disabled'); - } else if ((year === endYear && endMonth < i) || (year > endYear)) { - $(months[i]).addClass('disabled'); - } - } - - html = ''; - year = parseInt(year / 10, 10) * 10; - yearCont = picker.widget.find('.datepicker-years').find( - 'th:eq(1)').text(year + '-' + (year + 9)).parents('table').find('td'); - picker.widget.find('.datepicker-years').find('th').removeClass('disabled'); - if (startYear > year) { - picker.widget.find('.datepicker-years').find('th:eq(0)').addClass('disabled'); - } - if (endYear < year + 9) { - picker.widget.find('.datepicker-years').find('th:eq(2)').addClass('disabled'); - } - year -= 1; - for (i = -1; i < 11; i++) { - html += '' + year + ''; - year += 1; - } - yearCont.html(html); - }, - - fillHours = function () { - moment.locale(picker.options.language); - var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j; - table.parent().hide(); - if (picker.use24hours) { - current = 0; - for (i = 0; i < 6; i += 1) { - html += ''; - for (j = 0; j < 4; j += 1) { - html += ''; - current++; + while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) { + if (currentHour.hour() % 4 === 0) { + row = $(''); + html.push(row); } - html += ''; + row.append(''); + currentHour.add(1, 'h'); } - } - else { - current = 1; - for (i = 0; i < 3; i += 1) { - html += ''; - for (j = 0; j < 4; j += 1) { - html += ''; - current++; + table.empty().append(html); + }, + + fillMinutes = function () { + var table = widget.find('.timepicker-minutes table'), + currentMinute = viewDate.clone().startOf('h'), + html = [], + row = $(''), + step = options.stepping === 1 ? 5 : options.stepping; + + while (viewDate.isSame(currentMinute, 'h')) { + if (currentMinute.minute() % (step * 4) === 0) { + row = $(''); + html.push(row); } - html += ''; + row.append(''); + currentMinute.add(step, 'm'); } - } - table.html(html); - }, + table.empty().append(html); + }, - fillMinutes = function () { - var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping; - table.parent().hide(); - if (step === 1) { - step = 5; - } - for (i = 0; i < Math.ceil(60 / step / 4) ; i++) { - html += ''; - for (j = 0; j < 4; j += 1) { - if (current < 60) { - html += ''; - current += step; - } else { - html += ''; + fillSeconds = function () { + var table = widget.find('.timepicker-seconds table'), + currentSecond = viewDate.clone().startOf('m'), + html = [], + row = $(''); + + while (viewDate.isSame(currentSecond, 'm')) { + if (currentSecond.second() % 20 === 0) { + row = $(''); + html.push(row); } + row.append(''); + currentSecond.add(5, 's'); } - html += ''; - } - table.html(html); - }, - fillSeconds = function () { - var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j; - table.parent().hide(); - for (i = 0; i < 3; i++) { - html += ''; - for (j = 0; j < 4; j += 1) { - html += ''; - current += 5; + table.empty().append(html); + }, + + fillTime = function () { + var timeComponents = widget.find('.timepicker span[data-time-component]'); + if (!use24Hours) { + widget.find('.timepicker [data-action=togglePeriod]').text(date.format('A')); } - html += ''; - } - table.html(html); - }, + timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh')); + timeComponents.filter('[data-time-component=minutes]').text(date.format('mm')); + timeComponents.filter('[data-time-component=seconds]').text(date.format('ss')); - fillTime = function () { - if (!picker.date) { - return; - } - var timeComponents = picker.widget.find('.timepicker span[data-time-component]'), - hour = picker.date.hours(), - period = picker.date.format('A'); - if (!picker.use24hours) { - if (hour === 0) { - hour = 12; - } else if (hour !== 12) { - hour = hour % 12; + fillHours(); + fillMinutes(); + fillSeconds(); + }, + + update = function () { + if (!widget) { + return; } - picker.widget.find('.timepicker [data-action=togglePeriod]').text(period); - } - timeComponents.filter('[data-time-component=hours]').text(padLeft(hour)); - timeComponents.filter('[data-time-component=minutes]').text(padLeft(picker.date.minutes())); - timeComponents.filter('[data-time-component=seconds]').text(padLeft(picker.date.second())); - }, + fillDate(); + fillTime(); + }, - click = function (e) { - e.stopPropagation(); - e.preventDefault(); - picker.unset = false; - var target = $(e.target).closest('span, td, th'), month, year, step, day, oldDate = moment(picker.date); - if (target.length === 1) { - if (!target.is('.disabled')) { - switch (target[0].nodeName.toLowerCase()) { - case 'th': - switch (target[0].className) { - case 'picker-switch': - showMode(1); - break; - case 'prev': - case 'next': - step = dpGlobal.modes[picker.viewMode].navStep; - if (target[0].className === 'prev') { - step = step * -1; - } - picker.viewDate.add(step, dpGlobal.modes[picker.viewMode].navFnc); - fillDate(); - break; - } - break; - case 'span': - if (target.is('.month')) { - month = target.parent().find('span').index(target); - picker.viewDate.month(month); - } else { - year = parseInt(target.text(), 10) || 0; - picker.viewDate.year(year); - } - if (picker.viewMode === picker.minViewMode) { - picker.date = moment({ - y: picker.viewDate.year(), - M: picker.viewDate.month(), - d: picker.viewDate.date(), - h: picker.date.hours(), - m: picker.date.minutes(), - s: picker.date.seconds() - }); - set(); - notifyChange(oldDate, e.type); - } - showMode(-1); - fillDate(); - break; - case 'td': - if (target.is('.day')) { - day = parseInt(target.text(), 10) || 1; - month = picker.viewDate.month(); - year = picker.viewDate.year(); - if (target.is('.old')) { - if (month === 0) { - month = 11; - year -= 1; - } else { - month -= 1; - } - } else if (target.is('.new')) { - if (month === 11) { - month = 0; - year += 1; - } else { - month += 1; - } - } - picker.date = moment({ - y: year, - M: month, - d: day, - h: picker.date.hours(), - m: picker.date.minutes(), - s: picker.date.seconds() - } - ); - picker.viewDate = moment({ - y: year, M: month, d: Math.min(28, day) - }); - fillDate(); - set(); - notifyChange(oldDate, e.type); - } - break; - } + setValue = function (targetMoment) { + var oldDate = unset ? null : date; + + // case of calling setValue(null or false) + if (!targetMoment) { + unset = true; + input.val(''); + element.data('date', ''); + notifyEvent({ + type: 'dp.change', + date: null, + oldDate: oldDate + }); + update(); + return; } - } - }, - actions = { - incrementHours: function () { - checkDate('add', 'hours', 1); - }, + targetMoment = targetMoment.clone().locale(options.locale); - incrementMinutes: function () { - checkDate('add', 'minutes', picker.options.minuteStepping); - }, + if (options.stepping !== 1) { + targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0); + } - incrementSeconds: function () { - checkDate('add', 'seconds', 1); - }, - - decrementHours: function () { - checkDate('subtract', 'hours', 1); - }, - - decrementMinutes: function () { - checkDate('subtract', 'minutes', picker.options.minuteStepping); - }, - - decrementSeconds: function () { - checkDate('subtract', 'seconds', 1); - }, - - togglePeriod: function () { - var hour = picker.date.hours(); - if (hour >= 12) { - hour -= 12; + if (isValid(targetMoment)) { + date = targetMoment; + viewDate = date.clone(); + input.val(date.format(actualFormat)); + element.data('date', date.format(actualFormat)); + update(); + unset = false; + notifyEvent({ + type: 'dp.change', + date: date.clone(), + oldDate: oldDate + }); } else { - hour += 12; + if (!options.keepInvalid) { + input.val(unset ? '' : date.format(actualFormat)); + } + notifyEvent({ + type: 'dp.error', + date: targetMoment + }); } - picker.date.hours(hour); }, - showPicker: function () { - picker.widget.find('.timepicker > div:not(.timepicker-picker)').hide(); - picker.widget.find('.timepicker .timepicker-picker').show(); + hide = function () { + var transitioning = false; + if (!widget) { + return picker; + } + // Ignore event if in the middle of a picker transition + widget.find('.collapse').each(function () { + var collapseData = $(this).data('collapse'); + if (collapseData && collapseData.transitioning) { + transitioning = true; + return false; + } + return true; + }); + if (transitioning) { + return picker; + } + if (component && component.hasClass('btn')) { + component.toggleClass('active'); + } + widget.hide(); + + $(window).off('resize', place); + widget.off('click', '[data-action]'); + widget.off('mousedown', false); + + widget.remove(); + widget = false; + + notifyEvent({ + type: 'dp.hide', + date: date.clone() + }); + return picker; }, - showHours: function () { - picker.widget.find('.timepicker .timepicker-picker').hide(); - picker.widget.find('.timepicker .timepicker-hours').show(); + clear = function () { + setValue(null); }, - showMinutes: function () { - picker.widget.find('.timepicker .timepicker-picker').hide(); - picker.widget.find('.timepicker .timepicker-minutes').show(); - }, + /******************************************************************************** + * + * Widget UI interaction functions + * + ********************************************************************************/ + actions = { + next: function () { + viewDate.add(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc); + fillDate(); + }, - showSeconds: function () { - picker.widget.find('.timepicker .timepicker-picker').hide(); - picker.widget.find('.timepicker .timepicker-seconds').show(); - }, + previous: function () { + viewDate.subtract(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc); + fillDate(); + }, - selectHour: function (e) { - var hour = parseInt($(e.target).text(), 10); - if (!picker.use24hours) { - if (picker.date.hours() >= 12) { - if (hour !== 12) { - hour += 12; + pickerSwitch: function () { + showMode(1); + }, + + selectMonth: function (e) { + var month = $(e.target).closest('tbody').find('span').index($(e.target)); + viewDate.month(month); + if (currentViewMode === minViewModeNumber) { + setValue(date.clone().year(viewDate.year()).month(viewDate.month())); + if (!options.inline) { + hide(); } } else { - if (hour === 12) { - hour = 0; - } + showMode(-1); + fillDate(); } - } - picker.date.hours(hour); - actions.showPicker.call(picker); - }, + }, - selectMinute: function (e) { - picker.date.minutes(parseInt($(e.target).text(), 10)); - actions.showPicker.call(picker); - }, + selectYear: function (e) { + var year = parseInt($(e.target).text(), 10) || 0; + viewDate.year(year); + if (currentViewMode === minViewModeNumber) { + setValue(date.clone().year(viewDate.year())); + if (!options.inline) { + hide(); + } + } else { + showMode(-1); + fillDate(); + } + }, - selectSecond: function (e) { - picker.date.seconds(parseInt($(e.target).text(), 10)); - actions.showPicker.call(picker); - } - }, + selectDay: function (e) { + var day = viewDate.clone(); + if ($(e.target).is('.old')) { + day.subtract(1, 'M'); + } + if ($(e.target).is('.new')) { + day.add(1, 'M'); + } + setValue(day.date(parseInt($(e.target).text(), 10))); + if (!hasTime() && !options.keepOpen && !options.inline) { + hide(); + } + }, - doAction = function (e) { - var oldDate = moment(picker.date), - action = $(e.currentTarget).data('action'), - rv = actions[action].apply(picker, arguments); - stopEvent(e); - if (!picker.date) { - picker.date = moment({y: 1970}); - } - set(); - fillTime(); - notifyChange(oldDate, e.type); - return rv; - }, + incrementHours: function () { + setValue(date.clone().add(1, 'h')); + }, - stopEvent = function (e) { - e.stopPropagation(); - e.preventDefault(); - }, + incrementMinutes: function () { + setValue(date.clone().add(options.stepping, 'm')); + }, - keydown = function (e) { - if (e.keyCode === 27) { // allow escape to hide picker - picker.hide(); - } - }, + incrementSeconds: function () { + setValue(date.clone().add(1, 's')); + }, - change = function (e) { - moment.locale(picker.options.language); - var input = $(e.target), oldDate = moment(picker.date), newDate = moment(input.val(), picker.format, picker.options.useStrict); - if (newDate.isValid() && !isInDisableDates(newDate) && isInEnableDates(newDate)) { - update(); - picker.setValue(newDate); - notifyChange(oldDate, e.type); - set(); - } - else { - picker.viewDate = oldDate; - picker.unset = true; - notifyChange(oldDate, e.type); - notifyError(newDate); - } - }, + decrementHours: function () { + setValue(date.clone().subtract(1, 'h')); + }, - showMode = function (dir) { - if (dir) { - picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir)); - } - picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show(); - }, + decrementMinutes: function () { + setValue(date.clone().subtract(options.stepping, 'm')); + }, - attachDatePickerEvents = function () { - var $this, $parent, expanded, closed, collapseData; - picker.widget.on('click', '.datepicker *', $.proxy(click, this)); // this handles date picker clicks - picker.widget.on('click', '[data-action]', $.proxy(doAction, this)); // this handles time picker clicks - picker.widget.on('mousedown', $.proxy(stopEvent, this)); - picker.element.on('keydown', $.proxy(keydown, this)); - if (picker.options.pickDate && picker.options.pickTime) { - picker.widget.on('click.togglePicker', '.accordion-toggle', function (e) { - e.stopPropagation(); - $this = $(this); - $parent = $this.closest('ul'); - expanded = $parent.find('.in'); - closed = $parent.find('.collapse:not(.in)'); + decrementSeconds: function () { + setValue(date.clone().subtract(1, 's')); + }, + + togglePeriod: function () { + setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h')); + }, + + togglePicker: function (e) { + var $this = $(e.target), + $parent = $this.closest('ul'), + expanded = $parent.find('.in'), + closed = $parent.find('.collapse:not(.in)'), + collapseData; if (expanded && expanded.length) { collapseData = expanded.data('collapse'); if (collapseData && collapseData.transitioning) { return; } - expanded.collapse('hide'); - closed.collapse('show'); - $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date); - if (picker.component) { - picker.component.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date); + if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it + expanded.collapse('hide'); + closed.collapse('show'); + } else { // otherwise just toggle in class on the two views + expanded.removeClass('in'); + closed.addClass('in'); + } + if ($this.is('span')) { + $this.toggleClass(options.icons.time + ' ' + options.icons.date); + } else { + $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); + } + + // NOTE: uncomment if toggled state will be restored in show() + //if (component) { + // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); + //} + } + }, + + showPicker: function () { + widget.find('.timepicker > div:not(.timepicker-picker)').hide(); + widget.find('.timepicker .timepicker-picker').show(); + }, + + showHours: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-hours').show(); + }, + + showMinutes: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-minutes').show(); + }, + + showSeconds: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-seconds').show(); + }, + + selectHour: function (e) { + var hour = parseInt($(e.target).text(), 10); + + if (!use24Hours) { + if (date.hours() >= 12) { + if (hour !== 12) { + hour += 12; + } + } else { + if (hour === 12) { + hour = 0; + } } } - }); - } - if (picker.isInput) { - picker.element.on({ - 'click': $.proxy(picker.show, this), - 'focus': $.proxy(picker.show, this), - 'change': $.proxy(change, this), - 'blur': $.proxy(picker.hide, this) - }); - } else { - picker.element.on({ - 'change': $.proxy(change, this) - }, 'input'); - if (picker.component) { - picker.component.on('click', $.proxy(picker.show, this)); - picker.component.on('mousedown', $.proxy(stopEvent, this)); - } else { - picker.element.on('click', $.proxy(picker.show, this)); + setValue(date.clone().hours(hour)); + actions.showPicker.call(picker); + }, + + selectMinute: function (e) { + setValue(date.clone().minutes(parseInt($(e.target).text(), 10))); + actions.showPicker.call(picker); + }, + + selectSecond: function (e) { + setValue(date.clone().seconds(parseInt($(e.target).text(), 10))); + actions.showPicker.call(picker); + }, + + clear: clear, + + today: function () { + setValue(moment()); + }, + + close: hide + }, + + doAction = function (e) { + if ($(e.currentTarget).is('.disabled')) { + return false; } - } - }, + actions[$(e.currentTarget).data('action')].apply(picker, arguments); + return false; + }, - attachDatePickerGlobalEvents = function () { - $(window).on( - 'resize.datetimepicker' + picker.id, $.proxy(place, this)); - if (!picker.isInput) { - $(document).on( - 'mousedown.datetimepicker' + picker.id, $.proxy(picker.hide, this)); - } - }, + show = function () { + var currentMoment, + useCurrentGranularity = { + 'year': function (m) { + return m.month(0).date(1).hours(0).seconds(0).minutes(0); + }, + 'month': function (m) { + return m.date(1).hours(0).seconds(0).minutes(0); + }, + 'day': function (m) { + return m.hours(0).seconds(0).minutes(0); + }, + 'hour': function (m) { + return m.seconds(0).minutes(0); + }, + 'minute': function (m) { + return m.seconds(0); + } + }; - detachDatePickerEvents = function () { - picker.widget.off('click', '.datepicker *', picker.click); - picker.widget.off('click', '[data-action]'); - picker.widget.off('mousedown', picker.stopEvent); - if (picker.options.pickDate && picker.options.pickTime) { - picker.widget.off('click.togglePicker'); - } - if (picker.isInput) { - picker.element.off({ - 'focus': picker.show, + if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) { + return picker; + } + if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) { + currentMoment = moment(); + if (typeof options.useCurrent === 'string') { + currentMoment = useCurrentGranularity[options.useCurrent](currentMoment); + } + setValue(currentMoment); + } + + widget = getTemplate(); + + fillDow(); + fillMonths(); + + widget.find('.timepicker-hours').hide(); + widget.find('.timepicker-minutes').hide(); + widget.find('.timepicker-seconds').hide(); + + update(); + showMode(); + + $(window).on('resize', place); + widget.on('click', '[data-action]', doAction); // this handles clicks on the widget + widget.on('mousedown', false); + + if (component && component.hasClass('btn')) { + component.toggleClass('active'); + } + widget.show(); + place(); + + if (!input.is(':focus')) { + input.focus(); + } + + notifyEvent({ + type: 'dp.show' + }); + return picker; + }, + + toggle = function () { + return (widget ? hide() : show()); + }, + + parseInputDate = function (inputDate) { + if (moment.isMoment(inputDate) || inputDate instanceof Date) { + inputDate = moment(inputDate); + } else { + inputDate = moment(inputDate, parseFormats, options.useStrict); + } + inputDate.locale(options.locale); + return inputDate; + }, + + keydown = function (e) { + //if (e.keyCode === 27 && widget) { // allow escape to hide picker + // hide(); + // return false; + //} + //if (e.keyCode === 40 && !widget) { // allow down to show picker + // show(); + // e.preventDefault(); + //} + //return true; + + var handler = null, + index, + index2, + pressedKeys = [], + pressedModifiers = {}, + currentKey = e.which, + keyBindKeys, + allModifiersPressed, + pressed = 'p'; + + keyState[currentKey] = pressed; + + for (index in keyState) { + if (keyState.hasOwnProperty(index) && keyState[index] === pressed) { + pressedKeys.push(index); + if (parseInt(index, 10) !== currentKey) { + pressedModifiers[index] = true; + } + } + } + + for (index in options.keyBinds) { + if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') { + keyBindKeys = index.split(' '); + if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) { + allModifiersPressed = true; + for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) { + if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) { + allModifiersPressed = false; + break; + } + } + if (allModifiersPressed) { + handler = options.keyBinds[index]; + break; + } + } + } + } + + if (handler) { + handler.call(picker, widget); + e.stopPropagation(); + e.preventDefault(); + } + }, + + keyup = function (e) { + keyState[e.which] = 'r'; + e.stopPropagation(); + e.preventDefault(); + }, + + change = function (e) { + var val = $(e.target).val().trim(), + parsedDate = val ? parseInputDate(val) : null; + setValue(parsedDate); + e.stopImmediatePropagation(); + return false; + }, + + attachDatePickerElementEvents = function () { + input.on({ 'change': change, - 'click': picker.show, - 'blur' : picker.hide + 'blur': options.debug ? '' : hide, + 'keydown': keydown, + 'keyup': keyup }); - } else { - picker.element.off({ - 'change': change - }, 'input'); - if (picker.component) { - picker.component.off('click', picker.show); - picker.component.off('mousedown', picker.stopEvent); - } else { - picker.element.off('click', picker.show); + + if (element.is('input')) { + input.on({ + 'focus': show + }); + } else if (component) { + component.on('click', toggle); + component.on('mousedown', false); } - } - }, + }, - detachDatePickerGlobalEvents = function () { - $(window).off('resize.datetimepicker' + picker.id); - if (!picker.isInput) { - $(document).off('mousedown.datetimepicker' + picker.id); - } - }, + detachDatePickerElementEvents = function () { + input.off({ + 'change': change, + 'blur': hide, + 'keydown': keydown, + 'keyup': keyup + }); - isInFixed = function () { - if (picker.element) { - var parents = picker.element.parents(), inFixed = false, i; - for (i = 0; i < parents.length; i++) { - if ($(parents[i]).css('position') === 'fixed') { - inFixed = true; - break; + if (element.is('input')) { + input.off({ + 'focus': show + }); + } else if (component) { + component.off('click', toggle); + component.off('mousedown', false); + } + }, + + indexGivenDates = function (givenDatesArray) { + // Store given enabledDates and disabledDates as keys. + // This way we can check their existence in O(1) time instead of looping through whole array. + // (for example: options.enabledDates['2014-02-27'] === true) + var givenDatesIndexed = {}; + $.each(givenDatesArray, function () { + var dDate = parseInputDate(this); + if (dDate.isValid()) { + givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; } + }); + return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false; + }, + + initFormatting = function () { + var format = options.format || 'L LT'; + + actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) { + var newinput = date.localeData().longDateFormat(formatInput) || formatInput; + return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740 + return date.localeData().longDateFormat(formatInput2) || formatInput2; + }); + }); + + + parseFormats = options.extraFormats ? options.extraFormats.slice() : []; + if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) { + parseFormats.push(actualFormat); } - return inFixed; - } else { - return false; - } - }, - set = function () { - moment.locale(picker.options.language); - var formatted = ''; - if (!picker.unset) { - formatted = moment(picker.date).format(picker.format); - } - getPickerInput().val(formatted); - picker.element.data('date', formatted); - if (!picker.options.pickTime) { - picker.hide(); - } - }, + use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.indexOf('h') < 1); - checkDate = function (direction, unit, amount) { - moment.locale(picker.options.language); - var newDate; - if (direction === 'add') { - newDate = moment(picker.date); - if (newDate.hours() === 23) { - newDate.add(amount, unit); + if (isEnabled('y')) { + minViewModeNumber = 2; } - newDate.add(amount, unit); - } - else { - newDate = moment(picker.date).subtract(amount, unit); - } - if (isInDisableDates(moment(newDate.subtract(amount, unit))) || isInDisableDates(newDate)) { - notifyError(newDate.format(picker.format)); - return; - } - - if (direction === 'add') { - picker.date.add(amount, unit); - } - else { - picker.date.subtract(amount, unit); - } - picker.unset = false; - }, - - isInDisableDates = function (date, timeUnit) { - moment.locale(picker.options.language); - var maxDate = moment(picker.options.maxDate, picker.format, picker.options.useStrict), - minDate = moment(picker.options.minDate, picker.format, picker.options.useStrict); - - if (timeUnit) { - maxDate = maxDate.endOf(timeUnit); - minDate = minDate.startOf(timeUnit); - } - - if (date.isAfter(maxDate) || date.isBefore(minDate)) { - return true; - } - if (picker.options.disabledDates === false) { - return false; - } - return picker.options.disabledDates[date.format('YYYY-MM-DD')] === true; - }, - isInEnableDates = function (date) { - moment.locale(picker.options.language); - if (picker.options.enabledDates === false) { - return true; - } - return picker.options.enabledDates[date.format('YYYY-MM-DD')] === true; - }, - - indexGivenDates = function (givenDatesArray) { - // Store given enabledDates and disabledDates as keys. - // This way we can check their existence in O(1) time instead of looping through whole array. - // (for example: picker.options.enabledDates['2014-02-27'] === true) - var givenDatesIndexed = {}, givenDatesCount = 0, i; - for (i = 0; i < givenDatesArray.length; i++) { - if (moment.isMoment(givenDatesArray[i]) || givenDatesArray[i] instanceof Date) { - dDate = moment(givenDatesArray[i]); - } else { - dDate = moment(givenDatesArray[i], picker.format, picker.options.useStrict); + if (isEnabled('M')) { + minViewModeNumber = 1; } - if (dDate.isValid()) { - givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; - givenDatesCount++; + if (isEnabled('d')) { + minViewModeNumber = 0; } - } - if (givenDatesCount > 0) { - return givenDatesIndexed; - } - return false; - }, - padLeft = function (string) { - string = string.toString(); - if (string.length >= 2) { - return string; - } - return '0' + string; - }, + currentViewMode = Math.max(minViewModeNumber, currentViewMode); - getTemplate = function () { - var - headTemplate = - '' + - '' + - '' + - '' + - '', - contTemplate = - '', - template = '
' + - '
#' + weekdaysMin[i] + '' + weekdaysMin[0] + '' + weekdaysMin[i] + '
' + prevMonth.week() + '
').addClass('cw').text('#')); + } + + while (currentDate.isBefore(viewDate.clone().endOf('w'))) { + row.append($('').addClass('dow').text(currentDate.format('dd'))); + currentDate.add(1, 'd'); + } + widget.find('.datepicker-days thead').append(row); + }, + + isInDisabledDates = function (testDate) { + return options.disabledDates[testDate.format('YYYY-MM-DD')] === true; + }, + + isInEnabledDates = function (testDate) { + return options.enabledDates[testDate.format('YYYY-MM-DD')] === true; + }, + + isValid = function (targetMoment, granularity) { + if (!targetMoment.isValid()) { + return false; + } + if (options.disabledDates && isInDisabledDates(targetMoment) && granularity !== 'M') { + return false; + } + if (options.enabledDates && !isInEnabledDates(targetMoment) && granularity !== 'M') { + return false; + } + if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) { + return false; + } + if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) { + return false; + } + if (granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { //widget && widget.find('.datepicker-days').length > 0 + return false; + } + return true; + }, + + fillMonths = function () { + var spans = [], + monthsShort = viewDate.clone().startOf('y').hour(12); // hour is changed to avoid DST issues in some browsers + while (monthsShort.isSame(viewDate, 'y')) { + spans.push($('').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM'))); + monthsShort.add(1, 'M'); + } + widget.find('.datepicker-months td').empty().append(spans); + }, + + updateMonths = function () { + var monthsView = widget.find('.datepicker-months'), + monthsViewHeader = monthsView.find('th'), + months = monthsView.find('tbody').find('span'); + + monthsView.find('.disabled').removeClass('disabled'); + + if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) { + monthsViewHeader.eq(0).addClass('disabled'); + } + + monthsViewHeader.eq(1).text(viewDate.year()); + + if (!isValid(viewDate.clone().add(1, 'y'), 'y')) { + monthsViewHeader.eq(2).addClass('disabled'); + } + + months.removeClass('active'); + if (date.isSame(viewDate, 'y')) { + months.eq(date.month()).addClass('active'); + } + + months.each(function (index) { + if (!isValid(viewDate.clone().month(index), 'M')) { + $(this).addClass('disabled'); + } + }); + }, + + updateYears = function () { + var yearsView = widget.find('.datepicker-years'), + yearsViewHeader = yearsView.find('th'), + startYear = viewDate.clone().subtract(5, 'y'), + endYear = viewDate.clone().add(6, 'y'), + html = ''; + + yearsView.find('.disabled').removeClass('disabled'); + + if (options.minDate && options.minDate.isAfter(startYear, 'y')) { + yearsViewHeader.eq(0).addClass('disabled'); + } + + yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year()); + + if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) { + yearsViewHeader.eq(2).addClass('disabled'); + } + + while (!startYear.isAfter(endYear, 'y')) { + html += '' + startYear.year() + ''; + startYear.add(1, 'y'); + } + + yearsView.find('td').html(html); + }, + + fillDate = function () { + var daysView = widget.find('.datepicker-days'), + daysViewHeader = daysView.find('th'), + currentDate, + html = [], + row, + clsName; + + if (!hasDate()) { + return; + } + + daysView.find('.disabled').removeClass('disabled'); + daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat)); + + if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) { + daysViewHeader.eq(0).addClass('disabled'); + } + if (!isValid(viewDate.clone().add(1, 'M'), 'M')) { + daysViewHeader.eq(2).addClass('disabled'); + } + + currentDate = viewDate.clone().startOf('M').startOf('week'); + + while (!viewDate.clone().endOf('M').endOf('w').isBefore(currentDate, 'd')) { + if (currentDate.weekday() === 0) { + row = $('
' + currentDate.week() + '' + currentDate.date() + '' + prevMonth.date() + '
' + padLeft(current.toString()) + '
' + currentHour.format(use24Hours ? 'HH' : 'hh') + '
' + padLeft(current.toString()) + '
' + currentMinute.format('mm') + '
' + padLeft(current.toString()) + '
' + currentSecond.format('ss') + '
' + padLeft(current.toString()) + '
' + headTemplate + '
' + - '' + - '
' + - '' + headTemplate + contTemplate + '
' + - '
' + - '
' + - '' + headTemplate + contTemplate + '
' + - '
', - ret = ''; - if (picker.options.pickDate && picker.options.pickTime) { - ret = '
'; - return ret; - } - if (picker.options.pickTime) { - return ( - '' - ); - } - return ( - '' - ); - }, - - dpGlobal = { - modes: [ - { - clsName: 'days', - navFnc: 'month', - navStep: 1 - }, - { - clsName: 'months', - navFnc: 'year', - navStep: 1 - }, - { - clsName: 'years', - navFnc: 'year', - navStep: 10 - } - ] - }, - - tpGlobal = { - hourTemplate: '', - minuteTemplate: '', - secondTemplate: '' - }; - - tpGlobal.getTemplate = function () { - return ( - '
' + - '' + - '' + - '' + - '' + - '' + - (picker.options.useSeconds ? - '' : '') + - (picker.use24hours ? '' : '') + - '' + - '' + - ' ' + - '' + - ' ' + - (picker.options.useSeconds ? - '' : '') + - (picker.use24hours ? '' : '' + - '') + - '' + - '' + - '' + - '' + - '' + - (picker.options.useSeconds ? - '' : '') + - (picker.use24hours ? '' : '') + - '' + - '
' + (picker.options.useMinutes ? '' : '') + '
' + tpGlobal.hourTemplate + ':' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '00') + ':' + tpGlobal.secondTemplate + '
' + (picker.options.useMinutes ? '' : '') + '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - (picker.options.useSeconds ? - '
' : '') - ); - }; + }; + /******************************************************************************** + * + * Public API functions + * ===================== + * + * Important: Do not expose direct references to private objects or the options + * object to the outer world. Always return a clone when returning values or make + * a clone when setting a private variable. + * + ********************************************************************************/ picker.destroy = function () { - detachDatePickerEvents(); - detachDatePickerGlobalEvents(); - picker.widget.remove(); - picker.element.removeData('DateTimePicker'); - if (picker.component) { - picker.component.removeData('DateTimePicker'); - } + hide(); + detachDatePickerElementEvents(); + element.removeData('DateTimePicker'); + element.removeData('date'); }; - picker.show = function (e) { - if (getPickerInput().prop('disabled')) { - return; - } - if (picker.options.useCurrent) { - if (getPickerInput().val() === '') { - if (picker.options.minuteStepping !== 1) { - var mDate = moment(), - rInterval = picker.options.minuteStepping; - mDate.minutes((Math.round(mDate.minutes() / rInterval) * rInterval) % 60).seconds(0); - picker.setValue(mDate.format(picker.format)); - } else { - picker.setValue(moment().format(picker.format)); - } - notifyChange('', e.type); - } - } - // if this is a click event on the input field and picker is already open don't hide it - if (e && e.type === 'click' && picker.isInput && picker.widget.hasClass('picker-open')) { - return; - } - if (picker.widget.hasClass('picker-open')) { - picker.widget.hide(); - picker.widget.removeClass('picker-open'); - } - else { - picker.widget.show(); - picker.widget.addClass('picker-open'); - } - picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight(); - place(); - picker.element.trigger({ - type: 'dp.show', - date: moment(picker.date) - }); - attachDatePickerGlobalEvents(); - if (e) { - stopEvent(e); - } - }; + picker.toggle = toggle; + + picker.show = show; + + picker.hide = hide; picker.disable = function () { - var input = getPickerInput(); - if (input.prop('disabled')) { - return; + hide(); + if (component && component.hasClass('btn')) { + component.addClass('disabled'); } input.prop('disabled', true); - detachDatePickerEvents(); + return picker; }; picker.enable = function () { - var input = getPickerInput(); - if (!input.prop('disabled')) { - return; + if (component && component.hasClass('btn')) { + component.removeClass('disabled'); } input.prop('disabled', false); - attachDatePickerEvents(); + return picker; }; - picker.hide = function () { - // Ignore event if in the middle of a picker transition - var collapse = picker.widget.find('.collapse'), i, collapseData; - for (i = 0; i < collapse.length; i++) { - collapseData = collapse.eq(i).data('collapse'); - if (collapseData && collapseData.transitioning) { - return; + picker.ignoreReadonly = function (ignoreReadonly) { + if (arguments.length === 0) { + return options.ignoreReadonly; + } + if (typeof ignoreReadonly !== 'boolean') { + throw new TypeError('ignoreReadonly () expects a boolean parameter'); + } + options.ignoreReadonly = ignoreReadonly; + return picker; + }; + + picker.options = function (newOptions) { + if (arguments.length === 0) { + return $.extend(true, {}, options); + } + + if (!(newOptions instanceof Object)) { + throw new TypeError('options() options parameter should be an object'); + } + $.extend(true, options, newOptions); + $.each(options, function (key, value) { + if (picker[key] !== undefined) { + picker[key](value); + } else { + throw new TypeError('option ' + key + ' is not recognized!'); + } + }); + return picker; + }; + + picker.date = function (newDate) { + if (arguments.length === 0) { + if (unset) { + return null; + } + return date.clone(); + } + + if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { + throw new TypeError('date() parameter must be one of [null, string, moment or Date]'); + } + + setValue(newDate === null ? null : parseInputDate(newDate)); + return picker; + }; + + picker.format = function (newFormat) { + if (arguments.length === 0) { + return options.format; + } + + if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) { + throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat); + } + + options.format = newFormat; + if (actualFormat) { + initFormatting(); // reinit formatting + } + return picker; + }; + + picker.dayViewHeaderFormat = function (newFormat) { + if (arguments.length === 0) { + return options.dayViewHeaderFormat; + } + + if (typeof newFormat !== 'string') { + throw new TypeError('dayViewHeaderFormat() expects a string parameter'); + } + + options.dayViewHeaderFormat = newFormat; + return picker; + }; + + picker.extraFormats = function (formats) { + if (arguments.length === 0) { + return options.extraFormats; + } + + if (formats !== false && !(formats instanceof Array)) { + throw new TypeError('extraFormats() expects an array or false parameter'); + } + + options.extraFormats = formats; + if (parseFormats) { + initFormatting(); // reinit formatting + } + return picker; + }; + + picker.disabledDates = function (dates) { + if (arguments.length === 0) { + return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates); + } + + if (!dates) { + options.disabledDates = false; + update(); + return picker; + } + if (!(dates instanceof Array)) { + throw new TypeError('disabledDates() expects an array parameter'); + } + options.disabledDates = indexGivenDates(dates); + options.enabledDates = false; + update(); + return picker; + }; + + picker.enabledDates = function (dates) { + if (arguments.length === 0) { + return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates); + } + + if (!dates) { + options.enabledDates = false; + update(); + return picker; + } + if (!(dates instanceof Array)) { + throw new TypeError('enabledDates() expects an array parameter'); + } + options.enabledDates = indexGivenDates(dates); + options.disabledDates = false; + update(); + return picker; + }; + + picker.daysOfWeekDisabled = function (daysOfWeekDisabled) { + if (arguments.length === 0) { + return options.daysOfWeekDisabled.splice(0); + } + + if (!(daysOfWeekDisabled instanceof Array)) { + throw new TypeError('daysOfWeekDisabled() expects an array parameter'); + } + options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) { + currentValue = parseInt(currentValue, 10); + if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) { + return previousValue; + } + if (previousValue.indexOf(currentValue) === -1) { + previousValue.push(currentValue); + } + return previousValue; + }, []).sort(); + update(); + return picker; + }; + + picker.maxDate = function (maxDate) { + if (arguments.length === 0) { + return options.maxDate ? options.maxDate.clone() : options.maxDate; + } + + if ((typeof maxDate === 'boolean') && maxDate === false) { + options.maxDate = false; + update(); + return picker; + } + + if (typeof maxDate === 'string') { + if (maxDate === 'now' || maxDate === 'moment') { + maxDate = moment(); } } - picker.widget.hide(); - picker.widget.removeClass('picker-open'); - picker.viewMode = picker.startViewMode; + + var parsedDate = parseInputDate(maxDate); + + if (!parsedDate.isValid()) { + throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate); + } + if (options.minDate && parsedDate.isBefore(options.minDate)) { + throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat)); + } + options.maxDate = parsedDate; + if (options.maxDate.isBefore(maxDate)) { + setValue(options.maxDate); + } + if (viewDate.isAfter(parsedDate)) { + viewDate = parsedDate.clone(); + } + update(); + return picker; + }; + + picker.minDate = function (minDate) { + if (arguments.length === 0) { + return options.minDate ? options.minDate.clone() : options.minDate; + } + + if ((typeof minDate === 'boolean') && minDate === false) { + options.minDate = false; + update(); + return picker; + } + + if (typeof minDate === 'string') { + if (minDate === 'now' || minDate === 'moment') { + minDate = moment(); + } + } + + var parsedDate = parseInputDate(minDate); + + if (!parsedDate.isValid()) { + throw new TypeError('minDate() Could not parse date parameter: ' + minDate); + } + if (options.maxDate && parsedDate.isAfter(options.maxDate)) { + throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat)); + } + options.minDate = parsedDate; + if (options.minDate.isAfter(minDate)) { + setValue(options.minDate); + } + if (viewDate.isBefore(parsedDate)) { + viewDate = parsedDate.clone(); + } + update(); + return picker; + }; + + picker.defaultDate = function (defaultDate) { + if (arguments.length === 0) { + return options.defaultDate ? options.defaultDate.clone() : options.defaultDate; + } + if (!defaultDate) { + options.defaultDate = false; + return picker; + } + + if (typeof defaultDate === 'string') { + if (defaultDate === 'now' || defaultDate === 'moment') { + defaultDate = moment(); + } + } + + var parsedDate = parseInputDate(defaultDate); + if (!parsedDate.isValid()) { + throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate); + } + if (!isValid(parsedDate)) { + throw new TypeError('defaultDate() date passed is invalid according to component setup validations'); + } + + options.defaultDate = parsedDate; + + if (options.defaultDate && input.val().trim() === '' && input.attr('placeholder') === undefined) { + setValue(options.defaultDate); + } + return picker; + }; + + picker.locale = function (locale) { + if (arguments.length === 0) { + return options.locale; + } + + if (!moment.localeData(locale)) { + throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!'); + } + + options.locale = locale; + date.locale(options.locale); + viewDate.locale(options.locale); + + if (actualFormat) { + initFormatting(); // reinit formatting + } + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.stepping = function (stepping) { + if (arguments.length === 0) { + return options.stepping; + } + + stepping = parseInt(stepping, 10); + if (isNaN(stepping) || stepping < 1) { + stepping = 1; + } + options.stepping = stepping; + return picker; + }; + + picker.useCurrent = function (useCurrent) { + var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; + if (arguments.length === 0) { + return options.useCurrent; + } + + if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) { + throw new TypeError('useCurrent() expects a boolean or string parameter'); + } + if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) { + throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', ')); + } + options.useCurrent = useCurrent; + return picker; + }; + + picker.collapse = function (collapse) { + if (arguments.length === 0) { + return options.collapse; + } + + if (typeof collapse !== 'boolean') { + throw new TypeError('collapse() expects a boolean parameter'); + } + if (options.collapse === collapse) { + return picker; + } + options.collapse = collapse; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.icons = function (icons) { + if (arguments.length === 0) { + return $.extend({}, options.icons); + } + + if (!(icons instanceof Object)) { + throw new TypeError('icons() expects parameter to be an Object'); + } + $.extend(options.icons, icons); + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.useStrict = function (useStrict) { + if (arguments.length === 0) { + return options.useStrict; + } + + if (typeof useStrict !== 'boolean') { + throw new TypeError('useStrict() expects a boolean parameter'); + } + options.useStrict = useStrict; + return picker; + }; + + picker.sideBySide = function (sideBySide) { + if (arguments.length === 0) { + return options.sideBySide; + } + + if (typeof sideBySide !== 'boolean') { + throw new TypeError('sideBySide() expects a boolean parameter'); + } + options.sideBySide = sideBySide; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.viewMode = function (viewMode) { + if (arguments.length === 0) { + return options.viewMode; + } + + if (typeof viewMode !== 'string') { + throw new TypeError('viewMode() expects a string parameter'); + } + + if (viewModes.indexOf(viewMode) === -1) { + throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value'); + } + + options.viewMode = viewMode; + currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber); + showMode(); - picker.element.trigger({ - type: 'dp.hide', - date: moment(picker.date) - }); - detachDatePickerGlobalEvents(); + return picker; }; - picker.setValue = function (newDate) { - moment.locale(picker.options.language); - if (!newDate) { - picker.unset = true; - set(); + picker.toolbarPlacement = function (toolbarPlacement) { + if (arguments.length === 0) { + return options.toolbarPlacement; + } + + if (typeof toolbarPlacement !== 'string') { + throw new TypeError('toolbarPlacement() expects a string parameter'); + } + if (toolbarPlacements.indexOf(toolbarPlacement) === -1) { + throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value'); + } + options.toolbarPlacement = toolbarPlacement; + + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.widgetPositioning = function (widgetPositioning) { + if (arguments.length === 0) { + return $.extend({}, options.widgetPositioning); + } + + if (({}).toString.call(widgetPositioning) !== '[object Object]') { + throw new TypeError('widgetPositioning() expects an object variable'); + } + if (widgetPositioning.horizontal) { + if (typeof widgetPositioning.horizontal !== 'string') { + throw new TypeError('widgetPositioning() horizontal variable must be a string'); + } + widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase(); + if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) { + throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')'); + } + options.widgetPositioning.horizontal = widgetPositioning.horizontal; + } + if (widgetPositioning.vertical) { + if (typeof widgetPositioning.vertical !== 'string') { + throw new TypeError('widgetPositioning() vertical variable must be a string'); + } + widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase(); + if (verticalModes.indexOf(widgetPositioning.vertical) === -1) { + throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')'); + } + options.widgetPositioning.vertical = widgetPositioning.vertical; + } + update(); + return picker; + }; + + picker.calendarWeeks = function (calendarWeeks) { + if (arguments.length === 0) { + return options.calendarWeeks; + } + + if (typeof calendarWeeks !== 'boolean') { + throw new TypeError('calendarWeeks() expects parameter to be a boolean value'); + } + + options.calendarWeeks = calendarWeeks; + update(); + return picker; + }; + + picker.showTodayButton = function (showTodayButton) { + if (arguments.length === 0) { + return options.showTodayButton; + } + + if (typeof showTodayButton !== 'boolean') { + throw new TypeError('showTodayButton() expects a boolean parameter'); + } + + options.showTodayButton = showTodayButton; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.showClear = function (showClear) { + if (arguments.length === 0) { + return options.showClear; + } + + if (typeof showClear !== 'boolean') { + throw new TypeError('showClear() expects a boolean parameter'); + } + + options.showClear = showClear; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.widgetParent = function (widgetParent) { + if (arguments.length === 0) { + return options.widgetParent; + } + + if (typeof widgetParent === 'string') { + widgetParent = $(widgetParent); + } + + if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) { + throw new TypeError('widgetParent() expects a string or a jQuery object parameter'); + } + + options.widgetParent = widgetParent; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.keepOpen = function (keepOpen) { + if (arguments.length === 0) { + return options.keepOpen; + } + + if (typeof keepOpen !== 'boolean') { + throw new TypeError('keepOpen() expects a boolean parameter'); + } + + options.keepOpen = keepOpen; + return picker; + }; + + picker.inline = function (inline) { + if (arguments.length === 0) { + return options.inline; + } + + if (typeof inline !== 'boolean') { + throw new TypeError('inline() expects a boolean parameter'); + } + + options.inline = inline; + return picker; + }; + + picker.clear = function () { + clear(); + return picker; + }; + + picker.keyBinds = function (keyBinds) { + options.keyBinds = keyBinds; + return picker; + }; + + picker.debug = function (debug) { + if (typeof debug !== 'boolean') { + throw new TypeError('debug() expects a boolean parameter'); + } + + options.debug = debug; + return picker; + }; + + picker.showClose = function (showClose) { + if (arguments.length === 0) { + return options.showClose; + } + + if (typeof showClose !== 'boolean') { + throw new TypeError('showClose() expects a boolean parameter'); + } + + options.showClose = showClose; + return picker; + }; + + picker.keepInvalid = function (keepInvalid) { + if (arguments.length === 0) { + return options.keepInvalid; + } + + if (typeof keepInvalid !== 'boolean') { + throw new TypeError('keepInvalid() expects a boolean parameter'); + } + options.keepInvalid = keepInvalid; + return picker; + }; + + picker.datepickerInput = function (datepickerInput) { + if (arguments.length === 0) { + return options.datepickerInput; + } + + if (typeof datepickerInput !== 'string') { + throw new TypeError('datepickerInput() expects a string parameter'); + } + + options.datepickerInput = datepickerInput; + return picker; + }; + + // initializing element and component attributes + if (element.is('input')) { + input = element; + } else { + input = element.find(options.datepickerInput); + if (input.size() === 0) { + input = element.find('input'); + } else if (!input.is('input')) { + throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element'); + } + } + + if (element.hasClass('input-group')) { + // in case there is more then one 'input-group-addon' Issue #48 + if (element.find('.datepickerbutton').size() === 0) { + component = element.find('[class^="input-group-"]'); } else { - picker.unset = false; + component = element.find('.datepickerbutton'); } - if (!moment.isMoment(newDate)) { - newDate = (newDate instanceof Date) ? moment(newDate) : moment(newDate, picker.format, picker.options.useStrict); - } else { - newDate = newDate.locale(picker.options.language); - } - if (newDate.isValid()) { - picker.date = newDate; - set(); - picker.viewDate = moment({y: picker.date.year(), M: picker.date.month()}); - fillDate(); - fillTime(); - } - else { - notifyError(newDate); - } - }; + } - picker.getDate = function () { - if (picker.unset) { - return null; - } - return moment(picker.date); - }; + if (!options.inline && !input.is('input')) { + throw new Error('Could not initialize DateTimePicker without an input element'); + } - picker.setDate = function (date) { - var oldDate = moment(picker.date); - if (!date) { - picker.setValue(null); - } else { - picker.setValue(date); - } - notifyChange(oldDate, 'function'); - }; + $.extend(true, options, dataToOptions()); - picker.setDisabledDates = function (dates) { - picker.options.disabledDates = indexGivenDates(dates); - if (picker.viewDate) { - update(); - } - }; + picker.options(options); - picker.setEnabledDates = function (dates) { - picker.options.enabledDates = indexGivenDates(dates); - if (picker.viewDate) { - update(); - } - }; + initFormatting(); - picker.setMaxDate = function (date) { - if (date === undefined) { - return; - } - if (moment.isMoment(date) || date instanceof Date) { - picker.options.maxDate = moment(date); - } else { - picker.options.maxDate = moment(date, picker.format, picker.options.useStrict); - } - if (picker.viewDate) { - update(); - } - }; + attachDatePickerElementEvents(); - picker.setMinDate = function (date) { - if (date === undefined) { - return; - } - if (moment.isMoment(date) || date instanceof Date) { - picker.options.minDate = moment(date); - } else { - picker.options.minDate = moment(date, picker.format, picker.options.useStrict); - } - if (picker.viewDate) { - update(); - } - }; - - init(); + if (input.prop('disabled')) { + picker.disable(); + } + if (input.is('input') && input.val().trim().length !== 0) { + setValue(parseInputDate(input.val().trim())); + } + else if (options.defaultDate && input.attr('placeholder') === undefined) { + setValue(options.defaultDate); + } + if (options.inline) { + show(); + } + return picker; }; + /******************************************************************************** + * + * jQuery plugin constructor and defaults object + * + ********************************************************************************/ + $.fn.datetimepicker = function (options) { return this.each(function () { - var $this = $(this), - data = $this.data('DateTimePicker'); - if (!data) { - $this.data('DateTimePicker', new DateTimePicker(this, options)); + var $this = $(this); + if (!$this.data('DateTimePicker')) { + // create a private copy of the defaults object + options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); + $this.data('DateTimePicker', dateTimePicker($this, options)); } }); }; $.fn.datetimepicker.defaults = { format: false, - pickDate: true, - pickTime: true, - useMinutes: true, - useSeconds: false, + dayViewHeaderFormat: 'MMMM YYYY', + extraFormats: false, + stepping: 1, + minDate: false, + maxDate: false, useCurrent: true, - calendarWeeks: false, - minuteStepping: 1, - minDate: moment({y: 1900}), - maxDate: moment().add(100, 'y'), - showToday: true, collapse: true, - language: moment.locale(), - defaultDate: '', + locale: moment.locale(), + defaultDate: false, disabledDates: false, enabledDates: false, - icons: {}, + icons: { + time: 'glyphicon glyphicon-time', + date: 'glyphicon glyphicon-calendar', + up: 'glyphicon glyphicon-chevron-up', + down: 'glyphicon glyphicon-chevron-down', + previous: 'glyphicon glyphicon-chevron-left', + next: 'glyphicon glyphicon-chevron-right', + today: 'glyphicon glyphicon-screenshot', + clear: 'glyphicon glyphicon-trash', + close: 'glyphicon glyphicon-remove' + }, useStrict: false, - direction: 'auto', sideBySide: false, daysOfWeekDisabled: [], - widgetParent: false + calendarWeeks: false, + viewMode: 'days', + toolbarPlacement: 'default', + showTodayButton: false, + showClear: false, + showClose: false, + widgetPositioning: { + horizontal: 'auto', + vertical: 'auto' + }, + widgetParent: null, + ignoreReadonly: false, + keepOpen: false, + inline: false, + keepInvalid: false, + datepickerInput: '.datepickerinput', + keyBinds: { + up: function (widget) { + if (!widget) { + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(7, 'd')); + } else { + this.date(d.clone().add(1, 'm')); + } + }, + down: function (widget) { + if (!widget) { + this.show(); + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(7, 'd')); + } else { + this.date(d.clone().subtract(1, 'm')); + } + }, + 'control up': function (widget) { + if (!widget) { + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(1, 'y')); + } else { + this.date(d.clone().add(1, 'h')); + } + }, + 'control down': function (widget) { + if (!widget) { + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(1, 'y')); + } else { + this.date(d.clone().subtract(1, 'h')); + } + }, + left: function (widget) { + if (!widget) { + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(1, 'd')); + } + }, + right: function (widget) { + if (!widget) { + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(1, 'd')); + } + }, + pageUp: function (widget) { + if (!widget) { + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().subtract(1, 'M')); + } + }, + pageDown: function (widget) { + if (!widget) { + return; + } + var d = this.date() || moment(); + if (widget.find('.datepicker').is(':visible')) { + this.date(d.clone().add(1, 'M')); + } + }, + enter: function () { + this.hide(); + }, + escape: function () { + this.hide(); + }, + //tab: function (widget) { //this break the flow of the form. disabling for now + // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]'); + // if(toggle.length > 0) toggle.click(); + //}, + 'control space': function (widget) { + if (widget.find('.timepicker').is(':visible')) { + widget.find('.btn[data-action="togglePeriod"]').click(); + } + }, + t: function () { + this.date(moment()); + }, + 'delete': function () { + this.clear(); + } + }, + debug: false }; })); diff --git a/src/less/_bootstrap-datetimepicker.less b/src/less/_bootstrap-datetimepicker.less new file mode 100644 index 000000000..64d9a70e7 --- /dev/null +++ b/src/less/_bootstrap-datetimepicker.less @@ -0,0 +1,343 @@ +/*! + * Datetimepicker for Bootstrap 3 + * ! version : 4.7.14 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */ +@bs-datetimepicker-timepicker-font-size: 1.2em; +@bs-datetimepicker-active-bg: @btn-primary-bg; +@bs-datetimepicker-active-color: @btn-primary-color; +@bs-datetimepicker-border-radius: @border-radius-base; +@bs-datetimepicker-btn-hover-bg: @gray-lighter; +@bs-datetimepicker-disabled-color: @gray-light; +@bs-datetimepicker-alternate-color: @gray-light; +@bs-datetimepicker-secondary-border-color: #ccc; +@bs-datetimepicker-secondary-border-color-rgba: rgba(0, 0, 0, 0.2); +@bs-datetimepicker-primary-border-color: white; +@bs-datetimepicker-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + +.bootstrap-datetimepicker-widget { + list-style: none; + + &.dropdown-menu { + margin: 2px 0; + padding: 4px; + width: 19em; + + &.timepicker-sbs { + @media (min-width: @screen-sm-min) { + width: 38em; + } + + @media (min-width: @screen-md-min) { + width: 38em; + } + + @media (min-width: @screen-lg-min) { + width: 38em; + } + } + + &:before, &:after { + content: ''; + display: inline-block; + position: absolute; + } + + &.bottom { + &:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid @bs-datetimepicker-secondary-border-color; + border-bottom-color: @bs-datetimepicker-secondary-border-color-rgba; + top: -7px; + left: 7px; + } + + &:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid @bs-datetimepicker-primary-border-color; + top: -6px; + left: 8px; + } + } + + &.top { + &:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid @bs-datetimepicker-secondary-border-color; + border-top-color: @bs-datetimepicker-secondary-border-color-rgba; + bottom: -7px; + left: 6px; + } + + &:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid @bs-datetimepicker-primary-border-color; + bottom: -6px; + left: 7px; + } + } + + &.pull-right { + &:before { + left: auto; + right: 6px; + } + + &:after { + left: auto; + right: 7px; + } + } + } + + .list-unstyled { + margin: 0; + } + + a[data-action] { + padding: 6px 0; + } + + a[data-action]:active { + box-shadow: none; + } + + .timepicker-hour, .timepicker-minute, .timepicker-second { + width: 54px; + font-weight: bold; + font-size: @bs-datetimepicker-timepicker-font-size; + margin: 0; + } + + button[data-action] { + padding: 6px; + } + + .btn[data-action="incrementHours"]::after { + .sr-only(); + content: "Increment Hours"; + } + + .btn[data-action="incrementMinutes"]::after { + .sr-only(); + content: "Increment Minutes"; + } + + .btn[data-action="decrementHours"]::after { + .sr-only(); + content: "Decrement Hours"; + } + + .btn[data-action="decrementMinutes"]::after { + .sr-only(); + content: "Decrement Minutes"; + } + + .btn[data-action="showHours"]::after { + .sr-only(); + content: "Show Hours"; + } + + .btn[data-action="showMinutes"]::after { + .sr-only(); + content: "Show Minutes"; + } + + .btn[data-action="togglePeriod"]::after { + .sr-only(); + content: "Toggle AM/PM"; + } + + .btn[data-action="clear"]::after { + .sr-only(); + content: "Clear the picker"; + } + + .btn[data-action="today"]::after { + .sr-only(); + content: "Set the date to today"; + } + + .picker-switch { + text-align: center; + + &::after { + .sr-only(); + content: "Toggle Date and Time Screens"; + } + + td { + padding: 0; + margin: 0; + height: auto; + width: auto; + line-height: inherit; + + span { + line-height: 2.5; + height: 2.5em; + width: 100%; + } + } + } + + table { + width: 100%; + margin: 0; + + + & td, + & th { + text-align: center; + border-radius: @bs-datetimepicker-border-radius; + } + + & th { + height: 20px; + line-height: 20px; + width: 20px; + + &.picker-switch { + width: 145px; + } + + &.disabled, + &.disabled:hover { + background: none; + color: @bs-datetimepicker-disabled-color; + cursor: not-allowed; + } + + &.prev::after { + .sr-only(); + content: "Previous Month"; + } + + &.next::after { + .sr-only(); + content: "Next Month"; + } + } + + & thead tr:first-child th { + cursor: pointer; + + &:hover { + background: @bs-datetimepicker-btn-hover-bg; + } + } + + & td { + height: 54px; + line-height: 54px; + width: 54px; + + &.cw { + font-size: .8em; + height: 20px; + line-height: 20px; + color: @bs-datetimepicker-alternate-color; + } + + &.day { + height: 20px; + line-height: 20px; + width: 20px; + } + + &.day:hover, + &.hour:hover, + &.minute:hover, + &.second:hover { + background: @bs-datetimepicker-btn-hover-bg; + cursor: pointer; + } + + &.old, + &.new { + color: @bs-datetimepicker-alternate-color; + } + + &.today { + position: relative; + + &:before { + content: ''; + display: inline-block; + border: 0 0 7px 7px solid transparent; + border-bottom-color: @bs-datetimepicker-active-bg; + border-top-color: @bs-datetimepicker-secondary-border-color-rgba; + position: absolute; + bottom: 4px; + right: 4px; + } + } + + &.active, + &.active:hover { + background-color: @bs-datetimepicker-active-bg; + color: @bs-datetimepicker-active-color; + text-shadow: @bs-datetimepicker-text-shadow; + } + + &.active.today:before { + border-bottom-color: #fff; + } + + &.disabled, + &.disabled:hover { + background: none; + color: @bs-datetimepicker-disabled-color; + cursor: not-allowed; + } + + span { + display: inline-block; + width: 54px; + height: 54px; + line-height: 54px; + margin: 2px 1.5px; + cursor: pointer; + border-radius: @bs-datetimepicker-border-radius; + + &:hover { + background: @bs-datetimepicker-btn-hover-bg; + } + + &.active { + background-color: @bs-datetimepicker-active-bg; + color: @bs-datetimepicker-active-color; + text-shadow: @bs-datetimepicker-text-shadow; + } + + &.old { + color: @bs-datetimepicker-alternate-color; + } + + &.disabled, + &.disabled:hover { + background: none; + color: @bs-datetimepicker-disabled-color; + cursor: not-allowed; + } + } + } + } + + &.usetwentyfour { + td.hour { + height: 27px; + line-height: 27px; + } + } +} + +.input-group.date { + & .input-group-addon { + cursor: pointer; + } +} diff --git a/src/less/bootstrap-datetimepicker-build.less b/src/less/bootstrap-datetimepicker-build.less index 4a1737015..76dd98a65 100644 --- a/src/less/bootstrap-datetimepicker-build.less +++ b/src/less/bootstrap-datetimepicker-build.less @@ -1,5 +1,17 @@ -// Import boostrap variables including default color palette and fonts +// Import bootstrap variables including default color palette and fonts @import "../../node_modules/bootstrap/less/variables.less"; // Import datepicker component -@import "bootstrap-datetimepicker.less"; +@import "_bootstrap-datetimepicker.less"; + + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0,0,0,0); + border: 0; +} diff --git a/src/less/bootstrap-datetimepicker.less b/src/less/bootstrap-datetimepicker.less deleted file mode 100755 index 14eb9da54..000000000 --- a/src/less/bootstrap-datetimepicker.less +++ /dev/null @@ -1,294 +0,0 @@ -/*! - * Datetimepicker for Bootstrap v3 -//! version : 3.1.3 - * https://github.com/Eonasdan/bootstrap-datetimepicker/ - */ -.bootstrap-datetimepicker-widget { - top: 0; - left: 0; - width: 250px; - padding: 4px; - margin-top: 1px; - z-index: 99999 !important; - border-radius: @border-radius-base; - - &.timepicker-sbs { - width: 600px; - } - - &.bottom { - &:before { - content: ''; - display: inline-block; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-bottom-color: rgba(0,0,0,.2); - position: absolute; - top: -7px; - left: 7px; - } - - &:after { - content: ''; - display: inline-block; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid white; - position: absolute; - top: -6px; - left: 8px; - } - } - - &.top { - &:before { - content: ''; - display: inline-block; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-top: 7px solid #ccc; - border-top-color: rgba(0,0,0,.2); - position: absolute; - bottom: -7px; - left: 6px; - } - - &:after { - content: ''; - display: inline-block; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-top: 6px solid white; - position: absolute; - bottom: -6px; - left: 7px; - } - } - - & .dow { - width: 14.2857%; - } - - &.pull-right { - &:before { - left: auto; - right: 6px; - } - - &:after { - left: auto; - right: 7px; - } - } - - >ul { - list-style-type: none; - margin: 0; - } - - a[data-action] { - padding: 6px 0; - } - - a[data-action]:active { - box-shadow: none; - } - - .timepicker-hour, .timepicker-minute, .timepicker-second { - width: 54px; - font-weight: bold; - font-size: 1.2em; - margin: 0; - } - - button[data-action] { - padding: 6px; - } - - table[data-hour-format="12"] .separator { - width: 4px; - padding: 0; - margin: 0; - } - - .datepicker > div { - display: none; - } - - .picker-switch { - text-align: center; - } - - table { - width: 100%; - margin: 0; - } - - td, - th { - text-align: center; - border-radius: @border-radius-base; - } - - td { - height: 54px; - line-height: 54px; - width: 54px; - - &.cw - { - font-size: 10px; - height: 20px; - line-height: 20px; - color: @gray-light; - } - - &.day - { - height: 20px; - line-height: 20px; - width: 20px; - } - - &.day:hover, - &.hour:hover, - &.minute:hover, - &.second:hover { - background: @gray-lighter; - cursor: pointer; - } - - &.old, - &.new { - color: @gray-light; - } - - &.today { - position: relative; - - &:before { - content: ''; - display: inline-block; - border-left: 7px solid transparent; - border-bottom: 7px solid @btn-primary-bg; - border-top-color: rgba(0, 0, 0, 0.2); - position: absolute; - bottom: 4px; - right: 4px; - } - } - - &.active, - &.active:hover { - background-color: @btn-primary-bg; - color: @btn-primary-color; - text-shadow: 0 -1px 0 rgba(0,0,0,.25); - } - - &.active.today:before { - border-bottom-color: #fff; - } - - &.disabled, - &.disabled:hover { - background: none; - color: @gray-light; - cursor: not-allowed; - } - - span { - display: inline-block; - width: 54px; - height: 54px; - line-height: 54px; - margin: 2px 1.5px; - cursor: pointer; - border-radius: @border-radius-base; - - &:hover { - background: @gray-lighter; - } - - &.active { - background-color: @btn-primary-bg; - color: @btn-primary-color; - text-shadow: 0 -1px 0 rgba(0,0,0,.25); - } - - &.old { - color: @gray-light; - } - - &.disabled, - &.disabled:hover { - background: none; - color: @gray-light; - cursor: not-allowed; - } - } - } - - th { - height: 20px; - line-height: 20px; - width: 20px; - - &.picker-switch { - width: 145px; - } - - &.next, - &.prev { - font-size: @font-size-base * 1.5; - } - - &.disabled, - &.disabled:hover { - background: none; - color: @gray-light; - cursor: not-allowed; - } - } - - thead tr:first-child th { - cursor: pointer; - - &:hover { - background: @gray-lighter; - } - } -} - -.input-group { - &.date { - .input-group-addon span { - display: block; - cursor: pointer; - width: 16px; - height: 16px; - } - } -} - -.bootstrap-datetimepicker-widget.left-oriented { - &:before { - left: auto; - right: 6px; - } - - &:after { - left: auto; - right: 7px; - } -} - -.bootstrap-datetimepicker-widget ul.list-unstyled li div.timepicker div.timepicker-picker table.table-condensed tbody > tr > td { - padding: 0px !important; -} - -@media screen and (max-width: 767px) { - .bootstrap-datetimepicker-widget.timepicker-sbs { - width: 283px; - } -} diff --git a/src/nuget/Bootstrap.v3.Datetimepicker.CSS.nuspec b/src/nuget/Bootstrap.v3.Datetimepicker.CSS.nuspec index 4192e1eb7..8f2add7ef 100644 --- a/src/nuget/Bootstrap.v3.Datetimepicker.CSS.nuspec +++ b/src/nuget/Bootstrap.v3.Datetimepicker.CSS.nuspec @@ -2,7 +2,7 @@ Bootstrap.v3.Datetimepicker.CSS - 3.1.2 + 4.0.0 Bootstrap 3 Datetimepicker CSS Eonasdan Eonasdan @@ -12,12 +12,12 @@ For usage, installation and demos see Project Site on GitHub -For CSS version install Bootstrap.v3.Datetimepicker.CSS +For LESS version install Bootstrap.v3.Datetimepicker Check the change log on Github at https://github.com/Eonasdan/bootstrap-datetimepicker/wiki/Change-Log bootstrap date time picker datetimepicker datepicker jquery - + diff --git a/src/nuget/Bootstrap.v3.Datetimepicker.nuspec b/src/nuget/Bootstrap.v3.Datetimepicker.nuspec index 267ec06a4..2cd9551a0 100644 --- a/src/nuget/Bootstrap.v3.Datetimepicker.nuspec +++ b/src/nuget/Bootstrap.v3.Datetimepicker.nuspec @@ -2,7 +2,7 @@ Bootstrap.v3.Datetimepicker - 3.1.2 + 4.0.0 Bootstrap 3 Datetimepicker Eonasdan Eonasdan @@ -17,13 +17,13 @@ For CSS version install Bootstrap.v3.Datetimepicker.CSS bootstrap date time picker datetimepicker datepicker jquery - + - + diff --git a/src/nuget/install.ps1 b/src/nuget/install.ps1 index b0443b27c..e3220106e 100644 --- a/src/nuget/install.ps1 +++ b/src/nuget/install.ps1 @@ -1,2 +1,2 @@ # install.ps1 -$DTE.ItemOperations.Navigate("https://github.com/Eonasdan/bootstrap-datetimepicker#change-log", $DTE.vsNavigateOptions.vsNavigateOptionsNewWindow) +$DTE.ItemOperations.Navigate("http://eonasdan.github.io/bootstrap-datetimepicker/", $DTE.vsNavigateOptions.vsNavigateOptionsNewWindow) diff --git a/test/publicApiSpec.js b/test/publicApiSpec.js new file mode 100644 index 000000000..c9b7a5034 --- /dev/null +++ b/test/publicApiSpec.js @@ -0,0 +1,700 @@ +describe('Plugin initialization and component basic construction', function () { + 'use strict'; + + it('loads jquery plugin properly', function () { + expect($('
').datetimepicker).toBeDefined(); + expect(typeof $('
').datetimepicker).toEqual('function'); + expect($('
').datetimepicker.defaults).toBeDefined(); + }); + + it('creates the component with default options on an input element', function () { + var dtp = $(''); + $(document).find('body').append(dtp); + + expect(function () { + dtp = dtp.datetimepicker(); + }).not.toThrow(); + + expect(dtp).not.toBe(null); + }); + + xit('calls destroy when Element that the component is attached is removed', function () { + var dtpElement = $('
').attr('class', 'row').append($('
').attr('class', 'col-md-12').append($(''))), + dtp; + $(document).find('body').append(dtpElement); + dtpElement.datetimepicker(); + dtp = dtpElement.data('DateTimePicker'); + spyOn(dtp, 'destroy').and.callThrough(); + dtpElement.remove(); + expect(dtp.destroy).toHaveBeenCalled(); + }); +}); + +describe('Public API method tests', function () { + 'use strict'; + var dtp, + dtpElement, + dpChangeSpy, + dpShowSpy, + dpHideSpy, + dpErrorSpy; + + beforeEach(function () { + dpChangeSpy = jasmine.createSpy('dp.change event Spy'); + dpShowSpy = jasmine.createSpy('dp.show event Spy'); + dpHideSpy = jasmine.createSpy('dp.hide event Spy'); + dpErrorSpy = jasmine.createSpy('dp.error event Spy'); + dtpElement = $('').attr('id', 'dtp'); + + $(document).find('body').append($('
').attr('class', 'row').append($('
').attr('class', 'col-md-12').append(dtpElement))); + $(document).find('body').on('dp.change', dpChangeSpy); + $(document).find('body').on('dp.show', dpShowSpy); + $(document).find('body').on('dp.hide', dpHideSpy); + $(document).find('body').on('dp.error', dpErrorSpy); + + dtpElement.datetimepicker(); + dtp = dtpElement.data('DateTimePicker'); + }); + + afterEach(function () { + dtp.destroy(); + dtpElement.remove(); + }); + + describe('configuration option name match to public api function', function () { + Object.getOwnPropertyNames($.fn.datetimepicker.defaults).forEach(function (key) { + it('has function ' + key + '()', function () { + expect(dtp[key]).toBeDefined(); + }); + }); + }); + + describe('date() function', function () { + describe('typechecking', function () { + it('accepts a null', function () { + expect(function () { + dtp.date(null); + }).not.toThrow(); + }); + + it('accepts a string', function () { + expect(function () { + dtp.date('2013/05/24'); + }).not.toThrow(); + }); + + it('accepts a Date object', function () { + expect(function () { + dtp.date(new Date()); + }).not.toThrow(); + }); + + it('accepts a Moment object', function () { + expect(function () { + dtp.date(moment()); + }).not.toThrow(); + }); + + it('does not accept undefined', function () { + expect(function () { + dtp.date(undefined); + }).toThrow(); + }); + + it('does not accept a number', function () { + expect(function () { + dtp.date(0); + }).toThrow(); + }); + + it('does not accept a generic Object', function () { + expect(function () { + dtp.date({}); + }).toThrow(); + }); + + it('does not accept a boolean', function () { + expect(function () { + dtp.date(false); + }).toThrow(); + }); + }); + + describe('functionality', function () { + it('has no date set upon construction', function () { + expect(dtp.date()).toBe(null); + }); + + it('sets the date correctly', function () { + var timestamp = moment(); + dtp.date(timestamp); + expect(dtp.date().isSame(timestamp)).toBe(true); + }); + }); + }); + + describe('format() function', function () { + describe('typechecking', function () { + it('accepts a false value', function () { + expect(function () { + dtp.format(false); + }).not.toThrow(); + }); + + it('accepts a string', function () { + expect(function () { + dtp.format('YYYY-MM-DD'); + }).not.toThrow(); + }); + + it('does not accept undefined', function () { + expect(function () { + dtp.format(undefined); + }).toThrow(); + }); + + it('does not accept true', function () { + expect(function () { + dtp.format(true); + }).toThrow(); + }); + + it('does not accept a generic Object', function () { + expect(function () { + dtp.format({}); + }).toThrow(); + }); + }); + + describe('functionality', function () { + it('returns no format before format is set', function () { + expect(dtp.format()).toBe(false); + }); + + it('sets the format correctly', function () { + dtp.format('YYYY-MM-DD'); + expect(dtp.format()).toBe('YYYY-MM-DD'); + }); + }); + }); + + describe('destroy() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.destroy).toBeDefined(); + }); + }); + }); + + describe('toggle() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.toggle).toBeDefined(); + }); + }); + + // describe('functionality', function () { + // it('') + // }); + }); + + describe('show() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.show).toBeDefined(); + }); + }); + + describe('functionality', function () { + it('emits a show event when called while widget is hidden', function () { + dtp.show(); + expect(dpShowSpy).toHaveBeenCalled(); + }); + + it('does not emit a show event when called and widget is already showing', function () { + dtp.hide(); + dtp.show(); + dpShowSpy.calls.reset(); + dtp.show(); + expect(dpShowSpy).not.toHaveBeenCalled(); + }); + + it('actually shows the widget', function () { + dtp.show(); + expect($(document).find('body').find('.bootstrap-datetimepicker-widget').length).toEqual(1); + }); + }); + }); + + describe('hide() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.hide).toBeDefined(); + }); + }); + + describe('functionality', function () { + it('emits a hide event when called while widget is shown', function () { + dtp.show(); + dtp.hide(); + expect(dpHideSpy).toHaveBeenCalled(); + }); + + it('does not emit a hide event when called while widget is hidden', function () { + dtp.hide(); + expect(dpHideSpy).not.toHaveBeenCalled(); + }); + + it('actually hides the widget', function () { + dtp.show(); + dtp.hide(); + expect($(document).find('body').find('.bootstrap-datetimepicker-widget').length).toEqual(0); + }); + }); + }); + + describe('disable() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.disable).toBeDefined(); + }); + }); + }); + + describe('enable() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.enable).toBeDefined(); + }); + }); + }); + + describe('options() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.options).toBeDefined(); + }); + }); + }); + + describe('disabledDates() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.disabledDates).toBeDefined(); + }); + }); + }); + + describe('enabledDates() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.enabledDates).toBeDefined(); + }); + }); + }); + + describe('daysOfWeekDisabled() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.daysOfWeekDisabled).toBeDefined(); + }); + }); + }); + + describe('maxDate() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.maxDate).toBeDefined(); + }); + }); + }); + + describe('minDate() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.minDate).toBeDefined(); + }); + }); + }); + + describe('defaultDate() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.defaultDate).toBeDefined(); + }); + }); + describe('functionality', function () { + it('returns no defaultDate before defaultDate is set', function () { + expect(dtp.defaultDate()).toBe(false); + }); + + it('sets the defaultDate correctly', function () { + var timestamp = moment(); + dtp.defaultDate(timestamp); + expect(dtp.defaultDate().isSame(timestamp)).toBe(true); + expect(dtp.date().isSame(timestamp)).toBe(true); + }); + + it('triggers a change event upon setting a default date and input field is empty', function () { + dtp.date(null); + dtp.defaultDate(moment()); + expect(dpChangeSpy).toHaveBeenCalled(); + }); + + it('does not override input value if it already has one', function () { + var timestamp = moment(); + dtp.date(timestamp); + dtp.defaultDate(moment().year(2000)); + expect(dtp.date().isSame(timestamp)).toBe(true); + }); + }); + }); + + describe('locale() function', function () { + describe('functionality', function () { + it('it has the same locale as the global moment locale with default options', function () { + expect(dtp.locale()).toBe(moment.locale()); + }); + + it('it switches to a selected locale without affecting global moment locale', function () { + dtp.locale('el'); + dtp.date(moment()); + expect(dtp.locale()).toBe('el'); + expect(dtp.date().locale()).toBe('el'); + expect(moment.locale()).toBe('en'); + }); + }); + }); + + describe('useCurrent() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.useCurrent).toBeDefined(); + }); + }); + describe('check type and parameter validity', function () { + it('accepts either a boolean value or string', function () { + var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; + + expect(function () { + dtp.useCurrent(false); + }).not.toThrow(); + expect(function () { + dtp.useCurrent(true); + }).not.toThrow(); + + useCurrentOptions.forEach(function (value) { + expect(function () { + dtp.useCurrent(value); + }).not.toThrow(); + }); + + expect(function () { + dtp.useCurrent('test'); + }).toThrow(); + expect(function () { + dtp.useCurrent({}); + }).toThrow(); + }); + }); + describe('functionality', function () { + it('triggers a change event upon show() and input field is empty', function () { + dtp.useCurrent(true); + dtp.show(); + expect(dpChangeSpy).toHaveBeenCalled(); + }); + }); + }); + + describe('ignoreReadonly() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.ignoreReadonly).toBeDefined(); + }); + }); + }); + + describe('stepping() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.stepping).toBeDefined(); + }); + }); + }); + + describe('collapse() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.collapse).toBeDefined(); + }); + }); + }); + + describe('icons() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.icons).toBeDefined(); + }); + }); + }); + + describe('useStrict() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.useStrict).toBeDefined(); + }); + }); + }); + + describe('sideBySide() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.sideBySide).toBeDefined(); + }); + }); + }); + + describe('viewMode() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.viewMode).toBeDefined(); + }); + }); + }); + + describe('widgetPositioning() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.widgetPositioning).toBeDefined(); + }); + }); + }); + + describe('calendarWeeks() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.calendarWeeks).toBeDefined(); + }); + }); + }); + + describe('showTodayButton() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.showTodayButton).toBeDefined(); + }); + }); + }); + + describe('showClear() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.showClear).toBeDefined(); + }); + }); + }); + + describe('dayViewHeaderFormat() function', function () { + describe('typechecking', function () { + it('does not accept a false value', function () { + expect(function () { + dtp.dayViewHeaderFormat(false); + }).toThrow(); + }); + + it('accepts a string', function () { + expect(function () { + dtp.dayViewHeaderFormat('YYYY-MM-DD'); + }).not.toThrow(); + }); + + it('does not accept undefined', function () { + expect(function () { + dtp.dayViewHeaderFormat(undefined); + }).toThrow(); + }); + + it('does not accept true', function () { + expect(function () { + dtp.dayViewHeaderFormat(true); + }).toThrow(); + }); + + it('does not accept a generic Object', function () { + expect(function () { + dtp.dayViewHeaderFormat({}); + }).toThrow(); + }); + }); + + describe('functionality', function () { + it('expects dayViewHeaderFormat to be default of MMMM YYYY', function () { + expect(dtp.dayViewHeaderFormat()).toBe('MMMM YYYY'); + }); + + it('sets the dayViewHeaderFormat correctly', function () { + dtp.dayViewHeaderFormat('MM YY'); + expect(dtp.dayViewHeaderFormat()).toBe('MM YY'); + }); + }); + }); + + describe('extraFormats() function', function () { + describe('typechecking', function () { + it('accepts a false value', function () { + expect(function () { + dtp.extraFormats(false); + }).not.toThrow(); + }); + + it('does not accept a string', function () { + expect(function () { + dtp.extraFormats('YYYY-MM-DD'); + }).toThrow(); + }); + + it('does not accept undefined', function () { + expect(function () { + dtp.extraFormats(undefined); + }).toThrow(); + }); + + it('does not accept true', function () { + expect(function () { + dtp.extraFormats(true); + }).toThrow(); + }); + + it('accepts an Array', function () { + expect(function () { + dtp.extraFormats(['YYYY-MM-DD']); + }).not.toThrow(); + }); + }); + + describe('functionality', function () { + it('returns no extraFormats before extraFormats is set', function () { + expect(dtp.extraFormats()).toBe(false); + }); + + it('sets the extraFormats correctly', function () { + dtp.extraFormats(['YYYY-MM-DD']); + expect(dtp.extraFormats()[0]).toBe('YYYY-MM-DD'); + }); + }); + }); + + describe('toolbarPlacement() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.toolbarPlacement).toBeDefined(); + }); + }); + describe('check type and parameter validity', function () { + it('does not accept a false value', function () { + expect(function () { + dtp.dayViewHeaderFormat(false); + }).toThrow(); + }); + it('does not accept a false value', function () { + expect(function () { + dtp.dayViewHeaderFormat(false); + }).toThrow(); + }); + it('accepts a string', function () { + var toolbarPlacementOptions = ['default', 'top', 'bottom']; + + toolbarPlacementOptions.forEach(function (value) { + expect(function () { + dtp.toolbarPlacement(value); + }).not.toThrow(); + }); + + expect(function () { + dtp.toolbarPlacement('test'); + }).toThrow(); + expect(function () { + dtp.toolbarPlacement({}); + }).toThrow(); + }); + }); + }); + + describe('widgetParent() function', function () { + describe('typechecking', function () { + it('accepts a null', function () { + expect(function () { + dtp.widgetParent(null); + }).not.toThrow(); + }); + + it('accepts a string', function () { + expect(function () { + dtp.widgetParent('testDiv'); + }).not.toThrow(); + }); + + it('accepts a jquery object', function () { + expect(function () { + dtp.widgetParent($('#testDiv')); + }).not.toThrow(); + }); + + it('does not accept undefined', function () { + expect(function () { + dtp.widgetParent(undefined); + }).toThrow(); + }); + + it('does not accept a number', function () { + expect(function () { + dtp.widgetParent(0); + }).toThrow(); + }); + + it('does not accept a generic Object', function () { + expect(function () { + dtp.widgetParent({}); + }).toThrow(); + }); + + it('does not accept a boolean', function () { + expect(function () { + dtp.widgetParent(false); + }).toThrow(); + }); + }); + }); + + describe('keepOpen() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.keepOpen).toBeDefined(); + }); + }); + }); + + describe('inline() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.inline).toBeDefined(); + }); + }); + }); + + describe('clear() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.clear).toBeDefined(); + }); + }); + }); + + describe('keyBinds() function', function () { + describe('existence', function () { + it('is defined', function () { + expect(dtp.keyBinds).toBeDefined(); + }); + }); + }); +});