1 // Copyright (c) 2005 spinelz.org (http://script.spinelz.org/)
\r
3 // Permission is hereby granted, free of charge, to any person obtaining
\r
4 // a copy of this software and associated documentation files (the
\r
5 // "Software"), to deal in the Software without restriction, including
\r
6 // without limitation the rights to use, copy, modify, merge, publish,
\r
7 // distribute, sublicense, and/or sell copies of the Software, and to
\r
8 // permit persons to whom the Software is furnished to do so, subject to
\r
9 // the following conditions:
\r
11 // The above copyright notice and this permission notice shall be
\r
12 // included in all copies or substantial portions of the Software.
\r
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 var DatePicker = Class.create();
\r
23 DatePicker.className = {
\r
24 container: 'datepicker',
\r
25 header: 'datepicker_header',
\r
26 footer: 'datepicker_footer',
\r
27 preYears: 'datepicker_preYears',
\r
28 nextYears: 'datepicker_nextYears',
\r
29 years: 'datepicker_years',
\r
30 calendar: 'datepicker_calendar',
\r
31 date: 'datepicker_date',
\r
32 holiday: 'datepicker_holiday',
\r
33 ym: 'datepicker_ym',
\r
34 table: 'datepicker_table',
\r
35 tableTh: 'datepicker_tableTh',
\r
36 nextMonthMark: 'datepicker_nextMonthMark',
\r
37 nextYearMark: 'datepicker_nextYearMark',
\r
38 preMonthMark: 'datepicker_preMonthMark',
\r
39 preYearMark: 'datepicker_preYearMark',
\r
42 DatePicker.prototype = {
\r
44 initialize: function(element, target, trigger) {
\r
45 this.element = $(element);
\r
46 Element.setStyle(this.element, {visibility: 'hidden'});
\r
47 this.target = $(target);
\r
48 this.date = new Date();
\r
50 this.options = Object.extend({
\r
51 month: this.date.getMonth() + 1,
\r
52 date: this.date.getDate(),
\r
53 year: this.date.getFullYear(),
\r
54 format: DateUtil.toLocaleDateString,
\r
55 cssPrefix: 'custom_',
\r
56 callBack: Prototype.emptyFunction,
\r
58 beforeShow: Prototype.emptyFunction,
\r
60 dayOfWeek: DateUtil.dayOfWeek
\r
61 }, arguments[3] || {});
\r
63 var customCss = CssUtil.appendPrefix(this.options.cssPrefix, DatePicker.className);
\r
64 this.classNames = new CssUtil([DatePicker.className, customCss]);
\r
66 this.format = this.options.format;
\r
67 this.callBack = this.options.callBack;
\r
69 this.date.setMonth(this.options.month - 1);
\r
70 this.date.setDate(this.options.date);
\r
71 this.date.setFullYear(this.options.year);
\r
73 this.calendar = this.build();
\r
74 this.element.appendChild(this.calendar);
\r
75 this.cover = new IECover(this.element);
\r
77 this.doclistener = this.hide.bindAsEventListener(this);
\r
78 Event.observe($(trigger), "click", this.show.bindAsEventListener(this));
\r
80 Element.setStyle(this.element, {visibility: 'visible'});
\r
87 {className: this.classNames.joinClassNames('container')},
\r
90 this.buildCalendar(),
\r
97 buildHeader: function() {
\r
98 var headerNodes = Builder.node('TR');
\r
99 headerNodes.appendChild(this.buildHeaderLeft());
\r
100 headerNodes.appendChild(this.buildHeaderCenter());
\r
101 headerNodes.appendChild(this.buildHeaderRight());
\r
103 className = this.classNames.joinClassNames('header');
\r
104 var tbody = Builder.node('TBODY', [headerNodes]);
\r
105 return Builder.node('TABLE', {className: className}, [tbody]);
\r
108 buildFooter: function() {
\r
109 var footer = Builder.node('DIV');
\r
110 this.classNames.addClassNames(footer, 'footer');
\r
114 buildHeaderLeft: function() {
\r
115 var container = Builder.node('TD');
\r
116 this.classNames.addClassNames(container, 'preYears');
\r
118 var id = this.element.id.appendSuffix('preYear');
\r
119 var node = Builder.node('DIV', {id: id});
\r
120 this.classNames.addClassNames(node, 'preYearMark');
\r
121 Event.observe(node, "click", this.changeCalendar.bindAsEventListener(this));
\r
122 container.appendChild(node);
\r
124 id = this.element.id.appendSuffix('preMonth');
\r
125 node = Builder.node('DIV', {id: id});
\r
126 this.classNames.addClassNames(node, 'preMonthMark');
\r
127 Event.observe(node, "click", this.changeCalendar.bindAsEventListener(this));
\r
128 container.appendChild(node);
\r
133 buildHeaderCenter: function() {
\r
135 var yearMonth = this.getHeaderYearMonth();
\r
137 var id = this.element.id.appendSuffix('nextMonth');
\r
138 var node = Builder.node('SPAN', {id: id}, [yearMonth[0]]);
\r
139 this.classNames.addClassNames(node, 'ym');
\r
140 contents.push(node);
\r
142 id = this.element.id.appendSuffix('nextYear');
\r
143 node = Builder.node('SPAN', {id: id}, [yearMonth[1]]);
\r
144 this.classNames.addClassNames(node, 'ym');
\r
145 contents.push(node);
\r
147 var container = Builder.node('TD', contents);
\r
148 this.classNames.addClassNames(container, 'years');
\r
153 getHeaderYearMonth: function() {
\r
154 if (this.options.headerFormat) {
\r
155 var tmpl = new Template(this.options.headerFormat);
\r
156 return [tmpl.evaluate({year: this.date.getFullYear(), month: this.date.getMonth() + 1}), ' '];
\r
158 return [DateUtil.months[this.date.getMonth()], this.date.getFullYear()];
\r
161 buildHeaderRight: function() {
\r
162 var container = Builder.node('TD');
\r
163 this.classNames.addClassNames(container, 'nextYears');
\r
165 var id = this.element.id.appendSuffix('nextMonth');
\r
166 var node = Builder.node('DIV', {id: id});
\r
167 this.classNames.addClassNames(node, 'nextMonthMark');
\r
168 Event.observe(node, "click", this.changeCalendar.bindAsEventListener(this));
\r
169 container.appendChild(node);
\r
171 id = this.element.id.appendSuffix('nextYear');
\r
172 node = Builder.node('DIV', {id: id});
\r
173 this.classNames.addClassNames(node, 'nextYearMark');
\r
174 Event.observe(node, "click", this.changeCalendar.bindAsEventListener(this));
\r
175 container.appendChild(node);
\r
180 multiBuild: function(tagType, params, className, hover, clickEvent) {
\r
182 for (var i = 0; i < params.length; i++) {
\r
185 node = Builder.node(tagType, [params[i]]);
\r
187 this.classNames.addClassNames(node, className);
\r
193 Event.observe(node, "click", clickEvent.bindAsEventListener(this));
\r
195 children.push(node);
\r
201 buildCalendar: function() {
\r
202 var className = this.classNames.joinClassNames('table');
\r
203 var node = Builder.node('TBODY', [this.buildTableHeader(), this.buildTableData()]);
\r
204 var table = Builder.node('TABLE', {className: className}, [node]);
\r
206 className = this.classNames.joinClassNames('calendar');
\r
207 return Builder.node('DIV', {className: className}, [table]);
\r
210 buildTableHeader: function() {
\r
211 var weekArray = new Array();
\r
212 var className = this.classNames.joinClassNames('tableTh');
\r
213 for (var i = 0; i < DateUtil.dayOfWeek.length; i++) {
\r
215 Builder.node('TH', {className: className}, [this.options.dayOfWeek[i]]));
\r
218 return Builder.node('TR', weekArray);
\r
221 buildTableData: function() {
\r
222 var length = DateUtil.dayOfWeek.length * 6;
\r
223 var year = this.date.getFullYear();
\r
224 var month = this.date.getMonth();
\r
225 var firstDay = DateUtil.getFirstDate(year, month).getDay();
\r
226 var lastDate = DateUtil.getLastDate(year, month).getDate();
\r
227 var trs = new Array();
\r
228 var tds = new Array();
\r
230 for (var i = 0, day = 1; i <= length; i++) {
\r
231 if ((i < firstDay) || day > lastDate) {
\r
232 tds.push(Builder.node('TD'));
\r
236 if ((i % 7 == 0) || ((i+1) % 7 == 0))
\r
237 className = 'holiday';
\r
239 className = 'date';
\r
241 var defaultClass = this.classNames.joinClassNames(className);
\r
242 node = Builder.node('TD', {className: defaultClass}, [day]);
\r
244 Event.observe(node, "click", this.selectDate.bindAsEventListener(this));
\r
249 if ((i + 1) % 7 == 0) {
\r
250 trs.push(Builder.node('TR', tds));
\r
258 refresh: function() {
\r
259 this.element.innerHTML = '';
\r
260 this.calendar = this.build();
\r
261 this.element.appendChild(this.calendar);
\r
262 new IECover(this.element);
\r
265 getMonth: function() {
\r
266 return DateUtil.months[this.date.getMonth()];
\r
269 changeCalendar: function(event) {
\r
270 var element = Event.element(event);
\r
271 if (Element.hasClassName(element, DatePicker.className.preYearMark)) {
\r
272 this.date.setFullYear(this.date.getFullYear() - 1);
\r
273 } else if (Element.hasClassName(element, DatePicker.className.nextYearMark)) {
\r
274 this.date.setFullYear(this.date.getFullYear() + 1);
\r
275 } else if (Element.hasClassName(element, DatePicker.className.preMonthMark)) {
\r
276 var pre = this.date.getMonth() - 1;
\r
279 this.date.setFullYear(this.date.getFullYear() - 1);
\r
281 this.date.setMonth(pre);
\r
282 } else if (Element.hasClassName(element, DatePicker.className.nextMonthMark)) {
\r
283 var next = this.date.getMonth() + 1;
\r
286 this.date.setFullYear(this.date.getFullYear() + 1);
\r
288 this.date.setMonth(next);
\r
292 if (event) Event.stop(event);
\r
295 selectDate: function(event) {
\r
296 var src = Event.element(event);
\r
297 var text = Element.getTextNodes(src)[0];
\r
299 this.date.setDate(text.nodeValue);
\r
300 var value = this.formatDateString();
\r
302 if (this.target.value || this.target.value == '') {
\r
303 this.target.value = value;
\r
305 this.target.innerHTML = value;
\r
309 this.classNames.refreshClassNames(src, 'date');
\r
311 this.callBack(this);
\r
314 show: function(event) {
\r
315 var styles = $H({zIndex: ZindexManager.getIndex(this.options.zIndex)});
\r
316 if (this.options.standTo) {
\r
317 this.defaultParent = this.element.parentNode;
\r
318 document.body.appendChild(this.element);
\r
319 styles = styles.merge({
\r
320 position: 'absolute',
\r
321 left: Event.pointerX(event) + 'px',
\r
322 top: Event.pointerY(event) + 'px'
\r
326 Element.setStyle(this.element, styles);
\r
327 Element.show(this.element);
\r
328 this.cover.resetSize();
\r
329 Event.observe(document, "click", this.doclistener);
\r
336 Event.stopObserving(document, "click", this.doclistener);
\r
337 Element.hide(this.element);
\r
338 if (this.defaultParent) {
\r
339 this.defaultParent.appendChild(this.element);
\r
343 addTrigger: function(trigger) {
\r
344 Event.observe($(trigger), 'click', this.show.bindAsEventListener(this));
\r
347 changeTarget: function(target) {
\r
348 this.target = $(target);
\r
351 formatDateString: function() {
\r
353 if (this.format.constructor == Function) {
\r
354 string = this.format(this.date);
\r
355 } else if (this.format.constructor == String) {
\r
356 string = this.date.strftime(this.format);
\r