rails_admin 0.7.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails_admin might be problematic. Click here for more details.

Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +13 -2
  3. data/README.md +2 -2
  4. data/app/assets/javascripts/rails_admin/ra.filter-box.js +53 -39
  5. data/app/assets/javascripts/rails_admin/ra.filtering-multiselect.js +50 -32
  6. data/app/assets/javascripts/rails_admin/ra.i18n.coffee +5 -3
  7. data/app/assets/javascripts/rails_admin/ra.widgets.coffee +21 -6
  8. data/app/assets/javascripts/rails_admin/rails_admin.js +2 -3
  9. data/app/assets/stylesheets/rails_admin/base/theming.scss +6 -7
  10. data/app/assets/stylesheets/rails_admin/custom/mixins.scss +3 -4
  11. data/app/assets/stylesheets/rails_admin/custom/theming.scss +4 -4
  12. data/app/assets/stylesheets/rails_admin/custom/variables.scss +4 -4
  13. data/app/assets/stylesheets/rails_admin/rails_admin.scss.erb +3 -3
  14. data/app/assets/stylesheets/rails_admin/themes/default/mixins.scss +2 -2
  15. data/app/assets/stylesheets/rails_admin/themes/default/theming.scss +3 -3
  16. data/app/assets/stylesheets/rails_admin/themes/default/variables.scss +3 -3
  17. data/app/controllers/rails_admin/application_controller.rb +0 -2
  18. data/app/controllers/rails_admin/main_controller.rb +6 -5
  19. data/app/helpers/rails_admin/application_helper.rb +3 -3
  20. data/app/helpers/rails_admin/main_helper.rb +45 -0
  21. data/app/views/layouts/rails_admin/application.html.haml +2 -2
  22. data/app/views/layouts/rails_admin/pjax.html.haml +2 -2
  23. data/app/views/rails_admin/main/_form_datetime.html.haml +4 -1
  24. data/app/views/rails_admin/main/_form_filtering_multiselect.html.haml +1 -0
  25. data/app/views/rails_admin/main/_submit_buttons.html.haml +1 -1
  26. data/app/views/rails_admin/main/export.html.haml +13 -13
  27. data/app/views/rails_admin/main/index.html.haml +20 -64
  28. data/config/locales/rails_admin.en.yml +0 -1
  29. data/lib/generators/rails_admin/templates/initializer.erb +3 -0
  30. data/lib/rails_admin.rb +2 -1
  31. data/lib/rails_admin/abstract_model.rb +14 -16
  32. data/lib/rails_admin/adapters/active_record.rb +17 -8
  33. data/lib/rails_admin/adapters/active_record/association.rb +5 -0
  34. data/lib/rails_admin/adapters/mongoid.rb +7 -12
  35. data/lib/rails_admin/adapters/mongoid/association.rb +5 -0
  36. data/lib/rails_admin/config/actions/export.rb +1 -1
  37. data/lib/rails_admin/config/fields.rb +1 -0
  38. data/lib/rails_admin/config/fields/association.rb +5 -0
  39. data/lib/rails_admin/config/fields/base.rb +4 -0
  40. data/lib/rails_admin/config/fields/factories/paperclip.rb +1 -1
  41. data/lib/rails_admin/config/fields/factories/refile.rb +25 -0
  42. data/lib/rails_admin/config/fields/types/active_record_enum.rb +5 -5
  43. data/lib/rails_admin/config/fields/types/all.rb +1 -0
  44. data/lib/rails_admin/config/fields/types/bson_object_id.rb +16 -2
  45. data/lib/rails_admin/config/fields/types/date.rb +19 -8
  46. data/lib/rails_admin/config/fields/types/datetime.rb +33 -117
  47. data/lib/rails_admin/config/fields/types/json.rb +5 -2
  48. data/lib/rails_admin/config/fields/types/refile.rb +27 -0
  49. data/lib/rails_admin/config/fields/types/serialized.rb +5 -2
  50. data/lib/rails_admin/config/fields/types/time.rb +6 -18
  51. data/lib/rails_admin/config/has_fields.rb +2 -2
  52. data/lib/rails_admin/config/lazy_model.rb +2 -2
  53. data/lib/rails_admin/config/proxyable/proxy.rb +2 -4
  54. data/lib/rails_admin/extensions/pundit.rb +3 -0
  55. data/lib/rails_admin/extensions/pundit/authorization_adapter.rb +63 -0
  56. data/lib/rails_admin/support/datetime.rb +99 -0
  57. data/lib/rails_admin/support/hash_helper.rb +28 -0
  58. data/lib/rails_admin/support/i18n.rb +41 -0
  59. data/lib/rails_admin/version.rb +2 -2
  60. data/vendor/assets/javascripts/rails_admin/bootstrap-datetimepicker.js +2444 -0
  61. data/vendor/assets/javascripts/rails_admin/moment-with-locales.js +9977 -0
  62. data/vendor/assets/stylesheets/rails_admin/_bootstrap-datetimepicker.scss +343 -0
  63. data/vendor/assets/stylesheets/rails_admin/bootstrap-datetimepicker-build.scss +16 -0
  64. metadata +14 -9
  65. data/app/assets/javascripts/rails_admin/jquery.ui.timepicker.js +0 -1437
  66. data/app/assets/javascripts/rails_admin/ra.datetimepicker.js +0 -83
  67. data/app/assets/stylesheets/rails_admin/jquery.ui.timepicker.scss +0 -68
  68. data/app/assets/stylesheets/rails_admin/ra.calendar-additions.scss +0 -45
  69. data/lib/rails_admin/i18n_support.rb +0 -39
  70. data/lib/rails_admin/support/core_extensions.rb +0 -30
@@ -0,0 +1,343 @@
1
+ /*!
2
+ * Datetimepicker for Bootstrap 3
3
+ * ! version : 4.7.14
4
+ * https://github.com/Eonasdan/bootstrap-datetimepicker/
5
+ */
6
+ $bs-datetimepicker-timepicker-font-size: 1.2em;
7
+ $bs-datetimepicker-active-bg: $btn-primary-bg;
8
+ $bs-datetimepicker-active-color: $btn-primary-color;
9
+ $bs-datetimepicker-border-radius: $border-radius-base;
10
+ $bs-datetimepicker-btn-hover-bg: $gray-lighter;
11
+ $bs-datetimepicker-disabled-color: $gray-light;
12
+ $bs-datetimepicker-alternate-color: $gray-light;
13
+ $bs-datetimepicker-secondary-border-color: #ccc;
14
+ $bs-datetimepicker-secondary-border-color-rgba: rgba(0, 0, 0, 0.2);
15
+ $bs-datetimepicker-primary-border-color: white;
16
+ $bs-datetimepicker-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
17
+
18
+ .bootstrap-datetimepicker-widget {
19
+ list-style: none;
20
+
21
+ &.dropdown-menu {
22
+ margin: 2px 0;
23
+ padding: 4px;
24
+ width: 19em;
25
+
26
+ &.timepicker-sbs {
27
+ @media (min-width: $screen-sm-min) {
28
+ width: 38em;
29
+ }
30
+
31
+ @media (min-width: $screen-md-min) {
32
+ width: 38em;
33
+ }
34
+
35
+ @media (min-width: $screen-lg-min) {
36
+ width: 38em;
37
+ }
38
+ }
39
+
40
+ &:before, &:after {
41
+ content: '';
42
+ display: inline-block;
43
+ position: absolute;
44
+ }
45
+
46
+ &.bottom {
47
+ &:before {
48
+ border-left: 7px solid transparent;
49
+ border-right: 7px solid transparent;
50
+ border-bottom: 7px solid $bs-datetimepicker-secondary-border-color;
51
+ border-bottom-color: $bs-datetimepicker-secondary-border-color-rgba;
52
+ top: -7px;
53
+ left: 7px;
54
+ }
55
+
56
+ &:after {
57
+ border-left: 6px solid transparent;
58
+ border-right: 6px solid transparent;
59
+ border-bottom: 6px solid $bs-datetimepicker-primary-border-color;
60
+ top: -6px;
61
+ left: 8px;
62
+ }
63
+ }
64
+
65
+ &.top {
66
+ &:before {
67
+ border-left: 7px solid transparent;
68
+ border-right: 7px solid transparent;
69
+ border-top: 7px solid $bs-datetimepicker-secondary-border-color;
70
+ border-top-color: $bs-datetimepicker-secondary-border-color-rgba;
71
+ bottom: -7px;
72
+ left: 6px;
73
+ }
74
+
75
+ &:after {
76
+ border-left: 6px solid transparent;
77
+ border-right: 6px solid transparent;
78
+ border-top: 6px solid $bs-datetimepicker-primary-border-color;
79
+ bottom: -6px;
80
+ left: 7px;
81
+ }
82
+ }
83
+
84
+ &.pull-right {
85
+ &:before {
86
+ left: auto;
87
+ right: 6px;
88
+ }
89
+
90
+ &:after {
91
+ left: auto;
92
+ right: 7px;
93
+ }
94
+ }
95
+ }
96
+
97
+ .list-unstyled {
98
+ margin: 0;
99
+ }
100
+
101
+ a[data-action] {
102
+ padding: 6px 0;
103
+ }
104
+
105
+ a[data-action]:active {
106
+ box-shadow: none;
107
+ }
108
+
109
+ .timepicker-hour, .timepicker-minute, .timepicker-second {
110
+ width: 54px;
111
+ font-weight: bold;
112
+ font-size: $bs-datetimepicker-timepicker-font-size;
113
+ margin: 0;
114
+ }
115
+
116
+ button[data-action] {
117
+ padding: 6px;
118
+ }
119
+
120
+ .btn[data-action="incrementHours"]::after {
121
+ @extend .sr-only;
122
+ content: "Increment Hours";
123
+ }
124
+
125
+ .btn[data-action="incrementMinutes"]::after {
126
+ @extend .sr-only;
127
+ content: "Increment Minutes";
128
+ }
129
+
130
+ .btn[data-action="decrementHours"]::after {
131
+ @extend .sr-only;
132
+ content: "Decrement Hours";
133
+ }
134
+
135
+ .btn[data-action="decrementMinutes"]::after {
136
+ @extend .sr-only;
137
+ content: "Decrement Minutes";
138
+ }
139
+
140
+ .btn[data-action="showHours"]::after {
141
+ @extend .sr-only;
142
+ content: "Show Hours";
143
+ }
144
+
145
+ .btn[data-action="showMinutes"]::after {
146
+ @extend .sr-only;
147
+ content: "Show Minutes";
148
+ }
149
+
150
+ .btn[data-action="togglePeriod"]::after {
151
+ @extend .sr-only;
152
+ content: "Toggle AM/PM";
153
+ }
154
+
155
+ .btn[data-action="clear"]::after {
156
+ @extend .sr-only;
157
+ content: "Clear the picker";
158
+ }
159
+
160
+ .btn[data-action="today"]::after {
161
+ @extend .sr-only;
162
+ content: "Set the date to today";
163
+ }
164
+
165
+ .picker-switch {
166
+ text-align: center;
167
+
168
+ &::after {
169
+ @extend .sr-only;
170
+ content: "Toggle Date and Time Screens";
171
+ }
172
+
173
+ td {
174
+ padding: 0;
175
+ margin: 0;
176
+ height: auto;
177
+ width: auto;
178
+ line-height: inherit;
179
+
180
+ span {
181
+ line-height: 2.5;
182
+ height: 2.5em;
183
+ width: 100%;
184
+ }
185
+ }
186
+ }
187
+
188
+ table {
189
+ width: 100%;
190
+ margin: 0;
191
+
192
+
193
+ & td,
194
+ & th {
195
+ text-align: center;
196
+ border-radius: $bs-datetimepicker-border-radius;
197
+ }
198
+
199
+ & th {
200
+ height: 20px;
201
+ line-height: 20px;
202
+ width: 20px;
203
+
204
+ &.picker-switch {
205
+ width: 145px;
206
+ }
207
+
208
+ &.disabled,
209
+ &.disabled:hover {
210
+ background: none;
211
+ color: $bs-datetimepicker-disabled-color;
212
+ cursor: not-allowed;
213
+ }
214
+
215
+ &.prev::after {
216
+ @extend .sr-only;
217
+ content: "Previous Month";
218
+ }
219
+
220
+ &.next::after {
221
+ @extend .sr-only;
222
+ content: "Next Month";
223
+ }
224
+ }
225
+
226
+ & thead tr:first-child th {
227
+ cursor: pointer;
228
+
229
+ &:hover {
230
+ background: $bs-datetimepicker-btn-hover-bg;
231
+ }
232
+ }
233
+
234
+ & td {
235
+ height: 54px;
236
+ line-height: 54px;
237
+ width: 54px;
238
+
239
+ &.cw {
240
+ font-size: .8em;
241
+ height: 20px;
242
+ line-height: 20px;
243
+ color: $bs-datetimepicker-alternate-color;
244
+ }
245
+
246
+ &.day {
247
+ height: 20px;
248
+ line-height: 20px;
249
+ width: 20px;
250
+ }
251
+
252
+ &.day:hover,
253
+ &.hour:hover,
254
+ &.minute:hover,
255
+ &.second:hover {
256
+ background: $bs-datetimepicker-btn-hover-bg;
257
+ cursor: pointer;
258
+ }
259
+
260
+ &.old,
261
+ &.new {
262
+ color: $bs-datetimepicker-alternate-color;
263
+ }
264
+
265
+ &.today {
266
+ position: relative;
267
+
268
+ &:before {
269
+ content: '';
270
+ display: inline-block;
271
+ border: 0 0 7px 7px solid transparent;
272
+ border-bottom-color: $bs-datetimepicker-active-bg;
273
+ border-top-color: $bs-datetimepicker-secondary-border-color-rgba;
274
+ position: absolute;
275
+ bottom: 4px;
276
+ right: 4px;
277
+ }
278
+ }
279
+
280
+ &.active,
281
+ &.active:hover {
282
+ background-color: $bs-datetimepicker-active-bg;
283
+ color: $bs-datetimepicker-active-color;
284
+ text-shadow: $bs-datetimepicker-text-shadow;
285
+ }
286
+
287
+ &.active.today:before {
288
+ border-bottom-color: #fff;
289
+ }
290
+
291
+ &.disabled,
292
+ &.disabled:hover {
293
+ background: none;
294
+ color: $bs-datetimepicker-disabled-color;
295
+ cursor: not-allowed;
296
+ }
297
+
298
+ span {
299
+ display: inline-block;
300
+ width: 54px;
301
+ height: 54px;
302
+ line-height: 54px;
303
+ margin: 2px 1.5px;
304
+ cursor: pointer;
305
+ border-radius: $bs-datetimepicker-border-radius;
306
+
307
+ &:hover {
308
+ background: $bs-datetimepicker-btn-hover-bg;
309
+ }
310
+
311
+ &.active {
312
+ background-color: $bs-datetimepicker-active-bg;
313
+ color: $bs-datetimepicker-active-color;
314
+ text-shadow: $bs-datetimepicker-text-shadow;
315
+ }
316
+
317
+ &.old {
318
+ color: $bs-datetimepicker-alternate-color;
319
+ }
320
+
321
+ &.disabled,
322
+ &.disabled:hover {
323
+ background: none;
324
+ color: $bs-datetimepicker-disabled-color;
325
+ cursor: not-allowed;
326
+ }
327
+ }
328
+ }
329
+ }
330
+
331
+ &.usetwentyfour {
332
+ td.hour {
333
+ height: 27px;
334
+ line-height: 27px;
335
+ }
336
+ }
337
+ }
338
+
339
+ .input-group.date {
340
+ & .input-group-addon {
341
+ cursor: pointer;
342
+ }
343
+ }
@@ -0,0 +1,16 @@
1
+ // Import bootstrap variables including default color palette and fonts
2
+ //@import "../../node_modules/bootstrap/less/variables.less";
3
+
4
+ .sr-only {
5
+ position: absolute;
6
+ width: 1px;
7
+ height: 1px;
8
+ margin: -1px;
9
+ padding: 0;
10
+ overflow: hidden;
11
+ clip: rect(0,0,0,0);
12
+ border: 0;
13
+ }
14
+
15
+ // Import datepicker component
16
+ @import "_bootstrap-datetimepicker";
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Michaels-Ober
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2015-08-16 00:00:00.000000000 Z
15
+ date: 2015-11-24 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: builder
@@ -304,8 +304,6 @@ files:
304
304
  - app/assets/javascripts/rails_admin/jquery.colorpicker.js
305
305
  - app/assets/javascripts/rails_admin/jquery.pjax.js
306
306
  - app/assets/javascripts/rails_admin/jquery.remotipart.fixed.js
307
- - app/assets/javascripts/rails_admin/jquery.ui.timepicker.js
308
- - app/assets/javascripts/rails_admin/ra.datetimepicker.js
309
307
  - app/assets/javascripts/rails_admin/ra.filter-box.js
310
308
  - app/assets/javascripts/rails_admin/ra.filtering-multiselect.js
311
309
  - app/assets/javascripts/rails_admin/ra.filtering-select.js
@@ -401,8 +399,6 @@ files:
401
399
  - app/assets/stylesheets/rails_admin/custom/theming.scss
402
400
  - app/assets/stylesheets/rails_admin/custom/variables.scss
403
401
  - app/assets/stylesheets/rails_admin/jquery.colorpicker.scss
404
- - app/assets/stylesheets/rails_admin/jquery.ui.timepicker.scss
405
- - app/assets/stylesheets/rails_admin/ra.calendar-additions.scss
406
402
  - app/assets/stylesheets/rails_admin/ra.filtering-multiselect.scss
407
403
  - app/assets/stylesheets/rails_admin/ra.widgets.scss
408
404
  - app/assets/stylesheets/rails_admin/rails_admin.scss.erb
@@ -503,6 +499,7 @@ files:
503
499
  - lib/rails_admin/config/fields/factories/enum.rb
504
500
  - lib/rails_admin/config/fields/factories/paperclip.rb
505
501
  - lib/rails_admin/config/fields/factories/password.rb
502
+ - lib/rails_admin/config/fields/factories/refile.rb
506
503
  - lib/rails_admin/config/fields/group.rb
507
504
  - lib/rails_admin/config/fields/types.rb
508
505
  - lib/rails_admin/config/fields/types/active_record_enum.rb
@@ -532,6 +529,7 @@ files:
532
529
  - lib/rails_admin/config/fields/types/paperclip.rb
533
530
  - lib/rails_admin/config/fields/types/password.rb
534
531
  - lib/rails_admin/config/fields/types/polymorphic_association.rb
532
+ - lib/rails_admin/config/fields/types/refile.rb
535
533
  - lib/rails_admin/config/fields/types/serialized.rb
536
534
  - lib/rails_admin/config/fields/types/string.rb
537
535
  - lib/rails_admin/config/fields/types/text.rb
@@ -569,11 +567,18 @@ files:
569
567
  - lib/rails_admin/extensions/history/history.rb
570
568
  - lib/rails_admin/extensions/paper_trail.rb
571
569
  - lib/rails_admin/extensions/paper_trail/auditing_adapter.rb
572
- - lib/rails_admin/i18n_support.rb
573
- - lib/rails_admin/support/core_extensions.rb
570
+ - lib/rails_admin/extensions/pundit.rb
571
+ - lib/rails_admin/extensions/pundit/authorization_adapter.rb
574
572
  - lib/rails_admin/support/csv_converter.rb
573
+ - lib/rails_admin/support/datetime.rb
574
+ - lib/rails_admin/support/hash_helper.rb
575
+ - lib/rails_admin/support/i18n.rb
575
576
  - lib/rails_admin/version.rb
576
577
  - lib/tasks/rails_admin.rake
578
+ - vendor/assets/javascripts/rails_admin/bootstrap-datetimepicker.js
579
+ - vendor/assets/javascripts/rails_admin/moment-with-locales.js
580
+ - vendor/assets/stylesheets/rails_admin/_bootstrap-datetimepicker.scss
581
+ - vendor/assets/stylesheets/rails_admin/bootstrap-datetimepicker-build.scss
577
582
  homepage: https://github.com/sferik/rails_admin
578
583
  licenses:
579
584
  - MIT
@@ -594,7 +599,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
594
599
  version: 1.8.11
595
600
  requirements: []
596
601
  rubyforge_project:
597
- rubygems_version: 2.4.3
602
+ rubygems_version: 2.4.5.1
598
603
  signing_key:
599
604
  specification_version: 4
600
605
  summary: Admin for Rails
@@ -1,1437 +0,0 @@
1
- /*
2
- * jQuery UI Timepicker
3
- *
4
- * Copyright 2010-2013, Francois Gelinas
5
- * Dual licensed under the MIT or GPL Version 2 licenses.
6
- * http://jquery.org/license
7
- *
8
- * http://fgelinas.com/code/timepicker
9
- *
10
- * Depends:
11
- * jquery.ui.core.js
12
- * jquery.ui.position.js (only if position settngs are used)
13
- *
14
- * Change version 0.1.0 - moved the t-rex up here
15
- *
16
- ____
17
- ___ .-~. /_"-._
18
- `-._~-. / /_ "~o\ :Y
19
- \ \ / : \~x. ` ')
20
- ] Y / | Y< ~-.__j
21
- / ! _.--~T : l l< /.-~
22
- / / ____.--~ . ` l /~\ \<|Y
23
- / / .-~~" /| . ',-~\ \L|
24
- / / / .^ \ Y~Y \.^>/l_ "--'
25
- / Y .-"( . l__ j_j l_/ /~_.-~ .
26
- Y l / \ ) ~~~." / `/"~ / \.__/l_
27
- | \ _.-" ~-{__ l : l._Z~-.___.--~
28
- | ~---~ / ~~"---\_ ' __[>
29
- l . _.^ ___ _>-y~
30
- \ \ . .-~ .-~ ~>--" /
31
- \ ~---" / ./ _.-'
32
- "-.,_____.,_ _.--~\ _.-~
33
- ~~ ( _} -Row
34
- `. ~(
35
- ) \
36
- /,`--'~\--'~\
37
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38
- ->T-Rex<-
39
- */
40
-
41
- (function ($) {
42
-
43
- $.extend($.ui, { timepicker: { version: "0.3.2"} });
44
-
45
- var PROP_NAME = 'timepicker',
46
- tpuuid = new Date().getTime();
47
-
48
- /* Time picker manager.
49
- Use the singleton instance of this class, $.timepicker, to interact with the time picker.
50
- Settings for (groups of) time pickers are maintained in an instance object,
51
- allowing multiple different settings on the same page. */
52
-
53
- function Timepicker() {
54
- this.debug = true; // Change this to true to start debugging
55
- this._curInst = null; // The current instance in use
56
- this._disabledInputs = []; // List of time picker inputs that have been disabled
57
- this._timepickerShowing = false; // True if the popup picker is showing , false if not
58
- this._inDialog = false; // True if showing within a "dialog", false if not
59
- this._dialogClass = 'ui-timepicker-dialog'; // The name of the dialog marker class
60
- this._mainDivId = 'ui-timepicker-div'; // The ID of the main timepicker division
61
- this._inlineClass = 'ui-timepicker-inline'; // The name of the inline marker class
62
- this._currentClass = 'ui-timepicker-current'; // The name of the current hour / minutes marker class
63
- this._dayOverClass = 'ui-timepicker-days-cell-over'; // The name of the day hover marker class
64
-
65
- this.regional = []; // Available regional settings, indexed by language code
66
- this.regional[''] = { // Default regional settings
67
- hourText: 'Hour', // Display text for hours section
68
- minuteText: 'Minute', // Display text for minutes link
69
- amPmText: ['AM', 'PM'], // Display text for AM PM
70
- closeButtonText: 'Done', // Text for the confirmation button (ok button)
71
- nowButtonText: 'Now', // Text for the now button
72
- deselectButtonText: 'Deselect' // Text for the deselect button
73
- };
74
- this._defaults = { // Global defaults for all the time picker instances
75
- showOn: 'focus', // 'focus' for popup on focus,
76
- // 'button' for trigger button, or 'both' for either (not yet implemented)
77
- button: null, // 'button' element that will trigger the timepicker
78
- showAnim: 'fadeIn', // Name of jQuery animation for popup
79
- showOptions: {}, // Options for enhanced animations
80
- appendText: '', // Display text following the input box, e.g. showing the format
81
-
82
- beforeShow: null, // Define a callback function executed before the timepicker is shown
83
- onSelect: null, // Define a callback function when a hour / minutes is selected
84
- onClose: null, // Define a callback function when the timepicker is closed
85
-
86
- timeSeparator: ':', // The character to use to separate hours and minutes.
87
- periodSeparator: ' ', // The character to use to separate the time from the time period.
88
- showPeriod: false, // Define whether or not to show AM/PM with selected time
89
- showPeriodLabels: true, // Show the AM/PM labels on the left of the time picker
90
- showLeadingZero: true, // Define whether or not to show a leading zero for hours < 10. [true/false]
91
- showMinutesLeadingZero: true, // Define whether or not to show a leading zero for minutes < 10.
92
- altField: '', // Selector for an alternate field to store selected time into
93
- defaultTime: 'now', // Used as default time when input field is empty or for inline timePicker
94
- // (set to 'now' for the current time, '' for no highlighted time)
95
- myPosition: 'left top', // Position of the dialog relative to the input.
96
- // see the position utility for more info : http://jqueryui.com/demos/position/
97
- atPosition: 'left bottom', // Position of the input element to match
98
- // Note : if the position utility is not loaded, the timepicker will attach left top to left bottom
99
- //NEW: 2011-02-03
100
- onHourShow: null, // callback for enabling / disabling on selectable hours ex : function(hour) { return true; }
101
- onMinuteShow: null, // callback for enabling / disabling on time selection ex : function(hour,minute) { return true; }
102
-
103
- hours: {
104
- starts: 0, // first displayed hour
105
- ends: 23 // last displayed hour
106
- },
107
- minutes: {
108
- starts: 0, // first displayed minute
109
- ends: 55, // last displayed minute
110
- interval: 5 // interval of displayed minutes
111
- },
112
- rows: 4, // number of rows for the input tables, minimum 2, makes more sense if you use multiple of 2
113
- // 2011-08-05 0.2.4
114
- showHours: true, // display the hours section of the dialog
115
- showMinutes: true, // display the minute section of the dialog
116
- optionalMinutes: false, // optionally parse inputs of whole hours with minutes omitted
117
-
118
- // buttons
119
- showCloseButton: false, // shows an OK button to confirm the edit
120
- showNowButton: false, // Shows the 'now' button
121
- showDeselectButton: false // Shows the deselect time button
122
-
123
- };
124
- $.extend(this._defaults, this.regional['']);
125
-
126
- this.tpDiv = $('<div id="' + this._mainDivId + '" class="ui-timepicker ui-widget ui-helper-clearfix ui-corner-all " style="display: none"></div>');
127
- }
128
-
129
- $.extend(Timepicker.prototype, {
130
- /* Class name added to elements to indicate already configured with a time picker. */
131
- markerClassName: 'hasTimepicker',
132
-
133
- /* Debug logging (if enabled). */
134
- log: function () {
135
- if (this.debug)
136
- console.log.apply('', arguments);
137
- },
138
-
139
- _widgetTimepicker: function () {
140
- return this.tpDiv;
141
- },
142
-
143
- /* Override the default settings for all instances of the time picker.
144
- @param settings object - the new settings to use as defaults (anonymous object)
145
- @return the manager object */
146
- setDefaults: function (settings) {
147
- extendRemove(this._defaults, settings || {});
148
- return this;
149
- },
150
-
151
- /* Attach the time picker to a jQuery selection.
152
- @param target element - the target input field or division or span
153
- @param settings object - the new settings to use for this time picker instance (anonymous) */
154
- _attachTimepicker: function (target, settings) {
155
- // check for settings on the control itself - in namespace 'time:'
156
- var inlineSettings = null;
157
- for (var attrName in this._defaults) {
158
- var attrValue = target.getAttribute('time:' + attrName);
159
- if (attrValue) {
160
- inlineSettings = inlineSettings || {};
161
- try {
162
- inlineSettings[attrName] = eval(attrValue);
163
- } catch (err) {
164
- inlineSettings[attrName] = attrValue;
165
- }
166
- }
167
- }
168
- var nodeName = target.nodeName.toLowerCase();
169
- var inline = (nodeName == 'div' || nodeName == 'span');
170
-
171
- if (!target.id) {
172
- this.uuid += 1;
173
- target.id = 'tp' + this.uuid;
174
- }
175
- var inst = this._newInst($(target), inline);
176
- inst.settings = $.extend({}, settings || {}, inlineSettings || {});
177
- if (nodeName == 'input') {
178
- this._connectTimepicker(target, inst);
179
- // init inst.hours and inst.minutes from the input value
180
- this._setTimeFromField(inst);
181
- } else if (inline) {
182
- this._inlineTimepicker(target, inst);
183
- }
184
-
185
-
186
- },
187
-
188
- /* Create a new instance object. */
189
- _newInst: function (target, inline) {
190
- var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
191
- return {
192
- id: id, input: target, // associated target
193
- inline: inline, // is timepicker inline or not :
194
- tpDiv: (!inline ? this.tpDiv : // presentation div
195
- $('<div class="' + this._inlineClass + ' ui-timepicker ui-widget ui-helper-clearfix"></div>'))
196
- };
197
- },
198
-
199
- /* Attach the time picker to an input field. */
200
- _connectTimepicker: function (target, inst) {
201
- var input = $(target);
202
- inst.append = $([]);
203
- inst.trigger = $([]);
204
- if (input.hasClass(this.markerClassName)) { return; }
205
- this._attachments(input, inst);
206
- input.addClass(this.markerClassName).
207
- keydown(this._doKeyDown).
208
- keyup(this._doKeyUp).
209
- bind("setData.timepicker", function (event, key, value) {
210
- inst.settings[key] = value;
211
- }).
212
- bind("getData.timepicker", function (event, key) {
213
- return this._get(inst, key);
214
- });
215
- $.data(target, PROP_NAME, inst);
216
- },
217
-
218
- /* Handle keystrokes. */
219
- _doKeyDown: function (event) {
220
- var inst = $.timepicker._getInst(event.target);
221
- var handled = true;
222
- inst._keyEvent = true;
223
- if ($.timepicker._timepickerShowing) {
224
- switch (event.keyCode) {
225
- case 9: $.timepicker._hideTimepicker();
226
- handled = false;
227
- break; // hide on tab out
228
- case 13:
229
- $.timepicker._updateSelectedValue(inst);
230
- $.timepicker._hideTimepicker();
231
-
232
- return false; // don't submit the form
233
- break; // select the value on enter
234
- case 27: $.timepicker._hideTimepicker();
235
- break; // hide on escape
236
- default: handled = false;
237
- }
238
- }
239
- else if (event.keyCode == 36 && event.ctrlKey) { // display the time picker on ctrl+home
240
- $.timepicker._showTimepicker(this);
241
- }
242
- else {
243
- handled = false;
244
- }
245
- if (handled) {
246
- event.preventDefault();
247
- event.stopPropagation();
248
- }
249
- },
250
-
251
- /* Update selected time on keyUp */
252
- /* Added verion 0.0.5 */
253
- _doKeyUp: function (event) {
254
- var inst = $.timepicker._getInst(event.target);
255
- $.timepicker._setTimeFromField(inst);
256
- $.timepicker._updateTimepicker(inst);
257
- },
258
-
259
- /* Make attachments based on settings. */
260
- _attachments: function (input, inst) {
261
- var appendText = this._get(inst, 'appendText');
262
- var isRTL = this._get(inst, 'isRTL');
263
- if (inst.append) { inst.append.remove(); }
264
- if (appendText) {
265
- inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
266
- input[isRTL ? 'before' : 'after'](inst.append);
267
- }
268
- input.unbind('focus.timepicker', this._showTimepicker);
269
- input.unbind('click.timepicker', this._adjustZIndex);
270
-
271
- if (inst.trigger) { inst.trigger.remove(); }
272
-
273
- var showOn = this._get(inst, 'showOn');
274
- if (showOn == 'focus' || showOn == 'both') { // pop-up time picker when in the marked field
275
- input.bind("focus.timepicker", this._showTimepicker);
276
- input.bind("click.timepicker", this._adjustZIndex);
277
- }
278
- if (showOn == 'button' || showOn == 'both') { // pop-up time picker when 'button' element is clicked
279
- var button = this._get(inst, 'button');
280
- $(button).bind("click.timepicker", function () {
281
- if ($.timepicker._timepickerShowing && $.timepicker._lastInput == input[0]) {
282
- $.timepicker._hideTimepicker();
283
- } else if (!inst.input.is(':disabled')) {
284
- $.timepicker._showTimepicker(input[0]);
285
- }
286
- return false;
287
- });
288
-
289
- }
290
- },
291
-
292
-
293
- /* Attach an inline time picker to a div. */
294
- _inlineTimepicker: function(target, inst) {
295
- var divSpan = $(target);
296
- if (divSpan.hasClass(this.markerClassName))
297
- return;
298
- divSpan.addClass(this.markerClassName).append(inst.tpDiv).
299
- bind("setData.timepicker", function(event, key, value){
300
- inst.settings[key] = value;
301
- }).bind("getData.timepicker", function(event, key){
302
- return this._get(inst, key);
303
- });
304
- $.data(target, PROP_NAME, inst);
305
-
306
- this._setTimeFromField(inst);
307
- this._updateTimepicker(inst);
308
- inst.tpDiv.show();
309
- },
310
-
311
- _adjustZIndex: function(input) {
312
- input = input.target || input;
313
- var inst = $.timepicker._getInst(input);
314
- inst.tpDiv.css('zIndex', $.timepicker._getZIndex(input) +1);
315
- },
316
-
317
- /* Pop-up the time picker for a given input field.
318
- @param input element - the input field attached to the time picker or
319
- event - if triggered by focus */
320
- _showTimepicker: function (input) {
321
- input = input.target || input;
322
- if (input.nodeName.toLowerCase() != 'input') { input = $('input', input.parentNode)[0]; } // find from button/image trigger
323
-
324
- if ($.timepicker._isDisabledTimepicker(input) || $.timepicker._lastInput == input) { return; } // already here
325
-
326
- // fix v 0.0.8 - close current timepicker before showing another one
327
- $.timepicker._hideTimepicker();
328
-
329
- var inst = $.timepicker._getInst(input);
330
- if ($.timepicker._curInst && $.timepicker._curInst != inst) {
331
- $.timepicker._curInst.tpDiv.stop(true, true);
332
- }
333
- var beforeShow = $.timepicker._get(inst, 'beforeShow');
334
- extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
335
- inst.lastVal = null;
336
- $.timepicker._lastInput = input;
337
-
338
- $.timepicker._setTimeFromField(inst);
339
-
340
- // calculate default position
341
- if ($.timepicker._inDialog) { input.value = ''; } // hide cursor
342
- if (!$.timepicker._pos) { // position below input
343
- $.timepicker._pos = $.timepicker._findPos(input);
344
- $.timepicker._pos[1] += input.offsetHeight; // add the height
345
- }
346
- var isFixed = false;
347
- $(input).parents().each(function () {
348
- isFixed |= $(this).css('position') == 'fixed';
349
- return !isFixed;
350
- });
351
-
352
- var offset = { left: $.timepicker._pos[0], top: $.timepicker._pos[1] };
353
-
354
- $.timepicker._pos = null;
355
- // determine sizing offscreen
356
- inst.tpDiv.css({ position: 'absolute', display: 'block', top: '-1000px' });
357
- $.timepicker._updateTimepicker(inst);
358
-
359
-
360
- // position with the ui position utility, if loaded
361
- if ( ( ! inst.inline ) && ( typeof $.ui.position == 'object' ) ) {
362
- inst.tpDiv.position({
363
- of: inst.input,
364
- my: $.timepicker._get( inst, 'myPosition' ),
365
- at: $.timepicker._get( inst, 'atPosition' ),
366
- // offset: $( "#offset" ).val(),
367
- // using: using,
368
- collision: 'flip'
369
- });
370
- var offset = inst.tpDiv.offset();
371
- $.timepicker._pos = [offset.top, offset.left];
372
- }
373
-
374
-
375
- // reset clicked state
376
- inst._hoursClicked = false;
377
- inst._minutesClicked = false;
378
-
379
- // fix width for dynamic number of time pickers
380
- // and adjust position before showing
381
- offset = $.timepicker._checkOffset(inst, offset, isFixed);
382
- inst.tpDiv.css({ position: ($.timepicker._inDialog && $.blockUI ?
383
- 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
384
- left: offset.left + 'px', top: offset.top + 'px'
385
- });
386
- if ( ! inst.inline ) {
387
- var showAnim = $.timepicker._get(inst, 'showAnim');
388
- var duration = $.timepicker._get(inst, 'duration');
389
-
390
- var postProcess = function () {
391
- $.timepicker._timepickerShowing = true;
392
- var borders = $.timepicker._getBorders(inst.tpDiv);
393
- inst.tpDiv.find('iframe.ui-timepicker-cover'). // IE6- only
394
- css({ left: -borders[0], top: -borders[1],
395
- width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
396
- });
397
- };
398
-
399
- // Fixed the zIndex problem for real (I hope) - FG - v 0.2.9
400
- $.timepicker._adjustZIndex(input);
401
- //inst.tpDiv.css('zIndex', $.timepicker._getZIndex(input) +1);
402
-
403
- if ($.effects && $.effects[showAnim]) {
404
- inst.tpDiv.show(showAnim, $.timepicker._get(inst, 'showOptions'), duration, postProcess);
405
- }
406
- else {
407
- inst.tpDiv.show((showAnim ? duration : null), postProcess);
408
- }
409
- if (!showAnim || !duration) { postProcess(); }
410
- if (inst.input.is(':visible') && !inst.input.is(':disabled')) { inst.input.focus(); }
411
- $.timepicker._curInst = inst;
412
- }
413
- },
414
-
415
- // This is an enhanced copy of the zIndex function of UI core 1.8.?? For backward compatibility.
416
- // Enhancement returns maximum zindex value discovered while traversing parent elements,
417
- // rather than the first zindex value found. Ensures the timepicker popup will be in front,
418
- // even in funky scenarios like non-jq dialog containers with large fixed zindex values and
419
- // nested zindex-influenced elements of their own.
420
- _getZIndex: function (target) {
421
- var elem = $(target);
422
- var maxValue = 0;
423
- var position, value;
424
- while (elem.length && elem[0] !== document) {
425
- position = elem.css("position");
426
- if (position === "absolute" || position === "relative" || position === "fixed") {
427
- value = parseInt(elem.css("zIndex"), 10);
428
- if (!isNaN(value) && value !== 0) {
429
- if (value > maxValue) { maxValue = value; }
430
- }
431
- }
432
- elem = elem.parent();
433
- }
434
-
435
- return maxValue;
436
- },
437
-
438
- /* Refresh the time picker
439
- @param target element - The target input field or inline container element. */
440
- _refreshTimepicker: function(target) {
441
- var inst = this._getInst(target);
442
- if (inst) {
443
- this._updateTimepicker(inst);
444
- }
445
- },
446
-
447
-
448
- /* Generate the time picker content. */
449
- _updateTimepicker: function (inst) {
450
- inst.tpDiv.empty().append(this._generateHTML(inst));
451
- this._rebindDialogEvents(inst);
452
-
453
- },
454
-
455
- _rebindDialogEvents: function (inst) {
456
- var borders = $.timepicker._getBorders(inst.tpDiv),
457
- self = this;
458
- inst.tpDiv
459
- .find('iframe.ui-timepicker-cover') // IE6- only
460
- .css({ left: -borders[0], top: -borders[1],
461
- width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
462
- })
463
- .end()
464
- // after the picker html is appended bind the click & double click events (faster in IE this way
465
- // then letting the browser interpret the inline events)
466
- // the binding for the minute cells also exists in _updateMinuteDisplay
467
- .find('.ui-timepicker-minute-cell')
468
- .unbind()
469
- .bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectMinutes, this))
470
- .bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectMinutes, this))
471
- .end()
472
- .find('.ui-timepicker-hour-cell')
473
- .unbind()
474
- .bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectHours, this))
475
- .bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectHours, this))
476
- .end()
477
- .find('.ui-timepicker td a')
478
- .unbind()
479
- .bind('mouseout', function () {
480
- $(this).removeClass('ui-state-hover');
481
- if (this.className.indexOf('ui-timepicker-prev') != -1) $(this).removeClass('ui-timepicker-prev-hover');
482
- if (this.className.indexOf('ui-timepicker-next') != -1) $(this).removeClass('ui-timepicker-next-hover');
483
- })
484
- .bind('mouseover', function () {
485
- if ( ! self._isDisabledTimepicker(inst.inline ? inst.tpDiv.parent()[0] : inst.input[0])) {
486
- $(this).parents('.ui-timepicker-calendar').find('a').removeClass('ui-state-hover');
487
- $(this).addClass('ui-state-hover');
488
- if (this.className.indexOf('ui-timepicker-prev') != -1) $(this).addClass('ui-timepicker-prev-hover');
489
- if (this.className.indexOf('ui-timepicker-next') != -1) $(this).addClass('ui-timepicker-next-hover');
490
- }
491
- })
492
- .end()
493
- .find('.' + this._dayOverClass + ' a')
494
- .trigger('mouseover')
495
- .end()
496
- .find('.ui-timepicker-now').bind("click", function(e) {
497
- $.timepicker.selectNow(e);
498
- }).end()
499
- .find('.ui-timepicker-deselect').bind("click",function(e) {
500
- $.timepicker.deselectTime(e);
501
- }).end()
502
- .find('.ui-timepicker-close').bind("click",function(e) {
503
- $.timepicker._hideTimepicker();
504
- }).end();
505
- },
506
-
507
- /* Generate the HTML for the current state of the time picker. */
508
- _generateHTML: function (inst) {
509
-
510
- var h, m, row, col, html, hoursHtml, minutesHtml = '',
511
- showPeriod = (this._get(inst, 'showPeriod') == true),
512
- showPeriodLabels = (this._get(inst, 'showPeriodLabels') == true),
513
- showLeadingZero = (this._get(inst, 'showLeadingZero') == true),
514
- showHours = (this._get(inst, 'showHours') == true),
515
- showMinutes = (this._get(inst, 'showMinutes') == true),
516
- amPmText = this._get(inst, 'amPmText'),
517
- rows = this._get(inst, 'rows'),
518
- amRows = 0,
519
- pmRows = 0,
520
- amItems = 0,
521
- pmItems = 0,
522
- amFirstRow = 0,
523
- pmFirstRow = 0,
524
- hours = Array(),
525
- hours_options = this._get(inst, 'hours'),
526
- hoursPerRow = null,
527
- hourCounter = 0,
528
- hourLabel = this._get(inst, 'hourText'),
529
- showCloseButton = this._get(inst, 'showCloseButton'),
530
- closeButtonText = this._get(inst, 'closeButtonText'),
531
- showNowButton = this._get(inst, 'showNowButton'),
532
- nowButtonText = this._get(inst, 'nowButtonText'),
533
- showDeselectButton = this._get(inst, 'showDeselectButton'),
534
- deselectButtonText = this._get(inst, 'deselectButtonText'),
535
- showButtonPanel = showCloseButton || showNowButton || showDeselectButton;
536
-
537
-
538
-
539
- // prepare all hours and minutes, makes it easier to distribute by rows
540
- for (h = hours_options.starts; h <= hours_options.ends; h++) {
541
- hours.push (h);
542
- }
543
- hoursPerRow = Math.ceil(hours.length / rows); // always round up
544
-
545
- if (showPeriodLabels) {
546
- for (hourCounter = 0; hourCounter < hours.length; hourCounter++) {
547
- if (hours[hourCounter] < 12) {
548
- amItems++;
549
- }
550
- else {
551
- pmItems++;
552
- }
553
- }
554
- hourCounter = 0;
555
-
556
- amRows = Math.floor(amItems / hours.length * rows);
557
- pmRows = Math.floor(pmItems / hours.length * rows);
558
-
559
- // assign the extra row to the period that is more densely populated
560
- if (rows != amRows + pmRows) {
561
- // Make sure: AM Has Items and either PM Does Not, AM has no rows yet, or AM is more dense
562
- if (amItems && (!pmItems || !amRows || (pmRows && amItems / amRows >= pmItems / pmRows))) {
563
- amRows++;
564
- } else {
565
- pmRows++;
566
- }
567
- }
568
- amFirstRow = Math.min(amRows, 1);
569
- pmFirstRow = amRows + 1;
570
-
571
- if (amRows == 0) {
572
- hoursPerRow = Math.ceil(pmItems / pmRows);
573
- } else if (pmRows == 0) {
574
- hoursPerRow = Math.ceil(amItems / amRows);
575
- } else {
576
- hoursPerRow = Math.ceil(Math.max(amItems / amRows, pmItems / pmRows));
577
- }
578
- }
579
-
580
-
581
- html = '<table class="ui-timepicker-table ui-widget-content ui-corner-all"><tr>';
582
-
583
- if (showHours) {
584
-
585
- html += '<td class="ui-timepicker-hours">' +
586
- '<div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
587
- hourLabel +
588
- '</div>' +
589
- '<table class="ui-timepicker">';
590
-
591
- for (row = 1; row <= rows; row++) {
592
- html += '<tr>';
593
- // AM
594
- if (row == amFirstRow && showPeriodLabels) {
595
- html += '<th rowspan="' + amRows.toString() + '" class="periods" scope="row">' + amPmText[0] + '</th>';
596
- }
597
- // PM
598
- if (row == pmFirstRow && showPeriodLabels) {
599
- html += '<th rowspan="' + pmRows.toString() + '" class="periods" scope="row">' + amPmText[1] + '</th>';
600
- }
601
- for (col = 1; col <= hoursPerRow; col++) {
602
- if (showPeriodLabels && row < pmFirstRow && hours[hourCounter] >= 12) {
603
- html += this._generateHTMLHourCell(inst, undefined, showPeriod, showLeadingZero);
604
- } else {
605
- html += this._generateHTMLHourCell(inst, hours[hourCounter], showPeriod, showLeadingZero);
606
- hourCounter++;
607
- }
608
- }
609
- html += '</tr>';
610
- }
611
- html += '</table>' + // Close the hours cells table
612
- '</td>'; // Close the Hour td
613
- }
614
-
615
- if (showMinutes) {
616
- html += '<td class="ui-timepicker-minutes">';
617
- html += this._generateHTMLMinutes(inst);
618
- html += '</td>';
619
- }
620
-
621
- html += '</tr>';
622
-
623
-
624
- if (showButtonPanel) {
625
- var buttonPanel = '<tr><td colspan="3"><div class="ui-timepicker-buttonpane ui-widget-content">';
626
- if (showNowButton) {
627
- buttonPanel += '<button type="button" class="ui-timepicker-now ui-state-default ui-corner-all" '
628
- + ' data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
629
- + nowButtonText + '</button>';
630
- }
631
- if (showDeselectButton) {
632
- buttonPanel += '<button type="button" class="ui-timepicker-deselect ui-state-default ui-corner-all" '
633
- + ' data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
634
- + deselectButtonText + '</button>';
635
- }
636
- if (showCloseButton) {
637
- buttonPanel += '<button type="button" class="ui-timepicker-close ui-state-default ui-corner-all" '
638
- + ' data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
639
- + closeButtonText + '</button>';
640
- }
641
-
642
- html += buttonPanel + '</div></td></tr>';
643
- }
644
- html += '</table>';
645
-
646
- return html;
647
- },
648
-
649
- /* Special function that update the minutes selection in currently visible timepicker
650
- * called on hour selection when onMinuteShow is defined */
651
- _updateMinuteDisplay: function (inst) {
652
- var newHtml = this._generateHTMLMinutes(inst);
653
- inst.tpDiv.find('td.ui-timepicker-minutes').html(newHtml);
654
- this._rebindDialogEvents(inst);
655
- // after the picker html is appended bind the click & double click events (faster in IE this way
656
- // then letting the browser interpret the inline events)
657
- // yes I know, duplicate code, sorry
658
- /* .find('.ui-timepicker-minute-cell')
659
- .bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectMinutes, this))
660
- .bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectMinutes, this));
661
- */
662
-
663
- },
664
-
665
- /*
666
- * Generate the minutes table
667
- * This is separated from the _generateHTML function because is can be called separately (when hours changes)
668
- */
669
- _generateHTMLMinutes: function (inst) {
670
-
671
- var m, row, html = '',
672
- rows = this._get(inst, 'rows'),
673
- minutes = Array(),
674
- minutes_options = this._get(inst, 'minutes'),
675
- minutesPerRow = null,
676
- minuteCounter = 0,
677
- showMinutesLeadingZero = (this._get(inst, 'showMinutesLeadingZero') == true),
678
- onMinuteShow = this._get(inst, 'onMinuteShow'),
679
- minuteLabel = this._get(inst, 'minuteText');
680
-
681
- if ( ! minutes_options.starts) {
682
- minutes_options.starts = 0;
683
- }
684
- if ( ! minutes_options.ends) {
685
- minutes_options.ends = 59;
686
- }
687
- for (m = minutes_options.starts; m <= minutes_options.ends; m += minutes_options.interval) {
688
- minutes.push(m);
689
- }
690
- minutesPerRow = Math.round(minutes.length / rows + 0.49); // always round up
691
-
692
- /*
693
- * The minutes table
694
- */
695
- // if currently selected minute is not enabled, we have a problem and need to select a new minute.
696
- if (onMinuteShow &&
697
- (onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours , inst.minutes]) == false) ) {
698
- // loop minutes and select first available
699
- for (minuteCounter = 0; minuteCounter < minutes.length; minuteCounter += 1) {
700
- m = minutes[minuteCounter];
701
- if (onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours, m])) {
702
- inst.minutes = m;
703
- break;
704
- }
705
- }
706
- }
707
-
708
-
709
-
710
- html += '<div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
711
- minuteLabel +
712
- '</div>' +
713
- '<table class="ui-timepicker">';
714
-
715
- minuteCounter = 0;
716
- for (row = 1; row <= rows; row++) {
717
- html += '<tr>';
718
- while (minuteCounter < row * minutesPerRow) {
719
- var m = minutes[minuteCounter];
720
- var displayText = '';
721
- if (m !== undefined ) {
722
- displayText = (m < 10) && showMinutesLeadingZero ? "0" + m.toString() : m.toString();
723
- }
724
- html += this._generateHTMLMinuteCell(inst, m, displayText);
725
- minuteCounter++;
726
- }
727
- html += '</tr>';
728
- }
729
-
730
- html += '</table>';
731
-
732
- return html;
733
- },
734
-
735
- /* Generate the content of a "Hour" cell */
736
- _generateHTMLHourCell: function (inst, hour, showPeriod, showLeadingZero) {
737
-
738
- var displayHour = hour;
739
- if ((hour > 12) && showPeriod) {
740
- displayHour = hour - 12;
741
- }
742
- if ((displayHour == 0) && showPeriod) {
743
- displayHour = 12;
744
- }
745
- if ((displayHour < 10) && showLeadingZero) {
746
- displayHour = '0' + displayHour;
747
- }
748
-
749
- var html = "";
750
- var enabled = true;
751
- var onHourShow = this._get(inst, 'onHourShow'); //custom callback
752
-
753
- if (hour == undefined) {
754
- html = '<td><span class="ui-state-default ui-state-disabled">&nbsp;</span></td>';
755
- return html;
756
- }
757
-
758
- if (onHourShow) {
759
- enabled = onHourShow.apply((inst.input ? inst.input[0] : null), [hour]);
760
- }
761
-
762
- if (enabled) {
763
- html = '<td class="ui-timepicker-hour-cell" data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-hour="' + hour.toString() + '">' +
764
- '<a class="ui-state-default ' +
765
- (hour == inst.hours ? 'ui-state-active' : '') +
766
- '">' +
767
- displayHour.toString() +
768
- '</a></td>';
769
- }
770
- else {
771
- html =
772
- '<td>' +
773
- '<span class="ui-state-default ui-state-disabled ' +
774
- (hour == inst.hours ? ' ui-state-active ' : ' ') +
775
- '">' +
776
- displayHour.toString() +
777
- '</span>' +
778
- '</td>';
779
- }
780
- return html;
781
- },
782
-
783
- /* Generate the content of a "Hour" cell */
784
- _generateHTMLMinuteCell: function (inst, minute, displayText) {
785
- var html = "";
786
- var enabled = true;
787
- var onMinuteShow = this._get(inst, 'onMinuteShow'); //custom callback
788
- if (onMinuteShow) {
789
- //NEW: 2011-02-03 we should give the hour as a parameter as well!
790
- enabled = onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours,minute]); //trigger callback
791
- }
792
-
793
- if (minute == undefined) {
794
- html = '<td><span class="ui-state-default ui-state-disabled">&nbsp;</span></td>';
795
- return html;
796
- }
797
-
798
- if (enabled) {
799
- html = '<td class="ui-timepicker-minute-cell" data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-minute="' + minute.toString() + '" >' +
800
- '<a class="ui-state-default ' +
801
- (minute == inst.minutes ? 'ui-state-active' : '') +
802
- '" >' +
803
- displayText +
804
- '</a></td>';
805
- }
806
- else {
807
-
808
- html = '<td>' +
809
- '<span class="ui-state-default ui-state-disabled" >' +
810
- displayText +
811
- '</span>' +
812
- '</td>';
813
- }
814
- return html;
815
- },
816
-
817
-
818
- /* Detach a timepicker from its control.
819
- @param target element - the target input field or division or span */
820
- _destroyTimepicker: function(target) {
821
- var $target = $(target);
822
- var inst = $.data(target, PROP_NAME);
823
- if (!$target.hasClass(this.markerClassName)) {
824
- return;
825
- }
826
- var nodeName = target.nodeName.toLowerCase();
827
- $.removeData(target, PROP_NAME);
828
- if (nodeName == 'input') {
829
- inst.append.remove();
830
- inst.trigger.remove();
831
- $target.removeClass(this.markerClassName)
832
- .unbind('focus.timepicker', this._showTimepicker)
833
- .unbind('click.timepicker', this._adjustZIndex);
834
- } else if (nodeName == 'div' || nodeName == 'span')
835
- $target.removeClass(this.markerClassName).empty();
836
- },
837
-
838
- /* Enable the date picker to a jQuery selection.
839
- @param target element - the target input field or division or span */
840
- _enableTimepicker: function(target) {
841
- var $target = $(target),
842
- target_id = $target.attr('id'),
843
- inst = $.data(target, PROP_NAME);
844
-
845
- if (!$target.hasClass(this.markerClassName)) {
846
- return;
847
- }
848
- var nodeName = target.nodeName.toLowerCase();
849
- if (nodeName == 'input') {
850
- target.disabled = false;
851
- var button = this._get(inst, 'button');
852
- $(button).removeClass('ui-state-disabled').disabled = false;
853
- inst.trigger.filter('button').
854
- each(function() { this.disabled = false; }).end();
855
- }
856
- else if (nodeName == 'div' || nodeName == 'span') {
857
- var inline = $target.children('.' + this._inlineClass);
858
- inline.children().removeClass('ui-state-disabled');
859
- inline.find('button').each(
860
- function() { this.disabled = false }
861
- )
862
- }
863
- this._disabledInputs = $.map(this._disabledInputs,
864
- function(value) { return (value == target_id ? null : value); }); // delete entry
865
- },
866
-
867
- /* Disable the time picker to a jQuery selection.
868
- @param target element - the target input field or division or span */
869
- _disableTimepicker: function(target) {
870
- var $target = $(target);
871
- var inst = $.data(target, PROP_NAME);
872
- if (!$target.hasClass(this.markerClassName)) {
873
- return;
874
- }
875
- var nodeName = target.nodeName.toLowerCase();
876
- if (nodeName == 'input') {
877
- var button = this._get(inst, 'button');
878
-
879
- $(button).addClass('ui-state-disabled').disabled = true;
880
- target.disabled = true;
881
-
882
- inst.trigger.filter('button').
883
- each(function() { this.disabled = true; }).end();
884
-
885
- }
886
- else if (nodeName == 'div' || nodeName == 'span') {
887
- var inline = $target.children('.' + this._inlineClass);
888
- inline.children().addClass('ui-state-disabled');
889
- inline.find('button').each(
890
- function() { this.disabled = true }
891
- )
892
-
893
- }
894
- this._disabledInputs = $.map(this._disabledInputs,
895
- function(value) { return (value == target ? null : value); }); // delete entry
896
- this._disabledInputs[this._disabledInputs.length] = $target.attr('id');
897
- },
898
-
899
- /* Is the first field in a jQuery collection disabled as a timepicker?
900
- @param target_id element - the target input field or division or span
901
- @return boolean - true if disabled, false if enabled */
902
- _isDisabledTimepicker: function (target_id) {
903
- if ( ! target_id) { return false; }
904
- for (var i = 0; i < this._disabledInputs.length; i++) {
905
- if (this._disabledInputs[i] == target_id) { return true; }
906
- }
907
- return false;
908
- },
909
-
910
- /* Check positioning to remain on screen. */
911
- _checkOffset: function (inst, offset, isFixed) {
912
- var tpWidth = inst.tpDiv.outerWidth();
913
- var tpHeight = inst.tpDiv.outerHeight();
914
- var inputWidth = inst.input ? inst.input.outerWidth() : 0;
915
- var inputHeight = inst.input ? inst.input.outerHeight() : 0;
916
- var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
917
- var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
918
-
919
- offset.left -= (this._get(inst, 'isRTL') ? (tpWidth - inputWidth) : 0);
920
- offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
921
- offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
922
-
923
- // now check if datepicker is showing outside window viewport - move to a better place if so.
924
- offset.left -= Math.min(offset.left, (offset.left + tpWidth > viewWidth && viewWidth > tpWidth) ?
925
- Math.abs(offset.left + tpWidth - viewWidth) : 0);
926
- offset.top -= Math.min(offset.top, (offset.top + tpHeight > viewHeight && viewHeight > tpHeight) ?
927
- Math.abs(tpHeight + inputHeight) : 0);
928
-
929
- return offset;
930
- },
931
-
932
- /* Find an object's position on the screen. */
933
- _findPos: function (obj) {
934
- var inst = this._getInst(obj);
935
- var isRTL = this._get(inst, 'isRTL');
936
- while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
937
- obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
938
- }
939
- var position = $(obj).offset();
940
- return [position.left, position.top];
941
- },
942
-
943
- /* Retrieve the size of left and top borders for an element.
944
- @param elem (jQuery object) the element of interest
945
- @return (number[2]) the left and top borders */
946
- _getBorders: function (elem) {
947
- var convert = function (value) {
948
- return { thin: 1, medium: 2, thick: 3}[value] || value;
949
- };
950
- return [parseFloat(convert(elem.css('border-left-width'))),
951
- parseFloat(convert(elem.css('border-top-width')))];
952
- },
953
-
954
-
955
- /* Close time picker if clicked elsewhere. */
956
- _checkExternalClick: function (event) {
957
- if (!$.timepicker._curInst) { return; }
958
- var $target = $(event.target);
959
- if ($target[0].id != $.timepicker._mainDivId &&
960
- $target.parents('#' + $.timepicker._mainDivId).length == 0 &&
961
- !$target.hasClass($.timepicker.markerClassName) &&
962
- !$target.hasClass($.timepicker._triggerClass) &&
963
- $.timepicker._timepickerShowing && !($.timepicker._inDialog && $.blockUI))
964
- $.timepicker._hideTimepicker();
965
- },
966
-
967
- /* Hide the time picker from view.
968
- @param input element - the input field attached to the time picker */
969
- _hideTimepicker: function (input) {
970
- var inst = this._curInst;
971
- if (!inst || (input && inst != $.data(input, PROP_NAME))) { return; }
972
- if (this._timepickerShowing) {
973
- var showAnim = this._get(inst, 'showAnim');
974
- var duration = this._get(inst, 'duration');
975
- var postProcess = function () {
976
- $.timepicker._tidyDialog(inst);
977
- this._curInst = null;
978
- };
979
- if ($.effects && $.effects[showAnim]) {
980
- inst.tpDiv.hide(showAnim, $.timepicker._get(inst, 'showOptions'), duration, postProcess);
981
- }
982
- else {
983
- inst.tpDiv[(showAnim == 'slideDown' ? 'slideUp' :
984
- (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
985
- }
986
- if (!showAnim) { postProcess(); }
987
-
988
- this._timepickerShowing = false;
989
-
990
- this._lastInput = null;
991
- if (this._inDialog) {
992
- this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
993
- if ($.blockUI) {
994
- $.unblockUI();
995
- $('body').append(this.tpDiv);
996
- }
997
- }
998
- this._inDialog = false;
999
-
1000
- var onClose = this._get(inst, 'onClose');
1001
- if (onClose) {
1002
- onClose.apply(
1003
- (inst.input ? inst.input[0] : null),
1004
- [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
1005
- }
1006
-
1007
- }
1008
- },
1009
-
1010
-
1011
-
1012
- /* Tidy up after a dialog display. */
1013
- _tidyDialog: function (inst) {
1014
- inst.tpDiv.removeClass(this._dialogClass).unbind('.ui-timepicker');
1015
- },
1016
-
1017
- /* Retrieve the instance data for the target control.
1018
- @param target element - the target input field or division or span
1019
- @return object - the associated instance data
1020
- @throws error if a jQuery problem getting data */
1021
- _getInst: function (target) {
1022
- try {
1023
- return $.data(target, PROP_NAME);
1024
- }
1025
- catch (err) {
1026
- throw 'Missing instance data for this timepicker';
1027
- }
1028
- },
1029
-
1030
- /* Get a setting value, defaulting if necessary. */
1031
- _get: function (inst, name) {
1032
- return inst.settings[name] !== undefined ?
1033
- inst.settings[name] : this._defaults[name];
1034
- },
1035
-
1036
- /* Parse existing time and initialise time picker. */
1037
- _setTimeFromField: function (inst) {
1038
- if (inst.input.val() == inst.lastVal) { return; }
1039
- var defaultTime = this._get(inst, 'defaultTime');
1040
-
1041
- var timeToParse = defaultTime == 'now' ? this._getCurrentTimeRounded(inst) : defaultTime;
1042
- if ((inst.inline == false) && (inst.input.val() != '')) { timeToParse = inst.input.val() }
1043
-
1044
- if (timeToParse instanceof Date) {
1045
- inst.hours = timeToParse.getHours();
1046
- inst.minutes = timeToParse.getMinutes();
1047
- } else {
1048
- var timeVal = inst.lastVal = timeToParse;
1049
- if (timeToParse == '') {
1050
- inst.hours = -1;
1051
- inst.minutes = -1;
1052
- } else {
1053
- var time = this.parseTime(inst, timeVal);
1054
- inst.hours = time.hours;
1055
- inst.minutes = time.minutes;
1056
- }
1057
- }
1058
-
1059
-
1060
- $.timepicker._updateTimepicker(inst);
1061
- },
1062
-
1063
- /* Update or retrieve the settings for an existing time picker.
1064
- @param target element - the target input field or division or span
1065
- @param name object - the new settings to update or
1066
- string - the name of the setting to change or retrieve,
1067
- when retrieving also 'all' for all instance settings or
1068
- 'defaults' for all global defaults
1069
- @param value any - the new value for the setting
1070
- (omit if above is an object or to retrieve a value) */
1071
- _optionTimepicker: function(target, name, value) {
1072
- var inst = this._getInst(target);
1073
- if (arguments.length == 2 && typeof name == 'string') {
1074
- return (name == 'defaults' ? $.extend({}, $.timepicker._defaults) :
1075
- (inst ? (name == 'all' ? $.extend({}, inst.settings) :
1076
- this._get(inst, name)) : null));
1077
- }
1078
- var settings = name || {};
1079
- if (typeof name == 'string') {
1080
- settings = {};
1081
- settings[name] = value;
1082
- }
1083
- if (inst) {
1084
- if (this._curInst == inst) {
1085
- this._hideTimepicker();
1086
- }
1087
- extendRemove(inst.settings, settings);
1088
- this._updateTimepicker(inst);
1089
- }
1090
- },
1091
-
1092
-
1093
- /* Set the time for a jQuery selection.
1094
- @param target element - the target input field or division or span
1095
- @param time String - the new time */
1096
- _setTimeTimepicker: function(target, time) {
1097
- var inst = this._getInst(target);
1098
- if (inst) {
1099
- this._setTime(inst, time);
1100
- this._updateTimepicker(inst);
1101
- this._updateAlternate(inst, time);
1102
- }
1103
- },
1104
-
1105
- /* Set the time directly. */
1106
- _setTime: function(inst, time, noChange) {
1107
- var origHours = inst.hours;
1108
- var origMinutes = inst.minutes;
1109
- if (time instanceof Date) {
1110
- inst.hours = time.getHours();
1111
- inst.minutes = time.getMinutes();
1112
- } else {
1113
- var time = this.parseTime(inst, time);
1114
- inst.hours = time.hours;
1115
- inst.minutes = time.minutes;
1116
- }
1117
-
1118
- if ((origHours != inst.hours || origMinutes != inst.minutes) && !noChange) {
1119
- inst.input.trigger('change');
1120
- }
1121
- this._updateTimepicker(inst);
1122
- this._updateSelectedValue(inst);
1123
- },
1124
-
1125
- /* Return the current time, ready to be parsed, rounded to the closest 5 minute */
1126
- _getCurrentTimeRounded: function (inst) {
1127
- var currentTime = new Date(),
1128
- currentMinutes = currentTime.getMinutes(),
1129
- // round to closest 5
1130
- adjustedMinutes = Math.round( currentMinutes / 5 ) * 5;
1131
- currentTime.setMinutes(adjustedMinutes);
1132
- return currentTime;
1133
- },
1134
-
1135
- /*
1136
- * Parse a time string into hours and minutes
1137
- */
1138
- parseTime: function (inst, timeVal) {
1139
- var retVal = new Object();
1140
- retVal.hours = -1;
1141
- retVal.minutes = -1;
1142
-
1143
- if(!timeVal)
1144
- return '';
1145
-
1146
- var timeSeparator = this._get(inst, 'timeSeparator'),
1147
- amPmText = this._get(inst, 'amPmText'),
1148
- showHours = this._get(inst, 'showHours'),
1149
- showMinutes = this._get(inst, 'showMinutes'),
1150
- optionalMinutes = this._get(inst, 'optionalMinutes'),
1151
- showPeriod = (this._get(inst, 'showPeriod') == true),
1152
- p = timeVal.indexOf(timeSeparator);
1153
-
1154
- // check if time separator found
1155
- if (p != -1) {
1156
- retVal.hours = parseInt(timeVal.substr(0, p), 10);
1157
- retVal.minutes = parseInt(timeVal.substr(p + 1), 10);
1158
- }
1159
- // check for hours only
1160
- else if ( (showHours) && ( !showMinutes || optionalMinutes ) ) {
1161
- retVal.hours = parseInt(timeVal, 10);
1162
- }
1163
- // check for minutes only
1164
- else if ( ( ! showHours) && (showMinutes) ) {
1165
- retVal.minutes = parseInt(timeVal, 10);
1166
- }
1167
-
1168
- if (showHours) {
1169
- var timeValUpper = timeVal.toUpperCase();
1170
- if ((retVal.hours < 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[1].toUpperCase()) != -1)) {
1171
- retVal.hours += 12;
1172
- }
1173
- // fix for 12 AM
1174
- if ((retVal.hours == 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[0].toUpperCase()) != -1)) {
1175
- retVal.hours = 0;
1176
- }
1177
- }
1178
-
1179
- return retVal;
1180
- },
1181
-
1182
- selectNow: function(event) {
1183
- var id = $(event.target).attr("data-timepicker-instance-id"),
1184
- $target = $(id),
1185
- inst = this._getInst($target[0]);
1186
- //if (!inst || (input && inst != $.data(input, PROP_NAME))) { return; }
1187
- var currentTime = new Date();
1188
- inst.hours = currentTime.getHours();
1189
- inst.minutes = currentTime.getMinutes();
1190
- this._updateSelectedValue(inst);
1191
- this._updateTimepicker(inst);
1192
- this._hideTimepicker();
1193
- },
1194
-
1195
- deselectTime: function(event) {
1196
- var id = $(event.target).attr("data-timepicker-instance-id"),
1197
- $target = $(id),
1198
- inst = this._getInst($target[0]);
1199
- inst.hours = -1;
1200
- inst.minutes = -1;
1201
- this._updateSelectedValue(inst);
1202
- this._hideTimepicker();
1203
- },
1204
-
1205
-
1206
- selectHours: function (event) {
1207
- var $td = $(event.currentTarget),
1208
- id = $td.attr("data-timepicker-instance-id"),
1209
- newHours = parseInt($td.attr("data-hour")),
1210
- fromDoubleClick = event.data.fromDoubleClick,
1211
- $target = $(id),
1212
- inst = this._getInst($target[0]),
1213
- showMinutes = (this._get(inst, 'showMinutes') == true);
1214
-
1215
- // don't select if disabled
1216
- if ( $.timepicker._isDisabledTimepicker($target.attr('id')) ) { return false }
1217
-
1218
- $td.parents('.ui-timepicker-hours:first').find('a').removeClass('ui-state-active');
1219
- $td.children('a').addClass('ui-state-active');
1220
- inst.hours = newHours;
1221
-
1222
- // added for onMinuteShow callback
1223
- var onMinuteShow = this._get(inst, 'onMinuteShow');
1224
- if (onMinuteShow) {
1225
- // this will trigger a callback on selected hour to make sure selected minute is allowed.
1226
- this._updateMinuteDisplay(inst);
1227
- }
1228
-
1229
- this._updateSelectedValue(inst);
1230
-
1231
- inst._hoursClicked = true;
1232
- if ((inst._minutesClicked) || (fromDoubleClick) || (showMinutes == false)) {
1233
- $.timepicker._hideTimepicker();
1234
- }
1235
- // return false because if used inline, prevent the url to change to a hashtag
1236
- return false;
1237
- },
1238
-
1239
- selectMinutes: function (event) {
1240
- var $td = $(event.currentTarget),
1241
- id = $td.attr("data-timepicker-instance-id"),
1242
- newMinutes = parseInt($td.attr("data-minute")),
1243
- fromDoubleClick = event.data.fromDoubleClick,
1244
- $target = $(id),
1245
- inst = this._getInst($target[0]),
1246
- showHours = (this._get(inst, 'showHours') == true);
1247
-
1248
- // don't select if disabled
1249
- if ( $.timepicker._isDisabledTimepicker($target.attr('id')) ) { return false }
1250
-
1251
- $td.parents('.ui-timepicker-minutes:first').find('a').removeClass('ui-state-active');
1252
- $td.children('a').addClass('ui-state-active');
1253
-
1254
- inst.minutes = newMinutes;
1255
- this._updateSelectedValue(inst);
1256
-
1257
- inst._minutesClicked = true;
1258
- if ((inst._hoursClicked) || (fromDoubleClick) || (showHours == false)) {
1259
- $.timepicker._hideTimepicker();
1260
- // return false because if used inline, prevent the url to change to a hashtag
1261
- return false;
1262
- }
1263
-
1264
- // return false because if used inline, prevent the url to change to a hashtag
1265
- return false;
1266
- },
1267
-
1268
- _updateSelectedValue: function (inst) {
1269
- var newTime = this._getParsedTime(inst);
1270
- if (inst.input) {
1271
- inst.input.val(newTime);
1272
- inst.input.trigger('change');
1273
- }
1274
- var onSelect = this._get(inst, 'onSelect');
1275
- if (onSelect) { onSelect.apply((inst.input ? inst.input[0] : null), [newTime, inst]); } // trigger custom callback
1276
- this._updateAlternate(inst, newTime);
1277
- return newTime;
1278
- },
1279
-
1280
- /* this function process selected time and return it parsed according to instance options */
1281
- _getParsedTime: function(inst) {
1282
-
1283
- if (inst.hours == -1 && inst.minutes == -1) {
1284
- return '';
1285
- }
1286
-
1287
- // default to 0 AM if hours is not valid
1288
- if ((inst.hours < inst.hours.starts) || (inst.hours > inst.hours.ends )) { inst.hours = 0; }
1289
- // default to 0 minutes if minute is not valid
1290
- if ((inst.minutes < inst.minutes.starts) || (inst.minutes > inst.minutes.ends)) { inst.minutes = 0; }
1291
-
1292
- var period = "",
1293
- showPeriod = (this._get(inst, 'showPeriod') == true),
1294
- showLeadingZero = (this._get(inst, 'showLeadingZero') == true),
1295
- showHours = (this._get(inst, 'showHours') == true),
1296
- showMinutes = (this._get(inst, 'showMinutes') == true),
1297
- optionalMinutes = (this._get(inst, 'optionalMinutes') == true),
1298
- amPmText = this._get(inst, 'amPmText'),
1299
- selectedHours = inst.hours ? inst.hours : 0,
1300
- selectedMinutes = inst.minutes ? inst.minutes : 0,
1301
- displayHours = selectedHours ? selectedHours : 0,
1302
- parsedTime = '';
1303
-
1304
- // fix some display problem when hours or minutes are not selected yet
1305
- if (displayHours == -1) { displayHours = 0 }
1306
- if (selectedMinutes == -1) { selectedMinutes = 0 }
1307
-
1308
- if (showPeriod) {
1309
- if (inst.hours == 0) {
1310
- displayHours = 12;
1311
- }
1312
- if (inst.hours < 12) {
1313
- period = amPmText[0];
1314
- }
1315
- else {
1316
- period = amPmText[1];
1317
- if (displayHours > 12) {
1318
- displayHours -= 12;
1319
- }
1320
- }
1321
- }
1322
-
1323
- var h = displayHours.toString();
1324
- if (showLeadingZero && (displayHours < 10)) { h = '0' + h; }
1325
-
1326
- var m = selectedMinutes.toString();
1327
- if (selectedMinutes < 10) { m = '0' + m; }
1328
-
1329
- if (showHours) {
1330
- parsedTime += h;
1331
- }
1332
- if (showHours && showMinutes && (!optionalMinutes || m != 0)) {
1333
- parsedTime += this._get(inst, 'timeSeparator');
1334
- }
1335
- if (showMinutes && (!optionalMinutes || m != 0)) {
1336
- parsedTime += m;
1337
- }
1338
- if (showHours) {
1339
- if (period.length > 0) { parsedTime += this._get(inst, 'periodSeparator') + period; }
1340
- }
1341
-
1342
- return parsedTime;
1343
- },
1344
-
1345
- /* Update any alternate field to synchronise with the main field. */
1346
- _updateAlternate: function(inst, newTime) {
1347
- var altField = this._get(inst, 'altField');
1348
- if (altField) { // update alternate field too
1349
- $(altField).each(function(i,e) {
1350
- $(e).val(newTime);
1351
- });
1352
- }
1353
- },
1354
-
1355
- _getTimeAsDateTimepicker: function(input) {
1356
- var inst = this._getInst(input);
1357
- if (inst.hours == -1 && inst.minutes == -1) {
1358
- return '';
1359
- }
1360
-
1361
- // default to 0 AM if hours is not valid
1362
- if ((inst.hours < inst.hours.starts) || (inst.hours > inst.hours.ends )) { inst.hours = 0; }
1363
- // default to 0 minutes if minute is not valid
1364
- if ((inst.minutes < inst.minutes.starts) || (inst.minutes > inst.minutes.ends)) { inst.minutes = 0; }
1365
-
1366
- return new Date(0, 0, 0, inst.hours, inst.minutes, 0);
1367
- },
1368
- /* This might look unused but it's called by the $.fn.timepicker function with param getTime */
1369
- /* added v 0.2.3 - gitHub issue #5 - Thanks edanuff */
1370
- _getTimeTimepicker : function(input) {
1371
- var inst = this._getInst(input);
1372
- return this._getParsedTime(inst);
1373
- },
1374
- _getHourTimepicker: function(input) {
1375
- var inst = this._getInst(input);
1376
- if ( inst == undefined) { return -1; }
1377
- return inst.hours;
1378
- },
1379
- _getMinuteTimepicker: function(input) {
1380
- var inst= this._getInst(input);
1381
- if ( inst == undefined) { return -1; }
1382
- return inst.minutes;
1383
- }
1384
-
1385
- });
1386
-
1387
-
1388
-
1389
- /* Invoke the timepicker functionality.
1390
- @param options string - a command, optionally followed by additional parameters or
1391
- Object - settings for attaching new timepicker functionality
1392
- @return jQuery object */
1393
- $.fn.timepicker = function (options) {
1394
-
1395
- /* Initialise the time picker. */
1396
- if (!$.timepicker.initialized) {
1397
- $(document).mousedown($.timepicker._checkExternalClick).
1398
- find('body').append($.timepicker.tpDiv);
1399
- $.timepicker.initialized = true;
1400
- }
1401
-
1402
-
1403
-
1404
- var otherArgs = Array.prototype.slice.call(arguments, 1);
1405
- if (typeof options == 'string' && (options == 'getTime' || options == 'getTimeAsDate' || options == 'getHour' || options == 'getMinute' ))
1406
- return $.timepicker['_' + options + 'Timepicker'].
1407
- apply($.timepicker, [this[0]].concat(otherArgs));
1408
- if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
1409
- return $.timepicker['_' + options + 'Timepicker'].
1410
- apply($.timepicker, [this[0]].concat(otherArgs));
1411
- return this.each(function () {
1412
- typeof options == 'string' ?
1413
- $.timepicker['_' + options + 'Timepicker'].
1414
- apply($.timepicker, [this].concat(otherArgs)) :
1415
- $.timepicker._attachTimepicker(this, options);
1416
- });
1417
- };
1418
-
1419
- /* jQuery extend now ignores nulls! */
1420
- function extendRemove(target, props) {
1421
- $.extend(target, props);
1422
- for (var name in props)
1423
- if (props[name] == null || props[name] == undefined)
1424
- target[name] = props[name];
1425
- return target;
1426
- };
1427
-
1428
- $.timepicker = new Timepicker(); // singleton instance
1429
- $.timepicker.initialized = false;
1430
- $.timepicker.uuid = new Date().getTime();
1431
- $.timepicker.version = "0.3.2";
1432
-
1433
- // Workaround for #4055
1434
- // Add another global to avoid noConflict issues with inline event handlers
1435
- window['TP_jQuery_' + tpuuid] = $;
1436
-
1437
- })(jQuery);