zebra-datepicker-rails 1.9.5 → 1.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,107 +1,206 @@
1
- /*
2
-
3
- Zebra_DatePicker: a lightweight jQuery date picker plugin
4
-
5
- Metalic Theme
6
-
7
- copyright (c) 2011 - 2014 Stefan Gabos
8
- http://stefangabos.ro/jquery/zebra-datepicker/
9
-
10
- */
1
+ .Zebra_DatePicker {
2
+ background: #373737;
3
+ border-radius: 4px;
4
+ box-shadow: 0px 0px 10px #888;
5
+ color: #fff;
6
+ font: 13px Tahoma, Arial, Helvetica, sans-serif;
7
+ padding: 3px 3px;
8
+ position: absolute;
9
+ display: table;
10
+ z-index: 1200;
11
+ }
11
12
 
12
13
  .Zebra_DatePicker *,
13
14
  .Zebra_DatePicker *:after,
14
- .Zebra_DatePicker *:before { -moz-box-sizing: content-box !important; -webkit-box-sizing: content-box !important; box-sizing: content-box !important }
15
-
16
- .Zebra_DatePicker { position: absolute; background: #373737; border: 3px solid #373737; z-index: 1200; font-family: Geneva, 'Lucida Sans', 'Lucida Grande', 'Lucida Sans Unicode', Verdana, sans-serif; font-size: 13px; top: 0 }
17
-
18
- .Zebra_DatePicker * { margin: 0; padding: 0; color: #666; background: transparent; border: none }
19
-
20
- /* = GLOBALS
21
- ----------------------------------------------------------------------------------------------------------------------*/
22
- .Zebra_DatePicker table { border-collapse: collapse; border-spacing: 0; width: auto; table-layout: auto; }
23
-
24
- .Zebra_DatePicker td,
25
- .Zebra_DatePicker th { text-align: center; padding: 5px 0 }
26
-
27
- .Zebra_DatePicker td { cursor: pointer }
28
-
29
- .Zebra_DatePicker .dp_daypicker,
30
- .Zebra_DatePicker .dp_monthpicker,
31
- .Zebra_DatePicker .dp_yearpicker { margin-top: 3px }
15
+ .Zebra_DatePicker *:before {
16
+ box-sizing: content-box !important;
17
+ }
18
+
19
+ .Zebra_DatePicker * {
20
+ padding: 0;
21
+ }
22
+
23
+ .Zebra_DatePicker table {
24
+ border-collapse: collapse;
25
+ border-radius: 4px;
26
+ border-spacing: 0;
27
+ width: 100%;
28
+ }
29
+
30
+ .Zebra_DatePicker th, .Zebra_DatePicker td {
31
+ padding: 5px;
32
+ cursor: pointer;
33
+ text-align: center;
34
+ min-width: 25px;
35
+ width: 25px;
36
+ }
37
+
38
+ .Zebra_DatePicker .dp_body th, .Zebra_DatePicker .dp_body td {
39
+ border: 1px solid #bbb;
40
+ }
41
+
42
+ .Zebra_DatePicker .dp_body th:first-child, .Zebra_DatePicker .dp_body td:first-child {
43
+ border-left: none;
44
+ }
45
+
46
+ .Zebra_DatePicker .dp_body th:last-child, .Zebra_DatePicker .dp_body td:last-child {
47
+ border-right: none;
48
+ }
49
+
50
+ .Zebra_DatePicker .dp_body tr:first-child th,
51
+ .Zebra_DatePicker .dp_body tr:first-child td {
52
+ border-top: none;
53
+ }
54
+
55
+ .Zebra_DatePicker .dp_body tr:last-child th,
56
+ .Zebra_DatePicker .dp_body tr:last-child td {
57
+ border-bottom: none;
58
+ }
59
+
60
+ .Zebra_DatePicker .dp_body td {
61
+ background: #dedede;
62
+ color: #666;
63
+ }
64
+
65
+ .Zebra_DatePicker .dp_body .dp_weekend {
66
+ background: #d1d1d1;
67
+ }
68
+
69
+ .Zebra_DatePicker .dp_body .dp_not_in_month {
70
+ background: #ebebeb;
71
+ }
72
+
73
+ .Zebra_DatePicker .dp_body .dp_current {
74
+ color: #e26261;
75
+ }
76
+
77
+ .Zebra_DatePicker .dp_body .dp_selected {
78
+ background: #e26262;
79
+ color: #fff;
80
+ }
81
+
82
+ .Zebra_DatePicker .dp_body .dp_disabled {
83
+ background: #ececec;
84
+ color: #ccc;
85
+ cursor: text;
86
+ }
87
+
88
+ .Zebra_DatePicker .dp_body .dp_disabled.dp_current {
89
+ color: #f6cdcd;
90
+ }
91
+
92
+ .Zebra_DatePicker .dp_body .dp_hover {
93
+ color: #fff;
94
+ background: #67aabb;
95
+ }
96
+
97
+ .Zebra_DatePicker .dp_body .dp_hover.dp_time_control {
98
+ background-color: #5d5d5d;
99
+ }
32
100
 
33
- .Zebra_DatePicker .dp_daypicker td,
34
- .Zebra_DatePicker .dp_daypicker th,
35
101
  .Zebra_DatePicker .dp_monthpicker td,
36
- .Zebra_DatePicker .dp_yearpicker td { width: 30px; border: 1px solid #BBB; background: #DEDEDE asset-url('zebra-datepicker/metallic/default-date.png') repeat-x top; color: #666 }
37
-
38
- .Zebra_DatePicker,
39
- .Zebra_DatePicker .dp_header .dp_hover,
40
- .Zebra_DatePicker .dp_footer .dp_hover { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px }
41
-
42
- /* = VISIBLE/HIDDEN STATES (USE TRANSITIONS FOR EFFECTS)
43
- ----------------------------------------------------------------------------------------------------------------------*/
44
- .Zebra_DatePicker.dp_visible { visibility: visible; filter: alpha(opacity=100); -khtml-opacity: 1; -moz-opacity: 1; opacity: 1; transition: opacity 0.2s ease-in-out }
45
- .Zebra_DatePicker.dp_hidden { visibility: hidden; filter: alpha(opacity=0); -khtml-opacity: 0; -moz-opacity: 0; opacity: 0 }
46
-
47
- /* = HEADER
48
- ----------------------------------------------------------------------------------------------------------------------*/
49
- .Zebra_DatePicker .dp_header td { color: #E0E0E0 }
50
-
51
- .Zebra_DatePicker .dp_header .dp_previous,
52
- .Zebra_DatePicker .dp_header .dp_next { width: 30px }
53
-
54
- .Zebra_DatePicker .dp_header .dp_caption { font-weight: bold }
55
- .Zebra_DatePicker .dp_header .dp_hover { background: #67AABB; color: #FFF }
56
-
57
- /* = DATEPICKER
58
- ----------------------------------------------------------------------------------------------------------------------*/
59
- .Zebra_DatePicker td.dp_week_number,
60
- .Zebra_DatePicker .dp_daypicker th { background: #F1F1F1; font-size: 9px; padding-top: 7px }
61
-
62
- .Zebra_DatePicker td.dp_weekend_disabled,
63
- .Zebra_DatePicker td.dp_not_in_month,
64
- .Zebra_DatePicker td.dp_not_in_month_selectable { background: #ECECEC asset-url('zebra-datepicker/metallic/disabled-date.png'); color: #CCC; cursor: default }
65
- .Zebra_DatePicker td.dp_not_in_month_selectable { cursor: pointer }
66
-
67
- .Zebra_DatePicker td.dp_weekend { background: #DEDEDE asset-url('zebra-datepicker/metallic/default-date.png') repeat-x top; color: #666 }
68
-
69
- .Zebra_DatePicker td.dp_selected { background: #E26262; color: #E0E0E0 !important }
70
-
71
- /* = MONTHPICKER
72
- ----------------------------------------------------------------------------------------------------------------------*/
73
- .Zebra_DatePicker .dp_monthpicker td { width: 33% }
74
-
75
- /* = YEARPICKER
76
- ----------------------------------------------------------------------------------------------------------------------*/
77
- .Zebra_DatePicker .dp_yearpicker td { width: 33% }
78
-
79
- /* = FOOTER
80
- ----------------------------------------------------------------------------------------------------------------------*/
81
- .Zebra_DatePicker .dp_footer { margin-top: 3px }
82
- .Zebra_DatePicker .dp_footer .dp_hover { background: #67AABB; color: #FFF }
83
-
84
- /* = SELECT CURRENT DAY
85
- ----------------------------------------------------------------------------------------------------------------------*/
86
- .Zebra_DatePicker .dp_today { color: #E0E0E0; padding: 3px }
87
-
88
- /* = CLEAR DATE
89
- ----------------------------------------------------------------------------------------------------------------------*/
90
- .Zebra_DatePicker .dp_clear { color: #E0E0E0; padding: 3px }
91
-
92
- /* = SOME MORE GLOBALS (MUST BE LAST IN ORDER TO OVERWRITE PRESIOUS PROPERTIES)
93
- ----------------------------------------------------------------------------------------------------------------------*/
94
- .Zebra_DatePicker td.dp_current { color: #E26261 }
95
- .Zebra_DatePicker td.dp_disabled_current { color: #E38585 }
96
- .Zebra_DatePicker td.dp_hover { background: #67AABB asset-url('zebra-datepicker/metallic/selected-date.png') repeat-x top; color: #FFF }
97
- .Zebra_DatePicker td.dp_disabled { background: #ECECEC asset-url('zebra-datepicker/metallic/disabled-date.png') repeat-x top; color: #DDD; cursor: default }
98
-
99
- /* = ICON
100
- ----------------------------------------------------------------------------------------------------------------------*/
101
- button.Zebra_DatePicker_Icon { display: block; position: absolute; width: 16px; height: 16px; background: asset-url('zebra-datepicker/calendar.png') no-repeat left top; text-indent: -9000px; border: none; cursor: pointer; padding: 0; line-height: 0; vertical-align: top }
102
- button.Zebra_DatePicker_Icon_Disabled { background-image: asset-url('zebra-datepicker/calendar-disabled.png') }
103
-
104
- /* don't set vertical margins! */
105
- button.Zebra_DatePicker_Icon { margin: 0 0 0 3px }
106
- button.Zebra_DatePicker_Icon_Inside_Right { margin: 0 3px 0 0 }
107
- button.Zebra_DatePicker_Icon_Inside_Left { margin: 0 0 0 3px }
102
+ .Zebra_DatePicker .dp_yearpicker td,
103
+ .Zebra_DatePicker .dp_timepicker td {
104
+ width: 33.3333%;
105
+ }
106
+
107
+ .Zebra_DatePicker .dp_timepicker .dp_disabled {
108
+ border: none;
109
+ color: #666;
110
+ font-size: 39px;
111
+ font-weight: bold;
112
+ }
113
+
114
+ .Zebra_DatePicker .dp_time_separator div {
115
+ position: relative;
116
+ }
117
+
118
+ .Zebra_DatePicker .dp_time_separator div:after {
119
+ content: ":";
120
+ color: 1px solid #bbb;
121
+ font-size: 37px;
122
+ left: 100%;
123
+ position: absolute;
124
+ z-index: 1;
125
+ }
126
+
127
+ .Zebra_DatePicker .dp_header {
128
+ margin-bottom: 3px;
129
+ }
130
+
131
+ .Zebra_DatePicker .dp_footer {
132
+ margin-top: 3px;
133
+ }
134
+
135
+ .Zebra_DatePicker .dp_footer .dp_icon {
136
+ width: 50%;
137
+ }
138
+
139
+ .Zebra_DatePicker .dp_actions td {
140
+ border-radius: 4px;
141
+ }
142
+
143
+ .Zebra_DatePicker .dp_actions .dp_caption {
144
+ font-weight: bold;
145
+ width: 100%;
146
+ }
147
+
148
+ .Zebra_DatePicker .dp_actions .dp_hover {
149
+ background-color: #5d5d5d;
150
+ }
151
+
152
+ .Zebra_DatePicker .dp_daypicker th {
153
+ background: #f1f1f1;
154
+ color: #666;
155
+ cursor: text;
156
+ font-weight: bold;
157
+ }
158
+
159
+ .Zebra_DatePicker.dp_hidden {
160
+ display: none;
161
+ }
162
+
163
+ .Zebra_DatePicker .dp_icon {
164
+ height: 16px;
165
+ background-image: asset-url("zebra-datepicker/metallic/icons.png");
166
+ background-repeat: no-repeat;
167
+ }
168
+
169
+ .Zebra_DatePicker .dp_icon.dp_confirm {
170
+ background-position: center -123px;
171
+ }
172
+
173
+ .Zebra_DatePicker .dp_icon.dp_view_toggler {
174
+ background-position: center -91px;
175
+ }
176
+
177
+ .Zebra_DatePicker .dp_icon.dp_view_toggler.dp_calendar {
178
+ background-position: center -59px;
179
+ }
180
+
181
+ button.Zebra_DatePicker_Icon {
182
+ background: asset-url("zebra-datepicker/metallic/icons.png") no-repeat center top;
183
+ border: none;
184
+ cursor: pointer;
185
+ display: block;
186
+ height: 16px;
187
+ line-height: 0;
188
+ margin: 0 0 0 3px;
189
+ padding: 0;
190
+ position: absolute;
191
+ text-indent: -9000px;
192
+ width: 16px;
193
+ }
194
+
195
+ button.Zebra_DatePicker_Icon.Zebra_DatePicker_Icon_Disabled {
196
+ background-position: center -32px;
197
+ cursor: default;
198
+ }
199
+
200
+ button.Zebra_DatePicker_Icon.Zebra_DatePicker_Icon_Inside_Right {
201
+ margin: 0 3px 0 0;
202
+ }
203
+
204
+ button.Zebra_DatePicker_Icon.Zebra_DatePicker_Icon_Inside_Left {
205
+ margin: 0 0 0 3px;
206
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zebra-datepicker-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.5
4
+ version: 1.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcus Derencius
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-13 00:00:00.000000000 Z
11
+ date: 2018-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -83,15 +83,11 @@ files:
83
83
  - lib/zebra-datepicker-rails/engine.rb
84
84
  - lib/zebra-datepicker-rails/railtie.rb
85
85
  - lib/zebra-datepicker-rails/version.rb
86
- - vendor/assets/images/zebra-datepicker/calendar-disabled.png
87
- - vendor/assets/images/zebra-datepicker/calendar.png
88
- - vendor/assets/images/zebra-datepicker/metallic/default-date.png
89
- - vendor/assets/images/zebra-datepicker/metallic/disabled-date.png
90
- - vendor/assets/images/zebra-datepicker/metallic/header.png
91
- - vendor/assets/images/zebra-datepicker/metallic/selected-date.png
86
+ - vendor/assets/images/zebra-datepicker/bootstrap/icons.png
87
+ - vendor/assets/images/zebra-datepicker/default/icons.png
88
+ - vendor/assets/images/zebra-datepicker/metallic/icons.png
92
89
  - vendor/assets/javascripts/zebra-datepicker/core.js
93
90
  - vendor/assets/javascripts/zebra-datepicker/zebra_datepicker.js
94
- - vendor/assets/javascripts/zebra-datepicker/zebra_datepicker.src.js
95
91
  - vendor/assets/stylesheets/zebra-datepicker/bootstrap.scss
96
92
  - vendor/assets/stylesheets/zebra-datepicker/default.scss
97
93
  - vendor/assets/stylesheets/zebra-datepicker/metallic.scss
@@ -116,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
112
  version: '0'
117
113
  requirements: []
118
114
  rubyforge_project:
119
- rubygems_version: 2.6.8
115
+ rubygems_version: 2.7.3
120
116
  signing_key:
121
117
  specification_version: 4
122
118
  summary: Zebra Datepicker (http://stefangabos.ro/jquery/zebra-datepicker/) packaged
@@ -1,3229 +0,0 @@
1
- /**
2
- * Zebra_DatePicker
3
- *
4
- * Zebra_DatePicker is a small, compact and highly configurable date picker plugin for jQuery
5
- *
6
- * Visit {@link http://stefangabos.ro/jquery/zebra-datepicker/} for more information.
7
- *
8
- * For more resources visit {@link http://stefangabos.ro/}
9
- *
10
- * @author Stefan Gabos <contact@stefangabos.ro>
11
- * @version 1.9.5 (last revision: May 13, 2016)
12
- * @copyright (c) 2011 - 2016 Stefan Gabos
13
- * @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LESSER GENERAL PUBLIC LICENSE
14
- * @package Zebra_DatePicker
15
- */
16
- ;(function(factory) {
17
-
18
- 'use strict';
19
-
20
- // AMD
21
- if (typeof define === 'function' && define.amd) define(['jquery'], factory);
22
-
23
- // CommonJS
24
- else if (typeof exports === 'object') factory(require('jquery'));
25
-
26
- // browser globals
27
- else factory(jQuery);
28
-
29
- }(function($) {
30
-
31
- 'use strict';
32
-
33
- $.Zebra_DatePicker = function(element, options) {
34
-
35
- var defaults = {
36
-
37
- // setting this property to a jQuery element, will result in the date picker being always visible, the indicated
38
- // element being the date picker's container;
39
- always_visible: false,
40
-
41
- // by default, the date picker is injected into the <body>; use this property to tell the library to inject
42
- // the date picker into a custom element - useful when you want the date picker to open at a specific position
43
- //
44
- // must be a jQuery element
45
- //
46
- // default is $('body')
47
- container: $('body'),
48
-
49
- // dates that should have custom classes applied to them
50
- // an object in the form of
51
- // {
52
- // 'myclass1': [dates_to_apply_the_custom_class_to],
53
- // 'myclass2': [dates_to_apply_the_custom_class_to]
54
- // }
55
- // where "dates_to_apply_the_custom_class_to" is an array of dates in the same format as required for
56
- // "disabled_dates" property.
57
- //
58
- // custom classes will be applied *only* in the day picker view and not on month/year views!
59
- // also note that the class name will have the "_disabled" suffix added if the day the class is applied to
60
- // is disabled
61
- //
62
- // in order for the styles in your custom classes to be applied, make sure you are using the following syntax:
63
- //
64
- // .Zebra_DatePicker .dp_daypicker td.myclass1 { .. }
65
- // .Zebra_DatePicker .dp_daypicker td.myclass1_disabled { .. }
66
- //
67
- // default is FALSE, no custom classes
68
- custom_classes: false,
69
-
70
- // days of the week; Sunday to Saturday
71
- days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
72
-
73
- // by default, the abbreviated name of a day consists of the first 2 letters from the day's full name;
74
- // while this is common for most languages, there are also exceptions for languages like Thai, Loa, Myanmar,
75
- // etc. where this is not correct; for these cases, specify an array with the abbreviations to be used for
76
- // the 7 days of the week; leave it FALSE to use the first 2 letters of a day's name as the abbreviation.
77
- //
78
- // default is FALSE
79
- days_abbr: false,
80
-
81
- // the position of the date picker relative to the element it is attached to. note that, regardless of this
82
- // setting, the date picker's position will be automatically adjusted to fit in the viewport, if needed.
83
- //
84
- // possible values are "above" and "below"
85
- //
86
- // default is "above"
87
- default_position: 'above',
88
-
89
- // direction of the calendar
90
- //
91
- // a positive or negative integer: n (a positive integer) creates a future-only calendar beginning at n days
92
- // after today; -n (a negative integer); if n is 0, the calendar has no restrictions. use boolean true for
93
- // a future-only calendar starting with today and use boolean false for a past-only calendar ending today.
94
- //
95
- // you may also set this property to an array with two elements in the following combinations:
96
- //
97
- // - first item is boolean TRUE (calendar starts today), an integer > 0 (calendar starts n days after
98
- // today), or a valid date given in the format defined by the "format" attribute, using English for
99
- // month names (calendar starts at the specified date), and the second item is boolean FALSE (the calendar
100
- // has no ending date), an integer > 0 (calendar ends n days after the starting date), or a valid date
101
- // given in the format defined by the "format" attribute, using English for month names, and which occurs
102
- // after the starting date (calendar ends at the specified date)
103
- //
104
- // - first item is boolean FALSE (calendar ends today), an integer < 0 (calendar ends n days before today),
105
- // or a valid date given in the format defined by the "format" attribute, using English for month names
106
- // (calendar ends at the specified date), and the second item is an integer > 0 (calendar ends n days
107
- // before the ending date), or a valid date given in the format defined by the "format" attribute, using
108
- // English for month names and which occurs before the starting date (calendar starts at the specified
109
- // date)
110
- //
111
- // [1, 7] - calendar starts tomorrow and ends seven days after that
112
- // [true, 7] - calendar starts today and ends seven days after that
113
- // ['2013-01-01', false] - calendar starts on January 1st 2013 and has no ending date ("format" is YYYY-MM-DD)
114
- // [false, '2012-01-01'] - calendar ends today and starts on January 1st 2012 ("format" is YYYY-MM-DD)
115
- //
116
- // note that "disabled_dates" property will still apply!
117
- //
118
- // default is 0 (no restrictions)
119
- direction: 0,
120
-
121
- // an array of disabled dates in the following format: 'day month year weekday' where "weekday" is optional
122
- // and can be 0-6 (Saturday to Sunday); the syntax is similar to cron's syntax: the values are separated by
123
- // spaces and may contain * (asterisk) - (dash) and , (comma) delimiters:
124
- //
125
- // ['1 1 2012'] would disable January 1, 2012;
126
- // ['* 1 2012'] would disable all days in January 2012;
127
- // ['1-10 1 2012'] would disable January 1 through 10 in 2012;
128
- // ['1,10 1 2012'] would disable January 1 and 10 in 2012;
129
- // ['1-10,20,22,24 1-3 *'] would disable 1 through 10, plus the 22nd and 24th of January through March for every year;
130
- // ['* * * 0,6'] would disable all Saturdays and Sundays;
131
- // ['01 07 2012', '02 07 2012', '* 08 2012'] would disable 1st and 2nd of July 2012, and all of August of 2012
132
- //
133
- // default is FALSE, no disabled dates
134
- //
135
- // DISABLING ALL DATES AND NOT SPECIFYING AT LEAST ONE ENABLED DATE WILL SEND THE SCRIPT INTO AN INFINITE
136
- // LOOP SEARCHING FOR AN ENABLED DATE TO DISPLAY!
137
- disabled_dates: false,
138
-
139
- // an array of enabled dates in the same format as required for "disabled_dates" property.
140
- // to be used together with the "disabled_dates" property by first setting the "disabled_dates" property to
141
- // something like "[* * * *]" (which will disable everything) and the setting the "enabled_dates" property to,
142
- // say, "[* * * 0,6]" to enable just weekends.
143
- enabled_dates: false,
144
-
145
- // week's starting day
146
- //
147
- // valid values are 0 to 6, Sunday to Saturday
148
- //
149
- // default is 1, Monday
150
- first_day_of_week: 1,
151
-
152
- // format of the returned date
153
- //
154
- // accepts the following characters for date formatting: d, D, j, l, N, w, S, F, m, M, n, Y, y borrowing
155
- // syntax from PHP's "date" function.
156
- //
157
- // note that when setting a date format without days ('d', 'j'), the users will be able to select only years
158
- // and months, and when setting a format without months and days ('F', 'm', 'M', 'n', 'd', 'j'), the
159
- // users will be able to select only years; likewise, when setting a date format with just months ('F', 'm',
160
- // 'M', 'n') or just years ('Y', 'y'), users will be able to select only months and years, respectively.
161
- //
162
- // also note that the value of the "view" property (see below) may be overridden if it is the case: a value of
163
- // "days" for the "view" property makes no sense if the date format doesn't allow the selection of days.
164
- //
165
- // default is Y-m-d
166
- format: 'Y-m-d',
167
-
168
- // captions in the datepicker's header, for the 3 possible views: days, months, years
169
- //
170
- // for each of the 3 views the following special characters may be used borrowing from PHP's "date" function's
171
- // syntax: m, n, F, M, y and Y; any of these will be replaced at runtime with the appropriate date fragment,
172
- // depending on the currently viewed date. two more special characters are also available Y1 and Y2 (upper
173
- // case representing years with 4 digits, lowercase representing years with 2 digits) which represent
174
- // "currently selected year - 7" and "currently selected year + 4" and which only make sense used in the
175
- // "years" view.
176
- //
177
- // even though any of these special characters may be used in any of the 3 views, you should use m, n, F, M
178
- // for the "days" view and y, Y, Y1, Y2, y1, y2 for the "months" and "years" view or you may get unexpected
179
- // results!
180
- //
181
- // Text and HTML can also be used, and will be rendered as it is, as in the example below (the library is
182
- // smart enough to not replace special characters when used in words or HTML tags):
183
- //
184
- // header_captions: {
185
- // 'days': 'Departure:<br>F, Y',
186
- // 'months': 'Departure:<br>Y',
187
- // 'years': 'Departure:<br>Y1 - Y2'
188
- // }
189
- //
190
- // Default is
191
- //
192
- // header_captions: {
193
- // 'days': 'F, Y',
194
- // 'months': 'Y',
195
- // 'years': 'Y1 - Y2'
196
- // }
197
- header_captions: {
198
- 'days': 'F, Y',
199
- 'months': 'Y',
200
- 'years': 'Y1 - Y2'
201
- },
202
-
203
- // HTML to be used for the previous month/next month buttons
204
- //
205
- // default is ['&#171;','&#187;']
206
- header_navigation: ['&#171;', '&#187;'],
207
-
208
- // icon's position
209
- // accepted values are "left" and "right"
210
- //
211
- // default is "right"
212
- icon_position: 'right',
213
-
214
- // should the icon for opening the datepicker be inside the element?
215
- // if set to FALSE, the icon will be placed to the right of the parent element, while if set to TRUE it will
216
- // be placed to the right of the parent element, but *inside* the element itself
217
- //
218
- // default is TRUE
219
- inside: true,
220
-
221
- // the caption for the "Clear" button
222
- lang_clear_date: 'Clear date',
223
-
224
- // months names
225
- months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
226
-
227
- // by default, the abbreviated name of a month consists of the first 3 letters from the month's full name;
228
- // while this is common for most languages, there are also exceptions for languages like Thai, Loa, Myanmar,
229
- // etc. where this is not correct; for these cases, specify an array with the abbreviations to be used for
230
- // the months of the year; leave it FALSE to use the first 3 letters of a month's name as the abbreviation.
231
- //
232
- // default is FALSE
233
- months_abbr: false,
234
-
235
- // the offset, in pixels (x, y), to shift the date picker's position relative to the top-right of the icon
236
- // that toggles the date picker or, if the icon is disabled, relative to the top-right corner of the element
237
- // the plugin is attached to.
238
- //
239
- // note that this only applies if the position of element relative to the browser's viewport doesn't require
240
- // the date picker to be placed automatically so that it is visible!
241
- //
242
- // default is [5, -5]
243
- offset: [5, -5],
244
-
245
- // set whether the date picker should be shown *only* when clicking the icon
246
- // note that if you set the "show_icon" property to FALSE, you will not be able to show the date picker anymore!
247
- //
248
- // default is FALSE
249
- open_icon_only: false,
250
-
251
- // if set as a jQuery element with a Zebra_DatePicker attached, that particular date picker will use the
252
- // current date picker's value as starting date
253
- // note that the rules set in the "direction" property will still apply, only that the reference date will
254
- // not be the current system date but the value selected in the current date picker
255
- // default is FALSE (not paired with another date picker)
256
- pair: false,
257
-
258
- // should the element the calendar is attached to, be read-only?
259
- // if set to TRUE, a date can be set only through the date picker and cannot be entered manually
260
- //
261
- // default is TRUE
262
- readonly_element: true,
263
-
264
- // should days from previous and/or next month be selectable when visible?
265
- // note that if the value of this property is set to TRUE, the value of "show_other_months" will be considered
266
- // TRUE regardless of the actual value!
267
- //
268
- // default is FALSE
269
- select_other_months: false,
270
-
271
- // should the "Clear date" button be visible?
272
- //
273
- // accepted values are:
274
- //
275
- // - 0 (zero) - the button for clearing a previously selected date is shown only if a previously selected date
276
- // already exists; this means that if the input the date picker is attached to is empty, and the user selects
277
- // a date for the first time, this button will not be visible; once the user picked a date and opens the date
278
- // picker again, this time the button will be visible.
279
- //
280
- // - TRUE will make the button visible all the time
281
- //
282
- // - FALSE will disable the button
283
- //
284
- // default is "0" (without quotes)
285
- show_clear_date: 0,
286
-
287
- // should a calendar icon be added to the elements the plugin is attached to?
288
- //
289
- // default is TRUE
290
- show_icon: true,
291
-
292
- // should days from previous and/or next month be visible?
293
- //
294
- // default is TRUE
295
- show_other_months: true,
296
-
297
- // should the "Today" button be visible?
298
- // setting it to anything but boolean FALSE will enable the button and will use the property's value as
299
- // caption for the button; setting it to FALSE will disable the button
300
- //
301
- // default is "Today"
302
- show_select_today: 'Today',
303
-
304
- // should an extra column be shown, showing the number of each week?
305
- // anything other than FALSE will enable this feature, and use the given value as column title
306
- // i.e. show_week_number: 'Wk' would enable this feature and have "Wk" as the column's title
307
- //
308
- // default is FALSE
309
- show_week_number: false,
310
-
311
- // a default date to start the date picker with
312
- // must be specified in the format defined by the "format" property, or it will be ignored!
313
- // note that this value is used only if there is no value in the field the date picker is attached to!
314
- start_date: false,
315
-
316
- // should default values, in the input field the date picker is attached to, be deleted if they are not valid
317
- // according to "direction" and/or "disabled_dates"?
318
- //
319
- // default is FALSE
320
- strict: false,
321
-
322
- // how should the date picker start; valid values are "days", "months" and "years"
323
- // note that the date picker is always cycling days-months-years when clicking in the date picker's header,
324
- // and years-months-days when selecting dates (unless one or more of the views are missing due to the date's
325
- // format)
326
- //
327
- // also note that the value of the "view" property may be overridden if the date's format requires so! (i.e.
328
- // "days" for the "view" property makes no sense if the date format doesn't allow the selection of days)
329
- //
330
- // default is "days"
331
- view: 'days',
332
-
333
- // days of the week that are considered "weekend days"
334
- // valid values are 0 to 6, Sunday to Saturday
335
- //
336
- // default values are 0 and 6 (Saturday and Sunday)
337
- weekend_days: [0, 6],
338
-
339
- // when set to TRUE, day numbers < 10 will be prefixed with 0; set to FALSE if you don't want that
340
- //
341
- // default is TRUE
342
- zero_pad: false,
343
-
344
- // callback function to be executed whenever the user changes the view (days/months/years), as well as when
345
- // the user navigates by clicking on the "next"/"previous" icons in any of the views;
346
- //
347
- // the callback function called by this event takes 3 arguments - the first argument represents the current
348
- // view (can be "days", "months" or "years"), the second argument represents an array containing the "active"
349
- // elements (not disabled) from the view, as jQuery elements, allowing for easy customization and interaction
350
- // with particular cells in the date picker's view, while the third argument is a reference to the element
351
- // the date picker is attached to, as a jQuery object (deprecated - use the "this" keyword inside the callback
352
- // function to refer to the element the date picker is attached to)
353
- //
354
- // for simplifying searching for particular dates, each element in the second argument will also have a
355
- // "date" data attribute whose format depends on the value of the "view" argument:
356
- // - YYYY-MM-DD for elements in the "days" view
357
- // - YYYY-MM for elements in the "months" view
358
- // - YYYY for elements in the "years" view
359
- //
360
- // the "this" keyword inside the callback function refers to the element the date picker is attached to!
361
- onChange: null,
362
-
363
- // callback function to be executed when the user clicks the "Clear" button
364
- // the callback function takes a single argument:
365
- // - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
366
- // "this" keyword inside the callback function to refer to the element the date picker is attached to)
367
- //
368
- // the "this" keyword inside the callback function refers to the element the date picker is attached to!
369
- onClear: null,
370
-
371
- // callback function to be executed when the date picker is shown
372
- // the callback function takes a single argument:
373
- // - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
374
- // "this" keyword inside the callback function to refer to the element the date picker is attached to)
375
- //
376
- // the "this" keyword inside the callback function refers to the element the date picker is attached to!
377
- onOpen: null,
378
-
379
- // callback function to be executed when the date picker is closed, but only when the "always_visible"
380
- // property is set to FALSE
381
- // the callback function takes a single argument:
382
- // - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
383
- // "this" keyword inside the callback function to refer to the element the date picker is attached to)
384
- //
385
- // the "this" keyword inside the callback function refers to the element the date picker is attached to!
386
- onClose: null,
387
-
388
- // callback function to be executed when a date is selected
389
- // the callback function takes 5 arguments:
390
- // - the date in the format specified by the "format" attribute;
391
- // - the date in YYYY-MM-DD format
392
- // - the date as a JavaScript Date object
393
- // - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
394
- // "this" keyword inside the callback function to refer to the element the date picker is attached to)
395
- // - the ISO 8601 week number of the selected date
396
- //
397
- // the "this" keyword inside the callback function refers to the element the date picker is attached to!
398
- onSelect: null
399
-
400
- };
401
-
402
- // private properties
403
- var view, datepicker, icon, header, daypicker, monthpicker, yearpicker, cleardate, current_system_month, current_system_year,
404
- current_system_day, first_selectable_month, first_selectable_year, first_selectable_day, selected_month, selected_year,
405
- default_day, default_month, default_year, enabled_dates, disabled_dates, shim, start_date, end_date, last_selectable_day,
406
- last_selectable_year, last_selectable_month, daypicker_cells, monthpicker_cells, yearpicker_cells, views, clickables,
407
- selecttoday, footer, show_select_today, timeout, uniqueid, custom_classes, custom_class_names, original_attributes = {};
408
-
409
- var plugin = this;
410
-
411
- plugin.settings = {};
412
-
413
- // the jQuery version of the element
414
- // "element" (without the $) will point to the DOM element
415
- var $element = $(element);
416
-
417
- /**
418
- * Constructor method. Initializes the date picker.
419
- *
420
- * @return void
421
- */
422
- var init = function(update) {
423
-
424
- // generate a random ID for each date picker (we'll use this if later a certain date picker is destroyed to
425
- // remove related events)
426
- // the code is taken from http://stackoverflow.com/a/105074
427
- uniqueid = Math.floor((1 + Math.random()) * 0x10000).toString(16);
428
-
429
- // unless we're not just updating settings
430
- if (!update) {
431
-
432
- // merge default settings with user-settings (
433
- plugin.settings = $.extend({}, defaults, options);
434
-
435
- // preserve some of element's original attributes
436
- original_attributes['readonly'] = $element.attr('readonly');
437
- original_attributes['style'] = $element.attr('style');
438
-
439
- // iterate through the element's data attributes (if any)
440
- for (var data in $element.data())
441
-
442
- // if data attribute's name starts with "zdp_"
443
- if (data.indexOf('zdp_') === 0) {
444
-
445
- // remove the "zdp_" prefix
446
- data = data.replace(/^zdp\_/, '');
447
-
448
- // if such a property exists
449
- if (undefined !== defaults[data])
450
-
451
- // update the property's value
452
- // (note that for the "pair" property we need to convert the property to an element)
453
- plugin.settings[data] = (data == 'pair' ? $($element.data('zdp_' + data)) : $element.data('zdp_' + data));
454
-
455
- }
456
-
457
- }
458
-
459
- // if the element should be read-only, set the "readonly" attribute
460
- if (plugin.settings.readonly_element) $element.attr('readonly', 'readonly');
461
-
462
- // determine the views the user can cycle through, depending on the format
463
- // that is, if the format doesn't contain the day, the user will be able to cycle only through years and months,
464
- // whereas if the format doesn't contain months nor days, the user will only be able to select years
465
-
466
- var
467
-
468
- // the characters that may be present in the date format and that represent days, months and years
469
- date_chars = {
470
- days: ['d', 'j', 'D'],
471
- months: ['F', 'm', 'M', 'n', 't'],
472
- years: ['o', 'Y', 'y']
473
- },
474
-
475
- // some defaults
476
- has_days = false,
477
- has_months = false,
478
- has_years = false,
479
- type = null;
480
-
481
- // iterate through all the character blocks
482
- for (type in date_chars)
483
-
484
- // iterate through the characters of each block
485
- $.each(date_chars[type], function(index, character) {
486
-
487
- // if current character exists in the "format" property
488
- if (plugin.settings.format.indexOf(character) > -1)
489
-
490
- // set to TRUE the appropriate flag
491
- if (type == 'days') has_days = true;
492
- else if (type == 'months') has_months = true;
493
- else if (type == 'years') has_years = true;
494
-
495
- });
496
-
497
- // if user can cycle through all the views, set the flag accordingly
498
- if (has_days && has_months && has_years) views = ['years', 'months', 'days'];
499
-
500
- // if user can cycle only through year and months, set the flag accordingly
501
- else if (!has_days && has_months && has_years) views = ['years', 'months'];
502
-
503
- // if user can cycle only through months and days, set the flag accordingly
504
- else if (has_days && has_months && !has_years) views = ['months', 'days'];
505
-
506
- // if user can only see the year picker, set the flag accordingly
507
- else if (!has_days && !has_months && has_years) views = ['years'];
508
-
509
- // if user can only see the month picker, set the flag accordingly
510
- else if (!has_days && has_months && !has_years) views = ['months'];
511
-
512
- // if invalid format (no days, no months, no years) use the default where the user is able to cycle through
513
- // all the views
514
- else views = ['years', 'months', 'days'];
515
-
516
- // if the starting view is not amongst the views the user can cycle through, set the correct starting view
517
- if ($.inArray(plugin.settings.view, views) == -1) plugin.settings.view = views[views.length - 1];
518
-
519
- // parse the rules for disabling dates and turn them into arrays of arrays
520
-
521
- // array that will hold the rules for enabling/disabling dates
522
- disabled_dates = []; enabled_dates = []; custom_classes = {}; custom_class_names = [];
523
-
524
- var dates;
525
-
526
- for (var k in plugin.settings.custom_classes) if (plugin.settings.custom_classes.hasOwnProperty(k)) custom_class_names.push(k);
527
-
528
- // it's the same logic for preparing the enabled/disable dates, as well as dates that have custom classes
529
- for (var l = 0; l < 2 + custom_class_names.length; l++) {
530
-
531
- // first time we're doing disabled dates,
532
- if (l === 0) dates = plugin.settings.disabled_dates;
533
-
534
- // second time we're doing enabled_dates
535
- else if (l == 1) dates = plugin.settings.enabled_dates;
536
-
537
- // otherwise, we're doing dates that will have custom classes
538
- else dates = plugin.settings.custom_classes[custom_class_names[l - 2]];
539
-
540
- // if we have a non-empty array
541
- if ($.isArray(dates) && dates.length > 0)
542
-
543
- // iterate through the rules
544
- $.each(dates, function() {
545
-
546
- // split the values in rule by white space
547
- var rules = this.split(' ');
548
-
549
- // there can be a maximum of 4 rules (days, months, years and, optionally, day of the week)
550
- for (var i = 0; i < 4; i++) {
551
-
552
- // if one of the values is not available
553
- // replace it with a * (wildcard)
554
- if (!rules[i]) rules[i] = '*';
555
-
556
- // if rule contains a comma, create a new array by splitting the rule by commas
557
- // if there are no commas create an array containing the rule's string
558
- rules[i] = (rules[i].indexOf(',') > -1 ? rules[i].split(',') : new Array(rules[i]));
559
-
560
- // iterate through the items in the rule
561
- for (var j = 0; j < rules[i].length; j++)
562
-
563
- // if item contains a dash (defining a range)
564
- if (rules[i][j].indexOf('-') > -1) {
565
-
566
- // get the lower and upper limits of the range
567
- var limits = rules[i][j].match(/^([0-9]+)\-([0-9]+)/);
568
-
569
- // if range is valid
570
- if (null !== limits) {
571
-
572
- // iterate through the range
573
- for (var k = to_int(limits[1]); k <= to_int(limits[2]); k++)
574
-
575
- // if value is not already among the values of the rule
576
- // add it to the rule
577
- if ($.inArray(k, rules[i]) == -1) rules[i].push(k + '');
578
-
579
- // remove the range indicator
580
- rules[i].splice(j, 1);
581
-
582
- }
583
-
584
- }
585
-
586
- // iterate through the items in the rule
587
- // and make sure that numbers are numbers
588
- for (j = 0; j < rules[i].length; j++) rules[i][j] = (isNaN(to_int(rules[i][j])) ? rules[i][j] : to_int(rules[i][j]));
589
-
590
- }
591
-
592
- // add to the correct list of processed rules
593
- // first time we're doing disabled dates,
594
- if (l === 0) disabled_dates.push(rules);
595
-
596
- // second time we're doing enabled_dates
597
- else if (l == 1) enabled_dates.push(rules);
598
-
599
- // otherwise, we're doing the dates to which custom classes need to be applied
600
- else {
601
-
602
- if (undefined === custom_classes[custom_class_names[l - 2]]) custom_classes[custom_class_names[l - 2]] = [];
603
- custom_classes[custom_class_names[l - 2]].push(rules);
604
-
605
- }
606
-
607
- });
608
-
609
- }
610
-
611
- var
612
-
613
- // cache the current system date
614
- date = new Date(),
615
-
616
- // when the date picker's starting date depends on the value of another date picker, this value will be
617
- // set by the other date picker
618
- // this value will be used as base for all calculations (if not set, will be the same as the current
619
- // system date)
620
- reference_date = (!plugin.settings.reference_date ? ($element.data('zdp_reference_date') && undefined !== $element.data('zdp_reference_date') ? $element.data('zdp_reference_date') : date) : plugin.settings.reference_date),
621
-
622
- tmp_start_date, tmp_end_date;
623
-
624
- // reset these values here as this method might be called more than once during a date picker's lifetime
625
- // (when the selectable dates depend on the values from another date picker)
626
- start_date = undefined; end_date = undefined;
627
-
628
- // extract the date parts
629
- // also, save the current system month/day/year - we'll use them to highlight the current system date
630
- first_selectable_month = reference_date.getMonth();
631
- current_system_month = date.getMonth();
632
- first_selectable_year = reference_date.getFullYear();
633
- current_system_year = date.getFullYear();
634
- first_selectable_day = reference_date.getDate();
635
- current_system_day = date.getDate();
636
-
637
- // check if the calendar has any restrictions
638
-
639
- // calendar is future-only, starting today
640
- // it means we have a starting date (the current system date), but no ending date
641
- if (plugin.settings.direction === true) start_date = reference_date;
642
-
643
- // calendar is past only, ending today
644
- else if (plugin.settings.direction === false) {
645
-
646
- // it means we have an ending date (the reference date), but no starting date
647
- end_date = reference_date;
648
-
649
- // extract the date parts
650
- last_selectable_month = end_date.getMonth();
651
- last_selectable_year = end_date.getFullYear();
652
- last_selectable_day = end_date.getDate();
653
-
654
- } else if (
655
-
656
- // if direction is not given as an array and the value is an integer > 0
657
- (!$.isArray(plugin.settings.direction) && is_integer(plugin.settings.direction) && to_int(plugin.settings.direction) > 0) ||
658
-
659
- // or direction is given as an array
660
- ($.isArray(plugin.settings.direction) && (
661
-
662
- // and first entry is a valid date
663
- (tmp_start_date = check_date(plugin.settings.direction[0])) ||
664
- // or a boolean TRUE
665
- plugin.settings.direction[0] === true ||
666
- // or an integer > 0
667
- (is_integer(plugin.settings.direction[0]) && plugin.settings.direction[0] > 0)
668
-
669
- ) && (
670
-
671
- // and second entry is a valid date
672
- (tmp_end_date = check_date(plugin.settings.direction[1])) ||
673
- // or a boolean FALSE
674
- plugin.settings.direction[1] === false ||
675
- // or integer >= 0
676
- (is_integer(plugin.settings.direction[1]) && plugin.settings.direction[1] >= 0)
677
-
678
- ))
679
-
680
- ) {
681
-
682
- // if an exact starting date was given, use that as a starting date
683
- if (tmp_start_date) start_date = tmp_start_date;
684
-
685
- // otherwise
686
- else
687
-
688
- // figure out the starting date
689
- // use the Date object to normalize the date
690
- // for example, 2011 05 33 will be transformed to 2011 06 02
691
- start_date = new Date(
692
- first_selectable_year,
693
- first_selectable_month,
694
- first_selectable_day + (!$.isArray(plugin.settings.direction) ? to_int(plugin.settings.direction) : to_int(plugin.settings.direction[0] === true ? 0 : plugin.settings.direction[0]))
695
- );
696
-
697
- // re-extract the date parts
698
- first_selectable_month = start_date.getMonth();
699
- first_selectable_year = start_date.getFullYear();
700
- first_selectable_day = start_date.getDate();
701
-
702
- // if an exact ending date was given and the date is after the starting date, use that as a ending date
703
- if (tmp_end_date && +tmp_end_date >= +start_date) end_date = tmp_end_date;
704
-
705
- // if have information about the ending date
706
- else if (!tmp_end_date && plugin.settings.direction[1] !== false && $.isArray(plugin.settings.direction))
707
-
708
- // figure out the ending date
709
- // use the Date object to normalize the date
710
- // for example, 2011 05 33 will be transformed to 2011 06 02
711
- end_date = new Date(
712
- first_selectable_year,
713
- first_selectable_month,
714
- first_selectable_day + to_int(plugin.settings.direction[1])
715
- );
716
-
717
- // if a valid ending date exists
718
- if (end_date) {
719
-
720
- // extract the date parts
721
- last_selectable_month = end_date.getMonth();
722
- last_selectable_year = end_date.getFullYear();
723
- last_selectable_day = end_date.getDate();
724
-
725
- }
726
-
727
- } else if (
728
-
729
- // if direction is not given as an array and the value is an integer < 0
730
- (!$.isArray(plugin.settings.direction) && is_integer(plugin.settings.direction) && to_int(plugin.settings.direction) < 0) ||
731
-
732
- // or direction is given as an array
733
- ($.isArray(plugin.settings.direction) && (
734
-
735
- // and first entry is boolean FALSE
736
- plugin.settings.direction[0] === false ||
737
- // or an integer < 0
738
- (is_integer(plugin.settings.direction[0]) && plugin.settings.direction[0] < 0)
739
-
740
- ) && (
741
-
742
- // and second entry is a valid date
743
- (tmp_start_date = check_date(plugin.settings.direction[1])) ||
744
- // or an integer >= 0
745
- (is_integer(plugin.settings.direction[1]) && plugin.settings.direction[1] >= 0)
746
-
747
- ))
748
-
749
- ) {
750
-
751
- // figure out the ending date
752
- // use the Date object to normalize the date
753
- // for example, 2011 05 33 will be transformed to 2011 06 02
754
- end_date = new Date(
755
- first_selectable_year,
756
- first_selectable_month,
757
- first_selectable_day + (!$.isArray(plugin.settings.direction) ? to_int(plugin.settings.direction) : to_int(plugin.settings.direction[0] === false ? 0 : plugin.settings.direction[0]))
758
- );
759
-
760
- // re-extract the date parts
761
- last_selectable_month = end_date.getMonth();
762
- last_selectable_year = end_date.getFullYear();
763
- last_selectable_day = end_date.getDate();
764
-
765
- // if an exact starting date was given, and the date is before the ending date, use that as a starting date
766
- if (tmp_start_date && +tmp_start_date < +end_date) start_date = tmp_start_date;
767
-
768
- // if have information about the starting date
769
- else if (!tmp_start_date && $.isArray(plugin.settings.direction))
770
-
771
- // figure out the staring date
772
- // use the Date object to normalize the date
773
- // for example, 2011 05 33 will be transformed to 2011 06 02
774
- start_date = new Date(
775
- last_selectable_year,
776
- last_selectable_month,
777
- last_selectable_day - to_int(plugin.settings.direction[1])
778
- );
779
-
780
- // if a valid starting date exists
781
- if (start_date) {
782
-
783
- // extract the date parts
784
- first_selectable_month = start_date.getMonth();
785
- first_selectable_year = start_date.getFullYear();
786
- first_selectable_day = start_date.getDate();
787
-
788
- }
789
-
790
- // if there are disabled dates
791
- } else if ($.isArray(plugin.settings.disabled_dates) && plugin.settings.disabled_dates.length > 0)
792
-
793
- // iterate through the rules for disabling dates
794
- for (var interval in disabled_dates)
795
-
796
- // only if there is a rule that disables *everything*
797
- if (disabled_dates[interval][0] == '*' && disabled_dates[interval][1] == '*' && disabled_dates[interval][2] == '*' && disabled_dates[interval][3] == '*') {
798
-
799
- var tmpDates = [];
800
-
801
- // iterate through the rules for enabling dates
802
- // looking for the minimum/maximum selectable date (if it's the case)
803
- $.each(enabled_dates, function() {
804
-
805
- var rule = this;
806
-
807
- // if the rule doesn't apply to all years
808
- if (rule[2][0] != '*')
809
-
810
- // format date and store it in our stack
811
- tmpDates.push(parseInt(
812
- rule[2][0] +
813
- (rule[1][0] == '*' ? '12' : str_pad(rule[1][0], 2)) +
814
- (rule[0][0] == '*' ? (rule[1][0] == '*' ? '31' : new Date(rule[2][0], rule[1][0], 0).getDate()) : str_pad(rule[0][0], 2)), 10));
815
-
816
- });
817
-
818
- // sort dates ascending
819
- tmpDates.sort();
820
-
821
- // if we have any rules
822
- if (tmpDates.length > 0) {
823
-
824
- // get date parts
825
- var matches = (tmpDates[0] + '').match(/([0-9]{4})([0-9]{2})([0-9]{2})/);
826
-
827
- // assign the date parts to the appropriate variables
828
- first_selectable_year = parseInt(matches[1], 10);
829
- first_selectable_month = parseInt(matches[2], 10) - 1;
830
- first_selectable_day = parseInt(matches[3], 10);
831
-
832
- }
833
-
834
- // don't look further
835
- break;
836
-
837
- }
838
-
839
- // if first selectable date exists but is disabled, find the actual first selectable date
840
- if (is_disabled(first_selectable_year, first_selectable_month, first_selectable_day)) {
841
-
842
- // loop until we find the first selectable year
843
- while (is_disabled(first_selectable_year)) {
844
-
845
- // if calendar is past-only,
846
- if (!start_date) {
847
-
848
- // decrement the year
849
- first_selectable_year--;
850
-
851
- // because we've changed years, reset the month to December
852
- first_selectable_month = 11;
853
-
854
- // otherwise
855
- } else {
856
-
857
- // increment the year
858
- first_selectable_year++;
859
-
860
- // because we've changed years, reset the month to January
861
- first_selectable_month = 0;
862
-
863
- }
864
-
865
- }
866
-
867
- // loop until we find the first selectable month
868
- while (is_disabled(first_selectable_year, first_selectable_month)) {
869
-
870
- // if calendar is past-only
871
- if (!start_date) {
872
-
873
- // decrement the month
874
- first_selectable_month--;
875
-
876
- // because we've changed months, reset the day to the last day of the month
877
- first_selectable_day = new Date(first_selectable_year, first_selectable_month + 1, 0).getDate();
878
-
879
- // otherwise
880
- } else {
881
-
882
- // increment the month
883
- first_selectable_month++;
884
-
885
- // because we've changed months, reset the day to the first day of the month
886
- first_selectable_day = 1;
887
-
888
- }
889
-
890
- // if we moved to a following year
891
- if (first_selectable_month > 11) {
892
-
893
- // increment the year
894
- first_selectable_year++;
895
-
896
- // reset the month to January
897
- first_selectable_month = 0;
898
-
899
- // because we've changed months, reset the day to the first day of the month
900
- first_selectable_day = 1;
901
-
902
- // if we moved to a previous year
903
- } else if (first_selectable_month < 0) {
904
-
905
- // decrement the year
906
- first_selectable_year--;
907
-
908
- // reset the month to December
909
- first_selectable_month = 11;
910
-
911
- // because we've changed months, reset the day to the last day of the month
912
- first_selectable_day = new Date(first_selectable_year, first_selectable_month + 1, 0).getDate();
913
-
914
- }
915
-
916
- }
917
-
918
- // loop until we find the first selectable day
919
- while (is_disabled(first_selectable_year, first_selectable_month, first_selectable_day)) {
920
-
921
- // if calendar is past-only, decrement the day
922
- if (!start_date) first_selectable_day--;
923
-
924
- // otherwise, increment the day
925
- else first_selectable_day++;
926
-
927
- // use the Date object to normalize the date
928
- // for example, 2011 05 33 will be transformed to 2011 06 02
929
- date = new Date(first_selectable_year, first_selectable_month, first_selectable_day);
930
-
931
- // re-extract date parts from the normalized date
932
- // as we use them in the current loop
933
- first_selectable_year = date.getFullYear();
934
- first_selectable_month = date.getMonth();
935
- first_selectable_day = date.getDate();
936
-
937
- }
938
-
939
- // use the Date object to normalize the date
940
- // for example, 2011 05 33 will be transformed to 2011 06 02
941
- date = new Date(first_selectable_year, first_selectable_month, first_selectable_day);
942
-
943
- // re-extract date parts from the normalized date
944
- // as we use them in the current loop
945
- first_selectable_year = date.getFullYear();
946
- first_selectable_month = date.getMonth();
947
- first_selectable_day = date.getDate();
948
-
949
- }
950
-
951
- // get the default date, from the element, and check if it represents a valid date, according to the required format
952
- var default_date = check_date($element.val() || (plugin.settings.start_date ? plugin.settings.start_date : ''));
953
-
954
- // if there is a default date, date picker is in "strict" mode, and the default date is disabled
955
- if (default_date && plugin.settings.strict && is_disabled(default_date.getFullYear(), default_date.getMonth(), default_date.getDate()))
956
-
957
- // clear the value of the parent element
958
- $element.val('');
959
-
960
- // updates value for the date picker whose starting date depends on the selected date (if any)
961
- if (!update && (undefined !== start_date || undefined !== default_date))
962
- update_dependent(undefined !== default_date ? default_date : start_date);
963
-
964
- // if date picker is not always visible
965
- if (!plugin.settings.always_visible) {
966
-
967
- // if we're just creating the date picker
968
- if (!update) {
969
-
970
- // if a calendar icon should be added to the element the plugin is attached to, create the icon now
971
- if (plugin.settings.show_icon) {
972
-
973
- // strangely, in Firefox 21+ (or maybe even earlier) input elements have their "display" property
974
- // set to "inline" instead of "inline-block" as do all the other browsers.
975
- // because this behavior brakes the positioning of the icon, we'll set the "display" property to
976
- // "inline-block" before anything else;
977
- if (browser.name == 'firefox' && $element.is('input[type="text"]') && $element.css('display') == 'inline') $element.css('display', 'inline-block');
978
-
979
- // we create a wrapper for the parent element so that we can later position the icon
980
- // also, make sure the wrapper inherits some important css properties of the parent element
981
- var icon_wrapper = $('<span class="Zebra_DatePicker_Icon_Wrapper"></span>').css({
982
- 'display': $element.css('display'),
983
- 'position': $element.css('position') == 'static' ? 'relative' : $element.css('position'),
984
- 'float': $element.css('float'),
985
- 'top': $element.css('top'),
986
- 'right': $element.css('right'),
987
- 'bottom': $element.css('bottom'),
988
- 'left': $element.css('left')
989
- });
990
-
991
- // if parent element has its "display" property set to "block"
992
- // the wrapper has to have its "width" set
993
- if ($element.css('display') == 'block') icon_wrapper.css('width', $element.outerWidth(true));
994
-
995
- // put wrapper around the element
996
- // also, make sure we set some important css properties for it
997
- $element.wrap(icon_wrapper).css({
998
- 'position': 'relative',
999
- 'top': 'auto',
1000
- 'right': 'auto',
1001
- 'bottom': 'auto',
1002
- 'left': 'auto'
1003
- });
1004
-
1005
- // create the actual calendar icon (show a disabled icon if the element is disabled)
1006
- icon = $('<button type="button" class="Zebra_DatePicker_Icon' + ($element.attr('disabled') == 'disabled' ? ' Zebra_DatePicker_Icon_Disabled' : '') + '">Pick a date</button>');
1007
-
1008
- // a reference to the icon, as a global property
1009
- plugin.icon = icon;
1010
-
1011
- // the date picker will open when clicking both the icon and the element the plugin is attached to
1012
- // (or the icon only, if set so)
1013
- clickables = plugin.settings.open_icon_only ? icon : icon.add($element);
1014
-
1015
- // if calendar icon is not visible, the date picker will open when clicking the element
1016
- } else clickables = $element;
1017
-
1018
- // attach the click event to the clickable elements (icon and/or element)
1019
- clickables.bind('click.Zebra_DatePicker_' + uniqueid, function(e) {
1020
-
1021
- e.preventDefault();
1022
-
1023
- // if element is not disabled
1024
- if (!$element.attr('disabled'))
1025
-
1026
- // if the date picker is visible, hide it
1027
- if (datepicker.hasClass('dp_visible')) plugin.hide();
1028
-
1029
- // if the date picker is not visible, show it
1030
- else plugin.show();
1031
-
1032
- });
1033
-
1034
- // if users can manually enter dates and a pair date element exists
1035
- if (!plugin.settings.readonly_element && plugin.settings.pair)
1036
-
1037
- // whenever the element looses focus
1038
- $element.bind('blur.Zebra_DatePicker_' + uniqueid, function() {
1039
-
1040
- var date;
1041
-
1042
- // if a valid date was entered, update the paired date picker
1043
- if ((date = check_date($(this).val())) && !is_disabled(date.getFullYear(), date.getMonth(), date.getDate())) update_dependent(date);
1044
-
1045
- });
1046
-
1047
- // if icon exists, inject it into the DOM, right after the parent element (and inside the wrapper)
1048
- if (undefined !== icon) icon.insertAfter($element);
1049
-
1050
- }
1051
-
1052
- // if calendar icon exists
1053
- if (undefined !== icon) {
1054
-
1055
- // needed when updating: remove any inline style set previously by library,
1056
- // so we get the right values below
1057
- icon.attr('style', '');
1058
-
1059
- // if calendar icon is to be placed *inside* the element
1060
- // add an extra class to the icon
1061
- if (plugin.settings.inside) icon.addClass('Zebra_DatePicker_Icon_Inside_' + (plugin.settings.icon_position == 'right' ? 'Right' : 'Left'));
1062
-
1063
- var
1064
-
1065
- // get element's width and height (including margins)
1066
- element_width = $element.outerWidth(),
1067
- element_height = $element.outerHeight(),
1068
- element_margin_left = parseInt($element.css('marginLeft'), 10) || 0,
1069
- element_margin_top = parseInt($element.css('marginTop'), 10) || 0,
1070
-
1071
- // get icon's width, height and margins
1072
- icon_width = icon.outerWidth(),
1073
- icon_height = icon.outerHeight(),
1074
- icon_margin_left = parseInt(icon.css('marginLeft'), 10) || 0,
1075
- icon_margin_right = parseInt(icon.css('marginRight'), 10) || 0;
1076
-
1077
- // if icon is to be placed *inside* the element
1078
- // position the icon accordingly
1079
- if (plugin.settings.inside) {
1080
-
1081
- // set icon's top
1082
- icon.css('top', element_margin_top + ((element_height - icon_height) / 2));
1083
-
1084
- // place icon to the right or to the left, according to the settings
1085
- if (plugin.settings.icon_position == 'right') icon.css('right', 0);
1086
- else icon.css('left', 0);
1087
-
1088
- // if icon is to be placed to the right of the element
1089
- // position the icon accordingly
1090
- } else
1091
-
1092
- icon.css({
1093
- 'top': element_margin_top + ((element_height - icon_height) / 2),
1094
- 'left': element_margin_left + element_width + icon_margin_left
1095
- });
1096
-
1097
- // assume the datepicker is not disabled
1098
- icon.removeClass(' Zebra_DatePicker_Icon_Disabled');
1099
-
1100
- // if element the datepicker is attached to became disabled, disable the calendar icon, too
1101
- if ($element.attr('disabled') == 'disabled') icon.addClass('Zebra_DatePicker_Icon_Disabled');
1102
-
1103
- }
1104
-
1105
- }
1106
-
1107
- // if the "Today" button is to be shown and it makes sense to be shown
1108
- // (the "days" view is available and "today" is not a disabled date)
1109
- show_select_today = (plugin.settings.show_select_today !== false && $.inArray('days', views) > -1 && !is_disabled(current_system_year, current_system_month, current_system_day) ? plugin.settings.show_select_today : false);
1110
-
1111
- // if we just needed to recompute the things above
1112
- if (update) {
1113
-
1114
- // make sure we update these strings, in case they've changed
1115
- $('.dp_previous', datepicker).html(plugin.settings.header_navigation[0]);
1116
- $('.dp_next', datepicker).html(plugin.settings.header_navigation[1]);
1117
- $('.dp_clear', datepicker).html(plugin.settings.lang_clear_date);
1118
- $('.dp_today', datepicker).html(plugin.settings.show_select_today);
1119
-
1120
- // don't go further
1121
- return;
1122
-
1123
- }
1124
-
1125
- // update icon/date picker position on resize and/or changing orientation
1126
- $(window).bind('resize.Zebra_DatePicker_' + uniqueid + ', orientationchange.Zebra_DatePicker_' + uniqueid, function() {
1127
-
1128
- // hide the date picker
1129
- plugin.hide();
1130
-
1131
- // if the icon is visible, update its position as the parent element might have changed position
1132
- if (icon !== undefined) {
1133
-
1134
- // we use timeouts so that we do not call the "update" method on *every* step of the resize event
1135
-
1136
- // clear a previously set timeout
1137
- clearTimeout(timeout);
1138
-
1139
- // set timeout again
1140
- timeout = setTimeout(function() {
1141
-
1142
- // update the date picker
1143
- plugin.update();
1144
-
1145
- }, 100);
1146
-
1147
- }
1148
-
1149
- });
1150
-
1151
- // generate the container that will hold everything
1152
- var html = '' +
1153
- '<div class="Zebra_DatePicker">' +
1154
- '<table class="dp_header">' +
1155
- '<tr>' +
1156
- '<td class="dp_previous">' + plugin.settings.header_navigation[0] + '</td>' +
1157
- '<td class="dp_caption">&#032;</td>' +
1158
- '<td class="dp_next">' + plugin.settings.header_navigation[1] + '</td>' +
1159
- '</tr>' +
1160
- '</table>' +
1161
- '<table class="dp_daypicker"></table>' +
1162
- '<table class="dp_monthpicker"></table>' +
1163
- '<table class="dp_yearpicker"></table>' +
1164
- '<table class="dp_footer"><tr>' +
1165
- '<td class="dp_today"' + (plugin.settings.show_clear_date !== false ? ' style="width:50%"' : '') + '>' + show_select_today + '</td>' +
1166
- '<td class="dp_clear"' + (show_select_today !== false ? ' style="width:50%"' : '') + '>' + plugin.settings.lang_clear_date + '</td>' +
1167
- '</tr></table>' +
1168
- '</div>';
1169
-
1170
- // create a jQuery object out of the HTML above and create a reference to it
1171
- datepicker = $(html);
1172
-
1173
- // a reference to the calendar, as a global property
1174
- plugin.datepicker = datepicker;
1175
-
1176
- // create references to the different parts of the date picker
1177
- header = $('table.dp_header', datepicker);
1178
- daypicker = $('table.dp_daypicker', datepicker);
1179
- monthpicker = $('table.dp_monthpicker', datepicker);
1180
- yearpicker = $('table.dp_yearpicker', datepicker);
1181
- footer = $('table.dp_footer', datepicker);
1182
- selecttoday = $('td.dp_today', footer);
1183
- cleardate = $('td.dp_clear', footer);
1184
-
1185
- // if date picker is not always visible
1186
- if (!plugin.settings.always_visible)
1187
-
1188
- // inject the container into the DOM
1189
- plugin.settings.container.append(datepicker);
1190
-
1191
- // otherwise, if element is not disabled
1192
- else if (!$element.attr('disabled')) {
1193
-
1194
- // inject the date picker into the designated container element
1195
- plugin.settings.always_visible.append(datepicker);
1196
-
1197
- // and make it visible right away
1198
- plugin.show();
1199
-
1200
- }
1201
-
1202
- // add the mouseover/mousevents to all to the date picker's cells
1203
- // except those that are not selectable
1204
- datepicker.
1205
- delegate('td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)', 'mouseover', function() {
1206
- $(this).addClass('dp_hover');
1207
- }).
1208
- delegate('td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)', 'mouseout', function() {
1209
- $(this).removeClass('dp_hover');
1210
- });
1211
-
1212
- // prevent text highlighting for the text in the header
1213
- // (for the case when user keeps clicking the "next" and "previous" buttons)
1214
- disable_text_select($('td', header));
1215
-
1216
- // event for when clicking the "previous" button
1217
- $('.dp_previous', header).bind('click', function() {
1218
-
1219
- // if view is "months"
1220
- // decrement year by one
1221
- if (view == 'months') selected_year--;
1222
-
1223
- // if view is "years"
1224
- // decrement years by 12
1225
- else if (view == 'years') selected_year -= 12;
1226
-
1227
- // if view is "days"
1228
- // decrement the month and
1229
- // if month is out of range
1230
- else if (--selected_month < 0) {
1231
-
1232
- // go to the last month of the previous year
1233
- selected_month = 11;
1234
- selected_year--;
1235
-
1236
- }
1237
-
1238
- // generate the appropriate view
1239
- manage_views();
1240
-
1241
- });
1242
-
1243
- // attach a click event to the caption in header
1244
- $('.dp_caption', header).bind('click', function() {
1245
-
1246
- // if current view is "days", take the user to the next view, depending on the format
1247
- if (view == 'days') view = ($.inArray('months', views) > -1 ? 'months' : ($.inArray('years', views) > -1 ? 'years' : 'days'));
1248
-
1249
- // if current view is "months", take the user to the next view, depending on the format
1250
- else if (view == 'months') view = ($.inArray('years', views) > -1 ? 'years' : ($.inArray('days', views) > -1 ? 'days' : 'months'));
1251
-
1252
- // if current view is "years", take the user to the next view, depending on the format
1253
- else view = ($.inArray('days', views) > -1 ? 'days' : ($.inArray('months', views) > -1 ? 'months' : 'years'));
1254
-
1255
- // generate the appropriate view
1256
- manage_views();
1257
-
1258
- });
1259
-
1260
- // event for when clicking the "next" button
1261
- $('.dp_next', header).bind('click', function() {
1262
-
1263
- // if view is "months"
1264
- // increment year by 1
1265
- if (view == 'months') selected_year++;
1266
-
1267
- // if view is "years"
1268
- // increment years by 12
1269
- else if (view == 'years') selected_year += 12;
1270
-
1271
- // if view is "days"
1272
- // increment the month and
1273
- // if month is out of range
1274
- else if (++selected_month == 12) {
1275
-
1276
- // go to the first month of the next year
1277
- selected_month = 0;
1278
- selected_year++;
1279
-
1280
- }
1281
-
1282
- // generate the appropriate view
1283
- manage_views();
1284
-
1285
- });
1286
-
1287
- // attach a click event for the cells in the day picker
1288
- daypicker.delegate('td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)', 'click', function() {
1289
-
1290
- // if other months are selectable and currently clicked cell contains a class with the cell's date
1291
- if (plugin.settings.select_other_months && $(this).attr('class') && null !== (matches = $(this).attr('class').match(/date\_([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])/)))
1292
-
1293
- // use the stored date
1294
- select_date(matches[1], matches[2] - 1, matches[3], 'days', $(this));
1295
-
1296
- // put selected date in the element the plugin is attached to, and hide the date picker
1297
- else select_date(selected_year, selected_month, to_int($(this).html()), 'days', $(this));
1298
-
1299
- });
1300
-
1301
- // attach a click event for the cells in the month picker
1302
- monthpicker.delegate('td:not(.dp_disabled)', 'click', function() {
1303
-
1304
- // get the month we've clicked on
1305
- var matches = $(this).attr('class').match(/dp\_month\_([0-9]+)/);
1306
-
1307
- // set the selected month
1308
- selected_month = to_int(matches[1]);
1309
-
1310
- // if user can select only years and months
1311
- if ($.inArray('days', views) == -1)
1312
-
1313
- // put selected date in the element the plugin is attached to, and hide the date picker
1314
- select_date(selected_year, selected_month, 1, 'months', $(this));
1315
-
1316
- else {
1317
-
1318
- // direct the user to the "days" view
1319
- view = 'days';
1320
-
1321
- // if date picker is always visible
1322
- // empty the value in the text box the date picker is attached to
1323
- if (plugin.settings.always_visible) $element.val('');
1324
-
1325
- // generate the appropriate view
1326
- manage_views();
1327
-
1328
- }
1329
-
1330
- });
1331
-
1332
- // attach a click event for the cells in the year picker
1333
- yearpicker.delegate('td:not(.dp_disabled)', 'click', function() {
1334
-
1335
- // set the selected year
1336
- selected_year = to_int($(this).html());
1337
-
1338
- // if user can select only years
1339
- if ($.inArray('months', views) == -1)
1340
-
1341
- // put selected date in the element the plugin is attached to, and hide the date picker
1342
- select_date(selected_year, 1, 1, 'years', $(this));
1343
-
1344
- else {
1345
-
1346
- // direct the user to the "months" view
1347
- view = 'months';
1348
-
1349
- // if date picker is always visible
1350
- // empty the value in the text box the date picker is attached to
1351
- if (plugin.settings.always_visible) $element.val('');
1352
-
1353
- // generate the appropriate view
1354
- manage_views();
1355
-
1356
- }
1357
-
1358
- });
1359
-
1360
- // function to execute when the "Today" button is clicked
1361
- $(selecttoday).bind('click', function(e) {
1362
-
1363
- e.preventDefault();
1364
-
1365
- // select the current date
1366
- select_date(current_system_year, current_system_month, current_system_day, 'days', $('.dp_current', daypicker));
1367
-
1368
- // if date picker is always visible
1369
- if (plugin.settings.always_visible)
1370
-
1371
- // repaint the datepicker so it centers on the currently selected date
1372
- plugin.show();
1373
-
1374
- // hide the date picker
1375
- plugin.hide();
1376
-
1377
- });
1378
-
1379
- // function to execute when the "Clear" button is clicked
1380
- $(cleardate).bind('click', function(e) {
1381
-
1382
- e.preventDefault();
1383
-
1384
- // clear the element's value
1385
- $element.val('');
1386
-
1387
- // if date picker is not always visible
1388
- if (!plugin.settings.always_visible) {
1389
-
1390
- // reset these values
1391
- default_day = null; default_month = null; default_year = null; selected_month = null; selected_year = null;
1392
-
1393
- // if date picker is always visible
1394
- } else {
1395
-
1396
- // reset these values
1397
- default_day = null; default_month = null; default_year = null;
1398
-
1399
- // remove the "selected" class from all cells that have it
1400
- $('td.dp_selected', datepicker).removeClass('dp_selected');
1401
-
1402
- }
1403
-
1404
- // hide the date picker
1405
- plugin.hide();
1406
-
1407
- // if a callback function exists for when clearing a date
1408
- if (plugin.settings.onClear && typeof plugin.settings.onClear == 'function')
1409
-
1410
- // execute the callback function and pass as argument the element the plugin is attached to
1411
- plugin.settings.onClear.call($element, $element);
1412
-
1413
- });
1414
-
1415
- // if date picker is not always visible
1416
- if (!plugin.settings.always_visible) {
1417
-
1418
- //whenever anything is clicked on the page
1419
- $(document).bind('mousedown.Zebra_DatePicker_' + uniqueid + ', touchstart.Zebra_DatePicker_' + uniqueid, function(e) {
1420
-
1421
- // if the date picker is visible
1422
- if (datepicker.hasClass('dp_visible')) {
1423
-
1424
- // if the calendar icon is visible and we clicked it, let the onClick event of the icon to handle the event
1425
- // (we want it to toggle the date picker)
1426
- if (plugin.settings.show_icon && $(e.target).get(0) === icon.get(0)) return true;
1427
-
1428
- // if what's clicked is not inside the date picker
1429
- // hide the date picker
1430
- if ($(e.target).parents().filter('.Zebra_DatePicker').length === 0) plugin.hide();
1431
-
1432
- }
1433
-
1434
- });
1435
-
1436
- //whenever a key is pressed on the page
1437
- $(document).bind('keyup.Zebra_DatePicker_' + uniqueid, function(e) {
1438
-
1439
- // if the date picker is visible
1440
- // and the pressed key is ESC
1441
- // hide the date picker
1442
- if (datepicker.hasClass('dp_visible') && e.which == 27) plugin.hide();
1443
-
1444
- });
1445
-
1446
- }
1447
-
1448
- // last thing is to pre-render some of the date picker right away
1449
- manage_views();
1450
-
1451
- };
1452
-
1453
- /**
1454
- * Clears the selected date.
1455
- *
1456
- * @return void
1457
- */
1458
- plugin.clear_date = function() {
1459
-
1460
- $(cleardate).trigger('click');
1461
-
1462
- };
1463
-
1464
- /**
1465
- * Destroys the date picker.
1466
- *
1467
- * @return void
1468
- */
1469
- plugin.destroy = function() {
1470
-
1471
- // remove the attached icon (if it exists)...
1472
- if (undefined !== plugin.icon) plugin.icon.remove();
1473
-
1474
- // ...and the calendar
1475
- plugin.datepicker.remove();
1476
-
1477
- // if calendar icon was shown and the date picker was not always visible,
1478
- // also remove the wrapper needed for positioning it
1479
- if (plugin.settings.show_icon && !plugin.settings.always_visible) $element.unwrap();
1480
-
1481
- // remove associated event handlers from the element
1482
- $element.unbind('click.Zebra_DatePicker_' + uniqueid);
1483
- $element.unbind('blur.Zebra_DatePicker_' + uniqueid);
1484
-
1485
- // remove associated event handlers from the document
1486
- $(document).unbind('keyup.Zebra_DatePicker_' + uniqueid);
1487
- $(document).unbind('mousedown.Zebra_DatePicker_' + uniqueid);
1488
- $(window).unbind('resize.Zebra_DatePicker_' + uniqueid);
1489
- $(window).unbind('orientationchange.Zebra_DatePicker_' + uniqueid);
1490
-
1491
- // remove association with the element
1492
- $element.removeData('Zebra_DatePicker');
1493
-
1494
- // restore element's modified attributes
1495
- $element.attr('readonly', original_attributes['readonly'] ? true : false);
1496
- $element.attr('style', original_attributes['style'] ? original_attributes['style'] : '');
1497
-
1498
- };
1499
-
1500
- /**
1501
- * Hides the date picker.
1502
- *
1503
- * @return void
1504
- */
1505
- plugin.hide = function() {
1506
-
1507
- // if date picker is not always visible
1508
- if (!plugin.settings.always_visible) {
1509
-
1510
- // hide the iFrameShim in Internet Explorer 6
1511
- iframeShim('hide');
1512
-
1513
- // hide the date picker
1514
- datepicker.removeClass('dp_visible').addClass('dp_hidden');
1515
-
1516
- // if a callback function exists for when hiding the date picker
1517
- if (plugin.settings.onClose && typeof plugin.settings.onClose == 'function')
1518
-
1519
- // execute the callback function and pass as argument the element the plugin is attached to
1520
- plugin.settings.onClose.call($element, $element);
1521
- }
1522
-
1523
- };
1524
-
1525
- /**
1526
- * Set the date picker's value
1527
- *
1528
- * Must be in the format set by the "format" property!
1529
- *
1530
- * @return void
1531
- */
1532
- plugin.set_date = function(date) {
1533
-
1534
- var dateObj;
1535
-
1536
- // if a valid date was entered, and date is not disabled
1537
- if ((dateObj = check_date(date)) && !is_disabled(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate())) {
1538
-
1539
- // set the element's value
1540
- $element.val(date);
1541
-
1542
- // update the paired date picker (if any)
1543
- update_dependent(dateObj);
1544
-
1545
- }
1546
-
1547
- };
1548
-
1549
- /**
1550
- * Shows the date picker.
1551
- *
1552
- * @return void
1553
- */
1554
- plugin.show = function() {
1555
-
1556
- // always show the view defined in settings
1557
- view = plugin.settings.view;
1558
-
1559
- // get the default date, from the element, and check if it represents a valid date, according to the required format
1560
- var default_date = check_date($element.val() || (plugin.settings.start_date ? plugin.settings.start_date : ''));
1561
-
1562
- // if the value represents a valid date
1563
- if (default_date) {
1564
-
1565
- // extract the date parts
1566
- // we'll use these to highlight the default date in the date picker and as starting point to
1567
- // what year and month to start the date picker with
1568
- // why separate values? because selected_* will change as user navigates within the date picker
1569
- default_month = default_date.getMonth();
1570
- selected_month = default_date.getMonth();
1571
- default_year = default_date.getFullYear();
1572
- selected_year = default_date.getFullYear();
1573
- default_day = default_date.getDate();
1574
-
1575
- // if the default date represents a disabled date
1576
- if (is_disabled(default_year, default_month, default_day)) {
1577
-
1578
- // if date picker is in "strict" mode, clear the value of the parent element
1579
- if (plugin.settings.strict) $element.val('');
1580
-
1581
- // the calendar will start with the first selectable year/month
1582
- selected_month = first_selectable_month;
1583
- selected_year = first_selectable_year;
1584
-
1585
- }
1586
-
1587
- // if a default value is not available, or value does not represent a valid date
1588
- } else {
1589
-
1590
- // the calendar will start with the first selectable year/month
1591
- selected_month = first_selectable_month;
1592
- selected_year = first_selectable_year;
1593
-
1594
- }
1595
-
1596
- // generate the appropriate view
1597
- manage_views();
1598
-
1599
- // if date picker is not always visible and the calendar icon is visible
1600
- if (!plugin.settings.always_visible) {
1601
-
1602
- // if date picker is to be injected into the <body>
1603
- if (plugin.settings.container.is('body')) {
1604
-
1605
- var
1606
-
1607
- // get the date picker width and height
1608
- datepicker_width = datepicker.outerWidth(),
1609
- datepicker_height = datepicker.outerHeight(),
1610
-
1611
- // compute the date picker's default left and top
1612
- // this will be computed relative to the icon's top-right corner (if the calendar icon exists), or
1613
- // relative to the element's top-right corner otherwise, to which the offsets given at initialization
1614
- // are added/subtracted
1615
- left = (undefined !== icon ? icon.offset().left + icon.outerWidth(true) : $element.offset().left + $element.outerWidth(true)) + plugin.settings.offset[0],
1616
- top = (undefined !== icon ? icon.offset().top : $element.offset().top) - datepicker_height + plugin.settings.offset[1],
1617
-
1618
- // get browser window's width and height
1619
- window_width = $(window).width(),
1620
- window_height = $(window).height(),
1621
-
1622
- // get browser window's horizontal and vertical scroll offsets
1623
- window_scroll_top = $(window).scrollTop(),
1624
- window_scroll_left = $(window).scrollLeft();
1625
-
1626
- if (plugin.settings.default_position == 'below')
1627
- top = (undefined !== icon ? icon.offset().top : $element.offset().top) + plugin.settings.offset[1];
1628
-
1629
- // if date picker is outside the viewport, adjust its position so that it is visible
1630
- if (left + datepicker_width > window_scroll_left + window_width) left = window_scroll_left + window_width - datepicker_width;
1631
- if (left < window_scroll_left) left = window_scroll_left;
1632
-
1633
- if (top + datepicker_height > window_scroll_top + window_height) top = window_scroll_top + window_height - datepicker_height;
1634
- if (top < window_scroll_top) top = window_scroll_top;
1635
-
1636
- // make the date picker visible
1637
- datepicker.css({
1638
- 'left': left,
1639
- 'top': top
1640
- });
1641
-
1642
- // if date picker is to be injected into a custom container element
1643
- } else
1644
-
1645
- datepicker.css({
1646
- 'left': 0,
1647
- 'top': 0
1648
- });
1649
-
1650
- // fade-in the date picker
1651
- // for Internet Explorer < 9 show the date picker instantly or fading alters the font's weight
1652
- datepicker.removeClass('dp_hidden').addClass('dp_visible');
1653
-
1654
- // show the iFrameShim in Internet Explorer 6
1655
- iframeShim();
1656
-
1657
- // if date picker is always visible, show it
1658
- } else datepicker.removeClass('dp_hidden').addClass('dp_visible');
1659
-
1660
- // if a callback function exists for when showing the date picker
1661
- if (plugin.settings.onOpen && typeof plugin.settings.onOpen == 'function')
1662
-
1663
- // execute the callback function and pass as argument the element the plugin is attached to
1664
- plugin.settings.onOpen.call($element, $element);
1665
-
1666
- };
1667
-
1668
- /**
1669
- * Updates the configuration options given as argument
1670
- *
1671
- * @param object values An object containing any number of configuration options to be updated
1672
- *
1673
- * @return void
1674
- */
1675
- plugin.update = function(values) {
1676
-
1677
- // if original direction not saved, save it now
1678
- if (plugin.original_direction) plugin.original_direction = plugin.direction;
1679
-
1680
- // update configuration options
1681
- plugin.settings = $.extend(plugin.settings, values);
1682
-
1683
- // reinitialize the object with the new options
1684
- init(true);
1685
-
1686
- };
1687
-
1688
- /**
1689
- * Checks if a string represents a valid date according to the format defined by the "format" property.
1690
- *
1691
- * @param string str_date A string representing a date, formatted accordingly to the "format" property.
1692
- * For example, if "format" is "Y-m-d" the string should look like "2011-06-01"
1693
- *
1694
- * @return mixed Returns a JavaScript Date object if string represents a valid date according
1695
- * formatted according to the "format" property, or FALSE otherwise.
1696
- *
1697
- * @access private
1698
- */
1699
- var check_date = function(str_date) {
1700
-
1701
- // treat argument as a string
1702
- str_date += '';
1703
-
1704
- // if value is given
1705
- if ($.trim(str_date) !== '') {
1706
-
1707
- var
1708
-
1709
- // prepare the format by removing white space from it
1710
- // and also escape characters that could have special meaning in a regular expression
1711
- format = escape_regexp(plugin.settings.format),
1712
-
1713
- // allowed characters in date's format
1714
- format_chars = ['d','D','j','l','N','S','w','F','m','M','n','Y','y'],
1715
-
1716
- // "matches" will contain the characters defining the date's format
1717
- matches = [],
1718
-
1719
- // "regexp" will contain the regular expression built for each of the characters used in the date's format
1720
- regexp = [],
1721
-
1722
- // "position" will contain the position of the caracter found in the date's format
1723
- position = null,
1724
-
1725
- // "segments" will contain the matches of the regular expression
1726
- segments = null;
1727
-
1728
- // iterate through the allowed characters in date's format
1729
- for (var i = 0; i < format_chars.length; i++)
1730
-
1731
- // if character is found in the date's format
1732
- if ((position = format.indexOf(format_chars[i])) > -1)
1733
-
1734
- // save it, alongside the character's position
1735
- matches.push({character: format_chars[i], position: position});
1736
-
1737
- // sort characters defining the date's format based on their position, ascending
1738
- matches.sort(function(a, b){ return a.position - b.position; });
1739
-
1740
- // iterate through the characters defining the date's format
1741
- $.each(matches, function(index, match) {
1742
-
1743
- // add to the array of regular expressions, based on the character
1744
- switch (match.character) {
1745
-
1746
- case 'd': regexp.push('0[1-9]|[12][0-9]|3[01]'); break;
1747
- case 'D': regexp.push('[a-z]{3}'); break;
1748
- case 'j': regexp.push('[1-9]|[12][0-9]|3[01]'); break;
1749
- case 'l': regexp.push('[a-z]+'); break;
1750
- case 'N': regexp.push('[1-7]'); break;
1751
- case 'S': regexp.push('st|nd|rd|th'); break;
1752
- case 'w': regexp.push('[0-6]'); break;
1753
- case 'F': regexp.push('[a-z]+'); break;
1754
- case 'm': regexp.push('0[1-9]|1[012]+'); break;
1755
- case 'M': regexp.push('[a-z]{3}'); break;
1756
- case 'n': regexp.push('[1-9]|1[012]'); break;
1757
- case 'Y': regexp.push('[0-9]{4}'); break;
1758
- case 'y': regexp.push('[0-9]{2}'); break;
1759
-
1760
- }
1761
-
1762
- });
1763
-
1764
- // if we have an array of regular expressions
1765
- if (regexp.length) {
1766
-
1767
- // we will replace characters in the date's format in reversed order
1768
- matches.reverse();
1769
-
1770
- // iterate through the characters in date's format
1771
- $.each(matches, function(index, match) {
1772
-
1773
- // replace each character with the appropriate regular expression
1774
- format = format.replace(match.character, '(' + regexp[regexp.length - index - 1] + ')');
1775
-
1776
- });
1777
-
1778
- // the final regular expression
1779
- regexp = new RegExp('^' + format + '$', 'ig');
1780
-
1781
- // if regular expression was matched
1782
- if ((segments = regexp.exec(str_date))) {
1783
-
1784
- // check if date is a valid date (i.e. there's no February 31)
1785
-
1786
- var tmpdate = new Date(),
1787
- original_day = 1,
1788
- original_month = tmpdate.getMonth() + 1,
1789
- original_year = tmpdate.getFullYear(),
1790
- english_days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
1791
- english_months = ['January','February','March','April','May','June','July','August','September','October','November','December'],
1792
- iterable,
1793
-
1794
- // by default, we assume the date is valid
1795
- valid = true;
1796
-
1797
- // reverse back the characters in the date's format
1798
- matches.reverse();
1799
-
1800
- // iterate through the characters in the date's format
1801
- $.each(matches, function(index, match) {
1802
-
1803
- // if the date is not valid, don't look further
1804
- if (!valid) return true;
1805
-
1806
- // based on the character
1807
- switch (match.character) {
1808
-
1809
- case 'm':
1810
- case 'n':
1811
-
1812
- // extract the month from the value entered by the user
1813
- original_month = to_int(segments[index + 1]);
1814
-
1815
- break;
1816
-
1817
- case 'd':
1818
- case 'j':
1819
-
1820
- // extract the day from the value entered by the user
1821
- original_day = to_int(segments[index + 1]);
1822
-
1823
- break;
1824
-
1825
- case 'D':
1826
- case 'l':
1827
- case 'F':
1828
- case 'M':
1829
-
1830
- // if day is given as day name, we'll check against the names in the used language
1831
- if (match.character == 'D' || match.character == 'l') iterable = plugin.settings.days;
1832
-
1833
- // if month is given as month name, we'll check against the names in the used language
1834
- else iterable = plugin.settings.months;
1835
-
1836
- // by default, we assume the day or month was not entered correctly
1837
- valid = false;
1838
-
1839
- // iterate through the month/days in the used language
1840
- $.each(iterable, function(key, value) {
1841
-
1842
- // if month/day was entered correctly, don't look further
1843
- if (valid) return true;
1844
-
1845
- // if month/day was entered correctly
1846
- if (segments[index + 1].toLowerCase() == value.substring(0, (match.character == 'D' || match.character == 'M' ? 3 : value.length)).toLowerCase()) {
1847
-
1848
- // extract the day/month from the value entered by the user
1849
- switch (match.character) {
1850
-
1851
- case 'D': segments[index + 1] = english_days[key].substring(0, 3); break;
1852
- case 'l': segments[index + 1] = english_days[key]; break;
1853
- case 'F': segments[index + 1] = english_months[key]; original_month = key + 1; break;
1854
- case 'M': segments[index + 1] = english_months[key].substring(0, 3); original_month = key + 1; break;
1855
-
1856
- }
1857
-
1858
- // day/month value is valid
1859
- valid = true;
1860
-
1861
- }
1862
-
1863
- });
1864
-
1865
- break;
1866
-
1867
- case 'Y':
1868
-
1869
- // extract the year from the value entered by the user
1870
- original_year = to_int(segments[index + 1]);
1871
-
1872
- break;
1873
-
1874
- case 'y':
1875
-
1876
- // extract the year from the value entered by the user
1877
- original_year = '19' + to_int(segments[index + 1]);
1878
-
1879
- break;
1880
-
1881
- }
1882
- });
1883
-
1884
- // if everything is ok so far
1885
- if (valid) {
1886
-
1887
- // generate a Date object using the values entered by the user
1888
- // (handle also the case when original_month and/or original_day are undefined - i.e date format is "Y-m" or "Y")
1889
- var date = new Date(original_year, (original_month || 1) - 1, original_day || 1);
1890
-
1891
- // if, after that, the date is the same as the date entered by the user
1892
- if (date.getFullYear() == original_year && date.getDate() == (original_day || 1) && date.getMonth() == ((original_month || 1) - 1))
1893
-
1894
- // return the date as JavaScript date object
1895
- return date;
1896
-
1897
- }
1898
-
1899
- }
1900
-
1901
- }
1902
-
1903
- // if script gets this far, return false as something must've went wrong
1904
- return false;
1905
-
1906
- }
1907
-
1908
- };
1909
-
1910
- /**
1911
- * Prevents the possibility of selecting text on a given element. Used on the "previous" and "next" buttons
1912
- * where text might get accidentally selected when user quickly clicks on the buttons.
1913
- *
1914
- * Code by http://chris-barr.com/index.php/entry/disable_text_selection_with_jquery/
1915
- *
1916
- * @param jQuery Element el A jQuery element on which to prevents text selection.
1917
- *
1918
- * @return void
1919
- *
1920
- * @access private
1921
- */
1922
- var disable_text_select = function(el) {
1923
-
1924
- // if browser is Firefox
1925
- if (browser.name == 'firefox') el.css('MozUserSelect', 'none');
1926
-
1927
- // if browser is Internet Explorer
1928
- else if (browser.name == 'explorer') el.bind('selectstart', function() { return false; });
1929
-
1930
- // for the other browsers
1931
- else el.mousedown(function() { return false; });
1932
-
1933
- };
1934
-
1935
- /**
1936
- * Escapes special characters in a string, preparing it for use in a regular expression.
1937
- *
1938
- * @param string str The string in which special characters should be escaped.
1939
- *
1940
- * @return string Returns the string with escaped special characters.
1941
- *
1942
- * @access private
1943
- */
1944
- var escape_regexp = function(str) {
1945
-
1946
- // return string with special characters escaped
1947
- return str.replace(/([-.,*+?^${}()|[\]\/\\])/g, '\\$1');
1948
-
1949
- };
1950
-
1951
- /**
1952
- * Formats a JavaScript date object to the format specified by the "format" property.
1953
- * Code taken from http://electricprism.com/aeron/calendar/
1954
- *
1955
- * @param date date A valid JavaScript date object
1956
- *
1957
- * @return string Returns a string containing the formatted date
1958
- *
1959
- * @access private
1960
- */
1961
- var format = function(date) {
1962
-
1963
- var result = '',
1964
-
1965
- // extract parts of the date:
1966
- // day number, 1 - 31
1967
- j = date.getDate(),
1968
-
1969
- // day of the week, 0 - 6, Sunday - Saturday
1970
- w = date.getDay(),
1971
-
1972
- // the name of the day of the week Sunday - Saturday
1973
- l = plugin.settings.days[w],
1974
-
1975
- // the month number, 1 - 12
1976
- n = date.getMonth() + 1,
1977
-
1978
- // the month name, January - December
1979
- f = plugin.settings.months[n - 1],
1980
-
1981
- // the year (as a string)
1982
- y = date.getFullYear() + '';
1983
-
1984
- // iterate through the characters in the format
1985
- for (var i = 0; i < plugin.settings.format.length; i++) {
1986
-
1987
- // extract the current character
1988
- var chr = plugin.settings.format.charAt(i);
1989
-
1990
- // see what character it is
1991
- switch(chr) {
1992
-
1993
- // year as two digits
1994
- case 'y': y = y.substr(2);
1995
-
1996
- // year as four digits
1997
- case 'Y': result += y; break;
1998
-
1999
- // month number, prefixed with 0
2000
- case 'm': n = str_pad(n, 2);
2001
-
2002
- // month number, not prefixed with 0
2003
- case 'n': result += n; break;
2004
-
2005
- // month name, three letters
2006
- case 'M': f = ($.isArray(plugin.settings.months_abbr) && undefined !== plugin.settings.months_abbr[n - 1] ? plugin.settings.months_abbr[n - 1] : plugin.settings.months[n - 1].substr(0, 3));
2007
-
2008
- // full month name
2009
- case 'F': result += f; break;
2010
-
2011
- // day number, prefixed with 0
2012
- case 'd': j = str_pad(j, 2);
2013
-
2014
- // day number not prefixed with 0
2015
- case 'j': result += j; break;
2016
-
2017
- // day name, three letters
2018
- case 'D': l = ($.isArray(plugin.settings.days_abbr) && undefined !== plugin.settings.days_abbr[w] ? plugin.settings.days_abbr[w] : plugin.settings.days[w].substr(0, 3));
2019
-
2020
- // full day name
2021
- case 'l': result += l; break;
2022
-
2023
- // ISO-8601 numeric representation of the day of the week, 1 - 7
2024
- case 'N': w++;
2025
-
2026
- // day of the week, 0 - 6
2027
- case 'w': result += w; break;
2028
-
2029
- // English ordinal suffix for the day of the month, 2 characters
2030
- // (st, nd, rd or th (works well with j))
2031
- case 'S':
2032
-
2033
- if (j % 10 == 1 && j != '11') result += 'st';
2034
-
2035
- else if (j % 10 == 2 && j != '12') result += 'nd';
2036
-
2037
- else if (j % 10 == 3 && j != '13') result += 'rd';
2038
-
2039
- else result += 'th';
2040
-
2041
- break;
2042
-
2043
- // this is probably the separator
2044
- default: result += chr;
2045
-
2046
- }
2047
-
2048
- }
2049
-
2050
- // return formated date
2051
- return result;
2052
-
2053
- };
2054
-
2055
- /**
2056
- * Generates the day picker view, and displays it
2057
- *
2058
- * @return void
2059
- *
2060
- * @access private
2061
- */
2062
- var generate_daypicker = function() {
2063
-
2064
- var
2065
-
2066
- // get the number of days in the selected month
2067
- days_in_month = new Date(selected_year, selected_month + 1, 0).getDate(),
2068
-
2069
- // get the selected month's starting day (from 0 to 6)
2070
- first_day = new Date(selected_year, selected_month, 1).getDay(),
2071
-
2072
- // how many days are there in the previous month
2073
- days_in_previous_month = new Date(selected_year, selected_month, 0).getDate(),
2074
-
2075
- // how many days are there to be shown from the previous month
2076
- days_from_previous_month = first_day - plugin.settings.first_day_of_week;
2077
-
2078
- // the final value of how many days are there to be shown from the previous month
2079
- days_from_previous_month = days_from_previous_month < 0 ? 7 + days_from_previous_month : days_from_previous_month;
2080
-
2081
- // manage header caption and enable/disable navigation buttons if necessary
2082
- manage_header(plugin.settings.header_captions['days']);
2083
-
2084
- // start generating the HTML
2085
- var html = '<tr>';
2086
-
2087
- // if a column featuring the number of the week is to be shown
2088
- if (plugin.settings.show_week_number)
2089
-
2090
- // column title
2091
- html += '<th>' + plugin.settings.show_week_number + '</th>';
2092
-
2093
- // name of week days
2094
- // show the abbreviated day names (or only the first two letters of the full name if no abbreviations are specified)
2095
- // and also, take in account the value of the "first_day_of_week" property
2096
- for (var i = 0; i < 7; i++)
2097
-
2098
- html += '<th>' + ($.isArray(plugin.settings.days_abbr) && undefined !== plugin.settings.days_abbr[(plugin.settings.first_day_of_week + i) % 7] ? plugin.settings.days_abbr[(plugin.settings.first_day_of_week + i) % 7] : plugin.settings.days[(plugin.settings.first_day_of_week + i) % 7].substr(0, 2)) + '</th>';
2099
-
2100
- html += '</tr><tr>';
2101
-
2102
- // the calendar shows a total of 42 days
2103
- for (i = 0; i < 42; i++) {
2104
-
2105
- // seven days per row
2106
- if (i > 0 && i % 7 === 0) html += '</tr><tr>';
2107
-
2108
- // if week number is to be shown
2109
- if (i % 7 === 0 && plugin.settings.show_week_number)
2110
-
2111
- // show ISO 8601 week number
2112
- html += '<td class="dp_week_number">' + getWeekNumber(new Date(selected_year, selected_month, (i - days_from_previous_month + 1))) + '</td>';
2113
-
2114
- // the number of the day in month
2115
- var day = (i - days_from_previous_month + 1);
2116
-
2117
- // if dates in previous/next month can be selected, and this is one of those days
2118
- if (plugin.settings.select_other_months && (i < days_from_previous_month || day > days_in_month)) {
2119
-
2120
- // use the Date object to normalize the date
2121
- // for example, 2011 05 33 will be transformed to 2011 06 02
2122
- var real_date = new Date(selected_year, selected_month, day),
2123
- real_year = real_date.getFullYear(),
2124
- real_month = real_date.getMonth(),
2125
- real_day = real_date.getDate();
2126
-
2127
- // extract normalized date parts and merge them
2128
- real_date = real_year + str_pad(real_month + 1, 2) + str_pad(real_day, 2);
2129
-
2130
- }
2131
-
2132
- // if this is a day from the previous month
2133
- if (i < days_from_previous_month)
2134
-
2135
- html += '<td class="' + (plugin.settings.select_other_months && !is_disabled(real_year, real_month, real_day) ? 'dp_not_in_month_selectable date_' + real_date : 'dp_not_in_month') + '">' + (plugin.settings.select_other_months || plugin.settings.show_other_months ? str_pad(days_in_previous_month - days_from_previous_month + i + 1, plugin.settings.zero_pad ? 2 : 0) : '&nbsp;') + '</td>';
2136
-
2137
- // if this is a day from the next month
2138
- else if (day > days_in_month)
2139
-
2140
- html += '<td class="' + (plugin.settings.select_other_months && !is_disabled(real_year, real_month, real_day) ? 'dp_not_in_month_selectable date_' + real_date : 'dp_not_in_month') + '">' + (plugin.settings.select_other_months || plugin.settings.show_other_months ? str_pad(day - days_in_month, plugin.settings.zero_pad ? 2 : 0) : '&nbsp;') + '</td>';
2141
-
2142
- // if this is a day from the current month
2143
- else {
2144
-
2145
- var
2146
-
2147
- // get the week day (0 to 6, Sunday to Saturday)
2148
- weekday = (plugin.settings.first_day_of_week + i) % 7,
2149
-
2150
- class_name = '',
2151
-
2152
- // custom class, if any
2153
- custom_class_name = get_custom_class(selected_year, selected_month, day);
2154
-
2155
- // if date needs to be disabled
2156
- if (is_disabled(selected_year, selected_month, day)) {
2157
-
2158
- // if day is in weekend
2159
- if ($.inArray(weekday, plugin.settings.weekend_days) > -1) class_name = 'dp_weekend_disabled';
2160
-
2161
- // if work day
2162
- else class_name += ' dp_disabled';
2163
-
2164
- // highlight the current system date
2165
- if (selected_month == current_system_month && selected_year == current_system_year && current_system_day == day) class_name += ' dp_disabled_current';
2166
-
2167
- // apply custom class, with the "_disabled" suffix, if a custom class exists
2168
- if (custom_class_name != '') class_name += ' ' + custom_class_name + '_disabled';
2169
-
2170
- // if there are no restrictions
2171
- } else {
2172
-
2173
- // if day is in weekend
2174
- if ($.inArray(weekday, plugin.settings.weekend_days) > -1) class_name = 'dp_weekend';
2175
-
2176
- // highlight the currently selected date
2177
- if (selected_month == default_month && selected_year == default_year && default_day == day) class_name += ' dp_selected';
2178
-
2179
- // highlight the current system date
2180
- if (selected_month == current_system_month && selected_year == current_system_year && current_system_day == day) class_name += ' dp_current';
2181
-
2182
- // apply custom class, if a custom class exists
2183
- if (custom_class_name != '') class_name += ' ' + custom_class_name;
2184
-
2185
- }
2186
-
2187
- // print the day of the month (if "day" is NaN, use an empty string instead)
2188
- html += '<td' + (class_name !== '' ? ' class="' + $.trim(class_name) + '"' : '') + '>' + ((plugin.settings.zero_pad ? str_pad(day, 2) : day) || '&nbsp;') + '</td>';
2189
-
2190
- }
2191
-
2192
- }
2193
-
2194
- // wrap up generating the day picker
2195
- html += '</tr>';
2196
-
2197
- // inject the day picker into the DOM
2198
- daypicker.html($(html));
2199
-
2200
- // if date picker is always visible
2201
- if (plugin.settings.always_visible)
2202
-
2203
- // cache all the cells
2204
- // (we need them so that we can easily remove the "dp_selected" class from all of them when user selects a date)
2205
- daypicker_cells = $('td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)', daypicker);
2206
-
2207
- // make the day picker visible
2208
- daypicker.show();
2209
-
2210
- };
2211
-
2212
- /**
2213
- * Generates the month picker view, and displays it
2214
- *
2215
- * @return void
2216
- *
2217
- * @access private
2218
- */
2219
- var generate_monthpicker = function() {
2220
-
2221
- // manage header caption and enable/disable navigation buttons if necessary
2222
- manage_header(plugin.settings.header_captions['months']);
2223
-
2224
- // start generating the HTML
2225
- var html = '<tr>';
2226
-
2227
- // iterate through all the months
2228
- for (var i = 0; i < 12; i++) {
2229
-
2230
- // three month per row
2231
- if (i > 0 && i % 3 === 0) html += '</tr><tr>';
2232
-
2233
- var class_name = 'dp_month_' + i;
2234
-
2235
- // if month needs to be disabled
2236
- if (is_disabled(selected_year, i)) class_name += ' dp_disabled';
2237
-
2238
- // else, if a date is already selected and this is that particular month, highlight it
2239
- else if (default_month !== false && default_month == i && selected_year == default_year) class_name += ' dp_selected';
2240
-
2241
- // else, if this the current system month, highlight it
2242
- else if (current_system_month == i && current_system_year == selected_year) class_name += ' dp_current';
2243
-
2244
- // first three letters of the month's name
2245
- html += '<td class="' + $.trim(class_name) + '">' + ($.isArray(plugin.settings.months_abbr) && undefined !== plugin.settings.months_abbr[i] ? plugin.settings.months_abbr[i] : plugin.settings.months[i].substr(0, 3)) + '</td>';
2246
-
2247
- }
2248
-
2249
- // wrap up
2250
- html += '</tr>';
2251
-
2252
- // inject into the DOM
2253
- monthpicker.html($(html));
2254
-
2255
- // if date picker is always visible
2256
- if (plugin.settings.always_visible)
2257
-
2258
- // cache all the cells
2259
- // (we need them so that we can easily remove the "dp_selected" class from all of them when user selects a month)
2260
- monthpicker_cells = $('td:not(.dp_disabled)', monthpicker);
2261
-
2262
- // make the month picker visible
2263
- monthpicker.show();
2264
-
2265
- };
2266
-
2267
- /**
2268
- * Generates the year picker view, and displays it
2269
- *
2270
- * @return void
2271
- *
2272
- * @access private
2273
- */
2274
- var generate_yearpicker = function() {
2275
-
2276
- // manage header caption and enable/disable navigation buttons if necessary
2277
- manage_header(plugin.settings.header_captions['years']);
2278
-
2279
- // start generating the HTML
2280
- var html = '<tr>';
2281
-
2282
- // we're showing 9 years at a time, current year in the middle
2283
- for (var i = 0; i < 12; i++) {
2284
-
2285
- // three years per row
2286
- if (i > 0 && i % 3 === 0) html += '</tr><tr>';
2287
-
2288
- var class_name = '';
2289
-
2290
- // if year needs to be disabled
2291
- if (is_disabled(selected_year - 7 + i)) class_name += ' dp_disabled';
2292
-
2293
- // else, if a date is already selected and this is that particular year, highlight it
2294
- else if (default_year && default_year == selected_year - 7 + i) class_name += ' dp_selected';
2295
-
2296
- // else, if this is the current system year, highlight it
2297
- else if (current_system_year == (selected_year - 7 + i)) class_name += ' dp_current';
2298
-
2299
- // first three letters of the month's name
2300
- html += '<td' + ($.trim(class_name) !== '' ? ' class="' + $.trim(class_name) + '"' : '') + '>' + (selected_year - 7 + i) + '</td>';
2301
-
2302
- }
2303
-
2304
- // wrap up
2305
- html += '</tr>';
2306
-
2307
- // inject into the DOM
2308
- yearpicker.html($(html));
2309
-
2310
- // if date picker is always visible
2311
- if (plugin.settings.always_visible)
2312
-
2313
- // cache all the cells
2314
- // (we need them so that we can easily remove the "dp_selected" class from all of them when user selects a year)
2315
- yearpicker_cells = $('td:not(.dp_disabled)', yearpicker);
2316
-
2317
- // make the year picker visible
2318
- yearpicker.show();
2319
-
2320
- };
2321
-
2322
- /**
2323
- * Return the name of a custom class to be applied to the given date.
2324
- *
2325
- * @return string The name of a custom class to be applied to the given date, or an empty string if no custom
2326
- * class needs to be applied.
2327
- *
2328
- * @param integer year The year to check
2329
- * @param integer month The month to check
2330
- * @param integer day The day to check
2331
- *
2332
- * @access private
2333
- */
2334
- var get_custom_class = function(year, month, day) {
2335
-
2336
- var class_name, i, found;
2337
-
2338
- // if month is given as argument, increment it (as JavaScript uses 0 for January, 1 for February...)
2339
- if (typeof month != 'undefined') month = month + 1;
2340
-
2341
- // iterate through the custom classes
2342
- for (i in custom_class_names) {
2343
-
2344
- // the class name we're currently checking
2345
- class_name = custom_class_names[i]; found = false;
2346
-
2347
- // if there are any custom classes defined
2348
- if ($.isArray(custom_classes[class_name]))
2349
-
2350
- // iterate through the rules for which the custom class to be applied
2351
- $.each(custom_classes[class_name], function() {
2352
-
2353
- // if a custom class needs to be applied to the date we're checking, don't look further
2354
- if (found) return;
2355
-
2356
- var rule = this;
2357
-
2358
- // if the rules apply for the current year
2359
- if ($.inArray(year, rule[2]) > -1 || $.inArray('*', rule[2]) > -1)
2360
-
2361
- // if the rules apply for the current month
2362
- if ((typeof month != 'undefined' && $.inArray(month, rule[1]) > -1) || $.inArray('*', rule[1]) > -1)
2363
-
2364
- // if the rules apply for the current day
2365
- if ((typeof day != 'undefined' && $.inArray(day, rule[0]) > -1) || $.inArray('*', rule[0]) > -1) {
2366
-
2367
- // if custom class is to be applied whatever the day
2368
- // don't look any further
2369
- if (rule[3] == '*') return (found = class_name);
2370
-
2371
- // get the weekday
2372
- var weekday = new Date(year, month - 1, day).getDay();
2373
-
2374
- // if custom class is to be applied to weekday
2375
- // don't look any further
2376
- if ($.inArray(weekday, rule[3]) > -1) return (found = class_name);
2377
-
2378
- }
2379
-
2380
- });
2381
-
2382
- // if a custom class needs to be applied to the date we're checking, don't look further
2383
- if (found) return found;
2384
-
2385
- }
2386
-
2387
- // return what we've found
2388
- return found || '';
2389
-
2390
- };
2391
-
2392
- /**
2393
- * Generates an iFrame shim in Internet Explorer 6 so that the date picker appears above select boxes.
2394
- *
2395
- * @return void
2396
- *
2397
- * @access private
2398
- */
2399
- var iframeShim = function(action) {
2400
-
2401
- // this is necessary only if browser is Internet Explorer 6
2402
- if (browser.name == 'explorer' && browser.version == 6) {
2403
-
2404
- // if the iFrame was not yet created
2405
- // "undefined" evaluates as FALSE
2406
- if (!shim) {
2407
-
2408
- // the iFrame has to have the element's zIndex minus 1
2409
- var zIndex = to_int(datepicker.css('zIndex')) - 1;
2410
-
2411
- // create the iFrame
2412
- shim = $('<iframe>', {
2413
- 'src': 'javascript:document.write("")',
2414
- 'scrolling': 'no',
2415
- 'frameborder': 0,
2416
- css: {
2417
- 'zIndex': zIndex,
2418
- 'position': 'absolute',
2419
- 'top': -1000,
2420
- 'left': -1000,
2421
- 'width': datepicker.outerWidth(),
2422
- 'height': datepicker.outerHeight(),
2423
- 'filter': 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)',
2424
- 'display': 'none'
2425
- }
2426
- });
2427
-
2428
- // inject iFrame into DOM
2429
- $('body').append(shim);
2430
-
2431
- }
2432
-
2433
- // what do we need to do
2434
- switch (action) {
2435
-
2436
- // hide the iFrame?
2437
- case 'hide':
2438
-
2439
- // set the iFrame's display property to "none"
2440
- shim.hide();
2441
-
2442
- break;
2443
-
2444
- // show the iFrame?
2445
- default:
2446
-
2447
- // get date picker top and left position
2448
- var offset = datepicker.offset();
2449
-
2450
- // position the iFrame shim right underneath the date picker
2451
- // and set its display to "block"
2452
- shim.css({
2453
- 'top': offset.top,
2454
- 'left': offset.left,
2455
- 'display': 'block'
2456
- });
2457
-
2458
- }
2459
-
2460
- }
2461
-
2462
- };
2463
-
2464
- /**
2465
- * Checks if, according to the restrictions of the calendar and/or the values defined by the "disabled_dates"
2466
- * property, a day, a month or a year needs to be disabled.
2467
- *
2468
- * @param integer year The year to check
2469
- * @param integer month The month to check
2470
- * @param integer day The day to check
2471
- *
2472
- * @return boolean Returns TRUE if the given value is not disabled or FALSE otherwise
2473
- *
2474
- * @access private
2475
- */
2476
- var is_disabled = function(year, month, day) {
2477
-
2478
- // don't check bogus values
2479
- if ((undefined === year || isNaN(year)) && (undefined === month || isNaN(month)) && (undefined === day || isNaN(day))) return false;
2480
-
2481
- // this date picker cannot handle years before 1000, so we return false in this case
2482
- else if (year < 1000) return true;
2483
-
2484
- // if calendar has direction restrictions
2485
- if (!(!$.isArray(plugin.settings.direction) && to_int(plugin.settings.direction) === 0)) {
2486
-
2487
- var
2488
- // normalize and merge arguments then transform the result to an integer
2489
- now = to_int(str_concat(year, (typeof month != 'undefined' ? str_pad(month, 2) : ''), (typeof day != 'undefined' ? str_pad(day, 2) : ''))),
2490
-
2491
- // get the length of the argument
2492
- len = (now + '').length;
2493
-
2494
- // if we're checking days
2495
- if (len == 8 && (
2496
-
2497
- // day is before the first selectable date
2498
- (typeof start_date != 'undefined' && now < to_int(str_concat(first_selectable_year, str_pad(first_selectable_month, 2), str_pad(first_selectable_day, 2)))) ||
2499
-
2500
- // or day is after the last selectable date
2501
- (typeof end_date != 'undefined' && now > to_int(str_concat(last_selectable_year, str_pad(last_selectable_month, 2), str_pad(last_selectable_day, 2))))
2502
-
2503
- // day needs to be disabled
2504
- )) return true;
2505
-
2506
- // if we're checking months
2507
- else if (len == 6 && (
2508
-
2509
- // month is before the first selectable month
2510
- (typeof start_date != 'undefined' && now < to_int(str_concat(first_selectable_year, str_pad(first_selectable_month, 2)))) ||
2511
-
2512
- // or day is after the last selectable date
2513
- (typeof end_date != 'undefined' && now > to_int(str_concat(last_selectable_year, str_pad(last_selectable_month, 2))))
2514
-
2515
- // month needs to be disabled
2516
- )) return true;
2517
-
2518
- // if we're checking years
2519
- else if (len == 4 && (
2520
-
2521
- // year is before the first selectable year
2522
- (typeof start_date != 'undefined' && now < first_selectable_year) ||
2523
-
2524
- // or day is after the last selectable date
2525
- (typeof end_date != 'undefined' && now > last_selectable_year)
2526
-
2527
- // year needs to be disabled
2528
- )) return true;
2529
-
2530
- }
2531
-
2532
- // if month is given as argument, increment it (as JavaScript uses 0 for January, 1 for February...)
2533
- if (typeof month != 'undefined') month = month + 1;
2534
-
2535
- // by default, we assume the day/month/year is not enabled nor disabled
2536
- var disabled = false, enabled = false;
2537
-
2538
- // if there are rules for disabling dates
2539
- if ($.isArray(disabled_dates) && disabled_dates.length)
2540
-
2541
- // iterate through the rules for disabling dates
2542
- $.each(disabled_dates, function() {
2543
-
2544
- // if the date is to be disabled, don't look any further
2545
- if (disabled) return;
2546
-
2547
- var rule = this;
2548
-
2549
- // if the rules apply for the current year
2550
- if ($.inArray(year, rule[2]) > -1 || $.inArray('*', rule[2]) > -1)
2551
-
2552
- // if the rules apply for the current month
2553
- if ((typeof month != 'undefined' && $.inArray(month, rule[1]) > -1) || $.inArray('*', rule[1]) > -1)
2554
-
2555
- // if the rules apply for the current day
2556
- if ((typeof day != 'undefined' && $.inArray(day, rule[0]) > -1) || $.inArray('*', rule[0]) > -1) {
2557
-
2558
- // if day is to be disabled whatever the day
2559
- // don't look any further
2560
- if (rule[3] == '*') return (disabled = true);
2561
-
2562
- // get the weekday
2563
- var weekday = new Date(year, month - 1, day).getDay();
2564
-
2565
- // if weekday is to be disabled
2566
- // don't look any further
2567
- if ($.inArray(weekday, rule[3]) > -1) return (disabled = true);
2568
-
2569
- }
2570
-
2571
- });
2572
-
2573
- // if there are rules that explicitly enable dates
2574
- if (enabled_dates)
2575
-
2576
- // iterate through the rules for enabling dates
2577
- $.each(enabled_dates, function() {
2578
-
2579
- // if the date is to be enabled, don't look any further
2580
- if (enabled) return;
2581
-
2582
- var rule = this;
2583
-
2584
- // if the rules apply for the current year
2585
- if ($.inArray(year, rule[2]) > -1 || $.inArray('*', rule[2]) > -1) {
2586
-
2587
- // the year is enabled
2588
- enabled = true;
2589
-
2590
- // if we're also checking months
2591
- if (typeof month != 'undefined') {
2592
-
2593
- // we assume the month is enabled
2594
- enabled = true;
2595
-
2596
- // if the rules apply for the current month
2597
- if ($.inArray(month, rule[1]) > -1 || $.inArray('*', rule[1]) > -1) {
2598
-
2599
- // if we're also checking days
2600
- if (typeof day != 'undefined') {
2601
-
2602
- // we assume the day is enabled
2603
- enabled = true;
2604
-
2605
- // if the rules apply for the current day
2606
- if ($.inArray(day, rule[0]) > -1 || $.inArray('*', rule[0]) > -1) {
2607
-
2608
- // if day is to be enabled whatever the day
2609
- // don't look any further
2610
- if (rule[3] == '*') return (enabled = true);
2611
-
2612
- // get the weekday
2613
- var weekday = new Date(year, month - 1, day).getDay();
2614
-
2615
- // if weekday is to be enabled
2616
- // don't look any further
2617
- if ($.inArray(weekday, rule[3]) > -1) return (enabled = true);
2618
-
2619
- // if we get this far, it means the day is not enabled
2620
- enabled = false;
2621
-
2622
- // if day is not enabled
2623
- } else enabled = false;
2624
-
2625
- }
2626
-
2627
- // if month is not enabled
2628
- } else enabled = false;
2629
-
2630
- }
2631
-
2632
- }
2633
-
2634
- });
2635
-
2636
- // if checked date is enabled, return false
2637
- if (enabled_dates && enabled) return false;
2638
-
2639
- // if checked date is disabled return false
2640
- else if (disabled_dates && disabled) return true;
2641
-
2642
- // if script gets this far it means that the day/month/year doesn't need to be disabled
2643
- return false;
2644
-
2645
- };
2646
-
2647
- /**
2648
- * Checks whether a value is an integer number.
2649
- *
2650
- * @param mixed value Value to check
2651
- *
2652
- * @return Returns TRUE if the value represents an integer number, or FALSE otherwise
2653
- *
2654
- * @access private
2655
- */
2656
- var is_integer = function(value) {
2657
-
2658
- // return TRUE if value represents an integer number, or FALSE otherwise
2659
- return (value + '').match(/^\-?[0-9]+$/) ? true : false;
2660
-
2661
- };
2662
-
2663
- /**
2664
- * Sets the caption in the header of the date picker and enables or disables navigation buttons when necessary.
2665
- *
2666
- * @param string caption String that needs to be displayed in the header
2667
- *
2668
- * @return void
2669
- *
2670
- * @access private
2671
- */
2672
- var manage_header = function(caption) {
2673
-
2674
- // if "selected_month" has a value
2675
- // $.isNumeric is available only from jQuery 1.7 - thanks to birla for the fix!
2676
- if (!isNaN(parseFloat(selected_month)) && isFinite(selected_month))
2677
-
2678
- caption = caption.replace(/\bm\b|\bn\b|\bF\b|\bM\b/, function (match) {
2679
-
2680
- switch (match) {
2681
-
2682
- // month number, prefixed with 0
2683
- case 'm':
2684
- return str_pad(selected_month + 1, 2);
2685
-
2686
- // month number, not prefixed with 0
2687
- case 'n':
2688
- return selected_month + 1;
2689
-
2690
- // full month name
2691
- case 'F':
2692
- return plugin.settings.months[selected_month];
2693
-
2694
- // month name, three letters
2695
- case 'M':
2696
- return ($.isArray(plugin.settings.months_abbr) && undefined !== plugin.settings.months_abbr[selected_month] ? plugin.settings.months_abbr[selected_month] : plugin.settings.months[selected_month].substr(0, 3));
2697
-
2698
- // unknown replace
2699
- default:
2700
- return match;
2701
-
2702
- }
2703
-
2704
- });
2705
-
2706
- // if "selected_year" has a value
2707
- // $.isNumeric is available only from jQuery 1.7 - thanks to birla for the fix!
2708
- if (!isNaN(parseFloat(selected_year)) && isFinite(selected_year))
2709
-
2710
- // replace year-related patterns
2711
- caption =
2712
-
2713
- caption.
2714
-
2715
- // year as four digits
2716
- replace(/\bY\b/, selected_year).
2717
-
2718
- // year as two digits
2719
- replace(/\by\b/, (selected_year + '').substr(2)).
2720
-
2721
- // lower limit of year as two or four digits
2722
- replace(/\bY1\b/i, selected_year - 7).
2723
-
2724
- // upper limit of year as two or four digits
2725
- replace(/\bY2\b/i, selected_year + 4);
2726
-
2727
- // update the caption in the header
2728
- $('.dp_caption', header).html(caption);
2729
-
2730
- };
2731
-
2732
- /**
2733
- * Shows the appropriate view (days, months or years) according to the current value of the "view" property.
2734
- *
2735
- * @return void
2736
- *
2737
- * @access private
2738
- */
2739
- var manage_views = function() {
2740
-
2741
- // if the day picker was not yet generated
2742
- if (daypicker.text() === '' || view == 'days') {
2743
-
2744
- // if the day picker was not yet generated
2745
- if (daypicker.text() === '') {
2746
-
2747
- // if date picker is not always visible
2748
- if (!plugin.settings.always_visible)
2749
-
2750
- // temporarily set the date picker's left outside of view
2751
- // so that we can later grab its width and height
2752
- datepicker.css('left', -1000);
2753
-
2754
- // temporarily make the date picker visible
2755
- // so that we can later grab its width and height
2756
- datepicker.css('visibility', 'visible');
2757
-
2758
- // generate the day picker
2759
- generate_daypicker();
2760
-
2761
- // get the day picker's width and height
2762
- var width = daypicker.outerWidth(),
2763
- height = daypicker.outerHeight();
2764
-
2765
- // make the month picker have the same size as the day picker
2766
- monthpicker.css({
2767
- 'width': width,
2768
- 'height': height
2769
- });
2770
-
2771
- // make the year picker have the same size as the day picker
2772
- yearpicker.css({
2773
- 'width': width,
2774
- 'height': height
2775
- });
2776
-
2777
- // make the header and the footer have the same size as the day picker
2778
- header.css('width', width);
2779
- footer.css('width', width);
2780
-
2781
- // hide the date picker again
2782
- datepicker.css('visibility', '').addClass('dp_hidden');
2783
-
2784
- // if the day picker was previously generated at least once
2785
- // generate the day picker
2786
- } else generate_daypicker();
2787
-
2788
- // hide the year and the month pickers
2789
- monthpicker.hide();
2790
- yearpicker.hide();
2791
-
2792
- // if the view is "months"
2793
- } else if (view == 'months') {
2794
-
2795
- // generate the month picker
2796
- generate_monthpicker();
2797
-
2798
- // hide the day and the year pickers
2799
- daypicker.hide();
2800
- yearpicker.hide();
2801
-
2802
- // if the view is "years"
2803
- } else if (view == 'years') {
2804
-
2805
- // generate the year picker
2806
- generate_yearpicker();
2807
-
2808
- // hide the day and the month pickers
2809
- daypicker.hide();
2810
- monthpicker.hide();
2811
-
2812
- }
2813
-
2814
- // if a callback function exists for when navigating through months/years
2815
- if (plugin.settings.onChange && typeof plugin.settings.onChange == 'function' && undefined !== view) {
2816
-
2817
- // get the "active" elements in the view (ignoring the disabled ones)
2818
- var elements = (view == 'days' ?
2819
- daypicker.find('td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month)') :
2820
- (view == 'months' ?
2821
- monthpicker.find('td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month)') :
2822
- yearpicker.find('td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month)')));
2823
-
2824
- // iterate through the active elements
2825
- // and attach a "date" data attribute to each element in the form of
2826
- // YYYY-MM-DD if the view is "days"
2827
- // YYYY-MM if the view is "months"
2828
- // YYYY if the view is "years"
2829
- // so it's easy to identify elements in the list
2830
- elements.each(function() {
2831
-
2832
- var matches;
2833
-
2834
- // if view is "days"
2835
- if (view == 'days') {
2836
-
2837
- // if date is from a next/previous month and is selectable
2838
- if ($(this).hasClass('dp_not_in_month_selectable')) {
2839
-
2840
- // extract date from the attached class
2841
- matches = $(this).attr('class').match(/date\_([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])/);
2842
-
2843
- // attach a "date" data attribute to each element in the form of of YYYY-MM-DD for easily identifying sought elements
2844
- $(this).data('date', matches[1] + '-' + matches[2] + '-' + matches[3]);
2845
-
2846
- // if date is from the currently selected month
2847
- } else
2848
-
2849
- // attach a "date" data attribute to each element in the form of of YYYY-MM-DD for easily identifying sought elements
2850
- $(this).data('date', selected_year + '-' + str_pad(selected_month + 1, 2) + '-' + str_pad(to_int($(this).text()), 2));
2851
-
2852
- // if view is "months"
2853
- } else if (view == 'months') {
2854
-
2855
- // get the month's number for the element's class
2856
- matches = $(this).attr('class').match(/dp\_month\_([0-9]+)/);
2857
-
2858
- // attach a "date" data attribute to each element in the form of of YYYY-MM for easily identifying sought elements
2859
- $(this).data('date', selected_year + '-' + str_pad(to_int(matches[1]) + 1, 2));
2860
-
2861
- // if view is "years"
2862
- } else
2863
-
2864
- // attach a "date" data attribute to each element in the form of of YYYY for easily identifying sought elements
2865
- $(this).data('date', to_int($(this).text()));
2866
-
2867
- });
2868
-
2869
- // execute the callback function and send as arguments the current view, the elements in the view, and
2870
- // the element the plugin is attached to
2871
- plugin.settings.onChange.call($element, view, elements, $element);
2872
-
2873
- }
2874
-
2875
- // assume the footer is visible
2876
- footer.show();
2877
-
2878
- // if the button for clearing a previously selected date needs to be visible all the time,
2879
- // or the "Clear" button needs to be shown only when a date was previously selected, and now it's the case,
2880
- // or the date picker is always visible and the "Clear" button was not explicitly disabled
2881
- if (
2882
- plugin.settings.show_clear_date === true ||
2883
- (plugin.settings.show_clear_date === 0 && $element.val() !== '') ||
2884
- (plugin.settings.always_visible && plugin.settings.show_clear_date !== false)
2885
- ) {
2886
-
2887
- // show the "Clear" button
2888
- cleardate.show();
2889
-
2890
- // if the "Today" button is visible
2891
- if (show_select_today) {
2892
-
2893
- // show it, and set it's width to 50% of the available space
2894
- selecttoday.css('width', '50%');
2895
-
2896
- // the "Clear date" button only takes up 50% of the available space
2897
- cleardate.css('width', '50%');
2898
-
2899
- // if the "Today" button is not visible
2900
- } else {
2901
-
2902
- // hide the "Today" button
2903
- selecttoday.hide();
2904
-
2905
- // the "Clear date" button takes up 100% of the available space
2906
- cleardate.css('width', '100%');
2907
-
2908
- }
2909
-
2910
- // otherwise
2911
- } else {
2912
-
2913
- // hide the "Clear" button
2914
- cleardate.hide();
2915
-
2916
- // if the "Today" button is visible, it will now take up all the available space
2917
- if (show_select_today) selecttoday.show().css('width', '100%');
2918
-
2919
- // if the "Today" button is also not visible, hide the footer entirely
2920
- else footer.hide();
2921
-
2922
- }
2923
-
2924
-
2925
- };
2926
-
2927
- /**
2928
- * Puts the specified date in the element the plugin is attached to, and hides the date picker.
2929
- *
2930
- * @param integer year The year
2931
- *
2932
- * @param integer month The month
2933
- *
2934
- * @param integer day The day
2935
- *
2936
- * @param string view The view from where the method was called
2937
- *
2938
- * @param object cell The element that was clicked
2939
- *
2940
- * @return void
2941
- *
2942
- * @access private
2943
- */
2944
- var select_date = function(year, month, day, view, cell) {
2945
-
2946
- var
2947
-
2948
- // construct a new date object from the arguments
2949
- default_date = new Date(year, month, day, 12, 0, 0),
2950
-
2951
- // pointer to the cells in the current view
2952
- view_cells = (view == 'days' ? daypicker_cells : (view == 'months' ? monthpicker_cells : yearpicker_cells)),
2953
-
2954
- // the selected date, formatted correctly
2955
- selected_value = format(default_date);
2956
-
2957
- // set the currently selected and formated date as the value of the element the plugin is attached to
2958
- $element.val(selected_value);
2959
-
2960
- // if date picker is always visible
2961
- if (plugin.settings.always_visible) {
2962
-
2963
- // extract the date parts and reassign values to these variables
2964
- // so that everything will be correctly highlighted
2965
- default_month = default_date.getMonth();
2966
- selected_month = default_date.getMonth();
2967
- default_year = default_date.getFullYear();
2968
- selected_year = default_date.getFullYear();
2969
- default_day = default_date.getDate();
2970
-
2971
- // remove the "selected" class from all cells in the current view
2972
- view_cells.removeClass('dp_selected');
2973
-
2974
- // add the "selected" class to the currently selected cell
2975
- cell.addClass('dp_selected');
2976
-
2977
- // if we're on the "days" view and days from other months are selectable and one of those days was
2978
- // selected, repaint the datepicker so it will take us to the selected month
2979
- if (view == 'days' && cell.hasClass('dp_not_in_month_selectable')) plugin.show();
2980
-
2981
- }
2982
-
2983
- // hide the date picker
2984
- plugin.hide();
2985
-
2986
- // updates value for the date picker whose starting date depends on the selected date (if any)
2987
- update_dependent(default_date);
2988
-
2989
- // if a callback function exists for when selecting a date
2990
- if (plugin.settings.onSelect && typeof plugin.settings.onSelect == 'function')
2991
-
2992
- // execute the callback function
2993
- // make "this" inside the callback function refer to the element the date picker is attached to
2994
- plugin.settings.onSelect.call($element, selected_value, year + '-' + str_pad(month + 1, 2) + '-' + str_pad(day, 2), default_date, $element, getWeekNumber(default_date));
2995
-
2996
- // move focus to the element the plugin is attached to
2997
- $element.focus();
2998
-
2999
- };
3000
-
3001
- /**
3002
- * Concatenates any number of arguments and returns them as string.
3003
- *
3004
- * @return string Returns the concatenated values.
3005
- *
3006
- * @access private
3007
- */
3008
- var str_concat = function() {
3009
-
3010
- var str = '';
3011
-
3012
- // concatenate as string
3013
- for (var i = 0; i < arguments.length; i++) str += (arguments[i] + '');
3014
-
3015
- // return the concatenated values
3016
- return str;
3017
-
3018
- };
3019
-
3020
- /**
3021
- * Left-pad a string to a certain length with zeroes.
3022
- *
3023
- * @param string str The string to be padded.
3024
- *
3025
- * @param integer len The length to which the string must be padded
3026
- *
3027
- * @return string Returns the string left-padded with leading zeroes
3028
- *
3029
- * @access private
3030
- */
3031
- var str_pad = function(str, len) {
3032
-
3033
- // make sure argument is a string
3034
- str += '';
3035
-
3036
- // pad with leading zeroes until we get to the desired length
3037
- while (str.length < len) str = '0' + str;
3038
-
3039
- // return padded string
3040
- return str;
3041
-
3042
- };
3043
-
3044
- /**
3045
- * Returns the integer representation of a string
3046
- *
3047
- * @return int Returns the integer representation of the string given as argument
3048
- *
3049
- * @access private
3050
- */
3051
- var to_int = function(str) {
3052
-
3053
- // return the integer representation of the string given as argument
3054
- return parseInt(str, 10);
3055
-
3056
- };
3057
-
3058
- /**
3059
- * Updates the paired date picker (whose starting date depends on the value of the current date picker)
3060
- *
3061
- * @param date date A JavaScript date object representing the currently selected date
3062
- *
3063
- * @return void
3064
- *
3065
- * @access private
3066
- */
3067
- var update_dependent = function(date) {
3068
-
3069
- // if the pair element exists
3070
- if (plugin.settings.pair) {
3071
-
3072
- // iterate through the pair elements (as there may be more than just one)
3073
- $.each(plugin.settings.pair, function() {
3074
-
3075
- var $pair = $(this);
3076
-
3077
- // chances are that in the beginning the pair element doesn't have the Zebra_DatePicker attached to it yet
3078
- // (as the "start" element is usually created before the "end" element)
3079
- // so we'll have to rely on "data" to send the starting date to the pair element
3080
-
3081
- // therefore, if Zebra_DatePicker is not yet attached
3082
- if (!($pair.data && $pair.data('Zebra_DatePicker')))
3083
-
3084
- // set the starting date like this
3085
- $pair.data('zdp_reference_date', date);
3086
-
3087
- // if Zebra_DatePicker is attached to the pair element
3088
- else {
3089
-
3090
- // reference the date picker object attached to the other element
3091
- var dp = $pair.data('Zebra_DatePicker');
3092
-
3093
- // update the other date picker's starting date
3094
- // the value depends on the original value of the "direction" attribute
3095
- // (also, if the pair date picker does not have a direction, set it to 1)
3096
- dp.update({
3097
- 'reference_date': date,
3098
- 'direction': dp.settings.direction === 0 ? 1 : dp.settings.direction
3099
- });
3100
-
3101
- // if the other date picker is always visible, update the visuals now
3102
- if (dp.settings.always_visible) dp.show();
3103
-
3104
- }
3105
-
3106
- });
3107
-
3108
- }
3109
-
3110
- };
3111
-
3112
- /**
3113
- * Calculate the ISO 8601 week number for a given date.
3114
- *
3115
- * Code is based on the algorithm at http://www.tondering.dk/claus/cal/week.php#calcweekno
3116
- */
3117
- var getWeekNumber = function(date) {
3118
-
3119
- var y = date.getFullYear(),
3120
- m = date.getMonth() + 1,
3121
- d = date.getDate(),
3122
- a, b, c, s, e, f, g, n, w;
3123
-
3124
- // If month jan. or feb.
3125
- if (m < 3) {
3126
-
3127
- a = y - 1;
3128
- b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
3129
- c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
3130
- s = b - c;
3131
- e = 0;
3132
- f = d - 1 + 31 * (m - 1);
3133
-
3134
- // If month mar. through dec.
3135
- } else {
3136
-
3137
- a = y;
3138
- b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
3139
- c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
3140
- s = b - c;
3141
- e = s + 1;
3142
- f = d + ((153 * (m - 3) + 2) / 5 | 0) + 58 + s;
3143
-
3144
- }
3145
-
3146
- g = (a + b) % 7;
3147
- // ISO Weekday (0 is monday, 1 is tuesday etc.)
3148
- d = (f + g - e) % 7;
3149
- n = f + 3 - d;
3150
-
3151
- if (n < 0) w = 53 - ((g - s) / 5 | 0);
3152
-
3153
- else if (n > 364 + s) w = 1;
3154
-
3155
- else w = (n / 7 | 0) + 1;
3156
-
3157
- return w;
3158
-
3159
- };
3160
-
3161
- // since with jQuery 1.9.0 the $.browser object was removed, we rely on this piece of code from
3162
- // http://www.quirksmode.org/js/detect.html to detect the browser
3163
- var browser = {
3164
- init: function () {
3165
- this.name = this.searchString(this.dataBrowser) || '';
3166
- this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || '';
3167
- },
3168
- searchString: function (data) {
3169
- for (var i=0;i<data.length;i++) {
3170
- var dataString = data[i].string;
3171
- var dataProp = data[i].prop;
3172
- this.versionSearchString = data[i].versionSearch || data[i].identity;
3173
- if (dataString) {
3174
- if (dataString.indexOf(data[i].subString) != -1)
3175
- return data[i].identity;
3176
- }
3177
- else if (dataProp)
3178
- return data[i].identity;
3179
- }
3180
- },
3181
- searchVersion: function (dataString) {
3182
- var index = dataString.indexOf(this.versionSearchString);
3183
- if (index == -1) return;
3184
- return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
3185
- },
3186
- dataBrowser: [
3187
- {
3188
- string: navigator.userAgent,
3189
- subString: 'Firefox',
3190
- identity: 'firefox'
3191
- },
3192
- {
3193
- string: navigator.userAgent,
3194
- subString: 'MSIE',
3195
- identity: 'explorer',
3196
- versionSearch: 'MSIE'
3197
- }
3198
- ]
3199
- };
3200
-
3201
- browser.init();
3202
-
3203
- // initialize the plugin
3204
- init();
3205
-
3206
- };
3207
-
3208
- $.fn.Zebra_DatePicker = function(options) {
3209
-
3210
- // iterate through all the elements to which we need to attach the date picker to
3211
- return this.each(function() {
3212
-
3213
- // if element has a date picker already attached
3214
- if (undefined !== $(this).data('Zebra_DatePicker'))
3215
-
3216
- // remove the attached date picker
3217
- $(this).data('Zebra_DatePicker').destroy();
3218
-
3219
- // create an instance of the plugin
3220
- var plugin = new $.Zebra_DatePicker(this, options);
3221
-
3222
- // save a reference to the newly created object
3223
- $(this).data('Zebra_DatePicker', plugin);
3224
-
3225
- });
3226
-
3227
- };
3228
-
3229
- }));