| rev |
line source |
|
bsw@11
|
1 //
|
|
bsw@11
|
2 // Copyright (c) 2009 Public Software Group e. V., Berlin
|
|
bsw@11
|
3 //
|
|
bsw@11
|
4 // Permission is hereby granted, free of charge, to any person obtaining a
|
|
bsw@11
|
5 // copy of this software and associated documentation files (the
|
|
bsw@11
|
6 // "Software"), to deal in the Software without restriction, including
|
|
bsw@11
|
7 // without limitation the rights to use, copy, modify, merge, publish,
|
|
bsw@11
|
8 // distribute, sublicense, and/or sell copies of the Software, and to
|
|
bsw@11
|
9 // permit persons to whom the Software is furnished to do so, subject to
|
|
bsw@11
|
10 // the following conditions:
|
|
bsw@11
|
11 //
|
|
bsw@11
|
12 // The above copyright notice and this permission notice shall be included
|
|
bsw@11
|
13 // in all copies or substantial portions of the Software.
|
|
bsw@11
|
14 //
|
|
bsw@11
|
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
bsw@11
|
16 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
bsw@11
|
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
bsw@11
|
18 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
bsw@11
|
19 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
bsw@11
|
20 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
bsw@11
|
21 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
bsw@11
|
22 //
|
|
bsw@11
|
23
|
|
bsw@11
|
24 //
|
|
bsw@11
|
25 // All date calculations are based on the gregorian calender, also for
|
|
bsw@11
|
26 // dates before 1582 (before the gegorian calendar was introduced).
|
|
bsw@11
|
27 // The supported range is from January 1st 0001 up to December 31st 9999.
|
|
bsw@11
|
28 //
|
|
bsw@11
|
29 // gregor_daycount({year: <year>, month: <month>, day: <day>}) returns
|
|
bsw@11
|
30 // the number of days between the given date and January 1st 0001 (greg.).
|
|
bsw@11
|
31 //
|
|
bsw@11
|
32 // gregor_completeDate({year: <year>, month: <month>, day: <day>}) returns
|
|
bsw@11
|
33 // a structure (an object) with the following properties:
|
|
bsw@11
|
34 // - daycount (days since January 1st 0001, see gregor_daycount)
|
|
bsw@11
|
35 // - year (with century)
|
|
bsw@11
|
36 // - month (from 1 to 12)
|
|
bsw@11
|
37 // - day (from 1 to 28, 29, 30 or 31)
|
|
bsw@11
|
38 // - iso_string (string with format YYYY-MM-DD)
|
|
bsw@11
|
39 // - us_weekday (from 0 for Sunday to 6 for Monday)
|
|
bsw@11
|
40 // - iso_weekday (from 0 for Monday to 6 for Sunday)
|
|
bsw@11
|
41 // - iso_weekyear (Year containing greater part of week st. w. Monday)
|
|
bsw@11
|
42 // - iso_week (from 1 to 52 or 53)
|
|
bsw@11
|
43 // - us_week (from 1 to 53 or 54)
|
|
bsw@11
|
44 //
|
|
bsw@11
|
45 // The structure (the object) passed as parameter to gregor_daycount or
|
|
bsw@11
|
46 // gregor_completeDate may describe a date in the following ways:
|
|
bsw@11
|
47 // - daycount
|
|
bsw@11
|
48 // - year, month, day
|
|
bsw@11
|
49 // - year, us_week, us_weekday
|
|
bsw@11
|
50 // - year, iso_week, iso_weekday
|
|
bsw@11
|
51 // - iso_weekyear, iso_week, iso_weekday
|
|
bsw@11
|
52 //
|
|
bsw@11
|
53 // gregor_sheet({...}) returns a calendar sheet as DOM object. The
|
|
bsw@11
|
54 // structure (the object) passed to the function as an argument is altered
|
|
bsw@11
|
55 // by the function and used to store state variables. Initially it can
|
|
bsw@11
|
56 // contain the following fields:
|
|
bsw@11
|
57 // - year (year to show, defaults to todays year)
|
|
bsw@11
|
58 // - month (month to show, defaults to todays month)
|
|
bsw@11
|
59 // - today (structure describing a day, e.g. year, month, day)
|
|
bsw@11
|
60 // - selected (structure describing a day, e.g. year, month, day)
|
|
bsw@11
|
61 // - navigation ("enabled", "disabled", "hidden", default "enabled")
|
|
bsw@11
|
62 // - week_mode ("iso" or "us", defaults to "iso")
|
|
bsw@11
|
63 // - week_numbers ("left", "right" or null, defaults to null)
|
|
bsw@11
|
64 // - month_names (e.g. ["January", "Feburary", ...])
|
|
bsw@11
|
65 // - weekday_names (e.g. ["Mon", "Tue", ...] or ["Sun", "Mon", ...])
|
|
bsw@11
|
66 // - day_callback (function to render a cell)
|
|
bsw@11
|
67 // - select_callback (function to be called, when a date was selected)
|
|
bsw@11
|
68 // - element (for internal use only)
|
|
bsw@11
|
69 // If "today" is undefined, it is automatically intitialized with the
|
|
bsw@11
|
70 // current clients date. If "selected" is undefined or null, no date is
|
|
bsw@11
|
71 // be initially selected. It is mandatory to provide month_names and
|
|
bsw@11
|
72 // weekday_names.
|
|
bsw@11
|
73 //
|
|
bsw@11
|
74 // gregor_addGui({...}) alters a referenced input field in a way that
|
|
bsw@11
|
75 // focussing on it causes a calendar being shown at its right side, where a
|
|
bsw@11
|
76 // date can be selected. The structure (the object) passed to this function
|
|
bsw@11
|
77 // is only evaluated once, and never modified. All options except "element"
|
|
bsw@11
|
78 // of the gregor_sheet({...}) function may be used as options to
|
|
bsw@11
|
79 // gregor_addGui({...}) as well. In addition an "element_id" must be
|
|
bsw@11
|
80 // provided as argument, containing the id of a text input field. The
|
|
bsw@11
|
81 // behaviour caused by the options "selected" and "select_callback" are
|
|
bsw@11
|
82 // slightly different: If "selected" === undefined, then the current value
|
|
bsw@11
|
83 // of the text field referenced by "element_id" will be parsed and used as
|
|
bsw@11
|
84 // date selection. If "selected" === null, then no date will be initially
|
|
bsw@11
|
85 // selected, and the text field will be cleared. The "select_callback"
|
|
bsw@11
|
86 // function is always called once with the pre-selected date (or with null,
|
|
bsw@11
|
87 // if no date is initially selected). Whenever the selected date is changed
|
|
bsw@11
|
88 // or unselected later, the callback function is called again with the new
|
|
bsw@11
|
89 // date (or with null, in case of deselection).
|
|
bsw@11
|
90 //
|
|
bsw@11
|
91 // EXAMPLE:
|
|
bsw@11
|
92 //
|
|
bsw@11
|
93 // <input type="text" id="test_field" name="test_field" value=""/>
|
|
bsw@11
|
94 // <script type="text/javascript">
|
|
bsw@11
|
95 // gregor_addGui({
|
|
bsw@11
|
96 // element_id: 'test_field',
|
|
bsw@11
|
97 // month_names: [
|
|
bsw@11
|
98 // "January", "February", "March", "April", "May", "June",
|
|
bsw@11
|
99 // "July", "August", "September", "October", "November", "December"
|
|
bsw@11
|
100 // ],
|
|
bsw@11
|
101 // weekday_names: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
|
|
bsw@11
|
102 // week_numbers: "left"
|
|
bsw@11
|
103 // });
|
|
bsw@11
|
104 // </script>
|
|
bsw@11
|
105 //
|
|
bsw@11
|
106
|
|
bsw@11
|
107
|
|
bsw@11
|
108
|
|
bsw@11
|
109
|
|
bsw@11
|
110 // Internal constants and helper functions for date calculation
|
|
bsw@11
|
111
|
|
bsw@11
|
112
|
|
bsw@11
|
113 gregor_c1 = 365; // days of a non-leap year
|
|
bsw@11
|
114 gregor_c4 = 4 * gregor_c1 + 1; // days of a full 4 year cycle
|
|
bsw@11
|
115 gregor_c100 = 25 * gregor_c4 - 1; // days of a full 100 year cycle
|
|
bsw@11
|
116 gregor_c400 = 4 * gregor_c100 + 1; // days of a full 400 year cycle
|
|
bsw@11
|
117
|
|
bsw@11
|
118 gregor_normalMonthOffsets = [
|
|
bsw@11
|
119 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
|
|
bsw@11
|
120 ];
|
|
bsw@11
|
121
|
|
bsw@11
|
122 function gregor_getMonthOffset(year, month) {
|
|
bsw@11
|
123 if (
|
|
bsw@11
|
124 (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) &&
|
|
bsw@11
|
125 month > 2
|
|
bsw@11
|
126 ) return gregor_normalMonthOffsets[month-1] + 1;
|
|
bsw@11
|
127 else return gregor_normalMonthOffsets[month-1];
|
|
bsw@11
|
128 }
|
|
bsw@11
|
129
|
|
bsw@11
|
130 function gregor_formatInteger(int, digits) {
|
|
bsw@11
|
131 var result = int.toFixed();
|
|
bsw@11
|
132 if (digits != null) {
|
|
bsw@11
|
133 while (result.length < digits) result = "0" + result;
|
|
bsw@11
|
134 }
|
|
bsw@11
|
135 return result;
|
|
bsw@11
|
136 }
|
|
bsw@11
|
137
|
|
bsw@11
|
138
|
|
bsw@11
|
139
|
|
bsw@11
|
140 // Calculate days since January 1st 0001 (Gegorian) for a given date
|
|
bsw@11
|
141
|
|
bsw@11
|
142
|
|
bsw@11
|
143 function gregor_daycount(obj) {
|
|
bsw@11
|
144 if (
|
|
bsw@11
|
145 obj.daycount >= 0 && obj.daycount <= 3652058 && obj.daycount % 1 == 0
|
|
bsw@11
|
146 ) {
|
|
bsw@11
|
147 return obj.daycount;
|
|
bsw@11
|
148 } else if (
|
|
bsw@11
|
149 obj.year >= 1 && obj.year <= 9999 && obj.year % 1 == 0 &&
|
|
bsw@11
|
150 obj.month >= 1 && obj.month <= 12 && obj.month % 1 == 0 &&
|
|
bsw@11
|
151 obj.day >= 0 && obj.day <= 31 && obj.day % 1 == 0
|
|
bsw@11
|
152 ) {
|
|
bsw@11
|
153 var n400 = Math.floor((obj.year-1) / 400);
|
|
bsw@11
|
154 var r400 = (obj.year-1) % 400;
|
|
bsw@11
|
155 var n100 = Math.floor(r400 / 100);
|
|
bsw@11
|
156 var r100 = r400 % 100;
|
|
bsw@11
|
157 var n4 = Math.floor(r100 / 4);
|
|
bsw@11
|
158 var n1 = r100 % 4;
|
|
bsw@11
|
159 return (
|
|
bsw@11
|
160 gregor_c400 * n400 +
|
|
bsw@11
|
161 gregor_c100 * n100 +
|
|
bsw@11
|
162 gregor_c4 * n4 +
|
|
bsw@11
|
163 gregor_c1 * n1 +
|
|
bsw@11
|
164 gregor_getMonthOffset(obj.year, obj.month) + (obj.day - 1)
|
|
bsw@11
|
165 );
|
|
bsw@11
|
166 } else if (
|
|
bsw@11
|
167 (
|
|
bsw@11
|
168 (
|
|
bsw@11
|
169 obj.year >= 1 && obj.year <= 9999 &&
|
|
bsw@11
|
170 obj.year % 1 == 0 && obj.iso_weekyear == null
|
|
bsw@11
|
171 ) || (
|
|
bsw@11
|
172 obj.iso_weekyear >= 1 && obj.iso_weekyear <= 9999 &&
|
|
bsw@11
|
173 obj.iso_weekyear % 1 == 0 && obj.year == null
|
|
bsw@11
|
174 )
|
|
bsw@11
|
175 ) &&
|
|
bsw@11
|
176 obj.iso_week >= 0 && obj.iso_week <= 53 && obj.iso_week % 1 == 0 &&
|
|
bsw@11
|
177 obj.iso_weekday >= 0 && obj.iso_weekday <= 6 &&
|
|
bsw@11
|
178 obj.iso_weekday % 1 == 0
|
|
bsw@11
|
179 ) {
|
|
bsw@11
|
180 var jan4th = gregor_daycount({
|
|
bsw@11
|
181 year: (obj.year != null) ? obj.year : obj.iso_weekyear,
|
|
bsw@11
|
182 month: 1,
|
|
bsw@11
|
183 day: 4
|
|
bsw@11
|
184 });
|
|
bsw@11
|
185 var monday0 = jan4th - (jan4th % 7) - 7; // monday of week 0
|
|
bsw@11
|
186 return monday0 + 7 * obj.iso_week + obj.iso_weekday;
|
|
bsw@11
|
187 } else if (
|
|
bsw@11
|
188 obj.year >= 1 && obj.year <= 9999 && obj.year % 1 == 0 &&
|
|
bsw@11
|
189 obj.us_week >= 0 && obj.us_week <= 54 && obj.us_week % 1 == 0 &&
|
|
bsw@11
|
190 obj.us_weekday >= 0 && obj.us_weekday <= 6 && obj.us_weekday % 1 == 0
|
|
bsw@11
|
191 ) {
|
|
bsw@11
|
192 var jan1st = gregor_daycount({
|
|
bsw@11
|
193 year: obj.year,
|
|
bsw@11
|
194 month: 1,
|
|
bsw@11
|
195 day: 1
|
|
bsw@11
|
196 });
|
|
bsw@11
|
197 var sunday0 = jan1st - ((jan1st+1) % 7) - 7; // sunday of week 0
|
|
bsw@11
|
198 return sunday0 + 7 * obj.us_week + obj.us_weekday;
|
|
bsw@11
|
199 }
|
|
bsw@11
|
200 }
|
|
bsw@11
|
201
|
|
bsw@11
|
202
|
|
bsw@11
|
203
|
|
bsw@11
|
204 // Calculate all calendar related numbers for a given date
|
|
bsw@11
|
205
|
|
bsw@11
|
206
|
|
bsw@11
|
207 function gregor_completeDate(obj) {
|
|
bsw@11
|
208 if (
|
|
bsw@11
|
209 obj.daycount >= 0 && obj.daycount <= 3652058 && obj.daycount % 1 == 0
|
|
bsw@11
|
210 ) {
|
|
bsw@11
|
211 var daycount = obj.daycount;
|
|
bsw@11
|
212 var n400 = Math.floor(daycount / gregor_c400);
|
|
bsw@11
|
213 var r400 = daycount % gregor_c400;
|
|
bsw@11
|
214 var n100 = Math.floor(r400 / gregor_c100);
|
|
bsw@11
|
215 var r100 = r400 % gregor_c100;
|
|
bsw@11
|
216 if (n100 == 4) { n100 = 3; r100 = gregor_c100; }
|
|
bsw@11
|
217 var n4 = Math.floor(r100 / gregor_c4);
|
|
bsw@11
|
218 var r4 = r100 % gregor_c4;
|
|
bsw@11
|
219 var n1 = Math.floor(r4 / gregor_c1);
|
|
bsw@11
|
220 var r1 = r4 % gregor_c1;
|
|
bsw@11
|
221 if (n1 == 4) { n1 = 3; r1 = gregor_c1; }
|
|
bsw@11
|
222 var year = 1 + 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
|
bsw@11
|
223 var month = 1 + Math.floor(r1 / 31);
|
|
bsw@11
|
224 var monthOffset = gregor_getMonthOffset(year, month);
|
|
bsw@11
|
225 if (month < 12) {
|
|
bsw@11
|
226 var nextMonthOffset = gregor_getMonthOffset(year, month + 1);
|
|
bsw@11
|
227 if (r1 >= nextMonthOffset) {
|
|
bsw@11
|
228 month++;
|
|
bsw@11
|
229 monthOffset = nextMonthOffset;
|
|
bsw@11
|
230 }
|
|
bsw@11
|
231 }
|
|
bsw@11
|
232 var day = 1 + r1 - monthOffset;
|
|
bsw@11
|
233 var iso_string = ("" +
|
|
bsw@11
|
234 gregor_formatInteger(year, 4) + "-" +
|
|
bsw@11
|
235 gregor_formatInteger(month, 2) + "-" +
|
|
bsw@11
|
236 gregor_formatInteger(day, 2)
|
|
bsw@11
|
237 );
|
|
bsw@11
|
238 var us_weekday = (daycount+1) % 7;
|
|
bsw@11
|
239 var iso_weekday = daycount % 7;
|
|
bsw@11
|
240 var iso_weekyear = year;
|
|
bsw@11
|
241 if (
|
|
bsw@11
|
242 month == 1 && (
|
|
bsw@11
|
243 (day == 3 && iso_weekday == 6) ||
|
|
bsw@11
|
244 (day == 2 && iso_weekday >= 5) ||
|
|
bsw@11
|
245 (day == 1 && iso_weekday >= 4)
|
|
bsw@11
|
246 )
|
|
bsw@11
|
247 ) iso_weekyear--;
|
|
bsw@11
|
248 else if (
|
|
bsw@11
|
249 month == 12 && (
|
|
bsw@11
|
250 (day == 29 && iso_weekday == 0) ||
|
|
bsw@11
|
251 (day == 30 && iso_weekday <= 1) ||
|
|
bsw@11
|
252 (day == 31 && iso_weekday <= 2)
|
|
bsw@11
|
253 )
|
|
bsw@11
|
254 ) iso_weekyear++;
|
|
bsw@11
|
255 var jan4th = gregor_daycount({year: iso_weekyear, month: 1, day: 4});
|
|
bsw@11
|
256 var monday0 = jan4th - (jan4th % 7) - 7; // monday of week 0
|
|
bsw@11
|
257 var iso_week = Math.floor((daycount - monday0) / 7);
|
|
bsw@11
|
258 var jan1st = gregor_daycount({year: year, month: 1, day: 1});
|
|
bsw@11
|
259 var sunday0 = jan1st - ((jan1st+1) % 7) - 7; // sunday of week 0
|
|
bsw@11
|
260 var us_week = Math.floor((daycount - sunday0) / 7);
|
|
bsw@11
|
261 return {
|
|
bsw@11
|
262 daycount: daycount,
|
|
bsw@11
|
263 year: year,
|
|
bsw@11
|
264 month: month,
|
|
bsw@11
|
265 day: day,
|
|
bsw@11
|
266 iso_string: iso_string,
|
|
bsw@11
|
267 us_weekday: (daycount+1) % 7, // 0 = Sunday
|
|
bsw@11
|
268 iso_weekday: daycount % 7, // 0 = Monday
|
|
bsw@11
|
269 iso_weekyear: iso_weekyear,
|
|
bsw@11
|
270 iso_week: iso_week,
|
|
bsw@11
|
271 us_week: us_week
|
|
bsw@11
|
272 };
|
|
bsw@11
|
273 } else if (obj.daycount == null) {
|
|
bsw@11
|
274 var daycount = gregor_daycount(obj);
|
|
bsw@11
|
275 if (daycount != null) {
|
|
bsw@11
|
276 return gregor_completeDate({daycount: gregor_daycount(obj)});
|
|
bsw@11
|
277 }
|
|
bsw@11
|
278 }
|
|
bsw@11
|
279 }
|
|
bsw@11
|
280
|
|
bsw@11
|
281
|
|
bsw@11
|
282
|
|
bsw@11
|
283 // Test gregor_daycount and gregor_completeDate for consistency
|
|
bsw@11
|
284 // (Debugging only)
|
|
bsw@11
|
285
|
|
bsw@11
|
286
|
|
bsw@11
|
287 function gregor_test() {
|
|
bsw@11
|
288 for (i=650000; i<900000; i++) {
|
|
bsw@11
|
289 var obj = gregor_completeDate({daycount: i});
|
|
bsw@11
|
290 var j;
|
|
bsw@11
|
291 j = gregor_daycount({
|
|
bsw@11
|
292 year: obj.year,
|
|
bsw@11
|
293 month: obj.month,
|
|
bsw@11
|
294 day: obj.day
|
|
bsw@11
|
295 });
|
|
bsw@11
|
296 if (i != j) { alert("ERROR"); return; }
|
|
bsw@11
|
297 j = gregor_daycount({
|
|
bsw@11
|
298 iso_weekyear: obj.iso_weekyear,
|
|
bsw@11
|
299 iso_week: obj.iso_week,
|
|
bsw@11
|
300 iso_weekday: obj.iso_weekday
|
|
bsw@11
|
301 });
|
|
bsw@11
|
302 if (i != j) { alert("ERROR"); return; }
|
|
bsw@11
|
303 j = gregor_daycount({
|
|
bsw@11
|
304 year: obj.year,
|
|
bsw@11
|
305 iso_week:
|
|
bsw@11
|
306 (obj.iso_weekyear == obj.year + 1) ? 53 :
|
|
bsw@11
|
307 (obj.iso_weekyear == obj.year - 1) ? 0 :
|
|
bsw@11
|
308 obj.iso_week,
|
|
bsw@11
|
309 iso_weekday: obj.iso_weekday
|
|
bsw@11
|
310 });
|
|
bsw@11
|
311 if (i != j) { alert("ERROR"); return; }
|
|
bsw@11
|
312 j = gregor_daycount({
|
|
bsw@11
|
313 year: obj.year,
|
|
bsw@11
|
314 us_week: obj.us_week,
|
|
bsw@11
|
315 us_weekday: obj.us_weekday
|
|
bsw@11
|
316 });
|
|
bsw@11
|
317 if (i != j) { alert("ERROR"); return; }
|
|
bsw@11
|
318 }
|
|
bsw@11
|
319 alert("SUCCESS");
|
|
bsw@11
|
320 }
|
|
bsw@11
|
321
|
|
bsw@11
|
322
|
|
bsw@11
|
323
|
|
bsw@11
|
324 // Graphical calendar
|
|
bsw@11
|
325
|
|
bsw@11
|
326
|
|
bsw@11
|
327 gregor_iso_weekday_css = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
|
|
bsw@11
|
328
|
|
bsw@11
|
329 function gregor_sheet(args) {
|
|
bsw@11
|
330
|
|
bsw@11
|
331 // setting args.today and args.selected
|
|
bsw@11
|
332 if (args.today === undefined) {
|
|
bsw@11
|
333 var js_date = new Date();
|
|
bsw@11
|
334 args.today = gregor_completeDate({
|
|
bsw@11
|
335 year: js_date.getFullYear(),
|
|
bsw@11
|
336 month: js_date.getMonth() + 1,
|
|
bsw@11
|
337 day: js_date.getDate()
|
|
bsw@11
|
338 });
|
|
bsw@11
|
339 } else if (args.today != null) {
|
|
bsw@11
|
340 args.today = gregor_completeDate(args.today);
|
|
bsw@11
|
341 }
|
|
bsw@11
|
342 if (args.selected == "today") {
|
|
bsw@11
|
343 args.selected = args.today;
|
|
bsw@11
|
344 } else if (args.selected != null) {
|
|
bsw@11
|
345 args.selected = gregor_completeDate(args.selected);
|
|
bsw@11
|
346 }
|
|
bsw@11
|
347
|
|
bsw@11
|
348 // setting args.year and args.month
|
|
bsw@11
|
349 if (args.year == null) {
|
|
bsw@11
|
350 if (args.selected != null) args.year = args.selected.year;
|
|
bsw@11
|
351 else args.year = args.today.year;
|
|
bsw@11
|
352 }
|
|
bsw@11
|
353 if (args.month == null) {
|
|
bsw@11
|
354 if (args.selected != null) args.month = args.selected.month;
|
|
bsw@11
|
355 else args.month = args.today.month;
|
|
bsw@11
|
356 }
|
|
bsw@11
|
357
|
|
bsw@11
|
358 // setting first_day
|
|
bsw@11
|
359 var first_day = gregor_completeDate({
|
|
bsw@11
|
360 year: args.year,
|
|
bsw@11
|
361 month: args.month,
|
|
bsw@11
|
362 day: 1
|
|
bsw@11
|
363 });
|
|
bsw@11
|
364 if (first_day == null) return;
|
|
bsw@11
|
365
|
|
bsw@11
|
366 // checking args.navigation, args.week_mode and args.week_numbers
|
|
bsw@11
|
367 if (args.navigation == null) args.navigation = "enabled";
|
|
bsw@11
|
368 else if (
|
|
bsw@11
|
369 args.navigation != "enabled" &&
|
|
bsw@11
|
370 args.navigation != "disabled" &&
|
|
bsw@11
|
371 args.navigation != "hidden"
|
|
bsw@11
|
372 ) return;
|
|
bsw@11
|
373 if (args.week_mode == null) args.week_mode = "iso";
|
|
bsw@11
|
374 else if (args.week_mode != "iso" && args.week_mode != "us") return;
|
|
bsw@11
|
375 if (
|
|
bsw@11
|
376 args.week_numbers != null &&
|
|
bsw@11
|
377 args.week_numbers != "left" &&
|
|
bsw@11
|
378 args.week_numbers != "right"
|
|
bsw@11
|
379 ) return;
|
|
bsw@11
|
380
|
|
bsw@11
|
381 // checking args.month.names and args.weekday_names
|
|
bsw@11
|
382 if (args.month_names.length != 12) return;
|
|
bsw@11
|
383 if (args.weekday_names.length != 7) return;
|
|
bsw@11
|
384
|
|
bsw@11
|
385 // calculating number of days in month
|
|
bsw@11
|
386 var count;
|
|
bsw@11
|
387 if (args.year < 9999 || args.month < 12) {
|
|
bsw@11
|
388 count = gregor_daycount({
|
|
bsw@11
|
389 year: (args.month == 12) ? (args.year + 1) : args.year,
|
|
bsw@11
|
390 month: (args.month == 12) ? 1 : (args.month + 1),
|
|
bsw@11
|
391 day: 1
|
|
bsw@11
|
392 }) - first_day.daycount;
|
|
bsw@11
|
393 } else {
|
|
bsw@11
|
394 // workaround for year 9999
|
|
bsw@11
|
395 count = 31;
|
|
bsw@11
|
396 }
|
|
bsw@11
|
397
|
|
bsw@11
|
398 // locale variables for UI construction
|
|
bsw@11
|
399 var table, row, cell, element;
|
|
bsw@11
|
400
|
|
bsw@11
|
401 // take table element from args.element,
|
|
bsw@11
|
402 // if neccessary create and store it
|
|
bsw@11
|
403 if (args.element == null) {
|
|
bsw@11
|
404 table = document.createElement("table");
|
|
bsw@11
|
405 args.element = table;
|
|
bsw@11
|
406 } else {
|
|
bsw@11
|
407 table = args.element;
|
|
bsw@11
|
408 while (table.firstChild) table.removeChild(table.firstChild);
|
|
bsw@11
|
409 }
|
|
bsw@11
|
410
|
|
bsw@11
|
411 // set CSS class of table according to args.week_numbers
|
|
bsw@11
|
412 if (args.week_numbers == "left") {
|
|
bsw@11
|
413 table.className = "gregor_sheet gregor_weeks_left";
|
|
bsw@11
|
414 } else if (args.week_numbers == "right") {
|
|
bsw@11
|
415 table.className = "gregor_sheet gregor_weeks_right";
|
|
bsw@11
|
416 } else {
|
|
bsw@11
|
417 table.className = "gregor_sheet gregor_weeks_none";
|
|
bsw@11
|
418 }
|
|
bsw@11
|
419
|
|
bsw@11
|
420 // begin of table head
|
|
bsw@11
|
421 var thead = document.createElement("thead");
|
|
bsw@11
|
422
|
|
bsw@11
|
423 // navigation
|
|
bsw@11
|
424 if (args.navigation != "hidden") {
|
|
bsw@11
|
425
|
|
bsw@11
|
426 // UI head row containing the year
|
|
bsw@11
|
427 row = document.createElement("tr");
|
|
bsw@11
|
428 row.className = "gregor_year_row";
|
|
bsw@11
|
429 cell = document.createElement("th");
|
|
bsw@11
|
430 cell.className = "gregor_year";
|
|
bsw@11
|
431 cell.colSpan = args.week_numbers ? 8 : 7;
|
|
bsw@11
|
432 if (args.navigation == "enabled") {
|
|
bsw@11
|
433 element = document.createElement("a");
|
|
bsw@11
|
434 element.className = "gregor_turn gregor_turn_left";
|
|
bsw@11
|
435 element.style.cssFloat = "left";
|
|
bsw@11
|
436 element.style.styleFloat = "left";
|
|
bsw@11
|
437 element.href = "#";
|
|
bsw@11
|
438 element.onclick = function() {
|
|
bsw@11
|
439 if (args.year > 1) args.year--;
|
|
bsw@11
|
440 gregor_sheet(args);
|
|
bsw@11
|
441 return false;
|
|
bsw@11
|
442 }
|
|
bsw@11
|
443 element.ondblclick = element.onclick;
|
|
bsw@11
|
444 element.appendChild(document.createTextNode("<<"));
|
|
bsw@11
|
445 cell.appendChild(element);
|
|
bsw@11
|
446 element = document.createElement("a");
|
|
bsw@11
|
447 element.className = "gregor_turn gregor_turn_right";
|
|
bsw@11
|
448 element.style.cssFloat = "right";
|
|
bsw@11
|
449 element.style.styleFloat = "right";
|
|
bsw@11
|
450 element.href = "#";
|
|
bsw@11
|
451 element.onclick = function() {
|
|
bsw@11
|
452 if (args.year < 9999) args.year++;
|
|
bsw@11
|
453 gregor_sheet(args);
|
|
bsw@11
|
454 return false;
|
|
bsw@11
|
455 }
|
|
bsw@11
|
456 element.ondblclick = element.onclick;
|
|
bsw@11
|
457 element.appendChild(document.createTextNode(">>"));
|
|
bsw@11
|
458 cell.appendChild(element);
|
|
bsw@11
|
459 }
|
|
bsw@11
|
460 cell.appendChild(document.createTextNode(first_day.year));
|
|
bsw@11
|
461 row.appendChild(cell);
|
|
bsw@11
|
462 thead.appendChild(row);
|
|
bsw@11
|
463
|
|
bsw@11
|
464 // UI head row containing the month
|
|
bsw@11
|
465 row = document.createElement("tr");
|
|
bsw@11
|
466 row.className = "gregor_month_row";
|
|
bsw@11
|
467 cell = document.createElement("th");
|
|
bsw@11
|
468 cell.className = "gregor_month";
|
|
bsw@11
|
469 cell.colSpan = args.week_numbers ? 8 : 7;
|
|
bsw@11
|
470 if (args.navigation == "enabled") {
|
|
bsw@11
|
471 element = document.createElement("a");
|
|
bsw@11
|
472 element.className = "gregor_turn gregor_turn_left";
|
|
bsw@11
|
473 element.style.cssFloat = "left";
|
|
bsw@11
|
474 element.style.styleFloat = "left";
|
|
bsw@11
|
475 element.href = "#";
|
|
bsw@11
|
476 element.onclick = function() {
|
|
bsw@11
|
477 if (args.year > 1 || args.month > 1) {
|
|
bsw@11
|
478 args.month--;
|
|
bsw@11
|
479 if (args.month < 1) {
|
|
bsw@11
|
480 args.month = 12;
|
|
bsw@11
|
481 args.year--;
|
|
bsw@11
|
482 }
|
|
bsw@11
|
483 }
|
|
bsw@11
|
484 gregor_sheet(args);
|
|
bsw@11
|
485 return false;
|
|
bsw@11
|
486 }
|
|
bsw@11
|
487 element.ondblclick = element.onclick;
|
|
bsw@11
|
488 element.appendChild(document.createTextNode("<<"));
|
|
bsw@11
|
489 cell.appendChild(element);
|
|
bsw@11
|
490 element = document.createElement("a");
|
|
bsw@11
|
491 element.className = "gregor_turn gregor_turn_right";
|
|
bsw@11
|
492 element.style.cssFloat = "right";
|
|
bsw@11
|
493 element.style.styleFloat = "right";
|
|
bsw@11
|
494 element.href = "#";
|
|
bsw@11
|
495 element.onclick = function() {
|
|
bsw@11
|
496 if (args.year < 9999 || args.month < 12) {
|
|
bsw@11
|
497 args.month++;
|
|
bsw@11
|
498 if (args.month > 12) {
|
|
bsw@11
|
499 args.month = 1;
|
|
bsw@11
|
500 args.year++;
|
|
bsw@11
|
501 }
|
|
bsw@11
|
502 }
|
|
bsw@11
|
503 gregor_sheet(args);
|
|
bsw@11
|
504 return false;
|
|
bsw@11
|
505 }
|
|
bsw@11
|
506 element.ondblclick = element.onclick;
|
|
bsw@11
|
507 element.appendChild(document.createTextNode(">>"));
|
|
bsw@11
|
508 cell.appendChild(element);
|
|
bsw@11
|
509 }
|
|
bsw@11
|
510 cell.appendChild(document.createTextNode(
|
|
bsw@11
|
511 args.month_names[first_day.month-1]
|
|
bsw@11
|
512 ));
|
|
bsw@11
|
513 row.appendChild(cell);
|
|
bsw@11
|
514 thead.appendChild(row);
|
|
bsw@11
|
515
|
|
bsw@11
|
516 // end of navigation
|
|
bsw@11
|
517 }
|
|
bsw@11
|
518
|
|
bsw@11
|
519 // UI weekday row
|
|
bsw@11
|
520 row = document.createElement("tr");
|
|
bsw@11
|
521 row.className = "gregor_weekday_row";
|
|
bsw@11
|
522 if (args.week_numbers == "left") {
|
|
bsw@11
|
523 cell = document.createElement("th");
|
|
bsw@11
|
524 cell.className = "gregor_corner";
|
|
bsw@11
|
525 row.appendChild(cell);
|
|
bsw@11
|
526 }
|
|
bsw@11
|
527 for (var i=0; i<7; i++) {
|
|
bsw@11
|
528 cell = document.createElement("th");
|
|
bsw@11
|
529 cell.className = (
|
|
bsw@11
|
530 "gregor_weekday gregor_" +
|
|
bsw@11
|
531 gregor_iso_weekday_css[(args.week_mode == "us") ? ((i+6)%7) : i]
|
|
bsw@11
|
532 );
|
|
bsw@11
|
533 cell.appendChild(document.createTextNode(args.weekday_names[i]));
|
|
bsw@11
|
534 row.appendChild(cell);
|
|
bsw@11
|
535 }
|
|
bsw@11
|
536 if (args.week_numbers == "right") {
|
|
bsw@11
|
537 cell = document.createElement("th");
|
|
bsw@11
|
538 cell.className = "gregor_corner";
|
|
bsw@11
|
539 row.appendChild(cell);
|
|
bsw@11
|
540 }
|
|
bsw@11
|
541 thead.appendChild(row);
|
|
bsw@11
|
542
|
|
bsw@11
|
543 // end of table head and begin of table body
|
|
bsw@11
|
544 table.appendChild(thead);
|
|
bsw@11
|
545 var tbody = document.createElement("tbody");
|
|
bsw@11
|
546
|
|
bsw@11
|
547 // definition of insert_week function
|
|
bsw@11
|
548 var week = (
|
|
bsw@11
|
549 (args.week_mode == "us") ? first_day.us_week : first_day.iso_week
|
|
bsw@11
|
550 );
|
|
bsw@11
|
551 insert_week = function() {
|
|
bsw@11
|
552 cell = document.createElement("th");
|
|
bsw@11
|
553 cell.className = "gregor_week";
|
|
bsw@11
|
554 cell.appendChild(document.createTextNode(
|
|
bsw@11
|
555 (week < 10) ? ("0" + week) : week)
|
|
bsw@11
|
556 );
|
|
bsw@11
|
557 week++;
|
|
bsw@11
|
558 if (
|
|
bsw@11
|
559 args.week_mode == "iso" && (
|
|
bsw@11
|
560 (
|
|
bsw@11
|
561 args.month == 1 && week > 52
|
|
bsw@11
|
562 ) || (
|
|
bsw@11
|
563 args.month == 12 && week == 53 && (
|
|
bsw@11
|
564 first_day.iso_weekday == 0 ||
|
|
bsw@11
|
565 first_day.iso_weekday == 5 ||
|
|
bsw@11
|
566 first_day.iso_weekday == 6
|
|
bsw@11
|
567 )
|
|
bsw@11
|
568 )
|
|
bsw@11
|
569 )
|
|
bsw@11
|
570 ) week = 1;
|
|
bsw@11
|
571 row.appendChild(cell);
|
|
bsw@11
|
572 }
|
|
bsw@11
|
573
|
|
bsw@11
|
574 // output data fields
|
|
bsw@11
|
575 row = document.createElement("tr");
|
|
bsw@11
|
576 if (args.week_numbers == "left") insert_week();
|
|
bsw@11
|
577 var filler_count = (
|
|
bsw@11
|
578 (args.week_mode == "us") ? first_day.us_weekday : first_day.iso_weekday
|
|
bsw@11
|
579 );
|
|
bsw@11
|
580 for (var i=0; i<filler_count; i++) {
|
|
bsw@11
|
581 cell = document.createElement("td");
|
|
bsw@11
|
582 cell.className = "gregor_empty";
|
|
bsw@11
|
583 row.appendChild(cell);
|
|
bsw@11
|
584 }
|
|
bsw@11
|
585 for (var i=0; i<count; i++) {
|
|
bsw@11
|
586 var date = gregor_completeDate({daycount: first_day.daycount + i});
|
|
bsw@11
|
587 if (row == null) {
|
|
bsw@11
|
588 row = document.createElement("tr");
|
|
bsw@11
|
589 if (args.week_numbers == "left") insert_week();
|
|
bsw@11
|
590 }
|
|
bsw@11
|
591 cell = document.createElement("td");
|
|
bsw@11
|
592 var cssClass = (
|
|
bsw@11
|
593 "gregor_day gregor_" + gregor_iso_weekday_css[date.iso_weekday]
|
|
bsw@11
|
594 );
|
|
bsw@11
|
595 if (args.today != null && date.daycount == args.today.daycount) {
|
|
bsw@11
|
596 cssClass += " gregor_today";
|
|
bsw@11
|
597 }
|
|
bsw@11
|
598 if (args.selected != null && date.daycount == args.selected.daycount) {
|
|
bsw@11
|
599 cssClass += " gregor_selected";
|
|
bsw@11
|
600 }
|
|
bsw@11
|
601 cell.className = cssClass;
|
|
bsw@11
|
602 if (args.day_callback) {
|
|
bsw@11
|
603 args.day_callback(cell, date);
|
|
bsw@11
|
604 } else {
|
|
bsw@11
|
605 element = document.createElement("a");
|
|
bsw@11
|
606 element.href = "#";
|
|
bsw@11
|
607 var generate_onclick = function(date) {
|
|
bsw@11
|
608 return function() {
|
|
bsw@11
|
609 args.selected = date;
|
|
bsw@11
|
610 gregor_sheet(args);
|
|
bsw@11
|
611 if (args.select_callback != null) {
|
|
bsw@11
|
612 args.select_callback(date);
|
|
bsw@11
|
613 }
|
|
bsw@11
|
614 return false;
|
|
bsw@11
|
615 }
|
|
bsw@11
|
616 }
|
|
bsw@11
|
617 element.onclick = generate_onclick(date);
|
|
bsw@11
|
618 element.ondblclick = element.onclick;
|
|
bsw@11
|
619 element.appendChild(document.createTextNode(first_day.day + i));
|
|
bsw@11
|
620 cell.appendChild(element);
|
|
bsw@11
|
621 }
|
|
bsw@11
|
622 row.appendChild(cell);
|
|
bsw@11
|
623 if (row.childNodes.length == ((args.week_numbers == "left") ? 8 : 7)) {
|
|
bsw@11
|
624 if (args.week_numbers == "right") insert_week();
|
|
bsw@11
|
625 tbody.appendChild(row);
|
|
bsw@11
|
626 row = null;
|
|
bsw@11
|
627 }
|
|
bsw@11
|
628 }
|
|
bsw@11
|
629 if (row != null) {
|
|
bsw@11
|
630 while (row.childNodes.length < ((args.week_numbers == "left") ? 8 : 7)) {
|
|
bsw@11
|
631 cell = document.createElement("td");
|
|
bsw@11
|
632 cell.className = "gregor_empty";
|
|
bsw@11
|
633 row.appendChild(cell);
|
|
bsw@11
|
634 }
|
|
bsw@11
|
635 if (args.week_numbers == "right") insert_week();
|
|
bsw@11
|
636 tbody.appendChild(row);
|
|
bsw@11
|
637 }
|
|
bsw@11
|
638
|
|
bsw@11
|
639 // end of table body
|
|
bsw@11
|
640 table.appendChild(tbody);
|
|
bsw@11
|
641
|
|
bsw@11
|
642 // return table
|
|
bsw@11
|
643 return table;
|
|
bsw@11
|
644 }
|
|
bsw@11
|
645
|
|
bsw@11
|
646
|
|
bsw@11
|
647
|
|
bsw@11
|
648 // Rich form field support
|
|
bsw@11
|
649
|
|
bsw@11
|
650
|
|
bsw@11
|
651 function gregor_getAbsoluteLeft(elem) {
|
|
bsw@11
|
652 var result = 0;
|
|
bsw@11
|
653 while (elem && elem.style.position != "static") {
|
|
bsw@11
|
654 result += elem.offsetLeft;
|
|
bsw@11
|
655 elem = elem.offsetParent;
|
|
bsw@11
|
656 }
|
|
bsw@11
|
657 return result;
|
|
bsw@11
|
658 }
|
|
bsw@11
|
659
|
|
bsw@11
|
660 function gregor_getAbsoluteTop(elem) {
|
|
bsw@11
|
661 var result = 0;
|
|
bsw@11
|
662 while (elem && elem.style.position != "static") {
|
|
bsw@11
|
663 result += elem.offsetTop;
|
|
bsw@11
|
664 elem = elem.offsetParent;
|
|
bsw@11
|
665 }
|
|
bsw@11
|
666 return result;
|
|
bsw@11
|
667 }
|
|
bsw@11
|
668
|
|
bsw@11
|
669 function gregor_formatDate(format, date) {
|
|
bsw@11
|
670 if (date == null) return "";
|
|
bsw@11
|
671 var result = format;
|
|
bsw@11
|
672 result = result.replace(/Y+/, function(s) {
|
|
bsw@11
|
673 if (s.length == 2) return gregor_formatInteger(date.year % 100, 2);
|
|
bsw@11
|
674 else return gregor_formatInteger(date.year, s.length);
|
|
bsw@11
|
675 });
|
|
bsw@11
|
676 result = result.replace(/M+/, function(s) {
|
|
bsw@11
|
677 return gregor_formatInteger(date.month, s.length);
|
|
bsw@11
|
678 });
|
|
bsw@11
|
679 result = result.replace(/D+/, function(s) {
|
|
bsw@11
|
680 return gregor_formatInteger(date.day, s.length);
|
|
bsw@11
|
681 });
|
|
bsw@11
|
682 return result;
|
|
bsw@11
|
683 }
|
|
bsw@11
|
684
|
|
bsw@11
|
685 function gregor_map2digitYear(y2, maxYear) {
|
|
bsw@11
|
686 var guess = Math.floor(maxYear / 100) * 100 + y2;
|
|
bsw@11
|
687 if (guess <= maxYear) return guess;
|
|
bsw@11
|
688 else return guess - 100;
|
|
bsw@11
|
689 }
|
|
bsw@11
|
690
|
|
bsw@11
|
691 function gregor_parseDate(format, string, terminated, maxYear) {
|
|
bsw@11
|
692 var numericParts, formatParts;
|
|
bsw@11
|
693 numericParts = string.match(/^\s*([0-9]{4})-([0-9]{2})-([0-9]{2})\s*$/);
|
|
bsw@11
|
694 if (numericParts != null) {
|
|
bsw@11
|
695 return gregor_completeDate({
|
|
bsw@11
|
696 year: numericParts[1],
|
|
bsw@11
|
697 month: numericParts[2],
|
|
bsw@11
|
698 day: numericParts[3]
|
|
bsw@11
|
699 });
|
|
bsw@11
|
700 }
|
|
bsw@11
|
701 numericParts = string.match(/[0-9]+/g);
|
|
bsw@11
|
702 if (numericParts == null) return null;
|
|
bsw@11
|
703 formatParts = format.match(/[YMD]+/g);
|
|
bsw@11
|
704 if (numericParts.length != formatParts.length) return null;
|
|
bsw@11
|
705 if (
|
|
bsw@11
|
706 !terminated && (
|
|
bsw@11
|
707 numericParts[numericParts.length-1].length <
|
|
bsw@11
|
708 formatParts[formatParts.length-1].length
|
|
bsw@11
|
709 )
|
|
bsw@11
|
710 ) return null;
|
|
bsw@11
|
711 var year, month, day;
|
|
bsw@11
|
712 for (var i=0; i<numericParts.length; i++) {
|
|
bsw@11
|
713 var numericPart = numericParts[i];
|
|
bsw@11
|
714 var formatPart = formatParts[i];
|
|
bsw@11
|
715 if (formatPart.match(/^Y+$/)) {
|
|
bsw@11
|
716 if (numericPart.length == 2 && maxYear != null) {
|
|
bsw@11
|
717 year = gregor_map2digitYear(parseInt(numericPart, 10), maxYear);
|
|
bsw@11
|
718 } else if (numericPart.length > 2) {
|
|
bsw@11
|
719 year = parseInt(numericPart, 10);
|
|
bsw@11
|
720 }
|
|
bsw@11
|
721 } else if (formatPart.match(/^M+$/)) {
|
|
bsw@11
|
722 month = parseInt(numericPart, 10);
|
|
bsw@11
|
723 } else if (formatPart.match(/^D+$/)) {
|
|
bsw@11
|
724 day = parseInt(numericPart, 10);
|
|
bsw@11
|
725 } else {
|
|
bsw@11
|
726 //alert("Not implemented.");
|
|
bsw@11
|
727 return null;
|
|
bsw@11
|
728 }
|
|
bsw@11
|
729 }
|
|
bsw@11
|
730 return gregor_completeDate({year: year, month: month, day: day});
|
|
bsw@11
|
731 }
|
|
bsw@11
|
732
|
|
bsw@11
|
733 function gregor_addGui(args) {
|
|
bsw@11
|
734
|
|
bsw@11
|
735 // copy argument structure
|
|
bsw@11
|
736 var state = {};
|
|
bsw@11
|
737 for (key in args) state[key] = args[key];
|
|
bsw@11
|
738
|
|
bsw@11
|
739 // unset state.element, which should never be set anyway
|
|
bsw@11
|
740 state.element = null;
|
|
bsw@11
|
741
|
|
bsw@11
|
742 // save original values of "year" and "month" options
|
|
bsw@11
|
743 var original_year = state.year;
|
|
bsw@11
|
744 var original_month = state.month;
|
|
bsw@11
|
745
|
|
bsw@11
|
746 // get text field element
|
|
bsw@11
|
747 var element = document.getElementById(state.element_id);
|
|
bsw@11
|
748 state.element_id = null;
|
|
bsw@11
|
749
|
|
bsw@11
|
750 // setup state.today, state.selected and state.format options
|
|
bsw@11
|
751 if (state.today === undefined) {
|
|
bsw@11
|
752 var js_date = new Date();
|
|
bsw@11
|
753 state.today = gregor_completeDate({
|
|
bsw@11
|
754 year: js_date.getFullYear(),
|
|
bsw@11
|
755 month: js_date.getMonth() + 1,
|
|
bsw@11
|
756 day: js_date.getDate()
|
|
bsw@11
|
757 });
|
|
bsw@11
|
758 } else if (state.today != null) {
|
|
bsw@11
|
759 state.today = gregor_completeDate(args.today);
|
|
bsw@11
|
760 }
|
|
bsw@11
|
761 if (state.selected == "today") {
|
|
bsw@11
|
762 state.selected = state.today;
|
|
bsw@11
|
763 } else if (args.selected != null) {
|
|
bsw@11
|
764 state.selected = gregor_completeDate(state.selected);
|
|
bsw@11
|
765 }
|
|
bsw@11
|
766 if (state.format == null) state.format = "YYYY-MM-DD";
|
|
bsw@11
|
767
|
|
bsw@11
|
768 // using state.future to calculate maxYear (for 2 digit year conversions)
|
|
bsw@11
|
769 var maxYear = (state.today == null) ? null : (
|
|
bsw@11
|
770 state.today.year +
|
|
bsw@11
|
771 ((state.future == null) ? 12 : state.future)
|
|
bsw@11
|
772 );
|
|
bsw@11
|
773
|
|
bsw@11
|
774 // hook into state.select_callback
|
|
bsw@11
|
775 var select_callback = state.select_callback;
|
|
bsw@11
|
776 state.select_callback = function(date) {
|
|
bsw@11
|
777 element.value = gregor_formatDate(state.format, date);
|
|
bsw@11
|
778 if (select_callback) select_callback(date);
|
|
bsw@11
|
779 };
|
|
bsw@11
|
780
|
|
bsw@11
|
781 // function to parse text field and update calendar sheet state
|
|
bsw@11
|
782 var updateSheet = function(terminated) {
|
|
bsw@11
|
783 var date = gregor_parseDate(
|
|
bsw@11
|
784 state.format, element.value, terminated, maxYear
|
|
bsw@11
|
785 );
|
|
bsw@11
|
786 if (date) {
|
|
bsw@11
|
787 state.year = null;
|
|
bsw@11
|
788 state.month = null;
|
|
bsw@11
|
789 }
|
|
bsw@11
|
790 state.selected = date;
|
|
bsw@11
|
791 gregor_sheet(state);
|
|
bsw@11
|
792 };
|
|
bsw@11
|
793
|
|
bsw@11
|
794 // Initial synchronization
|
|
bsw@11
|
795 if (state.selected === undefined) updateSheet(true);
|
|
bsw@11
|
796 element.value = gregor_formatDate(state.format, state.selected);
|
|
bsw@11
|
797 if (select_callback) select_callback(state.selected);
|
|
bsw@11
|
798
|
|
bsw@11
|
799 // variables storing popup status
|
|
bsw@11
|
800 var visible = false;
|
|
bsw@11
|
801 var focus = false;
|
|
bsw@11
|
802 var protection = false;
|
|
bsw@11
|
803
|
|
bsw@11
|
804 // event handlers for text field
|
|
bsw@11
|
805 element.onfocus = function() {
|
|
bsw@11
|
806 focus = true;
|
|
bsw@11
|
807 if (!visible) {
|
|
bsw@11
|
808 state.year = original_year;
|
|
bsw@11
|
809 state.month = original_month;
|
|
bsw@11
|
810 gregor_sheet(state);
|
|
bsw@11
|
811 state.element.style.position = "absolute";
|
|
bsw@11
|
812 state.element.style.top = gregor_getAbsoluteTop(element) + element.offsetHeight;
|
|
bsw@11
|
813 state.element.style.left = gregor_getAbsoluteLeft(element);
|
|
bsw@11
|
814 state.element.onmousedown = function() {
|
|
bsw@11
|
815 protection = true;
|
|
bsw@11
|
816 };
|
|
bsw@11
|
817 state.element.onmouseup = function() {
|
|
bsw@11
|
818 protection = false;
|
|
bsw@11
|
819 element.focus();
|
|
bsw@11
|
820 };
|
|
bsw@11
|
821 state.element.onmouseout = state.element.onmouseup;
|
|
bsw@11
|
822 element.parentNode.appendChild(state.element);
|
|
bsw@11
|
823 visible = true;
|
|
bsw@11
|
824 }
|
|
bsw@11
|
825 };
|
|
bsw@11
|
826 element.onblur = function() {
|
|
bsw@11
|
827 focus = false;
|
|
bsw@11
|
828 window.setTimeout(function() {
|
|
bsw@11
|
829 if (visible && !focus && !protection) {
|
|
bsw@11
|
830 updateSheet(true);
|
|
bsw@11
|
831 element.value = gregor_formatDate(state.format, state.selected);
|
|
bsw@11
|
832 if (select_callback) select_callback(state.selected);
|
|
bsw@11
|
833 state.element.parentNode.removeChild(state.element);
|
|
bsw@11
|
834 visible = false;
|
|
bsw@11
|
835 protection = false;
|
|
bsw@11
|
836 }
|
|
bsw@11
|
837 }, 1);
|
|
bsw@11
|
838 };
|
|
bsw@11
|
839 element.onkeyup = function() {
|
|
bsw@11
|
840 updateSheet(false);
|
|
bsw@11
|
841 if (select_callback) select_callback(state.selected);
|
|
bsw@11
|
842 };
|
|
bsw@11
|
843
|
|
bsw@11
|
844 }
|
|
bsw@11
|
845
|