adminpanel 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. data/.rspec +2 -2
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +8 -8
  4. data/Gemfile +26 -24
  5. data/README.md +57 -57
  6. data/adminpanel.gemspec +41 -39
  7. data/app/assets/fonts/fontawesome-webfont.svg +254 -254
  8. data/app/assets/javascripts/adminpanel/bootstrap-datepicker.js +1159 -1159
  9. data/app/assets/javascripts/adminpanel/bootstrap-timepicker.js +803 -803
  10. data/app/assets/javascripts/adminpanel/bootstrap.js +2170 -2170
  11. data/app/assets/javascripts/adminpanel/{products.js → images_form.js} +13 -13
  12. data/app/assets/javascripts/adminpanel/imagesloaded.js +12 -12
  13. data/app/assets/javascripts/adminpanel/jquery.dataTables.min.js +155 -155
  14. data/app/assets/javascripts/adminpanel/jquery.facybox.js +395 -395
  15. data/app/assets/javascripts/adminpanel/jquery.masonry.min.js +9 -9
  16. data/app/assets/javascripts/adminpanel/jquery.slimscroll.min.js +13 -13
  17. data/app/assets/javascripts/adminpanel/medium-editor.js +702 -702
  18. data/app/assets/javascripts/adminpanel/realm.js +87 -87
  19. data/app/assets/javascripts/adminpanel/tables.js +126 -126
  20. data/app/assets/javascripts/application-admin.js +15 -15
  21. data/app/assets/stylesheets/adminpanel/_clearfix.css.scss +7 -7
  22. data/app/assets/stylesheets/adminpanel/alertify.css +241 -241
  23. data/app/assets/stylesheets/adminpanel/bootstrap.css +6103 -6103
  24. data/app/assets/stylesheets/adminpanel/colorpicker.css +6 -6
  25. data/app/assets/stylesheets/adminpanel/datepicker.css +9 -9
  26. data/app/assets/stylesheets/adminpanel/elfinder.min.css +59 -59
  27. data/app/assets/stylesheets/adminpanel/facybox.css +146 -146
  28. data/app/assets/stylesheets/adminpanel/font-awesome.min.css +33 -33
  29. data/app/assets/stylesheets/adminpanel/fullcalendar.css +618 -618
  30. data/app/assets/stylesheets/adminpanel/fullcalendar.print.css +61 -61
  31. data/app/assets/stylesheets/adminpanel/select2.css +524 -524
  32. data/app/assets/stylesheets/adminpanel/theme.css +1571 -1571
  33. data/app/assets/stylesheets/adminpanel/timepicker.css +82 -82
  34. data/app/assets/stylesheets/application-admin.css +13 -13
  35. data/app/controllers/adminpanel/application_controller.rb +32 -17
  36. data/app/controllers/adminpanel/galleries_controller.rb +80 -80
  37. data/app/controllers/adminpanel/sections_controller.rb +45 -45
  38. data/app/controllers/adminpanel/sessions_controller.rb +26 -26
  39. data/app/controllers/adminpanel/users_controller.rb +84 -84
  40. data/app/helpers/adminpanel/application_helper.rb +41 -51
  41. data/app/helpers/adminpanel/breadcrumbs_helper.rb +16 -0
  42. data/app/helpers/adminpanel/custom_form_builder.rb +248 -0
  43. data/app/helpers/adminpanel/images_helper.rb +9 -9
  44. data/app/helpers/adminpanel/rest_actions_helper.rb +47 -0
  45. data/app/helpers/adminpanel/router_helper.rb +33 -0
  46. data/app/helpers/adminpanel/sessions_helper.rb +25 -25
  47. data/app/models/adminpanel/gallery.rb +60 -60
  48. data/app/models/adminpanel/image.rb +14 -14
  49. data/app/models/adminpanel/section.rb +22 -22
  50. data/app/models/adminpanel/user.rb +35 -35
  51. data/app/uploaders/adminpanel/gallery_uploader.rb +55 -55
  52. data/app/uploaders/adminpanel/image_uploader.rb +57 -57
  53. data/app/views/adminpanel/galleries/_galleries_table.html.erb +14 -14
  54. data/app/views/adminpanel/galleries/create.html.erb +2 -2
  55. data/app/views/adminpanel/galleries/delete.html.erb +2 -2
  56. data/app/views/adminpanel/galleries/edit.html.erb +25 -25
  57. data/app/views/adminpanel/galleries/index.html.erb +51 -51
  58. data/app/views/adminpanel/galleries/new.html.erb +17 -17
  59. data/app/views/adminpanel/galleries/show.html.erb +17 -17
  60. data/app/views/adminpanel/galleries/update.html.erb +2 -2
  61. data/app/views/adminpanel/sections/_image_fields.html.erb +23 -23
  62. data/app/views/adminpanel/sections/_sections_table.html.erb +16 -16
  63. data/app/views/adminpanel/sections/create.html.erb +2 -2
  64. data/app/views/adminpanel/sections/destroy.html.erb +2 -2
  65. data/app/views/adminpanel/sections/edit.html.erb +41 -41
  66. data/app/views/adminpanel/sections/index.html.erb +44 -44
  67. data/app/views/adminpanel/sections/new.html.erb +26 -26
  68. data/app/views/adminpanel/sections/show.html.erb +30 -30
  69. data/app/views/adminpanel/sections/update.html.erb +2 -2
  70. data/app/views/adminpanel/sessions/new.html.erb +25 -25
  71. data/app/views/adminpanel/users/_user_form.html.erb +20 -20
  72. data/app/views/adminpanel/users/edit.html.erb +5 -5
  73. data/app/views/adminpanel/users/index.html.erb +49 -49
  74. data/app/views/adminpanel/users/new.html.erb +5 -5
  75. data/app/views/adminpanel/users/show.html.erb +20 -20
  76. data/app/views/layouts/_shim.html.erb +3 -3
  77. data/app/views/layouts/_side_menu.html.erb +49 -43
  78. data/app/views/layouts/_top_bar.html.erb +43 -43
  79. data/app/views/layouts/admin-login.html.erb +28 -28
  80. data/app/views/layouts/admin.html.erb +41 -39
  81. data/app/views/shared/_breadcrumb.html.erb +6 -6
  82. data/app/views/shared/_error_messages.html.erb +16 -16
  83. data/app/views/shared/_form_fields.html.erb +25 -0
  84. data/app/views/{adminpanel/products → shared}/_image_fields.html.erb +23 -23
  85. data/app/views/shared/_init_editor.html.erb +24 -0
  86. data/app/views/shared/edit.html.erb +28 -0
  87. data/app/views/shared/index.html.erb +94 -0
  88. data/app/views/shared/new.html.erb +28 -0
  89. data/app/views/shared/show.html.erb +63 -0
  90. data/config/locales/en.yml +5 -5
  91. data/config/locales/es.yml +127 -129
  92. data/config/routes.rb +24 -16
  93. data/lib/adminpanel.rb +9 -7
  94. data/lib/adminpanel/active_record_extension.rb +38 -0
  95. data/lib/adminpanel/engine.rb +5 -5
  96. data/lib/adminpanel/version.rb +3 -3
  97. data/lib/generators/adminpanel/initialize/initialize_generator.rb +17 -0
  98. data/lib/generators/adminpanel/{install/templates/migrations → initialize/templates}/create_adminpanel_tables.rb +45 -64
  99. data/lib/generators/adminpanel/resource/resource_generator.rb +105 -0
  100. data/lib/generators/adminpanel/resource/templates/controller.rb +4 -0
  101. data/lib/generators/adminpanel/resource/templates/migration.rb +9 -0
  102. data/lib/generators/adminpanel/resource/templates/resource.rb +19 -0
  103. data/spec/dummy/.gitignore +17 -17
  104. data/spec/dummy/README.rdoc +261 -261
  105. data/spec/dummy/Rakefile +7 -7
  106. data/{app/views/adminpanel/categories/show.html.erb → spec/dummy/app/adminpanel/products.rb} +0 -0
  107. data/spec/dummy/app/assets/javascripts/application.js +13 -13
  108. data/spec/dummy/app/assets/stylesheets/application.css +13 -13
  109. data/spec/dummy/app/controllers/adminpanel/.gitkeep +0 -0
  110. data/spec/dummy/app/controllers/application_controller.rb +3 -11
  111. data/spec/dummy/app/helpers/application_helper.rb +2 -2
  112. data/spec/dummy/app/views/layouts/application.html.erb +14 -14
  113. data/spec/dummy/config.ru +4 -4
  114. data/spec/dummy/config/application.rb +62 -62
  115. data/spec/dummy/config/boot.rb +9 -9
  116. data/spec/dummy/config/carrierwve.rb +5 -5
  117. data/spec/dummy/config/database.yml +24 -24
  118. data/spec/dummy/config/environment.rb +5 -5
  119. data/spec/dummy/config/environments/development.rb +41 -41
  120. data/spec/dummy/config/environments/production.rb +72 -72
  121. data/spec/dummy/config/environments/test.rb +41 -41
  122. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -7
  123. data/spec/dummy/config/initializers/inflections.rb +15 -15
  124. data/spec/dummy/config/initializers/mime_types.rb +5 -5
  125. data/spec/dummy/config/initializers/secret_token.rb +8 -8
  126. data/spec/dummy/config/initializers/session_store.rb +8 -8
  127. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -14
  128. data/spec/dummy/config/locales/en.yml +5 -5
  129. data/spec/dummy/config/routes.rb +4 -4
  130. data/spec/dummy/db/schema.rb +15 -15
  131. data/spec/dummy/public/404.html +26 -26
  132. data/spec/dummy/public/422.html +26 -26
  133. data/spec/dummy/public/500.html +25 -25
  134. data/spec/dummy/public/uploads/gallery/file/1/hipster.jpg +0 -0
  135. data/spec/dummy/public/uploads/gallery/file/1/thumb_hipster.jpg +0 -0
  136. data/spec/dummy/script/rails +6 -6
  137. data/spec/features/authentication_pages_spec.rb +43 -43
  138. data/spec/features/galleries_pages_spec.rb +124 -124
  139. data/spec/features/section_pages_spec.rb +37 -37
  140. data/spec/features/user_pages_spec.rb +48 -48
  141. data/spec/generators/initialize_spec.rb +9 -0
  142. data/spec/generators/resource_spec.rb +122 -0
  143. data/spec/models/gallery_spec.rb +21 -21
  144. data/spec/models/section_spec.rb +66 -66
  145. data/spec/models/user_spec.rb +105 -105
  146. data/spec/spec_helper.rb +32 -31
  147. data/spec/support/define_factory_models.rb +25 -36
  148. data/spec/support/helper_methods.rb +26 -26
  149. data/spec/support/submit_forms_without_button.rb +16 -16
  150. data/spec/support/test_database.rb +45 -58
  151. data/spec/uploaders/gallery_uploader_spec.rb +36 -30
  152. data/spec/uploaders/image_uploader_spec.rb +30 -29
  153. metadata +208 -64
  154. checksums.yaml +0 -7
  155. data/app/assets/javascripts/adminpanel/init_editor.js +0 -28
  156. data/app/controllers/adminpanel/categories_controller.rb +0 -41
  157. data/app/controllers/adminpanel/products_controller.rb +0 -88
  158. data/app/helpers/custom_form_builder.rb +0 -219
  159. data/app/models/adminpanel/category.rb +0 -7
  160. data/app/models/adminpanel/product.rb +0 -24
  161. data/app/views/adminpanel/categories/edit.html.erb +0 -18
  162. data/app/views/adminpanel/categories/index.html.erb +0 -55
  163. data/app/views/adminpanel/categories/new.html.erb +0 -18
  164. data/app/views/adminpanel/products/.DS_Store +0 -0
  165. data/app/views/adminpanel/products/_product_form.html.erb +0 -31
  166. data/app/views/adminpanel/products/edit.html.erb +0 -10
  167. data/app/views/adminpanel/products/index.html.erb +0 -51
  168. data/app/views/adminpanel/products/new.html.erb +0 -10
  169. data/app/views/adminpanel/products/show.html.erb +0 -61
  170. data/config/database.yml +0 -24
  171. data/lib/generators/adminpanel/install/install_generator.rb +0 -12
  172. data/spec/features/categories_pages_spec.rb +0 -44
  173. data/spec/features/product_pages_spec.rb +0 -64
  174. data/spec/models/category_spec.rb +0 -58
  175. data/spec/models/product_spec.rb +0 -51
@@ -1,1159 +1,1159 @@
1
- /* =========================================================
2
- * bootstrap-datepicker.js
3
- * http://www.eyecon.ro/bootstrap-datepicker
4
- * =========================================================
5
- * Copyright 2012 Stefan Petre
6
- * Improvements by Andrew Rowls
7
- *
8
- * Licensed under the Apache License, Version 2.0 (the "License");
9
- * you may not use this file except in compliance with the License.
10
- * You may obtain a copy of the License at
11
- *
12
- * http://www.apache.org/licenses/LICENSE-2.0
13
- *
14
- * Unless required by applicable law or agreed to in writing, software
15
- * distributed under the License is distributed on an "AS IS" BASIS,
16
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- * See the License for the specific language governing permissions and
18
- * limitations under the License.
19
- * ========================================================= */
20
-
21
- !function( $ ) {
22
-
23
- function UTCDate(){
24
- return new Date(Date.UTC.apply(Date, arguments));
25
- }
26
- function UTCToday(){
27
- var today = new Date();
28
- return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
29
- }
30
-
31
- // Picker object
32
-
33
- var Datepicker = function(element, options) {
34
- var that = this;
35
-
36
- this.element = $(element);
37
- this.language = options.language||this.element.data('date-language')||"en";
38
- 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"
39
- this.language = this.language in dates ? this.language : "en";
40
- this.isRTL = dates[this.language].rtl||false;
41
- this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||dates[this.language].format||'mm/dd/yyyy');
42
- this.isInline = false;
43
- this.isInput = this.element.is('input');
44
- this.component = this.element.is('.date') ? this.element.find('.add-on, .btn') : false;
45
- this.hasInput = this.component && this.element.find('input').length;
46
- if(this.component && this.component.length === 0)
47
- this.component = false;
48
-
49
- this.forceParse = true;
50
- if ('forceParse' in options) {
51
- this.forceParse = options.forceParse;
52
- } else if ('dateForceParse' in this.element.data()) {
53
- this.forceParse = this.element.data('date-force-parse');
54
- }
55
-
56
- this.picker = $(DPGlobal.template);
57
- this._buildEvents();
58
- this._attachEvents();
59
-
60
- if(this.isInline) {
61
- this.picker.addClass('datepicker-inline').appendTo(this.element);
62
- } else {
63
- this.picker.addClass('datepicker-dropdown dropdown-menu');
64
- }
65
- if (this.isRTL){
66
- this.picker.addClass('datepicker-rtl');
67
- this.picker.find('.prev i, .next i')
68
- .toggleClass('icon-arrow-left icon-arrow-right');
69
- }
70
-
71
- this.autoclose = false;
72
- if ('autoclose' in options) {
73
- this.autoclose = options.autoclose;
74
- } else if ('dateAutoclose' in this.element.data()) {
75
- this.autoclose = this.element.data('date-autoclose');
76
- }
77
-
78
- this.keyboardNavigation = true;
79
- if ('keyboardNavigation' in options) {
80
- this.keyboardNavigation = options.keyboardNavigation;
81
- } else if ('dateKeyboardNavigation' in this.element.data()) {
82
- this.keyboardNavigation = this.element.data('date-keyboard-navigation');
83
- }
84
-
85
- this.viewMode = this.startViewMode = 0;
86
- switch(options.startView || this.element.data('date-start-view')){
87
- case 2:
88
- case 'decade':
89
- this.viewMode = this.startViewMode = 2;
90
- break;
91
- case 1:
92
- case 'year':
93
- this.viewMode = this.startViewMode = 1;
94
- break;
95
- }
96
-
97
- this.minViewMode = options.minViewMode||this.element.data('date-min-view-mode')||0;
98
- if (typeof this.minViewMode === 'string') {
99
- switch (this.minViewMode) {
100
- case 'months':
101
- this.minViewMode = 1;
102
- break;
103
- case 'years':
104
- this.minViewMode = 2;
105
- break;
106
- default:
107
- this.minViewMode = 0;
108
- break;
109
- }
110
- }
111
-
112
- this.viewMode = this.startViewMode = Math.max(this.startViewMode, this.minViewMode);
113
-
114
- this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false);
115
- this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false);
116
-
117
- this.calendarWeeks = false;
118
- if ('calendarWeeks' in options) {
119
- this.calendarWeeks = options.calendarWeeks;
120
- } else if ('dateCalendarWeeks' in this.element.data()) {
121
- this.calendarWeeks = this.element.data('date-calendar-weeks');
122
- }
123
- if (this.calendarWeeks)
124
- this.picker.find('tfoot th.today')
125
- .attr('colspan', function(i, val){
126
- return parseInt(val) + 1;
127
- });
128
-
129
- this._allow_update = false;
130
-
131
- this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
132
- this.weekEnd = ((this.weekStart + 6) % 7);
133
- this.startDate = -Infinity;
134
- this.endDate = Infinity;
135
- this.daysOfWeekDisabled = [];
136
- this.setStartDate(options.startDate||this.element.data('date-startdate'));
137
- this.setEndDate(options.endDate||this.element.data('date-enddate'));
138
- this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled'));
139
- this.fillDow();
140
- this.fillMonths();
141
- this.setRange(options.range);
142
-
143
- this._allow_update = true;
144
-
145
- this.update();
146
- this.showMode();
147
-
148
- if(this.isInline) {
149
- this.show();
150
- }
151
- };
152
-
153
- Datepicker.prototype = {
154
- constructor: Datepicker,
155
-
156
- _events: [],
157
- _secondaryEvents: [],
158
- _applyEvents: function(evs){
159
- for (var i=0, el, ev; i<evs.length; i++){
160
- el = evs[i][0];
161
- ev = evs[i][1];
162
- el.on(ev);
163
- }
164
- },
165
- _unapplyEvents: function(evs){
166
- for (var i=0, el, ev; i<evs.length; i++){
167
- el = evs[i][0];
168
- ev = evs[i][1];
169
- el.off(ev);
170
- }
171
- },
172
- _buildEvents: function(){
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
- }
195
- else if (this.element.is('div')) { // inline datepicker
196
- this.isInline = true;
197
- }
198
- else {
199
- this._events = [
200
- [this.element, {
201
- click: $.proxy(this.show, this)
202
- }]
203
- ];
204
- }
205
-
206
- this._secondaryEvents = [
207
- [this.picker, {
208
- click: $.proxy(this.click, this)
209
- }],
210
- [$(window), {
211
- resize: $.proxy(this.place, this)
212
- }],
213
- [$(document), {
214
- mousedown: $.proxy(function (e) {
215
- // Clicked outside the datepicker, hide it
216
- if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
217
- this.hide();
218
- }
219
- }, this)
220
- }]
221
- ];
222
- },
223
- _attachEvents: function(){
224
- this._detachEvents();
225
- this._applyEvents(this._events);
226
- },
227
- _detachEvents: function(){
228
- this._unapplyEvents(this._events);
229
- },
230
- _attachSecondaryEvents: function(){
231
- this._detachSecondaryEvents();
232
- this._applyEvents(this._secondaryEvents);
233
- },
234
- _detachSecondaryEvents: function(){
235
- this._unapplyEvents(this._secondaryEvents);
236
- },
237
-
238
- show: function(e) {
239
- if (!this.isInline)
240
- this.picker.appendTo('body');
241
- this.picker.show();
242
- this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
243
- this.place();
244
- this._attachSecondaryEvents();
245
- if (e) {
246
- e.preventDefault();
247
- }
248
- this.element.trigger({
249
- type: 'show',
250
- date: this.date
251
- });
252
- },
253
-
254
- hide: function(e){
255
- if(this.isInline) return;
256
- if (!this.picker.is(':visible')) return;
257
- this.picker.hide().detach();
258
- this._detachSecondaryEvents();
259
- this.viewMode = this.startViewMode;
260
- this.showMode();
261
-
262
- if (
263
- this.forceParse &&
264
- (
265
- this.isInput && this.element.val() ||
266
- this.hasInput && this.element.find('input').val()
267
- )
268
- )
269
- this.setValue();
270
- this.element.trigger({
271
- type: 'hide',
272
- date: this.date
273
- });
274
- },
275
-
276
- remove: function() {
277
- this.hide();
278
- this._detachEvents();
279
- this._detachSecondaryEvents();
280
- this.picker.remove();
281
- delete this.element.data().datepicker;
282
- if (!this.isInput) {
283
- delete this.element.data().date;
284
- }
285
- },
286
-
287
- getDate: function() {
288
- var d = this.getUTCDate();
289
- return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
290
- },
291
-
292
- getUTCDate: function() {
293
- return this.date;
294
- },
295
-
296
- setDate: function(d) {
297
- this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
298
- },
299
-
300
- setUTCDate: function(d) {
301
- this.date = d;
302
- this.setValue();
303
- },
304
-
305
- setValue: function() {
306
- var formatted = this.getFormattedDate();
307
- if (!this.isInput) {
308
- if (this.component){
309
- this.element.find('input').val(formatted);
310
- }
311
- } else {
312
- this.element.val(formatted);
313
- }
314
- },
315
-
316
- getFormattedDate: function(format) {
317
- if (format === undefined)
318
- format = this.format;
319
- return DPGlobal.formatDate(this.date, format, this.language);
320
- },
321
-
322
- setStartDate: function(startDate){
323
- this.startDate = startDate||-Infinity;
324
- if (this.startDate !== -Infinity) {
325
- this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
326
- }
327
- this.update();
328
- this.updateNavArrows();
329
- },
330
-
331
- setEndDate: function(endDate){
332
- this.endDate = endDate||Infinity;
333
- if (this.endDate !== Infinity) {
334
- this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
335
- }
336
- this.update();
337
- this.updateNavArrows();
338
- },
339
-
340
- setDaysOfWeekDisabled: function(daysOfWeekDisabled){
341
- this.daysOfWeekDisabled = daysOfWeekDisabled||[];
342
- if (!$.isArray(this.daysOfWeekDisabled)) {
343
- this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
344
- }
345
- this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
346
- return parseInt(d, 10);
347
- });
348
- this.update();
349
- this.updateNavArrows();
350
- },
351
-
352
- place: function(){
353
- if(this.isInline) return;
354
- var zIndex = parseInt(this.element.parents().filter(function() {
355
- return $(this).css('z-index') != 'auto';
356
- }).first().css('z-index'))+10;
357
- var offset = this.component ? this.component.parent().offset() : this.element.offset();
358
- var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(true);
359
- this.picker.css({
360
- top: offset.top + height,
361
- left: offset.left,
362
- zIndex: zIndex
363
- });
364
- },
365
-
366
- _allow_update: true,
367
- update: function(){
368
- if (!this._allow_update) return;
369
-
370
- var date, fromArgs = false;
371
- if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
372
- date = arguments[0];
373
- fromArgs = true;
374
- } else {
375
- date = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
376
- delete this.element.data().date;
377
- }
378
-
379
- this.date = DPGlobal.parseDate(date, this.format, this.language);
380
-
381
- if(fromArgs) this.setValue();
382
-
383
- if (this.date < this.startDate) {
384
- this.viewDate = new Date(this.startDate);
385
- } else if (this.date > this.endDate) {
386
- this.viewDate = new Date(this.endDate);
387
- } else {
388
- this.viewDate = new Date(this.date);
389
- }
390
- this.fill();
391
- },
392
-
393
- fillDow: function(){
394
- var dowCnt = this.weekStart,
395
- html = '<tr>';
396
- if(this.calendarWeeks){
397
- var cell = '<th class="cw">&nbsp;</th>';
398
- html += cell;
399
- this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
400
- }
401
- while (dowCnt < this.weekStart + 7) {
402
- html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
403
- }
404
- html += '</tr>';
405
- this.picker.find('.datepicker-days thead').append(html);
406
- },
407
-
408
- fillMonths: function(){
409
- var html = '',
410
- i = 0;
411
- while (i < 12) {
412
- html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
413
- }
414
- this.picker.find('.datepicker-months td').html(html);
415
- },
416
-
417
- setRange: function(range){
418
- if (!range || !range.length)
419
- delete this.range;
420
- else
421
- this.range = $.map(range, function(d){ return d.valueOf(); });
422
- this.fill();
423
- },
424
-
425
- getClassNames: function(date){
426
- var cls = [],
427
- year = this.viewDate.getUTCFullYear(),
428
- month = this.viewDate.getUTCMonth(),
429
- currentDate = this.date.valueOf(),
430
- today = new Date();
431
- if (date.getUTCFullYear() < year || (date.getUTCFullYear() == year && date.getUTCMonth() < month)) {
432
- cls.push('old');
433
- } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() == year && date.getUTCMonth() > month)) {
434
- cls.push('new');
435
- }
436
- // Compare internal UTC date with local today, not UTC today
437
- if (this.todayHighlight &&
438
- date.getUTCFullYear() == today.getFullYear() &&
439
- date.getUTCMonth() == today.getMonth() &&
440
- date.getUTCDate() == today.getDate()) {
441
- cls.push('today');
442
- }
443
- if (currentDate && date.valueOf() == currentDate) {
444
- cls.push('active');
445
- }
446
- if (date.valueOf() < this.startDate || date.valueOf() > this.endDate ||
447
- $.inArray(date.getUTCDay(), this.daysOfWeekDisabled) !== -1) {
448
- cls.push('disabled');
449
- }
450
- if (this.range){
451
- if (date > this.range[0] && date < this.range[this.range.length-1]){
452
- cls.push('range');
453
- }
454
- if ($.inArray(date.valueOf(), this.range) != -1){
455
- cls.push('selected');
456
- }
457
- }
458
- return cls;
459
- },
460
-
461
- fill: function() {
462
- var d = new Date(this.viewDate),
463
- year = d.getUTCFullYear(),
464
- month = d.getUTCMonth(),
465
- startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
466
- startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
467
- endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
468
- endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
469
- currentDate = this.date && this.date.valueOf();
470
- this.picker.find('.datepicker-days thead th.datepicker-switch')
471
- .text(dates[this.language].months[month]+' '+year);
472
- this.picker.find('tfoot th.today')
473
- .text(dates[this.language].today)
474
- .toggle(this.todayBtn !== false);
475
- this.updateNavArrows();
476
- this.fillMonths();
477
- var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
478
- day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
479
- prevMonth.setUTCDate(day);
480
- prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
481
- var nextMonth = new Date(prevMonth);
482
- nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
483
- nextMonth = nextMonth.valueOf();
484
- var html = [];
485
- var clsName;
486
- while(prevMonth.valueOf() < nextMonth) {
487
- if (prevMonth.getUTCDay() == this.weekStart) {
488
- html.push('<tr>');
489
- if(this.calendarWeeks){
490
- // ISO 8601: First week contains first thursday.
491
- // ISO also states week starts on Monday, but we can be more abstract here.
492
- var
493
- // Start of current week: based on weekstart/current date
494
- ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
495
- // Thursday of this week
496
- th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
497
- // First Thursday of year, year from thursday
498
- yth = new Date(+(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
499
- // Calendar week: ms between thursdays, div ms per day, div 7 days
500
- calWeek = (th - yth) / 864e5 / 7 + 1;
501
- html.push('<td class="cw">'+ calWeek +'</td>');
502
-
503
- }
504
- }
505
- clsName = this.getClassNames(prevMonth);
506
- clsName.push('day');
507
- html.push('<td class="'+clsName.join(' ')+'">'+prevMonth.getUTCDate() + '</td>');
508
- if (prevMonth.getUTCDay() == this.weekEnd) {
509
- html.push('</tr>');
510
- }
511
- prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
512
- }
513
- this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
514
- var currentYear = this.date && this.date.getUTCFullYear();
515
-
516
- var months = this.picker.find('.datepicker-months')
517
- .find('th:eq(1)')
518
- .text(year)
519
- .end()
520
- .find('span').removeClass('active');
521
- if (currentYear && currentYear == year) {
522
- months.eq(this.date.getUTCMonth()).addClass('active');
523
- }
524
- if (year < startYear || year > endYear) {
525
- months.addClass('disabled');
526
- }
527
- if (year == startYear) {
528
- months.slice(0, startMonth).addClass('disabled');
529
- }
530
- if (year == endYear) {
531
- months.slice(endMonth+1).addClass('disabled');
532
- }
533
-
534
- html = '';
535
- year = parseInt(year/10, 10) * 10;
536
- var yearCont = this.picker.find('.datepicker-years')
537
- .find('th:eq(1)')
538
- .text(year + '-' + (year + 9))
539
- .end()
540
- .find('td');
541
- year -= 1;
542
- for (var i = -1; i < 11; i++) {
543
- html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
544
- year += 1;
545
- }
546
- yearCont.html(html);
547
- },
548
-
549
- updateNavArrows: function() {
550
- if (!this._allow_update) return;
551
-
552
- var d = new Date(this.viewDate),
553
- year = d.getUTCFullYear(),
554
- month = d.getUTCMonth();
555
- switch (this.viewMode) {
556
- case 0:
557
- if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
558
- this.picker.find('.prev').css({visibility: 'hidden'});
559
- } else {
560
- this.picker.find('.prev').css({visibility: 'visible'});
561
- }
562
- if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
563
- this.picker.find('.next').css({visibility: 'hidden'});
564
- } else {
565
- this.picker.find('.next').css({visibility: 'visible'});
566
- }
567
- break;
568
- case 1:
569
- case 2:
570
- if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
571
- this.picker.find('.prev').css({visibility: 'hidden'});
572
- } else {
573
- this.picker.find('.prev').css({visibility: 'visible'});
574
- }
575
- if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
576
- this.picker.find('.next').css({visibility: 'hidden'});
577
- } else {
578
- this.picker.find('.next').css({visibility: 'visible'});
579
- }
580
- break;
581
- }
582
- },
583
-
584
- click: function(e) {
585
- e.preventDefault();
586
- var target = $(e.target).closest('span, td, th');
587
- if (target.length == 1) {
588
- switch(target[0].nodeName.toLowerCase()) {
589
- case 'th':
590
- switch(target[0].className) {
591
- case 'datepicker-switch':
592
- this.showMode(1);
593
- break;
594
- case 'prev':
595
- case 'next':
596
- var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
597
- switch(this.viewMode){
598
- case 0:
599
- this.viewDate = this.moveMonth(this.viewDate, dir);
600
- break;
601
- case 1:
602
- case 2:
603
- this.viewDate = this.moveYear(this.viewDate, dir);
604
- break;
605
- }
606
- this.fill();
607
- break;
608
- case 'today':
609
- var date = new Date();
610
- date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
611
-
612
- this.showMode(-2);
613
- var which = this.todayBtn == 'linked' ? null : 'view';
614
- this._setDate(date, which);
615
- break;
616
- }
617
- break;
618
- case 'span':
619
- if (!target.is('.disabled')) {
620
- this.viewDate.setUTCDate(1);
621
- if (target.is('.month')) {
622
- var day = 1;
623
- var month = target.parent().find('span').index(target);
624
- var year = this.viewDate.getUTCFullYear();
625
- this.viewDate.setUTCMonth(month);
626
- this.element.trigger({
627
- type: 'changeMonth',
628
- date: this.viewDate
629
- });
630
- if ( this.minViewMode == 1 ) {
631
- this._setDate(UTCDate(year, month, day,0,0,0,0));
632
- }
633
- } else {
634
- var year = parseInt(target.text(), 10)||0;
635
- var day = 1;
636
- var month = 0;
637
- this.viewDate.setUTCFullYear(year);
638
- this.element.trigger({
639
- type: 'changeYear',
640
- date: this.viewDate
641
- });
642
- if ( this.minViewMode == 2 ) {
643
- this._setDate(UTCDate(year, month, day,0,0,0,0));
644
- }
645
- }
646
- this.showMode(-1);
647
- this.fill();
648
- }
649
- break;
650
- case 'td':
651
- if (target.is('.day') && !target.is('.disabled')){
652
- var day = parseInt(target.text(), 10)||1;
653
- var year = this.viewDate.getUTCFullYear(),
654
- month = this.viewDate.getUTCMonth();
655
- if (target.is('.old')) {
656
- if (month === 0) {
657
- month = 11;
658
- year -= 1;
659
- } else {
660
- month -= 1;
661
- }
662
- } else if (target.is('.new')) {
663
- if (month == 11) {
664
- month = 0;
665
- year += 1;
666
- } else {
667
- month += 1;
668
- }
669
- }
670
- this._setDate(UTCDate(year, month, day,0,0,0,0));
671
- }
672
- break;
673
- }
674
- }
675
- },
676
-
677
- _setDate: function(date, which){
678
- if (!which || which == 'date')
679
- this.date = date;
680
- if (!which || which == 'view')
681
- this.viewDate = date;
682
- this.fill();
683
- this.setValue();
684
- this.element.trigger({
685
- type: 'changeDate',
686
- date: this.date
687
- });
688
- var element;
689
- if (this.isInput) {
690
- element = this.element;
691
- } else if (this.component){
692
- element = this.element.find('input');
693
- }
694
- if (element) {
695
- element.change();
696
- if (this.autoclose && (!which || which == 'date')) {
697
- this.hide();
698
- }
699
- }
700
- },
701
-
702
- moveMonth: function(date, dir){
703
- if (!dir) return date;
704
- var new_date = new Date(date.valueOf()),
705
- day = new_date.getUTCDate(),
706
- month = new_date.getUTCMonth(),
707
- mag = Math.abs(dir),
708
- new_month, test;
709
- dir = dir > 0 ? 1 : -1;
710
- if (mag == 1){
711
- test = dir == -1
712
- // If going back one month, make sure month is not current month
713
- // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
714
- ? function(){ return new_date.getUTCMonth() == month; }
715
- // If going forward one month, make sure month is as expected
716
- // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
717
- : function(){ return new_date.getUTCMonth() != new_month; };
718
- new_month = month + dir;
719
- new_date.setUTCMonth(new_month);
720
- // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
721
- if (new_month < 0 || new_month > 11)
722
- new_month = (new_month + 12) % 12;
723
- } else {
724
- // For magnitudes >1, move one month at a time...
725
- for (var i=0; i<mag; i++)
726
- // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
727
- new_date = this.moveMonth(new_date, dir);
728
- // ...then reset the day, keeping it in the new month
729
- new_month = new_date.getUTCMonth();
730
- new_date.setUTCDate(day);
731
- test = function(){ return new_month != new_date.getUTCMonth(); };
732
- }
733
- // Common date-resetting loop -- if date is beyond end of month, make it
734
- // end of month
735
- while (test()){
736
- new_date.setUTCDate(--day);
737
- new_date.setUTCMonth(new_month);
738
- }
739
- return new_date;
740
- },
741
-
742
- moveYear: function(date, dir){
743
- return this.moveMonth(date, dir*12);
744
- },
745
-
746
- dateWithinRange: function(date){
747
- return date >= this.startDate && date <= this.endDate;
748
- },
749
-
750
- keydown: function(e){
751
- if (this.picker.is(':not(:visible)')){
752
- if (e.keyCode == 27) // allow escape to hide and re-show picker
753
- this.show();
754
- return;
755
- }
756
- var dateChanged = false,
757
- dir, day, month,
758
- newDate, newViewDate;
759
- switch(e.keyCode){
760
- case 27: // escape
761
- this.hide();
762
- e.preventDefault();
763
- break;
764
- case 37: // left
765
- case 39: // right
766
- if (!this.keyboardNavigation) break;
767
- dir = e.keyCode == 37 ? -1 : 1;
768
- if (e.ctrlKey){
769
- newDate = this.moveYear(this.date, dir);
770
- newViewDate = this.moveYear(this.viewDate, dir);
771
- } else if (e.shiftKey){
772
- newDate = this.moveMonth(this.date, dir);
773
- newViewDate = this.moveMonth(this.viewDate, dir);
774
- } else {
775
- newDate = new Date(this.date);
776
- newDate.setUTCDate(this.date.getUTCDate() + dir);
777
- newViewDate = new Date(this.viewDate);
778
- newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
779
- }
780
- if (this.dateWithinRange(newDate)){
781
- this.date = newDate;
782
- this.viewDate = newViewDate;
783
- this.setValue();
784
- this.update();
785
- e.preventDefault();
786
- dateChanged = true;
787
- }
788
- break;
789
- case 38: // up
790
- case 40: // down
791
- if (!this.keyboardNavigation) break;
792
- dir = e.keyCode == 38 ? -1 : 1;
793
- if (e.ctrlKey){
794
- newDate = this.moveYear(this.date, dir);
795
- newViewDate = this.moveYear(this.viewDate, dir);
796
- } else if (e.shiftKey){
797
- newDate = this.moveMonth(this.date, dir);
798
- newViewDate = this.moveMonth(this.viewDate, dir);
799
- } else {
800
- newDate = new Date(this.date);
801
- newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
802
- newViewDate = new Date(this.viewDate);
803
- newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
804
- }
805
- if (this.dateWithinRange(newDate)){
806
- this.date = newDate;
807
- this.viewDate = newViewDate;
808
- this.setValue();
809
- this.update();
810
- e.preventDefault();
811
- dateChanged = true;
812
- }
813
- break;
814
- case 13: // enter
815
- this.hide();
816
- e.preventDefault();
817
- break;
818
- case 9: // tab
819
- this.hide();
820
- break;
821
- }
822
- if (dateChanged){
823
- this.element.trigger({
824
- type: 'changeDate',
825
- date: this.date
826
- });
827
- var element;
828
- if (this.isInput) {
829
- element = this.element;
830
- } else if (this.component){
831
- element = this.element.find('input');
832
- }
833
- if (element) {
834
- element.change();
835
- }
836
- }
837
- },
838
-
839
- showMode: function(dir) {
840
- if (dir) {
841
- this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
842
- }
843
- /*
844
- vitalets: fixing bug of very special conditions:
845
- jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
846
- Method show() does not set display css correctly and datepicker is not shown.
847
- Changed to .css('display', 'block') solve the problem.
848
- See https://github.com/vitalets/x-editable/issues/37
849
-
850
- In jquery 1.7.2+ everything works fine.
851
- */
852
- //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
853
- this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
854
- this.updateNavArrows();
855
- }
856
- };
857
-
858
- var DateRangePicker = function(element, options){
859
- this.element = $(element);
860
- this.inputs = $.map(options.inputs, function(i){ return i.jquery ? i[0] : i; });
861
- delete options.inputs;
862
-
863
- $(this.inputs)
864
- .datepicker(options)
865
- .bind('changeDate', $.proxy(this.dateUpdated, this));
866
-
867
- this.pickers = $.map(this.inputs, function(i){ return $(i).data('datepicker'); });
868
- this.updateDates();
869
- };
870
- DateRangePicker.prototype = {
871
- updateDates: function(){
872
- this.dates = $.map(this.pickers, function(i){ return i.date; });
873
- this.updateRanges();
874
- },
875
- updateRanges: function(){
876
- var range = $.map(this.dates, function(d){ return d.valueOf(); });
877
- $.each(this.pickers, function(i, p){
878
- p.setRange(range);
879
- });
880
- },
881
- dateUpdated: function(e){
882
- var dp = $(e.target).data('datepicker'),
883
- new_date = e.date,
884
- i = $.inArray(e.target, this.inputs),
885
- l = this.inputs.length;
886
- if (i == -1) return;
887
-
888
- if (new_date < this.dates[i]){
889
- // Date being moved earlier/left
890
- while (i>=0 && new_date < this.dates[i]){
891
- this.pickers[i--].setUTCDate(new_date);
892
- }
893
- }
894
- else if (new_date > this.dates[i]){
895
- // Date being moved later/right
896
- while (i<l && new_date > this.dates[i]){
897
- this.pickers[i++].setUTCDate(new_date);
898
- }
899
- }
900
- this.updateDates();
901
- },
902
- remove: function(){
903
- $.map(this.pickers, function(p){ p.remove(); });
904
- delete this.element.data().datepicker;
905
- }
906
- };
907
-
908
- var old = $.fn.datepicker;
909
- $.fn.datepicker = function ( option ) {
910
- var args = Array.apply(null, arguments);
911
- args.shift();
912
- return this.each(function () {
913
- var $this = $(this),
914
- data = $this.data('datepicker'),
915
- options = typeof option == 'object' && option;
916
- if (!data) {
917
- if ($this.is('.input-daterange') || options.inputs){
918
- var opts = {
919
- inputs: options.inputs || $this.find('input').toArray()
920
- };
921
- $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, $.fn.datepicker.defaults,options))));
922
- }
923
- else{
924
- $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
925
- }
926
- }
927
- if (typeof option == 'string' && typeof data[option] == 'function') {
928
- data[option].apply(data, args);
929
- }
930
- });
931
- };
932
-
933
- $.fn.datepicker.defaults = {
934
- };
935
- $.fn.datepicker.Constructor = Datepicker;
936
- var dates = $.fn.datepicker.dates = {
937
- en: {
938
- days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
939
- daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
940
- daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
941
- months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
942
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
943
- today: "Today"
944
- }
945
- };
946
-
947
- var DPGlobal = {
948
- modes: [
949
- {
950
- clsName: 'days',
951
- navFnc: 'Month',
952
- navStep: 1
953
- },
954
- {
955
- clsName: 'months',
956
- navFnc: 'FullYear',
957
- navStep: 1
958
- },
959
- {
960
- clsName: 'years',
961
- navFnc: 'FullYear',
962
- navStep: 10
963
- }],
964
- isLeapYear: function (year) {
965
- return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
966
- },
967
- getDaysInMonth: function (year, month) {
968
- return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
969
- },
970
- validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
971
- nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
972
- parseFormat: function(format){
973
- // IE treats \0 as a string end in inputs (truncating the value),
974
- // so it's a bad format delimiter, anyway
975
- var separators = format.replace(this.validParts, '\0').split('\0'),
976
- parts = format.match(this.validParts);
977
- if (!separators || !separators.length || !parts || parts.length === 0){
978
- throw new Error("Invalid date format.");
979
- }
980
- return {separators: separators, parts: parts};
981
- },
982
- parseDate: function(date, format, language) {
983
- if (date instanceof Date) return date;
984
- if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) {
985
- var part_re = /([\-+]\d+)([dmwy])/,
986
- parts = date.match(/([\-+]\d+)([dmwy])/g),
987
- part, dir;
988
- date = new Date();
989
- for (var i=0; i<parts.length; i++) {
990
- part = part_re.exec(parts[i]);
991
- dir = parseInt(part[1]);
992
- switch(part[2]){
993
- case 'd':
994
- date.setUTCDate(date.getUTCDate() + dir);
995
- break;
996
- case 'm':
997
- date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
998
- break;
999
- case 'w':
1000
- date.setUTCDate(date.getUTCDate() + dir * 7);
1001
- break;
1002
- case 'y':
1003
- date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
1004
- break;
1005
- }
1006
- }
1007
- return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
1008
- }
1009
- var parts = date && date.match(this.nonpunctuation) || [],
1010
- date = new Date(),
1011
- parsed = {},
1012
- setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1013
- setters_map = {
1014
- yyyy: function(d,v){ return d.setUTCFullYear(v); },
1015
- yy: function(d,v){ return d.setUTCFullYear(2000+v); },
1016
- m: function(d,v){
1017
- v -= 1;
1018
- while (v<0) v += 12;
1019
- v %= 12;
1020
- d.setUTCMonth(v);
1021
- while (d.getUTCMonth() != v)
1022
- d.setUTCDate(d.getUTCDate()-1);
1023
- return d;
1024
- },
1025
- d: function(d,v){ return d.setUTCDate(v); }
1026
- },
1027
- val, filtered, part;
1028
- setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1029
- setters_map['dd'] = setters_map['d'];
1030
- date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
1031
- var fparts = format.parts.slice();
1032
- // Remove noop parts
1033
- if (parts.length != fparts.length) {
1034
- fparts = $(fparts).filter(function(i,p){
1035
- return $.inArray(p, setters_order) !== -1;
1036
- }).toArray();
1037
- }
1038
- // Process remainder
1039
- if (parts.length == fparts.length) {
1040
- for (var i=0, cnt = fparts.length; i < cnt; i++) {
1041
- val = parseInt(parts[i], 10);
1042
- part = fparts[i];
1043
- if (isNaN(val)) {
1044
- switch(part) {
1045
- case 'MM':
1046
- filtered = $(dates[language].months).filter(function(){
1047
- var m = this.slice(0, parts[i].length),
1048
- p = parts[i].slice(0, m.length);
1049
- return m == p;
1050
- });
1051
- val = $.inArray(filtered[0], dates[language].months) + 1;
1052
- break;
1053
- case 'M':
1054
- filtered = $(dates[language].monthsShort).filter(function(){
1055
- var m = this.slice(0, parts[i].length),
1056
- p = parts[i].slice(0, m.length);
1057
- return m == p;
1058
- });
1059
- val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1060
- break;
1061
- }
1062
- }
1063
- parsed[part] = val;
1064
- }
1065
- for (var i=0, s; i<setters_order.length; i++){
1066
- s = setters_order[i];
1067
- if (s in parsed && !isNaN(parsed[s]))
1068
- setters_map[s](date, parsed[s]);
1069
- }
1070
- }
1071
- return date;
1072
- },
1073
- formatDate: function(date, format, language){
1074
- var val = {
1075
- d: date.getUTCDate(),
1076
- D: dates[language].daysShort[date.getUTCDay()],
1077
- DD: dates[language].days[date.getUTCDay()],
1078
- m: date.getUTCMonth() + 1,
1079
- M: dates[language].monthsShort[date.getUTCMonth()],
1080
- MM: dates[language].months[date.getUTCMonth()],
1081
- yy: date.getUTCFullYear().toString().substring(2),
1082
- yyyy: date.getUTCFullYear()
1083
- };
1084
- val.dd = (val.d < 10 ? '0' : '') + val.d;
1085
- val.mm = (val.m < 10 ? '0' : '') + val.m;
1086
- var date = [],
1087
- seps = $.extend([], format.separators);
1088
- for (var i=0, cnt = format.parts.length; i < cnt; i++) {
1089
- if (seps.length)
1090
- date.push(seps.shift());
1091
- date.push(val[format.parts[i]]);
1092
- }
1093
- return date.join('');
1094
- },
1095
- headTemplate: '<thead>'+
1096
- '<tr>'+
1097
- '<th class="prev"><i class="icon-arrow-left"/></th>'+
1098
- '<th colspan="5" class="datepicker-switch"></th>'+
1099
- '<th class="next"><i class="icon-arrow-right"/></th>'+
1100
- '</tr>'+
1101
- '</thead>',
1102
- contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1103
- footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
1104
- };
1105
- DPGlobal.template = '<div class="datepicker">'+
1106
- '<div class="datepicker-days">'+
1107
- '<table class=" table-condensed">'+
1108
- DPGlobal.headTemplate+
1109
- '<tbody></tbody>'+
1110
- DPGlobal.footTemplate+
1111
- '</table>'+
1112
- '</div>'+
1113
- '<div class="datepicker-months">'+
1114
- '<table class="table-condensed">'+
1115
- DPGlobal.headTemplate+
1116
- DPGlobal.contTemplate+
1117
- DPGlobal.footTemplate+
1118
- '</table>'+
1119
- '</div>'+
1120
- '<div class="datepicker-years">'+
1121
- '<table class="table-condensed">'+
1122
- DPGlobal.headTemplate+
1123
- DPGlobal.contTemplate+
1124
- DPGlobal.footTemplate+
1125
- '</table>'+
1126
- '</div>'+
1127
- '</div>';
1128
-
1129
- $.fn.datepicker.DPGlobal = DPGlobal;
1130
-
1131
-
1132
- /* DATEPICKER NO CONFLICT
1133
- * =================== */
1134
-
1135
- $.fn.datepicker.noConflict = function(){
1136
- $.fn.datepicker = old;
1137
- return this;
1138
- };
1139
-
1140
-
1141
- /* DATEPICKER DATA-API
1142
- * ================== */
1143
-
1144
- $(document).on(
1145
- 'focus.datepicker.data-api click.datepicker.data-api',
1146
- '[data-provide="datepicker"]',
1147
- function(e){
1148
- var $this = $(this);
1149
- if ($this.data('datepicker')) return;
1150
- e.preventDefault();
1151
- // component click requires us to explicitly show it
1152
- $this.datepicker('show');
1153
- }
1154
- );
1155
- $(function(){
1156
- $('[data-provide="datepicker-inline"]').datepicker();
1157
- });
1158
-
1159
- }( window.jQuery );
1
+ /* =========================================================
2
+ * bootstrap-datepicker.js
3
+ * http://www.eyecon.ro/bootstrap-datepicker
4
+ * =========================================================
5
+ * Copyright 2012 Stefan Petre
6
+ * Improvements by Andrew Rowls
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ * ========================================================= */
20
+
21
+ !function( $ ) {
22
+
23
+ function UTCDate(){
24
+ return new Date(Date.UTC.apply(Date, arguments));
25
+ }
26
+ function UTCToday(){
27
+ var today = new Date();
28
+ return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
29
+ }
30
+
31
+ // Picker object
32
+
33
+ var Datepicker = function(element, options) {
34
+ var that = this;
35
+
36
+ this.element = $(element);
37
+ this.language = options.language||this.element.data('date-language')||"en";
38
+ 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"
39
+ this.language = this.language in dates ? this.language : "en";
40
+ this.isRTL = dates[this.language].rtl||false;
41
+ this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||dates[this.language].format||'mm/dd/yyyy');
42
+ this.isInline = false;
43
+ this.isInput = this.element.is('input');
44
+ this.component = this.element.is('.date') ? this.element.find('.add-on, .btn') : false;
45
+ this.hasInput = this.component && this.element.find('input').length;
46
+ if(this.component && this.component.length === 0)
47
+ this.component = false;
48
+
49
+ this.forceParse = true;
50
+ if ('forceParse' in options) {
51
+ this.forceParse = options.forceParse;
52
+ } else if ('dateForceParse' in this.element.data()) {
53
+ this.forceParse = this.element.data('date-force-parse');
54
+ }
55
+
56
+ this.picker = $(DPGlobal.template);
57
+ this._buildEvents();
58
+ this._attachEvents();
59
+
60
+ if(this.isInline) {
61
+ this.picker.addClass('datepicker-inline').appendTo(this.element);
62
+ } else {
63
+ this.picker.addClass('datepicker-dropdown dropdown-menu');
64
+ }
65
+ if (this.isRTL){
66
+ this.picker.addClass('datepicker-rtl');
67
+ this.picker.find('.prev i, .next i')
68
+ .toggleClass('icon-arrow-left icon-arrow-right');
69
+ }
70
+
71
+ this.autoclose = false;
72
+ if ('autoclose' in options) {
73
+ this.autoclose = options.autoclose;
74
+ } else if ('dateAutoclose' in this.element.data()) {
75
+ this.autoclose = this.element.data('date-autoclose');
76
+ }
77
+
78
+ this.keyboardNavigation = true;
79
+ if ('keyboardNavigation' in options) {
80
+ this.keyboardNavigation = options.keyboardNavigation;
81
+ } else if ('dateKeyboardNavigation' in this.element.data()) {
82
+ this.keyboardNavigation = this.element.data('date-keyboard-navigation');
83
+ }
84
+
85
+ this.viewMode = this.startViewMode = 0;
86
+ switch(options.startView || this.element.data('date-start-view')){
87
+ case 2:
88
+ case 'decade':
89
+ this.viewMode = this.startViewMode = 2;
90
+ break;
91
+ case 1:
92
+ case 'year':
93
+ this.viewMode = this.startViewMode = 1;
94
+ break;
95
+ }
96
+
97
+ this.minViewMode = options.minViewMode||this.element.data('date-min-view-mode')||0;
98
+ if (typeof this.minViewMode === 'string') {
99
+ switch (this.minViewMode) {
100
+ case 'months':
101
+ this.minViewMode = 1;
102
+ break;
103
+ case 'years':
104
+ this.minViewMode = 2;
105
+ break;
106
+ default:
107
+ this.minViewMode = 0;
108
+ break;
109
+ }
110
+ }
111
+
112
+ this.viewMode = this.startViewMode = Math.max(this.startViewMode, this.minViewMode);
113
+
114
+ this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false);
115
+ this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false);
116
+
117
+ this.calendarWeeks = false;
118
+ if ('calendarWeeks' in options) {
119
+ this.calendarWeeks = options.calendarWeeks;
120
+ } else if ('dateCalendarWeeks' in this.element.data()) {
121
+ this.calendarWeeks = this.element.data('date-calendar-weeks');
122
+ }
123
+ if (this.calendarWeeks)
124
+ this.picker.find('tfoot th.today')
125
+ .attr('colspan', function(i, val){
126
+ return parseInt(val) + 1;
127
+ });
128
+
129
+ this._allow_update = false;
130
+
131
+ this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
132
+ this.weekEnd = ((this.weekStart + 6) % 7);
133
+ this.startDate = -Infinity;
134
+ this.endDate = Infinity;
135
+ this.daysOfWeekDisabled = [];
136
+ this.setStartDate(options.startDate||this.element.data('date-startdate'));
137
+ this.setEndDate(options.endDate||this.element.data('date-enddate'));
138
+ this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled'));
139
+ this.fillDow();
140
+ this.fillMonths();
141
+ this.setRange(options.range);
142
+
143
+ this._allow_update = true;
144
+
145
+ this.update();
146
+ this.showMode();
147
+
148
+ if(this.isInline) {
149
+ this.show();
150
+ }
151
+ };
152
+
153
+ Datepicker.prototype = {
154
+ constructor: Datepicker,
155
+
156
+ _events: [],
157
+ _secondaryEvents: [],
158
+ _applyEvents: function(evs){
159
+ for (var i=0, el, ev; i<evs.length; i++){
160
+ el = evs[i][0];
161
+ ev = evs[i][1];
162
+ el.on(ev);
163
+ }
164
+ },
165
+ _unapplyEvents: function(evs){
166
+ for (var i=0, el, ev; i<evs.length; i++){
167
+ el = evs[i][0];
168
+ ev = evs[i][1];
169
+ el.off(ev);
170
+ }
171
+ },
172
+ _buildEvents: function(){
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
+ }
195
+ else if (this.element.is('div')) { // inline datepicker
196
+ this.isInline = true;
197
+ }
198
+ else {
199
+ this._events = [
200
+ [this.element, {
201
+ click: $.proxy(this.show, this)
202
+ }]
203
+ ];
204
+ }
205
+
206
+ this._secondaryEvents = [
207
+ [this.picker, {
208
+ click: $.proxy(this.click, this)
209
+ }],
210
+ [$(window), {
211
+ resize: $.proxy(this.place, this)
212
+ }],
213
+ [$(document), {
214
+ mousedown: $.proxy(function (e) {
215
+ // Clicked outside the datepicker, hide it
216
+ if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
217
+ this.hide();
218
+ }
219
+ }, this)
220
+ }]
221
+ ];
222
+ },
223
+ _attachEvents: function(){
224
+ this._detachEvents();
225
+ this._applyEvents(this._events);
226
+ },
227
+ _detachEvents: function(){
228
+ this._unapplyEvents(this._events);
229
+ },
230
+ _attachSecondaryEvents: function(){
231
+ this._detachSecondaryEvents();
232
+ this._applyEvents(this._secondaryEvents);
233
+ },
234
+ _detachSecondaryEvents: function(){
235
+ this._unapplyEvents(this._secondaryEvents);
236
+ },
237
+
238
+ show: function(e) {
239
+ if (!this.isInline)
240
+ this.picker.appendTo('body');
241
+ this.picker.show();
242
+ this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
243
+ this.place();
244
+ this._attachSecondaryEvents();
245
+ if (e) {
246
+ e.preventDefault();
247
+ }
248
+ this.element.trigger({
249
+ type: 'show',
250
+ date: this.date
251
+ });
252
+ },
253
+
254
+ hide: function(e){
255
+ if(this.isInline) return;
256
+ if (!this.picker.is(':visible')) return;
257
+ this.picker.hide().detach();
258
+ this._detachSecondaryEvents();
259
+ this.viewMode = this.startViewMode;
260
+ this.showMode();
261
+
262
+ if (
263
+ this.forceParse &&
264
+ (
265
+ this.isInput && this.element.val() ||
266
+ this.hasInput && this.element.find('input').val()
267
+ )
268
+ )
269
+ this.setValue();
270
+ this.element.trigger({
271
+ type: 'hide',
272
+ date: this.date
273
+ });
274
+ },
275
+
276
+ remove: function() {
277
+ this.hide();
278
+ this._detachEvents();
279
+ this._detachSecondaryEvents();
280
+ this.picker.remove();
281
+ delete this.element.data().datepicker;
282
+ if (!this.isInput) {
283
+ delete this.element.data().date;
284
+ }
285
+ },
286
+
287
+ getDate: function() {
288
+ var d = this.getUTCDate();
289
+ return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
290
+ },
291
+
292
+ getUTCDate: function() {
293
+ return this.date;
294
+ },
295
+
296
+ setDate: function(d) {
297
+ this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
298
+ },
299
+
300
+ setUTCDate: function(d) {
301
+ this.date = d;
302
+ this.setValue();
303
+ },
304
+
305
+ setValue: function() {
306
+ var formatted = this.getFormattedDate();
307
+ if (!this.isInput) {
308
+ if (this.component){
309
+ this.element.find('input').val(formatted);
310
+ }
311
+ } else {
312
+ this.element.val(formatted);
313
+ }
314
+ },
315
+
316
+ getFormattedDate: function(format) {
317
+ if (format === undefined)
318
+ format = this.format;
319
+ return DPGlobal.formatDate(this.date, format, this.language);
320
+ },
321
+
322
+ setStartDate: function(startDate){
323
+ this.startDate = startDate||-Infinity;
324
+ if (this.startDate !== -Infinity) {
325
+ this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
326
+ }
327
+ this.update();
328
+ this.updateNavArrows();
329
+ },
330
+
331
+ setEndDate: function(endDate){
332
+ this.endDate = endDate||Infinity;
333
+ if (this.endDate !== Infinity) {
334
+ this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
335
+ }
336
+ this.update();
337
+ this.updateNavArrows();
338
+ },
339
+
340
+ setDaysOfWeekDisabled: function(daysOfWeekDisabled){
341
+ this.daysOfWeekDisabled = daysOfWeekDisabled||[];
342
+ if (!$.isArray(this.daysOfWeekDisabled)) {
343
+ this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
344
+ }
345
+ this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
346
+ return parseInt(d, 10);
347
+ });
348
+ this.update();
349
+ this.updateNavArrows();
350
+ },
351
+
352
+ place: function(){
353
+ if(this.isInline) return;
354
+ var zIndex = parseInt(this.element.parents().filter(function() {
355
+ return $(this).css('z-index') != 'auto';
356
+ }).first().css('z-index'))+10;
357
+ var offset = this.component ? this.component.parent().offset() : this.element.offset();
358
+ var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(true);
359
+ this.picker.css({
360
+ top: offset.top + height,
361
+ left: offset.left,
362
+ zIndex: zIndex
363
+ });
364
+ },
365
+
366
+ _allow_update: true,
367
+ update: function(){
368
+ if (!this._allow_update) return;
369
+
370
+ var date, fromArgs = false;
371
+ if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
372
+ date = arguments[0];
373
+ fromArgs = true;
374
+ } else {
375
+ date = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
376
+ delete this.element.data().date;
377
+ }
378
+
379
+ this.date = DPGlobal.parseDate(date, this.format, this.language);
380
+
381
+ if(fromArgs) this.setValue();
382
+
383
+ if (this.date < this.startDate) {
384
+ this.viewDate = new Date(this.startDate);
385
+ } else if (this.date > this.endDate) {
386
+ this.viewDate = new Date(this.endDate);
387
+ } else {
388
+ this.viewDate = new Date(this.date);
389
+ }
390
+ this.fill();
391
+ },
392
+
393
+ fillDow: function(){
394
+ var dowCnt = this.weekStart,
395
+ html = '<tr>';
396
+ if(this.calendarWeeks){
397
+ var cell = '<th class="cw">&nbsp;</th>';
398
+ html += cell;
399
+ this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
400
+ }
401
+ while (dowCnt < this.weekStart + 7) {
402
+ html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
403
+ }
404
+ html += '</tr>';
405
+ this.picker.find('.datepicker-days thead').append(html);
406
+ },
407
+
408
+ fillMonths: function(){
409
+ var html = '',
410
+ i = 0;
411
+ while (i < 12) {
412
+ html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
413
+ }
414
+ this.picker.find('.datepicker-months td').html(html);
415
+ },
416
+
417
+ setRange: function(range){
418
+ if (!range || !range.length)
419
+ delete this.range;
420
+ else
421
+ this.range = $.map(range, function(d){ return d.valueOf(); });
422
+ this.fill();
423
+ },
424
+
425
+ getClassNames: function(date){
426
+ var cls = [],
427
+ year = this.viewDate.getUTCFullYear(),
428
+ month = this.viewDate.getUTCMonth(),
429
+ currentDate = this.date.valueOf(),
430
+ today = new Date();
431
+ if (date.getUTCFullYear() < year || (date.getUTCFullYear() == year && date.getUTCMonth() < month)) {
432
+ cls.push('old');
433
+ } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() == year && date.getUTCMonth() > month)) {
434
+ cls.push('new');
435
+ }
436
+ // Compare internal UTC date with local today, not UTC today
437
+ if (this.todayHighlight &&
438
+ date.getUTCFullYear() == today.getFullYear() &&
439
+ date.getUTCMonth() == today.getMonth() &&
440
+ date.getUTCDate() == today.getDate()) {
441
+ cls.push('today');
442
+ }
443
+ if (currentDate && date.valueOf() == currentDate) {
444
+ cls.push('active');
445
+ }
446
+ if (date.valueOf() < this.startDate || date.valueOf() > this.endDate ||
447
+ $.inArray(date.getUTCDay(), this.daysOfWeekDisabled) !== -1) {
448
+ cls.push('disabled');
449
+ }
450
+ if (this.range){
451
+ if (date > this.range[0] && date < this.range[this.range.length-1]){
452
+ cls.push('range');
453
+ }
454
+ if ($.inArray(date.valueOf(), this.range) != -1){
455
+ cls.push('selected');
456
+ }
457
+ }
458
+ return cls;
459
+ },
460
+
461
+ fill: function() {
462
+ var d = new Date(this.viewDate),
463
+ year = d.getUTCFullYear(),
464
+ month = d.getUTCMonth(),
465
+ startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
466
+ startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
467
+ endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
468
+ endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
469
+ currentDate = this.date && this.date.valueOf();
470
+ this.picker.find('.datepicker-days thead th.datepicker-switch')
471
+ .text(dates[this.language].months[month]+' '+year);
472
+ this.picker.find('tfoot th.today')
473
+ .text(dates[this.language].today)
474
+ .toggle(this.todayBtn !== false);
475
+ this.updateNavArrows();
476
+ this.fillMonths();
477
+ var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
478
+ day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
479
+ prevMonth.setUTCDate(day);
480
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
481
+ var nextMonth = new Date(prevMonth);
482
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
483
+ nextMonth = nextMonth.valueOf();
484
+ var html = [];
485
+ var clsName;
486
+ while(prevMonth.valueOf() < nextMonth) {
487
+ if (prevMonth.getUTCDay() == this.weekStart) {
488
+ html.push('<tr>');
489
+ if(this.calendarWeeks){
490
+ // ISO 8601: First week contains first thursday.
491
+ // ISO also states week starts on Monday, but we can be more abstract here.
492
+ var
493
+ // Start of current week: based on weekstart/current date
494
+ ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
495
+ // Thursday of this week
496
+ th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
497
+ // First Thursday of year, year from thursday
498
+ yth = new Date(+(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
499
+ // Calendar week: ms between thursdays, div ms per day, div 7 days
500
+ calWeek = (th - yth) / 864e5 / 7 + 1;
501
+ html.push('<td class="cw">'+ calWeek +'</td>');
502
+
503
+ }
504
+ }
505
+ clsName = this.getClassNames(prevMonth);
506
+ clsName.push('day');
507
+ html.push('<td class="'+clsName.join(' ')+'">'+prevMonth.getUTCDate() + '</td>');
508
+ if (prevMonth.getUTCDay() == this.weekEnd) {
509
+ html.push('</tr>');
510
+ }
511
+ prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
512
+ }
513
+ this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
514
+ var currentYear = this.date && this.date.getUTCFullYear();
515
+
516
+ var months = this.picker.find('.datepicker-months')
517
+ .find('th:eq(1)')
518
+ .text(year)
519
+ .end()
520
+ .find('span').removeClass('active');
521
+ if (currentYear && currentYear == year) {
522
+ months.eq(this.date.getUTCMonth()).addClass('active');
523
+ }
524
+ if (year < startYear || year > endYear) {
525
+ months.addClass('disabled');
526
+ }
527
+ if (year == startYear) {
528
+ months.slice(0, startMonth).addClass('disabled');
529
+ }
530
+ if (year == endYear) {
531
+ months.slice(endMonth+1).addClass('disabled');
532
+ }
533
+
534
+ html = '';
535
+ year = parseInt(year/10, 10) * 10;
536
+ var yearCont = this.picker.find('.datepicker-years')
537
+ .find('th:eq(1)')
538
+ .text(year + '-' + (year + 9))
539
+ .end()
540
+ .find('td');
541
+ year -= 1;
542
+ for (var i = -1; i < 11; i++) {
543
+ html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
544
+ year += 1;
545
+ }
546
+ yearCont.html(html);
547
+ },
548
+
549
+ updateNavArrows: function() {
550
+ if (!this._allow_update) return;
551
+
552
+ var d = new Date(this.viewDate),
553
+ year = d.getUTCFullYear(),
554
+ month = d.getUTCMonth();
555
+ switch (this.viewMode) {
556
+ case 0:
557
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
558
+ this.picker.find('.prev').css({visibility: 'hidden'});
559
+ } else {
560
+ this.picker.find('.prev').css({visibility: 'visible'});
561
+ }
562
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
563
+ this.picker.find('.next').css({visibility: 'hidden'});
564
+ } else {
565
+ this.picker.find('.next').css({visibility: 'visible'});
566
+ }
567
+ break;
568
+ case 1:
569
+ case 2:
570
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
571
+ this.picker.find('.prev').css({visibility: 'hidden'});
572
+ } else {
573
+ this.picker.find('.prev').css({visibility: 'visible'});
574
+ }
575
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
576
+ this.picker.find('.next').css({visibility: 'hidden'});
577
+ } else {
578
+ this.picker.find('.next').css({visibility: 'visible'});
579
+ }
580
+ break;
581
+ }
582
+ },
583
+
584
+ click: function(e) {
585
+ e.preventDefault();
586
+ var target = $(e.target).closest('span, td, th');
587
+ if (target.length == 1) {
588
+ switch(target[0].nodeName.toLowerCase()) {
589
+ case 'th':
590
+ switch(target[0].className) {
591
+ case 'datepicker-switch':
592
+ this.showMode(1);
593
+ break;
594
+ case 'prev':
595
+ case 'next':
596
+ var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
597
+ switch(this.viewMode){
598
+ case 0:
599
+ this.viewDate = this.moveMonth(this.viewDate, dir);
600
+ break;
601
+ case 1:
602
+ case 2:
603
+ this.viewDate = this.moveYear(this.viewDate, dir);
604
+ break;
605
+ }
606
+ this.fill();
607
+ break;
608
+ case 'today':
609
+ var date = new Date();
610
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
611
+
612
+ this.showMode(-2);
613
+ var which = this.todayBtn == 'linked' ? null : 'view';
614
+ this._setDate(date, which);
615
+ break;
616
+ }
617
+ break;
618
+ case 'span':
619
+ if (!target.is('.disabled')) {
620
+ this.viewDate.setUTCDate(1);
621
+ if (target.is('.month')) {
622
+ var day = 1;
623
+ var month = target.parent().find('span').index(target);
624
+ var year = this.viewDate.getUTCFullYear();
625
+ this.viewDate.setUTCMonth(month);
626
+ this.element.trigger({
627
+ type: 'changeMonth',
628
+ date: this.viewDate
629
+ });
630
+ if ( this.minViewMode == 1 ) {
631
+ this._setDate(UTCDate(year, month, day,0,0,0,0));
632
+ }
633
+ } else {
634
+ var year = parseInt(target.text(), 10)||0;
635
+ var day = 1;
636
+ var month = 0;
637
+ this.viewDate.setUTCFullYear(year);
638
+ this.element.trigger({
639
+ type: 'changeYear',
640
+ date: this.viewDate
641
+ });
642
+ if ( this.minViewMode == 2 ) {
643
+ this._setDate(UTCDate(year, month, day,0,0,0,0));
644
+ }
645
+ }
646
+ this.showMode(-1);
647
+ this.fill();
648
+ }
649
+ break;
650
+ case 'td':
651
+ if (target.is('.day') && !target.is('.disabled')){
652
+ var day = parseInt(target.text(), 10)||1;
653
+ var year = this.viewDate.getUTCFullYear(),
654
+ month = this.viewDate.getUTCMonth();
655
+ if (target.is('.old')) {
656
+ if (month === 0) {
657
+ month = 11;
658
+ year -= 1;
659
+ } else {
660
+ month -= 1;
661
+ }
662
+ } else if (target.is('.new')) {
663
+ if (month == 11) {
664
+ month = 0;
665
+ year += 1;
666
+ } else {
667
+ month += 1;
668
+ }
669
+ }
670
+ this._setDate(UTCDate(year, month, day,0,0,0,0));
671
+ }
672
+ break;
673
+ }
674
+ }
675
+ },
676
+
677
+ _setDate: function(date, which){
678
+ if (!which || which == 'date')
679
+ this.date = date;
680
+ if (!which || which == 'view')
681
+ this.viewDate = date;
682
+ this.fill();
683
+ this.setValue();
684
+ this.element.trigger({
685
+ type: 'changeDate',
686
+ date: this.date
687
+ });
688
+ var element;
689
+ if (this.isInput) {
690
+ element = this.element;
691
+ } else if (this.component){
692
+ element = this.element.find('input');
693
+ }
694
+ if (element) {
695
+ element.change();
696
+ if (this.autoclose && (!which || which == 'date')) {
697
+ this.hide();
698
+ }
699
+ }
700
+ },
701
+
702
+ moveMonth: function(date, dir){
703
+ if (!dir) return date;
704
+ var new_date = new Date(date.valueOf()),
705
+ day = new_date.getUTCDate(),
706
+ month = new_date.getUTCMonth(),
707
+ mag = Math.abs(dir),
708
+ new_month, test;
709
+ dir = dir > 0 ? 1 : -1;
710
+ if (mag == 1){
711
+ test = dir == -1
712
+ // If going back one month, make sure month is not current month
713
+ // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
714
+ ? function(){ return new_date.getUTCMonth() == month; }
715
+ // If going forward one month, make sure month is as expected
716
+ // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
717
+ : function(){ return new_date.getUTCMonth() != new_month; };
718
+ new_month = month + dir;
719
+ new_date.setUTCMonth(new_month);
720
+ // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
721
+ if (new_month < 0 || new_month > 11)
722
+ new_month = (new_month + 12) % 12;
723
+ } else {
724
+ // For magnitudes >1, move one month at a time...
725
+ for (var i=0; i<mag; i++)
726
+ // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
727
+ new_date = this.moveMonth(new_date, dir);
728
+ // ...then reset the day, keeping it in the new month
729
+ new_month = new_date.getUTCMonth();
730
+ new_date.setUTCDate(day);
731
+ test = function(){ return new_month != new_date.getUTCMonth(); };
732
+ }
733
+ // Common date-resetting loop -- if date is beyond end of month, make it
734
+ // end of month
735
+ while (test()){
736
+ new_date.setUTCDate(--day);
737
+ new_date.setUTCMonth(new_month);
738
+ }
739
+ return new_date;
740
+ },
741
+
742
+ moveYear: function(date, dir){
743
+ return this.moveMonth(date, dir*12);
744
+ },
745
+
746
+ dateWithinRange: function(date){
747
+ return date >= this.startDate && date <= this.endDate;
748
+ },
749
+
750
+ keydown: function(e){
751
+ if (this.picker.is(':not(:visible)')){
752
+ if (e.keyCode == 27) // allow escape to hide and re-show picker
753
+ this.show();
754
+ return;
755
+ }
756
+ var dateChanged = false,
757
+ dir, day, month,
758
+ newDate, newViewDate;
759
+ switch(e.keyCode){
760
+ case 27: // escape
761
+ this.hide();
762
+ e.preventDefault();
763
+ break;
764
+ case 37: // left
765
+ case 39: // right
766
+ if (!this.keyboardNavigation) break;
767
+ dir = e.keyCode == 37 ? -1 : 1;
768
+ if (e.ctrlKey){
769
+ newDate = this.moveYear(this.date, dir);
770
+ newViewDate = this.moveYear(this.viewDate, dir);
771
+ } else if (e.shiftKey){
772
+ newDate = this.moveMonth(this.date, dir);
773
+ newViewDate = this.moveMonth(this.viewDate, dir);
774
+ } else {
775
+ newDate = new Date(this.date);
776
+ newDate.setUTCDate(this.date.getUTCDate() + dir);
777
+ newViewDate = new Date(this.viewDate);
778
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
779
+ }
780
+ if (this.dateWithinRange(newDate)){
781
+ this.date = newDate;
782
+ this.viewDate = newViewDate;
783
+ this.setValue();
784
+ this.update();
785
+ e.preventDefault();
786
+ dateChanged = true;
787
+ }
788
+ break;
789
+ case 38: // up
790
+ case 40: // down
791
+ if (!this.keyboardNavigation) break;
792
+ dir = e.keyCode == 38 ? -1 : 1;
793
+ if (e.ctrlKey){
794
+ newDate = this.moveYear(this.date, dir);
795
+ newViewDate = this.moveYear(this.viewDate, dir);
796
+ } else if (e.shiftKey){
797
+ newDate = this.moveMonth(this.date, dir);
798
+ newViewDate = this.moveMonth(this.viewDate, dir);
799
+ } else {
800
+ newDate = new Date(this.date);
801
+ newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
802
+ newViewDate = new Date(this.viewDate);
803
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
804
+ }
805
+ if (this.dateWithinRange(newDate)){
806
+ this.date = newDate;
807
+ this.viewDate = newViewDate;
808
+ this.setValue();
809
+ this.update();
810
+ e.preventDefault();
811
+ dateChanged = true;
812
+ }
813
+ break;
814
+ case 13: // enter
815
+ this.hide();
816
+ e.preventDefault();
817
+ break;
818
+ case 9: // tab
819
+ this.hide();
820
+ break;
821
+ }
822
+ if (dateChanged){
823
+ this.element.trigger({
824
+ type: 'changeDate',
825
+ date: this.date
826
+ });
827
+ var element;
828
+ if (this.isInput) {
829
+ element = this.element;
830
+ } else if (this.component){
831
+ element = this.element.find('input');
832
+ }
833
+ if (element) {
834
+ element.change();
835
+ }
836
+ }
837
+ },
838
+
839
+ showMode: function(dir) {
840
+ if (dir) {
841
+ this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
842
+ }
843
+ /*
844
+ vitalets: fixing bug of very special conditions:
845
+ jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
846
+ Method show() does not set display css correctly and datepicker is not shown.
847
+ Changed to .css('display', 'block') solve the problem.
848
+ See https://github.com/vitalets/x-editable/issues/37
849
+
850
+ In jquery 1.7.2+ everything works fine.
851
+ */
852
+ //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
853
+ this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
854
+ this.updateNavArrows();
855
+ }
856
+ };
857
+
858
+ var DateRangePicker = function(element, options){
859
+ this.element = $(element);
860
+ this.inputs = $.map(options.inputs, function(i){ return i.jquery ? i[0] : i; });
861
+ delete options.inputs;
862
+
863
+ $(this.inputs)
864
+ .datepicker(options)
865
+ .bind('changeDate', $.proxy(this.dateUpdated, this));
866
+
867
+ this.pickers = $.map(this.inputs, function(i){ return $(i).data('datepicker'); });
868
+ this.updateDates();
869
+ };
870
+ DateRangePicker.prototype = {
871
+ updateDates: function(){
872
+ this.dates = $.map(this.pickers, function(i){ return i.date; });
873
+ this.updateRanges();
874
+ },
875
+ updateRanges: function(){
876
+ var range = $.map(this.dates, function(d){ return d.valueOf(); });
877
+ $.each(this.pickers, function(i, p){
878
+ p.setRange(range);
879
+ });
880
+ },
881
+ dateUpdated: function(e){
882
+ var dp = $(e.target).data('datepicker'),
883
+ new_date = e.date,
884
+ i = $.inArray(e.target, this.inputs),
885
+ l = this.inputs.length;
886
+ if (i == -1) return;
887
+
888
+ if (new_date < this.dates[i]){
889
+ // Date being moved earlier/left
890
+ while (i>=0 && new_date < this.dates[i]){
891
+ this.pickers[i--].setUTCDate(new_date);
892
+ }
893
+ }
894
+ else if (new_date > this.dates[i]){
895
+ // Date being moved later/right
896
+ while (i<l && new_date > this.dates[i]){
897
+ this.pickers[i++].setUTCDate(new_date);
898
+ }
899
+ }
900
+ this.updateDates();
901
+ },
902
+ remove: function(){
903
+ $.map(this.pickers, function(p){ p.remove(); });
904
+ delete this.element.data().datepicker;
905
+ }
906
+ };
907
+
908
+ var old = $.fn.datepicker;
909
+ $.fn.datepicker = function ( option ) {
910
+ var args = Array.apply(null, arguments);
911
+ args.shift();
912
+ return this.each(function () {
913
+ var $this = $(this),
914
+ data = $this.data('datepicker'),
915
+ options = typeof option == 'object' && option;
916
+ if (!data) {
917
+ if ($this.is('.input-daterange') || options.inputs){
918
+ var opts = {
919
+ inputs: options.inputs || $this.find('input').toArray()
920
+ };
921
+ $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, $.fn.datepicker.defaults,options))));
922
+ }
923
+ else{
924
+ $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
925
+ }
926
+ }
927
+ if (typeof option == 'string' && typeof data[option] == 'function') {
928
+ data[option].apply(data, args);
929
+ }
930
+ });
931
+ };
932
+
933
+ $.fn.datepicker.defaults = {
934
+ };
935
+ $.fn.datepicker.Constructor = Datepicker;
936
+ var dates = $.fn.datepicker.dates = {
937
+ en: {
938
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
939
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
940
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
941
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
942
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
943
+ today: "Today"
944
+ }
945
+ };
946
+
947
+ var DPGlobal = {
948
+ modes: [
949
+ {
950
+ clsName: 'days',
951
+ navFnc: 'Month',
952
+ navStep: 1
953
+ },
954
+ {
955
+ clsName: 'months',
956
+ navFnc: 'FullYear',
957
+ navStep: 1
958
+ },
959
+ {
960
+ clsName: 'years',
961
+ navFnc: 'FullYear',
962
+ navStep: 10
963
+ }],
964
+ isLeapYear: function (year) {
965
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
966
+ },
967
+ getDaysInMonth: function (year, month) {
968
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
969
+ },
970
+ validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
971
+ nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
972
+ parseFormat: function(format){
973
+ // IE treats \0 as a string end in inputs (truncating the value),
974
+ // so it's a bad format delimiter, anyway
975
+ var separators = format.replace(this.validParts, '\0').split('\0'),
976
+ parts = format.match(this.validParts);
977
+ if (!separators || !separators.length || !parts || parts.length === 0){
978
+ throw new Error("Invalid date format.");
979
+ }
980
+ return {separators: separators, parts: parts};
981
+ },
982
+ parseDate: function(date, format, language) {
983
+ if (date instanceof Date) return date;
984
+ if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) {
985
+ var part_re = /([\-+]\d+)([dmwy])/,
986
+ parts = date.match(/([\-+]\d+)([dmwy])/g),
987
+ part, dir;
988
+ date = new Date();
989
+ for (var i=0; i<parts.length; i++) {
990
+ part = part_re.exec(parts[i]);
991
+ dir = parseInt(part[1]);
992
+ switch(part[2]){
993
+ case 'd':
994
+ date.setUTCDate(date.getUTCDate() + dir);
995
+ break;
996
+ case 'm':
997
+ date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
998
+ break;
999
+ case 'w':
1000
+ date.setUTCDate(date.getUTCDate() + dir * 7);
1001
+ break;
1002
+ case 'y':
1003
+ date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
1004
+ break;
1005
+ }
1006
+ }
1007
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
1008
+ }
1009
+ var parts = date && date.match(this.nonpunctuation) || [],
1010
+ date = new Date(),
1011
+ parsed = {},
1012
+ setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1013
+ setters_map = {
1014
+ yyyy: function(d,v){ return d.setUTCFullYear(v); },
1015
+ yy: function(d,v){ return d.setUTCFullYear(2000+v); },
1016
+ m: function(d,v){
1017
+ v -= 1;
1018
+ while (v<0) v += 12;
1019
+ v %= 12;
1020
+ d.setUTCMonth(v);
1021
+ while (d.getUTCMonth() != v)
1022
+ d.setUTCDate(d.getUTCDate()-1);
1023
+ return d;
1024
+ },
1025
+ d: function(d,v){ return d.setUTCDate(v); }
1026
+ },
1027
+ val, filtered, part;
1028
+ setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1029
+ setters_map['dd'] = setters_map['d'];
1030
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
1031
+ var fparts = format.parts.slice();
1032
+ // Remove noop parts
1033
+ if (parts.length != fparts.length) {
1034
+ fparts = $(fparts).filter(function(i,p){
1035
+ return $.inArray(p, setters_order) !== -1;
1036
+ }).toArray();
1037
+ }
1038
+ // Process remainder
1039
+ if (parts.length == fparts.length) {
1040
+ for (var i=0, cnt = fparts.length; i < cnt; i++) {
1041
+ val = parseInt(parts[i], 10);
1042
+ part = fparts[i];
1043
+ if (isNaN(val)) {
1044
+ switch(part) {
1045
+ case 'MM':
1046
+ filtered = $(dates[language].months).filter(function(){
1047
+ var m = this.slice(0, parts[i].length),
1048
+ p = parts[i].slice(0, m.length);
1049
+ return m == p;
1050
+ });
1051
+ val = $.inArray(filtered[0], dates[language].months) + 1;
1052
+ break;
1053
+ case 'M':
1054
+ filtered = $(dates[language].monthsShort).filter(function(){
1055
+ var m = this.slice(0, parts[i].length),
1056
+ p = parts[i].slice(0, m.length);
1057
+ return m == p;
1058
+ });
1059
+ val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1060
+ break;
1061
+ }
1062
+ }
1063
+ parsed[part] = val;
1064
+ }
1065
+ for (var i=0, s; i<setters_order.length; i++){
1066
+ s = setters_order[i];
1067
+ if (s in parsed && !isNaN(parsed[s]))
1068
+ setters_map[s](date, parsed[s]);
1069
+ }
1070
+ }
1071
+ return date;
1072
+ },
1073
+ formatDate: function(date, format, language){
1074
+ var val = {
1075
+ d: date.getUTCDate(),
1076
+ D: dates[language].daysShort[date.getUTCDay()],
1077
+ DD: dates[language].days[date.getUTCDay()],
1078
+ m: date.getUTCMonth() + 1,
1079
+ M: dates[language].monthsShort[date.getUTCMonth()],
1080
+ MM: dates[language].months[date.getUTCMonth()],
1081
+ yy: date.getUTCFullYear().toString().substring(2),
1082
+ yyyy: date.getUTCFullYear()
1083
+ };
1084
+ val.dd = (val.d < 10 ? '0' : '') + val.d;
1085
+ val.mm = (val.m < 10 ? '0' : '') + val.m;
1086
+ var date = [],
1087
+ seps = $.extend([], format.separators);
1088
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
1089
+ if (seps.length)
1090
+ date.push(seps.shift());
1091
+ date.push(val[format.parts[i]]);
1092
+ }
1093
+ return date.join('');
1094
+ },
1095
+ headTemplate: '<thead>'+
1096
+ '<tr>'+
1097
+ '<th class="prev"><i class="icon-arrow-left"/></th>'+
1098
+ '<th colspan="5" class="datepicker-switch"></th>'+
1099
+ '<th class="next"><i class="icon-arrow-right"/></th>'+
1100
+ '</tr>'+
1101
+ '</thead>',
1102
+ contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1103
+ footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
1104
+ };
1105
+ DPGlobal.template = '<div class="datepicker">'+
1106
+ '<div class="datepicker-days">'+
1107
+ '<table class=" table-condensed">'+
1108
+ DPGlobal.headTemplate+
1109
+ '<tbody></tbody>'+
1110
+ DPGlobal.footTemplate+
1111
+ '</table>'+
1112
+ '</div>'+
1113
+ '<div class="datepicker-months">'+
1114
+ '<table class="table-condensed">'+
1115
+ DPGlobal.headTemplate+
1116
+ DPGlobal.contTemplate+
1117
+ DPGlobal.footTemplate+
1118
+ '</table>'+
1119
+ '</div>'+
1120
+ '<div class="datepicker-years">'+
1121
+ '<table class="table-condensed">'+
1122
+ DPGlobal.headTemplate+
1123
+ DPGlobal.contTemplate+
1124
+ DPGlobal.footTemplate+
1125
+ '</table>'+
1126
+ '</div>'+
1127
+ '</div>';
1128
+
1129
+ $.fn.datepicker.DPGlobal = DPGlobal;
1130
+
1131
+
1132
+ /* DATEPICKER NO CONFLICT
1133
+ * =================== */
1134
+
1135
+ $.fn.datepicker.noConflict = function(){
1136
+ $.fn.datepicker = old;
1137
+ return this;
1138
+ };
1139
+
1140
+
1141
+ /* DATEPICKER DATA-API
1142
+ * ================== */
1143
+
1144
+ $(document).on(
1145
+ 'focus.datepicker.data-api click.datepicker.data-api',
1146
+ '[data-provide="datepicker"]',
1147
+ function(e){
1148
+ var $this = $(this);
1149
+ if ($this.data('datepicker')) return;
1150
+ e.preventDefault();
1151
+ // component click requires us to explicitly show it
1152
+ $this.datepicker('show');
1153
+ }
1154
+ );
1155
+ $(function(){
1156
+ $('[data-provide="datepicker-inline"]').datepicker();
1157
+ });
1158
+
1159
+ }( window.jQuery );