data_grid 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/.rspec +3 -0
  2. data/CHANGELOG +5 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/Rakefile +1 -0
  6. data/app/assets/images/data_grid/calendar_view_month.png +0 -0
  7. data/app/assets/images/data_grid/csv.gif +0 -0
  8. data/app/assets/images/data_grid/delete.png +0 -0
  9. data/app/assets/images/data_grid/edit.png +0 -0
  10. data/app/assets/images/data_grid/no.png +0 -0
  11. data/app/assets/images/data_grid/sort_down.gif +0 -0
  12. data/app/assets/images/data_grid/sort_up.gif +0 -0
  13. data/app/assets/images/data_grid/yes.png +0 -0
  14. data/app/assets/javascripts/data_grid/data_grid.js +24 -0
  15. data/app/assets/javascripts/data_grid/grid_calendar/calendar-setup.js +200 -0
  16. data/app/assets/javascripts/data_grid/grid_calendar/calendar-setup_stripped.js +21 -0
  17. data/app/assets/javascripts/data_grid/grid_calendar/calendar.js +1819 -0
  18. data/app/assets/javascripts/data_grid/grid_calendar/calendar_original.js +1845 -0
  19. data/app/assets/javascripts/data_grid/grid_calendar/calendar_patched.js +1819 -0
  20. data/app/assets/javascripts/data_grid/grid_calendar/calendar_stripped.js +14 -0
  21. data/app/assets/javascripts/data_grid/grid_calendar/img.gif +0 -0
  22. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-af.js +39 -0
  23. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-al.js +101 -0
  24. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-bg.js +124 -0
  25. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-big5-utf8.js +123 -0
  26. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-big5.js +123 -0
  27. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-br.js +108 -0
  28. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ca.js +123 -0
  29. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-cs-utf8.js +65 -0
  30. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-cs-win.js +65 -0
  31. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-da.js +123 -0
  32. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-de.js +124 -0
  33. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-du.js +45 -0
  34. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-el.js +89 -0
  35. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-en.js +127 -0
  36. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-es.js +129 -0
  37. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-fi.js +98 -0
  38. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-fr.js +125 -0
  39. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-he-utf8.js +123 -0
  40. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-hr-utf8.js +49 -0
  41. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-hr.js +0 -0
  42. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-hu.js +124 -0
  43. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-it.js +124 -0
  44. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-jp.js +45 -0
  45. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ko-utf8.js +120 -0
  46. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ko.js +120 -0
  47. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-lt-utf8.js +114 -0
  48. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-lt.js +114 -0
  49. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-lv.js +123 -0
  50. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-nl.js +73 -0
  51. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-no.js +114 -0
  52. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-pl-utf8.js +93 -0
  53. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-pl.js +56 -0
  54. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-pt.js +123 -0
  55. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ro.js +66 -0
  56. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ru.js +123 -0
  57. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ru_win_.js +123 -0
  58. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-si.js +94 -0
  59. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-sk.js +99 -0
  60. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-sp.js +110 -0
  61. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-sv.js +93 -0
  62. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-tr.js +58 -0
  63. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-zh.js +119 -0
  64. data/app/assets/javascripts/data_grid/grid_calendar/lang/cn_utf8.js +123 -0
  65. data/app/assets/javascripts/data_grid/grid_calendar/menuarrow.gif +0 -0
  66. data/app/assets/javascripts/data_grid/grid_calendar/menuarrow2.gif +0 -0
  67. data/app/assets/stylesheets/data_grid/data_grid.css +90 -0
  68. data/app/assets/stylesheets/data_grid/data_grid_3_0.css +90 -0
  69. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-blue.css +233 -0
  70. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-blue2.css +237 -0
  71. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-brown.css +226 -0
  72. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-green.css +230 -0
  73. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-system.css +252 -0
  74. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-tas.css +240 -0
  75. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-1.css +272 -0
  76. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-2.css +272 -0
  77. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-cold-1.css +266 -0
  78. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-cold-2.css +272 -0
  79. data/app/assets/stylesheets/data_grid/grid_calendar/img.gif +0 -0
  80. data/app/assets/stylesheets/data_grid/grid_calendar/menuarrow.gif +0 -0
  81. data/app/assets/stylesheets/data_grid/grid_calendar/menuarrow2.gif +0 -0
  82. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/active-bg.gif +0 -0
  83. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/dark-bg.gif +0 -0
  84. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/hover-bg.gif +0 -0
  85. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/menuarrow.gif +0 -0
  86. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/normal-bg.gif +0 -0
  87. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/rowhover-bg.gif +0 -0
  88. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/status-bg.gif +0 -0
  89. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/theme.css +236 -0
  90. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/title-bg.gif +0 -0
  91. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/today-bg.gif +0 -0
  92. data/app/views/data_grid/_data_grid.html.erb +101 -0
  93. data/config/locales/en.yml +10 -0
  94. data/data_grid.gemspec +27 -0
  95. data/lib/data_grid/column.rb +38 -0
  96. data/lib/data_grid/controller.rb +30 -0
  97. data/lib/data_grid/cookies_state_saver.rb +42 -0
  98. data/lib/data_grid/csv_exporter.rb +79 -0
  99. data/lib/data_grid/data_grid_logic.rb +175 -0
  100. data/lib/data_grid/data_source_array.rb +267 -0
  101. data/lib/data_grid/data_source_orm.rb +207 -0
  102. data/lib/data_grid/engine.rb +19 -0
  103. data/lib/data_grid/summaries.rb +34 -0
  104. data/lib/data_grid/version.rb +3 -0
  105. data/lib/data_grid/view_helpers.rb +271 -0
  106. data/lib/data_grid.rb +43 -0
  107. data/lib/generators/data_grid/copy_view_generator.rb +16 -0
  108. data/lib/generators/data_grid/install_generator.rb +29 -0
  109. data/lib/generators/templates/data_grid.rb +29 -0
  110. data/lib/generators/templates/stylesheets/data_grid/data_grid_3_0.css +90 -0
  111. data/spec/orm_spec.rb +57 -0
  112. data/spec/spec_helper.rb +15 -0
  113. data/spec/support/active_record.rb +17 -0
  114. metadata +118 -5
@@ -0,0 +1,1845 @@
1
+ /* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo
2
+ * -----------------------------------------------------------
3
+ *
4
+ * The DHTML Calendar, version 1.0 "It is happening again"
5
+ *
6
+ * Details and latest version at:
7
+ * www.dynarch.com/projects/calendar
8
+ *
9
+ * This script is developed by Dynarch.com. Visit us at www.dynarch.com.
10
+ *
11
+ * This script is distributed under the GNU Lesser General Public License.
12
+ * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
13
+ */
14
+
15
+ // $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $
16
+
17
+ /** The Calendar object constructor. */
18
+ Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
19
+ // member variables
20
+ this.activeDiv = null;
21
+ this.currentDateEl = null;
22
+ this.getDateStatus = null;
23
+ this.getDateToolTip = null;
24
+ this.getDateText = null;
25
+ this.timeout = null;
26
+ this.onSelected = onSelected || null;
27
+ this.onClose = onClose || null;
28
+ this.dragging = false;
29
+ this.hidden = false;
30
+ this.minYear = 1970;
31
+ this.maxYear = 2050;
32
+ this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
33
+ this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
34
+ this.isPopup = true;
35
+ this.weekNumbers = true;
36
+ this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
37
+ this.showsOtherMonths = false;
38
+ this.dateStr = dateStr;
39
+ this.ar_days = null;
40
+ this.showsTime = false;
41
+ this.time24 = true;
42
+ this.yearStep = 2;
43
+ this.hiliteToday = true;
44
+ this.multiple = null;
45
+ // HTML elements
46
+ this.table = null;
47
+ this.element = null;
48
+ this.tbody = null;
49
+ this.firstdayname = null;
50
+ // Combo boxes
51
+ this.monthsCombo = null;
52
+ this.yearsCombo = null;
53
+ this.hilitedMonth = null;
54
+ this.activeMonth = null;
55
+ this.hilitedYear = null;
56
+ this.activeYear = null;
57
+ // Information
58
+ this.dateClicked = false;
59
+
60
+ // one-time initializations
61
+ if (typeof Calendar._SDN == "undefined") {
62
+ // table of short day names
63
+ if (typeof Calendar._SDN_len == "undefined")
64
+ Calendar._SDN_len = 3;
65
+ var ar = new Array();
66
+ for (var i = 8; i > 0;) {
67
+ ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
68
+ }
69
+ Calendar._SDN = ar;
70
+ // table of short month names
71
+ if (typeof Calendar._SMN_len == "undefined")
72
+ Calendar._SMN_len = 3;
73
+ ar = new Array();
74
+ for (var i = 12; i > 0;) {
75
+ ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
76
+ }
77
+ Calendar._SMN = ar;
78
+ }
79
+ };
80
+
81
+ // ** constants
82
+
83
+ /// "static", needed for event handlers.
84
+ Calendar._C = null;
85
+
86
+ /// detect a special case of "web browser"
87
+ Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
88
+ !/opera/i.test(navigator.userAgent) );
89
+
90
+ Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );
91
+
92
+ /// detect Opera browser
93
+ Calendar.is_opera = /opera/i.test(navigator.userAgent);
94
+
95
+ /// detect KHTML-based browsers
96
+ Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);
97
+
98
+ // BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
99
+ // library, at some point.
100
+
101
+
102
+ // not used at this time, see line 1426
103
+ Calendar.getViewportScrollX = function() {
104
+ var scrollX = 0;
105
+ if( document.documentElement && document.documentElement.scrollLeft ) { //IE standards compliant and W3C
106
+ scrollX = document.documentElement.scrollLeft;
107
+ }
108
+ else if( document.body && document.body.scrollLeft ) { // IE 6 not standards compliant
109
+ scrollX = document.body.scrollLeft;
110
+ }
111
+ else if( window.pageXOffset ) { // older browsers
112
+ scrollX = window.pageXOffset;
113
+ }
114
+ else if( window.scrollX ) { // Gecko and KHTML/Webkit browsers I think...
115
+ scrollX = window.scrollX;
116
+ }
117
+ return scrollX;
118
+ };
119
+
120
+ Calendar.getViewportScrollY = function() {
121
+ var scrollY = 0;
122
+ if( document.documentElement && document.documentElement.scrollTop ) {
123
+ scrollY = document.documentElement.scrollTop;
124
+ }else if( document.body && document.body.scrollTop ) {
125
+ scrollY = document.body.scrollTop;
126
+ }else if( window.pageYOffset ) {
127
+ scrollY = window.pageYOffset;
128
+ }
129
+ else if( window.scrollY ) {
130
+ scrollY = window.scrollY;
131
+ }
132
+ return scrollY;
133
+ };
134
+
135
+ Calendar.getAbsolutePos = function(el) {
136
+ var SL = 0, ST = 0;
137
+ var is_div = /^div$/i.test(el.tagName);
138
+ if (is_div && el.scrollLeft)
139
+ SL = el.scrollLeft;
140
+ if (is_div && el.scrollTop)
141
+ ST = el.scrollTop;
142
+ var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
143
+ if (el.offsetParent) {
144
+ var tmp = this.getAbsolutePos(el.offsetParent);
145
+ r.x += tmp.x;
146
+ r.y += tmp.y;
147
+ }
148
+ return r;
149
+ };
150
+
151
+ Calendar.isRelated = function (el, evt) {
152
+ var related = evt.relatedTarget;
153
+ if (!related) {
154
+ var type = evt.type;
155
+ if (type == "mouseover") {
156
+ related = evt.fromElement;
157
+ } else if (type == "mouseout") {
158
+ related = evt.toElement;
159
+ }
160
+ }
161
+ while (related) {
162
+ if (related == el) {
163
+ return true;
164
+ }
165
+ related = related.parentNode;
166
+ }
167
+ return false;
168
+ };
169
+
170
+ Calendar.removeClass = function(el, className) {
171
+ if (!(el && el.className)) {
172
+ return;
173
+ }
174
+ var cls = el.className.split(" ");
175
+ var ar = new Array();
176
+ for (var i = cls.length; i > 0;) {
177
+ if (cls[--i] != className) {
178
+ ar[ar.length] = cls[i];
179
+ }
180
+ }
181
+ el.className = ar.join(" ");
182
+ };
183
+
184
+ Calendar.addClass = function(el, className) {
185
+ Calendar.removeClass(el, className);
186
+ el.className += " " + className;
187
+ };
188
+
189
+ // FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
190
+ Calendar.getElement = function(ev) {
191
+ var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
192
+ while (f.nodeType != 1 || /^div$/i.test(f.tagName))
193
+ f = f.parentNode;
194
+ return f;
195
+ };
196
+
197
+ Calendar.getTargetElement = function(ev) {
198
+ var f = Calendar.is_ie ? window.event.srcElement : ev.target;
199
+ while (f.nodeType != 1)
200
+ f = f.parentNode;
201
+ return f;
202
+ };
203
+
204
+ Calendar.stopEvent = function(ev) {
205
+ ev || (ev = window.event);
206
+ if (Calendar.is_ie) {
207
+ ev.cancelBubble = true;
208
+ ev.returnValue = false;
209
+ } else {
210
+ ev.preventDefault();
211
+ ev.stopPropagation();
212
+ }
213
+ return false;
214
+ };
215
+
216
+ Calendar.addEvent = function(el, evname, func) {
217
+ if (el.attachEvent) { // IE
218
+ el.attachEvent("on" + evname, func);
219
+ } else if (el.addEventListener) { // Gecko / W3C
220
+ el.addEventListener(evname, func, true);
221
+ } else {
222
+ el["on" + evname] = func;
223
+ }
224
+ };
225
+
226
+ Calendar.removeEvent = function(el, evname, func) {
227
+ if (el.detachEvent) { // IE
228
+ el.detachEvent("on" + evname, func);
229
+ } else if (el.removeEventListener) { // Gecko / W3C
230
+ el.removeEventListener(evname, func, true);
231
+ } else {
232
+ el["on" + evname] = null;
233
+ }
234
+ };
235
+
236
+ Calendar.createElement = function(type, parent) {
237
+ var el = null;
238
+ if (document.createElementNS) {
239
+ // use the XHTML namespace; IE won't normally get here unless
240
+ // _they_ "fix" the DOM2 implementation.
241
+ el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
242
+ } else {
243
+ el = document.createElement(type);
244
+ }
245
+ if (typeof parent != "undefined") {
246
+ parent.appendChild(el);
247
+ }
248
+ return el;
249
+ };
250
+
251
+ // END: UTILITY FUNCTIONS
252
+
253
+ // BEGIN: CALENDAR STATIC FUNCTIONS
254
+
255
+ /** Internal -- adds a set of events to make some element behave like a button. */
256
+ Calendar._add_evs = function(el) {
257
+ with (Calendar) {
258
+ addEvent(el, "mouseover", dayMouseOver);
259
+ addEvent(el, "mousedown", dayMouseDown);
260
+ addEvent(el, "mouseout", dayMouseOut);
261
+ if (is_ie) {
262
+ addEvent(el, "dblclick", dayMouseDblClick);
263
+ el.setAttribute("unselectable", true);
264
+ }
265
+ }
266
+ };
267
+
268
+ Calendar.findMonth = function(el) {
269
+ if (typeof el.month != "undefined") {
270
+ return el;
271
+ } else if (typeof el.parentNode.month != "undefined") {
272
+ return el.parentNode;
273
+ }
274
+ return null;
275
+ };
276
+
277
+ Calendar.findYear = function(el) {
278
+ if (typeof el.year != "undefined") {
279
+ return el;
280
+ } else if (typeof el.parentNode.year != "undefined") {
281
+ return el.parentNode;
282
+ }
283
+ return null;
284
+ };
285
+
286
+ Calendar.showMonthsCombo = function () {
287
+ var cal = Calendar._C;
288
+ if (!cal) {
289
+ return false;
290
+ }
291
+ var cal = cal;
292
+ var cd = cal.activeDiv;
293
+ var mc = cal.monthsCombo;
294
+ if (cal.hilitedMonth) {
295
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
296
+ }
297
+ if (cal.activeMonth) {
298
+ Calendar.removeClass(cal.activeMonth, "active");
299
+ }
300
+ var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
301
+ Calendar.addClass(mon, "active");
302
+ cal.activeMonth = mon;
303
+ var s = mc.style;
304
+ s.display = "block";
305
+ if (cd.navtype < 0)
306
+ s.left = cd.offsetLeft + "px";
307
+ else {
308
+ var mcw = mc.offsetWidth;
309
+ if (typeof mcw == "undefined")
310
+ // Konqueror brain-dead techniques
311
+ mcw = 50;
312
+ s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
313
+ }
314
+ s.top = (cd.offsetTop + cd.offsetHeight) + "px";
315
+ };
316
+
317
+ Calendar.showYearsCombo = function (fwd) {
318
+ var cal = Calendar._C;
319
+ if (!cal) {
320
+ return false;
321
+ }
322
+ var cal = cal;
323
+ var cd = cal.activeDiv;
324
+ var yc = cal.yearsCombo;
325
+ if (cal.hilitedYear) {
326
+ Calendar.removeClass(cal.hilitedYear, "hilite");
327
+ }
328
+ if (cal.activeYear) {
329
+ Calendar.removeClass(cal.activeYear, "active");
330
+ }
331
+ cal.activeYear = null;
332
+ var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
333
+ var yr = yc.firstChild;
334
+ var show = false;
335
+ for (var i = 12; i > 0; --i) {
336
+ if (Y >= cal.minYear && Y <= cal.maxYear) {
337
+ yr.innerHTML = Y;
338
+ yr.year = Y;
339
+ yr.style.display = "block";
340
+ show = true;
341
+ } else {
342
+ yr.style.display = "none";
343
+ }
344
+ yr = yr.nextSibling;
345
+ Y += fwd ? cal.yearStep : -cal.yearStep;
346
+ }
347
+ if (show) {
348
+ var s = yc.style;
349
+ s.display = "block";
350
+ if (cd.navtype < 0)
351
+ s.left = cd.offsetLeft + "px";
352
+ else {
353
+ var ycw = yc.offsetWidth;
354
+ if (typeof ycw == "undefined")
355
+ // Konqueror brain-dead techniques
356
+ ycw = 50;
357
+ s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
358
+ }
359
+ s.top = (cd.offsetTop + cd.offsetHeight) + "px";
360
+ }
361
+ };
362
+
363
+ // event handlers
364
+
365
+ Calendar.tableMouseUp = function(ev) {
366
+ var cal = Calendar._C;
367
+ if (!cal) {
368
+ return false;
369
+ }
370
+ if (cal.timeout) {
371
+ clearTimeout(cal.timeout);
372
+ }
373
+ var el = cal.activeDiv;
374
+ if (!el) {
375
+ return false;
376
+ }
377
+ var target = Calendar.getTargetElement(ev);
378
+ ev || (ev = window.event);
379
+ Calendar.removeClass(el, "active");
380
+ if (target == el || target.parentNode == el) {
381
+ Calendar.cellClick(el, ev);
382
+ }
383
+ var mon = Calendar.findMonth(target);
384
+ var date = null;
385
+ if (mon) {
386
+ date = new Date(cal.date);
387
+ if (mon.month != date.getMonth()) {
388
+ date.setMonth(mon.month);
389
+ cal.setDate(date);
390
+ cal.dateClicked = false;
391
+ cal.callHandler();
392
+ }
393
+ } else {
394
+ var year = Calendar.findYear(target);
395
+ if (year) {
396
+ date = new Date(cal.date);
397
+ if (year.year != date.getFullYear()) {
398
+ date.setFullYear(year.year);
399
+ cal.setDate(date);
400
+ cal.dateClicked = false;
401
+ cal.callHandler();
402
+ }
403
+ }
404
+ }
405
+ with (Calendar) {
406
+ removeEvent(document, "mouseup", tableMouseUp);
407
+ removeEvent(document, "mouseover", tableMouseOver);
408
+ removeEvent(document, "mousemove", tableMouseOver);
409
+ cal._hideCombos();
410
+ _C = null;
411
+ return stopEvent(ev);
412
+ }
413
+ };
414
+
415
+ Calendar.tableMouseOver = function (ev) {
416
+ var cal = Calendar._C;
417
+ if (!cal) {
418
+ return;
419
+ }
420
+ var el = cal.activeDiv;
421
+ var target = Calendar.getTargetElement(ev);
422
+ if (target == el || target.parentNode == el) {
423
+ Calendar.addClass(el, "hilite active");
424
+ Calendar.addClass(el.parentNode, "rowhilite");
425
+ } else {
426
+ if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
427
+ Calendar.removeClass(el, "active");
428
+ Calendar.removeClass(el, "hilite");
429
+ Calendar.removeClass(el.parentNode, "rowhilite");
430
+ }
431
+ ev || (ev = window.event);
432
+ if (el.navtype == 50 && target != el) {
433
+ var pos = Calendar.getAbsolutePos(el);
434
+ var w = el.offsetWidth;
435
+ var x = ev.clientX;
436
+ var dx;
437
+ var decrease = true;
438
+ if (x > pos.x + w) {
439
+ dx = x - pos.x - w;
440
+ decrease = false;
441
+ } else
442
+ dx = pos.x - x;
443
+
444
+ if (dx < 0) dx = 0;
445
+ var range = el._range;
446
+ var current = el._current;
447
+ var count = Math.floor(dx / 10) % range.length;
448
+ for (var i = range.length; --i >= 0;)
449
+ if (range[i] == current)
450
+ break;
451
+ while (count-- > 0)
452
+ if (decrease) {
453
+ if (--i < 0)
454
+ i = range.length - 1;
455
+ } else if ( ++i >= range.length )
456
+ i = 0;
457
+ var newval = range[i];
458
+ el.innerHTML = newval;
459
+
460
+ cal.onUpdateTime();
461
+ }
462
+ var mon = Calendar.findMonth(target);
463
+ if (mon) {
464
+ if (mon.month != cal.date.getMonth()) {
465
+ if (cal.hilitedMonth) {
466
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
467
+ }
468
+ Calendar.addClass(mon, "hilite");
469
+ cal.hilitedMonth = mon;
470
+ } else if (cal.hilitedMonth) {
471
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
472
+ }
473
+ } else {
474
+ if (cal.hilitedMonth) {
475
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
476
+ }
477
+ var year = Calendar.findYear(target);
478
+ if (year) {
479
+ if (year.year != cal.date.getFullYear()) {
480
+ if (cal.hilitedYear) {
481
+ Calendar.removeClass(cal.hilitedYear, "hilite");
482
+ }
483
+ Calendar.addClass(year, "hilite");
484
+ cal.hilitedYear = year;
485
+ } else if (cal.hilitedYear) {
486
+ Calendar.removeClass(cal.hilitedYear, "hilite");
487
+ }
488
+ } else if (cal.hilitedYear) {
489
+ Calendar.removeClass(cal.hilitedYear, "hilite");
490
+ }
491
+ }
492
+ return Calendar.stopEvent(ev);
493
+ };
494
+
495
+ Calendar.tableMouseDown = function (ev) {
496
+ if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
497
+ return Calendar.stopEvent(ev);
498
+ }
499
+ };
500
+
501
+ Calendar.calDragIt = function (ev) {
502
+ var cal = Calendar._C;
503
+ if (!(cal && cal.dragging)) {
504
+ return false;
505
+ }
506
+ var posX;
507
+ var posY;
508
+ if (Calendar.is_ie) {
509
+ posY = window.event.clientY + document.body.scrollTop;
510
+ posX = window.event.clientX + document.body.scrollLeft;
511
+ } else {
512
+ posX = ev.pageX;
513
+ posY = ev.pageY;
514
+ }
515
+ cal.hideShowCovered();
516
+ var st = cal.element.style;
517
+ st.left = (posX - cal.xOffs) + "px";
518
+ st.top = (posY - cal.yOffs) + "px";
519
+ return Calendar.stopEvent(ev);
520
+ };
521
+
522
+ Calendar.calDragEnd = function (ev) {
523
+ var cal = Calendar._C;
524
+ if (!cal) {
525
+ return false;
526
+ }
527
+ cal.dragging = false;
528
+ with (Calendar) {
529
+ removeEvent(document, "mousemove", calDragIt);
530
+ removeEvent(document, "mouseup", calDragEnd);
531
+ tableMouseUp(ev);
532
+ }
533
+ cal.hideShowCovered();
534
+ };
535
+
536
+ Calendar.dayMouseDown = function(ev) {
537
+ var el = Calendar.getElement(ev);
538
+ if (el.disabled) {
539
+ return false;
540
+ }
541
+ var cal = el.calendar;
542
+ cal.activeDiv = el;
543
+ Calendar._C = cal;
544
+ if (el.navtype != 300) with (Calendar) {
545
+ if (el.navtype == 50) {
546
+ el._current = el.innerHTML;
547
+ addEvent(document, "mousemove", tableMouseOver);
548
+ } else
549
+ addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
550
+ addClass(el, "hilite active");
551
+ addEvent(document, "mouseup", tableMouseUp);
552
+ } else if (cal.isPopup) {
553
+ cal._dragStart(ev);
554
+ }
555
+ if (el.navtype == -1 || el.navtype == 1) {
556
+ if (cal.timeout) clearTimeout(cal.timeout);
557
+ cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
558
+ } else if (el.navtype == -2 || el.navtype == 2) {
559
+ if (cal.timeout) clearTimeout(cal.timeout);
560
+ cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
561
+ } else {
562
+ cal.timeout = null;
563
+ }
564
+ return Calendar.stopEvent(ev);
565
+ };
566
+
567
+ Calendar.dayMouseDblClick = function(ev) {
568
+ Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
569
+ if (Calendar.is_ie) {
570
+ document.selection.empty();
571
+ }
572
+ };
573
+
574
+ Calendar.dayMouseOver = function(ev) {
575
+ var el = Calendar.getElement(ev);
576
+ if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
577
+ return false;
578
+ }
579
+ if (el.ttip) {
580
+ if (el.ttip.substr(0, 1) == "_") {
581
+ el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
582
+ }
583
+ el.calendar.tooltips.innerHTML = el.ttip;
584
+ }
585
+ if (el.navtype != 300) {
586
+ Calendar.addClass(el, "hilite");
587
+ if (el.caldate) {
588
+ Calendar.addClass(el.parentNode, "rowhilite");
589
+ }
590
+ }
591
+ return Calendar.stopEvent(ev);
592
+ };
593
+
594
+ Calendar.dayMouseOut = function(ev) {
595
+ with (Calendar) {
596
+ var el = getElement(ev);
597
+ if (isRelated(el, ev) || _C || el.disabled)
598
+ return false;
599
+ removeClass(el, "hilite");
600
+ if (el.caldate)
601
+ removeClass(el.parentNode, "rowhilite");
602
+ if (el.calendar)
603
+ el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
604
+ return stopEvent(ev);
605
+ }
606
+ };
607
+
608
+ /**
609
+ * A generic "click" handler :) handles all types of buttons defined in this
610
+ * calendar.
611
+ */
612
+ Calendar.cellClick = function(el, ev) {
613
+ var cal = el.calendar;
614
+ var closing = false;
615
+ var newdate = false;
616
+ var date = null;
617
+ if (typeof el.navtype == "undefined") {
618
+ if (cal.currentDateEl) {
619
+ Calendar.removeClass(cal.currentDateEl, "selected");
620
+ Calendar.addClass(el, "selected");
621
+ closing = (cal.currentDateEl == el);
622
+ if (!closing) {
623
+ cal.currentDateEl = el;
624
+ }
625
+ }
626
+ cal.date.setDateOnly(el.caldate);
627
+ date = cal.date;
628
+ var other_month = !(cal.dateClicked = !el.otherMonth);
629
+ if (!other_month && !cal.currentDateEl)
630
+ cal._toggleMultipleDate(new Date(date));
631
+ else
632
+ newdate = !el.disabled;
633
+ // a date was clicked
634
+ if (other_month)
635
+ cal._init(cal.firstDayOfWeek, date);
636
+ } else {
637
+ if (el.navtype == 200) {
638
+ Calendar.removeClass(el, "hilite");
639
+ cal.callCloseHandler();
640
+ return;
641
+ }
642
+ date = new Date(cal.date);
643
+ if (el.navtype == 0)
644
+ date.setDateOnly(new Date()); // TODAY
645
+ // unless "today" was clicked, we assume no date was clicked so
646
+ // the selected handler will know not to close the calenar when
647
+ // in single-click mode.
648
+ // cal.dateClicked = (el.navtype == 0);
649
+ cal.dateClicked = false;
650
+ var year = date.getFullYear();
651
+ var mon = date.getMonth();
652
+ function setMonth(m) {
653
+ var day = date.getDate();
654
+ var max = date.getMonthDays(m);
655
+ if (day > max) {
656
+ date.setDate(max);
657
+ }
658
+ date.setMonth(m);
659
+ };
660
+ switch (el.navtype) {
661
+ case 400:
662
+ Calendar.removeClass(el, "hilite");
663
+ var text = Calendar._TT["ABOUT"];
664
+ if (typeof text != "undefined") {
665
+ text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
666
+ } else {
667
+ // FIXME: this should be removed as soon as lang files get updated!
668
+ text = "Help and about box text is not translated into this language.\n" +
669
+ "If you know this language and you feel generous please update\n" +
670
+ "the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
671
+ "and send it back to <mihai_bazon@yahoo.com> to get it into the distribution ;-)\n\n" +
672
+ "Thank you!\n" +
673
+ "http://dynarch.com/mishoo/calendar.epl\n";
674
+ }
675
+ alert(text);
676
+ return;
677
+ case -2:
678
+ if (year > cal.minYear) {
679
+ date.setFullYear(year - 1);
680
+ }
681
+ break;
682
+ case -1:
683
+ if (mon > 0) {
684
+ setMonth(mon - 1);
685
+ } else if (year-- > cal.minYear) {
686
+ date.setFullYear(year);
687
+ setMonth(11);
688
+ }
689
+ break;
690
+ case 1:
691
+ if (mon < 11) {
692
+ setMonth(mon + 1);
693
+ } else if (year < cal.maxYear) {
694
+ date.setFullYear(year + 1);
695
+ setMonth(0);
696
+ }
697
+ break;
698
+ case 2:
699
+ if (year < cal.maxYear) {
700
+ date.setFullYear(year + 1);
701
+ }
702
+ break;
703
+ case 100:
704
+ cal.setFirstDayOfWeek(el.fdow);
705
+ return;
706
+ case 50:
707
+ var range = el._range;
708
+ var current = el.innerHTML;
709
+ for (var i = range.length; --i >= 0;)
710
+ if (range[i] == current)
711
+ break;
712
+ if (ev && ev.shiftKey) {
713
+ if (--i < 0)
714
+ i = range.length - 1;
715
+ } else if ( ++i >= range.length )
716
+ i = 0;
717
+ var newval = range[i];
718
+ el.innerHTML = newval;
719
+ cal.onUpdateTime();
720
+ return;
721
+ case 0:
722
+ // TODAY will bring us here
723
+ if ((typeof cal.getDateStatus == "function") &&
724
+ cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
725
+ return false;
726
+ }
727
+ break;
728
+ }
729
+ if (!date.equalsTo(cal.date)) {
730
+ cal.setDate(date);
731
+ newdate = true;
732
+ } else if (el.navtype == 0)
733
+ newdate = closing = true;
734
+ }
735
+ if (newdate) {
736
+ ev && cal.callHandler();
737
+ }
738
+ if (closing) {
739
+ Calendar.removeClass(el, "hilite");
740
+ ev && cal.callCloseHandler();
741
+ }
742
+ };
743
+
744
+ // END: CALENDAR STATIC FUNCTIONS
745
+
746
+ // BEGIN: CALENDAR OBJECT FUNCTIONS
747
+
748
+ /**
749
+ * This function creates the calendar inside the given parent. If _par is
750
+ * null than it creates a popup calendar inside the BODY element. If _par is
751
+ * an element, be it BODY, then it creates a non-popup calendar (still
752
+ * hidden). Some properties need to be set before calling this function.
753
+ */
754
+ Calendar.prototype.create = function (_par) {
755
+ var parent = null;
756
+ if (! _par) {
757
+ // default parent is the document body, in which case we create
758
+ // a popup calendar.
759
+ parent = document.getElementsByTagName("body")[0];
760
+ this.isPopup = true;
761
+ } else {
762
+ parent = _par;
763
+ this.isPopup = false;
764
+ }
765
+ this.date = this.dateStr ? new Date(this.dateStr) : new Date();
766
+
767
+ var table = Calendar.createElement("table");
768
+ this.table = table;
769
+ table.cellSpacing = 0;
770
+ table.cellPadding = 0;
771
+ table.calendar = this;
772
+ Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
773
+
774
+ var div = Calendar.createElement("div");
775
+ this.element = div;
776
+ div.className = "calendar";
777
+ if (this.isPopup) {
778
+ div.style.position = "absolute";
779
+ div.style.display = "none";
780
+ }
781
+ div.appendChild(table);
782
+
783
+ var thead = Calendar.createElement("thead", table);
784
+ var cell = null;
785
+ var row = null;
786
+
787
+ var cal = this;
788
+ var hh = function (text, cs, navtype) {
789
+ cell = Calendar.createElement("td", row);
790
+ cell.colSpan = cs;
791
+ cell.className = "button";
792
+ if (navtype != 0 && Math.abs(navtype) <= 2)
793
+ cell.className += " nav";
794
+ Calendar._add_evs(cell);
795
+ cell.calendar = cal;
796
+ cell.navtype = navtype;
797
+ cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
798
+ return cell;
799
+ };
800
+
801
+ row = Calendar.createElement("tr", thead);
802
+ var title_length = 6;
803
+ (this.isPopup) && --title_length;
804
+ (this.weekNumbers) && ++title_length;
805
+
806
+ hh("?", 1, 400).ttip = Calendar._TT["INFO"];
807
+ this.title = hh("", title_length, 300);
808
+ this.title.className = "title";
809
+ if (this.isPopup) {
810
+ this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
811
+ this.title.style.cursor = "move";
812
+ hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
813
+ }
814
+
815
+ row = Calendar.createElement("tr", thead);
816
+ row.className = "headrow";
817
+
818
+ this._nav_py = hh("&#x00ab;", 1, -2);
819
+ this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
820
+
821
+ this._nav_pm = hh("&#x2039;", 1, -1);
822
+ this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
823
+
824
+ this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
825
+ this._nav_now.ttip = Calendar._TT["GO_TODAY"];
826
+
827
+ this._nav_nm = hh("&#x203a;", 1, 1);
828
+ this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
829
+
830
+ this._nav_ny = hh("&#x00bb;", 1, 2);
831
+ this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
832
+
833
+ // day names
834
+ row = Calendar.createElement("tr", thead);
835
+ row.className = "daynames";
836
+ if (this.weekNumbers) {
837
+ cell = Calendar.createElement("td", row);
838
+ cell.className = "name wn";
839
+ cell.innerHTML = Calendar._TT["WK"];
840
+ }
841
+ for (var i = 7; i > 0; --i) {
842
+ cell = Calendar.createElement("td", row);
843
+ if (!i) {
844
+ cell.navtype = 100;
845
+ cell.calendar = this;
846
+ Calendar._add_evs(cell);
847
+ }
848
+ }
849
+ this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
850
+ this._displayWeekdays();
851
+
852
+ var tbody = Calendar.createElement("tbody", table);
853
+ this.tbody = tbody;
854
+
855
+ for (i = 6; i > 0; --i) {
856
+ row = Calendar.createElement("tr", tbody);
857
+ if (this.weekNumbers) {
858
+ cell = Calendar.createElement("td", row);
859
+ }
860
+ for (var j = 7; j > 0; --j) {
861
+ cell = Calendar.createElement("td", row);
862
+ cell.calendar = this;
863
+ Calendar._add_evs(cell);
864
+ }
865
+ }
866
+
867
+ if (this.showsTime) {
868
+ row = Calendar.createElement("tr", tbody);
869
+ row.className = "time";
870
+
871
+ cell = Calendar.createElement("td", row);
872
+ cell.className = "time";
873
+ cell.colSpan = 2;
874
+ cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";
875
+
876
+ cell = Calendar.createElement("td", row);
877
+ cell.className = "time";
878
+ cell.colSpan = this.weekNumbers ? 4 : 3;
879
+
880
+ (function(){
881
+ function makeTimePart(className, init, range_start, range_end) {
882
+ var part = Calendar.createElement("span", cell);
883
+ part.className = className;
884
+ part.innerHTML = init;
885
+ part.calendar = cal;
886
+ part.ttip = Calendar._TT["TIME_PART"];
887
+ part.navtype = 50;
888
+ part._range = [];
889
+ if (typeof range_start != "number")
890
+ part._range = range_start;
891
+ else {
892
+ for (var i = range_start; i <= range_end; ++i) {
893
+ var txt;
894
+ if (i < 10 && range_end >= 10) txt = '0' + i;
895
+ else txt = '' + i;
896
+ part._range[part._range.length] = txt;
897
+ }
898
+ }
899
+ Calendar._add_evs(part);
900
+ return part;
901
+ };
902
+ var hrs = cal.date.getHours();
903
+ var mins = cal.date.getMinutes();
904
+ var t12 = !cal.time24;
905
+ var pm = (hrs > 12);
906
+ if (t12 && pm) hrs -= 12;
907
+ var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
908
+ var span = Calendar.createElement("span", cell);
909
+ span.innerHTML = ":";
910
+ span.className = "colon";
911
+ var M = makeTimePart("minute", mins, 0, 59);
912
+ var AP = null;
913
+ cell = Calendar.createElement("td", row);
914
+ cell.className = "time";
915
+ cell.colSpan = 2;
916
+ if (t12)
917
+ AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
918
+ else
919
+ cell.innerHTML = "&nbsp;";
920
+
921
+ cal.onSetTime = function() {
922
+ var pm, hrs = this.date.getHours(),
923
+ mins = this.date.getMinutes();
924
+ if (t12) {
925
+ pm = (hrs >= 12);
926
+ if (pm) hrs -= 12;
927
+ if (hrs == 0) hrs = 12;
928
+ AP.innerHTML = pm ? "pm" : "am";
929
+ }
930
+ H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
931
+ M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
932
+ };
933
+
934
+ cal.onUpdateTime = function() {
935
+ var date = this.date;
936
+ var h = parseInt(H.innerHTML, 10);
937
+ if (t12) {
938
+ if (/pm/i.test(AP.innerHTML) && h < 12)
939
+ h += 12;
940
+ else if (/am/i.test(AP.innerHTML) && h == 12)
941
+ h = 0;
942
+ }
943
+ var d = date.getDate();
944
+ var m = date.getMonth();
945
+ var y = date.getFullYear();
946
+ date.setHours(h);
947
+ date.setMinutes(parseInt(M.innerHTML, 10));
948
+ date.setFullYear(y);
949
+ date.setMonth(m);
950
+ date.setDate(d);
951
+ this.dateClicked = false;
952
+ this.callHandler();
953
+ };
954
+ })();
955
+ } else {
956
+ this.onSetTime = this.onUpdateTime = function() {};
957
+ }
958
+
959
+ var tfoot = Calendar.createElement("tfoot", table);
960
+
961
+ row = Calendar.createElement("tr", tfoot);
962
+ row.className = "footrow";
963
+
964
+ cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
965
+ cell.className = "ttip";
966
+ if (this.isPopup) {
967
+ cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
968
+ cell.style.cursor = "move";
969
+ }
970
+ this.tooltips = cell;
971
+
972
+ div = Calendar.createElement("div", this.element);
973
+ this.monthsCombo = div;
974
+ div.className = "combo";
975
+ for (i = 0; i < Calendar._MN.length; ++i) {
976
+ var mn = Calendar.createElement("div");
977
+ mn.className = Calendar.is_ie ? "label-IEfix" : "label";
978
+ mn.month = i;
979
+ mn.innerHTML = Calendar._SMN[i];
980
+ div.appendChild(mn);
981
+ }
982
+
983
+ div = Calendar.createElement("div", this.element);
984
+ this.yearsCombo = div;
985
+ div.className = "combo";
986
+ for (i = 12; i > 0; --i) {
987
+ var yr = Calendar.createElement("div");
988
+ yr.className = Calendar.is_ie ? "label-IEfix" : "label";
989
+ div.appendChild(yr);
990
+ }
991
+
992
+ this._init(this.firstDayOfWeek, this.date);
993
+ parent.appendChild(this.element);
994
+ };
995
+
996
+ /** keyboard navigation, only for popup calendars */
997
+ Calendar._keyEvent = function(ev) {
998
+ var cal = window._dynarch_popupCalendar;
999
+ if (!cal || cal.multiple)
1000
+ return false;
1001
+ (Calendar.is_ie) && (ev = window.event);
1002
+ var act = (Calendar.is_ie || ev.type == "keypress"),
1003
+ K = ev.keyCode;
1004
+ if (ev.ctrlKey) {
1005
+ switch (K) {
1006
+ case 37: // KEY left
1007
+ act && Calendar.cellClick(cal._nav_pm);
1008
+ break;
1009
+ case 38: // KEY up
1010
+ act && Calendar.cellClick(cal._nav_py);
1011
+ break;
1012
+ case 39: // KEY right
1013
+ act && Calendar.cellClick(cal._nav_nm);
1014
+ break;
1015
+ case 40: // KEY down
1016
+ act && Calendar.cellClick(cal._nav_ny);
1017
+ break;
1018
+ default:
1019
+ return false;
1020
+ }
1021
+ } else switch (K) {
1022
+ case 32: // KEY space (now)
1023
+ Calendar.cellClick(cal._nav_now);
1024
+ break;
1025
+ case 27: // KEY esc
1026
+ act && cal.callCloseHandler();
1027
+ break;
1028
+ case 37: // KEY left
1029
+ case 38: // KEY up
1030
+ case 39: // KEY right
1031
+ case 40: // KEY down
1032
+ if (act) {
1033
+ var prev, x, y, ne, el, step;
1034
+ prev = K == 37 || K == 38;
1035
+ step = (K == 37 || K == 39) ? 1 : 7;
1036
+ function setVars() {
1037
+ el = cal.currentDateEl;
1038
+ var p = el.pos;
1039
+ x = p & 15;
1040
+ y = p >> 4;
1041
+ ne = cal.ar_days[y][x];
1042
+ };setVars();
1043
+ function prevMonth() {
1044
+ var date = new Date(cal.date);
1045
+ date.setDate(date.getDate() - step);
1046
+ cal.setDate(date);
1047
+ };
1048
+ function nextMonth() {
1049
+ var date = new Date(cal.date);
1050
+ date.setDate(date.getDate() + step);
1051
+ cal.setDate(date);
1052
+ };
1053
+ while (1) {
1054
+ switch (K) {
1055
+ case 37: // KEY left
1056
+ if (--x >= 0)
1057
+ ne = cal.ar_days[y][x];
1058
+ else {
1059
+ x = 6;
1060
+ K = 38;
1061
+ continue;
1062
+ }
1063
+ break;
1064
+ case 38: // KEY up
1065
+ if (--y >= 0)
1066
+ ne = cal.ar_days[y][x];
1067
+ else {
1068
+ prevMonth();
1069
+ setVars();
1070
+ }
1071
+ break;
1072
+ case 39: // KEY right
1073
+ if (++x < 7)
1074
+ ne = cal.ar_days[y][x];
1075
+ else {
1076
+ x = 0;
1077
+ K = 40;
1078
+ continue;
1079
+ }
1080
+ break;
1081
+ case 40: // KEY down
1082
+ if (++y < cal.ar_days.length)
1083
+ ne = cal.ar_days[y][x];
1084
+ else {
1085
+ nextMonth();
1086
+ setVars();
1087
+ }
1088
+ break;
1089
+ }
1090
+ break;
1091
+ }
1092
+ if (ne) {
1093
+ if (!ne.disabled)
1094
+ Calendar.cellClick(ne);
1095
+ else if (prev)
1096
+ prevMonth();
1097
+ else
1098
+ nextMonth();
1099
+ }
1100
+ }
1101
+ break;
1102
+ case 13: // KEY enter
1103
+ if (act)
1104
+ Calendar.cellClick(cal.currentDateEl, ev);
1105
+ break;
1106
+ default:
1107
+ return false;
1108
+ }
1109
+ return Calendar.stopEvent(ev);
1110
+ };
1111
+
1112
+ /**
1113
+ * (RE)Initializes the calendar to the given date and firstDayOfWeek
1114
+ */
1115
+ Calendar.prototype._init = function (firstDayOfWeek, date) {
1116
+ var today = new Date(),
1117
+ TY = today.getFullYear(),
1118
+ TM = today.getMonth(),
1119
+ TD = today.getDate();
1120
+ this.table.style.visibility = "hidden";
1121
+ var year = date.getFullYear();
1122
+ if (year < this.minYear) {
1123
+ year = this.minYear;
1124
+ date.setFullYear(year);
1125
+ } else if (year > this.maxYear) {
1126
+ year = this.maxYear;
1127
+ date.setFullYear(year);
1128
+ }
1129
+ this.firstDayOfWeek = firstDayOfWeek;
1130
+ this.date = new Date(date);
1131
+ var month = date.getMonth();
1132
+ var mday = date.getDate();
1133
+ var no_days = date.getMonthDays();
1134
+
1135
+ // calendar voodoo for computing the first day that would actually be
1136
+ // displayed in the calendar, even if it's from the previous month.
1137
+ // WARNING: this is magic. ;-)
1138
+ date.setDate(1);
1139
+ var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
1140
+ if (day1 < 0)
1141
+ day1 += 7;
1142
+ date.setDate(-day1);
1143
+ date.setDate(date.getDate() + 1);
1144
+
1145
+ var row = this.tbody.firstChild;
1146
+ var MN = Calendar._SMN[month];
1147
+ var ar_days = this.ar_days = new Array();
1148
+ var weekend = Calendar._TT["WEEKEND"];
1149
+ var dates = this.multiple ? (this.datesCells = {}) : null;
1150
+ for (var i = 0; i < 6; ++i, row = row.nextSibling) {
1151
+ var cell = row.firstChild;
1152
+ if (this.weekNumbers) {
1153
+ cell.className = "day wn";
1154
+ cell.innerHTML = date.getWeekNumber();
1155
+ cell = cell.nextSibling;
1156
+ }
1157
+ row.className = "daysrow";
1158
+ var hasdays = false, iday, dpos = ar_days[i] = [];
1159
+ for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
1160
+ iday = date.getDate();
1161
+ var wday = date.getDay();
1162
+ cell.className = "day";
1163
+ cell.pos = i << 4 | j;
1164
+ dpos[j] = cell;
1165
+ var current_month = (date.getMonth() == month);
1166
+ if (!current_month) {
1167
+ if (this.showsOtherMonths) {
1168
+ cell.className += " othermonth";
1169
+ cell.otherMonth = true;
1170
+ } else {
1171
+ cell.className = "emptycell";
1172
+ cell.innerHTML = "&nbsp;";
1173
+ cell.disabled = true;
1174
+ continue;
1175
+ }
1176
+ } else {
1177
+ cell.otherMonth = false;
1178
+ hasdays = true;
1179
+ }
1180
+ cell.disabled = false;
1181
+ cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
1182
+ if (dates)
1183
+ dates[date.print("%Y%m%d")] = cell;
1184
+ if (this.getDateStatus) {
1185
+ var status = this.getDateStatus(date, year, month, iday);
1186
+ if (this.getDateToolTip) {
1187
+ var toolTip = this.getDateToolTip(date, year, month, iday);
1188
+ if (toolTip)
1189
+ cell.title = toolTip;
1190
+ }
1191
+ if (status === true) {
1192
+ cell.className += " disabled";
1193
+ cell.disabled = true;
1194
+ } else {
1195
+ if (/disabled/i.test(status))
1196
+ cell.disabled = true;
1197
+ cell.className += " " + status;
1198
+ }
1199
+ }
1200
+ if (!cell.disabled) {
1201
+ cell.caldate = new Date(date);
1202
+ cell.ttip = "_";
1203
+ if (!this.multiple && current_month
1204
+ && iday == mday && this.hiliteToday) {
1205
+ cell.className += " selected";
1206
+ this.currentDateEl = cell;
1207
+ }
1208
+ if (date.getFullYear() == TY &&
1209
+ date.getMonth() == TM &&
1210
+ iday == TD) {
1211
+ cell.className += " today";
1212
+ cell.ttip += Calendar._TT["PART_TODAY"];
1213
+ }
1214
+ if (weekend.indexOf(wday.toString()) != -1)
1215
+ cell.className += cell.otherMonth ? " oweekend" : " weekend";
1216
+ }
1217
+ }
1218
+ if (!(hasdays || this.showsOtherMonths))
1219
+ row.className = "emptyrow";
1220
+ }
1221
+ this.title.innerHTML = Calendar._MN[month] + ", " + year;
1222
+ this.onSetTime();
1223
+ this.table.style.visibility = "visible";
1224
+ this._initMultipleDates();
1225
+ // PROFILE
1226
+ // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
1227
+ };
1228
+
1229
+ Calendar.prototype._initMultipleDates = function() {
1230
+ if (this.multiple) {
1231
+ for (var i in this.multiple) {
1232
+ var cell = this.datesCells[i];
1233
+ var d = this.multiple[i];
1234
+ if (!d)
1235
+ continue;
1236
+ if (cell)
1237
+ cell.className += " selected";
1238
+ }
1239
+ }
1240
+ };
1241
+
1242
+ Calendar.prototype._toggleMultipleDate = function(date) {
1243
+ if (this.multiple) {
1244
+ var ds = date.print("%Y%m%d");
1245
+ var cell = this.datesCells[ds];
1246
+ if (cell) {
1247
+ var d = this.multiple[ds];
1248
+ if (!d) {
1249
+ Calendar.addClass(cell, "selected");
1250
+ this.multiple[ds] = date;
1251
+ } else {
1252
+ Calendar.removeClass(cell, "selected");
1253
+ delete this.multiple[ds];
1254
+ }
1255
+ }
1256
+ }
1257
+ };
1258
+
1259
+ Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
1260
+ this.getDateToolTip = unaryFunction;
1261
+ };
1262
+
1263
+ /**
1264
+ * Calls _init function above for going to a certain date (but only if the
1265
+ * date is different than the currently selected one).
1266
+ */
1267
+ Calendar.prototype.setDate = function (date) {
1268
+ if (!date.equalsTo(this.date)) {
1269
+ this._init(this.firstDayOfWeek, date);
1270
+ }
1271
+ };
1272
+
1273
+ /**
1274
+ * Refreshes the calendar. Useful if the "disabledHandler" function is
1275
+ * dynamic, meaning that the list of disabled date can change at runtime.
1276
+ * Just * call this function if you think that the list of disabled dates
1277
+ * should * change.
1278
+ */
1279
+ Calendar.prototype.refresh = function () {
1280
+ this._init(this.firstDayOfWeek, this.date);
1281
+ };
1282
+
1283
+ /** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
1284
+ Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
1285
+ this._init(firstDayOfWeek, this.date);
1286
+ this._displayWeekdays();
1287
+ };
1288
+
1289
+ /**
1290
+ * Allows customization of what dates are enabled. The "unaryFunction"
1291
+ * parameter must be a function object that receives the date (as a JS Date
1292
+ * object) and returns a boolean value. If the returned value is true then
1293
+ * the passed date will be marked as disabled.
1294
+ */
1295
+ Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
1296
+ this.getDateStatus = unaryFunction;
1297
+ };
1298
+
1299
+ /** Customization of allowed year range for the calendar. */
1300
+ Calendar.prototype.setRange = function (a, z) {
1301
+ this.minYear = a;
1302
+ this.maxYear = z;
1303
+ };
1304
+
1305
+ /** Calls the first user handler (selectedHandler). */
1306
+ Calendar.prototype.callHandler = function () {
1307
+ if (this.onSelected) {
1308
+ this.onSelected(this, this.date.print(this.dateFormat));
1309
+ }
1310
+ };
1311
+
1312
+ /** Calls the second user handler (closeHandler). */
1313
+ Calendar.prototype.callCloseHandler = function () {
1314
+ if (this.onClose) {
1315
+ this.onClose(this);
1316
+ }
1317
+ this.hideShowCovered();
1318
+ };
1319
+
1320
+ /** Removes the calendar object from the DOM tree and destroys it. */
1321
+ Calendar.prototype.destroy = function () {
1322
+ var el = this.element.parentNode;
1323
+ el.removeChild(this.element);
1324
+ Calendar._C = null;
1325
+ window._dynarch_popupCalendar = null;
1326
+ };
1327
+
1328
+ /**
1329
+ * Moves the calendar element to a different section in the DOM tree (changes
1330
+ * its parent).
1331
+ */
1332
+ Calendar.prototype.reparent = function (new_parent) {
1333
+ var el = this.element;
1334
+ el.parentNode.removeChild(el);
1335
+ new_parent.appendChild(el);
1336
+ };
1337
+
1338
+ // This gets called when the user presses a mouse button anywhere in the
1339
+ // document, if the calendar is shown. If the click was outside the open
1340
+ // calendar this function closes it.
1341
+ Calendar._checkCalendar = function(ev) {
1342
+ var calendar = window._dynarch_popupCalendar;
1343
+ if (!calendar) {
1344
+ return false;
1345
+ }
1346
+ var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
1347
+ for (; el != null && el != calendar.element; el = el.parentNode);
1348
+ if (el == null) {
1349
+ // calls closeHandler which should hide the calendar.
1350
+ window._dynarch_popupCalendar.callCloseHandler();
1351
+ return Calendar.stopEvent(ev);
1352
+ }
1353
+ };
1354
+
1355
+ /** Shows the calendar. */
1356
+ Calendar.prototype.show = function () {
1357
+ var rows = this.table.getElementsByTagName("tr");
1358
+ for (var i = rows.length; i > 0;) {
1359
+ var row = rows[--i];
1360
+ Calendar.removeClass(row, "rowhilite");
1361
+ var cells = row.getElementsByTagName("td");
1362
+ for (var j = cells.length; j > 0;) {
1363
+ var cell = cells[--j];
1364
+ Calendar.removeClass(cell, "hilite");
1365
+ Calendar.removeClass(cell, "active");
1366
+ }
1367
+ }
1368
+ this.element.style.display = "block";
1369
+ this.hidden = false;
1370
+ if (this.isPopup) {
1371
+ window._dynarch_popupCalendar = this;
1372
+ Calendar.addEvent(document, "keydown", Calendar._keyEvent);
1373
+ Calendar.addEvent(document, "keypress", Calendar._keyEvent);
1374
+ Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
1375
+ }
1376
+ this.hideShowCovered();
1377
+ };
1378
+
1379
+ /**
1380
+ * Hides the calendar. Also removes any "hilite" from the class of any TD
1381
+ * element.
1382
+ */
1383
+ Calendar.prototype.hide = function () {
1384
+ if (this.isPopup) {
1385
+ Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
1386
+ Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
1387
+ Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
1388
+ }
1389
+ this.element.style.display = "none";
1390
+ this.hidden = true;
1391
+ this.hideShowCovered();
1392
+ };
1393
+
1394
+ /**
1395
+ * Shows the calendar at a given absolute position (beware that, depending on
1396
+ * the calendar element style -- position property -- this might be relative
1397
+ * to the parent's containing rectangle).
1398
+ */
1399
+ Calendar.prototype.showAt = function (x, y) {
1400
+ var s = this.element.style;
1401
+ s.left = x + "px";
1402
+ s.top = y + "px";
1403
+ this.show();
1404
+ };
1405
+
1406
+ /** Shows the calendar near a given element. */
1407
+ Calendar.prototype.showAtElement = function (el, opts) {
1408
+ var self = this;
1409
+ var p = Calendar.getAbsolutePos(el);
1410
+ if (!opts || typeof opts != "string") {
1411
+ this.showAt(p.x, p.y + el.offsetHeight);
1412
+ return true;
1413
+ }
1414
+ function fixPosition(box) {
1415
+ if (box.x < 0)
1416
+ box.x = 0;
1417
+ if (box.y < 0)
1418
+ box.y = 0;
1419
+ var cp = document.createElement("div");
1420
+ var s = cp.style;
1421
+ s.position = "absolute";
1422
+ s.right = s.bottom = s.width = s.height = "0px";
1423
+ document.body.appendChild(cp);
1424
+ var br = Calendar.getAbsolutePos(cp);
1425
+ document.body.removeChild(cp);
1426
+ // PATCH ?
1427
+ // if (Calendar.is_ie) {
1428
+ // br.y += document.body.scrollTop;
1429
+ // br.x += document.body.scrollLeft;
1430
+ // } else {
1431
+ // br.y += window.scrollY;
1432
+ // br.x += window.scrollX;
1433
+ // }
1434
+ br.x += Calendar.getViewportScrollX();
1435
+ br.y += Calendar.getViewportScrollY();
1436
+
1437
+
1438
+ var tmp = box.x + box.width - br.x;
1439
+ if (tmp > 0) box.x -= tmp;
1440
+ tmp = box.y + box.height - br.y;
1441
+ if (tmp > 0) box.y -= tmp;
1442
+ };
1443
+ this.element.style.display = "block";
1444
+ Calendar.continuation_for_the_fucking_khtml_browser = function() {
1445
+ var w = self.element.offsetWidth;
1446
+ var h = self.element.offsetHeight;
1447
+ self.element.style.display = "none";
1448
+ var valign = opts.substr(0, 1);
1449
+ var halign = "l";
1450
+ if (opts.length > 1) {
1451
+ halign = opts.substr(1, 1);
1452
+ }
1453
+ // vertical alignment
1454
+ switch (valign) {
1455
+ case "T": p.y -= h; break;
1456
+ case "B": p.y += el.offsetHeight; break;
1457
+ case "C": p.y += (el.offsetHeight - h) / 2; break;
1458
+ case "t": p.y += el.offsetHeight - h; break;
1459
+ case "b": break; // already there
1460
+ }
1461
+ // horizontal alignment
1462
+ switch (halign) {
1463
+ case "L": p.x -= w; break;
1464
+ case "R": p.x += el.offsetWidth; break;
1465
+ case "C": p.x += (el.offsetWidth - w) / 2; break;
1466
+ case "l": p.x += el.offsetWidth - w; break;
1467
+ case "r": break; // already there
1468
+ }
1469
+ p.width = w;
1470
+ p.height = h + 40;
1471
+ self.monthsCombo.style.display = "none";
1472
+ fixPosition(p);
1473
+ self.showAt(p.x, p.y);
1474
+ };
1475
+ if (Calendar.is_khtml)
1476
+ setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
1477
+ else
1478
+ Calendar.continuation_for_the_fucking_khtml_browser();
1479
+ };
1480
+
1481
+ /** Customizes the date format. */
1482
+ Calendar.prototype.setDateFormat = function (str) {
1483
+ this.dateFormat = str;
1484
+ };
1485
+
1486
+ /** Customizes the tooltip date format. */
1487
+ Calendar.prototype.setTtDateFormat = function (str) {
1488
+ this.ttDateFormat = str;
1489
+ };
1490
+
1491
+ /**
1492
+ * Tries to identify the date represented in a string. If successful it also
1493
+ * calls this.setDate which moves the calendar to the given date.
1494
+ */
1495
+ Calendar.prototype.parseDate = function(str, fmt) {
1496
+ if (!fmt)
1497
+ fmt = this.dateFormat;
1498
+ this.setDate(Date.parseDate(str, fmt));
1499
+ };
1500
+
1501
+ Calendar.prototype.hideShowCovered = function () {
1502
+ if (!Calendar.is_ie && !Calendar.is_opera)
1503
+ return;
1504
+ function getVisib(obj){
1505
+ var value = obj.style.visibility;
1506
+ if (!value) {
1507
+ if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
1508
+ if (!Calendar.is_khtml)
1509
+ value = document.defaultView.
1510
+ getComputedStyle(obj, "").getPropertyValue("visibility");
1511
+ else
1512
+ value = '';
1513
+ } else if (obj.currentStyle) { // IE
1514
+ value = obj.currentStyle.visibility;
1515
+ } else
1516
+ value = '';
1517
+ }
1518
+ return value;
1519
+ };
1520
+
1521
+ var tags = new Array("applet", "iframe", "select");
1522
+ var el = this.element;
1523
+
1524
+ var p = Calendar.getAbsolutePos(el);
1525
+ var EX1 = p.x;
1526
+ var EX2 = el.offsetWidth + EX1;
1527
+ var EY1 = p.y;
1528
+ var EY2 = el.offsetHeight + EY1;
1529
+
1530
+ for (var k = tags.length; k > 0; ) {
1531
+ var ar = document.getElementsByTagName(tags[--k]);
1532
+ var cc = null;
1533
+
1534
+ for (var i = ar.length; i > 0;) {
1535
+ cc = ar[--i];
1536
+
1537
+ p = Calendar.getAbsolutePos(cc);
1538
+ var CX1 = p.x;
1539
+ var CX2 = cc.offsetWidth + CX1;
1540
+ var CY1 = p.y;
1541
+ var CY2 = cc.offsetHeight + CY1;
1542
+
1543
+ if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
1544
+ if (!cc.__msh_save_visibility) {
1545
+ cc.__msh_save_visibility = getVisib(cc);
1546
+ }
1547
+ cc.style.visibility = cc.__msh_save_visibility;
1548
+ } else {
1549
+ if (!cc.__msh_save_visibility) {
1550
+ cc.__msh_save_visibility = getVisib(cc);
1551
+ }
1552
+ cc.style.visibility = "hidden";
1553
+ }
1554
+ }
1555
+ }
1556
+ };
1557
+
1558
+ /** Internal function; it displays the bar with the names of the weekday. */
1559
+ Calendar.prototype._displayWeekdays = function () {
1560
+ var fdow = this.firstDayOfWeek;
1561
+ var cell = this.firstdayname;
1562
+ var weekend = Calendar._TT["WEEKEND"];
1563
+ for (var i = 0; i < 7; ++i) {
1564
+ cell.className = "day name";
1565
+ var realday = (i + fdow) % 7;
1566
+ if (i) {
1567
+ cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
1568
+ cell.navtype = 100;
1569
+ cell.calendar = this;
1570
+ cell.fdow = realday;
1571
+ Calendar._add_evs(cell);
1572
+ }
1573
+ if (weekend.indexOf(realday.toString()) != -1) {
1574
+ Calendar.addClass(cell, "weekend");
1575
+ }
1576
+ cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
1577
+ cell = cell.nextSibling;
1578
+ }
1579
+ };
1580
+
1581
+ /** Internal function. Hides all combo boxes that might be displayed. */
1582
+ Calendar.prototype._hideCombos = function () {
1583
+ this.monthsCombo.style.display = "none";
1584
+ this.yearsCombo.style.display = "none";
1585
+ };
1586
+
1587
+ /** Internal function. Starts dragging the element. */
1588
+ Calendar.prototype._dragStart = function (ev) {
1589
+ if (this.dragging) {
1590
+ return;
1591
+ }
1592
+ this.dragging = true;
1593
+ var posX;
1594
+ var posY;
1595
+ if (Calendar.is_ie) {
1596
+ posY = window.event.clientY + document.body.scrollTop;
1597
+ posX = window.event.clientX + document.body.scrollLeft;
1598
+ } else {
1599
+ posY = ev.clientY + window.scrollY;
1600
+ posX = ev.clientX + window.scrollX;
1601
+ }
1602
+ var st = this.element.style;
1603
+ this.xOffs = posX - parseInt(st.left);
1604
+ this.yOffs = posY - parseInt(st.top);
1605
+ with (Calendar) {
1606
+ addEvent(document, "mousemove", calDragIt);
1607
+ addEvent(document, "mouseup", calDragEnd);
1608
+ }
1609
+ };
1610
+
1611
+ // BEGIN: DATE OBJECT PATCHES
1612
+
1613
+ /** Adds the number of days array to the Date object. */
1614
+ Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
1615
+
1616
+ /** Constants used for time computations */
1617
+ Date.SECOND = 1000 /* milliseconds */;
1618
+ Date.MINUTE = 60 * Date.SECOND;
1619
+ Date.HOUR = 60 * Date.MINUTE;
1620
+ Date.DAY = 24 * Date.HOUR;
1621
+ Date.WEEK = 7 * Date.DAY;
1622
+
1623
+ Date.parseDate = function(str, fmt) {
1624
+ var today = new Date();
1625
+ var y = 0;
1626
+ var m = -1;
1627
+ var d = 0;
1628
+ var a = str.split(/\W+/);
1629
+ var b = fmt.match(/%./g);
1630
+ var i = 0, j = 0;
1631
+ var hr = 0;
1632
+ var min = 0;
1633
+ for (i = 0; i < a.length; ++i) {
1634
+ if (!a[i])
1635
+ continue;
1636
+ switch (b[i]) {
1637
+ case "%d":
1638
+ case "%e":
1639
+ d = parseInt(a[i], 10);
1640
+ break;
1641
+
1642
+ case "%m":
1643
+ m = parseInt(a[i], 10) - 1;
1644
+ break;
1645
+
1646
+ case "%Y":
1647
+ case "%y":
1648
+ y = parseInt(a[i], 10);
1649
+ (y < 100) && (y += (y > 29) ? 1900 : 2000);
1650
+ break;
1651
+
1652
+ case "%b":
1653
+ case "%B":
1654
+ for (j = 0; j < 12; ++j) {
1655
+ if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
1656
+ }
1657
+ break;
1658
+
1659
+ case "%H":
1660
+ case "%I":
1661
+ case "%k":
1662
+ case "%l":
1663
+ hr = parseInt(a[i], 10);
1664
+ break;
1665
+
1666
+ case "%P":
1667
+ case "%p":
1668
+ if (/pm/i.test(a[i]) && hr < 12)
1669
+ hr += 12;
1670
+ else if (/am/i.test(a[i]) && hr >= 12)
1671
+ hr -= 12;
1672
+ break;
1673
+
1674
+ case "%M":
1675
+ min = parseInt(a[i], 10);
1676
+ break;
1677
+ }
1678
+ }
1679
+ if (isNaN(y)) y = today.getFullYear();
1680
+ if (isNaN(m)) m = today.getMonth();
1681
+ if (isNaN(d)) d = today.getDate();
1682
+ if (isNaN(hr)) hr = today.getHours();
1683
+ if (isNaN(min)) min = today.getMinutes();
1684
+ if (y != 0 && m != -1 && d != 0)
1685
+ return new Date(y, m, d, hr, min, 0);
1686
+ y = 0; m = -1; d = 0;
1687
+ for (i = 0; i < a.length; ++i) {
1688
+ if (a[i].search(/[a-zA-Z]+/) != -1) {
1689
+ var t = -1;
1690
+ for (j = 0; j < 12; ++j) {
1691
+ if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
1692
+ }
1693
+ if (t != -1) {
1694
+ if (m != -1) {
1695
+ d = m+1;
1696
+ }
1697
+ m = t;
1698
+ }
1699
+ } else if (parseInt(a[i], 10) <= 12 && m == -1) {
1700
+ m = a[i]-1;
1701
+ } else if (parseInt(a[i], 10) > 31 && y == 0) {
1702
+ y = parseInt(a[i], 10);
1703
+ (y < 100) && (y += (y > 29) ? 1900 : 2000);
1704
+ } else if (d == 0) {
1705
+ d = a[i];
1706
+ }
1707
+ }
1708
+ if (y == 0)
1709
+ y = today.getFullYear();
1710
+ if (m != -1 && d != 0)
1711
+ return new Date(y, m, d, hr, min, 0);
1712
+ return today;
1713
+ };
1714
+
1715
+ /** Returns the number of days in the current month */
1716
+ Date.prototype.getMonthDays = function(month) {
1717
+ var year = this.getFullYear();
1718
+ if (typeof month == "undefined") {
1719
+ month = this.getMonth();
1720
+ }
1721
+ if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
1722
+ return 29;
1723
+ } else {
1724
+ return Date._MD[month];
1725
+ }
1726
+ };
1727
+
1728
+ /** Returns the number of day in the year. */
1729
+ Date.prototype.getDayOfYear = function() {
1730
+ var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
1731
+ var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
1732
+ var time = now - then;
1733
+ return Math.floor(time / Date.DAY);
1734
+ };
1735
+
1736
+ /** Returns the number of the week in year, as defined in ISO 8601. */
1737
+ Date.prototype.getWeekNumber = function() {
1738
+ var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
1739
+ var DoW = d.getDay();
1740
+ d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
1741
+ var ms = d.valueOf(); // GMT
1742
+ d.setMonth(0);
1743
+ d.setDate(4); // Thu in Week 1
1744
+ return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
1745
+ };
1746
+
1747
+ /** Checks date and time equality */
1748
+ Date.prototype.equalsTo = function(date) {
1749
+ return ((this.getFullYear() == date.getFullYear()) &&
1750
+ (this.getMonth() == date.getMonth()) &&
1751
+ (this.getDate() == date.getDate()) &&
1752
+ (this.getHours() == date.getHours()) &&
1753
+ (this.getMinutes() == date.getMinutes()));
1754
+ };
1755
+
1756
+ /** Set only the year, month, date parts (keep existing time) */
1757
+ Date.prototype.setDateOnly = function(date) {
1758
+ var tmp = new Date(date);
1759
+ this.setDate(1);
1760
+ this.setFullYear(tmp.getFullYear());
1761
+ this.setMonth(tmp.getMonth());
1762
+ this.setDate(tmp.getDate());
1763
+ };
1764
+
1765
+ /** Prints the date in a string according to the given format. */
1766
+ Date.prototype.print = function (str) {
1767
+ var m = this.getMonth();
1768
+ var d = this.getDate();
1769
+ var y = this.getFullYear();
1770
+ var wn = this.getWeekNumber();
1771
+ var w = this.getDay();
1772
+ var s = {};
1773
+ var hr = this.getHours();
1774
+ var pm = (hr >= 12);
1775
+ var ir = (pm) ? (hr - 12) : hr;
1776
+ var dy = this.getDayOfYear();
1777
+ if (ir == 0)
1778
+ ir = 12;
1779
+ var min = this.getMinutes();
1780
+ var sec = this.getSeconds();
1781
+ s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
1782
+ s["%A"] = Calendar._DN[w]; // full weekday name
1783
+ s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
1784
+ s["%B"] = Calendar._MN[m]; // full month name
1785
+ // FIXME: %c : preferred date and time representation for the current locale
1786
+ s["%C"] = 1 + Math.floor(y / 100); // the century number
1787
+ s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
1788
+ s["%e"] = d; // the day of the month (range 1 to 31)
1789
+ // FIXME: %D : american date style: %m/%d/%y
1790
+ // FIXME: %E, %F, %G, %g, %h (man strftime)
1791
+ s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
1792
+ s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
1793
+ s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
1794
+ s["%k"] = hr; // hour, range 0 to 23 (24h format)
1795
+ s["%l"] = ir; // hour, range 1 to 12 (12h format)
1796
+ s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
1797
+ s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
1798
+ s["%n"] = "\n"; // a newline character
1799
+ s["%p"] = pm ? "PM" : "AM";
1800
+ s["%P"] = pm ? "pm" : "am";
1801
+ // FIXME: %r : the time in am/pm notation %I:%M:%S %p
1802
+ // FIXME: %R : the time in 24-hour notation %H:%M
1803
+ s["%s"] = Math.floor(this.getTime() / 1000);
1804
+ s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
1805
+ s["%t"] = "\t"; // a tab character
1806
+ // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
1807
+ s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
1808
+ s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON)
1809
+ s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN)
1810
+ // FIXME: %x : preferred date representation for the current locale without the time
1811
+ // FIXME: %X : preferred time representation for the current locale without the date
1812
+ s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
1813
+ s["%Y"] = y; // year with the century
1814
+ s["%%"] = "%"; // a literal '%' character
1815
+
1816
+ var re = /%./g;
1817
+ if (!Calendar.is_ie5 && !Calendar.is_khtml)
1818
+ return str.replace(re, function (par) { return s[par] || par; });
1819
+
1820
+ var a = str.match(re);
1821
+ for (var i = 0; i < a.length; i++) {
1822
+ var tmp = s[a[i]];
1823
+ if (tmp) {
1824
+ re = new RegExp(a[i], 'g');
1825
+ str = str.replace(re, tmp);
1826
+ }
1827
+ }
1828
+
1829
+ return str;
1830
+ };
1831
+
1832
+ Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
1833
+ Date.prototype.setFullYear = function(y) {
1834
+ var d = new Date(this);
1835
+ d.__msh_oldSetFullYear(y);
1836
+ if (d.getMonth() != this.getMonth())
1837
+ this.setDate(28);
1838
+ this.__msh_oldSetFullYear(y);
1839
+ };
1840
+
1841
+ // END: DATE OBJECT PATCHES
1842
+
1843
+
1844
+ // global object that remembers the calendar
1845
+ window._dynarch_popupCalendar = null;