rails_admin_content 0.1.0

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