├── .gitignore ├── .jscs.json ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── build ├── css │ ├── bootstrap-datetimepicker.css │ └── bootstrap-datetimepicker.min.css └── js │ ├── bootstrap-persian-datetimepicker.js │ └── bootstrap-persian-datetimepicker.min.js ├── component.json ├── composer.json ├── package.json ├── src ├── js │ ├── bootstrap-datetimepicker.js │ └── fa.js ├── less │ ├── _bootstrap-datetimepicker.less │ └── bootstrap-datetimepicker-build.less └── nuget │ ├── Bootstrap.v3.Datetimepicker.CSS.nuspec │ ├── Bootstrap.v3.Datetimepicker.nuspec │ ├── NuGet.exe │ └── install.ps1 ├── tasks └── bump_version.js ├── test └── publicApiSpec.js └── usage.html /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | /test.html 4 | -------------------------------------------------------------------------------- /.jscs.json: -------------------------------------------------------------------------------- 1 | { 2 | "requireCurlyBraces": [ 3 | "if", 4 | "else", 5 | "for", 6 | "while", 7 | "do", 8 | "try", 9 | "catch" 10 | ], 11 | "requireSpaceAfterKeywords": [ 12 | "if", 13 | "else", 14 | "for", 15 | "while", 16 | "do", 17 | "switch", 18 | "return", 19 | "try", 20 | "catch" 21 | ], 22 | "requireSpaceBeforeBlockStatements": true, 23 | "requireParenthesesAroundIIFE": true, 24 | "requireSpacesInConditionalExpression": true, 25 | "requireSpacesInAnonymousFunctionExpression": { 26 | "beforeOpeningRoundBrace": true, 27 | "beforeOpeningCurlyBrace": true 28 | }, 29 | "requireSpacesInNamedFunctionExpression": { 30 | "beforeOpeningCurlyBrace": true 31 | }, 32 | "disallowSpacesInNamedFunctionExpression": { 33 | "beforeOpeningRoundBrace": true 34 | }, 35 | "requireMultipleVarDecl": "onevar", 36 | "requireBlocksOnNewline": true, 37 | "disallowPaddingNewlinesInBlocks": true, 38 | "disallowEmptyBlocks": true, 39 | "disallowSpacesInsideObjectBrackets": true, 40 | "disallowSpacesInsideArrayBrackets": true, 41 | "disallowSpacesInsideParentheses": true, 42 | "requireCommaBeforeLineBreak": true, 43 | "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], 44 | "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], 45 | "requireSpaceBeforeBinaryOperators": [ 46 | "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", 47 | "&=", "|=", "^=", 48 | 49 | "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", 50 | "|", "^", "&&", "||", "===", "==", ">=", 51 | "<=", "<", ">", "!=", "!==" 52 | ], 53 | "requireSpaceAfterBinaryOperators": true, 54 | "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", 55 | "disallowKeywords": ["with"], 56 | "disallowMultipleLineStrings": true, 57 | "validateIndentation": 4, 58 | "disallowTrailingWhitespace": true, 59 | "disallowTrailingComma": true, 60 | "requireLineFeedAtFileEnd": true, 61 | "requireCapitalizedConstructors": true 62 | } 63 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /assets 2 | /_includes 3 | /_layouts 4 | /.gitignore 5 | /node_modules 6 | /Makefile 7 | /test 8 | /build 9 | *.log 10 | *.swp 11 | *~ 12 | *.tgz 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.10 4 | 5 | before_script: 6 | - npm install -g grunt-cli 7 | 8 | script: grunt build:travis 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Submitting Issues 2 | ================= 3 | 4 | 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. 5 | 6 | Issues that are submitted without a description (title only) will be closed with no further explanation. 7 | 8 | Contributing code 9 | ================= 10 | 11 | To contribute, fork the library and install grunt and dependencies. You need [node](http://nodejs.org/); use [nvm](https://github.com/creationix/nvm) or [nenv](https://github.com/ryuone/nenv) to install it. 12 | 13 | ```bash 14 | git clone https://github.com/Eonasdan/bootstrap-datetimepicker.git 15 | cd bootstrap-datetimepicker 16 | npm install -g grunt-cli 17 | npm install 18 | git checkout development # all patches against development branch, please! 19 | grunt # this runs tests and jshint 20 | ``` 21 | 22 | Very important notes 23 | ==================== 24 | 25 | * **Pull requests to the `master` branch will be closed.** Please submit all pull requests to the `development` branch. 26 | * **Do not include the minified files in your pull request.** Don't worry, we'll build them when we cut a release. 27 | * Pull requests that do not include a description (title only) and the following will be closed: 28 | * What the change does 29 | * A use case (for new features or enhancements) 30 | 31 | Grunt tasks 32 | =========== 33 | 34 | We use Grunt for managing the build. Here are some useful Grunt tasks: 35 | 36 | * `grunt` The default task lints the code and runs the tests. You should make sure you do this before submitting a PR. 37 | * `grunt build` Compiles the less stylesheet and minifies the javascript source in build directory. 38 | * `grunt build:travis` Compliles and runs the jasmine/travis tests. **All PR's MUST pass tests in place** 39 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 'use strict'; 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | main: { 7 | src: ['bower_components/pdate/pdate.min.js','src/js/fa.js','src/js/bootstrap-datetimepicker.js'], 8 | dest: 'build/js/bootstrap-persian-datetimepicker.js' 9 | } 10 | }, 11 | uglify : { 12 | target: { 13 | files: { 14 | 'build/js/bootstrap-persian-datetimepicker.min.js' : 'build/js/bootstrap-persian-datetimepicker.js' 15 | } 16 | }, 17 | options: { 18 | mangle: true, 19 | compress: { 20 | dead_code: false // jshint ignore:line 21 | }, 22 | output: { 23 | ascii_only: true // jshint ignore:line 24 | }, 25 | report: 'min', 26 | preserveComments: 'none' 27 | } 28 | }, 29 | jshint: { 30 | all: [ 31 | 'Gruntfile.js', 'src/js/*.js', 'test/*.js' 32 | ], 33 | options: { 34 | 'browser' : true, 35 | 'node' : true, 36 | 'jquery' : true, 37 | 'boss' : false, 38 | 'curly' : true, 39 | 'debug' : false, 40 | 'devel' : false, 41 | 'eqeqeq' : true, 42 | 'bitwise' : true, 43 | 'eqnull' : true, 44 | 'evil' : false, 45 | 'forin' : true, 46 | 'immed' : false, 47 | 'laxbreak' : false, 48 | 'newcap' : true, 49 | 'noarg' : true, 50 | 'noempty' : false, 51 | 'nonew' : false, 52 | 'onevar' : true, 53 | 'plusplus' : false, 54 | 'regexp' : false, 55 | 'undef' : true, 56 | 'sub' : true, 57 | 'strict' : true, 58 | 'unused' : true, 59 | 'white' : true, 60 | 'es3' : true, 61 | 'camelcase' : true, 62 | 'quotmark' : 'single', 63 | 'globals': { 64 | 'define': false, 65 | 'moment': false, 66 | // Jasmine 67 | 'jasmine': false, 68 | 'describe': false, 69 | 'xdescribe': false, 70 | 'expect': false, 71 | 'it': false, 72 | 'xit': false, 73 | 'spyOn': false, 74 | 'beforeEach': false, 75 | 'afterEach': false 76 | } 77 | } 78 | }, 79 | 80 | jscs: { 81 | all: [ 82 | 'Gruntfile.js', 'src/js/*.js', 'test/*.js' 83 | ], 84 | options: { 85 | config: '.jscs.json' 86 | } 87 | }, 88 | 89 | less: { 90 | production: { 91 | options: { 92 | cleancss: true 93 | }, 94 | files: { 95 | 'build/css/bootstrap-datetimepicker.min.css': 'src/less/bootstrap-datetimepicker-build.less' 96 | } 97 | }, 98 | development: { 99 | files: { 100 | 'build/css/bootstrap-datetimepicker.css': 'src/less/bootstrap-datetimepicker-build.less' 101 | } 102 | } 103 | }, 104 | 105 | jasmine: { 106 | customTemplate: { 107 | src: 'src/js/*.js', 108 | options: { 109 | specs: 'test/*Spec.js', 110 | helpers: 'test/*Helper.js', 111 | styles: [ 112 | 'node_modules/bootstrap/dist/css/bootstrap.min.css', 113 | 'build/css/bootstrap-datetimepicker.min.css' 114 | ], 115 | vendor: [ 116 | 'node_modules/jquery/dist/jquery.min.js', 117 | 'node_modules/moment/min/moment-with-locales.min.js', 118 | 'node_modules/bootstrap/dist/js/bootstrap.min.js' 119 | ], 120 | display: 'true', 121 | summary: 'true' 122 | } 123 | } 124 | } 125 | 126 | }); 127 | 128 | grunt.loadTasks('tasks'); 129 | 130 | grunt.loadNpmTasks('grunt-contrib-jasmine'); 131 | grunt.loadNpmTasks('grunt-contrib-concat'); 132 | 133 | // These plugins provide necessary tasks. 134 | require('load-grunt-tasks')(grunt); 135 | 136 | // Default task. 137 | //grunt.registerTask('default', ['jshint', 'jscs', 'less', 'jasmine']); 138 | grunt.registerTask('default', ['less', 'jasmine']); 139 | 140 | // travis build task 141 | grunt.registerTask('build:travis', [ 142 | 'jasmine' 143 | ]); 144 | 145 | // Task to be run when building 146 | grunt.registerTask('build', [ 147 | 'concat','uglify', 'less' 148 | ]); 149 | 150 | grunt.registerTask('nuget', 'Create a nuget package', function () { 151 | var target = grunt.option('target') || 'less', done = this.async(); 152 | if (target === 'less') { 153 | grunt.util.spawn({ 154 | cmd: 'src/nuget/nuget.exe', 155 | args: [ 156 | 'pack', 157 | 'src/nuget/Bootstrap.v3.Datetimepicker.nuspec', 158 | '-OutputDirectory', 159 | 'build/nuget', 160 | '-Version', 161 | grunt.config.get('pkg').version 162 | ] 163 | }, function (error, result) { 164 | if (error) { 165 | grunt.log.error(error); 166 | } else { 167 | grunt.log.write(result); 168 | } 169 | done(); 170 | }); 171 | } 172 | else { //--target=css 173 | grunt.util.spawn({ 174 | cmd: 'src/nuget/nuget.exe', 175 | args: [ 176 | 'pack', 177 | 'src/nuget/Bootstrap.v3.Datetimepicker.CSS.nuspec', 178 | '-OutputDirectory', 179 | 'build/nuget', 180 | '-Version', 181 | grunt.config.get('pkg').version 182 | ] 183 | }, function (error, result) { 184 | if (error) { 185 | grunt.log.error(error); 186 | } else { 187 | grunt.log.write(result); 188 | } 189 | done(); 190 | }); 191 | } 192 | }); 193 | 194 | grunt.registerTask('test', ['jshint', 'jscs', 'uglify', 'less', 'jasmine']); 195 | }; 196 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jonathan Peterson (@Eonasdan) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bootstrap 3 Persian Date/Time Picker 2 | 3 | ![DateTimePicker](http://parhood.com/usage.png) 4 | 5 | ## Submitting Issues 6 | If you have issues, please check the following first: 7 | - Have you read the docs? 8 | - Do you have the latest version of momentjs? 9 | - Do you have the latest version of jQuery? 10 | 11 | ## How to use 12 | take a look at `usage.html` in the project directory 13 | 14 | ## Manual and the docs 15 | documentations is same as original project: 16 | 17 | [document and samples from Eonasdan's project](http://eonasdan.github.io/bootstrap-datetimepicker/) 18 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-persian-datetimepicker", 3 | "version": "4.7.147", 4 | "main": [ 5 | "build/css/bootstrap-datetimepicker.min.css", 6 | "build/js/bootstrap-persian-datetimepicker.min.js", 7 | "src/less/_bootstrap-datetimepicker.less", 8 | "src/less/bootstrap-datetimepicker-build.less", 9 | "src/js/bootstrap-datetimepicker.js" 10 | ], 11 | "dependencies": { 12 | "jquery": ">=1.8.3", 13 | "moment": ">=2.8.0" 14 | }, 15 | "homepage": "https://github.com/beygi/bootstrap-persian-datetimepicker", 16 | "authors": [ 17 | "Mahdy Beygi" 18 | ], 19 | "description": "bootstrap3 persian datetimepicker", 20 | "keywords": [ 21 | "twitter-bootstrap", 22 | "bootstrap", 23 | "datepicker", 24 | "datetimepicker", 25 | "timepicker", 26 | "moment" 27 | ], 28 | "license": "GPL v3", 29 | "ignore": [ 30 | "**/.*", 31 | "node_modules", 32 | "bower_components", 33 | "test", 34 | "tests" 35 | ], 36 | "devDependencies": { 37 | "pdate": "~0.0.5" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /build/css/bootstrap-datetimepicker.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Datetimepicker for Bootstrap 3 3 | * ! version : 4.7.14 4 | * https://github.com/Eonasdan/bootstrap-datetimepicker/ 5 | */ 6 | .bootstrap-datetimepicker-widget { 7 | list-style: none; 8 | } 9 | .bootstrap-datetimepicker-widget.dropdown-menu { 10 | margin: 2px 0; 11 | padding: 4px; 12 | width: 19em; 13 | } 14 | @media (min-width: 768px) { 15 | .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { 16 | width: 38em; 17 | } 18 | } 19 | @media (min-width: 992px) { 20 | .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { 21 | width: 38em; 22 | } 23 | } 24 | @media (min-width: 1200px) { 25 | .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { 26 | width: 38em; 27 | } 28 | } 29 | .bootstrap-datetimepicker-widget.dropdown-menu:before, 30 | .bootstrap-datetimepicker-widget.dropdown-menu:after { 31 | content: ''; 32 | display: inline-block; 33 | position: absolute; 34 | } 35 | .bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { 36 | border-left: 7px solid transparent; 37 | border-right: 7px solid transparent; 38 | border-bottom: 7px solid #cccccc; 39 | border-bottom-color: rgba(0, 0, 0, 0.2); 40 | top: -7px; 41 | left: 7px; 42 | } 43 | .bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { 44 | border-left: 6px solid transparent; 45 | border-right: 6px solid transparent; 46 | border-bottom: 6px solid white; 47 | top: -6px; 48 | left: 8px; 49 | } 50 | .bootstrap-datetimepicker-widget.dropdown-menu.top:before { 51 | border-left: 7px solid transparent; 52 | border-right: 7px solid transparent; 53 | border-top: 7px solid #cccccc; 54 | border-top-color: rgba(0, 0, 0, 0.2); 55 | bottom: -7px; 56 | left: 6px; 57 | } 58 | .bootstrap-datetimepicker-widget.dropdown-menu.top:after { 59 | border-left: 6px solid transparent; 60 | border-right: 6px solid transparent; 61 | border-top: 6px solid white; 62 | bottom: -6px; 63 | left: 7px; 64 | } 65 | .bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { 66 | left: auto; 67 | right: 6px; 68 | } 69 | .bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { 70 | left: auto; 71 | right: 7px; 72 | } 73 | .bootstrap-datetimepicker-widget .list-unstyled { 74 | margin: 0; 75 | } 76 | .bootstrap-datetimepicker-widget a[data-action] { 77 | padding: 6px 0; 78 | } 79 | .bootstrap-datetimepicker-widget a[data-action]:active { 80 | box-shadow: none; 81 | } 82 | .bootstrap-datetimepicker-widget .timepicker-hour, 83 | .bootstrap-datetimepicker-widget .timepicker-minute, 84 | .bootstrap-datetimepicker-widget .timepicker-second { 85 | width: 54px; 86 | font-weight: bold; 87 | font-size: 1.2em; 88 | margin: 0; 89 | } 90 | .bootstrap-datetimepicker-widget button[data-action] { 91 | padding: 6px; 92 | } 93 | .bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { 94 | position: absolute; 95 | width: 1px; 96 | height: 1px; 97 | margin: -1px; 98 | padding: 0; 99 | overflow: hidden; 100 | clip: rect(0, 0, 0, 0); 101 | border: 0; 102 | content: "Increment Hours"; 103 | } 104 | .bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { 105 | position: absolute; 106 | width: 1px; 107 | height: 1px; 108 | margin: -1px; 109 | padding: 0; 110 | overflow: hidden; 111 | clip: rect(0, 0, 0, 0); 112 | border: 0; 113 | content: "Increment Minutes"; 114 | } 115 | .bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { 116 | position: absolute; 117 | width: 1px; 118 | height: 1px; 119 | margin: -1px; 120 | padding: 0; 121 | overflow: hidden; 122 | clip: rect(0, 0, 0, 0); 123 | border: 0; 124 | content: "Decrement Hours"; 125 | } 126 | .bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { 127 | position: absolute; 128 | width: 1px; 129 | height: 1px; 130 | margin: -1px; 131 | padding: 0; 132 | overflow: hidden; 133 | clip: rect(0, 0, 0, 0); 134 | border: 0; 135 | content: "Decrement Minutes"; 136 | } 137 | .bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { 138 | position: absolute; 139 | width: 1px; 140 | height: 1px; 141 | margin: -1px; 142 | padding: 0; 143 | overflow: hidden; 144 | clip: rect(0, 0, 0, 0); 145 | border: 0; 146 | content: "Show Hours"; 147 | } 148 | .bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { 149 | position: absolute; 150 | width: 1px; 151 | height: 1px; 152 | margin: -1px; 153 | padding: 0; 154 | overflow: hidden; 155 | clip: rect(0, 0, 0, 0); 156 | border: 0; 157 | content: "Show Minutes"; 158 | } 159 | .bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { 160 | position: absolute; 161 | width: 1px; 162 | height: 1px; 163 | margin: -1px; 164 | padding: 0; 165 | overflow: hidden; 166 | clip: rect(0, 0, 0, 0); 167 | border: 0; 168 | content: "Toggle AM/PM"; 169 | } 170 | .bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { 171 | position: absolute; 172 | width: 1px; 173 | height: 1px; 174 | margin: -1px; 175 | padding: 0; 176 | overflow: hidden; 177 | clip: rect(0, 0, 0, 0); 178 | border: 0; 179 | content: "Clear the picker"; 180 | } 181 | .bootstrap-datetimepicker-widget .btn[data-action="today"]::after { 182 | position: absolute; 183 | width: 1px; 184 | height: 1px; 185 | margin: -1px; 186 | padding: 0; 187 | overflow: hidden; 188 | clip: rect(0, 0, 0, 0); 189 | border: 0; 190 | content: "Set the date to today"; 191 | } 192 | .bootstrap-datetimepicker-widget .picker-switch { 193 | text-align: center; 194 | } 195 | .bootstrap-datetimepicker-widget .picker-switch::after { 196 | position: absolute; 197 | width: 1px; 198 | height: 1px; 199 | margin: -1px; 200 | padding: 0; 201 | overflow: hidden; 202 | clip: rect(0, 0, 0, 0); 203 | border: 0; 204 | content: "Toggle Date and Time Screens"; 205 | } 206 | .bootstrap-datetimepicker-widget .picker-switch td { 207 | padding: 0; 208 | margin: 0; 209 | height: auto; 210 | width: auto; 211 | line-height: inherit; 212 | } 213 | .bootstrap-datetimepicker-widget .picker-switch td span { 214 | line-height: 2.5; 215 | height: 2.5em; 216 | width: 100%; 217 | } 218 | .bootstrap-datetimepicker-widget table { 219 | width: 100%; 220 | margin: 0; 221 | } 222 | .bootstrap-datetimepicker-widget table td, 223 | .bootstrap-datetimepicker-widget table th { 224 | text-align: center; 225 | border-radius: 4px; 226 | } 227 | .bootstrap-datetimepicker-widget table th { 228 | height: 20px; 229 | line-height: 20px; 230 | width: 20px; 231 | } 232 | .bootstrap-datetimepicker-widget table th.picker-switch { 233 | width: 145px; 234 | } 235 | .bootstrap-datetimepicker-widget table th.disabled, 236 | .bootstrap-datetimepicker-widget table th.disabled:hover { 237 | background: none; 238 | color: #777777; 239 | cursor: not-allowed; 240 | } 241 | .bootstrap-datetimepicker-widget table th.prev::after { 242 | position: absolute; 243 | width: 1px; 244 | height: 1px; 245 | margin: -1px; 246 | padding: 0; 247 | overflow: hidden; 248 | clip: rect(0, 0, 0, 0); 249 | border: 0; 250 | content: "Previous Month"; 251 | } 252 | .bootstrap-datetimepicker-widget table th.next::after { 253 | position: absolute; 254 | width: 1px; 255 | height: 1px; 256 | margin: -1px; 257 | padding: 0; 258 | overflow: hidden; 259 | clip: rect(0, 0, 0, 0); 260 | border: 0; 261 | content: "Next Month"; 262 | } 263 | .bootstrap-datetimepicker-widget table thead tr:first-child th { 264 | cursor: pointer; 265 | } 266 | .bootstrap-datetimepicker-widget table thead tr:first-child th:hover { 267 | background: #eeeeee; 268 | } 269 | .bootstrap-datetimepicker-widget table td { 270 | height: 54px; 271 | line-height: 54px; 272 | width: 54px; 273 | } 274 | .bootstrap-datetimepicker-widget table td.cw { 275 | font-size: .8em; 276 | height: 20px; 277 | line-height: 20px; 278 | color: #777777; 279 | } 280 | .bootstrap-datetimepicker-widget table td.day { 281 | height: 20px; 282 | line-height: 20px; 283 | width: 20px; 284 | } 285 | .bootstrap-datetimepicker-widget table td.day:hover, 286 | .bootstrap-datetimepicker-widget table td.hour:hover, 287 | .bootstrap-datetimepicker-widget table td.minute:hover, 288 | .bootstrap-datetimepicker-widget table td.second:hover { 289 | background: #eeeeee; 290 | cursor: pointer; 291 | } 292 | .bootstrap-datetimepicker-widget table td.old, 293 | .bootstrap-datetimepicker-widget table td.new { 294 | color: #777777; 295 | } 296 | .bootstrap-datetimepicker-widget table td.today { 297 | position: relative; 298 | } 299 | .bootstrap-datetimepicker-widget table td.today:before { 300 | content: ''; 301 | display: inline-block; 302 | border: 0 0 7px 7px solid transparent; 303 | border-bottom-color: #337ab7; 304 | border-top-color: rgba(0, 0, 0, 0.2); 305 | position: absolute; 306 | bottom: 4px; 307 | right: 4px; 308 | } 309 | .bootstrap-datetimepicker-widget table td.active, 310 | .bootstrap-datetimepicker-widget table td.active:hover { 311 | background-color: #337ab7; 312 | color: #ffffff; 313 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 314 | } 315 | .bootstrap-datetimepicker-widget table td.active.today:before { 316 | border-bottom-color: #fff; 317 | } 318 | .bootstrap-datetimepicker-widget table td.disabled, 319 | .bootstrap-datetimepicker-widget table td.disabled:hover { 320 | background: none; 321 | color: #777777; 322 | cursor: not-allowed; 323 | } 324 | .bootstrap-datetimepicker-widget table td span { 325 | display: inline-block; 326 | width: 54px; 327 | height: 54px; 328 | line-height: 54px; 329 | margin: 2px 1.5px; 330 | cursor: pointer; 331 | border-radius: 4px; 332 | } 333 | .bootstrap-datetimepicker-widget table td span:hover { 334 | background: #eeeeee; 335 | } 336 | .bootstrap-datetimepicker-widget table td span.active { 337 | background-color: #337ab7; 338 | color: #ffffff; 339 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 340 | } 341 | .bootstrap-datetimepicker-widget table td span.old { 342 | color: #777777; 343 | } 344 | .bootstrap-datetimepicker-widget table td span.disabled, 345 | .bootstrap-datetimepicker-widget table td span.disabled:hover { 346 | background: none; 347 | color: #777777; 348 | cursor: not-allowed; 349 | } 350 | .bootstrap-datetimepicker-widget.usetwentyfour td.hour { 351 | height: 27px; 352 | line-height: 27px; 353 | } 354 | .input-group.date .input-group-addon { 355 | cursor: pointer; 356 | } 357 | .datepicker { 358 | direction: rtl !important; 359 | } 360 | .timepicker { 361 | direction: ltr !important; 362 | } 363 | .ext-btns { 364 | width: 50% !important; 365 | } 366 | .picker-switch { 367 | direction: rtl !important; 368 | } 369 | .sr-only { 370 | position: absolute; 371 | width: 1px; 372 | height: 1px; 373 | margin: -1px; 374 | padding: 0; 375 | overflow: hidden; 376 | clip: rect(0, 0, 0, 0); 377 | border: 0; 378 | } 379 | -------------------------------------------------------------------------------- /build/css/bootstrap-datetimepicker.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Datetimepicker for Bootstrap 3 3 | * ! version : 4.7.14 4 | * https://github.com/Eonasdan/bootstrap-datetimepicker/ 5 | */ 6 | .bootstrap-datetimepicker-widget { 7 | list-style: none; 8 | } 9 | .bootstrap-datetimepicker-widget.dropdown-menu { 10 | margin: 2px 0; 11 | padding: 4px; 12 | width: 19em; 13 | } 14 | @media (min-width: 768px) { 15 | .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { 16 | width: 38em; 17 | } 18 | } 19 | @media (min-width: 992px) { 20 | .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { 21 | width: 38em; 22 | } 23 | } 24 | @media (min-width: 1200px) { 25 | .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { 26 | width: 38em; 27 | } 28 | } 29 | .bootstrap-datetimepicker-widget.dropdown-menu:before, 30 | .bootstrap-datetimepicker-widget.dropdown-menu:after { 31 | content: ''; 32 | display: inline-block; 33 | position: absolute; 34 | } 35 | .bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { 36 | border-left: 7px solid transparent; 37 | border-right: 7px solid transparent; 38 | border-bottom: 7px solid #cccccc; 39 | border-bottom-color: rgba(0, 0, 0, 0.2); 40 | top: -7px; 41 | left: 7px; 42 | } 43 | .bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { 44 | border-left: 6px solid transparent; 45 | border-right: 6px solid transparent; 46 | border-bottom: 6px solid white; 47 | top: -6px; 48 | left: 8px; 49 | } 50 | .bootstrap-datetimepicker-widget.dropdown-menu.top:before { 51 | border-left: 7px solid transparent; 52 | border-right: 7px solid transparent; 53 | border-top: 7px solid #cccccc; 54 | border-top-color: rgba(0, 0, 0, 0.2); 55 | bottom: -7px; 56 | left: 6px; 57 | } 58 | .bootstrap-datetimepicker-widget.dropdown-menu.top:after { 59 | border-left: 6px solid transparent; 60 | border-right: 6px solid transparent; 61 | border-top: 6px solid white; 62 | bottom: -6px; 63 | left: 7px; 64 | } 65 | .bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { 66 | left: auto; 67 | right: 6px; 68 | } 69 | .bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { 70 | left: auto; 71 | right: 7px; 72 | } 73 | .bootstrap-datetimepicker-widget .list-unstyled { 74 | margin: 0; 75 | } 76 | .bootstrap-datetimepicker-widget a[data-action] { 77 | padding: 6px 0; 78 | } 79 | .bootstrap-datetimepicker-widget a[data-action]:active { 80 | box-shadow: none; 81 | } 82 | .bootstrap-datetimepicker-widget .timepicker-hour, 83 | .bootstrap-datetimepicker-widget .timepicker-minute, 84 | .bootstrap-datetimepicker-widget .timepicker-second { 85 | width: 54px; 86 | font-weight: bold; 87 | font-size: 1.2em; 88 | margin: 0; 89 | } 90 | .bootstrap-datetimepicker-widget button[data-action] { 91 | padding: 6px; 92 | } 93 | .bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { 94 | position: absolute; 95 | width: 1px; 96 | height: 1px; 97 | margin: -1px; 98 | padding: 0; 99 | overflow: hidden; 100 | clip: rect(0, 0, 0, 0); 101 | border: 0; 102 | content: "Increment Hours"; 103 | } 104 | .bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { 105 | position: absolute; 106 | width: 1px; 107 | height: 1px; 108 | margin: -1px; 109 | padding: 0; 110 | overflow: hidden; 111 | clip: rect(0, 0, 0, 0); 112 | border: 0; 113 | content: "Increment Minutes"; 114 | } 115 | .bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { 116 | position: absolute; 117 | width: 1px; 118 | height: 1px; 119 | margin: -1px; 120 | padding: 0; 121 | overflow: hidden; 122 | clip: rect(0, 0, 0, 0); 123 | border: 0; 124 | content: "Decrement Hours"; 125 | } 126 | .bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { 127 | position: absolute; 128 | width: 1px; 129 | height: 1px; 130 | margin: -1px; 131 | padding: 0; 132 | overflow: hidden; 133 | clip: rect(0, 0, 0, 0); 134 | border: 0; 135 | content: "Decrement Minutes"; 136 | } 137 | .bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { 138 | position: absolute; 139 | width: 1px; 140 | height: 1px; 141 | margin: -1px; 142 | padding: 0; 143 | overflow: hidden; 144 | clip: rect(0, 0, 0, 0); 145 | border: 0; 146 | content: "Show Hours"; 147 | } 148 | .bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { 149 | position: absolute; 150 | width: 1px; 151 | height: 1px; 152 | margin: -1px; 153 | padding: 0; 154 | overflow: hidden; 155 | clip: rect(0, 0, 0, 0); 156 | border: 0; 157 | content: "Show Minutes"; 158 | } 159 | .bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { 160 | position: absolute; 161 | width: 1px; 162 | height: 1px; 163 | margin: -1px; 164 | padding: 0; 165 | overflow: hidden; 166 | clip: rect(0, 0, 0, 0); 167 | border: 0; 168 | content: "Toggle AM/PM"; 169 | } 170 | .bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { 171 | position: absolute; 172 | width: 1px; 173 | height: 1px; 174 | margin: -1px; 175 | padding: 0; 176 | overflow: hidden; 177 | clip: rect(0, 0, 0, 0); 178 | border: 0; 179 | content: "Clear the picker"; 180 | } 181 | .bootstrap-datetimepicker-widget .btn[data-action="today"]::after { 182 | position: absolute; 183 | width: 1px; 184 | height: 1px; 185 | margin: -1px; 186 | padding: 0; 187 | overflow: hidden; 188 | clip: rect(0, 0, 0, 0); 189 | border: 0; 190 | content: "Set the date to today"; 191 | } 192 | .bootstrap-datetimepicker-widget .picker-switch { 193 | text-align: center; 194 | } 195 | .bootstrap-datetimepicker-widget .picker-switch::after { 196 | position: absolute; 197 | width: 1px; 198 | height: 1px; 199 | margin: -1px; 200 | padding: 0; 201 | overflow: hidden; 202 | clip: rect(0, 0, 0, 0); 203 | border: 0; 204 | content: "Toggle Date and Time Screens"; 205 | } 206 | .bootstrap-datetimepicker-widget .picker-switch td { 207 | padding: 0; 208 | margin: 0; 209 | height: auto; 210 | width: auto; 211 | line-height: inherit; 212 | } 213 | .bootstrap-datetimepicker-widget .picker-switch td span { 214 | line-height: 2.5; 215 | height: 2.5em; 216 | width: 100%; 217 | } 218 | .bootstrap-datetimepicker-widget table { 219 | width: 100%; 220 | margin: 0; 221 | } 222 | .bootstrap-datetimepicker-widget table td, 223 | .bootstrap-datetimepicker-widget table th { 224 | text-align: center; 225 | border-radius: 4px; 226 | } 227 | .bootstrap-datetimepicker-widget table th { 228 | height: 20px; 229 | line-height: 20px; 230 | width: 20px; 231 | } 232 | .bootstrap-datetimepicker-widget table th.picker-switch { 233 | width: 145px; 234 | } 235 | .bootstrap-datetimepicker-widget table th.disabled, 236 | .bootstrap-datetimepicker-widget table th.disabled:hover { 237 | background: none; 238 | color: #777777; 239 | cursor: not-allowed; 240 | } 241 | .bootstrap-datetimepicker-widget table th.prev::after { 242 | position: absolute; 243 | width: 1px; 244 | height: 1px; 245 | margin: -1px; 246 | padding: 0; 247 | overflow: hidden; 248 | clip: rect(0, 0, 0, 0); 249 | border: 0; 250 | content: "Previous Month"; 251 | } 252 | .bootstrap-datetimepicker-widget table th.next::after { 253 | position: absolute; 254 | width: 1px; 255 | height: 1px; 256 | margin: -1px; 257 | padding: 0; 258 | overflow: hidden; 259 | clip: rect(0, 0, 0, 0); 260 | border: 0; 261 | content: "Next Month"; 262 | } 263 | .bootstrap-datetimepicker-widget table thead tr:first-child th { 264 | cursor: pointer; 265 | } 266 | .bootstrap-datetimepicker-widget table thead tr:first-child th:hover { 267 | background: #eeeeee; 268 | } 269 | .bootstrap-datetimepicker-widget table td { 270 | height: 54px; 271 | line-height: 54px; 272 | width: 54px; 273 | } 274 | .bootstrap-datetimepicker-widget table td.cw { 275 | font-size: .8em; 276 | height: 20px; 277 | line-height: 20px; 278 | color: #777777; 279 | } 280 | .bootstrap-datetimepicker-widget table td.day { 281 | height: 20px; 282 | line-height: 20px; 283 | width: 20px; 284 | } 285 | .bootstrap-datetimepicker-widget table td.day:hover, 286 | .bootstrap-datetimepicker-widget table td.hour:hover, 287 | .bootstrap-datetimepicker-widget table td.minute:hover, 288 | .bootstrap-datetimepicker-widget table td.second:hover { 289 | background: #eeeeee; 290 | cursor: pointer; 291 | } 292 | .bootstrap-datetimepicker-widget table td.old, 293 | .bootstrap-datetimepicker-widget table td.new { 294 | color: #777777; 295 | } 296 | .bootstrap-datetimepicker-widget table td.today { 297 | position: relative; 298 | } 299 | .bootstrap-datetimepicker-widget table td.today:before { 300 | content: ''; 301 | display: inline-block; 302 | border: 0 0 7px 7px solid transparent; 303 | border-bottom-color: #337ab7; 304 | border-top-color: rgba(0, 0, 0, 0.2); 305 | position: absolute; 306 | bottom: 4px; 307 | right: 4px; 308 | } 309 | .bootstrap-datetimepicker-widget table td.active, 310 | .bootstrap-datetimepicker-widget table td.active:hover { 311 | background-color: #337ab7; 312 | color: #ffffff; 313 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 314 | } 315 | .bootstrap-datetimepicker-widget table td.active.today:before { 316 | border-bottom-color: #fff; 317 | } 318 | .bootstrap-datetimepicker-widget table td.disabled, 319 | .bootstrap-datetimepicker-widget table td.disabled:hover { 320 | background: none; 321 | color: #777777; 322 | cursor: not-allowed; 323 | } 324 | .bootstrap-datetimepicker-widget table td span { 325 | display: inline-block; 326 | width: 54px; 327 | height: 54px; 328 | line-height: 54px; 329 | margin: 2px 1.5px; 330 | cursor: pointer; 331 | border-radius: 4px; 332 | } 333 | .bootstrap-datetimepicker-widget table td span:hover { 334 | background: #eeeeee; 335 | } 336 | .bootstrap-datetimepicker-widget table td span.active { 337 | background-color: #337ab7; 338 | color: #ffffff; 339 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 340 | } 341 | .bootstrap-datetimepicker-widget table td span.old { 342 | color: #777777; 343 | } 344 | .bootstrap-datetimepicker-widget table td span.disabled, 345 | .bootstrap-datetimepicker-widget table td span.disabled:hover { 346 | background: none; 347 | color: #777777; 348 | cursor: not-allowed; 349 | } 350 | .bootstrap-datetimepicker-widget.usetwentyfour td.hour { 351 | height: 27px; 352 | line-height: 27px; 353 | } 354 | .input-group.date .input-group-addon { 355 | cursor: pointer; 356 | } 357 | .datepicker { 358 | direction: rtl !important; 359 | } 360 | .timepicker { 361 | direction: ltr !important; 362 | } 363 | .ext-btns { 364 | width: 50% !important; 365 | } 366 | .picker-switch { 367 | direction: rtl !important; 368 | } 369 | .sr-only { 370 | position: absolute; 371 | width: 1px; 372 | height: 1px; 373 | margin: -1px; 374 | padding: 0; 375 | overflow: hidden; 376 | clip: rect(0, 0, 0, 0); 377 | border: 0; 378 | } 379 | -------------------------------------------------------------------------------- /build/js/bootstrap-persian-datetimepicker.min.js: -------------------------------------------------------------------------------- 1 | !function(){function a(a,b){return a-b*Math.floor(a/b)}function b(a){return a%4===0&&!(a%100===0&&a%400!==0)}function c(a,c,d){return l-1+365*(a-1)+Math.floor((a-1)/4)+-Math.floor((a-1)/100)+Math.floor((a-1)/400)+Math.floor((367*c-362)/12+(2>=c?0:b(a)?-1:-2)+d)}function d(d){var e,f,g,h,i,j,k,m,n,o,p,q;e=Math.floor(d-.5)+.5,f=e-l,g=Math.floor(f/146097),h=a(f,146097),i=Math.floor(h/36524),j=a(h,36524),k=Math.floor(j/1461),m=a(j,1461),n=Math.floor(m/365),o=400*g+100*i+4*k+n,4!=i&&4!=n&&o++,p=e-c(o,1,1),q=e=0?474:473),f=474+a(e,2820),d+(7>=c?31*(c-1):30*(c-1)+6)+Math.floor((682*f-110)/2816)+365*(f-1)+1029983*Math.floor(e/2820)+(m-1)}function f(b){var c,d,f,g,h,i,j,k,l,m;return b=Math.floor(b)+.5,g=b-e(475,1,1),h=Math.floor(g/1029983),i=a(g,1029983),1029982==i?j=2820:(k=Math.floor(i/366),l=a(i,366),j=Math.floor((2134*k+2816*l+2815)/1028522)+k+1),c=j+2820*h+474,0>=c&&c--,m=b-e(c,1,1)+1,d=Math.ceil(186>=m?m/31:(m-6)/30),f=b-e(c,d,1)+1,[c,d,f]}function g(a){return a.replace(/[۰-۹]/g,function(a){return String.fromCharCode(a.charCodeAt(0)-1728)})}function h(a){return 10>a?"0"+a:a}function i(a,b,c){if(b>12||0>=b){var d=Math.floor((b-1)/12);a+=d,b-=12*d}return e(a,b,c)}function j(a,b){var c=/^(\d|\d\d|\d\d\d\d)(?:([-\/])(\d{1,2})(?:\2(\d|\d\d|\d\d\d\d))?)?(([ T])(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?(Z|([+-])(\d{2})(?::?(\d{2}))?)?)?$/,e=c.exec(a);if(e){var f=e[2],g=e[6],h=+e[1],j=+e[3]||1,k=+e[4]||1,l="/"!=f&&" "!=e[6],m=+e[7]||0,o=+e[8]||0,p=+e[9]||0,q=1e3*+("0."+(e[10]||"0")),r=e[11],s=l&&(r||!e[5]),t=("-"==e[12]?-1:1)*(60*(+e[13]||0)+(+e[14]||0));if((!r&&"T"!=g||l)&&k>=1e3!=h>=1e3){if(k>=1e3){if("-"==f)return;k=+e[1],h=k}if(b){var u=d(i(h,j,k));h=u[0],j=u[1],k=u[2]}var v=new n(h,j-1,k,m,o,p,q);return s&&v.setUTCMinutes(v.getUTCMinutes()-v.getTimezoneOffset()+t),v}}}function k(a,b,c,e,f,h,l){if("string"==typeof a){if(convert=void 0!=b?b:!0,this._d=j(g(a),convert),!this._d)throw"Cannot parse date string"}else if(0==arguments.length)this._d=new n;else if(1==arguments.length)this._d=new n(a instanceof k?a._d:a);else{var m=d(i(a,(b||0)+1,c||1));this._d=new n(m[0],m[1]-1,m[2],e||0,f||0,h||0,l||0)}this._date=this._d,this._cached_date_ts=null,this._cached_date=[0,0,0],this._cached_utc_date_ts=null,this._cached_utc_date=[0,0,0]}var l=1721425.5,m=1948320.5,n=window.Date;k.prototype={_persianDate:function(){return this._cached_date_ts!=+this._d&&(this._cached_date_ts=+this._d,this._cached_date=f(c(this._d.getFullYear(),this._d.getMonth()+1,this._d.getDate()))),this._cached_date},_persianUTCDate:function(){return this._cached_utc_date_ts!=+this._d&&(this._cached_utc_date_ts=+this._d,this._cached_utc_date=f(c(this._d.getUTCFullYear(),this._d.getUTCMonth()+1,this._d.getUTCDate()))),this._cached_utc_date},_setPersianDate:function(a,b,c){var e=this._persianDate();e[a]=b,void 0!==c&&(e[2]=c);var f=d(i(e[0],e[1],e[2]));this._d.setFullYear(f[0]),this._d.setMonth(f[1]-1,f[2])},_setUTCPersianDate:function(a,b,c){var e=this._persianUTCDate();void 0!==c&&(e[2]=c),e[a]=b;var f=d(i(e[0],e[1],e[2]));this._d.setUTCFullYear(f[0]),this._d.setUTCMonth(f[1]-1,f[2])}},k.prototype.getDate=function(){return this._persianDate()[2]},k.prototype.getMonth=function(){return this._persianDate()[1]-1},k.prototype.getFullYear=function(){return this._persianDate()[0]},k.prototype.getUTCDate=function(){return this._persianUTCDate()[2]},k.prototype.getUTCMonth=function(){return this._persianUTCDate()[1]-1},k.prototype.getUTCFullYear=function(){return this._persianUTCDate()[0]},k.prototype.setDate=function(a){this._setPersianDate(2,a)},k.prototype.setFullYear=function(a){this._setPersianDate(0,a)},k.prototype.setMonth=function(a,b){this._setPersianDate(1,a+1,b)},k.prototype.setUTCDate=function(a){this._setUTCPersianDate(2,a)},k.prototype.setUTCFullYear=function(a){this._setUTCPersianDate(0,a)},k.prototype.setUTCMonth=function(a,b){this._setUTCPersianDate(1,a+1,b)},k.prototype.toLocaleString=function(){return this.getFullYear()+"/"+h(this.getMonth()+1)+"/"+h(this.getDate())+" "+h(this.getHours())+":"+h(this.getMinutes())+":"+h(this.getSeconds())},k.now=n.now,k.parse=function(a){new k(a).getTime()},k.UTC=function(a,b,c,e,f,g,h){var j=d(i(a,b+1,c));return n.UTC(j[0],j[1]-1,j[2],e||0,f||0,g||0,h||0)};var o,p="getHours getMilliseconds getMinutes getSeconds getTime getUTCDay getUTCHours getTimezoneOffset getUTCMilliseconds getUTCMinutes getUTCSeconds setHours setMilliseconds setMinutes setSeconds setTime setUTCHours setUTCMilliseconds setUTCMinutes setUTCSeconds toDateString toISOString toJSON toString toLocaleDateString toLocaleTimeString toTimeString toUTCString valueOf getDay".split(" "),q=function(a){return function(){return this._d[a].apply(this._d,arguments)}};for(o=0;oa?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چندین ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(a){return a.replace(/[۰-۹]/g,function(a){return c[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return b[a]}).replace(/,/g,"،")},ordinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,doy:12}})}),function(a){"use strict";if("function"==typeof define&&define.amd)define(["jquery","moment"],a);else if("object"==typeof exports)a(require("jquery"),require("moment"));else{if("undefined"==typeof jQuery)throw"bootstrap-datetimepicker requires jQuery to be loaded first";if("undefined"==typeof moment)throw"bootstrap-datetimepicker requires Moment.js to be loaded first";a(jQuery,moment)}}(function(a,b){"use strict";if(!b)throw new Error("bootstrap-datetimepicker requires Moment.js to be loaded first");var c=function(c,d){var e,f,g,h,i,j={},k=b().startOf("d"),l=k.clone(),m=!0,n=!1,o=!1,p=0,q=[{clsName:"days",navFnc:"M",navStep:1},{clsName:"months",navFnc:"y",navStep:1},{clsName:"years",navFnc:"y",navStep:10}],r=["days","months","years"],s=["top","bottom","auto"],t=["left","right","auto"],u=["default","top","bottom"],v={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"},w={},x=function(a){if("string"!=typeof a||a.length>1)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("").append("")),b.push(a("").append("").append("")),b.push(a("").append("").append("")),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)))),d.showExtraDateButtons?(b=[],b.push(a("
امروزفردا
آخر هفتهآخر ماه
اول هفته آیندهاول ماه آینده
").addClass("table-condensed").append(a("").append(b))):d.showExtraTimeButtons?(b=[],b.push(a("").append("").append("")),b.push(a("").append("").append("")),a("
صبحظهر
عصرشب
").addClass("table-condensed").append(a("").append(b))):a("
").addClass("table-condensed").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(){},showMinutes:function(){},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()),X()},tommorow:function(){W(b().add(1,"day")),X()},endOfWeek:function(){W(b().endOf("week")),X()},endOfMonth:function(){W(b().endOf("month")),X()},startOfNextWeek:function(){W(b().add(1,"week").startOf("week")),X()},startOfNextMonth:function(){W(b().add(1,"month").startOf("month")),X()},morning:function(){W(b().startOf("day").add(7,"hour")),X()},noon:function(){W(b().startOf("day").add(12,"hour")),X()},evening:function(){W(b().startOf("day").add(17,"hour")),X()},night:function(){W(b().startOf("day").add(21,"hour")),X()},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)},aa=function(){return o?X():_()},ba=function(a){return a=b.isMoment(a)||a instanceof Date?b(a):b(a,h,d.useStrict),a.locale(d.locale),a},ca=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())},da=function(a){w[a.which]="r",a.stopPropagation(),a.preventDefault()},ea=function(b){var c=a(b.target).val().trim(),d=c?ba(c):null;return W(d),b.stopImmediatePropagation(),!1},fa=function(){e.on({change:ea,blur:d.debug?"":X,keydown:ca,keyup:da}),c.is("input")?e.on({focus:_}):n&&(n.on("click",aa),n.on("mousedown",!1))},ga=function(){e.off({change:ea,blur:X,keydown:ca,keyup:da}),c.is("input")?e.off({focus:_}):n&&(n.off("click",aa),n.off("mousedown",!1))},ha=function(b){var c={};return a.each(b,function(){var a=ba(this);a.isValid()&&(c[a.format("YYYY-MM-DD")]=!0)}),Object.keys(c).length?c:!1},ia=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(),ga(),c.removeData("DateTimePicker"),c.removeData("date")},j.toggle=aa,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:ba(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&&ia(),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&&ia(),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=ha(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=ha(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=ba(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=ba(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&&(a=new pDate(a),a=b(a));var c=ba(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&&ia(),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"); 2 | 3 | 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.showExtraDateButtons=function(a){if(0===arguments.length)return d.showExtraDateButtons;if("boolean"!=typeof a)throw new TypeError("showExtraDateButtons() expects a boolean parameter");return d.showExtraDateButtons=a,o&&(X(),_()),j},j.showExtraTimeButtons=function(a){if(0===arguments.length)return d.showExtraTimeButtons;if("boolean"!=typeof a)throw new TypeError("showExtraTimeButtons() expects a boolean parameter");return d.showExtraTimeButtons=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.length)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").length?'[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),ia(),fa(),e.prop("disabled")&&j.disable(),e.is("input")&&0!==e.val().trim().length?W(ba(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-right",next:"glyphicon glyphicon-chevron-left",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,showExtraDateButtons:!1,showExtraTimeButtons:!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"))}},right:function(a){if(a){var c=this.date()||b();a.find(".datepicker").is(":visible")&&this.date(c.clone().subtract(1,"d"))}},left: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}}); -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-datetimepicker", 3 | "version": "4.7.14", 4 | "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"], 5 | "dependencies": { 6 | "jquery" : ">=1.8.3", 7 | "moment": ">=2.8.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eonasdan/bootstrap-datetimepicker", 3 | "type": "component", 4 | "version": "4.7.14", 5 | "description": "Date/time picker widget based on twitter bootstrap", 6 | "keywords": [ 7 | "bootstrap", 8 | "datetimepicker" 9 | ], 10 | "homepage": "http://eonasdan.github.io/bootstrap-datetimepicker/", 11 | "license": "MIT", 12 | "require": { 13 | "robloach/component-installer": "*", 14 | "components/jquery": ">=1.9.1", 15 | "moment/moment": ">=2.8" 16 | }, 17 | "extra": { 18 | "component": { 19 | "scripts": [ 20 | "src/js/bootstrap-datetimepicker.js" 21 | ], 22 | "files": [ 23 | "build/js/bootstrap-datetimepicker.min.js", 24 | "build/css/bootstrap-datetimepicker.css", 25 | "build/css/bootstrap-datetimepicker.min.css", 26 | "src/less/_bootstrap-datetimepicker.less", 27 | "src/less/bootstrap-datetimepicker-build.less" 28 | ] 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-persian-datetimepicker", 3 | "main": "build/js/bootstrap-persian-datetimepicker.js", 4 | "version": "4.7.143", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/beygi/bootstrap-persian-datetimepicker.git" 8 | }, 9 | "bugs": { 10 | "url": "https://github.com/beygi/bootstrap-persian-datetimepicker/issues" 11 | }, 12 | "keywords": [ 13 | "twitter-bootstrap", 14 | "bootstrap", 15 | "datepicker", 16 | "datetimepicker", 17 | "timepicker", 18 | "moment", 19 | "shamsi", 20 | "persian", 21 | "jalali" 22 | ], 23 | "dependencies": { 24 | "bootstrap": "^3.0", 25 | "jquery": "latest", 26 | "moment": "~2.8.2" 27 | }, 28 | "devDependencies": { 29 | "grunt": "latest", 30 | "grunt-contrib-concat": "^0.5.1", 31 | "grunt-contrib-jasmine": "^0.7.0", 32 | "grunt-contrib-jshint": "latest", 33 | "grunt-contrib-less": "latest", 34 | "grunt-contrib-uglify": "latest", 35 | "grunt-jscs": "latest", 36 | "grunt-string-replace": "latest", 37 | "load-grunt-tasks": "latest" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/js/bootstrap-datetimepicker.js: -------------------------------------------------------------------------------- 1 | /*! version : 4.7.14 2 | ========================================================= 3 | bootstrap-datetimejs 4 | https://github.com/Eonasdan/bootstrap-datetimepicker 5 | Copyright (c) 2015 Jonathan Peterson 6 | ========================================================= 7 | */ 8 | /* 9 | The MIT License (MIT) 10 | 11 | Copyright (c) 2015 Jonathan Peterson 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | THE SOFTWARE. 30 | */ 31 | /*global define:false */ 32 | /*global exports:false */ 33 | /*global require:false */ 34 | /*global jQuery:false */ 35 | /*global moment:false */ 36 | (function (factory) { 37 | 'use strict'; 38 | if (typeof define === 'function' && define.amd) { 39 | // AMD is used - Register as an anonymous module. 40 | define(['jquery', 'moment'], factory); 41 | } else if (typeof exports === 'object') { 42 | factory(require('jquery'), require('moment')); 43 | } else { 44 | // Neither AMD nor CommonJS used. Use global variables. 45 | if (typeof jQuery === 'undefined') { 46 | throw 'bootstrap-datetimepicker requires jQuery to be loaded first'; 47 | } 48 | if (typeof moment === 'undefined') { 49 | throw 'bootstrap-datetimepicker requires Moment.js to be loaded first'; 50 | } 51 | factory(jQuery, moment); 52 | } 53 | }(function ($, moment) { 54 | 'use strict'; 55 | if (!moment) { 56 | throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first'); 57 | } 58 | 59 | var dateTimePicker = function (element, options) { 60 | var picker = {}, 61 | date = moment().startOf('d'), 62 | viewDate = date.clone(), 63 | unset = true, 64 | input, 65 | component = false, 66 | widget = false, 67 | use24Hours, 68 | minViewModeNumber = 0, 69 | actualFormat, 70 | parseFormats, 71 | currentViewMode, 72 | datePickerModes = [ 73 | { 74 | clsName: 'days', 75 | navFnc: 'M', 76 | navStep: 1 77 | }, 78 | { 79 | clsName: 'months', 80 | navFnc: 'y', 81 | navStep: 1 82 | }, 83 | { 84 | clsName: 'years', 85 | navFnc: 'y', 86 | navStep: 10 87 | } 88 | ], 89 | viewModes = ['days', 'months', 'years'], 90 | verticalModes = ['top', 'bottom', 'auto'], 91 | horizontalModes = ['left', 'right', 'auto'], 92 | toolbarPlacements = ['default', 'top', 'bottom'], 93 | keyMap = { 94 | 'up': 38, 95 | 38: 'up', 96 | 'down': 40, 97 | 40: 'down', 98 | 'left': 37, 99 | 37: 'left', 100 | 'right': 39, 101 | 39: 'right', 102 | 'tab': 9, 103 | 9: 'tab', 104 | 'escape': 27, 105 | 27: 'escape', 106 | 'enter': 13, 107 | 13: 'enter', 108 | 'pageUp': 33, 109 | 33: 'pageUp', 110 | 'pageDown': 34, 111 | 34: 'pageDown', 112 | 'shift': 16, 113 | 16: 'shift', 114 | 'control': 17, 115 | 17: 'control', 116 | 'space': 32, 117 | 32: 'space', 118 | 't': 84, 119 | 84: 't', 120 | 'delete': 46, 121 | 46: 'delete' 122 | }, 123 | keyState = {}, 124 | 125 | /******************************************************************************** 126 | * 127 | * Private functions 128 | * 129 | ********************************************************************************/ 130 | isEnabled = function (granularity) { 131 | if (typeof granularity !== 'string' || granularity.length > 1) { 132 | throw new TypeError('isEnabled expects a single character string parameter'); 133 | } 134 | switch (granularity) { 135 | case 'y': 136 | return actualFormat.indexOf('Y') !== -1; 137 | case 'M': 138 | return actualFormat.indexOf('M') !== -1; 139 | case 'd': 140 | return actualFormat.toLowerCase().indexOf('d') !== -1; 141 | case 'h': 142 | case 'H': 143 | return actualFormat.toLowerCase().indexOf('h') !== -1; 144 | case 'm': 145 | return actualFormat.indexOf('m') !== -1; 146 | case 's': 147 | return actualFormat.indexOf('s') !== -1; 148 | default: 149 | return false; 150 | } 151 | }, 152 | 153 | hasTime = function () { 154 | return (isEnabled('h') || isEnabled('m') || isEnabled('s')); 155 | }, 156 | 157 | hasDate = function () { 158 | return (isEnabled('y') || isEnabled('M') || isEnabled('d')); 159 | }, 160 | 161 | getDatePickerTemplate = function () { 162 | var headTemplate = $('') 163 | .append($('') 164 | .append($('') 173 | .append($('') 174 | .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') 165 | .append($('').addClass(options.icons.previous)) 166 | ) 167 | .append($('').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5'))) 168 | .append($('').addClass('next').attr('data-action', 'next') 169 | .append($('').addClass(options.icons.next)) 170 | ) 171 | ), 172 | contTemplate = $('
').attr('colspan', (options.calendarWeeks ? '8' : '7'))) 175 | ); 176 | 177 | return [ 178 | $('
').addClass('datepicker-days') 179 | .append($('').addClass('table-condensed') 180 | .append(headTemplate) 181 | .append($('')) 182 | ), 183 | $('
').addClass('datepicker-months') 184 | .append($('
').addClass('table-condensed') 185 | .append(headTemplate.clone()) 186 | .append(contTemplate.clone()) 187 | ), 188 | $('
').addClass('datepicker-years') 189 | .append($('
').addClass('table-condensed') 190 | .append(headTemplate.clone()) 191 | .append(contTemplate.clone()) 192 | ) 193 | ]; 194 | }, 195 | 196 | getTimePickerMainTemplate = function () { 197 | var topRow = $(''), 198 | middleRow = $(''), 199 | bottomRow = $(''); 200 | 201 | if (isEnabled('h')) { 202 | topRow.append($('
') 203 | .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementHours') 204 | .append($('').addClass(options.icons.up)))); 205 | middleRow.append($('') 206 | .append($('').addClass('timepicker-hour').attr('data-time-component', 'hours').attr('data-action', 'showHours'))); 207 | bottomRow.append($('') 208 | .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementHours') 209 | .append($('').addClass(options.icons.down)))); 210 | } 211 | if (isEnabled('m')) { 212 | if (isEnabled('h')) { 213 | topRow.append($('').addClass('separator')); 214 | middleRow.append($('').addClass('separator').html(':')); 215 | bottomRow.append($('').addClass('separator')); 216 | } 217 | topRow.append($('') 218 | .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementMinutes') 219 | .append($('').addClass(options.icons.up)))); 220 | middleRow.append($('') 221 | .append($('').addClass('timepicker-minute').attr('data-time-component', 'minutes').attr('data-action', 'showMinutes'))); 222 | bottomRow.append($('') 223 | .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementMinutes') 224 | .append($('').addClass(options.icons.down)))); 225 | } 226 | if (isEnabled('s')) { 227 | if (isEnabled('m')) { 228 | topRow.append($('').addClass('separator')); 229 | middleRow.append($('').addClass('separator').html(':')); 230 | bottomRow.append($('').addClass('separator')); 231 | } 232 | topRow.append($('') 233 | .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'incrementSeconds') 234 | .append($('').addClass(options.icons.up)))); 235 | middleRow.append($('') 236 | .append($('').addClass('timepicker-second').attr('data-time-component', 'seconds').attr('data-action', 'showSeconds'))); 237 | bottomRow.append($('') 238 | .append($('').attr({href: '#', tabindex: '-1'}).addClass('btn').attr('data-action', 'decrementSeconds') 239 | .append($('').addClass(options.icons.down)))); 240 | } 241 | 242 | if (!use24Hours) { 243 | topRow.append($('').addClass('separator')); 244 | middleRow.append($('') 245 | .append($('').addClass('separator')); 247 | } 248 | 249 | return $('
').addClass('timepicker-picker') 250 | .append($('').addClass('table-condensed') 251 | .append([topRow, middleRow, bottomRow])); 252 | }, 253 | 254 | getTimePickerTemplate = function () { 255 | var hoursView = $('
').addClass('timepicker-hours') 256 | .append($('
').addClass('table-condensed')), 257 | minutesView = $('
').addClass('timepicker-minutes') 258 | .append($('
').addClass('table-condensed')), 259 | secondsView = $('
').addClass('timepicker-seconds') 260 | .append($('
').addClass('table-condensed')), 261 | ret = [getTimePickerMainTemplate()]; 262 | 263 | if (isEnabled('h')) { 264 | ret.push(hoursView); 265 | } 266 | if (isEnabled('m')) { 267 | ret.push(minutesView); 268 | } 269 | if (isEnabled('s')) { 270 | ret.push(secondsView); 271 | } 272 | 273 | return ret; 274 | }, 275 | 276 | getToolbar = function () { 277 | var row = []; 278 | if (options.showTodayButton) { 279 | row.push($('').append("").append("")); 293 | row.push($('').append("").append("")); 294 | row.push($('').append("").append("")); 295 | 296 | return $('
').append($('').attr('data-action', 'today').append($('').addClass(options.icons.today)))); 280 | } 281 | if (!options.sideBySide && hasDate() && hasTime()) { 282 | row.push($('').append($('').attr('data-action', 'togglePicker').append($('').addClass(options.icons.time)))); 283 | } 284 | if (options.showClear) { 285 | row.push($('').append($('').attr('data-action', 'clear').append($('').addClass(options.icons.clear)))); 286 | } 287 | if (options.showClose) { 288 | row.push($('').append($('').attr('data-action', 'close').append($('').addClass(options.icons.close)))); 289 | } 290 | if (options.showExtraDateButtons) { 291 | row = []; 292 | row.push($('
امروزفردا
آخر هفتهآخر ماه
اول هفته آیندهاول ماه آینده
').addClass('table-condensed').append($('').append(row)); 297 | } 298 | if (options.showExtraTimeButtons) { 299 | row = []; 300 | row.push($('').append("").append("")); 301 | row.push($('').append("").append("")); 302 | return $('
صبحظهر
عصرشب
').addClass('table-condensed').append($('').append(row)); 303 | } 304 | 305 | return $('
').addClass('table-condensed').append($('').append(row)); 306 | }, 307 | 308 | getTemplate = function () { 309 | var template = $('
').addClass('bootstrap-datetimepicker-widget dropdown-menu'), 310 | dateView = $('
').addClass('datepicker').append(getDatePickerTemplate()), 311 | timeView = $('
').addClass('timepicker').append(getTimePickerTemplate()), 312 | content = $('
    ').addClass('list-unstyled'), 313 | toolbar = $('
  • ').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar()); 314 | 315 | if (options.inline) { 316 | template.removeClass('dropdown-menu'); 317 | } 318 | 319 | if (use24Hours) { 320 | template.addClass('usetwentyfour'); 321 | } 322 | if (options.sideBySide && hasDate() && hasTime()) { 323 | template.addClass('timepicker-sbs'); 324 | template.append( 325 | $('
    ').addClass('row') 326 | .append(dateView.addClass('col-sm-6')) 327 | .append(timeView.addClass('col-sm-6')) 328 | ); 329 | template.append(toolbar); 330 | return template; 331 | } 332 | 333 | if (options.toolbarPlacement === 'top') { 334 | content.append(toolbar); 335 | } 336 | if (hasDate()) { 337 | content.append($('
  • ').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView)); 338 | } 339 | if (options.toolbarPlacement === 'default') { 340 | content.append(toolbar); 341 | } 342 | if (hasTime()) { 343 | content.append($('
  • ').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView)); 344 | } 345 | if (options.toolbarPlacement === 'bottom') { 346 | content.append(toolbar); 347 | } 348 | return template.append(content); 349 | }, 350 | 351 | dataToOptions = function () { 352 | var eData, 353 | dataOptions = {}; 354 | 355 | if (element.is('input') || options.inline) { 356 | eData = element.data(); 357 | } else { 358 | eData = element.find('input').data(); 359 | } 360 | 361 | if (eData.dateOptions && eData.dateOptions instanceof Object) { 362 | dataOptions = $.extend(true, dataOptions, eData.dateOptions); 363 | } 364 | 365 | $.each(options, function (key) { 366 | var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); 367 | if (eData[attributeName] !== undefined) { 368 | dataOptions[key] = eData[attributeName]; 369 | } 370 | }); 371 | return dataOptions; 372 | }, 373 | 374 | place = function () { 375 | var position = (component || element).position(), 376 | offset = (component || element).offset(), 377 | vertical = options.widgetPositioning.vertical, 378 | horizontal = options.widgetPositioning.horizontal, 379 | parent; 380 | 381 | if (options.widgetParent) { 382 | parent = options.widgetParent.append(widget); 383 | } else if (element.is('input')) { 384 | parent = element.parent().append(widget); 385 | } else if (options.inline) { 386 | parent = element.append(widget); 387 | return; 388 | } else { 389 | parent = element; 390 | element.children().first().after(widget); 391 | } 392 | 393 | // Top and bottom logic 394 | if (vertical === 'auto') { 395 | if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && 396 | widget.height() + element.outerHeight() < offset.top) { 397 | vertical = 'top'; 398 | } else { 399 | vertical = 'bottom'; 400 | } 401 | } 402 | 403 | // Left and right logic 404 | if (horizontal === 'auto') { 405 | if (parent.width() < offset.left + widget.outerWidth() / 2 && 406 | offset.left + widget.outerWidth() > $(window).width()) { 407 | horizontal = 'right'; 408 | } else { 409 | horizontal = 'left'; 410 | } 411 | } 412 | 413 | if (vertical === 'top') { 414 | widget.addClass('top').removeClass('bottom'); 415 | } else { 416 | widget.addClass('bottom').removeClass('top'); 417 | } 418 | 419 | if (horizontal === 'right') { 420 | widget.addClass('pull-right'); 421 | } else { 422 | widget.removeClass('pull-right'); 423 | } 424 | 425 | // find the first parent element that has a relative css positioning 426 | if (parent.css('position') !== 'relative') { 427 | parent = parent.parents().filter(function () { 428 | return $(this).css('position') === 'relative'; 429 | }).first(); 430 | } 431 | 432 | if (parent.length === 0) { 433 | throw new Error('datetimepicker component should be placed within a relative positioned container'); 434 | } 435 | 436 | widget.css({ 437 | top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(), 438 | bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto', 439 | left: horizontal === 'left' ? parent.css('padding-left') : 'auto', 440 | right: horizontal === 'left' ? 'auto' : parent.width() - element.outerWidth() 441 | }); 442 | }, 443 | 444 | notifyEvent = function (e) { 445 | if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) { 446 | return; 447 | } 448 | element.trigger(e); 449 | }, 450 | 451 | showMode = function (dir) { 452 | if (!widget) { 453 | return; 454 | } 455 | if (dir) { 456 | currentViewMode = Math.max(minViewModeNumber, Math.min(2, currentViewMode + dir)); 457 | } 458 | widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show(); 459 | }, 460 | 461 | fillDow = function () { 462 | var row = $('
'), 463 | currentDate = viewDate.clone().startOf('w'); 464 | 465 | if (options.calendarWeeks === true) { 466 | row.append($(''); 599 | if (options.calendarWeeks) { 600 | row.append(''); 601 | } 602 | html.push(row); 603 | } 604 | clsName = ''; 605 | if (currentDate.isBefore(viewDate, 'M')) { 606 | clsName += ' old'; 607 | } 608 | if (currentDate.isAfter(viewDate, 'M')) { 609 | clsName += ' new'; 610 | } 611 | if (currentDate.isSame(date, 'd') && !unset) { 612 | clsName += ' active'; 613 | } 614 | if (!isValid(currentDate, 'd')) { 615 | clsName += ' disabled'; 616 | } 617 | if (currentDate.isSame(moment(), 'd')) { 618 | clsName += ' today'; 619 | } 620 | if (currentDate.day() === 0 || currentDate.day() === 6) { 621 | clsName += ' weekend'; 622 | } 623 | row.append(''); 624 | currentDate.add(1, 'd'); 625 | } 626 | 627 | daysView.find('tbody').empty().append(html); 628 | 629 | updateMonths(); 630 | 631 | updateYears(); 632 | }, 633 | 634 | fillHours = function () { 635 | var table = widget.find('.timepicker-hours table'), 636 | currentHour = viewDate.clone().startOf('d'), 637 | html = [], 638 | row = $(''); 639 | 640 | if (viewDate.hour() > 11 && !use24Hours) { 641 | currentHour.hour(12); 642 | } 643 | while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) { 644 | if (currentHour.hour() % 4 === 0) { 645 | row = $(''); 646 | html.push(row); 647 | } 648 | row.append(''); 649 | currentHour.add(1, 'h'); 650 | } 651 | table.empty().append(html); 652 | }, 653 | 654 | fillMinutes = function () { 655 | var table = widget.find('.timepicker-minutes table'), 656 | currentMinute = viewDate.clone().startOf('h'), 657 | html = [], 658 | row = $(''), 659 | step = options.stepping === 1 ? 5 : options.stepping; 660 | 661 | while (viewDate.isSame(currentMinute, 'h')) { 662 | if (currentMinute.minute() % (step * 4) === 0) { 663 | row = $(''); 664 | html.push(row); 665 | } 666 | row.append(''); 667 | currentMinute.add(step, 'm'); 668 | } 669 | table.empty().append(html); 670 | }, 671 | 672 | fillSeconds = function () { 673 | var table = widget.find('.timepicker-seconds table'), 674 | currentSecond = viewDate.clone().startOf('m'), 675 | html = [], 676 | row = $(''); 677 | 678 | while (viewDate.isSame(currentSecond, 'm')) { 679 | if (currentSecond.second() % 20 === 0) { 680 | row = $(''); 681 | html.push(row); 682 | } 683 | row.append(''); 684 | currentSecond.add(5, 's'); 685 | } 686 | 687 | table.empty().append(html); 688 | }, 689 | 690 | fillTime = function () { 691 | var timeComponents = widget.find('.timepicker span[data-time-component]'); 692 | if (!use24Hours) { 693 | widget.find('.timepicker [data-action=togglePeriod]').text(date.format('A')); 694 | } 695 | timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh')); 696 | timeComponents.filter('[data-time-component=minutes]').text(date.format('mm')); 697 | timeComponents.filter('[data-time-component=seconds]').text(date.format('ss')); 698 | 699 | fillHours(); 700 | fillMinutes(); 701 | fillSeconds(); 702 | }, 703 | 704 | update = function () { 705 | if (!widget) { 706 | return; 707 | } 708 | fillDate(); 709 | fillTime(); 710 | }, 711 | 712 | setValue = function (targetMoment) { 713 | var oldDate = unset ? null : date; 714 | 715 | // case of calling setValue(null or false) 716 | if (!targetMoment) { 717 | unset = true; 718 | input.val(''); 719 | element.data('date', ''); 720 | notifyEvent({ 721 | type: 'dp.change', 722 | date: null, 723 | oldDate: oldDate 724 | }); 725 | update(); 726 | return; 727 | } 728 | 729 | targetMoment = targetMoment.clone().locale(options.locale); 730 | 731 | if (options.stepping !== 1) { 732 | targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0); 733 | } 734 | 735 | if (isValid(targetMoment)) { 736 | date = targetMoment; 737 | viewDate = date.clone(); 738 | input.val(date.format(actualFormat)); 739 | element.data('date', date.format(actualFormat)); 740 | update(); 741 | unset = false; 742 | notifyEvent({ 743 | type: 'dp.change', 744 | date: date.clone(), 745 | oldDate: oldDate 746 | }); 747 | } else { 748 | if (!options.keepInvalid) { 749 | input.val(unset ? '' : date.format(actualFormat)); 750 | } 751 | notifyEvent({ 752 | type: 'dp.error', 753 | date: targetMoment 754 | }); 755 | } 756 | }, 757 | 758 | hide = function () { 759 | //debug 760 | //return false; 761 | var transitioning = false; 762 | if (!widget) { 763 | return picker; 764 | } 765 | // Ignore event if in the middle of a picker transition 766 | widget.find('.collapse').each(function () { 767 | var collapseData = $(this).data('collapse'); 768 | if (collapseData && collapseData.transitioning) { 769 | transitioning = true; 770 | return false; 771 | } 772 | return true; 773 | }); 774 | if (transitioning) { 775 | return picker; 776 | } 777 | if (component && component.hasClass('btn')) { 778 | component.toggleClass('active'); 779 | } 780 | widget.hide(); 781 | 782 | $(window).off('resize', place); 783 | widget.off('click', '[data-action]'); 784 | widget.off('mousedown', false); 785 | 786 | widget.remove(); 787 | widget = false; 788 | 789 | notifyEvent({ 790 | type: 'dp.hide', 791 | date: date.clone() 792 | }); 793 | return picker; 794 | }, 795 | 796 | clear = function () { 797 | setValue(null); 798 | }, 799 | 800 | /******************************************************************************** 801 | * 802 | * Widget UI interaction functions 803 | * 804 | ********************************************************************************/ 805 | actions = { 806 | next: function () { 807 | viewDate.add(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc); 808 | fillDate(); 809 | }, 810 | 811 | previous: function () { 812 | viewDate.subtract(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc); 813 | fillDate(); 814 | }, 815 | 816 | pickerSwitch: function () { 817 | showMode(1); 818 | }, 819 | 820 | selectMonth: function (e) { 821 | var month = $(e.target).closest('tbody').find('span').index($(e.target)); 822 | viewDate.month(month); 823 | if (currentViewMode === minViewModeNumber) { 824 | setValue(date.clone().year(viewDate.year()).month(viewDate.month())); 825 | if (!options.inline) { 826 | hide(); 827 | } 828 | } else { 829 | showMode(-1); 830 | fillDate(); 831 | } 832 | }, 833 | 834 | selectYear: function (e) { 835 | var year = parseInt($(e.target).text(), 10) || 0; 836 | viewDate.year(year); 837 | if (currentViewMode === minViewModeNumber) { 838 | setValue(date.clone().year(viewDate.year())); 839 | if (!options.inline) { 840 | hide(); 841 | } 842 | } else { 843 | showMode(-1); 844 | fillDate(); 845 | } 846 | }, 847 | 848 | selectDay: function (e) { 849 | var day = viewDate.clone(); 850 | if ($(e.target).is('.old')) { 851 | day.subtract(1, 'M'); 852 | } 853 | if ($(e.target).is('.new')) { 854 | day.add(1, 'M'); 855 | } 856 | setValue(day.date(parseInt($(e.target).text(), 10))); 857 | if (!hasTime() && !options.keepOpen && !options.inline) { 858 | hide(); 859 | } 860 | }, 861 | 862 | incrementHours: function () { 863 | setValue(date.clone().add(1, 'h')); 864 | }, 865 | 866 | incrementMinutes: function () { 867 | setValue(date.clone().add(options.stepping, 'm')); 868 | }, 869 | 870 | incrementSeconds: function () { 871 | setValue(date.clone().add(1, 's')); 872 | }, 873 | 874 | decrementHours: function () { 875 | setValue(date.clone().subtract(1, 'h')); 876 | }, 877 | 878 | decrementMinutes: function () { 879 | setValue(date.clone().subtract(options.stepping, 'm')); 880 | }, 881 | 882 | decrementSeconds: function () { 883 | setValue(date.clone().subtract(1, 's')); 884 | }, 885 | 886 | togglePeriod: function () { 887 | setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h')); 888 | }, 889 | 890 | togglePicker: function (e) { 891 | var $this = $(e.target), 892 | $parent = $this.closest('ul'), 893 | expanded = $parent.find('.in'), 894 | closed = $parent.find('.collapse:not(.in)'), 895 | collapseData; 896 | 897 | if (expanded && expanded.length) { 898 | collapseData = expanded.data('collapse'); 899 | if (collapseData && collapseData.transitioning) { 900 | return; 901 | } 902 | if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it 903 | expanded.collapse('hide'); 904 | closed.collapse('show'); 905 | } else { // otherwise just toggle in class on the two views 906 | expanded.removeClass('in'); 907 | closed.addClass('in'); 908 | } 909 | if ($this.is('span')) { 910 | $this.toggleClass(options.icons.time + ' ' + options.icons.date); 911 | } else { 912 | $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); 913 | } 914 | 915 | // NOTE: uncomment if toggled state will be restored in show() 916 | //if (component) { 917 | // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); 918 | //} 919 | } 920 | }, 921 | 922 | showPicker: function () { 923 | widget.find('.timepicker > div:not(.timepicker-picker)').hide(); 924 | widget.find('.timepicker .timepicker-picker').show(); 925 | }, 926 | 927 | showHours: function () { 928 | //widget.find('.timepicker .timepicker-picker').hide(); 929 | //widget.find('.timepicker .timepicker-hours').show(); 930 | }, 931 | 932 | showMinutes: function () { 933 | // widget.find('.timepicker .timepicker-picker').hide(); 934 | // widget.find('.timepicker .timepicker-minutes').show(); 935 | }, 936 | 937 | showSeconds: function () { 938 | widget.find('.timepicker .timepicker-picker').hide(); 939 | widget.find('.timepicker .timepicker-seconds').show(); 940 | }, 941 | 942 | selectHour: function (e) { 943 | var hour = parseInt($(e.target).text(), 10); 944 | 945 | if (!use24Hours) { 946 | if (date.hours() >= 12) { 947 | if (hour !== 12) { 948 | hour += 12; 949 | } 950 | } else { 951 | if (hour === 12) { 952 | hour = 0; 953 | } 954 | } 955 | } 956 | setValue(date.clone().hours(hour)); 957 | actions.showPicker.call(picker); 958 | }, 959 | 960 | selectMinute: function (e) { 961 | setValue(date.clone().minutes(parseInt($(e.target).text(), 10))); 962 | actions.showPicker.call(picker); 963 | }, 964 | 965 | selectSecond: function (e) { 966 | setValue(date.clone().seconds(parseInt($(e.target).text(), 10))); 967 | actions.showPicker.call(picker); 968 | }, 969 | 970 | clear: clear, 971 | 972 | today: function () { 973 | setValue(moment()); 974 | hide(); 975 | }, 976 | tommorow: function () { 977 | setValue(moment().add(1, 'day')); 978 | hide(); 979 | }, 980 | endOfWeek : function(){ 981 | setValue(moment().endOf('week')); 982 | hide(); 983 | }, 984 | endOfMonth : function(){ 985 | setValue(moment().endOf('month')); 986 | hide(); 987 | }, 988 | startOfNextWeek: function(){ 989 | setValue(moment().add(1, 'week').startOf('week')); 990 | hide(); 991 | }, 992 | startOfNextMonth: function(){ 993 | setValue(moment().add(1, 'month').startOf('month')); 994 | hide(); 995 | }, 996 | morning: function(){ 997 | setValue(moment().startOf('day').add(7,'hour')); 998 | hide(); 999 | }, 1000 | noon: function(){ 1001 | setValue(moment().startOf('day').add(12,'hour')); 1002 | hide(); 1003 | }, 1004 | evening: function(){ 1005 | setValue(moment().startOf('day').add(17,'hour')); 1006 | hide(); 1007 | }, 1008 | night: function(){ 1009 | setValue(moment().startOf('day').add(21,'hour')); 1010 | hide(); 1011 | }, 1012 | 1013 | close: hide 1014 | }, 1015 | 1016 | doAction = function (e) { 1017 | if ($(e.currentTarget).is('.disabled')) { 1018 | return false; 1019 | } 1020 | actions[$(e.currentTarget).data('action')].apply(picker, arguments); 1021 | return false; 1022 | }, 1023 | 1024 | show = function () { 1025 | var currentMoment, 1026 | useCurrentGranularity = { 1027 | 'year': function (m) { 1028 | return m.month(0).date(1).hours(0).seconds(0).minutes(0); 1029 | }, 1030 | 'month': function (m) { 1031 | return m.date(1).hours(0).seconds(0).minutes(0); 1032 | }, 1033 | 'day': function (m) { 1034 | return m.hours(0).seconds(0).minutes(0); 1035 | }, 1036 | 'hour': function (m) { 1037 | return m.seconds(0).minutes(0); 1038 | }, 1039 | 'minute': function (m) { 1040 | return m.seconds(0); 1041 | } 1042 | }; 1043 | 1044 | if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) { 1045 | return picker; 1046 | } 1047 | if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) { 1048 | currentMoment = moment(); 1049 | if (typeof options.useCurrent === 'string') { 1050 | currentMoment = useCurrentGranularity[options.useCurrent](currentMoment); 1051 | } 1052 | setValue(currentMoment); 1053 | } 1054 | 1055 | widget = getTemplate(); 1056 | 1057 | fillDow(); 1058 | fillMonths(); 1059 | 1060 | widget.find('.timepicker-hours').hide(); 1061 | widget.find('.timepicker-minutes').hide(); 1062 | widget.find('.timepicker-seconds').hide(); 1063 | 1064 | update(); 1065 | showMode(); 1066 | 1067 | $(window).on('resize', place); 1068 | widget.on('click', '[data-action]', doAction); // this handles clicks on the widget 1069 | widget.on('mousedown', false); 1070 | 1071 | if (component && component.hasClass('btn')) { 1072 | component.toggleClass('active'); 1073 | } 1074 | widget.show(); 1075 | place(); 1076 | 1077 | if (!input.is(':focus')) { 1078 | input.focus(); 1079 | } 1080 | 1081 | notifyEvent({ 1082 | type: 'dp.show' 1083 | }); 1084 | return picker; 1085 | }, 1086 | 1087 | toggle = function () { 1088 | return (widget ? hide() : show()); 1089 | }, 1090 | 1091 | parseInputDate = function (inputDate) { 1092 | if (moment.isMoment(inputDate) || inputDate instanceof Date) { 1093 | inputDate = moment(inputDate); 1094 | } else { 1095 | inputDate = moment(inputDate, parseFormats, options.useStrict); 1096 | } 1097 | inputDate.locale(options.locale); 1098 | return inputDate; 1099 | }, 1100 | 1101 | keydown = function (e) { 1102 | //if (e.keyCode === 27 && widget) { // allow escape to hide picker 1103 | // hide(); 1104 | // return false; 1105 | //} 1106 | //if (e.keyCode === 40 && !widget) { // allow down to show picker 1107 | // show(); 1108 | // e.preventDefault(); 1109 | //} 1110 | //return true; 1111 | 1112 | var handler = null, 1113 | index, 1114 | index2, 1115 | pressedKeys = [], 1116 | pressedModifiers = {}, 1117 | currentKey = e.which, 1118 | keyBindKeys, 1119 | allModifiersPressed, 1120 | pressed = 'p'; 1121 | 1122 | keyState[currentKey] = pressed; 1123 | 1124 | for (index in keyState) { 1125 | if (keyState.hasOwnProperty(index) && keyState[index] === pressed) { 1126 | pressedKeys.push(index); 1127 | if (parseInt(index, 10) !== currentKey) { 1128 | pressedModifiers[index] = true; 1129 | } 1130 | } 1131 | } 1132 | 1133 | for (index in options.keyBinds) { 1134 | if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') { 1135 | keyBindKeys = index.split(' '); 1136 | if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) { 1137 | allModifiersPressed = true; 1138 | for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) { 1139 | if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) { 1140 | allModifiersPressed = false; 1141 | break; 1142 | } 1143 | } 1144 | if (allModifiersPressed) { 1145 | handler = options.keyBinds[index]; 1146 | break; 1147 | } 1148 | } 1149 | } 1150 | } 1151 | 1152 | if (handler) { 1153 | handler.call(picker, widget); 1154 | e.stopPropagation(); 1155 | e.preventDefault(); 1156 | } 1157 | }, 1158 | 1159 | keyup = function (e) { 1160 | keyState[e.which] = 'r'; 1161 | e.stopPropagation(); 1162 | e.preventDefault(); 1163 | }, 1164 | 1165 | change = function (e) { 1166 | var val = $(e.target).val().trim(), 1167 | parsedDate = val ? parseInputDate(val) : null; 1168 | setValue(parsedDate); 1169 | e.stopImmediatePropagation(); 1170 | return false; 1171 | }, 1172 | 1173 | attachDatePickerElementEvents = function () { 1174 | input.on({ 1175 | 'change': change, 1176 | 'blur': options.debug ? '' : hide, 1177 | 'keydown': keydown, 1178 | 'keyup': keyup 1179 | }); 1180 | 1181 | if (element.is('input')) { 1182 | input.on({ 1183 | 'focus': show 1184 | }); 1185 | } else if (component) { 1186 | component.on('click', toggle); 1187 | component.on('mousedown', false); 1188 | } 1189 | }, 1190 | 1191 | detachDatePickerElementEvents = function () { 1192 | input.off({ 1193 | 'change': change, 1194 | 'blur': hide, 1195 | 'keydown': keydown, 1196 | 'keyup': keyup 1197 | }); 1198 | 1199 | if (element.is('input')) { 1200 | input.off({ 1201 | 'focus': show 1202 | }); 1203 | } else if (component) { 1204 | component.off('click', toggle); 1205 | component.off('mousedown', false); 1206 | } 1207 | }, 1208 | 1209 | indexGivenDates = function (givenDatesArray) { 1210 | // Store given enabledDates and disabledDates as keys. 1211 | // This way we can check their existence in O(1) time instead of looping through whole array. 1212 | // (for example: options.enabledDates['2014-02-27'] === true) 1213 | var givenDatesIndexed = {}; 1214 | $.each(givenDatesArray, function () { 1215 | var dDate = parseInputDate(this); 1216 | if (dDate.isValid()) { 1217 | givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; 1218 | } 1219 | }); 1220 | return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false; 1221 | }, 1222 | 1223 | initFormatting = function () { 1224 | var format = options.format || 'L LT'; 1225 | 1226 | actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) { 1227 | var newinput = date.localeData().longDateFormat(formatInput) || formatInput; 1228 | return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740 1229 | return date.localeData().longDateFormat(formatInput2) || formatInput2; 1230 | }); 1231 | }); 1232 | 1233 | 1234 | parseFormats = options.extraFormats ? options.extraFormats.slice() : []; 1235 | if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) { 1236 | parseFormats.push(actualFormat); 1237 | } 1238 | 1239 | use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.indexOf('h') < 1); 1240 | 1241 | if (isEnabled('y')) { 1242 | minViewModeNumber = 2; 1243 | } 1244 | if (isEnabled('M')) { 1245 | minViewModeNumber = 1; 1246 | } 1247 | if (isEnabled('d')) { 1248 | minViewModeNumber = 0; 1249 | } 1250 | 1251 | currentViewMode = Math.max(minViewModeNumber, currentViewMode); 1252 | 1253 | if (!unset) { 1254 | setValue(date); 1255 | } 1256 | }; 1257 | 1258 | /******************************************************************************** 1259 | * 1260 | * Public API functions 1261 | * ===================== 1262 | * 1263 | * Important: Do not expose direct references to private objects or the options 1264 | * object to the outer world. Always return a clone when returning values or make 1265 | * a clone when setting a private variable. 1266 | * 1267 | ********************************************************************************/ 1268 | picker.destroy = function () { 1269 | hide(); 1270 | detachDatePickerElementEvents(); 1271 | element.removeData('DateTimePicker'); 1272 | element.removeData('date'); 1273 | }; 1274 | 1275 | picker.toggle = toggle; 1276 | 1277 | picker.show = show; 1278 | 1279 | picker.hide = hide; 1280 | 1281 | picker.disable = function () { 1282 | hide(); 1283 | if (component && component.hasClass('btn')) { 1284 | component.addClass('disabled'); 1285 | } 1286 | input.prop('disabled', true); 1287 | return picker; 1288 | }; 1289 | 1290 | picker.enable = function () { 1291 | if (component && component.hasClass('btn')) { 1292 | component.removeClass('disabled'); 1293 | } 1294 | input.prop('disabled', false); 1295 | return picker; 1296 | }; 1297 | 1298 | picker.ignoreReadonly = function (ignoreReadonly) { 1299 | if (arguments.length === 0) { 1300 | return options.ignoreReadonly; 1301 | } 1302 | if (typeof ignoreReadonly !== 'boolean') { 1303 | throw new TypeError('ignoreReadonly () expects a boolean parameter'); 1304 | } 1305 | options.ignoreReadonly = ignoreReadonly; 1306 | return picker; 1307 | }; 1308 | 1309 | picker.options = function (newOptions) { 1310 | if (arguments.length === 0) { 1311 | return $.extend(true, {}, options); 1312 | } 1313 | 1314 | if (!(newOptions instanceof Object)) { 1315 | throw new TypeError('options() options parameter should be an object'); 1316 | } 1317 | $.extend(true, options, newOptions); 1318 | $.each(options, function (key, value) { 1319 | if (picker[key] !== undefined) { 1320 | picker[key](value); 1321 | } else { 1322 | throw new TypeError('option ' + key + ' is not recognized!'); 1323 | } 1324 | }); 1325 | return picker; 1326 | }; 1327 | 1328 | picker.date = function (newDate) { 1329 | if (arguments.length === 0) { 1330 | if (unset) { 1331 | return null; 1332 | } 1333 | return date.clone(); 1334 | } 1335 | 1336 | if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { 1337 | throw new TypeError('date() parameter must be one of [null, string, moment or Date]'); 1338 | } 1339 | 1340 | setValue(newDate === null ? null : parseInputDate(newDate)); 1341 | return picker; 1342 | }; 1343 | 1344 | picker.format = function (newFormat) { 1345 | if (arguments.length === 0) { 1346 | return options.format; 1347 | } 1348 | 1349 | if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) { 1350 | throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat); 1351 | } 1352 | 1353 | options.format = newFormat; 1354 | if (actualFormat) { 1355 | initFormatting(); // reinit formatting 1356 | } 1357 | return picker; 1358 | }; 1359 | 1360 | picker.dayViewHeaderFormat = function (newFormat) { 1361 | if (arguments.length === 0) { 1362 | return options.dayViewHeaderFormat; 1363 | } 1364 | 1365 | if (typeof newFormat !== 'string') { 1366 | throw new TypeError('dayViewHeaderFormat() expects a string parameter'); 1367 | } 1368 | 1369 | options.dayViewHeaderFormat = newFormat; 1370 | return picker; 1371 | }; 1372 | 1373 | picker.extraFormats = function (formats) { 1374 | if (arguments.length === 0) { 1375 | return options.extraFormats; 1376 | } 1377 | 1378 | if (formats !== false && !(formats instanceof Array)) { 1379 | throw new TypeError('extraFormats() expects an array or false parameter'); 1380 | } 1381 | 1382 | options.extraFormats = formats; 1383 | if (parseFormats) { 1384 | initFormatting(); // reinit formatting 1385 | } 1386 | return picker; 1387 | }; 1388 | 1389 | picker.disabledDates = function (dates) { 1390 | if (arguments.length === 0) { 1391 | return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates); 1392 | } 1393 | 1394 | if (!dates) { 1395 | options.disabledDates = false; 1396 | update(); 1397 | return picker; 1398 | } 1399 | if (!(dates instanceof Array)) { 1400 | throw new TypeError('disabledDates() expects an array parameter'); 1401 | } 1402 | options.disabledDates = indexGivenDates(dates); 1403 | options.enabledDates = false; 1404 | update(); 1405 | return picker; 1406 | }; 1407 | 1408 | picker.enabledDates = function (dates) { 1409 | if (arguments.length === 0) { 1410 | return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates); 1411 | } 1412 | 1413 | if (!dates) { 1414 | options.enabledDates = false; 1415 | update(); 1416 | return picker; 1417 | } 1418 | if (!(dates instanceof Array)) { 1419 | throw new TypeError('enabledDates() expects an array parameter'); 1420 | } 1421 | options.enabledDates = indexGivenDates(dates); 1422 | options.disabledDates = false; 1423 | update(); 1424 | return picker; 1425 | }; 1426 | 1427 | picker.daysOfWeekDisabled = function (daysOfWeekDisabled) { 1428 | if (arguments.length === 0) { 1429 | return options.daysOfWeekDisabled.splice(0); 1430 | } 1431 | 1432 | if (!(daysOfWeekDisabled instanceof Array)) { 1433 | throw new TypeError('daysOfWeekDisabled() expects an array parameter'); 1434 | } 1435 | options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) { 1436 | currentValue = parseInt(currentValue, 10); 1437 | if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) { 1438 | return previousValue; 1439 | } 1440 | if (previousValue.indexOf(currentValue) === -1) { 1441 | previousValue.push(currentValue); 1442 | } 1443 | return previousValue; 1444 | }, []).sort(); 1445 | update(); 1446 | return picker; 1447 | }; 1448 | 1449 | picker.maxDate = function (maxDate) { 1450 | if (arguments.length === 0) { 1451 | return options.maxDate ? options.maxDate.clone() : options.maxDate; 1452 | } 1453 | 1454 | if ((typeof maxDate === 'boolean') && maxDate === false) { 1455 | options.maxDate = false; 1456 | update(); 1457 | return picker; 1458 | } 1459 | 1460 | if (typeof maxDate === 'string') { 1461 | if (maxDate === 'now' || maxDate === 'moment') { 1462 | maxDate = moment(); 1463 | } 1464 | } 1465 | 1466 | var parsedDate = parseInputDate(maxDate); 1467 | 1468 | if (!parsedDate.isValid()) { 1469 | throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate); 1470 | } 1471 | if (options.minDate && parsedDate.isBefore(options.minDate)) { 1472 | throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat)); 1473 | } 1474 | options.maxDate = parsedDate; 1475 | if (options.maxDate.isBefore(maxDate)) { 1476 | setValue(options.maxDate); 1477 | } 1478 | if (viewDate.isAfter(parsedDate)) { 1479 | viewDate = parsedDate.clone(); 1480 | } 1481 | update(); 1482 | return picker; 1483 | }; 1484 | 1485 | picker.minDate = function (minDate) { 1486 | if (arguments.length === 0) { 1487 | return options.minDate ? options.minDate.clone() : options.minDate; 1488 | } 1489 | 1490 | if ((typeof minDate === 'boolean') && minDate === false) { 1491 | options.minDate = false; 1492 | update(); 1493 | return picker; 1494 | } 1495 | 1496 | if (typeof minDate === 'string') { 1497 | if (minDate === 'now' || minDate === 'moment') { 1498 | minDate = moment(); 1499 | } 1500 | } 1501 | 1502 | var parsedDate = parseInputDate(minDate); 1503 | 1504 | if (!parsedDate.isValid()) { 1505 | throw new TypeError('minDate() Could not parse date parameter: ' + minDate); 1506 | } 1507 | if (options.maxDate && parsedDate.isAfter(options.maxDate)) { 1508 | throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat)); 1509 | } 1510 | options.minDate = parsedDate; 1511 | if (options.minDate.isAfter(minDate)) { 1512 | setValue(options.minDate); 1513 | } 1514 | if (viewDate.isBefore(parsedDate)) { 1515 | viewDate = parsedDate.clone(); 1516 | } 1517 | update(); 1518 | return picker; 1519 | }; 1520 | 1521 | picker.defaultDate = function (defaultDate) { 1522 | if (arguments.length === 0) { 1523 | return options.defaultDate ? options.defaultDate.clone() : options.defaultDate; 1524 | } 1525 | if (!defaultDate) { 1526 | options.defaultDate = false; 1527 | return picker; 1528 | } 1529 | 1530 | if (typeof defaultDate === 'string') { 1531 | defaultDate = new pDate(defaultDate); 1532 | defaultDate = moment(defaultDate); 1533 | } 1534 | 1535 | var parsedDate = parseInputDate(defaultDate); 1536 | if (!parsedDate.isValid()) { 1537 | throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate); 1538 | } 1539 | if (!isValid(parsedDate)) { 1540 | throw new TypeError('defaultDate() date passed is invalid according to component setup validations'); 1541 | } 1542 | 1543 | options.defaultDate = parsedDate; 1544 | 1545 | if (options.defaultDate && input.val().trim() === '' && input.attr('placeholder') === undefined) { 1546 | setValue(options.defaultDate); 1547 | } 1548 | return picker; 1549 | }; 1550 | 1551 | picker.locale = function (locale) { 1552 | if (arguments.length === 0) { 1553 | return options.locale; 1554 | } 1555 | 1556 | if (!moment.localeData(locale)) { 1557 | throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!'); 1558 | } 1559 | 1560 | options.locale = locale; 1561 | date.locale(options.locale); 1562 | viewDate.locale(options.locale); 1563 | 1564 | if (actualFormat) { 1565 | initFormatting(); // reinit formatting 1566 | } 1567 | if (widget) { 1568 | hide(); 1569 | show(); 1570 | } 1571 | return picker; 1572 | }; 1573 | 1574 | picker.stepping = function (stepping) { 1575 | if (arguments.length === 0) { 1576 | return options.stepping; 1577 | } 1578 | 1579 | stepping = parseInt(stepping, 10); 1580 | if (isNaN(stepping) || stepping < 1) { 1581 | stepping = 1; 1582 | } 1583 | options.stepping = stepping; 1584 | return picker; 1585 | }; 1586 | 1587 | picker.useCurrent = function (useCurrent) { 1588 | var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; 1589 | if (arguments.length === 0) { 1590 | return options.useCurrent; 1591 | } 1592 | 1593 | if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) { 1594 | throw new TypeError('useCurrent() expects a boolean or string parameter'); 1595 | } 1596 | if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) { 1597 | throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', ')); 1598 | } 1599 | options.useCurrent = useCurrent; 1600 | return picker; 1601 | }; 1602 | 1603 | picker.collapse = function (collapse) { 1604 | if (arguments.length === 0) { 1605 | return options.collapse; 1606 | } 1607 | 1608 | if (typeof collapse !== 'boolean') { 1609 | throw new TypeError('collapse() expects a boolean parameter'); 1610 | } 1611 | if (options.collapse === collapse) { 1612 | return picker; 1613 | } 1614 | options.collapse = collapse; 1615 | if (widget) { 1616 | hide(); 1617 | show(); 1618 | } 1619 | return picker; 1620 | }; 1621 | 1622 | picker.icons = function (icons) { 1623 | if (arguments.length === 0) { 1624 | return $.extend({}, options.icons); 1625 | } 1626 | 1627 | if (!(icons instanceof Object)) { 1628 | throw new TypeError('icons() expects parameter to be an Object'); 1629 | } 1630 | $.extend(options.icons, icons); 1631 | if (widget) { 1632 | hide(); 1633 | show(); 1634 | } 1635 | return picker; 1636 | }; 1637 | 1638 | picker.useStrict = function (useStrict) { 1639 | if (arguments.length === 0) { 1640 | return options.useStrict; 1641 | } 1642 | 1643 | if (typeof useStrict !== 'boolean') { 1644 | throw new TypeError('useStrict() expects a boolean parameter'); 1645 | } 1646 | options.useStrict = useStrict; 1647 | return picker; 1648 | }; 1649 | 1650 | picker.sideBySide = function (sideBySide) { 1651 | if (arguments.length === 0) { 1652 | return options.sideBySide; 1653 | } 1654 | 1655 | if (typeof sideBySide !== 'boolean') { 1656 | throw new TypeError('sideBySide() expects a boolean parameter'); 1657 | } 1658 | options.sideBySide = sideBySide; 1659 | if (widget) { 1660 | hide(); 1661 | show(); 1662 | } 1663 | return picker; 1664 | }; 1665 | 1666 | picker.viewMode = function (viewMode) { 1667 | if (arguments.length === 0) { 1668 | return options.viewMode; 1669 | } 1670 | 1671 | if (typeof viewMode !== 'string') { 1672 | throw new TypeError('viewMode() expects a string parameter'); 1673 | } 1674 | 1675 | if (viewModes.indexOf(viewMode) === -1) { 1676 | throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value'); 1677 | } 1678 | 1679 | options.viewMode = viewMode; 1680 | currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber); 1681 | 1682 | showMode(); 1683 | return picker; 1684 | }; 1685 | 1686 | picker.toolbarPlacement = function (toolbarPlacement) { 1687 | if (arguments.length === 0) { 1688 | return options.toolbarPlacement; 1689 | } 1690 | 1691 | if (typeof toolbarPlacement !== 'string') { 1692 | throw new TypeError('toolbarPlacement() expects a string parameter'); 1693 | } 1694 | if (toolbarPlacements.indexOf(toolbarPlacement) === -1) { 1695 | throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value'); 1696 | } 1697 | options.toolbarPlacement = toolbarPlacement; 1698 | 1699 | if (widget) { 1700 | hide(); 1701 | show(); 1702 | } 1703 | return picker; 1704 | }; 1705 | 1706 | picker.widgetPositioning = function (widgetPositioning) { 1707 | if (arguments.length === 0) { 1708 | return $.extend({}, options.widgetPositioning); 1709 | } 1710 | 1711 | if (({}).toString.call(widgetPositioning) !== '[object Object]') { 1712 | throw new TypeError('widgetPositioning() expects an object variable'); 1713 | } 1714 | if (widgetPositioning.horizontal) { 1715 | if (typeof widgetPositioning.horizontal !== 'string') { 1716 | throw new TypeError('widgetPositioning() horizontal variable must be a string'); 1717 | } 1718 | widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase(); 1719 | if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) { 1720 | throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')'); 1721 | } 1722 | options.widgetPositioning.horizontal = widgetPositioning.horizontal; 1723 | } 1724 | if (widgetPositioning.vertical) { 1725 | if (typeof widgetPositioning.vertical !== 'string') { 1726 | throw new TypeError('widgetPositioning() vertical variable must be a string'); 1727 | } 1728 | widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase(); 1729 | if (verticalModes.indexOf(widgetPositioning.vertical) === -1) { 1730 | throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')'); 1731 | } 1732 | options.widgetPositioning.vertical = widgetPositioning.vertical; 1733 | } 1734 | update(); 1735 | return picker; 1736 | }; 1737 | 1738 | picker.calendarWeeks = function (calendarWeeks) { 1739 | if (arguments.length === 0) { 1740 | return options.calendarWeeks; 1741 | } 1742 | 1743 | if (typeof calendarWeeks !== 'boolean') { 1744 | throw new TypeError('calendarWeeks() expects parameter to be a boolean value'); 1745 | } 1746 | 1747 | options.calendarWeeks = calendarWeeks; 1748 | update(); 1749 | return picker; 1750 | }; 1751 | 1752 | picker.showTodayButton = function (showTodayButton) { 1753 | if (arguments.length === 0) { 1754 | return options.showTodayButton; 1755 | } 1756 | 1757 | if (typeof showTodayButton !== 'boolean') { 1758 | throw new TypeError('showTodayButton() expects a boolean parameter'); 1759 | } 1760 | 1761 | options.showTodayButton = showTodayButton; 1762 | if (widget) { 1763 | hide(); 1764 | show(); 1765 | } 1766 | return picker; 1767 | }; 1768 | 1769 | picker.showExtraDateButtons = function (showExtraDateButtons) { 1770 | if (arguments.length === 0) { 1771 | return options.showExtraDateButtons; 1772 | } 1773 | 1774 | if (typeof showExtraDateButtons !== 'boolean') { 1775 | throw new TypeError('showExtraDateButtons() expects a boolean parameter'); 1776 | } 1777 | 1778 | options.showExtraDateButtons = showExtraDateButtons; 1779 | if (widget) { 1780 | hide(); 1781 | show(); 1782 | } 1783 | return picker; 1784 | }; 1785 | 1786 | picker.showExtraTimeButtons = function (showExtraTimeButtons) { 1787 | if (arguments.length === 0) { 1788 | return options.showExtraTimeButtons; 1789 | } 1790 | 1791 | if (typeof showExtraTimeButtons !== 'boolean') { 1792 | throw new TypeError('showExtraTimeButtons() expects a boolean parameter'); 1793 | } 1794 | 1795 | options.showExtraTimeButtons = showExtraTimeButtons; 1796 | if (widget) { 1797 | hide(); 1798 | show(); 1799 | } 1800 | return picker; 1801 | }; 1802 | 1803 | picker.showClear = function (showClear) { 1804 | if (arguments.length === 0) { 1805 | return options.showClear; 1806 | } 1807 | 1808 | if (typeof showClear !== 'boolean') { 1809 | throw new TypeError('showClear() expects a boolean parameter'); 1810 | } 1811 | 1812 | options.showClear = showClear; 1813 | if (widget) { 1814 | hide(); 1815 | show(); 1816 | } 1817 | return picker; 1818 | }; 1819 | 1820 | picker.widgetParent = function (widgetParent) { 1821 | if (arguments.length === 0) { 1822 | return options.widgetParent; 1823 | } 1824 | 1825 | if (typeof widgetParent === 'string') { 1826 | widgetParent = $(widgetParent); 1827 | } 1828 | 1829 | if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) { 1830 | throw new TypeError('widgetParent() expects a string or a jQuery object parameter'); 1831 | } 1832 | 1833 | options.widgetParent = widgetParent; 1834 | if (widget) { 1835 | hide(); 1836 | show(); 1837 | } 1838 | return picker; 1839 | }; 1840 | 1841 | picker.keepOpen = function (keepOpen) { 1842 | if (arguments.length === 0) { 1843 | return options.keepOpen; 1844 | } 1845 | 1846 | if (typeof keepOpen !== 'boolean') { 1847 | throw new TypeError('keepOpen() expects a boolean parameter'); 1848 | } 1849 | 1850 | options.keepOpen = keepOpen; 1851 | return picker; 1852 | }; 1853 | 1854 | picker.inline = function (inline) { 1855 | if (arguments.length === 0) { 1856 | return options.inline; 1857 | } 1858 | 1859 | if (typeof inline !== 'boolean') { 1860 | throw new TypeError('inline() expects a boolean parameter'); 1861 | } 1862 | 1863 | options.inline = inline; 1864 | return picker; 1865 | }; 1866 | 1867 | picker.clear = function () { 1868 | clear(); 1869 | return picker; 1870 | }; 1871 | 1872 | picker.keyBinds = function (keyBinds) { 1873 | options.keyBinds = keyBinds; 1874 | return picker; 1875 | }; 1876 | 1877 | picker.debug = function (debug) { 1878 | if (typeof debug !== 'boolean') { 1879 | throw new TypeError('debug() expects a boolean parameter'); 1880 | } 1881 | 1882 | options.debug = debug; 1883 | return picker; 1884 | }; 1885 | 1886 | picker.showClose = function (showClose) { 1887 | if (arguments.length === 0) { 1888 | return options.showClose; 1889 | } 1890 | 1891 | if (typeof showClose !== 'boolean') { 1892 | throw new TypeError('showClose() expects a boolean parameter'); 1893 | } 1894 | 1895 | options.showClose = showClose; 1896 | return picker; 1897 | }; 1898 | 1899 | picker.keepInvalid = function (keepInvalid) { 1900 | if (arguments.length === 0) { 1901 | return options.keepInvalid; 1902 | } 1903 | 1904 | if (typeof keepInvalid !== 'boolean') { 1905 | throw new TypeError('keepInvalid() expects a boolean parameter'); 1906 | } 1907 | options.keepInvalid = keepInvalid; 1908 | return picker; 1909 | }; 1910 | 1911 | picker.datepickerInput = function (datepickerInput) { 1912 | if (arguments.length === 0) { 1913 | return options.datepickerInput; 1914 | } 1915 | 1916 | if (typeof datepickerInput !== 'string') { 1917 | throw new TypeError('datepickerInput() expects a string parameter'); 1918 | } 1919 | 1920 | options.datepickerInput = datepickerInput; 1921 | return picker; 1922 | }; 1923 | 1924 | // initializing element and component attributes 1925 | if (element.is('input')) { 1926 | input = element; 1927 | } else { 1928 | input = element.find(options.datepickerInput); 1929 | if (input.size() === 0) { 1930 | input = element.find('input'); 1931 | } else if (!input.is('input')) { 1932 | throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element'); 1933 | } 1934 | } 1935 | 1936 | if (element.hasClass('input-group')) { 1937 | // in case there is more then one 'input-group-addon' Issue #48 1938 | if (element.find('.datepickerbutton').size() === 0) { 1939 | component = element.find('[class^="input-group-"]'); 1940 | } else { 1941 | component = element.find('.datepickerbutton'); 1942 | } 1943 | } 1944 | 1945 | if (!options.inline && !input.is('input')) { 1946 | throw new Error('Could not initialize DateTimePicker without an input element'); 1947 | } 1948 | 1949 | $.extend(true, options, dataToOptions()); 1950 | 1951 | picker.options(options); 1952 | 1953 | initFormatting(); 1954 | 1955 | attachDatePickerElementEvents(); 1956 | 1957 | if (input.prop('disabled')) { 1958 | picker.disable(); 1959 | } 1960 | if (input.is('input') && input.val().trim().length !== 0) { 1961 | setValue(parseInputDate(input.val().trim())); 1962 | } 1963 | else if (options.defaultDate && input.attr('placeholder') === undefined) { 1964 | setValue(options.defaultDate); 1965 | } 1966 | if (options.inline) { 1967 | show(); 1968 | } 1969 | return picker; 1970 | }; 1971 | 1972 | /******************************************************************************** 1973 | * 1974 | * jQuery plugin constructor and defaults object 1975 | * 1976 | ********************************************************************************/ 1977 | 1978 | $.fn.datetimepicker = function (options) { 1979 | return this.each(function () { 1980 | var $this = $(this); 1981 | if (!$this.data('DateTimePicker')) { 1982 | // create a private copy of the defaults object 1983 | options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); 1984 | $this.data('DateTimePicker', dateTimePicker($this, options)); 1985 | } 1986 | }); 1987 | }; 1988 | 1989 | $.fn.datetimepicker.defaults = { 1990 | format: false, 1991 | dayViewHeaderFormat: 'MMMM YYYY', 1992 | extraFormats: false, 1993 | stepping: 1, 1994 | minDate: false, 1995 | maxDate: false, 1996 | useCurrent: true, 1997 | collapse: true, 1998 | locale: moment.locale(), 1999 | defaultDate: false, 2000 | disabledDates: false, 2001 | enabledDates: false, 2002 | icons: { 2003 | time: 'glyphicon glyphicon-time', 2004 | date: 'glyphicon glyphicon-calendar', 2005 | up: 'glyphicon glyphicon-chevron-up', 2006 | down: 'glyphicon glyphicon-chevron-down', 2007 | previous: 'glyphicon glyphicon-chevron-right', 2008 | next: 'glyphicon glyphicon-chevron-left', 2009 | today: 'glyphicon glyphicon-screenshot', 2010 | clear: 'glyphicon glyphicon-trash', 2011 | close: 'glyphicon glyphicon-remove' 2012 | }, 2013 | useStrict: false, 2014 | sideBySide: false, 2015 | daysOfWeekDisabled: [], 2016 | calendarWeeks: false, 2017 | viewMode: 'days', 2018 | toolbarPlacement: 'default', 2019 | showTodayButton: false, 2020 | showExtraDateButtons: false, 2021 | showExtraTimeButtons: false, 2022 | showClear: false, 2023 | showClose: false, 2024 | widgetPositioning: { 2025 | horizontal: 'auto', 2026 | vertical: 'auto' 2027 | }, 2028 | widgetParent: null, 2029 | ignoreReadonly: false, 2030 | keepOpen: false, 2031 | inline: false, 2032 | keepInvalid: false, 2033 | datepickerInput: '.datepickerinput', 2034 | keyBinds: { 2035 | up: function (widget) { 2036 | if (!widget) { 2037 | return; 2038 | } 2039 | var d = this.date() || moment(); 2040 | if (widget.find('.datepicker').is(':visible')) { 2041 | this.date(d.clone().subtract(7, 'd')); 2042 | } else { 2043 | this.date(d.clone().add(1, 'm')); 2044 | } 2045 | }, 2046 | down: function (widget) { 2047 | if (!widget) { 2048 | this.show(); 2049 | return; 2050 | } 2051 | var d = this.date() || moment(); 2052 | if (widget.find('.datepicker').is(':visible')) { 2053 | this.date(d.clone().add(7, 'd')); 2054 | } else { 2055 | this.date(d.clone().subtract(1, 'm')); 2056 | } 2057 | }, 2058 | 'control up': function (widget) { 2059 | if (!widget) { 2060 | return; 2061 | } 2062 | var d = this.date() || moment(); 2063 | if (widget.find('.datepicker').is(':visible')) { 2064 | this.date(d.clone().subtract(1, 'y')); 2065 | } else { 2066 | this.date(d.clone().add(1, 'h')); 2067 | } 2068 | }, 2069 | 'control down': function (widget) { 2070 | if (!widget) { 2071 | return; 2072 | } 2073 | var d = this.date() || moment(); 2074 | if (widget.find('.datepicker').is(':visible')) { 2075 | this.date(d.clone().add(1, 'y')); 2076 | } else { 2077 | this.date(d.clone().subtract(1, 'h')); 2078 | } 2079 | }, 2080 | right: function (widget) { 2081 | if (!widget) { 2082 | return; 2083 | } 2084 | var d = this.date() || moment(); 2085 | if (widget.find('.datepicker').is(':visible')) { 2086 | this.date(d.clone().subtract(1, 'd')); 2087 | } 2088 | }, 2089 | left: function (widget) { 2090 | if (!widget) { 2091 | return; 2092 | } 2093 | var d = this.date() || moment(); 2094 | if (widget.find('.datepicker').is(':visible')) { 2095 | this.date(d.clone().add(1, 'd')); 2096 | } 2097 | }, 2098 | pageUp: function (widget) { 2099 | if (!widget) { 2100 | return; 2101 | } 2102 | var d = this.date() || moment(); 2103 | if (widget.find('.datepicker').is(':visible')) { 2104 | this.date(d.clone().subtract(1, 'M')); 2105 | } 2106 | }, 2107 | pageDown: function (widget) { 2108 | if (!widget) { 2109 | return; 2110 | } 2111 | var d = this.date() || moment(); 2112 | if (widget.find('.datepicker').is(':visible')) { 2113 | this.date(d.clone().add(1, 'M')); 2114 | } 2115 | }, 2116 | enter: function () { 2117 | this.hide(); 2118 | }, 2119 | escape: function () { 2120 | this.hide(); 2121 | }, 2122 | //tab: function (widget) { //this break the flow of the form. disabling for now 2123 | // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]'); 2124 | // if(toggle.length > 0) toggle.click(); 2125 | //}, 2126 | 'control space': function (widget) { 2127 | if (widget.find('.timepicker').is(':visible')) { 2128 | widget.find('.btn[data-action="togglePeriod"]').click(); 2129 | } 2130 | }, 2131 | t: function () { 2132 | this.date(moment()); 2133 | }, 2134 | 'delete': function () { 2135 | this.clear(); 2136 | } 2137 | }, 2138 | debug: false 2139 | }; 2140 | })); 2141 | -------------------------------------------------------------------------------- /src/js/fa.js: -------------------------------------------------------------------------------- 1 | // moment.js locale configuration 2 | (function (factory) { 3 | if (typeof define === 'function' && define.amd) { 4 | define(['moment'], factory); // AMD 5 | } else if (typeof exports === 'object') { 6 | module.exports = factory(require('../moment')); // Node 7 | } else { 8 | factory((typeof global !== 'undefined' ? global : this).moment); // node or other global 9 | } 10 | }(function (moment) { 11 | var symbolMap = { 12 | '1': '۱', 13 | '2': '۲', 14 | '3': '۳', 15 | '4': '۴', 16 | '5': '۵', 17 | '6': '۶', 18 | '7': '۷', 19 | '8': '۸', 20 | '9': '۹', 21 | '0': '۰' 22 | }, numberMap = { 23 | '۱': '1', 24 | '۲': '2', 25 | '۳': '3', 26 | '۴': '4', 27 | '۵': '5', 28 | '۶': '6', 29 | '۷': '7', 30 | '۸': '8', 31 | '۹': '9', 32 | '۰': '0' 33 | }; 34 | 35 | return moment.defineLocale('fa', { 36 | months : 'فروردین_اردیبهشت_خرداد_تیر_مرداد_شهریور_مهر_آبان_آذر_دی_بهمن_اسفند'.split('_'), 37 | monthsShort : 'فروردین_اردیبهشت_خرداد_تیر_مرداد_شهریور_مهر_آبان_آذر_دی_بهمن_اسفند'.split('_'), 38 | weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), 39 | weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), 40 | weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), 41 | longDateFormat : { 42 | LT : 'HH:mm', 43 | LTS : 'LT:ss', 44 | L : 'DD/MM/YYYY', 45 | LL : 'D MMMM YYYY', 46 | LLL : 'D MMMM YYYY LT', 47 | LLLL : 'dddd, D MMMM YYYY LT' 48 | }, 49 | meridiem : function (hour, minute, isLower) { 50 | if (hour < 12) { 51 | return 'قبل از ظهر'; 52 | } else { 53 | return 'بعد از ظهر'; 54 | } 55 | }, 56 | calendar : { 57 | sameDay : '[امروز ساعت] LT', 58 | nextDay : '[فردا ساعت] LT', 59 | nextWeek : 'dddd [ساعت] LT', 60 | lastDay : '[دیروز ساعت] LT', 61 | lastWeek : 'dddd [پیش] [ساعت] LT', 62 | sameElse : 'L' 63 | }, 64 | relativeTime : { 65 | future : 'در %s', 66 | past : '%s پیش', 67 | s : 'چندین ثانیه', 68 | m : 'یک دقیقه', 69 | mm : '%d دقیقه', 70 | h : 'یک ساعت', 71 | hh : '%d ساعت', 72 | d : 'یک روز', 73 | dd : '%d روز', 74 | M : 'یک ماه', 75 | MM : '%d ماه', 76 | y : 'یک سال', 77 | yy : '%d سال' 78 | }, 79 | preparse: function (string) { 80 | return string.replace(/[۰-۹]/g, function (match) { 81 | return numberMap[match]; 82 | }).replace(/،/g, ','); 83 | }, 84 | postformat: function (string) { 85 | return string.replace(/\d/g, function (match) { 86 | return symbolMap[match]; 87 | }).replace(/,/g, '،'); 88 | }, 89 | ordinalParse: /\d{1,2}م/, 90 | ordinal : '%dم', 91 | week : { 92 | dow : 6, // Saturday is the first day of the week. 93 | doy : 12 // The week that contains Jan 1st is the first week of the year. 94 | } 95 | }); 96 | })); 97 | -------------------------------------------------------------------------------- /src/less/_bootstrap-datetimepicker.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Datetimepicker for Bootstrap 3 3 | * ! version : 4.7.14 4 | * https://github.com/Eonasdan/bootstrap-datetimepicker/ 5 | */ 6 | @bs-datetimepicker-timepicker-font-size: 1.2em; 7 | @bs-datetimepicker-active-bg: @btn-primary-bg; 8 | @bs-datetimepicker-active-color: @btn-primary-color; 9 | @bs-datetimepicker-border-radius: @border-radius-base; 10 | @bs-datetimepicker-btn-hover-bg: @gray-lighter; 11 | @bs-datetimepicker-disabled-color: @gray-light; 12 | @bs-datetimepicker-alternate-color: @gray-light; 13 | @bs-datetimepicker-secondary-border-color: #ccc; 14 | @bs-datetimepicker-secondary-border-color-rgba: rgba(0, 0, 0, 0.2); 15 | @bs-datetimepicker-primary-border-color: white; 16 | @bs-datetimepicker-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 17 | 18 | .bootstrap-datetimepicker-widget { 19 | list-style: none; 20 | 21 | &.dropdown-menu { 22 | margin: 2px 0; 23 | padding: 4px; 24 | width: 19em; 25 | 26 | &.timepicker-sbs { 27 | @media (min-width: @screen-sm-min) { 28 | width: 38em; 29 | } 30 | 31 | @media (min-width: @screen-md-min) { 32 | width: 38em; 33 | } 34 | 35 | @media (min-width: @screen-lg-min) { 36 | width: 38em; 37 | } 38 | } 39 | 40 | &:before, &:after { 41 | content: ''; 42 | display: inline-block; 43 | position: absolute; 44 | } 45 | 46 | &.bottom { 47 | &:before { 48 | border-left: 7px solid transparent; 49 | border-right: 7px solid transparent; 50 | border-bottom: 7px solid @bs-datetimepicker-secondary-border-color; 51 | border-bottom-color: @bs-datetimepicker-secondary-border-color-rgba; 52 | top: -7px; 53 | left: 7px; 54 | } 55 | 56 | &:after { 57 | border-left: 6px solid transparent; 58 | border-right: 6px solid transparent; 59 | border-bottom: 6px solid @bs-datetimepicker-primary-border-color; 60 | top: -6px; 61 | left: 8px; 62 | } 63 | } 64 | 65 | &.top { 66 | &:before { 67 | border-left: 7px solid transparent; 68 | border-right: 7px solid transparent; 69 | border-top: 7px solid @bs-datetimepicker-secondary-border-color; 70 | border-top-color: @bs-datetimepicker-secondary-border-color-rgba; 71 | bottom: -7px; 72 | left: 6px; 73 | } 74 | 75 | &:after { 76 | border-left: 6px solid transparent; 77 | border-right: 6px solid transparent; 78 | border-top: 6px solid @bs-datetimepicker-primary-border-color; 79 | bottom: -6px; 80 | left: 7px; 81 | } 82 | } 83 | 84 | &.pull-right { 85 | &:before { 86 | left: auto; 87 | right: 6px; 88 | } 89 | 90 | &:after { 91 | left: auto; 92 | right: 7px; 93 | } 94 | } 95 | } 96 | 97 | .list-unstyled { 98 | margin: 0; 99 | } 100 | 101 | a[data-action] { 102 | padding: 6px 0; 103 | } 104 | 105 | a[data-action]:active { 106 | box-shadow: none; 107 | } 108 | 109 | .timepicker-hour, .timepicker-minute, .timepicker-second { 110 | width: 54px; 111 | font-weight: bold; 112 | font-size: @bs-datetimepicker-timepicker-font-size; 113 | margin: 0; 114 | } 115 | 116 | button[data-action] { 117 | padding: 6px; 118 | } 119 | 120 | .btn[data-action="incrementHours"]::after { 121 | .sr-only(); 122 | content: "Increment Hours"; 123 | } 124 | 125 | .btn[data-action="incrementMinutes"]::after { 126 | .sr-only(); 127 | content: "Increment Minutes"; 128 | } 129 | 130 | .btn[data-action="decrementHours"]::after { 131 | .sr-only(); 132 | content: "Decrement Hours"; 133 | } 134 | 135 | .btn[data-action="decrementMinutes"]::after { 136 | .sr-only(); 137 | content: "Decrement Minutes"; 138 | } 139 | 140 | .btn[data-action="showHours"]::after { 141 | .sr-only(); 142 | content: "Show Hours"; 143 | } 144 | 145 | .btn[data-action="showMinutes"]::after { 146 | .sr-only(); 147 | content: "Show Minutes"; 148 | } 149 | 150 | .btn[data-action="togglePeriod"]::after { 151 | .sr-only(); 152 | content: "Toggle AM/PM"; 153 | } 154 | 155 | .btn[data-action="clear"]::after { 156 | .sr-only(); 157 | content: "Clear the picker"; 158 | } 159 | 160 | .btn[data-action="today"]::after { 161 | .sr-only(); 162 | content: "Set the date to today"; 163 | } 164 | 165 | .picker-switch { 166 | text-align: center; 167 | 168 | &::after { 169 | .sr-only(); 170 | content: "Toggle Date and Time Screens"; 171 | } 172 | 173 | td { 174 | padding: 0; 175 | margin: 0; 176 | height: auto; 177 | width: auto; 178 | line-height: inherit; 179 | 180 | span { 181 | line-height: 2.5; 182 | height: 2.5em; 183 | width: 100%; 184 | } 185 | } 186 | } 187 | 188 | table { 189 | width: 100%; 190 | margin: 0; 191 | 192 | 193 | & td, 194 | & th { 195 | text-align: center; 196 | border-radius: @bs-datetimepicker-border-radius; 197 | } 198 | 199 | & th { 200 | height: 20px; 201 | line-height: 20px; 202 | width: 20px; 203 | 204 | &.picker-switch { 205 | width: 145px; 206 | } 207 | 208 | &.disabled, 209 | &.disabled:hover { 210 | background: none; 211 | color: @bs-datetimepicker-disabled-color; 212 | cursor: not-allowed; 213 | } 214 | 215 | &.prev::after { 216 | .sr-only(); 217 | content: "Previous Month"; 218 | } 219 | 220 | &.next::after { 221 | .sr-only(); 222 | content: "Next Month"; 223 | } 224 | } 225 | 226 | & thead tr:first-child th { 227 | cursor: pointer; 228 | 229 | &:hover { 230 | background: @bs-datetimepicker-btn-hover-bg; 231 | } 232 | } 233 | 234 | & td { 235 | height: 54px; 236 | line-height: 54px; 237 | width: 54px; 238 | 239 | &.cw { 240 | font-size: .8em; 241 | height: 20px; 242 | line-height: 20px; 243 | color: @bs-datetimepicker-alternate-color; 244 | } 245 | 246 | &.day { 247 | height: 20px; 248 | line-height: 20px; 249 | width: 20px; 250 | } 251 | 252 | &.day:hover, 253 | &.hour:hover, 254 | &.minute:hover, 255 | &.second:hover { 256 | background: @bs-datetimepicker-btn-hover-bg; 257 | cursor: pointer; 258 | } 259 | 260 | &.old, 261 | &.new { 262 | color: @bs-datetimepicker-alternate-color; 263 | } 264 | 265 | &.today { 266 | position: relative; 267 | 268 | &:before { 269 | content: ''; 270 | display: inline-block; 271 | border: 0 0 7px 7px solid transparent; 272 | border-bottom-color: @bs-datetimepicker-active-bg; 273 | border-top-color: @bs-datetimepicker-secondary-border-color-rgba; 274 | position: absolute; 275 | bottom: 4px; 276 | right: 4px; 277 | } 278 | } 279 | 280 | &.active, 281 | &.active:hover { 282 | background-color: @bs-datetimepicker-active-bg; 283 | color: @bs-datetimepicker-active-color; 284 | text-shadow: @bs-datetimepicker-text-shadow; 285 | } 286 | 287 | &.active.today:before { 288 | border-bottom-color: #fff; 289 | } 290 | 291 | &.disabled, 292 | &.disabled:hover { 293 | background: none; 294 | color: @bs-datetimepicker-disabled-color; 295 | cursor: not-allowed; 296 | } 297 | 298 | span { 299 | display: inline-block; 300 | width: 54px; 301 | height: 54px; 302 | line-height: 54px; 303 | margin: 2px 1.5px; 304 | cursor: pointer; 305 | border-radius: @bs-datetimepicker-border-radius; 306 | 307 | &:hover { 308 | background: @bs-datetimepicker-btn-hover-bg; 309 | } 310 | 311 | &.active { 312 | background-color: @bs-datetimepicker-active-bg; 313 | color: @bs-datetimepicker-active-color; 314 | text-shadow: @bs-datetimepicker-text-shadow; 315 | } 316 | 317 | &.old { 318 | color: @bs-datetimepicker-alternate-color; 319 | } 320 | 321 | &.disabled, 322 | &.disabled:hover { 323 | background: none; 324 | color: @bs-datetimepicker-disabled-color; 325 | cursor: not-allowed; 326 | } 327 | } 328 | } 329 | } 330 | 331 | &.usetwentyfour { 332 | td.hour { 333 | height: 27px; 334 | line-height: 27px; 335 | } 336 | } 337 | } 338 | 339 | .input-group.date { 340 | & .input-group-addon { 341 | cursor: pointer; 342 | } 343 | } 344 | 345 | 346 | 347 | //rtl 348 | .datepicker { 349 | direction: rtl !important; 350 | } 351 | .timepicker 352 | { 353 | direction: ltr !important; 354 | } 355 | .ext-btns 356 | { 357 | width : 50% !important; 358 | } 359 | .picker-switch 360 | { 361 | direction: rtl !important; 362 | } 363 | -------------------------------------------------------------------------------- /src/less/bootstrap-datetimepicker-build.less: -------------------------------------------------------------------------------- 1 | // Import bootstrap variables including default color palette and fonts 2 | @import "../../node_modules/bootstrap/less/variables.less"; 3 | 4 | // Import datepicker component 5 | @import "_bootstrap-datetimepicker.less"; 6 | 7 | 8 | .sr-only { 9 | position: absolute; 10 | width: 1px; 11 | height: 1px; 12 | margin: -1px; 13 | padding: 0; 14 | overflow: hidden; 15 | clip: rect(0,0,0,0); 16 | border: 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/nuget/Bootstrap.v3.Datetimepicker.CSS.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Bootstrap.v3.Datetimepicker.CSS 5 | 4.0.0 6 | Bootstrap 3 Datetimepicker CSS 7 | Eonasdan 8 | Eonasdan 9 | https://github.com/Eonasdan/bootstrap-datetimepicker 10 | false 11 | A date/time picker component designed to work with Bootstrap 3 and Momentjs. 12 | 13 | For usage, installation and demos see Project Site on GitHub 14 | 15 | For LESS version install Bootstrap.v3.Datetimepicker 16 | Check the change log on Github at https://github.com/Eonasdan/bootstrap-datetimepicker/wiki/Change-Log 17 | bootstrap date time picker datetimepicker datepicker jquery 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/nuget/Bootstrap.v3.Datetimepicker.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Bootstrap.v3.Datetimepicker 5 | 4.0.0 6 | Bootstrap 3 Datetimepicker 7 | Eonasdan 8 | Eonasdan 9 | https://github.com/Eonasdan/bootstrap-datetimepicker 10 | false 11 | A date/time picker component designed to work with Bootstrap 3 and Momentjs. 12 | 13 | For usage, installation and demos see Project Site on GitHub 14 | 15 | For CSS version install Bootstrap.v3.Datetimepicker.CSS 16 | Check the change log on Github at https://github.com/Eonasdan/bootstrap-datetimepicker/wiki/Change-Log 17 | bootstrap date time picker datetimepicker datepicker jquery 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beygi/bootstrap-persian-datetimepicker/c35996f9e2bc5fe965dadf0945b61d71edae9b00/src/nuget/NuGet.exe -------------------------------------------------------------------------------- /src/nuget/install.ps1: -------------------------------------------------------------------------------- 1 | # install.ps1 2 | $DTE.ItemOperations.Navigate("http://eonasdan.github.io/bootstrap-datetimepicker/", $DTE.vsNavigateOptions.vsNavigateOptionsNewWindow) 3 | -------------------------------------------------------------------------------- /tasks/bump_version.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | grunt.registerTask('bump_version', function (version) { 3 | if (!version || version.split('.').length !== 3) { 4 | grunt.fail.fatal("malformed version. Use\n\n grunt bump_version:1.2.3") 5 | } 6 | 7 | grunt.config('string-replace.bootstrap-datetimepicker-js', { 8 | files: {'src/js/bootstrap-datetimepicker.js': 'src/js/bootstrap-datetimepicker.js'}, 9 | options: { 10 | replacements: [ 11 | { 12 | pattern: /\/\/! version : .*/, 13 | replacement: '//! version : ' + version 14 | } 15 | ] 16 | } 17 | }); 18 | 19 | grunt.config('string-replace.bootstrap-datetimepicker-css', { 20 | files: {'src/less/bootstrap-datetimepicker.less': 'src/less/bootstrap-datetimepicker.less'}, 21 | options: { 22 | replacements: [ 23 | { 24 | pattern: /\/\/! version : .*/, 25 | replacement: '//! version : ' + version 26 | } 27 | ] 28 | } 29 | }); 30 | 31 | grunt.config('string-replace.package-json', { 32 | files: {'package.json': 'package.json'}, 33 | options: { 34 | replacements: [ 35 | { 36 | pattern: /"version": .*/, 37 | replacement: '"version": "' + version + '",' 38 | } 39 | ] 40 | } 41 | }); 42 | 43 | grunt.config('string-replace.bower-json', { 44 | files: {'bower.json': 'bower.json'}, 45 | options: { 46 | replacements: [ 47 | { 48 | pattern: /"version": .*/, 49 | replacement: '"version": "' + version + '",' 50 | } 51 | ] 52 | } 53 | }); 54 | 55 | grunt.config('string-replace.component-json', { 56 | files: {'component.json': 'component.json'}, 57 | options: { 58 | replacements: [ 59 | { 60 | pattern: /"version": .*/, 61 | replacement: '"version": "' + version + '",' 62 | } 63 | ] 64 | } 65 | }); 66 | 67 | grunt.config('string-replace.composer-json', { 68 | files: {'composer.json': 'composer.json'}, 69 | options: { 70 | replacements: [ 71 | { 72 | pattern: /"version": .*/, 73 | replacement: '"version": "' + version + '",' 74 | } 75 | ] 76 | } 77 | }); 78 | 79 | grunt.task.run([ 80 | 'string-replace:bootstrap-datetimepicker-js', 81 | 'string-replace:bootstrap-datetimepicker-css', 82 | 'string-replace:package-json', 83 | 'string-replace:bower-json', 84 | 'string-replace:component-json', 85 | 'string-replace:composer-json' 86 | ]); 87 | }); 88 | }; 89 | -------------------------------------------------------------------------------- /test/publicApiSpec.js: -------------------------------------------------------------------------------- 1 | describe('Plugin initialization and component basic construction', function () { 2 | 'use strict'; 3 | 4 | it('loads jquery plugin properly', function () { 5 | expect($('
').datetimepicker).toBeDefined(); 6 | expect(typeof $('
').datetimepicker).toEqual('function'); 7 | expect($('
').datetimepicker.defaults).toBeDefined(); 8 | }); 9 | 10 | it('creates the component with default options on an input element', function () { 11 | var dtp = $(''); 12 | $(document).find('body').append(dtp); 13 | 14 | expect(function () { 15 | dtp = dtp.datetimepicker(); 16 | }).not.toThrow(); 17 | 18 | expect(dtp).not.toBe(null); 19 | }); 20 | 21 | xit('calls destroy when Element that the component is attached is removed', function () { 22 | var dtpElement = $('
').attr('class', 'row').append($('
').attr('class', 'col-md-12').append($(''))), 23 | dtp; 24 | $(document).find('body').append(dtpElement); 25 | dtpElement.datetimepicker(); 26 | dtp = dtpElement.data('DateTimePicker'); 27 | spyOn(dtp, 'destroy').and.callThrough(); 28 | dtpElement.remove(); 29 | expect(dtp.destroy).toHaveBeenCalled(); 30 | }); 31 | }); 32 | 33 | describe('Public API method tests', function () { 34 | 'use strict'; 35 | var dtp, 36 | dtpElement, 37 | dpChangeSpy, 38 | dpShowSpy, 39 | dpHideSpy, 40 | dpErrorSpy; 41 | 42 | beforeEach(function () { 43 | dpChangeSpy = jasmine.createSpy('dp.change event Spy'); 44 | dpShowSpy = jasmine.createSpy('dp.show event Spy'); 45 | dpHideSpy = jasmine.createSpy('dp.hide event Spy'); 46 | dpErrorSpy = jasmine.createSpy('dp.error event Spy'); 47 | dtpElement = $('').attr('id', 'dtp'); 48 | 49 | $(document).find('body').append($('
').attr('class', 'row').append($('
').attr('class', 'col-md-12').append(dtpElement))); 50 | $(document).find('body').on('dp.change', dpChangeSpy); 51 | $(document).find('body').on('dp.show', dpShowSpy); 52 | $(document).find('body').on('dp.hide', dpHideSpy); 53 | $(document).find('body').on('dp.error', dpErrorSpy); 54 | 55 | dtpElement.datetimepicker(); 56 | dtp = dtpElement.data('DateTimePicker'); 57 | }); 58 | 59 | afterEach(function () { 60 | dtp.destroy(); 61 | dtpElement.remove(); 62 | }); 63 | 64 | describe('configuration option name match to public api function', function () { 65 | Object.getOwnPropertyNames($.fn.datetimepicker.defaults).forEach(function (key) { 66 | it('has function ' + key + '()', function () { 67 | expect(dtp[key]).toBeDefined(); 68 | }); 69 | }); 70 | }); 71 | 72 | describe('date() function', function () { 73 | describe('typechecking', function () { 74 | it('accepts a null', function () { 75 | expect(function () { 76 | dtp.date(null); 77 | }).not.toThrow(); 78 | }); 79 | 80 | it('accepts a string', function () { 81 | expect(function () { 82 | dtp.date('2013/05/24'); 83 | }).not.toThrow(); 84 | }); 85 | 86 | it('accepts a Date object', function () { 87 | expect(function () { 88 | dtp.date(new Date()); 89 | }).not.toThrow(); 90 | }); 91 | 92 | it('accepts a Moment object', function () { 93 | expect(function () { 94 | dtp.date(moment()); 95 | }).not.toThrow(); 96 | }); 97 | 98 | it('does not accept undefined', function () { 99 | expect(function () { 100 | dtp.date(undefined); 101 | }).toThrow(); 102 | }); 103 | 104 | it('does not accept a number', function () { 105 | expect(function () { 106 | dtp.date(0); 107 | }).toThrow(); 108 | }); 109 | 110 | it('does not accept a generic Object', function () { 111 | expect(function () { 112 | dtp.date({}); 113 | }).toThrow(); 114 | }); 115 | 116 | it('does not accept a boolean', function () { 117 | expect(function () { 118 | dtp.date(false); 119 | }).toThrow(); 120 | }); 121 | }); 122 | 123 | describe('functionality', function () { 124 | it('has no date set upon construction', function () { 125 | expect(dtp.date()).toBe(null); 126 | }); 127 | 128 | it('sets the date correctly', function () { 129 | var timestamp = moment(); 130 | dtp.date(timestamp); 131 | expect(dtp.date().isSame(timestamp)).toBe(true); 132 | }); 133 | }); 134 | }); 135 | 136 | describe('format() function', function () { 137 | describe('typechecking', function () { 138 | it('accepts a false value', function () { 139 | expect(function () { 140 | dtp.format(false); 141 | }).not.toThrow(); 142 | }); 143 | 144 | it('accepts a string', function () { 145 | expect(function () { 146 | dtp.format('YYYY-MM-DD'); 147 | }).not.toThrow(); 148 | }); 149 | 150 | it('does not accept undefined', function () { 151 | expect(function () { 152 | dtp.format(undefined); 153 | }).toThrow(); 154 | }); 155 | 156 | it('does not accept true', function () { 157 | expect(function () { 158 | dtp.format(true); 159 | }).toThrow(); 160 | }); 161 | 162 | it('does not accept a generic Object', function () { 163 | expect(function () { 164 | dtp.format({}); 165 | }).toThrow(); 166 | }); 167 | }); 168 | 169 | describe('functionality', function () { 170 | it('returns no format before format is set', function () { 171 | expect(dtp.format()).toBe(false); 172 | }); 173 | 174 | it('sets the format correctly', function () { 175 | dtp.format('YYYY-MM-DD'); 176 | expect(dtp.format()).toBe('YYYY-MM-DD'); 177 | }); 178 | }); 179 | }); 180 | 181 | describe('destroy() function', function () { 182 | describe('existence', function () { 183 | it('is defined', function () { 184 | expect(dtp.destroy).toBeDefined(); 185 | }); 186 | }); 187 | }); 188 | 189 | describe('toggle() function', function () { 190 | describe('existence', function () { 191 | it('is defined', function () { 192 | expect(dtp.toggle).toBeDefined(); 193 | }); 194 | }); 195 | 196 | // describe('functionality', function () { 197 | // it('') 198 | // }); 199 | }); 200 | 201 | describe('show() function', function () { 202 | describe('existence', function () { 203 | it('is defined', function () { 204 | expect(dtp.show).toBeDefined(); 205 | }); 206 | }); 207 | 208 | describe('functionality', function () { 209 | it('emits a show event when called while widget is hidden', function () { 210 | dtp.show(); 211 | expect(dpShowSpy).toHaveBeenCalled(); 212 | }); 213 | 214 | it('does not emit a show event when called and widget is already showing', function () { 215 | dtp.hide(); 216 | dtp.show(); 217 | dpShowSpy.calls.reset(); 218 | dtp.show(); 219 | expect(dpShowSpy).not.toHaveBeenCalled(); 220 | }); 221 | 222 | it('actually shows the widget', function () { 223 | dtp.show(); 224 | expect($(document).find('body').find('.bootstrap-datetimepicker-widget').length).toEqual(1); 225 | }); 226 | }); 227 | }); 228 | 229 | describe('hide() function', function () { 230 | describe('existence', function () { 231 | it('is defined', function () { 232 | expect(dtp.hide).toBeDefined(); 233 | }); 234 | }); 235 | 236 | describe('functionality', function () { 237 | it('emits a hide event when called while widget is shown', function () { 238 | dtp.show(); 239 | dtp.hide(); 240 | expect(dpHideSpy).toHaveBeenCalled(); 241 | }); 242 | 243 | it('does not emit a hide event when called while widget is hidden', function () { 244 | dtp.hide(); 245 | expect(dpHideSpy).not.toHaveBeenCalled(); 246 | }); 247 | 248 | it('actually hides the widget', function () { 249 | dtp.show(); 250 | dtp.hide(); 251 | expect($(document).find('body').find('.bootstrap-datetimepicker-widget').length).toEqual(0); 252 | }); 253 | }); 254 | }); 255 | 256 | describe('disable() function', function () { 257 | describe('existence', function () { 258 | it('is defined', function () { 259 | expect(dtp.disable).toBeDefined(); 260 | }); 261 | }); 262 | }); 263 | 264 | describe('enable() function', function () { 265 | describe('existence', function () { 266 | it('is defined', function () { 267 | expect(dtp.enable).toBeDefined(); 268 | }); 269 | }); 270 | }); 271 | 272 | describe('options() function', function () { 273 | describe('existence', function () { 274 | it('is defined', function () { 275 | expect(dtp.options).toBeDefined(); 276 | }); 277 | }); 278 | }); 279 | 280 | describe('disabledDates() function', function () { 281 | describe('existence', function () { 282 | it('is defined', function () { 283 | expect(dtp.disabledDates).toBeDefined(); 284 | }); 285 | }); 286 | }); 287 | 288 | describe('enabledDates() function', function () { 289 | describe('existence', function () { 290 | it('is defined', function () { 291 | expect(dtp.enabledDates).toBeDefined(); 292 | }); 293 | }); 294 | }); 295 | 296 | describe('daysOfWeekDisabled() function', function () { 297 | describe('existence', function () { 298 | it('is defined', function () { 299 | expect(dtp.daysOfWeekDisabled).toBeDefined(); 300 | }); 301 | }); 302 | }); 303 | 304 | describe('maxDate() function', function () { 305 | describe('existence', function () { 306 | it('is defined', function () { 307 | expect(dtp.maxDate).toBeDefined(); 308 | }); 309 | }); 310 | }); 311 | 312 | describe('minDate() function', function () { 313 | describe('existence', function () { 314 | it('is defined', function () { 315 | expect(dtp.minDate).toBeDefined(); 316 | }); 317 | }); 318 | }); 319 | 320 | describe('defaultDate() function', function () { 321 | describe('existence', function () { 322 | it('is defined', function () { 323 | expect(dtp.defaultDate).toBeDefined(); 324 | }); 325 | }); 326 | describe('functionality', function () { 327 | it('returns no defaultDate before defaultDate is set', function () { 328 | expect(dtp.defaultDate()).toBe(false); 329 | }); 330 | 331 | it('sets the defaultDate correctly', function () { 332 | var timestamp = moment(); 333 | dtp.defaultDate(timestamp); 334 | expect(dtp.defaultDate().isSame(timestamp)).toBe(true); 335 | expect(dtp.date().isSame(timestamp)).toBe(true); 336 | }); 337 | 338 | it('triggers a change event upon setting a default date and input field is empty', function () { 339 | dtp.date(null); 340 | dtp.defaultDate(moment()); 341 | expect(dpChangeSpy).toHaveBeenCalled(); 342 | }); 343 | 344 | it('does not override input value if it already has one', function () { 345 | var timestamp = moment(); 346 | dtp.date(timestamp); 347 | dtp.defaultDate(moment().year(2000)); 348 | expect(dtp.date().isSame(timestamp)).toBe(true); 349 | }); 350 | }); 351 | }); 352 | 353 | describe('locale() function', function () { 354 | describe('functionality', function () { 355 | it('it switches to a selected locale without affecting global moment locale', function () { 356 | dtp.locale('el'); 357 | dtp.date(moment()); 358 | expect(dtp.locale()).toBe('el'); 359 | expect(dtp.date().locale()).toBe('el'); 360 | expect(moment.locale()).toBe('fa'); 361 | }); 362 | }); 363 | }); 364 | 365 | describe('useCurrent() function', function () { 366 | describe('existence', function () { 367 | it('is defined', function () { 368 | expect(dtp.useCurrent).toBeDefined(); 369 | }); 370 | }); 371 | describe('check type and parameter validity', function () { 372 | it('accepts either a boolean value or string', function () { 373 | var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; 374 | 375 | expect(function () { 376 | dtp.useCurrent(false); 377 | }).not.toThrow(); 378 | expect(function () { 379 | dtp.useCurrent(true); 380 | }).not.toThrow(); 381 | 382 | useCurrentOptions.forEach(function (value) { 383 | expect(function () { 384 | dtp.useCurrent(value); 385 | }).not.toThrow(); 386 | }); 387 | 388 | expect(function () { 389 | dtp.useCurrent('test'); 390 | }).toThrow(); 391 | expect(function () { 392 | dtp.useCurrent({}); 393 | }).toThrow(); 394 | }); 395 | }); 396 | describe('functionality', function () { 397 | it('triggers a change event upon show() and input field is empty', function () { 398 | dtp.useCurrent(true); 399 | dtp.show(); 400 | expect(dpChangeSpy).toHaveBeenCalled(); 401 | }); 402 | }); 403 | }); 404 | 405 | describe('ignoreReadonly() function', function () { 406 | describe('existence', function () { 407 | it('is defined', function () { 408 | expect(dtp.ignoreReadonly).toBeDefined(); 409 | }); 410 | }); 411 | }); 412 | 413 | describe('stepping() function', function () { 414 | describe('existence', function () { 415 | it('is defined', function () { 416 | expect(dtp.stepping).toBeDefined(); 417 | }); 418 | }); 419 | }); 420 | 421 | describe('collapse() function', function () { 422 | describe('existence', function () { 423 | it('is defined', function () { 424 | expect(dtp.collapse).toBeDefined(); 425 | }); 426 | }); 427 | }); 428 | 429 | describe('icons() function', function () { 430 | describe('existence', function () { 431 | it('is defined', function () { 432 | expect(dtp.icons).toBeDefined(); 433 | }); 434 | }); 435 | }); 436 | 437 | describe('useStrict() function', function () { 438 | describe('existence', function () { 439 | it('is defined', function () { 440 | expect(dtp.useStrict).toBeDefined(); 441 | }); 442 | }); 443 | }); 444 | 445 | describe('sideBySide() function', function () { 446 | describe('existence', function () { 447 | it('is defined', function () { 448 | expect(dtp.sideBySide).toBeDefined(); 449 | }); 450 | }); 451 | }); 452 | 453 | describe('viewMode() function', function () { 454 | describe('existence', function () { 455 | it('is defined', function () { 456 | expect(dtp.viewMode).toBeDefined(); 457 | }); 458 | }); 459 | }); 460 | 461 | describe('widgetPositioning() function', function () { 462 | describe('existence', function () { 463 | it('is defined', function () { 464 | expect(dtp.widgetPositioning).toBeDefined(); 465 | }); 466 | }); 467 | }); 468 | 469 | describe('calendarWeeks() function', function () { 470 | describe('existence', function () { 471 | it('is defined', function () { 472 | expect(dtp.calendarWeeks).toBeDefined(); 473 | }); 474 | }); 475 | }); 476 | 477 | describe('showTodayButton() function', function () { 478 | describe('existence', function () { 479 | it('is defined', function () { 480 | expect(dtp.showTodayButton).toBeDefined(); 481 | }); 482 | }); 483 | }); 484 | 485 | describe('showClear() function', function () { 486 | describe('existence', function () { 487 | it('is defined', function () { 488 | expect(dtp.showClear).toBeDefined(); 489 | }); 490 | }); 491 | }); 492 | 493 | describe('dayViewHeaderFormat() function', function () { 494 | describe('typechecking', function () { 495 | it('does not accept a false value', function () { 496 | expect(function () { 497 | dtp.dayViewHeaderFormat(false); 498 | }).toThrow(); 499 | }); 500 | 501 | it('accepts a string', function () { 502 | expect(function () { 503 | dtp.dayViewHeaderFormat('YYYY-MM-DD'); 504 | }).not.toThrow(); 505 | }); 506 | 507 | it('does not accept undefined', function () { 508 | expect(function () { 509 | dtp.dayViewHeaderFormat(undefined); 510 | }).toThrow(); 511 | }); 512 | 513 | it('does not accept true', function () { 514 | expect(function () { 515 | dtp.dayViewHeaderFormat(true); 516 | }).toThrow(); 517 | }); 518 | 519 | it('does not accept a generic Object', function () { 520 | expect(function () { 521 | dtp.dayViewHeaderFormat({}); 522 | }).toThrow(); 523 | }); 524 | }); 525 | 526 | describe('functionality', function () { 527 | it('expects dayViewHeaderFormat to be default of MMMM YYYY', function () { 528 | expect(dtp.dayViewHeaderFormat()).toBe('MMMM YYYY'); 529 | }); 530 | 531 | it('sets the dayViewHeaderFormat correctly', function () { 532 | dtp.dayViewHeaderFormat('MM YY'); 533 | expect(dtp.dayViewHeaderFormat()).toBe('MM YY'); 534 | }); 535 | }); 536 | }); 537 | 538 | describe('extraFormats() function', function () { 539 | describe('typechecking', function () { 540 | it('accepts a false value', function () { 541 | expect(function () { 542 | dtp.extraFormats(false); 543 | }).not.toThrow(); 544 | }); 545 | 546 | it('does not accept a string', function () { 547 | expect(function () { 548 | dtp.extraFormats('YYYY-MM-DD'); 549 | }).toThrow(); 550 | }); 551 | 552 | it('does not accept undefined', function () { 553 | expect(function () { 554 | dtp.extraFormats(undefined); 555 | }).toThrow(); 556 | }); 557 | 558 | it('does not accept true', function () { 559 | expect(function () { 560 | dtp.extraFormats(true); 561 | }).toThrow(); 562 | }); 563 | 564 | it('accepts an Array', function () { 565 | expect(function () { 566 | dtp.extraFormats(['YYYY-MM-DD']); 567 | }).not.toThrow(); 568 | }); 569 | }); 570 | 571 | describe('functionality', function () { 572 | it('returns no extraFormats before extraFormats is set', function () { 573 | expect(dtp.extraFormats()).toBe(false); 574 | }); 575 | 576 | it('sets the extraFormats correctly', function () { 577 | dtp.extraFormats(['YYYY-MM-DD']); 578 | expect(dtp.extraFormats()[0]).toBe('YYYY-MM-DD'); 579 | }); 580 | }); 581 | }); 582 | 583 | describe('toolbarPlacement() function', function () { 584 | describe('existence', function () { 585 | it('is defined', function () { 586 | expect(dtp.toolbarPlacement).toBeDefined(); 587 | }); 588 | }); 589 | describe('check type and parameter validity', function () { 590 | it('does not accept a false value', function () { 591 | expect(function () { 592 | dtp.dayViewHeaderFormat(false); 593 | }).toThrow(); 594 | }); 595 | it('does not accept a false value', function () { 596 | expect(function () { 597 | dtp.dayViewHeaderFormat(false); 598 | }).toThrow(); 599 | }); 600 | it('accepts a string', function () { 601 | var toolbarPlacementOptions = ['default', 'top', 'bottom']; 602 | 603 | toolbarPlacementOptions.forEach(function (value) { 604 | expect(function () { 605 | dtp.toolbarPlacement(value); 606 | }).not.toThrow(); 607 | }); 608 | 609 | expect(function () { 610 | dtp.toolbarPlacement('test'); 611 | }).toThrow(); 612 | expect(function () { 613 | dtp.toolbarPlacement({}); 614 | }).toThrow(); 615 | }); 616 | }); 617 | }); 618 | 619 | describe('widgetParent() function', function () { 620 | describe('typechecking', function () { 621 | it('accepts a null', function () { 622 | expect(function () { 623 | dtp.widgetParent(null); 624 | }).not.toThrow(); 625 | }); 626 | 627 | it('accepts a string', function () { 628 | expect(function () { 629 | dtp.widgetParent('testDiv'); 630 | }).not.toThrow(); 631 | }); 632 | 633 | it('accepts a jquery object', function () { 634 | expect(function () { 635 | dtp.widgetParent($('#testDiv')); 636 | }).not.toThrow(); 637 | }); 638 | 639 | it('does not accept undefined', function () { 640 | expect(function () { 641 | dtp.widgetParent(undefined); 642 | }).toThrow(); 643 | }); 644 | 645 | it('does not accept a number', function () { 646 | expect(function () { 647 | dtp.widgetParent(0); 648 | }).toThrow(); 649 | }); 650 | 651 | it('does not accept a generic Object', function () { 652 | expect(function () { 653 | dtp.widgetParent({}); 654 | }).toThrow(); 655 | }); 656 | 657 | it('does not accept a boolean', function () { 658 | expect(function () { 659 | dtp.widgetParent(false); 660 | }).toThrow(); 661 | }); 662 | }); 663 | }); 664 | 665 | describe('keepOpen() function', function () { 666 | describe('existence', function () { 667 | it('is defined', function () { 668 | expect(dtp.keepOpen).toBeDefined(); 669 | }); 670 | }); 671 | }); 672 | 673 | describe('inline() function', function () { 674 | describe('existence', function () { 675 | it('is defined', function () { 676 | expect(dtp.inline).toBeDefined(); 677 | }); 678 | }); 679 | }); 680 | 681 | describe('clear() function', function () { 682 | describe('existence', function () { 683 | it('is defined', function () { 684 | expect(dtp.clear).toBeDefined(); 685 | }); 686 | }); 687 | }); 688 | 689 | describe('keyBinds() function', function () { 690 | describe('existence', function () { 691 | it('is defined', function () { 692 | expect(dtp.keyBinds).toBeDefined(); 693 | }); 694 | }); 695 | }); 696 | }); 697 | -------------------------------------------------------------------------------- /usage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Basic Usage 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |





18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 |
32 | 43 |
44 |
45 |
46 | --------------------------------------------------------------------------------
').addClass('cw').text('#')); 467 | } 468 | 469 | while (currentDate.isBefore(viewDate.clone().endOf('w'))) { 470 | row.append($('').addClass('dow').text(currentDate.format('dd'))); 471 | currentDate.add(1, 'd'); 472 | } 473 | widget.find('.datepicker-days thead').append(row); 474 | }, 475 | 476 | isInDisabledDates = function (testDate) { 477 | return options.disabledDates[testDate.format('YYYY-MM-DD')] === true; 478 | }, 479 | 480 | isInEnabledDates = function (testDate) { 481 | return options.enabledDates[testDate.format('YYYY-MM-DD')] === true; 482 | }, 483 | 484 | isValid = function (targetMoment, granularity) { 485 | if (!targetMoment.isValid()) { 486 | return false; 487 | } 488 | if (options.disabledDates && isInDisabledDates(targetMoment) && granularity !== 'M') { 489 | return false; 490 | } 491 | if (options.enabledDates && !isInEnabledDates(targetMoment) && granularity !== 'M') { 492 | return false; 493 | } 494 | if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) { 495 | return false; 496 | } 497 | if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) { 498 | return false; 499 | } 500 | if (granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { //widget && widget.find('.datepicker-days').length > 0 501 | return false; 502 | } 503 | return true; 504 | }, 505 | 506 | fillMonths = function () { 507 | var spans = [], 508 | monthsShort = viewDate.clone().startOf('y').hour(12); // hour is changed to avoid DST issues in some browsers 509 | while (monthsShort.isSame(viewDate, 'y')) { 510 | spans.push($('').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM'))); 511 | monthsShort.add(1, 'M'); 512 | } 513 | widget.find('.datepicker-months td').empty().append(spans); 514 | }, 515 | 516 | updateMonths = function () { 517 | var monthsView = widget.find('.datepicker-months'), 518 | monthsViewHeader = monthsView.find('th'), 519 | months = monthsView.find('tbody').find('span'); 520 | 521 | monthsView.find('.disabled').removeClass('disabled'); 522 | 523 | if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) { 524 | monthsViewHeader.eq(0).addClass('disabled'); 525 | } 526 | 527 | monthsViewHeader.eq(1).text(viewDate.year()); 528 | 529 | if (!isValid(viewDate.clone().add(1, 'y'), 'y')) { 530 | monthsViewHeader.eq(2).addClass('disabled'); 531 | } 532 | 533 | months.removeClass('active'); 534 | if (date.isSame(viewDate, 'y')) { 535 | months.eq(date.month()).addClass('active'); 536 | } 537 | 538 | months.each(function (index) { 539 | if (!isValid(viewDate.clone().month(index), 'M')) { 540 | $(this).addClass('disabled'); 541 | } 542 | }); 543 | }, 544 | 545 | updateYears = function () { 546 | var yearsView = widget.find('.datepicker-years'), 547 | yearsViewHeader = yearsView.find('th'), 548 | startYear = viewDate.clone().subtract(5, 'y'), 549 | endYear = viewDate.clone().add(6, 'y'), 550 | html = ''; 551 | 552 | yearsView.find('.disabled').removeClass('disabled'); 553 | 554 | if (options.minDate && options.minDate.isAfter(startYear, 'y')) { 555 | yearsViewHeader.eq(0).addClass('disabled'); 556 | } 557 | 558 | yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year()); 559 | 560 | if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) { 561 | yearsViewHeader.eq(2).addClass('disabled'); 562 | } 563 | 564 | while (!startYear.isAfter(endYear, 'y')) { 565 | html += '' + startYear.year() + ''; 566 | startYear.add(1, 'y'); 567 | } 568 | 569 | yearsView.find('td').html(html); 570 | }, 571 | 572 | fillDate = function () { 573 | var daysView = widget.find('.datepicker-days'), 574 | daysViewHeader = daysView.find('th'), 575 | currentDate, 576 | html = [], 577 | row, 578 | clsName; 579 | 580 | if (!hasDate()) { 581 | return; 582 | } 583 | 584 | daysView.find('.disabled').removeClass('disabled'); 585 | daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat)); 586 | 587 | if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) { 588 | daysViewHeader.eq(0).addClass('disabled'); 589 | } 590 | if (!isValid(viewDate.clone().add(1, 'M'), 'M')) { 591 | daysViewHeader.eq(2).addClass('disabled'); 592 | } 593 | 594 | currentDate = viewDate.clone().startOf('M').startOf('week'); 595 | 596 | while (!viewDate.clone().endOf('M').endOf('w').isBefore(currentDate, 'd')) { 597 | if (currentDate.weekday() === 0) { 598 | row = $('
' + currentDate.week() + '' + currentDate.date() + '
' + currentHour.format(use24Hours ? 'HH' : 'hh') + '
' + currentMinute.format('mm') + '
' + currentSecond.format('ss') + '