bootstrap-datetime-picker-for-rails 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +20 -0
  3. data/Rakefile +23 -0
  4. data/lib/bootstrap-datetimepicker-rails.rb +4 -0
  5. data/lib/bootstrap-datetimepicker-rails/engine.rb +4 -0
  6. data/lib/bootstrap-datetimepicker-rails/version.rb +3 -0
  7. data/lib/tasks/bootstrap-datetimepicker-rails_tasks.rake +4 -0
  8. data/vendor/assets/javascripts/bootstrap-datetimepicker/bootstrap-datetimepicker.js +1473 -0
  9. data/vendor/assets/javascripts/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js +1 -0
  10. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.bg.js +16 -0
  11. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.ca.js +16 -0
  12. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.cs.js +17 -0
  13. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.da.js +16 -0
  14. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.de.js +18 -0
  15. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.el.js +15 -0
  16. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.es.js +16 -0
  17. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.fi.js +16 -0
  18. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.fr.js +18 -0
  19. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.he.js +17 -0
  20. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.hr.js +15 -0
  21. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.hu.js +17 -0
  22. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.id.js +15 -0
  23. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.is.js +16 -0
  24. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.it.js +18 -0
  25. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.ja.js +15 -0
  26. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.kr.js +15 -0
  27. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.lt.js +18 -0
  28. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.lv.js +18 -0
  29. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.ms.js +16 -0
  30. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.nb.js +16 -0
  31. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.nl.js +16 -0
  32. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.pl.js +17 -0
  33. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.pt-BR.js +16 -0
  34. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.pt.js +16 -0
  35. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.ro.js +17 -0
  36. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.rs-latin.js +16 -0
  37. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.rs.js +16 -0
  38. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.ru.js +16 -0
  39. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.sk.js +17 -0
  40. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.sl.js +16 -0
  41. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.sv.js +16 -0
  42. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.sw.js +17 -0
  43. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.th.js +16 -0
  44. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.tr.js +17 -0
  45. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.uk.js +16 -0
  46. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.zh-CN.js +16 -0
  47. data/vendor/assets/javascripts/bootstrap-datetimepicker/locales/bootstrap-datetimepicker.zh-TW.js +15 -0
  48. data/vendor/assets/stylesheets/bootstrap-datetimepicker.css +366 -0
  49. metadata +116 -0
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ ##Bootstrap Datetimepicker Rails
2
+
3
+ Add [http://www.malot.fr/bootstrap-datetimepicker/](http://www.malot.fr/bootstrap-datetimepicker/index.php) to the rails asset pipeline.
4
+
5
+ ### Install
6
+
7
+ gem install bootstrap-datetime-picker-for-rails
8
+
9
+ In application.js
10
+
11
+ //= require bootstrap-datetimepicker/bootstrap-datetimepicker
12
+ //= require bootstrap-datetimepicker/locales/bootstrap-datetimepicker.[locale] # if you need extra locales
13
+
14
+
15
+ In application.css
16
+
17
+ *= require bootstrap-datetimepicker
18
+
19
+
20
+
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'BootstrapDatetimepickerRails'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.md')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,4 @@
1
+ require "bootstrap-datetimepicker-rails/engine"
2
+
3
+ module BootstrapDatetimepickerRails
4
+ end
@@ -0,0 +1,4 @@
1
+ module BootstrapDatetimepickerRails
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module BootstrapDatetimepickerRails
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :bootstrap-datetimepicker-rails do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,1473 @@
1
+ /* =========================================================
2
+ * bootstrap-datetimepicker.js
3
+ * =========================================================
4
+ * Copyright 2012 Stefan Petre
5
+ * Improvements by Andrew Rowls
6
+ * Improvements by Sébastien Malot
7
+ * Project URL : http://www.malot.fr/bootstrap-datetimepicker
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ * ========================================================= */
21
+
22
+ !function( $ ) {
23
+
24
+ function UTCDate(){
25
+ return new Date(Date.UTC.apply(Date, arguments));
26
+ }
27
+ function UTCToday(){
28
+ var today = new Date();
29
+ return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), today.getUTCHours(), today.getUTCMinutes(), today.getUTCSeconds(), 0);
30
+ }
31
+
32
+ // Picker object
33
+
34
+ var Datetimepicker = function(element, options) {
35
+ var that = this;
36
+
37
+ this.element = $(element);
38
+ this.language = options.language || this.element.data('date-language') || "en";
39
+ this.language = this.language in dates ? this.language : "en";
40
+ this.isRTL = dates[this.language].rtl || false;
41
+ this.formatType = options.formatType || this.element.data('format-type') || 'standard';
42
+ this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType);
43
+ this.isInline = false;
44
+ this.isVisible = false;
45
+ this.isInput = this.element.is('input');
46
+ this.component = this.element.is('.date') ? this.element.find('.add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar').parent() : false;
47
+ this.componentReset = this.element.is('.date') ? this.element.find('.add-on .icon-remove').parent() : false;
48
+ this.hasInput = this.component && this.element.find('input').length;
49
+ if (this.component && this.component.length === 0) {
50
+ this.component = false;
51
+ }
52
+ this.linkField = options.linkField || this.element.data('link-field') || false;
53
+ this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType);
54
+ this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
55
+ this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
56
+ this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false;
57
+ this.initialDate = options.initialDate || new Date();
58
+
59
+ this._attachEvents();
60
+
61
+ this.formatViewType = "datetime";
62
+ if ('formatViewType' in options) {
63
+ this.formatViewType = options.formatViewType;
64
+ } else if ('formatViewType' in this.element.data()) {
65
+ this.formatViewType = this.element.data('formatViewType');
66
+ }
67
+
68
+ this.minView = 0;
69
+ if ('minView' in options) {
70
+ this.minView = options.minView;
71
+ } else if ('minView' in this.element.data()) {
72
+ this.minView = this.element.data('min-view');
73
+ }
74
+ this.minView = DPGlobal.convertViewMode(this.minView);
75
+
76
+ this.maxView = DPGlobal.modes.length-1;
77
+ if ('maxView' in options) {
78
+ this.maxView = options.maxView;
79
+ } else if ('maxView' in this.element.data()) {
80
+ this.maxView = this.element.data('max-view');
81
+ }
82
+ this.maxView = DPGlobal.convertViewMode(this.maxView);
83
+
84
+ this.startViewMode = 2;
85
+ if ('startView' in options) {
86
+ this.startViewMode = options.startView;
87
+ } else if ('startView' in this.element.data()) {
88
+ this.startViewMode = this.element.data('start-view');
89
+ }
90
+ this.startViewMode = DPGlobal.convertViewMode(this.startViewMode);
91
+ this.viewMode = this.startViewMode;
92
+
93
+ this.viewSelect = this.minView;
94
+ if ('viewSelect' in options) {
95
+ this.viewSelect = options.viewSelect;
96
+ } else if ('viewSelect' in this.element.data()) {
97
+ this.viewSelect = this.element.data('view-select');
98
+ }
99
+ this.viewSelect = DPGlobal.convertViewMode(this.viewSelect);
100
+
101
+ this.forceParse = true;
102
+ if ('forceParse' in options) {
103
+ this.forceParse = options.forceParse;
104
+ } else if ('dateForceParse' in this.element.data()) {
105
+ this.forceParse = this.element.data('date-force-parse');
106
+ }
107
+
108
+ this.picker = $(DPGlobal.template)
109
+ .appendTo(this.isInline ? this.element : 'body')
110
+ .on({
111
+ click: $.proxy(this.click, this),
112
+ mousedown: $.proxy(this.mousedown, this)
113
+ });
114
+
115
+ if (this.isInline) {
116
+ this.picker.addClass('datetimepicker-inline');
117
+ } else {
118
+ this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu');
119
+ }
120
+ if (this.isRTL){
121
+ this.picker.addClass('datetimepicker-rtl');
122
+ this.picker.find('.prev i, .next i')
123
+ .toggleClass('icon-arrow-left icon-arrow-right');
124
+ }
125
+ $(document).on('mousedown', function (e) {
126
+ // Clicked outside the datetimepicker, hide it
127
+ if ($(e.target).closest('.datetimepicker').length === 0) {
128
+ that.hide();
129
+ }
130
+ });
131
+
132
+ this.autoclose = false;
133
+ if ('autoclose' in options) {
134
+ this.autoclose = options.autoclose;
135
+ } else if ('dateAutoclose' in this.element.data()) {
136
+ this.autoclose = this.element.data('date-autoclose');
137
+ }
138
+
139
+ this.keyboardNavigation = true;
140
+ if ('keyboardNavigation' in options) {
141
+ this.keyboardNavigation = options.keyboardNavigation;
142
+ } else if ('dateKeyboardNavigation' in this.element.data()) {
143
+ this.keyboardNavigation = this.element.data('date-keyboard-navigation');
144
+ }
145
+
146
+ this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);
147
+ this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);
148
+
149
+ this.weekStart = ((options.weekStart || this.element.data('date-weekstart') || dates[this.language].weekStart || 0) % 7);
150
+ this.weekEnd = ((this.weekStart + 6) % 7);
151
+ this.startDate = -Infinity;
152
+ this.endDate = Infinity;
153
+ this.daysOfWeekDisabled = [];
154
+ this.setStartDate(options.startDate || this.element.data('date-startdate'));
155
+ this.setEndDate(options.endDate || this.element.data('date-enddate'));
156
+ this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));
157
+ this.fillDow();
158
+ this.fillMonths();
159
+ this.update();
160
+ this.showMode();
161
+
162
+ if(this.isInline) {
163
+ this.show();
164
+ }
165
+ };
166
+
167
+ Datetimepicker.prototype = {
168
+ constructor: Datetimepicker,
169
+
170
+ _events: [],
171
+ _attachEvents: function(){
172
+ this._detachEvents();
173
+ if (this.isInput) { // single input
174
+ this._events = [
175
+ [this.element, {
176
+ focus: $.proxy(this.show, this),
177
+ keyup: $.proxy(this.update, this),
178
+ keydown: $.proxy(this.keydown, this)
179
+ }]
180
+ ];
181
+ }
182
+ else if (this.component && this.hasInput){ // component: input + button
183
+ this._events = [
184
+ // For components that are not readonly, allow keyboard nav
185
+ [this.element.find('input'), {
186
+ focus: $.proxy(this.show, this),
187
+ keyup: $.proxy(this.update, this),
188
+ keydown: $.proxy(this.keydown, this)
189
+ }],
190
+ [this.component, {
191
+ click: $.proxy(this.show, this)
192
+ }]
193
+ ];
194
+ if (this.componentReset) {
195
+ this._events.push([
196
+ this.componentReset,
197
+ {click: $.proxy(this.reset, this)}
198
+ ]);
199
+ }
200
+ }
201
+ else if (this.element.is('div')) { // inline datetimepicker
202
+ this.isInline = true;
203
+ }
204
+ else {
205
+ this._events = [
206
+ [this.element, {
207
+ click: $.proxy(this.show, this)
208
+ }]
209
+ ];
210
+ }
211
+ for (var i=0, el, ev; i<this._events.length; i++){
212
+ el = this._events[i][0];
213
+ ev = this._events[i][1];
214
+ el.on(ev);
215
+ }
216
+ },
217
+
218
+ _detachEvents: function(){
219
+ for (var i=0, el, ev; i<this._events.length; i++){
220
+ el = this._events[i][0];
221
+ ev = this._events[i][1];
222
+ el.off(ev);
223
+ }
224
+ this._events = [];
225
+ },
226
+
227
+ show: function(e) {
228
+ this.picker.show();
229
+ this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
230
+ if (this.forceParse) {
231
+ this.update();
232
+ }
233
+ this.place();
234
+ $(window).on('resize', $.proxy(this.place, this));
235
+ if (e) {
236
+ e.stopPropagation();
237
+ e.preventDefault();
238
+ }
239
+ this.isVisible = true;
240
+ this.element.trigger({
241
+ type: 'show',
242
+ date: this.date
243
+ });
244
+ },
245
+
246
+ hide: function(e){
247
+ if(!this.isVisible) return;
248
+ if(this.isInline) return;
249
+ this.picker.hide();
250
+ $(window).off('resize', this.place);
251
+ this.viewMode = this.startViewMode;
252
+ this.showMode();
253
+ if (!this.isInput) {
254
+ $(document).off('mousedown', this.hide);
255
+ }
256
+
257
+ if (
258
+ this.forceParse &&
259
+ (
260
+ this.isInput && this.element.val() ||
261
+ this.hasInput && this.element.find('input').val()
262
+ )
263
+ )
264
+ this.setValue();
265
+ this.isVisible = false;
266
+ this.element.trigger({
267
+ type: 'hide',
268
+ date: this.date
269
+ });
270
+ },
271
+
272
+ remove: function() {
273
+ this._detachEvents();
274
+ this.picker.remove();
275
+ delete this.element.data().datetimepicker;
276
+ },
277
+
278
+ getDate: function() {
279
+ var d = this.getUTCDate();
280
+ return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
281
+ },
282
+
283
+ getUTCDate: function() {
284
+ return this.date;
285
+ },
286
+
287
+ setDate: function(d) {
288
+ this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
289
+ },
290
+
291
+ setUTCDate: function(d) {
292
+ if (d >= this.startDate && d <= this.endDate) {
293
+ this.date = d;
294
+ this.setValue();
295
+ this.viewDate = this.date;
296
+ this.fill();
297
+ } else {
298
+ this.element.trigger({
299
+ type: 'outOfRange',
300
+ date: d,
301
+ startDate: this.startDate,
302
+ endDate: this.endDate
303
+ });
304
+ }
305
+ },
306
+
307
+ setValue: function() {
308
+ var formatted = this.getFormattedDate();
309
+ if (!this.isInput) {
310
+ if (this.component){
311
+ this.element.find('input').val(formatted);
312
+ }
313
+ this.element.data('date', formatted);
314
+ } else {
315
+ this.element.val(formatted);
316
+ }
317
+ if (this.linkField) {
318
+ $('#' + this.linkField).val(this.getFormattedDate(this.linkFormat));
319
+ }
320
+ },
321
+
322
+ getFormattedDate: function(format) {
323
+ if(format == undefined) format = this.format;
324
+ return DPGlobal.formatDate(this.date, format, this.language, this.formatType);
325
+ },
326
+
327
+ setStartDate: function(startDate){
328
+ this.startDate = startDate || -Infinity;
329
+ if (this.startDate !== -Infinity) {
330
+ this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType);
331
+ }
332
+ this.update();
333
+ this.updateNavArrows();
334
+ },
335
+
336
+ setEndDate: function(endDate){
337
+ this.endDate = endDate || Infinity;
338
+ if (this.endDate !== Infinity) {
339
+ this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType);
340
+ }
341
+ this.update();
342
+ this.updateNavArrows();
343
+ },
344
+
345
+ setDaysOfWeekDisabled: function(daysOfWeekDisabled){
346
+ this.daysOfWeekDisabled = daysOfWeekDisabled || [];
347
+ if (!$.isArray(this.daysOfWeekDisabled)) {
348
+ this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
349
+ }
350
+ this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
351
+ return parseInt(d, 10);
352
+ });
353
+ this.update();
354
+ this.updateNavArrows();
355
+ },
356
+
357
+ place: function(){
358
+ if(this.isInline) return;
359
+ var zIndex = parseInt(this.element.parents().filter(function() {
360
+ return $(this).css('z-index') != 'auto';
361
+ }).first().css('z-index'))+10;
362
+ var offset, top, left;
363
+ if (this.component) {
364
+ offset = this.component.offset();
365
+ left = offset.left;
366
+ if (this.pickerPosition == 'bottom-left' || this.pickerPosition == 'top-left') {
367
+ left += this.component.outerWidth() - this.picker.outerWidth();
368
+ }
369
+ } else {
370
+ offset = this.element.offset();
371
+ left = offset.left;
372
+ }
373
+ if (this.pickerPosition == 'top-left' || this.pickerPosition == 'top-right') {
374
+ top = offset.top - this.picker.outerHeight();
375
+ } else {
376
+ top = offset.top + this.height;
377
+ }
378
+ this.picker.css({
379
+ top: top,
380
+ left: left,
381
+ zIndex: zIndex
382
+ });
383
+ },
384
+
385
+ update: function(){
386
+ var date, fromArgs = false;
387
+ if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
388
+ date = arguments[0];
389
+ fromArgs = true;
390
+ } else {
391
+ date = (this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val()) || this.initialDate;
392
+ }
393
+
394
+ if (!date) {
395
+ date = new Date();
396
+ fromArgs = false;
397
+ }
398
+
399
+ this.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType);
400
+
401
+ if (fromArgs) this.setValue();
402
+
403
+ if (this.date < this.startDate) {
404
+ this.viewDate = new Date(this.startDate);
405
+ } else if (this.date > this.endDate) {
406
+ this.viewDate = new Date(this.endDate);
407
+ } else {
408
+ this.viewDate = new Date(this.date);
409
+ }
410
+ this.fill();
411
+ },
412
+
413
+ fillDow: function(){
414
+ var dowCnt = this.weekStart,
415
+ html = '<tr>';
416
+ while (dowCnt < this.weekStart + 7) {
417
+ html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
418
+ }
419
+ html += '</tr>';
420
+ this.picker.find('.datetimepicker-days thead').append(html);
421
+ },
422
+
423
+ fillMonths: function(){
424
+ var html = '',
425
+ i = 0;
426
+ while (i < 12) {
427
+ html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
428
+ }
429
+ this.picker.find('.datetimepicker-months td').html(html);
430
+ },
431
+
432
+ fill: function() {
433
+ if (this.date == null || this.viewDate == null) {
434
+ return;
435
+ }
436
+ var d = new Date(this.viewDate),
437
+ year = d.getUTCFullYear(),
438
+ month = d.getUTCMonth(),
439
+ dayMonth = d.getUTCDate(),
440
+ hours = d.getUTCHours(),
441
+ minutes = d.getUTCMinutes(),
442
+ startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
443
+ startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
444
+ endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
445
+ endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
446
+ currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(),
447
+ today = new Date();
448
+ this.picker.find('.datetimepicker-days thead th:eq(1)')
449
+ .text(dates[this.language].months[month]+' '+year);
450
+ if (this.formatViewType == "time") {
451
+ var hourConverted = hours % 12 ? hours % 12 : 12;
452
+ var hoursDisplay = (hourConverted < 10 ? '0' : '') + hourConverted;
453
+ var minutesDisplay = (minutes < 10 ? '0' : '') + minutes;
454
+ var meridianDisplay = dates[this.language].meridiem[hours < 12 ? 0 : 1];
455
+ this.picker.find('.datetimepicker-hours thead th:eq(1)')
456
+ .text(hoursDisplay + ':' + minutesDisplay + ' ' + meridianDisplay.toUpperCase());
457
+ this.picker.find('.datetimepicker-minutes thead th:eq(1)')
458
+ .text(hoursDisplay + ':' + minutesDisplay + ' ' + meridianDisplay.toUpperCase());
459
+ } else {
460
+ this.picker.find('.datetimepicker-hours thead th:eq(1)')
461
+ .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
462
+ this.picker.find('.datetimepicker-minutes thead th:eq(1)')
463
+ .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
464
+ }
465
+ this.picker.find('tfoot th.today')
466
+ .text(dates[this.language].today)
467
+ .toggle(this.todayBtn !== false);
468
+ this.updateNavArrows();
469
+ this.fillMonths();
470
+ /*var prevMonth = UTCDate(year, month, 0,0,0,0,0);
471
+ prevMonth.setUTCDate(prevMonth.getDate() - (prevMonth.getUTCDay() - this.weekStart + 7)%7);*/
472
+ var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
473
+ day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
474
+ prevMonth.setUTCDate(day);
475
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
476
+ var nextMonth = new Date(prevMonth);
477
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
478
+ nextMonth = nextMonth.valueOf();
479
+ var html = [];
480
+ var clsName;
481
+ while(prevMonth.valueOf() < nextMonth) {
482
+ if (prevMonth.getUTCDay() == this.weekStart) {
483
+ html.push('<tr>');
484
+ }
485
+ clsName = '';
486
+ if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
487
+ clsName += ' old';
488
+ } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
489
+ clsName += ' new';
490
+ }
491
+ // Compare internal UTC date with local today, not UTC today
492
+ if (this.todayHighlight &&
493
+ prevMonth.getUTCFullYear() == today.getFullYear() &&
494
+ prevMonth.getUTCMonth() == today.getMonth() &&
495
+ prevMonth.getUTCDate() == today.getDate()) {
496
+ clsName += ' today';
497
+ }
498
+ if (prevMonth.valueOf() == currentDate) {
499
+ clsName += ' active';
500
+ }
501
+ if ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate ||
502
+ $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) {
503
+ clsName += ' disabled';
504
+ }
505
+ html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
506
+ if (prevMonth.getUTCDay() == this.weekEnd) {
507
+ html.push('</tr>');
508
+ }
509
+ prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
510
+ }
511
+ this.picker.find('.datetimepicker-days tbody').empty().append(html.join(''));
512
+
513
+ html = [];
514
+ var txt = '', meridian = '', meridianOld = '';
515
+ for (var i=0;i<24;i++) {
516
+ var actual = UTCDate(year, month, dayMonth, i);
517
+ clsName = '';
518
+ // We want the previous hour for the startDate
519
+ if ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) {
520
+ clsName += ' disabled';
521
+ } else if (hours == i) {
522
+ clsName += ' active';
523
+ }
524
+ if (this.showMeridian && dates[this.language].meridiem.length == 2) {
525
+ meridian = (i<12?dates[this.language].meridiem[0]:dates[this.language].meridiem[1]);
526
+ if (meridian != meridianOld) {
527
+ if (meridianOld != '') {
528
+ html.push('</fieldset>');
529
+ }
530
+ html.push('<fieldset class="hour"><legend>'+meridian.toUpperCase()+'</legend>');
531
+ }
532
+ meridianOld = meridian;
533
+ txt = (i%12?i%12:12);
534
+ html.push('<span class="hour'+clsName+' hour_'+(i<12?'am':'pm')+'">'+txt+'</span>');
535
+ if (i == 23) {
536
+ html.push('</fieldset>');
537
+ }
538
+ } else {
539
+ txt = i+':00';
540
+ html.push('<span class="hour'+clsName+'">'+txt+'</span>');
541
+ }
542
+ }
543
+ this.picker.find('.datetimepicker-hours td').html(html.join(''));
544
+
545
+ html = [];
546
+ txt = '', meridian = '', meridianOld = '';
547
+ for(var i=0;i<60;i+=this.minuteStep) {
548
+ var actual = UTCDate(year, month, dayMonth, hours, i, 0);
549
+ clsName = '';
550
+ if (actual.valueOf() < this.startDate || actual.valueOf() > this.endDate) {
551
+ clsName += ' disabled';
552
+ } else if (Math.floor(minutes/this.minuteStep) == Math.floor(i/this.minuteStep)) {
553
+ clsName += ' active';
554
+ }
555
+ if (this.showMeridian && dates[this.language].meridiem.length == 2) {
556
+ meridian = (hours<12?dates[this.language].meridiem[0]:dates[this.language].meridiem[1]);
557
+ if (meridian != meridianOld) {
558
+ if (meridianOld != '') {
559
+ html.push('</fieldset>');
560
+ }
561
+ html.push('<fieldset class="minute"><legend>'+meridian.toUpperCase()+'</legend>');
562
+ }
563
+ meridianOld = meridian;
564
+ txt = (hours%12?hours%12:12);
565
+ //html.push('<span class="minute'+clsName+' minute_'+(hours<12?'am':'pm')+'">'+txt+'</span>');
566
+ html.push('<span class="minute'+clsName+'">'+txt+':'+(i<10?'0'+i:i)+'</span>');
567
+ if (i == 59) {
568
+ html.push('</fieldset>');
569
+ }
570
+ } else {
571
+ txt = i+':00';
572
+ //html.push('<span class="hour'+clsName+'">'+txt+'</span>');
573
+ html.push('<span class="minute'+clsName+'">'+hours+':'+(i<10?'0'+i:i)+'</span>');
574
+ }
575
+ }
576
+ this.picker.find('.datetimepicker-minutes td').html(html.join(''));
577
+
578
+ var currentYear = this.date.getUTCFullYear();
579
+ var months = this.picker.find('.datetimepicker-months')
580
+ .find('th:eq(1)')
581
+ .text(year)
582
+ .end()
583
+ .find('span').removeClass('active');
584
+ if (currentYear == year) {
585
+ months.eq(this.date.getUTCMonth()).addClass('active');
586
+ }
587
+ if (year < startYear || year > endYear) {
588
+ months.addClass('disabled');
589
+ }
590
+ if (year == startYear) {
591
+ months.slice(0, startMonth).addClass('disabled');
592
+ }
593
+ if (year == endYear) {
594
+ months.slice(endMonth+1).addClass('disabled');
595
+ }
596
+
597
+ html = '';
598
+ year = parseInt(year/10, 10) * 10;
599
+ var yearCont = this.picker.find('.datetimepicker-years')
600
+ .find('th:eq(1)')
601
+ .text(year + '-' + (year + 9))
602
+ .end()
603
+ .find('td');
604
+ year -= 1;
605
+ for (var i = -1; i < 11; i++) {
606
+ html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
607
+ year += 1;
608
+ }
609
+ yearCont.html(html);
610
+ this.place();
611
+ },
612
+
613
+ updateNavArrows: function() {
614
+ var d = new Date(this.viewDate),
615
+ year = d.getUTCFullYear(),
616
+ month = d.getUTCMonth(),
617
+ day = d.getUTCDate(),
618
+ hour = d.getUTCHours();
619
+ switch (this.viewMode) {
620
+ case 0:
621
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()
622
+ && month <= this.startDate.getUTCMonth()
623
+ && day <= this.startDate.getUTCDate()
624
+ && hour <= this.startDate.getUTCHours()) {
625
+ this.picker.find('.prev').css({visibility: 'hidden'});
626
+ } else {
627
+ this.picker.find('.prev').css({visibility: 'visible'});
628
+ }
629
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()
630
+ && month >= this.endDate.getUTCMonth()
631
+ && day >= this.endDate.getUTCDate()
632
+ && hour >= this.endDate.getUTCHours()) {
633
+ this.picker.find('.next').css({visibility: 'hidden'});
634
+ } else {
635
+ this.picker.find('.next').css({visibility: 'visible'});
636
+ }
637
+ break;
638
+ case 1:
639
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()
640
+ && month <= this.startDate.getUTCMonth()
641
+ && day <= this.startDate.getUTCDate()) {
642
+ this.picker.find('.prev').css({visibility: 'hidden'});
643
+ } else {
644
+ this.picker.find('.prev').css({visibility: 'visible'});
645
+ }
646
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()
647
+ && month >= this.endDate.getUTCMonth()
648
+ && day >= this.endDate.getUTCDate()) {
649
+ this.picker.find('.next').css({visibility: 'hidden'});
650
+ } else {
651
+ this.picker.find('.next').css({visibility: 'visible'});
652
+ }
653
+ break;
654
+ case 2:
655
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()
656
+ && month <= this.startDate.getUTCMonth()) {
657
+ this.picker.find('.prev').css({visibility: 'hidden'});
658
+ } else {
659
+ this.picker.find('.prev').css({visibility: 'visible'});
660
+ }
661
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()
662
+ && month >= this.endDate.getUTCMonth()) {
663
+ this.picker.find('.next').css({visibility: 'hidden'});
664
+ } else {
665
+ this.picker.find('.next').css({visibility: 'visible'});
666
+ }
667
+ break;
668
+ case 3:
669
+ case 4:
670
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
671
+ this.picker.find('.prev').css({visibility: 'hidden'});
672
+ } else {
673
+ this.picker.find('.prev').css({visibility: 'visible'});
674
+ }
675
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
676
+ this.picker.find('.next').css({visibility: 'hidden'});
677
+ } else {
678
+ this.picker.find('.next').css({visibility: 'visible'});
679
+ }
680
+ break;
681
+ }
682
+ },
683
+
684
+ click: function(e) {
685
+ e.stopPropagation();
686
+ e.preventDefault();
687
+ var target = $(e.target).closest('span, td, th, legend');
688
+ if (target.length == 1) {
689
+ if (target.is('.disabled')) {
690
+ this.element.trigger({
691
+ type: 'outOfRange',
692
+ date: this.viewDate,
693
+ startDate: this.startDate,
694
+ endDate: this.endDate
695
+ });
696
+ return;
697
+ }
698
+ switch(target[0].nodeName.toLowerCase()) {
699
+ case 'th':
700
+ switch(target[0].className) {
701
+ case 'switch':
702
+ this.showMode(1);
703
+ break;
704
+ case 'prev':
705
+ case 'next':
706
+ var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
707
+ switch(this.viewMode){
708
+ case 0:
709
+ this.viewDate = this.moveHour(this.viewDate, dir);
710
+ break;
711
+ case 1:
712
+ this.viewDate = this.moveDate(this.viewDate, dir);
713
+ break;
714
+ case 2:
715
+ this.viewDate = this.moveMonth(this.viewDate, dir);
716
+ break;
717
+ case 3:
718
+ case 4:
719
+ this.viewDate = this.moveYear(this.viewDate, dir);
720
+ break;
721
+ }
722
+ this.fill();
723
+ break;
724
+ case 'today':
725
+ var date = new Date();
726
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);
727
+
728
+ this.viewMode = this.startViewMode;
729
+ this.showMode(0);
730
+ this._setDate(date);
731
+ this.fill();
732
+ if (this.autoclose) {
733
+ this.hide();
734
+ }
735
+ break;
736
+ }
737
+ break;
738
+ case 'span':
739
+ if (!target.is('.disabled')) {
740
+ var year = this.viewDate.getUTCFullYear(),
741
+ month = this.viewDate.getUTCMonth(),
742
+ day = this.viewDate.getUTCDate(),
743
+ hours = this.viewDate.getUTCHours(),
744
+ minutes = this.viewDate.getUTCMinutes(),
745
+ seconds = this.viewDate.getUTCSeconds();
746
+
747
+ if (target.is('.month')) {
748
+ this.viewDate.setUTCDate(1);
749
+ month = target.parent().find('span').index(target);
750
+ day = this.viewDate.getUTCDate();
751
+ this.viewDate.setUTCMonth(month);
752
+ this.element.trigger({
753
+ type: 'changeMonth',
754
+ date: this.viewDate
755
+ });
756
+ if (this.viewSelect >= 3) {
757
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
758
+ }
759
+ } else if (target.is('.year')) {
760
+ this.viewDate.setUTCDate(1);
761
+ year = parseInt(target.text(), 10) || 0;
762
+ this.viewDate.setUTCFullYear(year);
763
+ this.element.trigger({
764
+ type: 'changeYear',
765
+ date: this.viewDate
766
+ });
767
+ if (this.viewSelect >= 4) {
768
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
769
+ }
770
+ } else if (target.is('.hour')){
771
+ hours = parseInt(target.text(), 10) || 0;
772
+ if (target.hasClass('hour_am') || target.hasClass('hour_pm')) {
773
+ if (hours == 12 && target.hasClass('hour_am')) {
774
+ hours = 0;
775
+ } else if (hours != 12 && target.hasClass('hour_pm')) {
776
+ hours += 12;
777
+ }
778
+ }
779
+ this.viewDate.setUTCHours(hours);
780
+ this.element.trigger({
781
+ type: 'changeHour',
782
+ date: this.viewDate
783
+ });
784
+ if (this.viewSelect >= 1) {
785
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
786
+ }
787
+ } else if (target.is('.minute')){
788
+ minutes = parseInt(target.text().substr(target.text().indexOf(':')+1), 10) || 0;
789
+ this.viewDate.setUTCMinutes(minutes);
790
+ this.element.trigger({
791
+ type: 'changeMinute',
792
+ date: this.viewDate
793
+ });
794
+ if (this.viewSelect >= 0) {
795
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
796
+ }
797
+ }
798
+ if (this.viewMode != 0) {
799
+ var oldViewMode = this.viewMode;
800
+ this.showMode(-1);
801
+ this.fill();
802
+ if (oldViewMode == this.viewMode && this.autoclose) {
803
+ this.hide();
804
+ }
805
+ } else {
806
+ this.fill();
807
+ if (this.autoclose) {
808
+ this.hide();
809
+ }
810
+ }
811
+ }
812
+ break;
813
+ case 'td':
814
+ if (target.is('.day') && !target.is('.disabled')){
815
+ var day = parseInt(target.text(), 10) || 1;
816
+ var year = this.viewDate.getUTCFullYear(),
817
+ month = this.viewDate.getUTCMonth(),
818
+ hours = this.viewDate.getUTCHours(),
819
+ minutes = this.viewDate.getUTCMinutes(),
820
+ seconds = this.viewDate.getUTCSeconds();
821
+ if (target.is('.old')) {
822
+ if (month === 0) {
823
+ month = 11;
824
+ year -= 1;
825
+ } else {
826
+ month -= 1;
827
+ }
828
+ } else if (target.is('.new')) {
829
+ if (month == 11) {
830
+ month = 0;
831
+ year += 1;
832
+ } else {
833
+ month += 1;
834
+ }
835
+ }
836
+ this.viewDate.setUTCDate(day);
837
+ this.viewDate.setUTCMonth(month);
838
+ this.viewDate.setUTCFullYear(year);
839
+ this.element.trigger({
840
+ type: 'changeDay',
841
+ date: this.viewDate
842
+ });
843
+ if (this.viewSelect >= 2) {
844
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
845
+ }
846
+ }
847
+ var oldViewMode = this.viewMode;
848
+ this.showMode(-1);
849
+ this.fill();
850
+ if (oldViewMode == this.viewMode && this.autoclose) {
851
+ this.hide();
852
+ }
853
+ break;
854
+ }
855
+ }
856
+ },
857
+
858
+ _setDate: function(date, which){
859
+ if (!which || which == 'date')
860
+ this.date = date;
861
+ if (!which || which == 'view')
862
+ this.viewDate = date;
863
+ this.fill();
864
+ this.setValue();
865
+ var element;
866
+ if (this.isInput) {
867
+ element = this.element;
868
+ } else if (this.component){
869
+ element = this.element.find('input');
870
+ }
871
+ if (element) {
872
+ element.change();
873
+ if (this.autoclose && (!which || which == 'date')) {
874
+ //this.hide();
875
+ }
876
+ }
877
+ this.element.trigger({
878
+ type: 'changeDate',
879
+ date: this.date
880
+ });
881
+ },
882
+
883
+ moveMinute: function(date, dir){
884
+ if (!dir) return date;
885
+ var new_date = new Date(date.valueOf());
886
+ //dir = dir > 0 ? 1 : -1;
887
+ new_date.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep));
888
+ return new_date;
889
+ },
890
+
891
+ moveHour: function(date, dir){
892
+ if (!dir) return date;
893
+ var new_date = new Date(date.valueOf());
894
+ //dir = dir > 0 ? 1 : -1;
895
+ new_date.setUTCHours(new_date.getUTCHours() + dir);
896
+ return new_date;
897
+ },
898
+
899
+ moveDate: function(date, dir){
900
+ if (!dir) return date;
901
+ var new_date = new Date(date.valueOf());
902
+ //dir = dir > 0 ? 1 : -1;
903
+ new_date.setUTCDate(new_date.getUTCDate() + dir);
904
+ return new_date;
905
+ },
906
+
907
+ moveMonth: function(date, dir){
908
+ if (!dir) return date;
909
+ var new_date = new Date(date.valueOf()),
910
+ day = new_date.getUTCDate(),
911
+ month = new_date.getUTCMonth(),
912
+ mag = Math.abs(dir),
913
+ new_month, test;
914
+ dir = dir > 0 ? 1 : -1;
915
+ if (mag == 1){
916
+ test = dir == -1
917
+ // If going back one month, make sure month is not current month
918
+ // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
919
+ ? function(){ return new_date.getUTCMonth() == month; }
920
+ // If going forward one month, make sure month is as expected
921
+ // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
922
+ : function(){ return new_date.getUTCMonth() != new_month; };
923
+ new_month = month + dir;
924
+ new_date.setUTCMonth(new_month);
925
+ // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
926
+ if (new_month < 0 || new_month > 11)
927
+ new_month = (new_month + 12) % 12;
928
+ } else {
929
+ // For magnitudes >1, move one month at a time...
930
+ for (var i=0; i<mag; i++)
931
+ // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
932
+ new_date = this.moveMonth(new_date, dir);
933
+ // ...then reset the day, keeping it in the new month
934
+ new_month = new_date.getUTCMonth();
935
+ new_date.setUTCDate(day);
936
+ test = function(){ return new_month != new_date.getUTCMonth(); };
937
+ }
938
+ // Common date-resetting loop -- if date is beyond end of month, make it
939
+ // end of month
940
+ while (test()){
941
+ new_date.setUTCDate(--day);
942
+ new_date.setUTCMonth(new_month);
943
+ }
944
+ return new_date;
945
+ },
946
+
947
+ moveYear: function(date, dir){
948
+ return this.moveMonth(date, dir*12);
949
+ },
950
+
951
+ dateWithinRange: function(date){
952
+ return date >= this.startDate && date <= this.endDate;
953
+ },
954
+
955
+ keydown: function(e){
956
+ if (this.picker.is(':not(:visible)')){
957
+ if (e.keyCode == 27) // allow escape to hide and re-show picker
958
+ this.show();
959
+ return;
960
+ }
961
+ var dateChanged = false,
962
+ dir, day, month,
963
+ newDate, newViewDate;
964
+ switch(e.keyCode){
965
+ case 27: // escape
966
+ this.hide();
967
+ e.preventDefault();
968
+ break;
969
+ case 37: // left
970
+ case 39: // right
971
+ if (!this.keyboardNavigation) break;
972
+ dir = e.keyCode == 37 ? -1 : 1;
973
+ viewMode = this.viewMode;
974
+ if (e.ctrlKey) {
975
+ viewMode += 2;
976
+ } else if (e.shiftKey) {
977
+ viewMode += 1;
978
+ }
979
+ if (viewMode == 4) {
980
+ newDate = this.moveYear(this.date, dir);
981
+ newViewDate = this.moveYear(this.viewDate, dir);
982
+ } else if (viewMode == 3) {
983
+ newDate = this.moveMonth(this.date, dir);
984
+ newViewDate = this.moveMonth(this.viewDate, dir);
985
+ } else if (viewMode == 2) {
986
+ newDate = this.moveDate(this.date, dir);
987
+ newViewDate = this.moveDate(this.viewDate, dir);
988
+ } else if (viewMode == 1) {
989
+ newDate = this.moveHour(this.date, dir);
990
+ newViewDate = this.moveHour(this.viewDate, dir);
991
+ } else if (viewMode == 0) {
992
+ newDate = this.moveMinute(this.date, dir);
993
+ newViewDate = this.moveMinute(this.viewDate, dir);
994
+ }
995
+ if (this.dateWithinRange(newDate)){
996
+ this.date = newDate;
997
+ this.viewDate = newViewDate;
998
+ this.setValue();
999
+ this.update();
1000
+ e.preventDefault();
1001
+ dateChanged = true;
1002
+ }
1003
+ break;
1004
+ case 38: // up
1005
+ case 40: // down
1006
+ if (!this.keyboardNavigation) break;
1007
+ dir = e.keyCode == 38 ? -1 : 1;
1008
+ viewMode = this.viewMode;
1009
+ if (e.ctrlKey) {
1010
+ viewMode += 2;
1011
+ } else if (e.shiftKey) {
1012
+ viewMode += 1;
1013
+ }
1014
+ if (viewMode == 4) {
1015
+ newDate = this.moveYear(this.date, dir);
1016
+ newViewDate = this.moveYear(this.viewDate, dir);
1017
+ } else if (viewMode == 3) {
1018
+ newDate = this.moveMonth(this.date, dir);
1019
+ newViewDate = this.moveMonth(this.viewDate, dir);
1020
+ } else if (viewMode == 2) {
1021
+ newDate = this.moveDate(this.date, dir * 7);
1022
+ newViewDate = this.moveDate(this.viewDate, dir * 7);
1023
+ } else if (viewMode == 1) {
1024
+ if (this.showMeridian) {
1025
+ newDate = this.moveHour(this.date, dir * 6);
1026
+ newViewDate = this.moveHour(this.viewDate, dir * 6);
1027
+ } else {
1028
+ newDate = this.moveHour(this.date, dir * 4);
1029
+ newViewDate = this.moveHour(this.viewDate, dir * 4);
1030
+ }
1031
+ } else if (viewMode == 0) {
1032
+ newDate = this.moveMinute(this.date, dir * 4);
1033
+ newViewDate = this.moveMinute(this.viewDate, dir * 4);
1034
+ }
1035
+ if (this.dateWithinRange(newDate)){
1036
+ this.date = newDate;
1037
+ this.viewDate = newViewDate;
1038
+ this.setValue();
1039
+ this.update();
1040
+ e.preventDefault();
1041
+ dateChanged = true;
1042
+ }
1043
+ break;
1044
+ case 13: // enter
1045
+ if (this.viewMode != 0) {
1046
+ var oldViewMode = this.viewMode;
1047
+ this.showMode(-1);
1048
+ this.fill();
1049
+ if (oldViewMode == this.viewMode && this.autoclose) {
1050
+ this.hide();
1051
+ }
1052
+ } else {
1053
+ this.fill();
1054
+ if (this.autoclose) {
1055
+ this.hide();
1056
+ }
1057
+ }
1058
+ e.preventDefault();
1059
+ break;
1060
+ case 9: // tab
1061
+ this.hide();
1062
+ break;
1063
+ }
1064
+ if (dateChanged){
1065
+ var element;
1066
+ if (this.isInput) {
1067
+ element = this.element;
1068
+ } else if (this.component){
1069
+ element = this.element.find('input');
1070
+ }
1071
+ if (element) {
1072
+ element.change();
1073
+ }
1074
+ this.element.trigger({
1075
+ type: 'changeDate',
1076
+ date: this.date
1077
+ });
1078
+ }
1079
+ },
1080
+
1081
+ showMode: function(dir) {
1082
+ if (dir) {
1083
+ var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));
1084
+ if (newViewMode >= this.minView && newViewMode <= this.maxView) {
1085
+ this.viewMode = newViewMode;
1086
+ }
1087
+ }
1088
+ /*
1089
+ vitalets: fixing bug of very special conditions:
1090
+ jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover.
1091
+ Method show() does not set display css correctly and datetimepicker is not shown.
1092
+ Changed to .css('display', 'block') solve the problem.
1093
+ See https://github.com/vitalets/x-editable/issues/37
1094
+
1095
+ In jquery 1.7.2+ everything works fine.
1096
+ */
1097
+ //this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
1098
+ this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
1099
+ this.updateNavArrows();
1100
+ },
1101
+
1102
+ reset: function(e) {
1103
+ this._setDate(null, 'date');
1104
+ }
1105
+ };
1106
+
1107
+ $.fn.datetimepicker = function ( option ) {
1108
+ var args = Array.apply(null, arguments);
1109
+ args.shift();
1110
+ return this.each(function () {
1111
+ var $this = $(this),
1112
+ data = $this.data('datetimepicker'),
1113
+ options = typeof option == 'object' && option;
1114
+ if (!data) {
1115
+ $this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults,options))));
1116
+ }
1117
+ if (typeof option == 'string' && typeof data[option] == 'function') {
1118
+ data[option].apply(data, args);
1119
+ }
1120
+ });
1121
+ };
1122
+
1123
+ $.fn.datetimepicker.defaults = {
1124
+ };
1125
+ $.fn.datetimepicker.Constructor = Datetimepicker;
1126
+ var dates = $.fn.datetimepicker.dates = {
1127
+ en: {
1128
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
1129
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
1130
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
1131
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
1132
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1133
+ meridiem: ["am", "pm"],
1134
+ suffix: ["st", "nd", "rd", "th"],
1135
+ today: "Today"
1136
+ }
1137
+ };
1138
+
1139
+ var DPGlobal = {
1140
+ modes: [
1141
+ {
1142
+ clsName: 'minutes',
1143
+ navFnc: 'Hours',
1144
+ navStep: 1
1145
+ },
1146
+ {
1147
+ clsName: 'hours',
1148
+ navFnc: 'Date',
1149
+ navStep: 1
1150
+ },
1151
+ {
1152
+ clsName: 'days',
1153
+ navFnc: 'Month',
1154
+ navStep: 1
1155
+ },
1156
+ {
1157
+ clsName: 'months',
1158
+ navFnc: 'FullYear',
1159
+ navStep: 1
1160
+ },
1161
+ {
1162
+ clsName: 'years',
1163
+ navFnc: 'FullYear',
1164
+ navStep: 10
1165
+ }],
1166
+ isLeapYear: function (year) {
1167
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
1168
+ },
1169
+ getDaysInMonth: function (year, month) {
1170
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
1171
+ },
1172
+ getDefaultFormat: function (type, field) {
1173
+ if (type == "standard") {
1174
+ if (field == 'input')
1175
+ return 'yyyy-mm-dd hh:ii';
1176
+ else
1177
+ return 'yyyy-mm-dd hh:ii:ss';
1178
+ } else if (type == "php") {
1179
+ if (field == 'input')
1180
+ return 'Y-m-d H:i';
1181
+ else
1182
+ return 'Y-m-d H:i:s';
1183
+ } else {
1184
+ throw new Error("Invalid format type.");
1185
+ }
1186
+ },
1187
+ validParts: function (type) {
1188
+ if (type == "standard") {
1189
+ return /hh?|HH?|p|P|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g;
1190
+ } else if (type == "php") {
1191
+ return /[dDjlNwzFmMnStyYaABgGhHis]/g;
1192
+ } else {
1193
+ throw new Error("Invalid format type.");
1194
+ }
1195
+ },
1196
+ nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,
1197
+ parseFormat: function(format, type){
1198
+ // IE treats \0 as a string end in inputs (truncating the value),
1199
+ // so it's a bad format delimiter, anyway
1200
+ var separators = format.replace(this.validParts(type), '\0').split('\0'),
1201
+ parts = format.match(this.validParts(type));
1202
+ if (!separators || !separators.length || !parts || parts.length == 0){
1203
+ throw new Error("Invalid date format.");
1204
+ }
1205
+ return {separators: separators, parts: parts};
1206
+ },
1207
+ parseDate: function(date, format, language, type) {
1208
+ if (date instanceof Date) {
1209
+ var dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000);
1210
+ dateUTC.setMilliseconds(0);
1211
+ return dateUTC;
1212
+ }
1213
+ if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
1214
+ format = this.parseFormat('yyyy-mm-dd', type);
1215
+ }
1216
+ if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) {
1217
+ format = this.parseFormat('yyyy-mm-dd hh:ii', type);
1218
+ }
1219
+ if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) {
1220
+ format = this.parseFormat('yyyy-mm-dd hh:ii:ss', type);
1221
+ }
1222
+ if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
1223
+ var part_re = /([-+]\d+)([dmwy])/,
1224
+ parts = date.match(/([-+]\d+)([dmwy])/g),
1225
+ part, dir;
1226
+ date = new Date();
1227
+ for (var i=0; i<parts.length; i++) {
1228
+ part = part_re.exec(parts[i]);
1229
+ dir = parseInt(part[1]);
1230
+ switch(part[2]){
1231
+ case 'd':
1232
+ date.setUTCDate(date.getUTCDate() + dir);
1233
+ break;
1234
+ case 'm':
1235
+ date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);
1236
+ break;
1237
+ case 'w':
1238
+ date.setUTCDate(date.getUTCDate() + dir * 7);
1239
+ break;
1240
+ case 'y':
1241
+ date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);
1242
+ break;
1243
+ }
1244
+ }
1245
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0);
1246
+ }
1247
+ var parts = date && date.match(this.nonpunctuation) || [],
1248
+ date = new Date(0, 0, 0, 0, 0, 0, 0),
1249
+ parsed = {},
1250
+ setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P'],
1251
+ setters_map = {
1252
+ hh: function(d,v){ return d.setUTCHours(v); },
1253
+ h: function(d,v){ return d.setUTCHours(v); },
1254
+ HH: function(d,v){ return d.setUTCHours(v==12?0:v); },
1255
+ H: function(d,v){ return d.setUTCHours(v==12?0:v); },
1256
+ ii: function(d,v){ return d.setUTCMinutes(v); },
1257
+ i: function(d,v){ return d.setUTCMinutes(v); },
1258
+ ss: function(d,v){ return d.setUTCSeconds(v); },
1259
+ s: function(d,v){ return d.setUTCSeconds(v); },
1260
+ yyyy: function(d,v){ return d.setUTCFullYear(v); },
1261
+ yy: function(d,v){ return d.setUTCFullYear(2000+v); },
1262
+ m: function(d,v){
1263
+ v -= 1;
1264
+ while (v<0) v += 12;
1265
+ v %= 12;
1266
+ d.setUTCMonth(v);
1267
+ while (d.getUTCMonth() != v)
1268
+ d.setUTCDate(d.getUTCDate()-1);
1269
+ return d;
1270
+ },
1271
+ d: function(d,v){ return d.setUTCDate(v); },
1272
+ p: function(d,v){ return d.setUTCHours(v==1?d.getUTCHours()+12:d.getUTCHours()); }
1273
+ },
1274
+ val, filtered, part;
1275
+ setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1276
+ setters_map['dd'] = setters_map['d'];
1277
+ setters_map['P'] = setters_map['p'];
1278
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
1279
+ if (parts.length == format.parts.length) {
1280
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
1281
+ val = parseInt(parts[i], 10);
1282
+ part = format.parts[i];
1283
+ if (isNaN(val)) {
1284
+ switch(part) {
1285
+ case 'MM':
1286
+ filtered = $(dates[language].months).filter(function(){
1287
+ var m = this.slice(0, parts[i].length),
1288
+ p = parts[i].slice(0, m.length);
1289
+ return m == p;
1290
+ });
1291
+ val = $.inArray(filtered[0], dates[language].months) + 1;
1292
+ break;
1293
+ case 'M':
1294
+ filtered = $(dates[language].monthsShort).filter(function(){
1295
+ var m = this.slice(0, parts[i].length),
1296
+ p = parts[i].slice(0, m.length);
1297
+ return m == p;
1298
+ });
1299
+ val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1300
+ break;
1301
+ case 'p':
1302
+ case 'P':
1303
+ val = $.inArray(parts[i].toLowerCase(), dates[language].meridiem);
1304
+ break;
1305
+ }
1306
+ }
1307
+ parsed[part] = val;
1308
+ }
1309
+ for (var i=0, s; i<setters_order.length; i++){
1310
+ s = setters_order[i];
1311
+ if (s in parsed && !isNaN(parsed[s]))
1312
+ setters_map[s](date, parsed[s])
1313
+ }
1314
+ }
1315
+ return date;
1316
+ },
1317
+ formatDate: function(date, format, language, type){
1318
+ if (date == null) {
1319
+ return '';
1320
+ }
1321
+ var val;
1322
+ if (type == 'standard') {
1323
+ val = {
1324
+ // year
1325
+ yy: date.getUTCFullYear().toString().substring(2),
1326
+ yyyy: date.getUTCFullYear(),
1327
+ // month
1328
+ m: date.getUTCMonth() + 1,
1329
+ M: dates[language].monthsShort[date.getUTCMonth()],
1330
+ MM: dates[language].months[date.getUTCMonth()],
1331
+ // day
1332
+ d: date.getUTCDate(),
1333
+ D: dates[language].daysShort[date.getUTCDay()],
1334
+ DD: dates[language].days[date.getUTCDay()],
1335
+ p: (dates[language].meridiem.length==2?dates[language].meridiem[date.getUTCHours()<12?0:1]:''),
1336
+ // hour
1337
+ h: date.getUTCHours(),
1338
+ // minute
1339
+ i: date.getUTCMinutes(),
1340
+ // second
1341
+ s: date.getUTCSeconds()
1342
+ };
1343
+ val.H = (val.h%12==0? 12 : val.h%12);
1344
+ val.HH = (val.H < 10 ? '0' : '') + val.H;
1345
+ val.P = val.p.toUpperCase();
1346
+ val.hh = (val.h < 10 ? '0' : '') + val.h;
1347
+ val.ii = (val.i < 10 ? '0' : '') + val.i;
1348
+ val.ss = (val.s < 10 ? '0' : '') + val.s;
1349
+ val.dd = (val.d < 10 ? '0' : '') + val.d;
1350
+ val.mm = (val.m < 10 ? '0' : '') + val.m;
1351
+ } else if (type == 'php') {
1352
+ // php format
1353
+ val = {
1354
+ // year
1355
+ y: date.getUTCFullYear().toString().substring(2),
1356
+ Y: date.getUTCFullYear(),
1357
+ // month
1358
+ F: dates[language].months[date.getUTCMonth()],
1359
+ M: dates[language].monthsShort[date.getUTCMonth()],
1360
+ n: date.getUTCMonth() + 1,
1361
+ t: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()),
1362
+ // day
1363
+ j: date.getUTCDate(),
1364
+ l: dates[language].days[date.getUTCDay()],
1365
+ D: dates[language].daysShort[date.getUTCDay()],
1366
+ w: date.getUTCDay(), // 0 -> 6
1367
+ N: (date.getUTCDay()==0?7:date.getUTCDay()), // 1 -> 7
1368
+ S: (date.getUTCDate()%10<=dates[language].suffix.length?dates[language].suffix[date.getUTCDate()%10-1]:''),
1369
+ // hour
1370
+ a: (dates[language].meridiem.length==2?dates[language].meridiem[date.getUTCHours()<12?0:1]:''),
1371
+ g: (date.getUTCHours()%12==0?12:date.getUTCHours()%12),
1372
+ G: date.getUTCHours(),
1373
+ // minute
1374
+ i: date.getUTCMinutes(),
1375
+ // second
1376
+ s: date.getUTCSeconds()
1377
+ };
1378
+ val.m = (val.n < 10 ? '0' : '') + val.n;
1379
+ val.d = (val.j < 10 ? '0' : '') + val.j;
1380
+ val.A = val.a.toString().toUpperCase();
1381
+ val.h = (val.g < 10 ? '0' : '') + val.g;
1382
+ val.H = (val.G < 10 ? '0' : '') + val.G;
1383
+ val.i = (val.i < 10 ? '0' : '') + val.i;
1384
+ val.s = (val.s < 10 ? '0' : '') + val.s;
1385
+ } else {
1386
+ throw new Error("Invalid format type.");
1387
+ }
1388
+ var date = [],
1389
+ seps = $.extend([], format.separators);
1390
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
1391
+ if (seps.length)
1392
+ date.push(seps.shift())
1393
+ date.push(val[format.parts[i]]);
1394
+ }
1395
+ return date.join('');
1396
+ },
1397
+ convertViewMode: function(viewMode){
1398
+ switch (viewMode) {
1399
+ case 4:
1400
+ case 'decade':
1401
+ viewMode = 4;
1402
+ break;
1403
+ case 3:
1404
+ case 'year':
1405
+ viewMode = 3;
1406
+ break;
1407
+ case 2:
1408
+ case 'month':
1409
+ viewMode = 2;
1410
+ break;
1411
+ case 1:
1412
+ case 'day':
1413
+ viewMode = 1;
1414
+ break;
1415
+ case 0:
1416
+ case 'hour':
1417
+ viewMode = 0;
1418
+ break;
1419
+ }
1420
+
1421
+ return viewMode;
1422
+ },
1423
+ headTemplate: '<thead>'+
1424
+ '<tr>'+
1425
+ '<th class="prev"><i class="icon-arrow-left"/></th>'+
1426
+ '<th colspan="5" class="switch"></th>'+
1427
+ '<th class="next"><i class="icon-arrow-right"/></th>'+
1428
+ '</tr>'+
1429
+ '</thead>',
1430
+ contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1431
+ footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
1432
+ };
1433
+ DPGlobal.template = '<div class="datetimepicker">'+
1434
+ '<div class="datetimepicker-minutes">'+
1435
+ '<table class=" table-condensed">'+
1436
+ DPGlobal.headTemplate+
1437
+ DPGlobal.contTemplate+
1438
+ DPGlobal.footTemplate+
1439
+ '</table>'+
1440
+ '</div>'+
1441
+ '<div class="datetimepicker-hours">'+
1442
+ '<table class=" table-condensed">'+
1443
+ DPGlobal.headTemplate+
1444
+ DPGlobal.contTemplate+
1445
+ DPGlobal.footTemplate+
1446
+ '</table>'+
1447
+ '</div>'+
1448
+ '<div class="datetimepicker-days">'+
1449
+ '<table class=" table-condensed">'+
1450
+ DPGlobal.headTemplate+
1451
+ '<tbody></tbody>'+
1452
+ DPGlobal.footTemplate+
1453
+ '</table>'+
1454
+ '</div>'+
1455
+ '<div class="datetimepicker-months">'+
1456
+ '<table class="table-condensed">'+
1457
+ DPGlobal.headTemplate+
1458
+ DPGlobal.contTemplate+
1459
+ DPGlobal.footTemplate+
1460
+ '</table>'+
1461
+ '</div>'+
1462
+ '<div class="datetimepicker-years">'+
1463
+ '<table class="table-condensed">'+
1464
+ DPGlobal.headTemplate+
1465
+ DPGlobal.contTemplate+
1466
+ DPGlobal.footTemplate+
1467
+ '</table>'+
1468
+ '</div>'+
1469
+ '</div>';
1470
+
1471
+ $.fn.datetimepicker.DPGlobal = DPGlobal;
1472
+
1473
+ }( window.jQuery );