decidim-core 0.0.7 → 0.0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_core_manifest.js +3 -0
  3. data/app/assets/javascripts/decidim.js.es6 +8 -0
  4. data/app/assets/javascripts/decidim/widget.js.es6 +14 -0
  5. data/app/assets/stylesheets/decidim/extras/_embed.scss +11 -0
  6. data/app/assets/stylesheets/decidim/modules/_datepicker.scss +224 -0
  7. data/app/assets/stylesheets/decidim/modules/_modules.scss +1 -0
  8. data/app/assets/stylesheets/decidim/modules/_share.scss +1 -1
  9. data/app/assets/stylesheets/decidim/widget.scss.erb +25 -0
  10. data/app/controllers/decidim/participatory_process_widgets_controller.rb +17 -0
  11. data/app/controllers/decidim/participatory_processes_controller.rb +1 -0
  12. data/app/controllers/decidim/widgets_controller.rb +30 -0
  13. data/app/helpers/decidim/widget_urls_helper.rb +10 -0
  14. data/app/views/decidim/participatory_process_widgets/show.html.erb +28 -0
  15. data/app/views/decidim/participatory_processes/show.html.erb +1 -0
  16. data/app/views/decidim/shared/_embed_modal.html.erb +19 -0
  17. data/app/views/decidim/widgets/show.js.erb +22 -0
  18. data/app/views/layouts/decidim/_application.html.erb +1 -1
  19. data/app/views/layouts/decidim/widget.html.erb +17 -0
  20. data/config/locales/ca.yml +9 -1
  21. data/config/locales/en.yml +9 -1
  22. data/config/locales/es.yml +9 -1
  23. data/config/locales/eu.yml +0 -2
  24. data/config/locales/fi.yml +0 -2
  25. data/config/locales/fr.yml +9 -0
  26. data/config/locales/nl.yml +373 -0
  27. data/config/routes.rb +1 -0
  28. data/db/migrate/20170404132616_change_steps_end_and_start_date_to_date.rb +6 -0
  29. data/lib/decidim/core/version.rb +2 -2
  30. data/lib/decidim/form_builder.rb +33 -0
  31. data/lib/decidim/has_reference.rb +3 -2
  32. data/lib/tasks/decidim_tasks.rake +0 -5
  33. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.ca.js +17 -0
  34. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.es.js +14 -0
  35. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.eu.js +15 -0
  36. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.fi.js +14 -0
  37. data/vendor/assets/javascripts/form_datepicker.js.es6 +30 -0
  38. data/vendor/assets/javascripts/foundation-datepicker.js +1417 -0
  39. metadata +32 -12
data/config/routes.rb CHANGED
@@ -24,6 +24,7 @@ Decidim::Core::Engine.routes.draw do
24
24
  resources :participatory_process_groups, only: :show, path: "processes_groups"
25
25
  resources :participatory_processes, only: [:index, :show], path: "processes" do
26
26
  resources :participatory_process_steps, only: [:index], path: "steps"
27
+ resource :participatory_process_widget, only: :show, path: "embed"
27
28
  end
28
29
 
29
30
  scope "/processes/:participatory_process_id/f/:feature_id" do
@@ -0,0 +1,6 @@
1
+ class ChangeStepsEndAndStartDateToDate < ActiveRecord::Migration[5.0]
2
+ def change
3
+ change_column :decidim_participatory_process_steps, :start_date, :date
4
+ change_column :decidim_participatory_process_steps, :end_date, :date
5
+ end
6
+ end
@@ -2,7 +2,7 @@
2
2
  # This holds Decidim's version and the Rails version on which it depends.
3
3
  module Decidim
4
4
  def self.version
5
- "0.0.7"
5
+ "0.0.8.1"
6
6
  end
7
7
 
8
8
  def self.rails_version
@@ -14,7 +14,7 @@ module Decidim
14
14
  spec.authors = ["Josep Jaume Rey Peroy", "Marc Riera Casals", "Oriol Gual Oliva"]
15
15
  spec.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"]
16
16
  spec.license = "AGPLv3"
17
- spec.homepage = "https://github.com/AjuntamentdeBarcelona/decidim"
17
+ spec.homepage = "https://github.com/decidim/decidim"
18
18
  spec.required_ruby_version = ">= 2.3.1"
19
19
  end
20
20
  end
@@ -133,6 +133,39 @@ module Decidim
133
133
  end + error_and_help_text(attribute, options)
134
134
  end
135
135
 
136
+ # Public: Override so the date fields are rendered using foundation
137
+ # datepicker library
138
+ def date_field(attribute, options = {})
139
+ template = ""
140
+ template += label(attribute, label_for(attribute))
141
+ template += @template.text_field(@object_name, attribute, options.merge({
142
+ name: nil,
143
+ id: "date_field_#{@object_name}_#{attribute}",
144
+ data: { datepicker: '', startdate: object.send(attribute) }
145
+ }))
146
+ template += @template.hidden_field(@object_name, attribute)
147
+ template += error_and_help_text(attribute, options)
148
+ template.html_safe
149
+ end
150
+
151
+ # Public: Generates a timepicker field using foundation
152
+ # datepicker library
153
+ def datetime_field(attribute, options = {})
154
+ value = object.send(attribute)
155
+ formatted_value = I18n.localize(value, format: :timepicker) if value
156
+ template = ""
157
+ template += label(attribute, label_for(attribute))
158
+ template += @template.text_field(@object_name, attribute, options.merge({
159
+ value: formatted_value,
160
+ name: nil,
161
+ id: "datetime_field_#{@object_name}_#{attribute}",
162
+ data: { datepicker: '', timepicker: '' }
163
+ }))
164
+ template += @template.hidden_field(@object_name, attribute)
165
+ template += error_and_help_text(attribute, options)
166
+ template.html_safe
167
+ end
168
+
136
169
  private
137
170
 
138
171
  # Private: Override from FoundationRailsHelper in order to render
@@ -8,9 +8,9 @@ module Decidim
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  included do
11
- before_save :store_reference
11
+ after_commit :store_reference
12
12
 
13
- validates :reference, presence: true
13
+ validates :reference, presence: true, on: :update
14
14
 
15
15
  def reference
16
16
  self[:reference] || calculate_reference
@@ -44,6 +44,7 @@ module Decidim
44
44
  # Returns nothing.
45
45
  def store_reference
46
46
  self[:reference] ||= calculate_reference
47
+ self.save if self.changed?
47
48
  end
48
49
  end
49
50
  end
@@ -1,9 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # desc "Explaining what the task does"
3
- # task :decidim do
4
- # # Task goes here
5
- # end
6
-
7
2
  namespace :decidim do
8
3
  desc "Install migrations from Decidim to the app."
9
4
  task upgrade: ["railties:install:migrations"]
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Catalan translation for foundation-datepicker, language file from bootstrap-datepicker
3
+ * J. Garcia <jogaco.en@gmail.com>
4
+ */
5
+ ;(function($){
6
+ $.fn.fdatepicker.dates['ca'] = {
7
+ days: ["Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte"],
8
+ daysShort: ["Diu", "Dil", "Dmt", "Dmc", "Dij", "Div", "Dis"],
9
+ daysMin: ["dg", "dl", "dt", "dc", "dj", "dv", "ds"],
10
+ months: ["Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"],
11
+ monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Des"],
12
+ today: "Avui",
13
+ clear: "Esborrar",
14
+ weekStart: 1,
15
+ format: "dd/mm/yyyy"
16
+ };
17
+ }(jQuery));
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Spanish translation for foundation-datepicker
3
+ * Bruno Bonamin <bruno.bonamin@gmail.com>
4
+ */
5
+ ;(function($){
6
+ $.fn.fdatepicker.dates['es'] = {
7
+ days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"],
8
+ daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"],
9
+ daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"],
10
+ months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
11
+ monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"],
12
+ today: "Hoy"
13
+ };
14
+ }(jQuery));
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Basque translation for foundation-datepicker, language file from bootstrap-datepicker
3
+ * Arkaitz Etxeberria <kondi80@gmail.com>
4
+ */
5
+ ;(function($){
6
+ $.fn.fdatepicker.dates['eu'] = {
7
+ days: ['Igandea', 'Astelehena', 'Asteartea', 'Asteazkena', 'Osteguna', 'Ostirala', 'Larunbata'],
8
+ daysShort: ['Ig', 'Al', 'Ar', 'Az', 'Og', 'Ol', 'Lr'],
9
+ daysMin: ['Ig', 'Al', 'Ar', 'Az', 'Og', 'Ol', 'Lr'],
10
+ months: ['Urtarrila', 'Otsaila', 'Martxoa', 'Apirila', 'Maiatza', 'Ekaina', 'Uztaila', 'Abuztua', 'Iraila', 'Urria', 'Azaroa', 'Abendua'],
11
+ monthsShort: ['Urt', 'Ots', 'Mar', 'Api', 'Mai', 'Eka', 'Uzt', 'Abu', 'Ira', 'Urr', 'Aza', 'Abe'],
12
+ today: "Gaur"
13
+ };
14
+ }(jQuery));
15
+
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Finnish translation for foundation-datepicker
3
+ * Jaakko Salonen <https://github.com/jsalonen>
4
+ */
5
+ ;(function($){
6
+ $.fn.fdatepicker.dates['fi'] = {
7
+ days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"],
8
+ daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau", "sun"],
9
+ daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la", "su"],
10
+ months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
11
+ monthsShort: ["tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mar", "jou"],
12
+ today: "tänään"
13
+ };
14
+ }(jQuery));
@@ -0,0 +1,30 @@
1
+ ((exports) => {
2
+ const formDatePicker = () => {
3
+ $('[data-datepicker]').each((_index, node) => {
4
+ const language = $('html').attr('lang') || 'en';
5
+ const initialDate = $(node).data('startdate') || '';
6
+ const pickTime = $(node).data('timepicker') === '';
7
+ const languageProps = $(node).fdatepicker.dates[language] && $(node).fdatepicker.dates[language].format;
8
+ let format = languageProps || 'mm/dd/yyyy';
9
+
10
+ if (pickTime) {
11
+ format = `${format}, hh:ii`;
12
+ }
13
+
14
+ $(node).fdatepicker({
15
+ format,
16
+ initialDate,
17
+ language,
18
+ pickTime,
19
+ disableDblClickSelection: true,
20
+ leftArrow: '<<',
21
+ rightArrow: '>>'
22
+ }).on('changeDate', (ev) => {
23
+ $(ev.target).siblings('input').val(exports.moment.utc(ev.date));
24
+ });
25
+ });
26
+ };
27
+
28
+ exports.Decidim = exports.Decidim || {};
29
+ exports.Decidim.formDatePicker = formDatePicker;
30
+ })(window);
@@ -0,0 +1,1417 @@
1
+ /* =========================================================
2
+ * foundation-datepicker.js
3
+ * Copyright 2015 Peter Beno, najlepsiwebdesigner@gmail.com, @benopeter
4
+ * project website http://foundation-datepicker.peterbeno.com
5
+ * ========================================================= */
6
+ ! function($) {
7
+
8
+ function UTCDate() {
9
+ return new Date(Date.UTC.apply(Date, arguments));
10
+ }
11
+
12
+ function UTCToday() {
13
+ var today = new Date();
14
+ return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
15
+ }
16
+
17
+ var Datepicker = function(element, options) {
18
+ var that = this;
19
+
20
+ this.element = $(element);
21
+ this.autoShow = (options.autoShow == undefined ? true : options.autoShow);
22
+ this.appendTo = options.appendTo || 'body';
23
+ this.closeButton = options.closeButton;
24
+ this.language = options.language || this.element.data('date-language') || "en";
25
+ this.language = this.language in dates ? this.language : this.language.split('-')[0]; //Check if "de-DE" style date is available, if not language should fallback to 2 letter code eg "de"
26
+ this.language = this.language in dates ? this.language : "en";
27
+ this.isRTL = dates[this.language].rtl || false;
28
+ this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || 'mm/dd/yyyy');
29
+ this.formatText = options.format || this.element.data('date-format') || dates[this.language].format || 'mm/dd/yyyy';
30
+ this.isInline = false;
31
+ this.isInput = this.element.is('input');
32
+ this.component = this.element.is('.date') ? this.element.find('.prefix, .postfix') : false;
33
+ this.hasInput = this.component && this.element.find('input').length;
34
+ this.disableDblClickSelection = options.disableDblClickSelection;
35
+ this.onRender = options.onRender || function() {};
36
+ if (this.component && this.component.length === 0) {
37
+ this.component = false;
38
+ }
39
+ this.linkField = options.linkField || this.element.data('link-field') || false;
40
+ this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || 'yyyy-mm-dd hh:ii:ss');
41
+ this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
42
+ this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
43
+ this.initialDate = options.initialDate || null;
44
+ this.faCSSprefix = options.faCSSprefix || 'fa';
45
+ this.leftArrow = options.leftArrow || '<i class="' + this.faCSSprefix + ' ' + this.faCSSprefix + '-chevron-left fi-arrow-left"/>';
46
+ this.rightArrow = options.rightArrow || '<i class="' + this.faCSSprefix + ' ' + this.faCSSprefix + '-chevron-right fi-arrow-right"/>';
47
+ this.closeIcon = options.closeIcon || '<i class="' + this.faCSSprefix + ' ' + this.faCSSprefix + '-remove ' + this.faCSSprefix + '-times fi-x"></i>';
48
+
49
+
50
+
51
+ this.minView = 0;
52
+ if ('minView' in options) {
53
+ this.minView = options.minView;
54
+ } else if ('minView' in this.element.data()) {
55
+ this.minView = this.element.data('min-view');
56
+ }
57
+ this.minView = DPGlobal.convertViewMode(this.minView);
58
+
59
+ this.maxView = DPGlobal.modes.length - 1;
60
+ if ('maxView' in options) {
61
+ this.maxView = options.maxView;
62
+ } else if ('maxView' in this.element.data()) {
63
+ this.maxView = this.element.data('max-view');
64
+ }
65
+ this.maxView = DPGlobal.convertViewMode(this.maxView);
66
+
67
+ this.startViewMode = 'month';
68
+ if ('startView' in options) {
69
+ this.startViewMode = options.startView;
70
+ } else if ('startView' in this.element.data()) {
71
+ this.startViewMode = this.element.data('start-view');
72
+ }
73
+ this.startViewMode = DPGlobal.convertViewMode(this.startViewMode);
74
+ this.viewMode = this.startViewMode;
75
+
76
+ if (!('minView' in options) && !('maxView' in options) && !(this.element.data('min-view')) && !(this.element.data('max-view'))) {
77
+ this.pickTime = false;
78
+ if ('pickTime' in options) {
79
+ this.pickTime = options.pickTime;
80
+ }
81
+ if (this.pickTime == true) {
82
+ this.minView = 0;
83
+ this.maxView = 4;
84
+ } else {
85
+ this.minView = 2;
86
+ this.maxView = 4;
87
+ }
88
+ }
89
+
90
+ this.forceParse = true;
91
+ if ('forceParse' in options) {
92
+ this.forceParse = options.forceParse;
93
+ } else if ('dateForceParse' in this.element.data()) {
94
+ this.forceParse = this.element.data('date-force-parse');
95
+ }
96
+
97
+
98
+ this.picker = $(DPGlobal.template(this.leftArrow, this.rightArrow, this.closeIcon))
99
+ .appendTo(this.isInline ? this.element : this.appendTo)
100
+ .on({
101
+ click: $.proxy(this.click, this),
102
+ mousedown: $.proxy(this.mousedown, this)
103
+ });
104
+ if (this.closeButton) {
105
+ this.picker.find('a.datepicker-close').show();
106
+ } else {
107
+ this.picker.find('a.datepicker-close').hide();
108
+ }
109
+
110
+ if (this.isInline) {
111
+ this.picker.addClass('datepicker-inline');
112
+ } else {
113
+ this.picker.addClass('datepicker-dropdown dropdown-menu');
114
+ }
115
+ if (this.isRTL) {
116
+ this.picker.addClass('datepicker-rtl');
117
+
118
+ this.picker.find('.date-switch').each(function(){
119
+ $(this).parent().prepend($(this).siblings('.next'));
120
+ $(this).parent().append($(this).siblings('.prev'));
121
+ })
122
+ this.picker.find('.prev, .next').toggleClass('prev next');
123
+
124
+ }
125
+ $(document).on('mousedown', function(e) {
126
+ if (that.isInput && e.target === that.element[0]) {
127
+ return;
128
+ }
129
+
130
+ // Clicked outside the datepicker, hide it
131
+ if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
132
+ that.hide();
133
+ }
134
+ });
135
+
136
+ this.autoclose = true;
137
+ if ('autoclose' in options) {
138
+ this.autoclose = options.autoclose;
139
+ } else if ('dateAutoclose' in this.element.data()) {
140
+ this.autoclose = this.element.data('date-autoclose');
141
+ }
142
+
143
+ this.keyboardNavigation = true;
144
+ if ('keyboardNavigation' in options) {
145
+ this.keyboardNavigation = options.keyboardNavigation;
146
+ } else if ('dateKeyboardNavigation' in this.element.data()) {
147
+ this.keyboardNavigation = this.element.data('date-keyboard-navigation');
148
+ }
149
+
150
+ this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);
151
+ this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);
152
+
153
+ this.calendarWeeks = false;
154
+ if ('calendarWeeks' in options) {
155
+ this.calendarWeeks = options.calendarWeeks;
156
+ } else if ('dateCalendarWeeks' in this.element.data()) {
157
+ this.calendarWeeks = this.element.data('date-calendar-weeks');
158
+ }
159
+ if (this.calendarWeeks)
160
+ this.picker.find('tfoot th.today')
161
+ .attr('colspan', function(i, val) {
162
+ return parseInt(val) + 1;
163
+ });
164
+
165
+ this.weekStart = ((options.weekStart || this.element.data('date-weekstart') || dates[this.language].weekStart || 0) % 7);
166
+ this.weekEnd = ((this.weekStart + 6) % 7);
167
+ this.startDate = -Infinity;
168
+ this.endDate = Infinity;
169
+ this.daysOfWeekDisabled = [];
170
+ this.datesDisabled = [];
171
+ this.setStartDate(options.startDate || this.element.data('date-startdate'));
172
+ this.setEndDate(options.endDate || this.element.data('date-enddate'));
173
+ this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));
174
+ this.setDatesDisabled(options.datesDisabled || this.element.data('dates-disabled'));
175
+
176
+ this.fillDow();
177
+ this.fillMonths();
178
+ this.update();
179
+
180
+ this.showMode();
181
+
182
+ if (this.isInline) {
183
+ this.show();
184
+ }
185
+
186
+ this._attachEvents();
187
+ };
188
+
189
+ Datepicker.prototype = {
190
+ constructor: Datepicker,
191
+
192
+ _events: [],
193
+ _attachEvents: function() {
194
+ this._detachEvents();
195
+ if (this.isInput) { // single input
196
+ if (!this.keyboardNavigation) {
197
+ this._events = [
198
+ [this.element, {
199
+ focus: (this.autoShow) ? $.proxy(this.show, this) : function() {}
200
+ }]
201
+ ];
202
+ } else {
203
+ this._events = [
204
+ [this.element, {
205
+ focus: (this.autoShow) ? $.proxy(this.show, this) : function() {},
206
+ keyup: $.proxy(this.update, this),
207
+ keydown: $.proxy(this.keydown, this),
208
+ click: (this.element.attr('readonly')) ? $.proxy(this.show, this) : function() {}
209
+ }]
210
+ ];
211
+ }
212
+ }
213
+ else if (this.component && this.hasInput) { // component: input + button
214
+ this._events = [
215
+ // For components that are not readonly, allow keyboard nav
216
+ [this.element.find('input'), {
217
+ focus: (this.autoShow) ? $.proxy(this.show, this) : function() {},
218
+ keyup: $.proxy(this.update, this),
219
+ keydown: $.proxy(this.keydown, this)
220
+ }],
221
+ [this.component, {
222
+ click: $.proxy(this.show, this)
223
+ }]
224
+ ];
225
+ } else if (this.element.is('div')) { // inline datepicker
226
+ this.isInline = true;
227
+ } else {
228
+ this._events = [
229
+ [this.element, {
230
+ click: $.proxy(this.show, this)
231
+ }]
232
+ ];
233
+ }
234
+
235
+ if (this.disableDblClickSelection) {
236
+ this._events[this._events.length] = [
237
+ this.element, {
238
+ dblclick: function(e) {
239
+ e.preventDefault();
240
+ e.stopPropagation();
241
+ $(this).blur()
242
+ }
243
+ }
244
+ ];
245
+ }
246
+
247
+ for (var i = 0, el, ev; i < this._events.length; i++) {
248
+ el = this._events[i][0];
249
+ ev = this._events[i][1];
250
+ el.on(ev);
251
+ }
252
+ },
253
+ _detachEvents: function() {
254
+ for (var i = 0, el, ev; i < this._events.length; i++) {
255
+ el = this._events[i][0];
256
+ ev = this._events[i][1];
257
+ el.off(ev);
258
+ }
259
+ this._events = [];
260
+ },
261
+
262
+ show: function(e) {
263
+ this.picker.show();
264
+ this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
265
+ this.update();
266
+ this.place();
267
+ $(window).on('resize', $.proxy(this.place, this));
268
+ if (e) {
269
+ e.stopPropagation();
270
+ e.preventDefault();
271
+ }
272
+ this.element.trigger({
273
+ type: 'show',
274
+ date: this.date
275
+ });
276
+ },
277
+
278
+ hide: function(e) {
279
+ if (this.isInline) return;
280
+ if (!this.picker.is(':visible')) return;
281
+ this.picker.hide();
282
+ $(window).off('resize', this.place);
283
+ this.viewMode = this.startViewMode;
284
+ this.showMode();
285
+ if (!this.isInput) {
286
+ $(document).off('mousedown', this.hide);
287
+ }
288
+
289
+ if (
290
+ this.forceParse &&
291
+ (
292
+ this.isInput && this.element.val() ||
293
+ this.hasInput && this.element.find('input').val()
294
+ )
295
+ )
296
+ this.setValue();
297
+ this.element.trigger({
298
+ type: 'hide',
299
+ date: this.date
300
+ });
301
+ },
302
+
303
+ remove: function() {
304
+ this._detachEvents();
305
+ this.picker.remove();
306
+ delete this.element.data().datepicker;
307
+ },
308
+
309
+ getDate: function() {
310
+ var d = this.getUTCDate();
311
+ return new Date(d.getTime() + (d.getTimezoneOffset() * 60000));
312
+ },
313
+
314
+ getUTCDate: function() {
315
+ return this.date;
316
+ },
317
+
318
+ setDate: function(d) {
319
+ this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000)));
320
+ },
321
+
322
+ setUTCDate: function(d) {
323
+ this.date = d;
324
+ this.setValue();
325
+ },
326
+
327
+ setValue: function() {
328
+ var formatted = this.getFormattedDate();
329
+ if (!this.isInput) {
330
+ if (this.component) {
331
+ this.element.find('input').val(formatted);
332
+ }
333
+ this.element.data('date', formatted);
334
+ } else {
335
+ this.element.val(formatted);
336
+ }
337
+ },
338
+
339
+ getFormattedDate: function(format) {
340
+ if (format === undefined)
341
+ format = this.format;
342
+ return DPGlobal.formatDate(this.date, format, this.language);
343
+ },
344
+
345
+ setStartDate: function(startDate) {
346
+ this.startDate = startDate || -Infinity;
347
+ if (this.startDate !== -Infinity) {
348
+ this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
349
+ }
350
+ this.update();
351
+ this.updateNavArrows();
352
+ },
353
+
354
+ setEndDate: function(endDate) {
355
+ this.endDate = endDate || Infinity;
356
+ if (this.endDate !== Infinity) {
357
+ this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
358
+ }
359
+ this.update();
360
+ this.updateNavArrows();
361
+ },
362
+
363
+ setDaysOfWeekDisabled: function(daysOfWeekDisabled) {
364
+ this.daysOfWeekDisabled = daysOfWeekDisabled || [];
365
+ if (!$.isArray(this.daysOfWeekDisabled)) {
366
+ this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
367
+ }
368
+ this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function(d) {
369
+ return parseInt(d, 10);
370
+ });
371
+ this.update();
372
+ this.updateNavArrows();
373
+ },
374
+
375
+ setDatesDisabled: function(datesDisabled) {
376
+ this.datesDisabled = datesDisabled || [];
377
+ if (!$.isArray(this.datesDisabled)) {
378
+ this.datesDisabled = this.datesDisabled.split(/,\s*/);
379
+ }
380
+ this.datesDisabled = $.map(this.datesDisabled, function(d) {
381
+ return DPGlobal.parseDate(d, this.format, this.language).valueOf();
382
+ });
383
+ this.update();
384
+ this.updateNavArrows();
385
+ },
386
+
387
+ place: function() {
388
+ if (this.isInline) return;
389
+ var zIndex = parseInt(this.element.parents().filter(function() {
390
+ return $(this).css('z-index') != 'auto';
391
+ }).first().css('z-index')) + 10;
392
+ var textbox = this.component ? this.component : this.element;
393
+ var offset = textbox.offset();
394
+ var height = textbox.outerHeight() + parseInt(textbox.css('margin-top'));
395
+ var width = textbox.outerWidth() + parseInt(textbox.css('margin-left'));
396
+ var fullOffsetTop = offset.top + height;
397
+ var offsetLeft = offset.left;
398
+ this.picker.removeClass('datepicker-top datepicker-bottom');
399
+ // if the datepicker is going to be below the window, show it on top of the input
400
+ if ((fullOffsetTop + this.picker.outerHeight()) >= $(window).scrollTop() + $(window).height()) {
401
+ fullOffsetTop = offset.top - this.picker.outerHeight();
402
+ this.picker.addClass('datepicker-top');
403
+ }
404
+ else {
405
+ this.picker.addClass('datepicker-bottom');
406
+ }
407
+
408
+ // if the datepicker is going to go past the right side of the window, we want
409
+ // to set the right position so the datepicker lines up with the textbox
410
+ if (offset.left + this.picker.width() >= $(window).width()) {
411
+ offsetLeft = (offset.left + width) - this.picker.width();
412
+ }
413
+ this.picker.css({
414
+ top: fullOffsetTop,
415
+ left: offsetLeft,
416
+ zIndex: zIndex
417
+ });
418
+ },
419
+
420
+ update: function() {
421
+ var date, fromArgs = false;
422
+ var currentVal = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
423
+ if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
424
+ date = arguments[0];
425
+ fromArgs = true;
426
+ }
427
+ else if (!currentVal && this.initialDate != null) { // If value is not set, set it to the initialDate
428
+ date = this.initialDate
429
+ }
430
+ else {
431
+ date = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
432
+ }
433
+
434
+ if (date && date.length > this.formatText.length) {
435
+ $(this.picker).addClass('is-invalid')
436
+ $(this.element).addClass('is-invalid-input')
437
+ return;
438
+ } else {
439
+ $(this.picker).removeClass('is-invalid')
440
+ $(this.element).removeClass('is-invalid-input')
441
+
442
+ }
443
+
444
+ this.date = DPGlobal.parseDate(date, this.format, this.language);
445
+
446
+ if (fromArgs || this.initialDate != null) this.setValue();
447
+
448
+ if (this.date < this.startDate) {
449
+ this.viewDate = new Date(this.startDate.valueOf());
450
+ } else if (this.date > this.endDate) {
451
+ this.viewDate = new Date(this.endDate.valueOf());
452
+ } else {
453
+ this.viewDate = new Date(this.date.valueOf());
454
+ }
455
+ this.fill();
456
+ },
457
+
458
+ fillDow: function() {
459
+ var dowCnt = this.weekStart,
460
+ html = '<tr>';
461
+ if (this.calendarWeeks) {
462
+ var cell = '<th class="cw">&nbsp;</th>';
463
+ html += cell;
464
+ this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
465
+ }
466
+ while (dowCnt < this.weekStart + 7) {
467
+ html += '<th class="dow">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>';
468
+ }
469
+ html += '</tr>';
470
+ this.picker.find('.datepicker-days thead').append(html);
471
+ },
472
+
473
+ fillMonths: function() {
474
+ var html = '',
475
+ i = 0;
476
+ while (i < 12) {
477
+ html += '<span class="month">' + dates[this.language].monthsShort[i++] + '</span>';
478
+ }
479
+ this.picker.find('.datepicker-months td').html(html);
480
+ },
481
+
482
+ fill: function() {
483
+ if (this.date == null || this.viewDate == null) {
484
+ return;
485
+ }
486
+
487
+ var d = new Date(this.viewDate.valueOf()),
488
+ year = d.getUTCFullYear(),
489
+ month = d.getUTCMonth(),
490
+ dayMonth = d.getUTCDate(),
491
+ hours = d.getUTCHours(),
492
+ minutes = d.getUTCMinutes(),
493
+ startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
494
+ startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
495
+ endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
496
+ endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
497
+ currentDate = this.date && UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate()).valueOf(),
498
+ today = new Date(),
499
+ titleFormat = dates[this.language].titleFormat || dates['en'].titleFormat;
500
+ // this.picker.find('.datepicker-days thead th.date-switch')
501
+ // .text(DPGlobal.formatDate(new UTCDate(year, month), titleFormat, this.language));
502
+
503
+ this.picker.find('.datepicker-days thead th:eq(1)')
504
+ .text(dates[this.language].months[month] + ' ' + year);
505
+ this.picker.find('.datepicker-hours thead th:eq(1)')
506
+ .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
507
+ this.picker.find('.datepicker-minutes thead th:eq(1)')
508
+ .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
509
+
510
+
511
+ this.picker.find('tfoot th.today')
512
+ .text(dates[this.language].today)
513
+ .toggle(this.todayBtn !== false);
514
+ this.updateNavArrows();
515
+ this.fillMonths();
516
+ var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0),
517
+ day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
518
+ prevMonth.setUTCDate(day);
519
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
520
+ var nextMonth = new Date(prevMonth.valueOf());
521
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
522
+ nextMonth = nextMonth.valueOf();
523
+ var html = [];
524
+ var clsName;
525
+ while (prevMonth.valueOf() < nextMonth) {
526
+ if (prevMonth.getUTCDay() == this.weekStart) {
527
+ html.push('<tr>');
528
+ if (this.calendarWeeks) {
529
+ // adapted from https://github.com/timrwood/moment/blob/master/moment.js#L128
530
+ var a = new Date(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth(), prevMonth.getUTCDate() - prevMonth.getDay() + 10 - (this.weekStart && this.weekStart % 7 < 5 && 7)),
531
+ b = new Date(a.getFullYear(), 0, 4),
532
+ calWeek = ~~((a - b) / 864e5 / 7 + 1.5);
533
+ html.push('<td class="cw">' + calWeek + '</td>');
534
+ }
535
+ }
536
+ clsName = ' ' + this.onRender(prevMonth) + ' ';
537
+ if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
538
+ clsName += ' old';
539
+ } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
540
+ clsName += ' new';
541
+ }
542
+ // Compare internal UTC date with local today, not UTC today
543
+ if (this.todayHighlight &&
544
+ prevMonth.getUTCFullYear() == today.getFullYear() &&
545
+ prevMonth.getUTCMonth() == today.getMonth() &&
546
+ prevMonth.getUTCDate() == today.getDate()) {
547
+ clsName += ' today';
548
+ }
549
+ if (currentDate && prevMonth.valueOf() == currentDate) {
550
+ clsName += ' active';
551
+ }
552
+ if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate ||
553
+ $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1 ||
554
+ $.inArray(prevMonth.valueOf(), this.datesDisabled) !== -1) {
555
+ clsName += ' disabled';
556
+ }
557
+ html.push('<td class="day' + clsName + '">' + prevMonth.getUTCDate() + '</td>');
558
+ if (prevMonth.getUTCDay() == this.weekEnd) {
559
+ html.push('</tr>');
560
+ }
561
+ prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
562
+ }
563
+ this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
564
+
565
+ html = [];
566
+ for (var i = 0; i < 24; i++) {
567
+ var actual = UTCDate(year, month, dayMonth, i);
568
+ clsName = '';
569
+ // We want the previous hour for the startDate
570
+ if ((actual.valueOf() + 3600000) < this.startDate || actual.valueOf() > this.endDate) {
571
+ clsName += ' disabled';
572
+ } else if (hours == i) {
573
+ clsName += ' active';
574
+ }
575
+ html.push('<span class="hour' + clsName + '">' + i + ':00</span>');
576
+ }
577
+ this.picker.find('.datepicker-hours td').html(html.join(''));
578
+
579
+ html = [];
580
+ for (var i = 0; i < 60; i += this.minuteStep) {
581
+ var actual = UTCDate(year, month, dayMonth, hours, i);
582
+ clsName = '';
583
+ if (actual.valueOf() < this.startDate || actual.valueOf() > this.endDate) {
584
+ clsName += ' disabled';
585
+ } else if (Math.floor(minutes / this.minuteStep) == Math.floor(i / this.minuteStep)) {
586
+ clsName += ' active';
587
+ }
588
+ html.push('<span class="minute' + clsName + '">' + hours + ':' + (i < 10 ? '0' + i : i) + '</span>');
589
+ }
590
+ this.picker.find('.datepicker-minutes td').html(html.join(''));
591
+
592
+
593
+ var currentYear = this.date && this.date.getUTCFullYear();
594
+ var months = this.picker.find('.datepicker-months')
595
+ .find('th:eq(1)')
596
+ .text(year)
597
+ .end()
598
+ .find('span').removeClass('active');
599
+ if (currentYear && currentYear == year) {
600
+ months.eq(this.date.getUTCMonth()).addClass('active');
601
+ }
602
+ if (year < startYear || year > endYear) {
603
+ months.addClass('disabled');
604
+ }
605
+ if (year == startYear) {
606
+ months.slice(0, startMonth).addClass('disabled');
607
+ }
608
+ if (year == endYear) {
609
+ months.slice(endMonth + 1).addClass('disabled');
610
+ }
611
+
612
+ html = '';
613
+ year = parseInt(year / 10, 10) * 10;
614
+ var yearCont = this.picker.find('.datepicker-years')
615
+ .find('th:eq(1)')
616
+ .text(year + '-' + (year + 9))
617
+ .end()
618
+ .find('td');
619
+ year -= 1;
620
+ for (var i = -1; i < 11; i++) {
621
+ html += '<span class="year' + (i == -1 || i == 10 ? ' old' : '') + (currentYear == year ? ' active' : '') + (year < startYear || year > endYear ? ' disabled' : '') + '">' + year + '</span>';
622
+ year += 1;
623
+ }
624
+ yearCont.html(html);
625
+ },
626
+
627
+ updateNavArrows: function() {
628
+ var d = new Date(this.viewDate),
629
+ year = d.getUTCFullYear(),
630
+ month = d.getUTCMonth(),
631
+ day = d.getUTCDate(),
632
+ hour = d.getUTCHours();
633
+ switch (this.viewMode) {
634
+ case 0:
635
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth() && day <= this.startDate.getUTCDate() && hour <= this.startDate.getUTCHours()) {
636
+ this.picker.find('.prev').css({
637
+ visibility: 'hidden'
638
+ });
639
+ } else {
640
+ this.picker.find('.prev').css({
641
+ visibility: 'visible'
642
+ });
643
+ }
644
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth() && day >= this.endDate.getUTCDate() && hour >= this.endDate.getUTCHours()) {
645
+ this.picker.find('.next').css({
646
+ visibility: 'hidden'
647
+ });
648
+ } else {
649
+ this.picker.find('.next').css({
650
+ visibility: 'visible'
651
+ });
652
+ }
653
+ break;
654
+ case 1:
655
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth() && day <= this.startDate.getUTCDate()) {
656
+ this.picker.find('.prev').css({
657
+ visibility: 'hidden'
658
+ });
659
+ } else {
660
+ this.picker.find('.prev').css({
661
+ visibility: 'visible'
662
+ });
663
+ }
664
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth() && day >= this.endDate.getUTCDate()) {
665
+ this.picker.find('.next').css({
666
+ visibility: 'hidden'
667
+ });
668
+ } else {
669
+ this.picker.find('.next').css({
670
+ visibility: 'visible'
671
+ });
672
+ }
673
+ break;
674
+ case 2:
675
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
676
+ this.picker.find('.prev').css({
677
+ visibility: 'hidden'
678
+ });
679
+ } else {
680
+ this.picker.find('.prev').css({
681
+ visibility: 'visible'
682
+ });
683
+ }
684
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
685
+ this.picker.find('.next').css({
686
+ visibility: 'hidden'
687
+ });
688
+ } else {
689
+ this.picker.find('.next').css({
690
+ visibility: 'visible'
691
+ });
692
+ }
693
+ break;
694
+ case 3:
695
+ case 4:
696
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
697
+ this.picker.find('.prev').css({
698
+ visibility: 'hidden'
699
+ });
700
+ } else {
701
+ this.picker.find('.prev').css({
702
+ visibility: 'visible'
703
+ });
704
+ }
705
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
706
+ this.picker.find('.next').css({
707
+ visibility: 'hidden'
708
+ });
709
+ } else {
710
+ this.picker.find('.next').css({
711
+ visibility: 'visible'
712
+ });
713
+ }
714
+ break;
715
+ }
716
+ },
717
+
718
+ click: function(e) {
719
+ e.stopPropagation();
720
+ e.preventDefault();
721
+
722
+ if ($(e.target).hasClass('datepicker-close') || $(e.target).parent().hasClass('datepicker-close')) {
723
+ this.hide();
724
+ }
725
+
726
+ var target = $(e.target).closest('span, td, th');
727
+ if (target.length == 1) {
728
+ if (target.is('.disabled')) {
729
+ this.element.trigger({
730
+ type: 'outOfRange',
731
+ date: this.viewDate,
732
+ startDate: this.startDate,
733
+ endDate: this.endDate
734
+ });
735
+ return;
736
+ }
737
+
738
+ switch (target[0].nodeName.toLowerCase()) {
739
+ case 'th':
740
+ switch (target[0].className) {
741
+ case 'date-switch':
742
+ this.showMode(1);
743
+ break;
744
+ case 'prev':
745
+ case 'next':
746
+ var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
747
+ switch (this.viewMode) {
748
+ case 0:
749
+ this.viewDate = this.moveHour(this.viewDate, dir);
750
+ break;
751
+ case 1:
752
+ this.viewDate = this.moveDate(this.viewDate, dir);
753
+ break;
754
+ case 2:
755
+ this.viewDate = this.moveMonth(this.viewDate, dir);
756
+ break;
757
+ case 3:
758
+ case 4:
759
+ this.viewDate = this.moveYear(this.viewDate, dir);
760
+ break;
761
+ }
762
+ this.fill();
763
+ break;
764
+ case 'today':
765
+ var date = new Date();
766
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
767
+
768
+ this.viewMode = this.startViewMode;
769
+ this.showMode(0);
770
+ this._setDate(date);
771
+ break;
772
+ }
773
+ break;
774
+ case 'span':
775
+ if (!target.is('.disabled')) {
776
+ if (target.is('.month')) {
777
+ if (this.minView === 3) {
778
+ var month = target.parent().find('span').index(target) || 0;
779
+ var year = this.viewDate.getUTCFullYear(),
780
+ day = 1,
781
+ hours = this.viewDate.getUTCHours(),
782
+ minutes = this.viewDate.getUTCMinutes(),
783
+ seconds = this.viewDate.getUTCSeconds();
784
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
785
+ } else {
786
+ this.viewDate.setUTCDate(1);
787
+ var month = target.parent().find('span').index(target);
788
+ this.viewDate.setUTCMonth(month);
789
+ this.element.trigger({
790
+ type: 'changeMonth',
791
+ date: this.viewDate
792
+ });
793
+ }
794
+ } else if (target.is('.year')) {
795
+ if (this.minView === 4) {
796
+ var year = parseInt(target.text(), 10) || 0;
797
+ var month = 0,
798
+ day = 1,
799
+ hours = this.viewDate.getUTCHours(),
800
+ minutes = this.viewDate.getUTCMinutes(),
801
+ seconds = this.viewDate.getUTCSeconds();
802
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
803
+ } else {
804
+ this.viewDate.setUTCDate(1);
805
+ var year = parseInt(target.text(), 10) || 0;
806
+ this.viewDate.setUTCFullYear(year);
807
+ this.element.trigger({
808
+ type: 'changeYear',
809
+ date: this.viewDate
810
+ });
811
+ }
812
+ } else if (target.is('.hour')) {
813
+ var hours = parseInt(target.text(), 10) || 0;
814
+ var year = this.viewDate.getUTCFullYear(),
815
+ month = this.viewDate.getUTCMonth(),
816
+ day = this.viewDate.getUTCDate(),
817
+ minutes = this.viewDate.getUTCMinutes(),
818
+ seconds = this.viewDate.getUTCSeconds();
819
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
820
+ } else if (target.is('.minute')) {
821
+ var minutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0;
822
+ var year = this.viewDate.getUTCFullYear(),
823
+ month = this.viewDate.getUTCMonth(),
824
+ day = this.viewDate.getUTCDate(),
825
+ hours = this.viewDate.getUTCHours(),
826
+ seconds = this.viewDate.getUTCSeconds();
827
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
828
+ }
829
+
830
+
831
+
832
+ if (this.viewMode != 0) {
833
+
834
+
835
+
836
+ var oldViewMode = this.viewMode;
837
+ this.showMode(-1);
838
+ this.fill();
839
+ if (oldViewMode == this.viewMode && this.autoclose) {
840
+ this.hide();
841
+ }
842
+ } else {
843
+ this.fill();
844
+ if (this.autoclose) {
845
+ this.hide();
846
+ }
847
+ }
848
+ }
849
+ break;
850
+ case 'td':
851
+
852
+
853
+
854
+ if (target.is('.day') && !target.is('.disabled')) {
855
+ var day = parseInt(target.text(), 10) || 1;
856
+ var year = this.viewDate.getUTCFullYear(),
857
+ month = this.viewDate.getUTCMonth(),
858
+ hours = this.viewDate.getUTCHours(),
859
+ minutes = this.viewDate.getUTCMinutes(),
860
+ seconds = this.viewDate.getUTCSeconds();
861
+ if (target.is('.old')) {
862
+ if (month === 0) {
863
+ month = 11;
864
+ year -= 1;
865
+ } else {
866
+ month -= 1;
867
+ }
868
+ } else if (target.is('.new')) {
869
+ if (month == 11) {
870
+ month = 0;
871
+ year += 1;
872
+ } else {
873
+ month += 1;
874
+ }
875
+ }
876
+ this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
877
+ }
878
+
879
+
880
+
881
+ var oldViewMode = this.viewMode;
882
+
883
+
884
+ this.showMode(-1);
885
+
886
+
887
+ this.fill();
888
+ if (oldViewMode == this.viewMode && this.autoclose) {
889
+ this.hide();
890
+ }
891
+ break;
892
+ }
893
+ }
894
+ },
895
+
896
+ _setDate: function(date, which) {
897
+
898
+ if (!which || which == 'date')
899
+ this.date = date;
900
+ if (!which || which == 'view')
901
+ this.viewDate = date;
902
+ this.fill();
903
+ this.setValue();
904
+ this.element.trigger({
905
+ type: 'changeDate',
906
+ date: this.date
907
+ });
908
+ var element;
909
+ if (this.isInput) {
910
+ element = this.element;
911
+ } else if (this.component) {
912
+ element = this.element.find('input');
913
+ }
914
+ if (element) {
915
+ element.change();
916
+ if (this.autoclose && (!which || which == 'date')) {
917
+ // this.hide();
918
+ }
919
+ }
920
+ },
921
+
922
+ moveHour: function(date, dir) {
923
+ if (!dir) return date;
924
+ var new_date = new Date(date.valueOf());
925
+ dir = dir > 0 ? 1 : -1;
926
+ new_date.setUTCHours(new_date.getUTCHours() + dir);
927
+ return new_date;
928
+ },
929
+
930
+ moveDate: function(date, dir) {
931
+ if (!dir) return date;
932
+ var new_date = new Date(date.valueOf());
933
+ dir = dir > 0 ? 1 : -1;
934
+ new_date.setUTCDate(new_date.getUTCDate() + dir);
935
+ return new_date;
936
+ },
937
+
938
+ moveMonth: function(date, dir) {
939
+ if (!dir) return date;
940
+ var new_date = new Date(date.valueOf()),
941
+ day = new_date.getUTCDate(),
942
+ month = new_date.getUTCMonth(),
943
+ mag = Math.abs(dir),
944
+ new_month, test;
945
+ dir = dir > 0 ? 1 : -1;
946
+ if (mag == 1) {
947
+ test = dir == -1
948
+ // If going back one month, make sure month is not current month
949
+ // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
950
+ ? function() {
951
+ return new_date.getUTCMonth() == month;
952
+ }
953
+ // If going forward one month, make sure month is as expected
954
+ // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
955
+ : function() {
956
+ return new_date.getUTCMonth() != new_month;
957
+ };
958
+ new_month = month + dir;
959
+ new_date.setUTCMonth(new_month);
960
+ // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
961
+ if (new_month < 0 || new_month > 11)
962
+ new_month = (new_month + 12) % 12;
963
+ } else {
964
+ // For magnitudes >1, move one month at a time...
965
+ for (var i = 0; i < mag; i++)
966
+ // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
967
+ new_date = this.moveMonth(new_date, dir);
968
+ // ...then reset the day, keeping it in the new month
969
+ new_month = new_date.getUTCMonth();
970
+ new_date.setUTCDate(day);
971
+ test = function() {
972
+ return new_month != new_date.getUTCMonth();
973
+ };
974
+ }
975
+ // Common date-resetting loop -- if date is beyond end of month, make it
976
+ // end of month
977
+ while (test()) {
978
+ new_date.setUTCDate(--day);
979
+ new_date.setUTCMonth(new_month);
980
+ }
981
+ return new_date;
982
+ },
983
+
984
+ moveYear: function(date, dir) {
985
+ return this.moveMonth(date, dir * 12);
986
+ },
987
+
988
+ dateWithinRange: function(date) {
989
+ return date >= this.startDate && date <= this.endDate;
990
+ },
991
+
992
+ keydown: function(e) {
993
+ if (!this.keyboardNavigation) {
994
+ return true;
995
+ }
996
+ if (this.picker.is(':not(:visible)')) {
997
+ if (e.keyCode == 27) // allow escape to hide and re-show picker
998
+ this.show();
999
+ return;
1000
+ }
1001
+ var dateChanged = false,
1002
+ dir, day, month,
1003
+ newDate, newViewDate;
1004
+ switch (e.keyCode) {
1005
+ case 27: // escape
1006
+ this.hide();
1007
+ e.preventDefault();
1008
+ break;
1009
+ case 37: // left
1010
+ case 39: // right
1011
+ if (!this.keyboardNavigation) break;
1012
+ dir = e.keyCode == 37 ? -1 : 1;
1013
+ if (e.ctrlKey) {
1014
+ newDate = this.moveYear(this.date, dir);
1015
+ newViewDate = this.moveYear(this.viewDate, dir);
1016
+ } else if (e.shiftKey) {
1017
+ newDate = this.moveMonth(this.date, dir);
1018
+ newViewDate = this.moveMonth(this.viewDate, dir);
1019
+ } else {
1020
+ newDate = new Date(this.date.valueOf());
1021
+ newDate.setUTCDate(this.date.getUTCDate() + dir);
1022
+ newViewDate = new Date(this.viewDate.valueOf());
1023
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
1024
+ }
1025
+ if (this.dateWithinRange(newDate)) {
1026
+ this.date = newDate;
1027
+ this.viewDate = newViewDate;
1028
+ this.setValue();
1029
+ this.update();
1030
+ e.preventDefault();
1031
+ dateChanged = true;
1032
+ }
1033
+ break;
1034
+ case 38: // up
1035
+ case 40: // down
1036
+ if (!this.keyboardNavigation) break;
1037
+ dir = e.keyCode == 38 ? -1 : 1;
1038
+ if (e.ctrlKey) {
1039
+ newDate = this.moveYear(this.date, dir);
1040
+ newViewDate = this.moveYear(this.viewDate, dir);
1041
+ } else if (e.shiftKey) {
1042
+ newDate = this.moveMonth(this.date, dir);
1043
+ newViewDate = this.moveMonth(this.viewDate, dir);
1044
+ } else {
1045
+ newDate = new Date(this.date.valueOf());
1046
+ newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
1047
+ newViewDate = new Date(this.viewDate.valueOf());
1048
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
1049
+ }
1050
+ if (this.dateWithinRange(newDate)) {
1051
+ this.date = newDate;
1052
+ this.viewDate = newViewDate;
1053
+ this.setValue();
1054
+ this.update();
1055
+ e.preventDefault();
1056
+ dateChanged = true;
1057
+ }
1058
+ break;
1059
+ case 13: // enter
1060
+ this.hide();
1061
+ e.preventDefault();
1062
+ break;
1063
+ case 9: // tab
1064
+ this.hide();
1065
+ break;
1066
+ }
1067
+ if (dateChanged) {
1068
+ this.element.trigger({
1069
+ type: 'changeDate',
1070
+ date: this.date
1071
+ });
1072
+ var element;
1073
+ if (this.isInput) {
1074
+ element = this.element;
1075
+ } else if (this.component) {
1076
+ element = this.element.find('input');
1077
+ }
1078
+ if (element) {
1079
+ element.change();
1080
+ }
1081
+ }
1082
+ },
1083
+
1084
+ showMode: function(dir) {
1085
+
1086
+ if (dir) {
1087
+ var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));
1088
+ if (newViewMode >= this.minView && newViewMode <= this.maxView) {
1089
+ this.viewMode = newViewMode;
1090
+ }
1091
+ }
1092
+ /*
1093
+ vitalets: fixing bug of very special conditions:
1094
+ jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
1095
+ Method show() does not set display css correctly and datepicker is not shown.
1096
+ Changed to .css('display', 'block') solve the problem.
1097
+ See https://github.com/vitalets/x-editable/issues/37
1098
+
1099
+ In jquery 1.7.2+ everything works fine.
1100
+ */
1101
+ //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
1102
+ this.picker.find('>div').hide().filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
1103
+ this.updateNavArrows();
1104
+ },
1105
+
1106
+ changeViewDate: function(date) {
1107
+ this.date = date;
1108
+ this.viewDate = date;
1109
+ this.fill();
1110
+ },
1111
+
1112
+ reset: function(e) {
1113
+ this._setDate(null, 'date');
1114
+ }
1115
+ };
1116
+
1117
+ $.fn.fdatepicker = function(option) {
1118
+ var args = Array.apply(null, arguments);
1119
+ args.shift();
1120
+ return this.each(function() {
1121
+ var $this = $(this),
1122
+ data = $this.data('datepicker'),
1123
+ options = typeof option == 'object' && option;
1124
+ if (!data) {
1125
+ $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.fdatepicker.defaults, options))));
1126
+ }
1127
+ if (typeof option == 'string' && typeof data[option] == 'function') {
1128
+ data[option].apply(data, args);
1129
+ }
1130
+ });
1131
+ };
1132
+
1133
+ $.fn.fdatepicker.defaults = {
1134
+ onRender: function(date) {
1135
+ return '';
1136
+ }
1137
+ };
1138
+ $.fn.fdatepicker.Constructor = Datepicker;
1139
+ var dates = $.fn.fdatepicker.dates = {
1140
+ 'en': {
1141
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
1142
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
1143
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
1144
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
1145
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1146
+ today: "Today",
1147
+ titleFormat: "MM yyyy"
1148
+ }
1149
+ };
1150
+
1151
+ var DPGlobal = {
1152
+ modes: [{
1153
+ clsName: 'minutes',
1154
+ navFnc: 'Hours',
1155
+ navStep: 1
1156
+ }, {
1157
+ clsName: 'hours',
1158
+ navFnc: 'Date',
1159
+ navStep: 1
1160
+ }, {
1161
+ clsName: 'days',
1162
+ navFnc: 'Month',
1163
+ navStep: 1
1164
+ }, {
1165
+ clsName: 'months',
1166
+ navFnc: 'FullYear',
1167
+ navStep: 1
1168
+ }, {
1169
+ clsName: 'years',
1170
+ navFnc: 'FullYear',
1171
+ navStep: 10
1172
+ }],
1173
+ isLeapYear: function(year) {
1174
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
1175
+ },
1176
+ getDaysInMonth: function(year, month) {
1177
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1178
+ },
1179
+ validParts: /hh?|ii?|ss?|dd?|mm?|MM?|yy(?:yy)?/g,
1180
+ nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
1181
+ parseFormat: function(format) {
1182
+ // IE treats \0 as a string end in inputs (truncating the value),
1183
+ // so it's a bad format delimiter, anyway
1184
+ var separators = format.replace(this.validParts, '\0').split('\0'),
1185
+ parts = format.match(this.validParts);
1186
+ if (!separators || !separators.length || !parts || parts.length === 0) {
1187
+ throw new Error("Invalid date format.");
1188
+ }
1189
+ this.formatText = format;
1190
+ return {
1191
+ separators: separators,
1192
+ parts: parts
1193
+ };
1194
+ },
1195
+ parseDate: function(date, format, language) {
1196
+ if (date instanceof Date) return new Date(date.valueOf() - date.getTimezoneOffset() * 60000);
1197
+ if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
1198
+ format = this.parseFormat('yyyy-mm-dd');
1199
+ }
1200
+ if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) {
1201
+ format = this.parseFormat('yyyy-mm-dd hh:ii');
1202
+ }
1203
+ if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) {
1204
+ format = this.parseFormat('yyyy-mm-dd hh:ii:ss');
1205
+ }
1206
+ if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
1207
+ var part_re = /([-+]\d+)([dmwy])/,
1208
+ parts = date.match(/([-+]\d+)([dmwy])/g),
1209
+ part, dir;
1210
+ date = new Date();
1211
+ for (var i = 0; i < parts.length; i++) {
1212
+ part = part_re.exec(parts[i]);
1213
+ dir = parseInt(part[1]);
1214
+ switch (part[2]) {
1215
+ case 'd':
1216
+ date.setUTCDate(date.getUTCDate() + dir);
1217
+ break;
1218
+ case 'm':
1219
+ date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);
1220
+ break;
1221
+ case 'w':
1222
+ date.setUTCDate(date.getUTCDate() + dir * 7);
1223
+ break;
1224
+ case 'y':
1225
+ date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);
1226
+ break;
1227
+ }
1228
+ }
1229
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
1230
+ }
1231
+ var parts = date && date.match(this.nonpunctuation) || [],
1232
+ date = new Date(),
1233
+ parsed = {},
1234
+ setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1235
+ setters_map = {
1236
+ hh: function(d, v) {
1237
+ return d.setUTCHours(v);
1238
+ },
1239
+ h: function(d, v) {
1240
+ return d.setUTCHours(v);
1241
+ },
1242
+ ii: function(d, v) {
1243
+ return d.setUTCMinutes(v);
1244
+ },
1245
+ i: function(d, v) {
1246
+ return d.setUTCMinutes(v);
1247
+ },
1248
+ ss: function(d, v) {
1249
+ return d.setUTCSeconds(v);
1250
+ },
1251
+ s: function(d, v) {
1252
+ return d.setUTCSeconds(v);
1253
+ },
1254
+ yyyy: function(d, v) {
1255
+ return d.setUTCFullYear(v);
1256
+ },
1257
+ yy: function(d, v) {
1258
+ return d.setUTCFullYear(2000 + v);
1259
+ },
1260
+ m: function(d, v) {
1261
+ v -= 1;
1262
+ while (v < 0) v += 12;
1263
+ v %= 12;
1264
+ d.setUTCMonth(v);
1265
+ while (d.getUTCMonth() != v)
1266
+ d.setUTCDate(d.getUTCDate() - 1);
1267
+ return d;
1268
+ },
1269
+ d: function(d, v) {
1270
+ return d.setUTCDate(v);
1271
+ }
1272
+ },
1273
+ val, filtered, part;
1274
+ setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1275
+ setters_map['dd'] = setters_map['d'];
1276
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); //date.getHours(), date.getMinutes(), date.getSeconds());
1277
+ if (parts.length == format.parts.length) {
1278
+ for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1279
+ val = parseInt(parts[i], 10);
1280
+ part = format.parts[i];
1281
+ if (isNaN(val)) {
1282
+ switch (part) {
1283
+ case 'MM':
1284
+ filtered = $(dates[language].months).filter(function() {
1285
+ var m = this.slice(0, parts[i].length),
1286
+ p = parts[i].slice(0, m.length);
1287
+ return m == p;
1288
+ });
1289
+ val = $.inArray(filtered[0], dates[language].months) + 1;
1290
+ break;
1291
+ case 'M':
1292
+ filtered = $(dates[language].monthsShort).filter(function() {
1293
+ var m = this.slice(0, parts[i].length),
1294
+ p = parts[i].slice(0, m.length);
1295
+ return m == p;
1296
+ });
1297
+ val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1298
+ break;
1299
+ }
1300
+ }
1301
+ parsed[part] = val;
1302
+ }
1303
+ for (var i = 0, s; i < setters_order.length; i++) {
1304
+ s = setters_order[i];
1305
+ if (s in parsed && !isNaN(parsed[s]))
1306
+ setters_map[s](date, parsed[s])
1307
+ }
1308
+ }
1309
+ return date;
1310
+ },
1311
+ formatDate: function(date, format, language) {
1312
+ if (date == null) {
1313
+ return '';
1314
+ }
1315
+ var val = {
1316
+ h: date.getUTCHours(),
1317
+ i: date.getUTCMinutes(),
1318
+ s: date.getUTCSeconds(),
1319
+ d: date.getUTCDate(),
1320
+ m: date.getUTCMonth() + 1,
1321
+ M: dates[language].monthsShort[date.getUTCMonth()],
1322
+ MM: dates[language].months[date.getUTCMonth()],
1323
+ yy: date.getUTCFullYear().toString().substring(2),
1324
+ yyyy: date.getUTCFullYear()
1325
+ };
1326
+ val.hh = (val.h < 10 ? '0' : '') + val.h;
1327
+ val.ii = (val.i < 10 ? '0' : '') + val.i;
1328
+ val.ss = (val.s < 10 ? '0' : '') + val.s;
1329
+ val.dd = (val.d < 10 ? '0' : '') + val.d;
1330
+ val.mm = (val.m < 10 ? '0' : '') + val.m;
1331
+ var date = [],
1332
+ seps = $.extend([], format.separators);
1333
+ for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1334
+ if (seps.length)
1335
+ date.push(seps.shift())
1336
+ date.push(val[format.parts[i]]);
1337
+ }
1338
+ return date.join('');
1339
+ },
1340
+ convertViewMode: function(viewMode) {
1341
+ switch (viewMode) {
1342
+ case 4:
1343
+ case 'decade':
1344
+ viewMode = 4;
1345
+ break;
1346
+ case 3:
1347
+ case 'year':
1348
+ viewMode = 3;
1349
+ break;
1350
+ case 2:
1351
+ case 'month':
1352
+ viewMode = 2;
1353
+ break;
1354
+ case 1:
1355
+ case 'day':
1356
+ viewMode = 1;
1357
+ break;
1358
+ case 0:
1359
+ case 'hour':
1360
+ viewMode = 0;
1361
+ break;
1362
+ }
1363
+
1364
+ return viewMode;
1365
+ },
1366
+ headTemplate: function(leftArrow, rightArrow) {return('<thead>' +
1367
+ '<tr>' +
1368
+ '<th class="prev">' + leftArrow + '</th>' +
1369
+ '<th colspan="5" class="date-switch"></th>' +
1370
+ '<th class="next">' + rightArrow + '</th>' +
1371
+ '</tr>' +
1372
+ '</thead>')},
1373
+ contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1374
+ footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
1375
+ };
1376
+ DPGlobal.template = function(leftArrow, rightArrow, closeIcon) {return( '<div class="datepicker">' +
1377
+ '<div class="datepicker-minutes">' +
1378
+ '<table class=" table-condensed">' +
1379
+ DPGlobal.headTemplate(leftArrow, rightArrow) +
1380
+ DPGlobal.contTemplate +
1381
+ DPGlobal.footTemplate +
1382
+ '</table>' +
1383
+ '</div>' +
1384
+ '<div class="datepicker-hours">' +
1385
+ '<table class=" table-condensed">' +
1386
+ DPGlobal.headTemplate(leftArrow, rightArrow) +
1387
+ DPGlobal.contTemplate +
1388
+ DPGlobal.footTemplate +
1389
+ '</table>' +
1390
+ '</div>' +
1391
+ '<div class="datepicker-days">' +
1392
+ '<table class=" table-condensed">' +
1393
+ DPGlobal.headTemplate(leftArrow, rightArrow) +
1394
+ '<tbody></tbody>' +
1395
+ DPGlobal.footTemplate +
1396
+ '</table>' +
1397
+ '</div>' +
1398
+ '<div class="datepicker-months">' +
1399
+ '<table class="table-condensed">' +
1400
+ DPGlobal.headTemplate(leftArrow, rightArrow) +
1401
+ DPGlobal.contTemplate +
1402
+ DPGlobal.footTemplate +
1403
+ '</table>' +
1404
+ '</div>' +
1405
+ '<div class="datepicker-years">' +
1406
+ '<table class="table-condensed">' +
1407
+ DPGlobal.headTemplate(leftArrow, rightArrow) +
1408
+ DPGlobal.contTemplate +
1409
+ DPGlobal.footTemplate +
1410
+ '</table>' +
1411
+ '</div>' +
1412
+ '<a class="button datepicker-close tiny alert right" style="width:auto;">' + closeIcon + '</a>' +
1413
+ '</div>')};
1414
+
1415
+ $.fn.fdatepicker.DPGlobal = DPGlobal;
1416
+
1417
+ }(window.jQuery);