less-rails-bootstrap-datepicker 1.4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +4 -0
  4. data/CODE_OF_CONDUCT.md +13 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE +22 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +45 -0
  9. data/Rakefile +47 -0
  10. data/app/assets/javascripts/bootstrap-datepicker/bootstrap-datepicker.js +2 -0
  11. data/app/assets/javascripts/bootstrap-datepicker/core.js +1782 -0
  12. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ar.js +15 -0
  13. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.az.js +12 -0
  14. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.bg.js +14 -0
  15. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.bs.js +15 -0
  16. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ca.js +17 -0
  17. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.cs.js +18 -0
  18. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.cy.js +14 -0
  19. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.da.js +15 -0
  20. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.de.js +17 -0
  21. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.el.js +16 -0
  22. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.js +17 -0
  23. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.es.js +17 -0
  24. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.et.js +18 -0
  25. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.eu.js +15 -0
  26. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.fa.js +17 -0
  27. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.fi.js +16 -0
  28. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.fo.js +15 -0
  29. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.js +20 -0
  30. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.fr.js +17 -0
  31. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.gl.js +13 -0
  32. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.he.js +15 -0
  33. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.hr.js +13 -0
  34. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.hu.js +16 -0
  35. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.hy.js +17 -0
  36. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.id.js +15 -0
  37. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.is.js +14 -0
  38. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.js +20 -0
  39. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.it.js +17 -0
  40. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ja.js +16 -0
  41. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ka.js +17 -0
  42. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.kh.js +15 -0
  43. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.kk.js +15 -0
  44. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.kr.js +13 -0
  45. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.lt.js +16 -0
  46. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.lv.js +16 -0
  47. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.me.js +17 -0
  48. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.mk.js +15 -0
  49. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ms.js +14 -0
  50. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.nb.js +14 -0
  51. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.js +17 -0
  52. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.nl.js +17 -0
  53. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.no.js +16 -0
  54. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.pl.js +16 -0
  55. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.js +15 -0
  56. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.pt.js +16 -0
  57. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ro.js +16 -0
  58. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.js +16 -0
  59. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.rs.js +16 -0
  60. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.ru.js +17 -0
  61. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sk.js +15 -0
  62. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sl.js +14 -0
  63. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sq.js +15 -0
  64. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.js +16 -0
  65. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sr.js +16 -0
  66. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sv.js +17 -0
  67. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.sw.js +15 -0
  68. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.th.js +14 -0
  69. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.tr.js +18 -0
  70. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.uk.js +17 -0
  71. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.vi.js +16 -0
  72. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.js +17 -0
  73. data/app/assets/javascripts/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.js +17 -0
  74. data/app/assets/stylesheets/bootstrap-datepicker/datepicker.less +239 -0
  75. data/app/assets/stylesheets/bootstrap-datepicker/datepicker3.less +230 -0
  76. data/less-rails-bootstrap-datepicker.gemspec +27 -0
  77. data/lib/less/rails/bootstrap/datepicker.rb +12 -0
  78. data/lib/less/rails/bootstrap/datepicker/engine.rb +15 -0
  79. data/lib/less/rails/bootstrap/datepicker/version.rb +9 -0
  80. metadata +219 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 61d57277a6f92c5177d933ad64078232687a5a6f
4
+ data.tar.gz: 9fe4d68f885769b8e9b211ae77cd618c6c239b73
5
+ SHA512:
6
+ metadata.gz: bb74fb8b436c1ff9c9a88570564fdcca85d731b22e1022597cd918f4c4a47ff44d1ca385660385b7f9554e08002fa8493a6216ac0c606954007d2630c3debc48
7
+ data.tar.gz: 5114eb0e0a903e9ab27c2ea21ce84e16da3ce4f5e887668a27ca2287df469f2597488f1ad83d2cc9f3cee563f48c8d3625e500499f83a63aa429e52db626679a
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.gem
11
+ bootstrap-datepicker-src
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.5
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in less-rails-bootstrap-datepicker.gemspec
4
+ gemspec
5
+
6
+ gem 'therubyracer', '>= 0.10.1', :require => nil, :platforms => :ruby
7
+ gem 'therubyrhino', '>= 1.73.2', :require => nil, :platforms => :jruby
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Erich Quintero
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
+
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Erich Quintero
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
13
+ all 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
21
+ THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ # Less Rails Bootstrap Datepicker
2
+
3
+ The `less-rails-bootstrap-datepicker` project makes [bootstrap-datepicker](https://github.com/eternicode/bootstrap-datepicker/)'s source LESS files, compiled CSS, and JavaScript files available in the Rails asset pipeline.
4
+
5
+ The benefits:
6
+
7
+ * Assets are namespaced to avoid asset conflicts.
8
+ * Top level requires to get all stylesheets or javascripts.
9
+ * Ability to import or require individually namespaced stylesheets or javascripts.
10
+
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'less-rails-bootstrap-datepicker'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ ```$ bundle```
23
+
24
+ Or install it yourself as:
25
+
26
+ ```$ gem install less-rails-bootstrap-datepicker```
27
+
28
+ ## Usage
29
+
30
+ TODO: Write usage instructions here
31
+
32
+ ## Development
33
+
34
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
35
+
36
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
37
+
38
+ ## Contributing
39
+
40
+ Bug reports and pull requests are welcome on GitHub at https://github.com/qbantek/less-rails-bootstrap-datepicker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
41
+
42
+
43
+ ## License
44
+
45
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'json'
4
+ require File.expand_path('../lib/less/rails/bootstrap/datepicker/version', __FILE__)
5
+
6
+ desc 'Update assets'
7
+ task :update do
8
+ if ARGV.count > 1
9
+ checkout_branch = "tags/#{ARGV.last}"
10
+ task ARGV.last.to_sym {}
11
+ else
12
+ checkout_branch = '`git describe --abbrev=0`'
13
+ end
14
+
15
+ if Dir.exist?('bootstrap-datepicker-src')
16
+ system("cd bootstrap-datepicker-src && git checkout master && git pull && git checkout #{checkout_branch}")
17
+ else
18
+ system('git clone git://github.com/eternicode/bootstrap-datepicker.git bootstrap-datepicker-src')
19
+ system("cd bootstrap-datepicker-src && git checkout #{checkout_branch}")
20
+ end
21
+
22
+ system('cp bootstrap-datepicker-src/less/datepicker*.less app/assets/stylesheets/bootstrap-datepicker/')
23
+ system('cp bootstrap-datepicker-src/dist/js/bootstrap-datepicker.js app/assets/javascripts/bootstrap-datepicker/core.js')
24
+ system('cp bootstrap-datepicker-src/js/locales/*.js app/assets/javascripts/bootstrap-datepicker/locales/')
25
+ system('git status')
26
+
27
+ puts "\n"
28
+ puts "bootstrap-datepicker version: #{JSON.parse(File.read('./bootstrap-datepicker-src/bower.json'))['version']}"
29
+ puts "less-rails-bootstrap-datepicker version: #{Less::Rails::Bootstrap::Datepicker::VERSION}"
30
+ end
31
+
32
+ desc 'Build'
33
+ task 'build' do
34
+ system('gem build less-rails-bootstrap-datepicker.gemspec')
35
+ end
36
+
37
+ desc 'Build and publish the gem'
38
+ task :publish => :build do
39
+ tags = `git tag`.split
40
+ current_version = Less::Rails::Bootstrap::Datepicker::VERSION
41
+ system("git tag -a #{current_version} -m 'Release #{current_version}'") unless tags.include?(current_version)
42
+ system("gem push less-rails-bootstrap-datepicker-#{current_version}.gem")
43
+ system('git push --follow-tags')
44
+ end
45
+
46
+ task :release => :publish do
47
+ end
@@ -0,0 +1,2 @@
1
+ //= require ./core
2
+ //= require_tree ./locales/
@@ -0,0 +1,1782 @@
1
+ /*!
2
+ * Datepicker for Bootstrap v1.4.0 (https://github.com/eternicode/bootstrap-datepicker)
3
+ *
4
+ * Copyright 2012 Stefan Petre
5
+ * Improvements by Andrew Rowls
6
+ * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7
+ */(function($, undefined){
8
+
9
+ function UTCDate(){
10
+ return new Date(Date.UTC.apply(Date, arguments));
11
+ }
12
+ function UTCToday(){
13
+ var today = new Date();
14
+ return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
15
+ }
16
+ function isUTCEquals(date1, date2) {
17
+ return (
18
+ date1.getUTCFullYear() === date2.getUTCFullYear() &&
19
+ date1.getUTCMonth() === date2.getUTCMonth() &&
20
+ date1.getUTCDate() === date2.getUTCDate()
21
+ );
22
+ }
23
+ function alias(method){
24
+ return function(){
25
+ return this[method].apply(this, arguments);
26
+ };
27
+ }
28
+
29
+ var DateArray = (function(){
30
+ var extras = {
31
+ get: function(i){
32
+ return this.slice(i)[0];
33
+ },
34
+ contains: function(d){
35
+ // Array.indexOf is not cross-browser;
36
+ // $.inArray doesn't work with Dates
37
+ var val = d && d.valueOf();
38
+ for (var i=0, l=this.length; i < l; i++)
39
+ if (this[i].valueOf() === val)
40
+ return i;
41
+ return -1;
42
+ },
43
+ remove: function(i){
44
+ this.splice(i,1);
45
+ },
46
+ replace: function(new_array){
47
+ if (!new_array)
48
+ return;
49
+ if (!$.isArray(new_array))
50
+ new_array = [new_array];
51
+ this.clear();
52
+ this.push.apply(this, new_array);
53
+ },
54
+ clear: function(){
55
+ this.length = 0;
56
+ },
57
+ copy: function(){
58
+ var a = new DateArray();
59
+ a.replace(this);
60
+ return a;
61
+ }
62
+ };
63
+
64
+ return function(){
65
+ var a = [];
66
+ a.push.apply(a, arguments);
67
+ $.extend(a, extras);
68
+ return a;
69
+ };
70
+ })();
71
+
72
+
73
+ // Picker object
74
+
75
+ var Datepicker = function(element, options){
76
+ this._process_options(options);
77
+
78
+ this.dates = new DateArray();
79
+ this.viewDate = this.o.defaultViewDate;
80
+ this.focusDate = null;
81
+
82
+ this.element = $(element);
83
+ this.isInline = false;
84
+ this.isInput = this.element.is('input');
85
+ this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
86
+ this.hasInput = this.component && this.element.find('input').length;
87
+ if (this.component && this.component.length === 0)
88
+ this.component = false;
89
+
90
+ this.picker = $(DPGlobal.template);
91
+ this._buildEvents();
92
+ this._attachEvents();
93
+
94
+ if (this.isInline){
95
+ this.picker.addClass('datepicker-inline').appendTo(this.element);
96
+ }
97
+ else {
98
+ this.picker.addClass('datepicker-dropdown dropdown-menu');
99
+ }
100
+
101
+ if (this.o.rtl){
102
+ this.picker.addClass('datepicker-rtl');
103
+ }
104
+
105
+ this.viewMode = this.o.startView;
106
+
107
+ if (this.o.calendarWeeks)
108
+ this.picker.find('tfoot .today, tfoot .clear')
109
+ .attr('colspan', function(i, val){
110
+ return parseInt(val) + 1;
111
+ });
112
+
113
+ this._allow_update = false;
114
+
115
+ this.setStartDate(this._o.startDate);
116
+ this.setEndDate(this._o.endDate);
117
+ this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
118
+ this.setDatesDisabled(this.o.datesDisabled);
119
+
120
+ this.fillDow();
121
+ this.fillMonths();
122
+
123
+ this._allow_update = true;
124
+
125
+ this.update();
126
+ this.showMode();
127
+
128
+ if (this.isInline){
129
+ this.show();
130
+ }
131
+ };
132
+
133
+ Datepicker.prototype = {
134
+ constructor: Datepicker,
135
+
136
+ _process_options: function(opts){
137
+ // Store raw options for reference
138
+ this._o = $.extend({}, this._o, opts);
139
+ // Processed options
140
+ var o = this.o = $.extend({}, this._o);
141
+
142
+ // Check if "de-DE" style date is available, if not language should
143
+ // fallback to 2 letter code eg "de"
144
+ var lang = o.language;
145
+ if (!dates[lang]){
146
+ lang = lang.split('-')[0];
147
+ if (!dates[lang])
148
+ lang = defaults.language;
149
+ }
150
+ o.language = lang;
151
+
152
+ switch (o.startView){
153
+ case 2:
154
+ case 'decade':
155
+ o.startView = 2;
156
+ break;
157
+ case 1:
158
+ case 'year':
159
+ o.startView = 1;
160
+ break;
161
+ default:
162
+ o.startView = 0;
163
+ }
164
+
165
+ switch (o.minViewMode){
166
+ case 1:
167
+ case 'months':
168
+ o.minViewMode = 1;
169
+ break;
170
+ case 2:
171
+ case 'years':
172
+ o.minViewMode = 2;
173
+ break;
174
+ default:
175
+ o.minViewMode = 0;
176
+ }
177
+
178
+ o.startView = Math.max(o.startView, o.minViewMode);
179
+
180
+ // true, false, or Number > 0
181
+ if (o.multidate !== true){
182
+ o.multidate = Number(o.multidate) || false;
183
+ if (o.multidate !== false)
184
+ o.multidate = Math.max(0, o.multidate);
185
+ }
186
+ o.multidateSeparator = String(o.multidateSeparator);
187
+
188
+ o.weekStart %= 7;
189
+ o.weekEnd = ((o.weekStart + 6) % 7);
190
+
191
+ var format = DPGlobal.parseFormat(o.format);
192
+ if (o.startDate !== -Infinity){
193
+ if (!!o.startDate){
194
+ if (o.startDate instanceof Date)
195
+ o.startDate = this._local_to_utc(this._zero_time(o.startDate));
196
+ else
197
+ o.startDate = DPGlobal.parseDate(o.startDate, format, o.language);
198
+ }
199
+ else {
200
+ o.startDate = -Infinity;
201
+ }
202
+ }
203
+ if (o.endDate !== Infinity){
204
+ if (!!o.endDate){
205
+ if (o.endDate instanceof Date)
206
+ o.endDate = this._local_to_utc(this._zero_time(o.endDate));
207
+ else
208
+ o.endDate = DPGlobal.parseDate(o.endDate, format, o.language);
209
+ }
210
+ else {
211
+ o.endDate = Infinity;
212
+ }
213
+ }
214
+
215
+ o.daysOfWeekDisabled = o.daysOfWeekDisabled||[];
216
+ if (!$.isArray(o.daysOfWeekDisabled))
217
+ o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/);
218
+ o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){
219
+ return parseInt(d, 10);
220
+ });
221
+
222
+ o.datesDisabled = o.datesDisabled||[];
223
+ if (!$.isArray(o.datesDisabled)) {
224
+ var datesDisabled = [];
225
+ datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language));
226
+ o.datesDisabled = datesDisabled;
227
+ }
228
+ o.datesDisabled = $.map(o.datesDisabled,function(d){
229
+ return DPGlobal.parseDate(d, format, o.language);
230
+ });
231
+
232
+ var plc = String(o.orientation).toLowerCase().split(/\s+/g),
233
+ _plc = o.orientation.toLowerCase();
234
+ plc = $.grep(plc, function(word){
235
+ return /^auto|left|right|top|bottom$/.test(word);
236
+ });
237
+ o.orientation = {x: 'auto', y: 'auto'};
238
+ if (!_plc || _plc === 'auto')
239
+ ; // no action
240
+ else if (plc.length === 1){
241
+ switch (plc[0]){
242
+ case 'top':
243
+ case 'bottom':
244
+ o.orientation.y = plc[0];
245
+ break;
246
+ case 'left':
247
+ case 'right':
248
+ o.orientation.x = plc[0];
249
+ break;
250
+ }
251
+ }
252
+ else {
253
+ _plc = $.grep(plc, function(word){
254
+ return /^left|right$/.test(word);
255
+ });
256
+ o.orientation.x = _plc[0] || 'auto';
257
+
258
+ _plc = $.grep(plc, function(word){
259
+ return /^top|bottom$/.test(word);
260
+ });
261
+ o.orientation.y = _plc[0] || 'auto';
262
+ }
263
+ if (o.defaultViewDate) {
264
+ var year = o.defaultViewDate.year || new Date().getFullYear();
265
+ var month = o.defaultViewDate.month || 0;
266
+ var day = o.defaultViewDate.day || 1;
267
+ o.defaultViewDate = UTCDate(year, month, day);
268
+ } else {
269
+ o.defaultViewDate = UTCToday();
270
+ }
271
+ o.showOnFocus = o.showOnFocus !== undefined ? o.showOnFocus : true;
272
+ },
273
+ _events: [],
274
+ _secondaryEvents: [],
275
+ _applyEvents: function(evs){
276
+ for (var i=0, el, ch, ev; i < evs.length; i++){
277
+ el = evs[i][0];
278
+ if (evs[i].length === 2){
279
+ ch = undefined;
280
+ ev = evs[i][1];
281
+ }
282
+ else if (evs[i].length === 3){
283
+ ch = evs[i][1];
284
+ ev = evs[i][2];
285
+ }
286
+ el.on(ev, ch);
287
+ }
288
+ },
289
+ _unapplyEvents: function(evs){
290
+ for (var i=0, el, ev, ch; i < evs.length; i++){
291
+ el = evs[i][0];
292
+ if (evs[i].length === 2){
293
+ ch = undefined;
294
+ ev = evs[i][1];
295
+ }
296
+ else if (evs[i].length === 3){
297
+ ch = evs[i][1];
298
+ ev = evs[i][2];
299
+ }
300
+ el.off(ev, ch);
301
+ }
302
+ },
303
+ _buildEvents: function(){
304
+ var events = {
305
+ keyup: $.proxy(function(e){
306
+ if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
307
+ this.update();
308
+ }, this),
309
+ keydown: $.proxy(this.keydown, this)
310
+ };
311
+
312
+ if (this.o.showOnFocus === true) {
313
+ events.focus = $.proxy(this.show, this);
314
+ }
315
+
316
+ if (this.isInput) { // single input
317
+ this._events = [
318
+ [this.element, events]
319
+ ];
320
+ }
321
+ else if (this.component && this.hasInput) { // component: input + button
322
+ this._events = [
323
+ // For components that are not readonly, allow keyboard nav
324
+ [this.element.find('input'), events],
325
+ [this.component, {
326
+ click: $.proxy(this.show, this)
327
+ }]
328
+ ];
329
+ }
330
+ else if (this.element.is('div')){ // inline datepicker
331
+ this.isInline = true;
332
+ }
333
+ else {
334
+ this._events = [
335
+ [this.element, {
336
+ click: $.proxy(this.show, this)
337
+ }]
338
+ ];
339
+ }
340
+ this._events.push(
341
+ // Component: listen for blur on element descendants
342
+ [this.element, '*', {
343
+ blur: $.proxy(function(e){
344
+ this._focused_from = e.target;
345
+ }, this)
346
+ }],
347
+ // Input: listen for blur on element
348
+ [this.element, {
349
+ blur: $.proxy(function(e){
350
+ this._focused_from = e.target;
351
+ }, this)
352
+ }]
353
+ );
354
+
355
+ this._secondaryEvents = [
356
+ [this.picker, {
357
+ click: $.proxy(this.click, this)
358
+ }],
359
+ [$(window), {
360
+ resize: $.proxy(this.place, this)
361
+ }],
362
+ [$(document), {
363
+ 'mousedown touchstart': $.proxy(function(e){
364
+ // Clicked outside the datepicker, hide it
365
+ if (!(
366
+ this.element.is(e.target) ||
367
+ this.element.find(e.target).length ||
368
+ this.picker.is(e.target) ||
369
+ this.picker.find(e.target).length
370
+ )){
371
+ this.hide();
372
+ }
373
+ }, this)
374
+ }]
375
+ ];
376
+ },
377
+ _attachEvents: function(){
378
+ this._detachEvents();
379
+ this._applyEvents(this._events);
380
+ },
381
+ _detachEvents: function(){
382
+ this._unapplyEvents(this._events);
383
+ },
384
+ _attachSecondaryEvents: function(){
385
+ this._detachSecondaryEvents();
386
+ this._applyEvents(this._secondaryEvents);
387
+ },
388
+ _detachSecondaryEvents: function(){
389
+ this._unapplyEvents(this._secondaryEvents);
390
+ },
391
+ _trigger: function(event, altdate){
392
+ var date = altdate || this.dates.get(-1),
393
+ local_date = this._utc_to_local(date);
394
+
395
+ this.element.trigger({
396
+ type: event,
397
+ date: local_date,
398
+ dates: $.map(this.dates, this._utc_to_local),
399
+ format: $.proxy(function(ix, format){
400
+ if (arguments.length === 0){
401
+ ix = this.dates.length - 1;
402
+ format = this.o.format;
403
+ }
404
+ else if (typeof ix === 'string'){
405
+ format = ix;
406
+ ix = this.dates.length - 1;
407
+ }
408
+ format = format || this.o.format;
409
+ var date = this.dates.get(ix);
410
+ return DPGlobal.formatDate(date, format, this.o.language);
411
+ }, this)
412
+ });
413
+ },
414
+
415
+ show: function(){
416
+ if (this.element.attr('readonly') && this.o.enableOnReadonly === false)
417
+ return;
418
+ if (!this.isInline)
419
+ this.picker.appendTo(this.o.container);
420
+ this.place();
421
+ this.picker.show();
422
+ this._attachSecondaryEvents();
423
+ this._trigger('show');
424
+ if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
425
+ $(this.element).blur();
426
+ }
427
+ return this;
428
+ },
429
+
430
+ hide: function(){
431
+ if (this.isInline)
432
+ return this;
433
+ if (!this.picker.is(':visible'))
434
+ return this;
435
+ this.focusDate = null;
436
+ this.picker.hide().detach();
437
+ this._detachSecondaryEvents();
438
+ this.viewMode = this.o.startView;
439
+ this.showMode();
440
+
441
+ if (
442
+ this.o.forceParse &&
443
+ (
444
+ this.isInput && this.element.val() ||
445
+ this.hasInput && this.element.find('input').val()
446
+ )
447
+ )
448
+ this.setValue();
449
+ this._trigger('hide');
450
+ return this;
451
+ },
452
+
453
+ remove: function(){
454
+ this.hide();
455
+ this._detachEvents();
456
+ this._detachSecondaryEvents();
457
+ this.picker.remove();
458
+ delete this.element.data().datepicker;
459
+ if (!this.isInput){
460
+ delete this.element.data().date;
461
+ }
462
+ return this;
463
+ },
464
+
465
+ _utc_to_local: function(utc){
466
+ return utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000));
467
+ },
468
+ _local_to_utc: function(local){
469
+ return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
470
+ },
471
+ _zero_time: function(local){
472
+ return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
473
+ },
474
+ _zero_utc_time: function(utc){
475
+ return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()));
476
+ },
477
+
478
+ getDates: function(){
479
+ return $.map(this.dates, this._utc_to_local);
480
+ },
481
+
482
+ getUTCDates: function(){
483
+ return $.map(this.dates, function(d){
484
+ return new Date(d);
485
+ });
486
+ },
487
+
488
+ getDate: function(){
489
+ return this._utc_to_local(this.getUTCDate());
490
+ },
491
+
492
+ getUTCDate: function(){
493
+ var selected_date = this.dates.get(-1);
494
+ if (typeof selected_date !== 'undefined') {
495
+ return new Date(selected_date);
496
+ } else {
497
+ return null;
498
+ }
499
+ },
500
+
501
+ clearDates: function(){
502
+ var element;
503
+ if (this.isInput) {
504
+ element = this.element;
505
+ } else if (this.component) {
506
+ element = this.element.find('input');
507
+ }
508
+
509
+ if (element) {
510
+ element.val('').change();
511
+ }
512
+
513
+ this.update();
514
+ this._trigger('changeDate');
515
+
516
+ if (this.o.autoclose) {
517
+ this.hide();
518
+ }
519
+ },
520
+ setDates: function(){
521
+ var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
522
+ this.update.apply(this, args);
523
+ this._trigger('changeDate');
524
+ this.setValue();
525
+ return this;
526
+ },
527
+
528
+ setUTCDates: function(){
529
+ var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
530
+ this.update.apply(this, $.map(args, this._utc_to_local));
531
+ this._trigger('changeDate');
532
+ this.setValue();
533
+ return this;
534
+ },
535
+
536
+ setDate: alias('setDates'),
537
+ setUTCDate: alias('setUTCDates'),
538
+
539
+ setValue: function(){
540
+ var formatted = this.getFormattedDate();
541
+ if (!this.isInput){
542
+ if (this.component){
543
+ this.element.find('input').val(formatted).change();
544
+ }
545
+ }
546
+ else {
547
+ this.element.val(formatted).change();
548
+ }
549
+ return this;
550
+ },
551
+
552
+ getFormattedDate: function(format){
553
+ if (format === undefined)
554
+ format = this.o.format;
555
+
556
+ var lang = this.o.language;
557
+ return $.map(this.dates, function(d){
558
+ return DPGlobal.formatDate(d, format, lang);
559
+ }).join(this.o.multidateSeparator);
560
+ },
561
+
562
+ setStartDate: function(startDate){
563
+ this._process_options({startDate: startDate});
564
+ this.update();
565
+ this.updateNavArrows();
566
+ return this;
567
+ },
568
+
569
+ setEndDate: function(endDate){
570
+ this._process_options({endDate: endDate});
571
+ this.update();
572
+ this.updateNavArrows();
573
+ return this;
574
+ },
575
+
576
+ setDaysOfWeekDisabled: function(daysOfWeekDisabled){
577
+ this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
578
+ this.update();
579
+ this.updateNavArrows();
580
+ return this;
581
+ },
582
+
583
+ setDatesDisabled: function(datesDisabled){
584
+ this._process_options({datesDisabled: datesDisabled});
585
+ this.update();
586
+ this.updateNavArrows();
587
+ },
588
+
589
+ place: function(){
590
+ if (this.isInline)
591
+ return this;
592
+ var calendarWidth = this.picker.outerWidth(),
593
+ calendarHeight = this.picker.outerHeight(),
594
+ visualPadding = 10,
595
+ windowWidth = $(this.o.container).width(),
596
+ windowHeight = $(this.o.container).height(),
597
+ scrollTop = $(this.o.container).scrollTop(),
598
+ appendOffset = $(this.o.container).offset();
599
+
600
+ var parentsZindex = [];
601
+ this.element.parents().each(function(){
602
+ var itemZIndex = $(this).css('z-index');
603
+ if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex));
604
+ });
605
+ var zIndex = Math.max.apply(Math, parentsZindex) + 10;
606
+ var offset = this.component ? this.component.parent().offset() : this.element.offset();
607
+ var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
608
+ var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
609
+ var left = offset.left - appendOffset.left,
610
+ top = offset.top - appendOffset.top;
611
+
612
+ this.picker.removeClass(
613
+ 'datepicker-orient-top datepicker-orient-bottom '+
614
+ 'datepicker-orient-right datepicker-orient-left'
615
+ );
616
+
617
+ if (this.o.orientation.x !== 'auto'){
618
+ this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
619
+ if (this.o.orientation.x === 'right')
620
+ left -= calendarWidth - width;
621
+ }
622
+ // auto x orientation is best-placement: if it crosses a window
623
+ // edge, fudge it sideways
624
+ else {
625
+ if (offset.left < 0) {
626
+ // component is outside the window on the left side. Move it into visible range
627
+ this.picker.addClass('datepicker-orient-left');
628
+ left -= offset.left - visualPadding;
629
+ } else if (left + calendarWidth > windowWidth) {
630
+ // the calendar passes the widow right edge. Align it to component right side
631
+ this.picker.addClass('datepicker-orient-right');
632
+ left = offset.left + width - calendarWidth;
633
+ } else {
634
+ // Default to left
635
+ this.picker.addClass('datepicker-orient-left');
636
+ }
637
+ }
638
+
639
+ // auto y orientation is best-situation: top or bottom, no fudging,
640
+ // decision based on which shows more of the calendar
641
+ var yorient = this.o.orientation.y,
642
+ top_overflow, bottom_overflow;
643
+ if (yorient === 'auto'){
644
+ top_overflow = -scrollTop + top - calendarHeight;
645
+ bottom_overflow = scrollTop + windowHeight - (top + height + calendarHeight);
646
+ if (Math.max(top_overflow, bottom_overflow) === bottom_overflow)
647
+ yorient = 'top';
648
+ else
649
+ yorient = 'bottom';
650
+ }
651
+ this.picker.addClass('datepicker-orient-' + yorient);
652
+ if (yorient === 'top')
653
+ top += height;
654
+ else
655
+ top -= calendarHeight + parseInt(this.picker.css('padding-top'));
656
+
657
+ if (this.o.rtl) {
658
+ var right = windowWidth - (left + width);
659
+ this.picker.css({
660
+ top: top,
661
+ right: right,
662
+ zIndex: zIndex
663
+ });
664
+ } else {
665
+ this.picker.css({
666
+ top: top,
667
+ left: left,
668
+ zIndex: zIndex
669
+ });
670
+ }
671
+ return this;
672
+ },
673
+
674
+ _allow_update: true,
675
+ update: function(){
676
+ if (!this._allow_update)
677
+ return this;
678
+
679
+ var oldDates = this.dates.copy(),
680
+ dates = [],
681
+ fromArgs = false;
682
+ if (arguments.length){
683
+ $.each(arguments, $.proxy(function(i, date){
684
+ if (date instanceof Date)
685
+ date = this._local_to_utc(date);
686
+ dates.push(date);
687
+ }, this));
688
+ fromArgs = true;
689
+ }
690
+ else {
691
+ dates = this.isInput
692
+ ? this.element.val()
693
+ : this.element.data('date') || this.element.find('input').val();
694
+ if (dates && this.o.multidate)
695
+ dates = dates.split(this.o.multidateSeparator);
696
+ else
697
+ dates = [dates];
698
+ delete this.element.data().date;
699
+ }
700
+
701
+ dates = $.map(dates, $.proxy(function(date){
702
+ return DPGlobal.parseDate(date, this.o.format, this.o.language);
703
+ }, this));
704
+ dates = $.grep(dates, $.proxy(function(date){
705
+ return (
706
+ date < this.o.startDate ||
707
+ date > this.o.endDate ||
708
+ !date
709
+ );
710
+ }, this), true);
711
+ this.dates.replace(dates);
712
+
713
+ if (this.dates.length)
714
+ this.viewDate = new Date(this.dates.get(-1));
715
+ else if (this.viewDate < this.o.startDate)
716
+ this.viewDate = new Date(this.o.startDate);
717
+ else if (this.viewDate > this.o.endDate)
718
+ this.viewDate = new Date(this.o.endDate);
719
+
720
+ if (fromArgs){
721
+ // setting date by clicking
722
+ this.setValue();
723
+ }
724
+ else if (dates.length){
725
+ // setting date by typing
726
+ if (String(oldDates) !== String(this.dates))
727
+ this._trigger('changeDate');
728
+ }
729
+ if (!this.dates.length && oldDates.length)
730
+ this._trigger('clearDate');
731
+
732
+ this.fill();
733
+ return this;
734
+ },
735
+
736
+ fillDow: function(){
737
+ var dowCnt = this.o.weekStart,
738
+ html = '<tr>';
739
+ if (this.o.calendarWeeks){
740
+ this.picker.find('.datepicker-days thead tr:first-child .datepicker-switch')
741
+ .attr('colspan', function(i, val){
742
+ return parseInt(val) + 1;
743
+ });
744
+ var cell = '<th class="cw">&#160;</th>';
745
+ html += cell;
746
+ }
747
+ while (dowCnt < this.o.weekStart + 7){
748
+ html += '<th class="dow">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
749
+ }
750
+ html += '</tr>';
751
+ this.picker.find('.datepicker-days thead').append(html);
752
+ },
753
+
754
+ fillMonths: function(){
755
+ var html = '',
756
+ i = 0;
757
+ while (i < 12){
758
+ html += '<span class="month">'+dates[this.o.language].monthsShort[i++]+'</span>';
759
+ }
760
+ this.picker.find('.datepicker-months td').html(html);
761
+ },
762
+
763
+ setRange: function(range){
764
+ if (!range || !range.length)
765
+ delete this.range;
766
+ else
767
+ this.range = $.map(range, function(d){
768
+ return d.valueOf();
769
+ });
770
+ this.fill();
771
+ },
772
+
773
+ getClassNames: function(date){
774
+ var cls = [],
775
+ year = this.viewDate.getUTCFullYear(),
776
+ month = this.viewDate.getUTCMonth(),
777
+ today = new Date();
778
+ if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
779
+ cls.push('old');
780
+ }
781
+ else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
782
+ cls.push('new');
783
+ }
784
+ if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
785
+ cls.push('focused');
786
+ // Compare internal UTC date with local today, not UTC today
787
+ if (this.o.todayHighlight &&
788
+ date.getUTCFullYear() === today.getFullYear() &&
789
+ date.getUTCMonth() === today.getMonth() &&
790
+ date.getUTCDate() === today.getDate()){
791
+ cls.push('today');
792
+ }
793
+ if (this.dates.contains(date) !== -1)
794
+ cls.push('active');
795
+ if (date.valueOf() < this.o.startDate || date.valueOf() > this.o.endDate ||
796
+ $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1){
797
+ cls.push('disabled');
798
+ }
799
+ if (this.o.datesDisabled.length > 0 &&
800
+ $.grep(this.o.datesDisabled, function(d){
801
+ return isUTCEquals(date, d); }).length > 0) {
802
+ cls.push('disabled', 'disabled-date');
803
+ }
804
+
805
+ if (this.range){
806
+ if (date > this.range[0] && date < this.range[this.range.length-1]){
807
+ cls.push('range');
808
+ }
809
+ if ($.inArray(date.valueOf(), this.range) !== -1){
810
+ cls.push('selected');
811
+ }
812
+ }
813
+ return cls;
814
+ },
815
+
816
+ fill: function(){
817
+ var d = new Date(this.viewDate),
818
+ year = d.getUTCFullYear(),
819
+ month = d.getUTCMonth(),
820
+ startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
821
+ startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
822
+ endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
823
+ endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
824
+ todaytxt = dates[this.o.language].today || dates['en'].today || '',
825
+ cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
826
+ tooltip;
827
+ if (isNaN(year) || isNaN(month))
828
+ return;
829
+ this.picker.find('.datepicker-days thead .datepicker-switch')
830
+ .text(dates[this.o.language].months[month]+' '+year);
831
+ this.picker.find('tfoot .today')
832
+ .text(todaytxt)
833
+ .toggle(this.o.todayBtn !== false);
834
+ this.picker.find('tfoot .clear')
835
+ .text(cleartxt)
836
+ .toggle(this.o.clearBtn !== false);
837
+ this.updateNavArrows();
838
+ this.fillMonths();
839
+ var prevMonth = UTCDate(year, month-1, 28),
840
+ day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
841
+ prevMonth.setUTCDate(day);
842
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
843
+ var nextMonth = new Date(prevMonth);
844
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
845
+ nextMonth = nextMonth.valueOf();
846
+ var html = [];
847
+ var clsName;
848
+ while (prevMonth.valueOf() < nextMonth){
849
+ if (prevMonth.getUTCDay() === this.o.weekStart){
850
+ html.push('<tr>');
851
+ if (this.o.calendarWeeks){
852
+ // ISO 8601: First week contains first thursday.
853
+ // ISO also states week starts on Monday, but we can be more abstract here.
854
+ var
855
+ // Start of current week: based on weekstart/current date
856
+ ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
857
+ // Thursday of this week
858
+ th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
859
+ // First Thursday of year, year from thursday
860
+ yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
861
+ // Calendar week: ms between thursdays, div ms per day, div 7 days
862
+ calWeek = (th - yth) / 864e5 / 7 + 1;
863
+ html.push('<td class="cw">'+ calWeek +'</td>');
864
+
865
+ }
866
+ }
867
+ clsName = this.getClassNames(prevMonth);
868
+ clsName.push('day');
869
+
870
+ if (this.o.beforeShowDay !== $.noop){
871
+ var before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
872
+ if (before === undefined)
873
+ before = {};
874
+ else if (typeof(before) === 'boolean')
875
+ before = {enabled: before};
876
+ else if (typeof(before) === 'string')
877
+ before = {classes: before};
878
+ if (before.enabled === false)
879
+ clsName.push('disabled');
880
+ if (before.classes)
881
+ clsName = clsName.concat(before.classes.split(/\s+/));
882
+ if (before.tooltip)
883
+ tooltip = before.tooltip;
884
+ }
885
+
886
+ clsName = $.unique(clsName);
887
+ html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>'+prevMonth.getUTCDate() + '</td>');
888
+ tooltip = null;
889
+ if (prevMonth.getUTCDay() === this.o.weekEnd){
890
+ html.push('</tr>');
891
+ }
892
+ prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
893
+ }
894
+ this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
895
+
896
+ var months = this.picker.find('.datepicker-months')
897
+ .find('th:eq(1)')
898
+ .text(year)
899
+ .end()
900
+ .find('span').removeClass('active');
901
+
902
+ $.each(this.dates, function(i, d){
903
+ if (d.getUTCFullYear() === year)
904
+ months.eq(d.getUTCMonth()).addClass('active');
905
+ });
906
+
907
+ if (year < startYear || year > endYear){
908
+ months.addClass('disabled');
909
+ }
910
+ if (year === startYear){
911
+ months.slice(0, startMonth).addClass('disabled');
912
+ }
913
+ if (year === endYear){
914
+ months.slice(endMonth+1).addClass('disabled');
915
+ }
916
+
917
+ if (this.o.beforeShowMonth !== $.noop){
918
+ var that = this;
919
+ $.each(months, function(i, month){
920
+ if (!$(month).hasClass('disabled')) {
921
+ var moDate = new Date(year, i, 1);
922
+ var before = that.o.beforeShowMonth(moDate);
923
+ if (before === false)
924
+ $(month).addClass('disabled');
925
+ }
926
+ });
927
+ }
928
+
929
+ html = '';
930
+ year = parseInt(year/10, 10) * 10;
931
+ var yearCont = this.picker.find('.datepicker-years')
932
+ .find('th:eq(1)')
933
+ .text(year + '-' + (year + 9))
934
+ .end()
935
+ .find('td');
936
+ year -= 1;
937
+ var years = $.map(this.dates, function(d){
938
+ return d.getUTCFullYear();
939
+ }),
940
+ classes;
941
+ for (var i = -1; i < 11; i++){
942
+ classes = ['year'];
943
+ if (i === -1)
944
+ classes.push('old');
945
+ else if (i === 10)
946
+ classes.push('new');
947
+ if ($.inArray(year, years) !== -1)
948
+ classes.push('active');
949
+ if (year < startYear || year > endYear)
950
+ classes.push('disabled');
951
+ html += '<span class="' + classes.join(' ') + '">' + year + '</span>';
952
+ year += 1;
953
+ }
954
+ yearCont.html(html);
955
+ },
956
+
957
+ updateNavArrows: function(){
958
+ if (!this._allow_update)
959
+ return;
960
+
961
+ var d = new Date(this.viewDate),
962
+ year = d.getUTCFullYear(),
963
+ month = d.getUTCMonth();
964
+ switch (this.viewMode){
965
+ case 0:
966
+ if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){
967
+ this.picker.find('.prev').css({visibility: 'hidden'});
968
+ }
969
+ else {
970
+ this.picker.find('.prev').css({visibility: 'visible'});
971
+ }
972
+ if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){
973
+ this.picker.find('.next').css({visibility: 'hidden'});
974
+ }
975
+ else {
976
+ this.picker.find('.next').css({visibility: 'visible'});
977
+ }
978
+ break;
979
+ case 1:
980
+ case 2:
981
+ if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear()){
982
+ this.picker.find('.prev').css({visibility: 'hidden'});
983
+ }
984
+ else {
985
+ this.picker.find('.prev').css({visibility: 'visible'});
986
+ }
987
+ if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear()){
988
+ this.picker.find('.next').css({visibility: 'hidden'});
989
+ }
990
+ else {
991
+ this.picker.find('.next').css({visibility: 'visible'});
992
+ }
993
+ break;
994
+ }
995
+ },
996
+
997
+ click: function(e){
998
+ e.preventDefault();
999
+ var target = $(e.target).closest('span, td, th'),
1000
+ year, month, day;
1001
+ if (target.length === 1){
1002
+ switch (target[0].nodeName.toLowerCase()){
1003
+ case 'th':
1004
+ switch (target[0].className){
1005
+ case 'datepicker-switch':
1006
+ this.showMode(1);
1007
+ break;
1008
+ case 'prev':
1009
+ case 'next':
1010
+ var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);
1011
+ switch (this.viewMode){
1012
+ case 0:
1013
+ this.viewDate = this.moveMonth(this.viewDate, dir);
1014
+ this._trigger('changeMonth', this.viewDate);
1015
+ break;
1016
+ case 1:
1017
+ case 2:
1018
+ this.viewDate = this.moveYear(this.viewDate, dir);
1019
+ if (this.viewMode === 1)
1020
+ this._trigger('changeYear', this.viewDate);
1021
+ break;
1022
+ }
1023
+ this.fill();
1024
+ break;
1025
+ case 'today':
1026
+ var date = new Date();
1027
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
1028
+
1029
+ this.showMode(-2);
1030
+ var which = this.o.todayBtn === 'linked' ? null : 'view';
1031
+ this._setDate(date, which);
1032
+ break;
1033
+ case 'clear':
1034
+ this.clearDates();
1035
+ break;
1036
+ }
1037
+ break;
1038
+ case 'span':
1039
+ if (!target.hasClass('disabled')){
1040
+ this.viewDate.setUTCDate(1);
1041
+ if (target.hasClass('month')){
1042
+ day = 1;
1043
+ month = target.parent().find('span').index(target);
1044
+ year = this.viewDate.getUTCFullYear();
1045
+ this.viewDate.setUTCMonth(month);
1046
+ this._trigger('changeMonth', this.viewDate);
1047
+ if (this.o.minViewMode === 1){
1048
+ this._setDate(UTCDate(year, month, day));
1049
+ }
1050
+ }
1051
+ else {
1052
+ day = 1;
1053
+ month = 0;
1054
+ year = parseInt(target.text(), 10)||0;
1055
+ this.viewDate.setUTCFullYear(year);
1056
+ this._trigger('changeYear', this.viewDate);
1057
+ if (this.o.minViewMode === 2){
1058
+ this._setDate(UTCDate(year, month, day));
1059
+ }
1060
+ }
1061
+ this.showMode(-1);
1062
+ this.fill();
1063
+ }
1064
+ break;
1065
+ case 'td':
1066
+ if (target.hasClass('day') && !target.hasClass('disabled')){
1067
+ day = parseInt(target.text(), 10)||1;
1068
+ year = this.viewDate.getUTCFullYear();
1069
+ month = this.viewDate.getUTCMonth();
1070
+ if (target.hasClass('old')){
1071
+ if (month === 0){
1072
+ month = 11;
1073
+ year -= 1;
1074
+ }
1075
+ else {
1076
+ month -= 1;
1077
+ }
1078
+ }
1079
+ else if (target.hasClass('new')){
1080
+ if (month === 11){
1081
+ month = 0;
1082
+ year += 1;
1083
+ }
1084
+ else {
1085
+ month += 1;
1086
+ }
1087
+ }
1088
+ this._setDate(UTCDate(year, month, day));
1089
+ }
1090
+ break;
1091
+ }
1092
+ }
1093
+ if (this.picker.is(':visible') && this._focused_from){
1094
+ $(this._focused_from).focus();
1095
+ }
1096
+ delete this._focused_from;
1097
+ },
1098
+
1099
+ _toggle_multidate: function(date){
1100
+ var ix = this.dates.contains(date);
1101
+ if (!date){
1102
+ this.dates.clear();
1103
+ }
1104
+
1105
+ if (ix !== -1){
1106
+ if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
1107
+ this.dates.remove(ix);
1108
+ }
1109
+ } else if (this.o.multidate === false) {
1110
+ this.dates.clear();
1111
+ this.dates.push(date);
1112
+ }
1113
+ else {
1114
+ this.dates.push(date);
1115
+ }
1116
+
1117
+ if (typeof this.o.multidate === 'number')
1118
+ while (this.dates.length > this.o.multidate)
1119
+ this.dates.remove(0);
1120
+ },
1121
+
1122
+ _setDate: function(date, which){
1123
+ if (!which || which === 'date')
1124
+ this._toggle_multidate(date && new Date(date));
1125
+ if (!which || which === 'view')
1126
+ this.viewDate = date && new Date(date);
1127
+
1128
+ this.fill();
1129
+ this.setValue();
1130
+ if (!which || which !== 'view') {
1131
+ this._trigger('changeDate');
1132
+ }
1133
+ var element;
1134
+ if (this.isInput){
1135
+ element = this.element;
1136
+ }
1137
+ else if (this.component){
1138
+ element = this.element.find('input');
1139
+ }
1140
+ if (element){
1141
+ element.change();
1142
+ }
1143
+ if (this.o.autoclose && (!which || which === 'date')){
1144
+ this.hide();
1145
+ }
1146
+ },
1147
+
1148
+ moveMonth: function(date, dir){
1149
+ if (!date)
1150
+ return undefined;
1151
+ if (!dir)
1152
+ return date;
1153
+ var new_date = new Date(date.valueOf()),
1154
+ day = new_date.getUTCDate(),
1155
+ month = new_date.getUTCMonth(),
1156
+ mag = Math.abs(dir),
1157
+ new_month, test;
1158
+ dir = dir > 0 ? 1 : -1;
1159
+ if (mag === 1){
1160
+ test = dir === -1
1161
+ // If going back one month, make sure month is not current month
1162
+ // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
1163
+ ? function(){
1164
+ return new_date.getUTCMonth() === month;
1165
+ }
1166
+ // If going forward one month, make sure month is as expected
1167
+ // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
1168
+ : function(){
1169
+ return new_date.getUTCMonth() !== new_month;
1170
+ };
1171
+ new_month = month + dir;
1172
+ new_date.setUTCMonth(new_month);
1173
+ // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1174
+ if (new_month < 0 || new_month > 11)
1175
+ new_month = (new_month + 12) % 12;
1176
+ }
1177
+ else {
1178
+ // For magnitudes >1, move one month at a time...
1179
+ for (var i=0; i < mag; i++)
1180
+ // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
1181
+ new_date = this.moveMonth(new_date, dir);
1182
+ // ...then reset the day, keeping it in the new month
1183
+ new_month = new_date.getUTCMonth();
1184
+ new_date.setUTCDate(day);
1185
+ test = function(){
1186
+ return new_month !== new_date.getUTCMonth();
1187
+ };
1188
+ }
1189
+ // Common date-resetting loop -- if date is beyond end of month, make it
1190
+ // end of month
1191
+ while (test()){
1192
+ new_date.setUTCDate(--day);
1193
+ new_date.setUTCMonth(new_month);
1194
+ }
1195
+ return new_date;
1196
+ },
1197
+
1198
+ moveYear: function(date, dir){
1199
+ return this.moveMonth(date, dir*12);
1200
+ },
1201
+
1202
+ dateWithinRange: function(date){
1203
+ return date >= this.o.startDate && date <= this.o.endDate;
1204
+ },
1205
+
1206
+ keydown: function(e){
1207
+ if (!this.picker.is(':visible')){
1208
+ if (e.keyCode === 27) // allow escape to hide and re-show picker
1209
+ this.show();
1210
+ return;
1211
+ }
1212
+ var dateChanged = false,
1213
+ dir, newDate, newViewDate,
1214
+ focusDate = this.focusDate || this.viewDate;
1215
+ switch (e.keyCode){
1216
+ case 27: // escape
1217
+ if (this.focusDate){
1218
+ this.focusDate = null;
1219
+ this.viewDate = this.dates.get(-1) || this.viewDate;
1220
+ this.fill();
1221
+ }
1222
+ else
1223
+ this.hide();
1224
+ e.preventDefault();
1225
+ break;
1226
+ case 37: // left
1227
+ case 39: // right
1228
+ if (!this.o.keyboardNavigation)
1229
+ break;
1230
+ dir = e.keyCode === 37 ? -1 : 1;
1231
+ if (e.ctrlKey){
1232
+ newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);
1233
+ newViewDate = this.moveYear(focusDate, dir);
1234
+ this._trigger('changeYear', this.viewDate);
1235
+ }
1236
+ else if (e.shiftKey){
1237
+ newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);
1238
+ newViewDate = this.moveMonth(focusDate, dir);
1239
+ this._trigger('changeMonth', this.viewDate);
1240
+ }
1241
+ else {
1242
+ newDate = new Date(this.dates.get(-1) || UTCToday());
1243
+ newDate.setUTCDate(newDate.getUTCDate() + dir);
1244
+ newViewDate = new Date(focusDate);
1245
+ newViewDate.setUTCDate(focusDate.getUTCDate() + dir);
1246
+ }
1247
+ if (this.dateWithinRange(newViewDate)){
1248
+ this.focusDate = this.viewDate = newViewDate;
1249
+ this.setValue();
1250
+ this.fill();
1251
+ e.preventDefault();
1252
+ }
1253
+ break;
1254
+ case 38: // up
1255
+ case 40: // down
1256
+ if (!this.o.keyboardNavigation)
1257
+ break;
1258
+ dir = e.keyCode === 38 ? -1 : 1;
1259
+ if (e.ctrlKey){
1260
+ newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);
1261
+ newViewDate = this.moveYear(focusDate, dir);
1262
+ this._trigger('changeYear', this.viewDate);
1263
+ }
1264
+ else if (e.shiftKey){
1265
+ newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);
1266
+ newViewDate = this.moveMonth(focusDate, dir);
1267
+ this._trigger('changeMonth', this.viewDate);
1268
+ }
1269
+ else {
1270
+ newDate = new Date(this.dates.get(-1) || UTCToday());
1271
+ newDate.setUTCDate(newDate.getUTCDate() + dir * 7);
1272
+ newViewDate = new Date(focusDate);
1273
+ newViewDate.setUTCDate(focusDate.getUTCDate() + dir * 7);
1274
+ }
1275
+ if (this.dateWithinRange(newViewDate)){
1276
+ this.focusDate = this.viewDate = newViewDate;
1277
+ this.setValue();
1278
+ this.fill();
1279
+ e.preventDefault();
1280
+ }
1281
+ break;
1282
+ case 32: // spacebar
1283
+ // Spacebar is used in manually typing dates in some formats.
1284
+ // As such, its behavior should not be hijacked.
1285
+ break;
1286
+ case 13: // enter
1287
+ focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
1288
+ if (this.o.keyboardNavigation) {
1289
+ this._toggle_multidate(focusDate);
1290
+ dateChanged = true;
1291
+ }
1292
+ this.focusDate = null;
1293
+ this.viewDate = this.dates.get(-1) || this.viewDate;
1294
+ this.setValue();
1295
+ this.fill();
1296
+ if (this.picker.is(':visible')){
1297
+ e.preventDefault();
1298
+ if (typeof e.stopPropagation === 'function') {
1299
+ e.stopPropagation(); // All modern browsers, IE9+
1300
+ } else {
1301
+ e.cancelBubble = true; // IE6,7,8 ignore "stopPropagation"
1302
+ }
1303
+ if (this.o.autoclose)
1304
+ this.hide();
1305
+ }
1306
+ break;
1307
+ case 9: // tab
1308
+ this.focusDate = null;
1309
+ this.viewDate = this.dates.get(-1) || this.viewDate;
1310
+ this.fill();
1311
+ this.hide();
1312
+ break;
1313
+ }
1314
+ if (dateChanged){
1315
+ if (this.dates.length)
1316
+ this._trigger('changeDate');
1317
+ else
1318
+ this._trigger('clearDate');
1319
+ var element;
1320
+ if (this.isInput){
1321
+ element = this.element;
1322
+ }
1323
+ else if (this.component){
1324
+ element = this.element.find('input');
1325
+ }
1326
+ if (element){
1327
+ element.change();
1328
+ }
1329
+ }
1330
+ },
1331
+
1332
+ showMode: function(dir){
1333
+ if (dir){
1334
+ this.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir));
1335
+ }
1336
+ this.picker
1337
+ .children('div')
1338
+ .hide()
1339
+ .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
1340
+ .css('display', 'block');
1341
+ this.updateNavArrows();
1342
+ }
1343
+ };
1344
+
1345
+ var DateRangePicker = function(element, options){
1346
+ this.element = $(element);
1347
+ this.inputs = $.map(options.inputs, function(i){
1348
+ return i.jquery ? i[0] : i;
1349
+ });
1350
+ delete options.inputs;
1351
+
1352
+ datepickerPlugin.call($(this.inputs), options)
1353
+ .bind('changeDate', $.proxy(this.dateUpdated, this));
1354
+
1355
+ this.pickers = $.map(this.inputs, function(i){
1356
+ return $(i).data('datepicker');
1357
+ });
1358
+ this.updateDates();
1359
+ };
1360
+ DateRangePicker.prototype = {
1361
+ updateDates: function(){
1362
+ this.dates = $.map(this.pickers, function(i){
1363
+ return i.getUTCDate();
1364
+ });
1365
+ this.updateRanges();
1366
+ },
1367
+ updateRanges: function(){
1368
+ var range = $.map(this.dates, function(d){
1369
+ return d.valueOf();
1370
+ });
1371
+ $.each(this.pickers, function(i, p){
1372
+ p.setRange(range);
1373
+ });
1374
+ },
1375
+ dateUpdated: function(e){
1376
+ // `this.updating` is a workaround for preventing infinite recursion
1377
+ // between `changeDate` triggering and `setUTCDate` calling. Until
1378
+ // there is a better mechanism.
1379
+ if (this.updating)
1380
+ return;
1381
+ this.updating = true;
1382
+
1383
+ var dp = $(e.target).data('datepicker'),
1384
+ new_date = dp.getUTCDate(),
1385
+ i = $.inArray(e.target, this.inputs),
1386
+ j = i - 1,
1387
+ k = i + 1,
1388
+ l = this.inputs.length;
1389
+ if (i === -1)
1390
+ return;
1391
+
1392
+ $.each(this.pickers, function(i, p){
1393
+ if (!p.getUTCDate())
1394
+ p.setUTCDate(new_date);
1395
+ });
1396
+
1397
+ if (new_date < this.dates[j]){
1398
+ // Date being moved earlier/left
1399
+ while (j >= 0 && new_date < this.dates[j]){
1400
+ this.pickers[j--].setUTCDate(new_date);
1401
+ }
1402
+ }
1403
+ else if (new_date > this.dates[k]){
1404
+ // Date being moved later/right
1405
+ while (k < l && new_date > this.dates[k]){
1406
+ this.pickers[k++].setUTCDate(new_date);
1407
+ }
1408
+ }
1409
+ this.updateDates();
1410
+
1411
+ delete this.updating;
1412
+ },
1413
+ remove: function(){
1414
+ $.map(this.pickers, function(p){ p.remove(); });
1415
+ delete this.element.data().datepicker;
1416
+ }
1417
+ };
1418
+
1419
+ function opts_from_el(el, prefix){
1420
+ // Derive options from element data-attrs
1421
+ var data = $(el).data(),
1422
+ out = {}, inkey,
1423
+ replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
1424
+ prefix = new RegExp('^' + prefix.toLowerCase());
1425
+ function re_lower(_,a){
1426
+ return a.toLowerCase();
1427
+ }
1428
+ for (var key in data)
1429
+ if (prefix.test(key)){
1430
+ inkey = key.replace(replace, re_lower);
1431
+ out[inkey] = data[key];
1432
+ }
1433
+ return out;
1434
+ }
1435
+
1436
+ function opts_from_locale(lang){
1437
+ // Derive options from locale plugins
1438
+ var out = {};
1439
+ // Check if "de-DE" style date is available, if not language should
1440
+ // fallback to 2 letter code eg "de"
1441
+ if (!dates[lang]){
1442
+ lang = lang.split('-')[0];
1443
+ if (!dates[lang])
1444
+ return;
1445
+ }
1446
+ var d = dates[lang];
1447
+ $.each(locale_opts, function(i,k){
1448
+ if (k in d)
1449
+ out[k] = d[k];
1450
+ });
1451
+ return out;
1452
+ }
1453
+
1454
+ var old = $.fn.datepicker;
1455
+ var datepickerPlugin = function(option){
1456
+ var args = Array.apply(null, arguments);
1457
+ args.shift();
1458
+ var internal_return;
1459
+ this.each(function(){
1460
+ var $this = $(this),
1461
+ data = $this.data('datepicker'),
1462
+ options = typeof option === 'object' && option;
1463
+ if (!data){
1464
+ var elopts = opts_from_el(this, 'date'),
1465
+ // Preliminary otions
1466
+ xopts = $.extend({}, defaults, elopts, options),
1467
+ locopts = opts_from_locale(xopts.language),
1468
+ // Options priority: js args, data-attrs, locales, defaults
1469
+ opts = $.extend({}, defaults, locopts, elopts, options);
1470
+ if ($this.hasClass('input-daterange') || opts.inputs){
1471
+ var ropts = {
1472
+ inputs: opts.inputs || $this.find('input').toArray()
1473
+ };
1474
+ $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, ropts))));
1475
+ }
1476
+ else {
1477
+ $this.data('datepicker', (data = new Datepicker(this, opts)));
1478
+ }
1479
+ }
1480
+ if (typeof option === 'string' && typeof data[option] === 'function'){
1481
+ internal_return = data[option].apply(data, args);
1482
+ if (internal_return !== undefined)
1483
+ return false;
1484
+ }
1485
+ });
1486
+ if (internal_return !== undefined)
1487
+ return internal_return;
1488
+ else
1489
+ return this;
1490
+ };
1491
+ $.fn.datepicker = datepickerPlugin;
1492
+
1493
+ var defaults = $.fn.datepicker.defaults = {
1494
+ autoclose: false,
1495
+ beforeShowDay: $.noop,
1496
+ beforeShowMonth: $.noop,
1497
+ calendarWeeks: false,
1498
+ clearBtn: false,
1499
+ toggleActive: false,
1500
+ daysOfWeekDisabled: [],
1501
+ datesDisabled: [],
1502
+ endDate: Infinity,
1503
+ forceParse: true,
1504
+ format: 'mm/dd/yyyy',
1505
+ keyboardNavigation: true,
1506
+ language: 'en',
1507
+ minViewMode: 0,
1508
+ multidate: false,
1509
+ multidateSeparator: ',',
1510
+ orientation: "auto",
1511
+ rtl: false,
1512
+ startDate: -Infinity,
1513
+ startView: 0,
1514
+ todayBtn: false,
1515
+ todayHighlight: false,
1516
+ weekStart: 0,
1517
+ disableTouchKeyboard: false,
1518
+ enableOnReadonly: true,
1519
+ container: 'body'
1520
+ };
1521
+ var locale_opts = $.fn.datepicker.locale_opts = [
1522
+ 'format',
1523
+ 'rtl',
1524
+ 'weekStart'
1525
+ ];
1526
+ $.fn.datepicker.Constructor = Datepicker;
1527
+ var dates = $.fn.datepicker.dates = {
1528
+ en: {
1529
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
1530
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
1531
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
1532
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
1533
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1534
+ today: "Today",
1535
+ clear: "Clear"
1536
+ }
1537
+ };
1538
+
1539
+ var DPGlobal = {
1540
+ modes: [
1541
+ {
1542
+ clsName: 'days',
1543
+ navFnc: 'Month',
1544
+ navStep: 1
1545
+ },
1546
+ {
1547
+ clsName: 'months',
1548
+ navFnc: 'FullYear',
1549
+ navStep: 1
1550
+ },
1551
+ {
1552
+ clsName: 'years',
1553
+ navFnc: 'FullYear',
1554
+ navStep: 10
1555
+ }],
1556
+ isLeapYear: function(year){
1557
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
1558
+ },
1559
+ getDaysInMonth: function(year, month){
1560
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1561
+ },
1562
+ validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1563
+ nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
1564
+ parseFormat: function(format){
1565
+ // IE treats \0 as a string end in inputs (truncating the value),
1566
+ // so it's a bad format delimiter, anyway
1567
+ var separators = format.replace(this.validParts, '\0').split('\0'),
1568
+ parts = format.match(this.validParts);
1569
+ if (!separators || !separators.length || !parts || parts.length === 0){
1570
+ throw new Error("Invalid date format.");
1571
+ }
1572
+ return {separators: separators, parts: parts};
1573
+ },
1574
+ parseDate: function(date, format, language){
1575
+ if (!date)
1576
+ return undefined;
1577
+ if (date instanceof Date)
1578
+ return date;
1579
+ if (typeof format === 'string')
1580
+ format = DPGlobal.parseFormat(format);
1581
+ var part_re = /([\-+]\d+)([dmwy])/,
1582
+ parts = date.match(/([\-+]\d+)([dmwy])/g),
1583
+ part, dir, i;
1584
+ if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1585
+ date = new Date();
1586
+ for (i=0; i < parts.length; i++){
1587
+ part = part_re.exec(parts[i]);
1588
+ dir = parseInt(part[1]);
1589
+ switch (part[2]){
1590
+ case 'd':
1591
+ date.setUTCDate(date.getUTCDate() + dir);
1592
+ break;
1593
+ case 'm':
1594
+ date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
1595
+ break;
1596
+ case 'w':
1597
+ date.setUTCDate(date.getUTCDate() + dir * 7);
1598
+ break;
1599
+ case 'y':
1600
+ date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
1601
+ break;
1602
+ }
1603
+ }
1604
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
1605
+ }
1606
+ parts = date && date.match(this.nonpunctuation) || [];
1607
+ date = new Date();
1608
+ var parsed = {},
1609
+ setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1610
+ setters_map = {
1611
+ yyyy: function(d,v){
1612
+ return d.setUTCFullYear(v);
1613
+ },
1614
+ yy: function(d,v){
1615
+ return d.setUTCFullYear(2000+v);
1616
+ },
1617
+ m: function(d,v){
1618
+ if (isNaN(d))
1619
+ return d;
1620
+ v -= 1;
1621
+ while (v < 0) v += 12;
1622
+ v %= 12;
1623
+ d.setUTCMonth(v);
1624
+ while (d.getUTCMonth() !== v)
1625
+ d.setUTCDate(d.getUTCDate()-1);
1626
+ return d;
1627
+ },
1628
+ d: function(d,v){
1629
+ return d.setUTCDate(v);
1630
+ }
1631
+ },
1632
+ val, filtered;
1633
+ setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1634
+ setters_map['dd'] = setters_map['d'];
1635
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
1636
+ var fparts = format.parts.slice();
1637
+ // Remove noop parts
1638
+ if (parts.length !== fparts.length){
1639
+ fparts = $(fparts).filter(function(i,p){
1640
+ return $.inArray(p, setters_order) !== -1;
1641
+ }).toArray();
1642
+ }
1643
+ // Process remainder
1644
+ function match_part(){
1645
+ var m = this.slice(0, parts[i].length),
1646
+ p = parts[i].slice(0, m.length);
1647
+ return m.toLowerCase() === p.toLowerCase();
1648
+ }
1649
+ if (parts.length === fparts.length){
1650
+ var cnt;
1651
+ for (i=0, cnt = fparts.length; i < cnt; i++){
1652
+ val = parseInt(parts[i], 10);
1653
+ part = fparts[i];
1654
+ if (isNaN(val)){
1655
+ switch (part){
1656
+ case 'MM':
1657
+ filtered = $(dates[language].months).filter(match_part);
1658
+ val = $.inArray(filtered[0], dates[language].months) + 1;
1659
+ break;
1660
+ case 'M':
1661
+ filtered = $(dates[language].monthsShort).filter(match_part);
1662
+ val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1663
+ break;
1664
+ }
1665
+ }
1666
+ parsed[part] = val;
1667
+ }
1668
+ var _date, s;
1669
+ for (i=0; i < setters_order.length; i++){
1670
+ s = setters_order[i];
1671
+ if (s in parsed && !isNaN(parsed[s])){
1672
+ _date = new Date(date);
1673
+ setters_map[s](_date, parsed[s]);
1674
+ if (!isNaN(_date))
1675
+ date = _date;
1676
+ }
1677
+ }
1678
+ }
1679
+ return date;
1680
+ },
1681
+ formatDate: function(date, format, language){
1682
+ if (!date)
1683
+ return '';
1684
+ if (typeof format === 'string')
1685
+ format = DPGlobal.parseFormat(format);
1686
+ var val = {
1687
+ d: date.getUTCDate(),
1688
+ D: dates[language].daysShort[date.getUTCDay()],
1689
+ DD: dates[language].days[date.getUTCDay()],
1690
+ m: date.getUTCMonth() + 1,
1691
+ M: dates[language].monthsShort[date.getUTCMonth()],
1692
+ MM: dates[language].months[date.getUTCMonth()],
1693
+ yy: date.getUTCFullYear().toString().substring(2),
1694
+ yyyy: date.getUTCFullYear()
1695
+ };
1696
+ val.dd = (val.d < 10 ? '0' : '') + val.d;
1697
+ val.mm = (val.m < 10 ? '0' : '') + val.m;
1698
+ date = [];
1699
+ var seps = $.extend([], format.separators);
1700
+ for (var i=0, cnt = format.parts.length; i <= cnt; i++){
1701
+ if (seps.length)
1702
+ date.push(seps.shift());
1703
+ date.push(val[format.parts[i]]);
1704
+ }
1705
+ return date.join('');
1706
+ },
1707
+ headTemplate: '<thead>'+
1708
+ '<tr>'+
1709
+ '<th class="prev">&#171;</th>'+
1710
+ '<th colspan="5" class="datepicker-switch"></th>'+
1711
+ '<th class="next">&#187;</th>'+
1712
+ '</tr>'+
1713
+ '</thead>',
1714
+ contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1715
+ footTemplate: '<tfoot>'+
1716
+ '<tr>'+
1717
+ '<th colspan="7" class="today"></th>'+
1718
+ '</tr>'+
1719
+ '<tr>'+
1720
+ '<th colspan="7" class="clear"></th>'+
1721
+ '</tr>'+
1722
+ '</tfoot>'
1723
+ };
1724
+ DPGlobal.template = '<div class="datepicker">'+
1725
+ '<div class="datepicker-days">'+
1726
+ '<table class=" table-condensed">'+
1727
+ DPGlobal.headTemplate+
1728
+ '<tbody></tbody>'+
1729
+ DPGlobal.footTemplate+
1730
+ '</table>'+
1731
+ '</div>'+
1732
+ '<div class="datepicker-months">'+
1733
+ '<table class="table-condensed">'+
1734
+ DPGlobal.headTemplate+
1735
+ DPGlobal.contTemplate+
1736
+ DPGlobal.footTemplate+
1737
+ '</table>'+
1738
+ '</div>'+
1739
+ '<div class="datepicker-years">'+
1740
+ '<table class="table-condensed">'+
1741
+ DPGlobal.headTemplate+
1742
+ DPGlobal.contTemplate+
1743
+ DPGlobal.footTemplate+
1744
+ '</table>'+
1745
+ '</div>'+
1746
+ '</div>';
1747
+
1748
+ $.fn.datepicker.DPGlobal = DPGlobal;
1749
+
1750
+
1751
+ /* DATEPICKER NO CONFLICT
1752
+ * =================== */
1753
+
1754
+ $.fn.datepicker.noConflict = function(){
1755
+ $.fn.datepicker = old;
1756
+ return this;
1757
+ };
1758
+
1759
+ /* DATEPICKER VERSION
1760
+ * =================== */
1761
+ $.fn.datepicker.version = "1.4.0";
1762
+
1763
+ /* DATEPICKER DATA-API
1764
+ * ================== */
1765
+
1766
+ $(document).on(
1767
+ 'focus.datepicker.data-api click.datepicker.data-api',
1768
+ '[data-provide="datepicker"]',
1769
+ function(e){
1770
+ var $this = $(this);
1771
+ if ($this.data('datepicker'))
1772
+ return;
1773
+ e.preventDefault();
1774
+ // component click requires us to explicitly show it
1775
+ datepickerPlugin.call($this, 'show');
1776
+ }
1777
+ );
1778
+ $(function(){
1779
+ datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
1780
+ });
1781
+
1782
+ }(window.jQuery));