1 /**
  2  * @fileOverview This file is a source which be used to create a calendar
  3  * @author <a href="mailto:support@fogtower.com">Fog Tower</a>
  4  * @see <a href="http://www.fogtower.com">fogtower.com</a>
  5  * @version 1.3
  6  */
  7 
  8 /**
  9  * Construct a namespace.
 10  * @namespace JSCalender
 11  */
 12 JSCalender = {
 13 
 14 };
 15 
 16 /**
 17  * Construct a new InlineCalender.
 18  * @class Represents a InlineCalender.
 19  * @constructor
 20  * @example 
 21  * var myCalender = new JSCalender.InlineCalender("containerId");
 22  * @param {String} targetId The id of the Calender's input element.
 23  * @param {String} onClickElementId The id of the Calender's input element.
 24  * @return A new instance of a Calender.
 25  */
 26 JSCalender.InlineCalender = function(id, left, top){
 27    /**
 28     * The id of calender's parent node
 29     * @type String
 30     */
 31     this.id = id;
 32     
 33    /**
 34     * The left of calender
 35     * @type Number
 36     */
 37     this.left = left;
 38     
 39    /**
 40     * The top of calender
 41     * @type Number
 42     */
 43     this.top = top;
 44     
 45     this._initialize();
 46 };
 47 
 48 /**
 49 * Show calendar.
 50 * @public
 51 */
 52 JSCalender.InlineCalender.prototype.show = function(){
 53     this._createCalendarContainer();
 54     if(document.inlineCalendar){
 55     	document.inlineCalendar = this;
 56     	this._addCalendarEvent();
 57     	return;
 58     }
 59     //add event after dom was created.
 60     this._addDocumentEvent();
 61     this._addCalendarEvent();
 62     this._addMonthComboboxEvent();
 63     this._addYearComboboxEvent();
 64     document.inlineCalendar = this;
 65 };
 66 
 67 /**
 68 * Initialize calendar.
 69 * @private
 70 */
 71 JSCalender.InlineCalender.prototype._initialize = function(){
 72     /**
 73      * The id of calender's container
 74      * @default "fogtower-calendar-calendarcontainer"
 75      * @type String
 76      */
 77     this.calendarContainerId = this.id ? this.id + "-calendarcontainer" : "fogtower-calendar-calendarcontainer";
 78 
 79     /**
 80      * The config of calender
 81      * @type Object
 82      */
 83     this.config = Calender_Config;
 84 
 85     /**
 86      * The resource of calender
 87      * @type Object
 88      */
 89     this.resource = Calender_Resources[(this.config.language 
 90                     || (navigator.browserLanguage?navigator.browserLanguage:navigator.language)).toLowerCase()] || Calender_Resources["en"];
 91    
 92     /**
 93      * The first day in week
 94      * @example 
 95      * this.firstDayInWeek = 0;
 96      * The first day in week is Monday.
 97      * this.firstDayInWeek = 6;
 98      * The first day in week is Sunday.
 99      * @type Number
100      */
101     this.firstDayInWeek = this.config.firstDayInWeek;
102 
103     /**
104      * The days' number in month
105      * @type Array
106      */
107     this.monthDate = [31,28,31,30,31,30,31,31,30,31,30,31];
108 
109     /**
110      * Today
111      * @type Date
112      */
113     this.thisDay = new Date();
114 
115     /**
116      * This year
117      * @type Number
118      */
119     this.year = this.thisDay.getFullYear();
120 
121     /**
122      * This month
123      * @type Number
124      */
125     this.month = this.thisDay.getMonth();
126     
127 };
128 
129 
130 /**
131  * Get type of the browser.
132  * @namespace The browser's type
133  * @public
134  */
135 JSCalender.InlineCalender.prototype.Browser = {
136     /**
137      * Browser is IE
138      * @public
139      * @type Boolean
140      */
141     IE : !!(window.attachEvent && !window.opera),
142 
143     /**
144      * Browser is Firefox
145      * @public
146      * @type Boolean
147      */
148     FF : navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
149 
150     /**
151      * Browser is Opera
152      * @public
153      * @type Boolean
154      */
155     Opera : !!window.opera,
156 
157     /**
158      * Browser is WebKit
159      * @public
160      * @type Boolean
161      */
162     WebKit : navigator.userAgent.indexOf('AppleWebKit/') > -1
163 };
164 
165 /**
166  * Create calendar's container.
167  * @private
168  */
169 JSCalender.InlineCalender.prototype._createCalendarContainer = function(){
170     this.calendarContainer = document.getElementById(this.calendarContainerId);
171     if(this.calendarContainer){
172         this.calendarContainer.parentNode.removeChild(this.calendarContainer);
173     }
174     this.calendarContainer = document.createElement("div");
175     this.calendarContainer.id = this.calendarContainerId;
176     this.calendarContainer.className = this.config.css;
177     this.calendarContainer.position = "relative";
178     this.calendarContainer.onselectstart = function(){
179         return false;
180     };
181     if(this.left){
182     	this.calendarContainer.style.left = this.left + "px";
183     }
184     if(this.top){
185     	this.calendarContainer.style.top = this.top + "px";
186     }	
187     var container = document.getElementById(this.id);
188     if(container){
189     	container.appendChild(this.calendarContainer);
190     }
191     else{
192     	document.body.appendChild(this.calendarContainer);
193     }
194     this.calendarContainer.innerHTML = this._createCalendarPanel();
195     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
196     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
197 	this._checkSlidePanel(this._getDateString(this.thisDay.getFullYear(), this.thisDay.getMonth() + 1, this.thisDay.getDate()));
198 };
199 
200 /**
201  * Create calendar's panel.
202  * @private
203  * @returns {String} Create panel of calendar.
204 */
205 JSCalender.InlineCalender.prototype._createCalendarPanel = function(){
206     var str = "<table class='panel' cellspacing='0' cellpadding='0'><tr><td style='height:1px;'>"
207             + "<div class='topleft'></div><div class='topright'></div><div class='monthcombobox' id='"
208         	+ this.calendarContainerId
209         	+ "-monthCombobox'>"
210             + this._createMonthCombobox()
211             + "</div><div class='yearcombobox' id='"
212         	+ this.calendarContainerId
213             + "-yearCombobox' >"
214             + this._createYearCombobox()
215             + "</div></td></tr><tr style='display:none;'><td>"
216         	+ this._createCalendarSlide()
217         	+ "</td></tr><tr><td>"
218             + this._createCalendarTop()
219             + "</td></tr><tr><td id='"
220             + this.calendarContainerId
221             + "-bodypanel'>"
222             + this._createCalendarBody()
223             + "</td></tr><tr><td style='height:10px;'>"
224         	+ this._createCalendarInfoPanel()
225         	+ "</td></tr><tr><td style='height:10px;'>"
226             + this._createCalendarBottom()
227             + "</td></tr></table>";
228     return str; 
229 };
230 
231 
232 /**
233  * Create calendar's slide panel.
234  * @private
235  * @returns {String} Create slide panel of calendar.
236 */
237 JSCalender.InlineCalender.prototype._createCalendarSlide = function(){
238 	var str = "<table class='slidepanel' id='"
239 		    + this.calendarContainerId + "-slidePanel" 
240 			+ "'><tr><td></td><td class='slidepanel-text'></td></tr><tr><td class='slidepanel-text' colspan='2'></td></tr></table>";
241 	return str;
242 };
243 
244 /**
245  * Create calendar's top panel.
246  * @private
247  * @returns {String} Create top panel of calendar.
248 */
249 JSCalender.InlineCalender.prototype._createCalendarTop = function(){
250     var str = "<table class='toppanel'><tr>";
251     var topPostionArray = this.config.topPanel;
252     for(var i = 0, len = topPostionArray.length; i < len; i++){
253         str += "<td onmouseover='javascript:this.className=\"toppanel-hover\";' "
254             + " onmouseout='javascript:this.className=\"\";' ";
255         if(topPostionArray[i].width){
256             str +=" style='width:" + topPostionArray[i].width + ";' ";
257         }
258         str += " id='" + this.calendarContainerId + "-" + topPostionArray[i].id
259             + "' title='" + (this.resource[topPostionArray[i].id] || "") + "' ";
260         if(topPostionArray[i].backgroundImage){
261             str += "style='backgroundImage : " + topPostionArray[i].backgroundImage + ";' ";
262         }
263         if(topPostionArray[i].width){
264             str += "width='" + topPostionArray[i].width + "' ";
265         }
266         if(topPostionArray[i].text){
267             str += ">" + topPostionArray[i].text;
268         }
269         else{
270             str += ">";
271         }
272         str += "</td>";
273     }
274     return str + "</tr></table>";
275 };
276 
277 /**
278  * Create calendar's body panel.
279  * @private
280  * @returns {String} Create body panel of calendar.
281 */
282 JSCalender.InlineCalender.prototype._createCalendarBody = function(){
283     var str = "<table cellspacing='0' cellpadding='0' class='bodypanel'>"
284             + this._createCalendarDays()
285             + this._createCalendarDates()
286             + "</table>";
287     return str;
288 };
289 
290 /**
291  * Create calendar's days in body panel.
292  * @private
293  * @returns {String} Create days in body panel of calendar.
294 */
295 JSCalender.InlineCalender.prototype._createCalendarDays = function(){
296     var weekTitle = this.resource.weekTitle;
297     var weekDays = this.resource.weekDays;
298     var firstDayInWeek = this.firstDayInWeek;
299     var arr = [];
300     if(typeof firstDayInWeek != "number" || firstDayInWeek > 6 || firstDayInWeek < 0){
301         firstDayInWeek = 6;
302     }
303     for(var i = 0; i < 7; i++){
304         if(i >= firstDayInWeek){
305             arr[i - firstDayInWeek] = weekDays[i];
306         }
307         else{
308             arr[7- firstDayInWeek + i] = weekDays[i];
309         }
310     }
311     var str = "<tr class='bodypanel-headrow'><td style='width:16%;' class='bodypanel-weekhead'>" + weekTitle + "</td>";
312     for(var i = 0;i < 7; i++){
313         str += "<td style='width:12%;' class='bodypanel-dayhead";
314         if(arr[i] == weekDays[5] || arr[i] == weekDays[6]){
315             str +=" bodypanel-weekendhead";
316         }
317         str += "'>" + arr[i] + "</td>";
318     }
319     str += "</tr>";
320     return str;
321 };
322 
323 /**
324  * Create calendar's dates in body panel.
325  * @private
326  * @returns {String} Create dates in body panel of calendar.
327 */
328 JSCalender.InlineCalender.prototype._createCalendarDates = function(){
329     var firstDayInWeek = this.firstDayInWeek;
330     var preMonthDate = this._getMonthDate((this.month == 0)?11:(this.month-1));
331     var thisMonthDate = this._getMonthDate(this.month);
332     var weekNumber = this._getYearWeek(new Date(this.year, this.month, 1));
333     var _date = new Date(this.year, this.month, 1);
334     var weekDay = _date.getDay() - 1 - firstDayInWeek;
335     if(weekDay < 0){
336         weekDay = weekDay + 7;
337     }
338     var str = "<tr><td class='bodypanel-week'>"
339         + weekNumber++ 
340         + "</td>";
341 
342     //create last month dates
343     for(var i = 1; i < weekDay + 1; i++){
344         var date = preMonthDate - weekDay + i;
345         var dateString = "";
346             if(this.month == 0){
347                 dateString = this._getDateString(this.year - 1, 12, date);
348             }else{
349                 dateString = this._getDateString(this.year, this.month, date);
350             }
351         str += "<td class='bodypanel-othermonthday' date='" + dateString;
352         str += "'>" + date + "</td>";
353     }
354 
355     //create this month dates
356     var count = weekDay;
357     for(var j = 1; j < thisMonthDate + 1; j++){
358         if(count != 0 && count%7 == 0){
359             str += "<tr><td class='bodypanel-week'>"
360                 + weekNumber++ 
361                 + "</td>";
362         }
363         var _day = new Date(this.year, this.month, j).getDay();
364         var dateString = this._getDateString(this.year, this.month+1, j);
365         str += "<td  date='" + dateString + "' class='";
366         if(_day == 0 || _day == 6){
367             str += "bodypanel-date bodypanel-weekend";
368         }
369         else{
370             str += "bodypanel-date";
371         }
372         var today = this._getDateString(this.thisDay.getFullYear(), this.thisDay.getMonth() + 1, this.thisDay.getDate());
373         if(today == this._getDateString(this.year, this.month+1, j)){
374             str += " bodypanel-today";
375         }
376         if(this.config.dates[dateString] && this.config.dates[dateString].text){
377             str += "' title='"  + this.config.dates[dateString].text;
378         }
379         str += "'>" + j + "</td>";
380         count++;
381         if(count != 0 && count%7 == 0){
382             str += "</tr>";
383         }
384     }
385 
386     //create next month dates
387     _date = new Date(this.year, this.month + 1, 1);
388     weekDay = _date.getDay();
389     if(((weekDay == 0)?6:weekDay - 1) != firstDayInWeek){
390         var dayOfMonth = (firstDayInWeek >= 0)?(firstDayInWeek):6;
391         if(weekDay <= dayOfMonth){
392             var nextMonthCount = dayOfMonth - weekDay;
393         }
394         else{
395             var nextMonthCount = dayOfMonth + 7 - weekDay;
396         }
397         for(var n = 1; n < nextMonthCount + 2; n++){
398             var dateString = "";
399             if(this.month == 11){
400                 dateString = this._getDateString(this.year + 1,1, n);
401             }else{
402                 dateString = this._getDateString(this.year, this.month + 2, n);
403             }
404             str += "<td class='bodypanel-othermonthday' date='"
405                 + dateString + "'>" + n + "</td>";
406         }
407     }
408     str += "</tr>";
409     return str;
410 };
411 
412 /**
413  * Get the number of dates by month.
414  * @param {Number} month The month.
415  * @return The number of dates.
416  */
417 JSCalender.InlineCalender.prototype._getMonthDate = function(month){
418     if(month == 1){
419         return (0==this.year%4 && (this.year%100!=0 || this.year%400==0)) ? 29 : 28;
420     }
421     else{
422         return this.monthDate[month];
423     }
424 };
425 
426 /**
427  * Get the index of year's week by date.
428  * @param {Date} date The date.
429  * @return The index of week.
430  */
431 JSCalender.InlineCalender.prototype._getYearWeek = function(date){
432     var fistDay = new Date(this.year, 0, 1);
433     var d = Math.round((date.valueOf() - fistDay.valueOf()) / 86400000);
434     var weekDay = fistDay.getDay() - 1 - this.firstDayInWeek;
435     if(weekDay < 0){
436         weekDay = weekDay + 7;
437     }
438     var value;
439     if(d==0){
440         value = 1;
441     }
442     else{
443         value = (d + weekDay)/7 + 1;
444     }
445     return parseInt(value, 10);
446 };
447 
448 /**
449  * Create calendar's info panel.
450  * @private
451  * @returns {String} Create info panel of calendar.
452  */
453 JSCalender.InlineCalender.prototype._createCalendarInfoPanel = function(){
454     return "<div class='inforpanel' id='" + this.calendarContainerId + "-info'>"
455     + this.resource.noSelected + "</div>";
456 };
457 
458 /**
459  * Create calendar's bottom panel.
460  * @private
461  * @returns {String} Create bottom panel of calendar.
462  */
463 JSCalender.InlineCalender.prototype._createCalendarBottom = function(){
464     return "<div class='bottompanel'><div class='bottomleft'> </div><div class='bottomright'> </div></div>";
465 };
466 
467 
468 /**
469  * Create month combobox.
470  * @private
471  * @returns {String} Create month combobox of calendar.
472  */
473 JSCalender.InlineCalender.prototype._createMonthCombobox = function(){
474     var months = this.resource.monthArray;
475     var str = "";
476     for(var i = 0; i < 12; i++){
477         str += "<div value='" + i + "'";
478         if(i == this.month){
479             str += " class='monthcombobox-thismonth'";
480         }
481         str += ">";
482         str += months[i];
483         str += "</div>";
484     }
485     return str;
486 };
487 
488 /**
489  * Create year combobox.
490  * @private
491  * @returns {String} Create year combobox of calendar.
492  */
493 JSCalender.InlineCalender.prototype._createYearCombobox = function(year){
494     var thisYear = this.year;
495     if(typeof year == "undefined"){
496         year = thisYear;
497     }
498     var str = "<div class='plus'>-</div>";
499     for(var i = year - 5; i < year + 6; i++){
500         str += "<div value='" + i + "'";
501         if(i == thisYear){
502             str += " class='yearcombobox-thisyear'";
503         }
504         str += ">" + i + "</div>";
505     }
506     str += "<div class='plus'>+</div>";
507     return str;
508 };
509 
510 /**
511  * Add event to calendar.
512  * @private
513  */
514 JSCalender.InlineCalender.prototype._addCalendarEvent = function(){
515     var othis = this;
516     var preYear = document.getElementById(this.calendarContainerId + "-preYear");
517     preYear.onclick = function(){
518         othis._preYear(false);
519     };
520     var nextYear = document.getElementById(this.calendarContainerId + "-nextYear");
521     nextYear.onclick = function(){
522         othis._nextYear(false);
523     };
524     var preMonth = document.getElementById(this.calendarContainerId + "-preMonth");
525     preMonth.onclick = function(){
526         othis._preMonth(false);
527     };
528     var nextMonth = document.getElementById(this.calendarContainerId + "-nextMonth");
529     nextMonth.onclick = function(){
530         othis._nextMonth(false);
531     };
532 
533     var thisMonth = document.getElementById(this.calendarContainerId + "-thisMonth");
534     thisMonth.onclick = function(){
535         var monthCombobox = document.getElementById(othis.calendarContainerId + "-monthCombobox");
536         monthCombobox.innerHTML = othis._createMonthCombobox();
537         othis._addMonthComboboxEvent();
538         monthCombobox.style.display = "block";
539         var thisMonth = document.getElementById(othis.calendarContainerId + "-thisMonth");
540         monthCombobox.style.left = thisMonth.offsetLeft + "px";
541         monthCombobox.style.top = thisMonth.offsetTop + thisMonth.offsetHeight + "px";
542         monthCombobox.style.width = thisMonth.offsetWidth + 15 + "px";
543     };
544 
545     var thisYear = document.getElementById(this.calendarContainerId + "-thisYear");
546     thisYear.onclick = function(){
547         var yearCombobox = document.getElementById(othis.calendarContainerId + "-yearCombobox");
548         yearCombobox.innerHTML = othis._createYearCombobox();
549         othis._addYearComboboxEvent();
550         yearCombobox.style.display = "block";
551         var thisYear = document.getElementById(othis.calendarContainerId + "-thisYear");
552         yearCombobox.style.left = thisYear.offsetLeft + "px";
553         yearCombobox.style.top = thisYear.offsetTop + thisYear.offsetHeight + "px";
554         yearCombobox.style.width = thisYear.offsetWidth-2 + "px";
555     };
556 
557     var rows = document.getElementById(this.calendarContainerId + "-bodypanel").childNodes[0].rows;
558     for(var i = 1; i < rows.length; i++){
559         var row = rows[i];
560         row.onmouseover = function(){
561             othis._addClass(this, "bodypanel-daterow-hover");
562         };
563         row.onmouseout = function(){
564             othis._removeClass(this, "bodypanel-daterow-hover");
565         };
566         var cells = rows[i].cells;        
567         for(var j = 1; j < cells.length; j++){
568             var date = cells[j];
569             var dateValue = date.getAttribute("date");
570             if(dateValue == this.selectedDateValue || this._inDateRange(dateValue)){
571                 this._addClass(date, "bodypanel-date-select");
572             }
573             date.onclick = function(event){
574                 var event = window.event || event;
575                 if(event.shiftKey){
576                 	othis.preSelectedDateValue = othis.selectedDateValue;
577                 }
578                 else{
579                 	othis.preSelectedDateValue = "";
580                 }
581                 othis._addClass(this, "bodypanel-date-select");
582                 othis.selectedDateValue = this.getAttribute("date");
583                 var month = parseInt(othis.selectedDateValue.split('-')[1],10);
584                 var thisMonth = othis.month + 1;
585                 if(thisMonth == 1 && month == 12){
586                     othis._preMonth();
587                 }
588                 else if(thisMonth == 12 && month == 1){
589                     othis._nextMonth();
590                 }
591                 else if(thisMonth > month){
592                     othis._preMonth();
593                 }
594                 else if(thisMonth < month){
595                     othis._nextMonth();
596                 }
597                 othis._freshDaysPanel();
598                 othis._print(othis.selectedDateValue);
599                 othis._checkSlidePanel(othis.selectedDateValue);
600             };
601             date.onmouseover = function(){
602                 othis._addClass(this, "bodypanel-date-hover");
603             };
604             date.onmouseout = function(){
605                 othis._removeClass(this, "bodypanel-date-hover");
606             };
607         }
608     }
609 };
610 
611 /**
612  * Add event to window.document.
613  * @private
614  */
615 JSCalender.InlineCalender.prototype._addDocumentEvent = function(){
616     if(document.addEventListener){
617         document.addEventListener("keypress",this._keyEvent,false);
618         document.addEventListener("mousedown",this._clickCheck,false);
619     }
620     else{
621         document.attachEvent("onkeydown",this._keyEvent);
622         document.attachEvent("onmousedown",this._clickCheck);
623     }
624 };
625 
626 /**
627  * Hide calendar or combobox when clicked
628  * @private
629  */
630 JSCalender.InlineCalender.prototype._clickCheck = function(event){
631     var calendar = document.inlineCalendar;
632     if (!calendar) {
633         return;
634     }
635     event = window.event || event;
636     var element = event.srcElement || event.target;
637     var calendarDom = document.getElementById(calendar.calendarContainerId);
638     var monthCombobox = document.getElementById(calendar.calendarContainerId + "-monthCombobox");
639     var yearCombobox = document.getElementById(calendar.calendarContainerId + "-yearCombobox");
640     for (; element != null && element != calendarDom; element = element.parentNode);
641     if (element == null) {
642         monthCombobox.style.display = "none";
643         yearCombobox.style.display = "none";
644         calendar.focus = false;
645         return;
646     }
647     else{
648     	calendar.focus = true;
649     }
650     element = event.srcElement || event.target;
651     for (; element != null && element != monthCombobox; element = element.parentNode);
652     if (element == null) {
653         monthCombobox.style.display = "none";
654     }
655     element = event.srcElement || event.target;
656     for (; element != null && element != yearCombobox; element = element.parentNode);
657     if (element == null) {
658         yearCombobox.style.display = "none";
659     }
660 };
661 
662 /**
663  * Check data to decide that whether show the slide panel
664  * @param {String} date The date.
665  * @private
666  */
667 JSCalender.InlineCalender.prototype._checkSlidePanel = function(date){
668     var dateInfo = this.config.dates[date];
669     var defaultInfo = this.config.dates["default"];
670     var slidePanelContainer = document.getElementById(this.calendarContainerId + "-slidePanel").parentNode.parentNode;
671     if(dateInfo){
672     	this._showSlidePanel(dateInfo.image, dateInfo.text, date);
673     	slidePanelContainer.style.display = "";
674     }
675     else if(defaultInfo){
676     	this._showSlidePanel(defaultInfo.image, defaultInfo.text, date);
677     	slidePanelContainer.style.display = "";
678     }
679     else{
680     	slidePanelContainer.style.display = "none";	
681     }
682 };
683 
684 /**
685  * Process key event when press keyboard
686  * @param {Object} event The event which comes from pressing keyboard.
687  * @private
688  */
689 JSCalender.InlineCalender.prototype._keyEvent = function(event){
690     var othis = document.inlineCalendar;
691     if(!othis.focus){
692     	return;
693     }
694     var KEY = {
695         LEFT  : 37,
696         UP    : 38,
697         RIGHT : 39,
698         DOWN  : 40,
699         ESC   : 27,
700         ENTER : 13,
701         SPACE : 32
702     };
703     var code = event.keyCode || event.charCode;
704     if(event.ctrlKey){
705         switch(code)
706         {
707             case KEY.LEFT:
708                 othis._preMonth();
709                 break;
710             case KEY.RIGHT:
711                 othis._nextMonth();
712                 break;
713             case KEY.UP:
714                 othis._preYear();
715                 break;
716             case KEY.DOWN:
717                 othis._nextYear();
718                 break;
719             default:
720                 break;
721         }
722     }
723     else{
724         switch(code){
725             case KEY.LEFT:
726                 othis._parseDate(1);
727                 othis._print(othis.selectedDateValue);
728                 break;
729             case KEY.RIGHT:
730                 othis._parseDate(-1);
731                 othis._print(othis.selectedDateValue);
732                 break;
733             case KEY.UP:
734                 othis._parseDate(7);
735                 othis._print(othis.selectedDateValue);
736                 break;
737             case KEY.DOWN:
738                 othis._parseDate(-7);
739                 othis._print(othis.selectedDateValue);
740                 break;
741             case KEY.ESC:
742                 othis._unfocus();
743                 break;
744             case KEY.ENTER:
745                 othis._print(othis.selectedDateValue);
746                 break;
747             case KEY.SPACE:
748                 othis.selectedDateValue = othis._getDateString(othis.thisDay.getFullYear(),othis.thisDay.getMonth()+1,othis.thisDay.getDate());
749                 othis.year = othis.thisDay.getFullYear();
750                 othis.month = othis.thisDay.getMonth();
751                 document.getElementById(othis.calendarContainerId + "-thisYear").innerHTML = othis.year;
752                 document.getElementById(othis.calendarContainerId + "-thisMonth").innerHTML = othis.resource.monthArray[othis.month];
753                 othis._freshDaysPanel();
754                 othis._print(othis.selectedDateValue);
755                 break;
756             default: 
757                 break;
758         }
759     }
760     othis._checkSlidePanel(othis.selectedDateValue);
761     if(event.preventDefault){
762         event.preventDefault();
763     }
764     else{
765         return false;
766     }
767 };
768 
769 /**
770  * Get last year's calendar
771  * @private
772  */
773 JSCalender.InlineCalender.prototype._preYear = function(){
774     this.year--;
775     this._freshDaysPanel();
776     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
777 };
778 
779 /**
780  * Get next year's calendar
781  * @private
782  */
783 JSCalender.InlineCalender.prototype._nextYear = function(){
784     this.year++;
785     this._freshDaysPanel();
786     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
787 };
788 
789 /**
790  * Get last month's calendar
791  * @private
792  */
793 JSCalender.InlineCalender.prototype._preMonth = function(){
794     if(this.month == 0){
795         this.month = 11;
796         this.year--;
797         document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
798     }
799     else{
800         this.month--;
801     }
802     this._freshDaysPanel();
803     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
804 };
805 
806 /**
807  * Get next month's calendar
808  * @private
809  */
810 JSCalender.InlineCalender.prototype._nextMonth = function(){
811     if(this.month == 11){
812         this.month = 0;
813         this.year++;
814         document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
815     }
816     else{
817         this.month++;
818     }
819     this._freshDaysPanel();
820     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
821 };
822 
823 /**
824  * Fresh calendar when press keyboard
825  * @param {Number} step The diff which compares with the selected date.
826  * @private
827  */
828 JSCalender.InlineCalender.prototype._parseDate = function(step){
829     if(this.selectedDateValue){
830         var arr = this.selectedDateValue.split('-');
831         var date = new Date(new Date(arr[0],arr[1]-1,arr[2]) - 24*60*60*1000*step);
832     }
833     else{
834         var date = new Date(this.thisDay - 24*60*60*1000*step);
835     }
836     this.year = date.getFullYear();
837     this.month = date.getMonth();
838     this.date = date.getDate();
839     this.selectedDateValue = this._getDateString(this.year,this.month + 1,this.date);
840     this._freshDaysPanel();
841     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
842     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
843 };
844 
845 /**
846  * Convert Date to string
847  * @param {Number} year The year.
848  * @param {Number} month The month.
849  * @param {Date} date The date.
850  * @private
851  */
852 JSCalender.InlineCalender.prototype._getDateString = function(year,month,date){
853     return year + "-" + ((month < 10)?("0" + (month)):month) + "-" + ((date < 10)?("0" + (date)):date);
854 };
855 
856 
857 /**
858  * Fresh calendar
859  * @private
860  */
861 JSCalender.InlineCalender.prototype._freshDaysPanel = function(){
862     var str = "<table cellspacing='0' cellpadding='0' class='bodypanel'>"
863             + this._createCalendarDays() + this._createCalendarDates()
864             + "</table>";
865     document.getElementById(this.calendarContainerId + "-bodypanel").innerHTML = str;
866     this._addCalendarEvent();
867 };
868 
869 /**
870  * Show slide panel
871  * @private
872  */
873 JSCalender.InlineCalender.prototype._showSlidePanel = function(img, text, dateString){
874 	var slidePanel = document.getElementById(this.calendarContainerId + "-slidePanel");
875 	var imageContainer = slidePanel.rows[0].cells[0];
876 	var topTextContainer = slidePanel.rows[0].cells[1];
877 	var bottomTextContainer = slidePanel.rows[1].cells[0];
878 	if(img){
879 		imageContainer.style.display = "";
880 		imageContainer.innerHTML = "<img class='slidepanel-img' alt='" 
881 							     + dateString + "' src='" + img + "'/>";
882 	}
883 	else{
884 		imageContainer.style.display = "none";
885 	}
886 	if(text){
887 		var textArr = text.split('\n');
888 		
889 		if(textArr.length < 2){
890 			topTextContainer.style.display = "";
891 			bottomTextContainer.style.display = "none";
892 			topTextContainer.innerHTML = textArr[0];
893 		}
894 		else{
895 			topTextContainer.style.display = "";
896 			bottomTextContainer.style.display = "";
897 			topTextContainer.innerHTML = textArr[0];
898 			textArr[0] = "";
899 			bottomTextContainer.innerHTML = textArr.join(" ");
900 		}
901 	}
902 	else{
903 		topTextContainer.style.display = "none";
904 		bottomTextContainer.style.display = "none";
905 	}
906 };
907 
908 /**
909  * Add event to month combobox
910  * @private
911  */
912 JSCalender.InlineCalender.prototype._addMonthComboboxEvent = function(){
913     var othis = this;
914     var monthCombobox = document.getElementById(this.calendarContainerId + "-monthCombobox");
915     for(var i = 0, len = monthCombobox.childNodes.length; i < len; i++){
916         var row = monthCombobox.childNodes[i];
917         row.onclick = function(){
918             document.getElementById(othis.calendarContainerId + "-thisMonth").innerHTML = this.innerHTML;
919             monthCombobox.style.display = "none";
920             othis.month = parseInt(this.getAttribute("value"),10);
921             othis._freshDaysPanel();
922         };
923         row.onmouseover = function(){
924             othis._addClass(this, "monthcombobox-hover");
925         };
926         row.onmouseout = function(){
927             othis._removeClass(this, "monthcombobox-hover");
928         };
929     }
930 };
931 
932 /**
933  * Add event to year combobox
934  * @private
935  */
936 JSCalender.InlineCalender.prototype._addYearComboboxEvent = function(){	
937     var othis = this;
938     var yearCombobox = document.getElementById(this.calendarContainerId + "-yearCombobox");
939 
940     for(var i = 0, len = yearCombobox.childNodes.length; i < len; i++){
941         var row = yearCombobox.childNodes[i];
942         if(i == 0){
943             row.onclick = function(){
944                 var yearCombobox = document.getElementById(othis.calendarContainerId + "-yearCombobox");
945                 yearCombobox.innerHTML = othis._createYearCombobox(parseInt(yearCombobox.childNodes[5].innerHTML,10));
946                 othis._addYearComboboxEvent();
947             };
948         }
949         else if(i == len - 1){
950             row.onclick = function(){
951                 var yearCombobox = document.getElementById(othis.calendarContainerId + "-yearCombobox");
952                 yearCombobox.innerHTML = othis._createYearCombobox(parseInt(yearCombobox.childNodes[5].innerHTML,10) + 2);
953                 othis._addYearComboboxEvent();
954             };
955         }
956         else{
957             row.onclick = function(){
958                 document.getElementById(othis.calendarContainerId + "-thisYear").innerHTML = this.innerHTML;
959                 yearCombobox.style.display = "none";
960                 othis.year = parseInt(this.getAttribute("value"),10);
961                 othis._freshDaysPanel();
962             };
963         }
964         row.onmouseover = function(){
965             othis._addClass(this, "yearcombobox-hover");
966         };
967         row.onmouseout = function(){
968             othis._removeClass(this, "yearcombobox-hover");
969         };
970     }
971 };
972 
973 /**
974  * Add css class to element.
975  * @param {Object} el The element where adds class.
976  * @param {String} className The css class which to be added..
977  * @private
978  */
979 JSCalender.InlineCalender.prototype._addClass = function(el, className) {
980     this._removeClass(el, className);
981     el.className += " " + className;
982 };
983 
984 /**
985  * Remove css class of element.
986  * @param {Object} el The element where removes class.
987  * @param {String} className The css class which to be removed.
988  * @private
989  */
990 JSCalender.InlineCalender.prototype._removeClass = function(el, className) {
991     if (!(el && el.className)) {
992         return;
993     }
994     var cssArr = el.className.split(" ");
995     var newArr = new Array();
996     for (var i = 0, len = cssArr.length; i< len; i++){
997         if (cssArr[i] != className) {
998             newArr[newArr.length] = cssArr[i];
999         }
1000     }
1001     el.className = newArr.join(" ");
1002 };
1003 
1004 /**
1005  * Judge the date is in date range or not.
1006  * @param {String} dataString The date which to be judged.
1007  * @returns {Boolean} in date range or not.
1008  * @private
1009  */
1010 JSCalender.InlineCalender.prototype._inDateRange = function(dataString) {
1011 	if(!this.selectedDateValue || !this.preSelectedDateValue){
1012 		return false;
1013 	}
1014 	if(this.selectedDateValue > this.preSelectedDateValue){
1015 		var earlyDate = this.preSelectedDateValue;
1016 		var oldDate = this.selectedDateValue;
1017 	}
1018 	else{
1019 		var earlyDate = this.selectedDateValue;
1020 		var oldDate = this.preSelectedDateValue;
1021 	}
1022 	if(dataString >= earlyDate && dataString <= oldDate){
1023 		return true;
1024 	}
1025 	return false;
1026 	
1027 };
1028 
1029 /**
1030  * Output the selected date
1031  * @param {String} dateString The format of outputed date
1032  * @private
1033  */
1034 JSCalender.InlineCalender.prototype._print = function(dateString) {
1035 	if(!dateString){
1036 		return;
1037 	}
1038     var arr = dateString.split('-');
1039     var printFormat = (this.config.printFormat || "").toLowerCase();
1040     printFormat = printFormat.replace("yyyy", arr[0]);
1041     printFormat = printFormat.replace("yy", arr[0].substr(2));
1042     printFormat = printFormat.replace("mm", arr[1]);
1043     printFormat = printFormat.replace("dd", arr[2]);
1044     var bottom = document.getElementById(this.calendarContainerId + "-info");
1045     var number = this._getSelectedDatesNumber();
1046     if(number > 1){
1047     	bottom.innerHTML = number + this.resource.selectedDates;
1048     }
1049     else{
1050     	bottom.innerHTML = this.resource.selectedSingleDate + printFormat;
1051     }
1052 };
1053 
1054 /**
1055  * Get the number of selected dates
1056  * @returns {Number} The number of selected dates
1057  * @private
1058  */
1059 JSCalender.InlineCalender.prototype._getSelectedDatesNumber = function() {
1060 	if(!this.selectedDateValue || !this.preSelectedDateValue){
1061 		return 0;
1062 	}
1063 	if(this.selectedDateValue > this.preSelectedDateValue){
1064 		var currentArr = this.selectedDateValue.split('-');
1065 		var preArr = this.preSelectedDateValue.split('-');
1066 	}
1067 	else{
1068 		var currentArr = this.preSelectedDateValue.split('-');
1069 		var preArr = this.selectedDateValue.split('-');
1070 	}
1071 	var cuurentSelectedDate =  new Date(currentArr[0], currentArr[1], currentArr[2]);
1072 	var preSelectedDate =  new Date(preArr[0], preArr[1], preArr[2]);
1073     var number = Math.round((cuurentSelectedDate.valueOf() - preSelectedDate.valueOf()) / 86400000) + 1;
1074     return number;
1075 };
1076 
1077 /**
1078  * Set the config of calendar
1079  * @param {String} config The config which to be set
1080  * @public
1081  */
1082 JSCalender.InlineCalender.prototype.setConfig = function(config) {
1083 	this.config = config;
1084 };
1085 
1086 /**
1087  * Set the language of calendar
1088  * @param {String} lang The language which to be set
1089  * @public
1090  */
1091 JSCalender.InlineCalender.prototype.setLanguage = function(lang) {
1092 	this.resource = Calender_Resources[lang.toLowerCase()]|| Calender_Resources["en"];
1093 };
1094 
1095 /**
1096  * Set the css of calendar
1097  * @param {String} css The css which to be set
1098  * @public
1099  */
1100 JSCalender.InlineCalender.prototype.setCss = function(css) {
1101 	this.config.css = css;
1102 };
1103 
1104 /**
1105  * Set the first day in week
1106  * @param {Number} day The day which to be set
1107  * @public
1108  */
1109 JSCalender.InlineCalender.prototype.setFirstDayInWeek = function(day) {
1110 	this.firstDayInWeek = day;
1111 };
1112 
1113 /**
1114  * Set the export format
1115  * @param {String} date The date which to be set
1116  * @param {String} image The image which to be show in slide panel
1117  * @param {String} text The text which to be show in slide panel
1118  * @public
1119  */
1120 JSCalender.InlineCalender.prototype.setSlideDate = function(date, image, text) {
1121 	this.config.dates[date] = {};
1122 	this.config.dates[date].text = text;
1123 	this.config.dates[date].image = image;
1124 };
1125 
1126 /**
1127  * Construct a new PopCalender.
1128  * @class Represents a PopCalender.
1129  * @constructor
1130  * @example 
1131  * var myCalender = new JSCalender.PopCalender("inputId", "buttonId");
1132  * @param {String} targetId The id of the Calender's input element.
1133  * @param {String} onClickElementId The id of the Calender's input element.
1134  * @return A new instance of a Calender.
1135  */
1136 JSCalender.PopCalender = function(targetId, onClickElementId){
1137    /**
1138     * The id of input element where calender outputs
1139     * @type String
1140     */
1141     this.targetId = targetId;
1142 
1143     /**
1144      * The id of the element which be clicked to show calender
1145      * @type String
1146      */
1147     this.onClickElementId = onClickElementId;
1148     
1149     this._initialize();
1150 };
1151 
1152 /**
1153  * Show the calendar.
1154  * @public
1155  */
1156 JSCalender.PopCalender.prototype.show = function(){
1157     if(document.popCalendar){
1158         if(document.popCalendar.calendarContainerId == this.calendarContainerId){
1159             this._show();
1160             return;
1161         }
1162         else{
1163             this._remove();
1164         }
1165     }
1166     this._createCalendarContainer();
1167 
1168     //add event after dom was created.
1169     this._addDocumentEvent();
1170     this._addCalendarEvent();
1171     this._addMonthComboboxEvent();
1172     this._addYearComboboxEvent();
1173     document.popCalendar = this;
1174 };
1175 
1176 /**
1177 * Initialize calendar.
1178 * @private
1179 */
1180 JSCalender.PopCalender.prototype._initialize = function(){
1181     /**
1182      * The id of calender's container
1183      * @default "fogtower-calendar-calendarcontainer"
1184      * @type String
1185      */
1186     this.calendarContainerId = this.targetId ? this.targetId + "-calendarcontainer" : "fogtower-calendar-calendarcontainer";
1187 
1188     /**
1189      * The config of calender
1190      * @type Object
1191      */
1192     this.config = Calender_Config;
1193 
1194     /**
1195      * The resource of calender
1196      * @type Object
1197      */
1198     this.resource = Calender_Resources[(this.config.language 
1199                     || (navigator.browserLanguage?navigator.browserLanguage:navigator.language)).toLowerCase()] || Calender_Resources["en"];
1200 
1201     /**
1202      * The first day in week
1203      * @example 
1204      * this.firstDayInWeek = 0;
1205      * The first day in week is Monday.
1206      * this.firstDayInWeek = 6;
1207      * The first day in week is Sunday.
1208      * @type Number
1209      */
1210     this.firstDayInWeek = this.config.firstDayInWeek;
1211 
1212     /**
1213      * The days' number in month
1214      * @type Array
1215      */
1216     this.monthDate = [31,28,31,30,31,30,31,31,30,31,30,31];
1217 
1218     /**
1219      * Today
1220      * @type Date
1221      */
1222     this.thisDay = new Date();
1223 
1224     /**
1225      * This year
1226      * @type Number
1227      */
1228     this.year = this.thisDay.getFullYear();
1229 
1230     /**
1231      * This month
1232      * @type Number
1233      */
1234     this.month = this.thisDay.getMonth();
1235 };
1236 
1237 
1238 /**
1239  * Get type of the browser.
1240  * @namespace The browser's type
1241  * @public
1242  */
1243 JSCalender.PopCalender.prototype.Browser = {
1244     /**
1245      * Browser is IE
1246      * @public
1247      * @type Boolean
1248      */
1249     IE : !!(window.attachEvent && !window.opera),
1250 
1251     /**
1252      * Browser is Firefox
1253      * @public
1254      * @type Boolean
1255      */
1256     FF : navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
1257 
1258     /**
1259      * Browser is Opera
1260      * @public
1261      * @type Boolean
1262      */
1263     Opera : !!window.opera,
1264 
1265     /**
1266      * Browser is WebKit
1267      * @public
1268      * @type Boolean
1269      */
1270     WebKit : navigator.userAgent.indexOf('AppleWebKit/') > -1
1271 };
1272 
1273 
1274 
1275 /**
1276  * Create calendar's container.
1277  * @private
1278  */
1279 JSCalender.PopCalender.prototype._createCalendarContainer = function(){
1280     this.calendarContainer = document.getElementById(this.calendarContainerId);
1281     if(this.calendarContainer){
1282         this.calendarContainer.parentNode.removeChild(this.calendarContainer);
1283     }
1284     var pos = this._getPosition(document.getElementById(this.onClickElementId));
1285     this.top = pos.top;
1286     this.left = pos.left;
1287     this.calendarContainer = document.createElement("div");
1288     this.calendarContainer.id = this.calendarContainerId;
1289     this.calendarContainer.className = this.config.css;
1290     this.calendarContainer.style.left = this.left + "px";
1291     this.calendarContainer.style.top = this.top + "px";
1292     document.body.appendChild(this.calendarContainer);
1293     this.calendarContainer.innerHTML = this._createCalendarPanel();
1294     if(this.Browser.IE){
1295         document.body.appendChild(this._createIframeShim());
1296     }
1297     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
1298     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
1299 	this._checkSlidePanel(this._getDateString(this.thisDay.getFullYear(), this.thisDay.getMonth() + 1, this.thisDay.getDate()));
1300 };
1301 
1302 /**
1303  * Create a iframe to fix the combobox's bug of IE6.
1304  * @returns {Object} The created iframe.
1305  * @private
1306  */
1307 JSCalender.PopCalender.prototype._createIframeShim = function(){
1308     var iframe = document.getElementById(this.calendarContainerId + "-iframeshim");
1309     if(iframe){
1310         iframe.parentNode.removeChild(iframe);
1311     }
1312     iframe = document.createElement("iframe");
1313     iframe.id = this.calendarContainerId + "-iframeshim";
1314     iframe.className = this.config.css + "-iframeshim";
1315     iframe.scrolling = "no";
1316     iframe.frameBorder = "0";
1317     iframe.style.position = "absolute";
1318     iframe.style.left = this.left + "px";
1319     iframe.style.top = this.top + "px";
1320     iframe.style.width = this.calendarContainer.offsetWidth + "px";
1321     iframe.style.height = this.calendarContainer.offsetHeight + "px";
1322     return iframe;
1323 };
1324 
1325 /**
1326  * Create calendar's panel.
1327  * @private
1328  * @returns {String} Create panel of calendar.
1329 */
1330 JSCalender.PopCalender.prototype._createCalendarPanel = function(){
1331     var str = "<table class='panel' cellspacing='0' cellpadding='0'><tr><td style='height:1px;'>"
1332             + "<div class='topleft'></div><div class='topright'></div><div class='monthcombobox' id='"
1333         	+ this.calendarContainerId
1334         	+ "-monthCombobox'>"
1335             + this._createMonthCombobox()
1336             + "</div><div class='yearcombobox' id='"
1337         	+ this.calendarContainerId
1338             + "-yearCombobox' >"
1339             + this._createYearCombobox()
1340             + "</div></td></tr><tr style='display:none;'><td>"
1341         	+ this._createCalendarSlide()
1342         	+ "</td></tr><tr><td>"
1343             + this._createCalendarTop()
1344             + "</td></tr><tr><td id='"
1345             + this.calendarContainerId
1346             + "-bodypanel'>"
1347             + this._createCalendarBody()
1348             + "</td></tr><tr><td style='height:10px;'>"
1349             + this._createCalendarBottom()
1350             + "</td></tr></table>";
1351     return str; 
1352 };
1353 
1354 
1355 /**
1356  * Create calendar's slide panel.
1357  * @private
1358  * @returns {String} Create slide panel of calendar.
1359 */
1360 JSCalender.PopCalender.prototype._createCalendarSlide = function(){
1361 	var str = "<table class='slidepanel' id='"
1362 		    + this.calendarContainerId + "-slidePanel" 
1363 			+ "'><tr><td></td><td class='slidepanel-text'></td></tr><tr><td class='slidepanel-text' colspan='2'></td></tr></table>";
1364 	return str;
1365 };
1366 
1367 /**
1368  * Create calendar's top panel.
1369  * @private
1370  * @returns {String} Create top panel of calendar.
1371 */
1372 JSCalender.PopCalender.prototype._createCalendarTop = function(){
1373     var str = "<table class='toppanel'><tr>";
1374     var topPostionArray = this.config.topPanel;
1375     for(var i = 0, len = topPostionArray.length; i < len; i++){
1376         str += "<td onmouseover='javascript:this.className=\"toppanel-hover\";' "
1377             + " onmouseout='javascript:this.className=\"\";' ";
1378         if(topPostionArray[i].width){
1379             str +=" style='width:" + topPostionArray[i].width + ";' ";
1380         }
1381         str += " id='" + this.calendarContainerId + "-" + topPostionArray[i].id
1382             + "' title='" + (this.resource[topPostionArray[i].id] || "") + "' ";
1383         if(topPostionArray[i].backgroundImage){
1384             str += "style='backgroundImage : " + topPostionArray[i].backgroundImage + ";' ";
1385         }
1386         if(topPostionArray[i].width){
1387             str += "width='" + topPostionArray[i].width + "' ";
1388         }
1389         if(topPostionArray[i].text){
1390             str += ">" + topPostionArray[i].text;
1391         }
1392         else{
1393             str += ">";
1394         }
1395         str += "</td>";
1396     }
1397     return str + "</tr></table>";
1398 };
1399 
1400 /**
1401  * Create calendar's body panel.
1402  * @private
1403  * @returns {String} Create body panel of calendar.
1404 */
1405 JSCalender.PopCalender.prototype._createCalendarBody = function(){
1406     var str = "<table cellspacing='0' cellpadding='0' class='bodypanel'>"
1407             + this._createCalendarDays()
1408             + this._createCalendarDates()
1409             + "</table>";
1410     return str;
1411 };
1412 
1413 /**
1414  * Create calendar's days in body panel.
1415  * @private
1416  * @returns {String} Create days in body panel of calendar.
1417 */
1418 JSCalender.PopCalender.prototype._createCalendarDays = function(){
1419     var weekTitle = this.resource.weekTitle;
1420     var weekDays = this.resource.weekDays;
1421     var firstDayInWeek = this.firstDayInWeek;
1422     var arr = [];
1423     if(typeof firstDayInWeek != "number" || firstDayInWeek > 6 || firstDayInWeek < 0){
1424         firstDayInWeek = 6;
1425     }
1426     for(var i = 0; i < 7; i++){
1427         if(i >= firstDayInWeek){
1428             arr[i - firstDayInWeek] = weekDays[i];
1429         }
1430         else{
1431             arr[7- firstDayInWeek + i] = weekDays[i];
1432         }
1433     }
1434     var str = "<tr class='bodypanel-headrow'><td style='width:16%;' class='bodypanel-weekhead'>" + weekTitle + "</td>";
1435     for(var i = 0;i < 7; i++){
1436         str += "<td style='width:12%;' class='bodypanel-dayhead";
1437         if(arr[i] == weekDays[5] || arr[i] == weekDays[6]){
1438             str +=" bodypanel-weekendhead";
1439         }
1440         str += "'>" + arr[i] + "</td>";
1441     }
1442     str += "</tr>";
1443     return str;
1444 };
1445 
1446 /**
1447  * Create calendar's dates in body panel.
1448  * @private
1449  * @returns {String} Create dates in body panel of calendar.
1450 */
1451 JSCalender.PopCalender.prototype._createCalendarDates = function(){
1452     var firstDayInWeek = this.firstDayInWeek;
1453     var preMonthDate = this._getMonthDate((this.month == 0)?11:(this.month-1));
1454     var thisMonthDate = this._getMonthDate(this.month);
1455     var weekNumber = this._getYearWeek(new Date(this.year, this.month, 1));
1456     var _date = new Date(this.year, this.month, 1);
1457     var weekDay = _date.getDay() - 1 - firstDayInWeek;
1458     if(weekDay < 0){
1459         weekDay = weekDay + 7;
1460     }
1461     var str = "<tr><td class='bodypanel-week'>"
1462         + weekNumber++ 
1463         + "</td>";
1464 
1465     //create last month dates
1466     for(var i = 1; i < weekDay + 1; i++){
1467         var date = preMonthDate - weekDay + i;
1468         var dateString = "";
1469             if(this.month == 0){
1470                 dateString = this._getDateString(this.year - 1, 12, date);
1471             }else{
1472                 dateString = this._getDateString(this.year, this.month, date);
1473             }
1474         str += "<td class='bodypanel-othermonthday' date='" + dateString;
1475         str += "'>" + date + "</td>";
1476     }
1477 
1478     //create this month dates
1479     var count = weekDay;
1480     for(var j = 1; j < thisMonthDate + 1; j++){
1481         if(count != 0 && count%7 == 0){
1482             str += "<tr><td class='bodypanel-week'>"
1483                 + weekNumber++ 
1484                 + "</td>";
1485         }
1486         var _day = new Date(this.year, this.month, j).getDay();
1487         var dateString = this._getDateString(this.year, this.month+1, j);
1488         str += "<td  date='" + dateString + "' class='";
1489         if(_day == 0 || _day == 6){
1490             str += "bodypanel-date bodypanel-weekend";
1491         }
1492         else{
1493             str += "bodypanel-date";
1494         }
1495         var today = this._getDateString(this.thisDay.getFullYear(), this.thisDay.getMonth() + 1, this.thisDay.getDate());
1496         if(today == this._getDateString(this.year, this.month+1, j)){
1497             str += " bodypanel-today";
1498         }
1499         if(this.config.dates[dateString] && this.config.dates[dateString].text){
1500             str += "' title='"  + this.config.dates[dateString].text;
1501         }
1502         str += "'>" + j + "</td>";
1503         count++;
1504         if(count != 0 && count%7 == 0){
1505             str += "</tr>";
1506         }
1507     }
1508 
1509     //create next month dates
1510     _date = new Date(this.year, this.month + 1, 1);
1511     weekDay = _date.getDay();
1512     if(((weekDay == 0)?6:weekDay - 1) != firstDayInWeek){
1513         var dayOfMonth = (firstDayInWeek >= 0)?(firstDayInWeek):6;
1514         if(weekDay <= dayOfMonth){
1515             var nextMonthCount = dayOfMonth - weekDay;
1516         }
1517         else{
1518             var nextMonthCount = dayOfMonth + 7 - weekDay;
1519         }
1520         for(var n = 1; n < nextMonthCount + 2; n++){
1521             var dateString = "";
1522             if(this.month == 11){
1523                 dateString = this._getDateString(this.year + 1,1, n);
1524             }else{
1525                 dateString = this._getDateString(this.year, this.month + 2, n);
1526             }
1527             str += "<td class='bodypanel-othermonthday' date='"
1528                 + dateString + "'>" + n + "</td>";
1529         }
1530     }
1531     str += "</tr>";
1532     return str;
1533 };
1534 
1535 /**
1536  * Get the number of dates by month.
1537  * @param {Number} month The month.
1538  * @return The number of dates.
1539  */
1540 JSCalender.PopCalender.prototype._getMonthDate = function(month){
1541     if(month == 1){
1542         return (0==this.year%4 && (this.year%100!=0 || this.year%400==0)) ? 29 : 28;
1543     }
1544     else{
1545         return this.monthDate[month];
1546     }
1547 };
1548 
1549 /**
1550  * Get the index of year's week by date.
1551  * @param {Date} date The date.
1552  * @return The index of week.
1553  */
1554 JSCalender.PopCalender.prototype._getYearWeek = function(date){
1555     var fistDay = new Date(this.year, 0, 1);
1556     var d = Math.round((date.valueOf() - fistDay.valueOf()) / 86400000);
1557     var weekDay = fistDay.getDay() - 1 - this.firstDayInWeek;
1558     if(weekDay < 0){
1559         weekDay = weekDay + 7;
1560     }
1561     var value;
1562     if(d==0){
1563         value = 1;
1564     }
1565     else{
1566         value = (d + weekDay)/7 + 1;
1567     }
1568     return parseInt(value, 10);
1569 };
1570 
1571 /**
1572  * Create calendar's bottom panel.
1573  * @private
1574  * @returns {String} Create bottom panel of calendar.
1575  */
1576 JSCalender.PopCalender.prototype._createCalendarBottom = function(){
1577     return "<div class='bottompanel'><div class='bottomleft'> </div><div class='bottomright'> </div></div>";
1578 };
1579 
1580 /**
1581  * Create month combobox.
1582  * @private
1583  * @returns {String} Create month combobox of calendar.
1584  */
1585 JSCalender.PopCalender.prototype._createMonthCombobox = function(){
1586     var months = this.resource.monthArray;
1587     var str = "";
1588     for(var i = 0; i < 12; i++){
1589         str += "<div value='" + i + "'";
1590         if(i == this.month){
1591             str += " class='monthcombobox-thismonth'";
1592         }
1593         str += ">";
1594         str += months[i];
1595         str += "</div>";
1596     }
1597     return str;
1598 };
1599 
1600 /**
1601  * Create year combobox.
1602  * @private
1603  * @returns {String} Create year combobox of calendar.
1604  */
1605 JSCalender.PopCalender.prototype._createYearCombobox = function(year){
1606     var thisYear = this.year;
1607     if(typeof year == "undefined"){
1608         year = thisYear;
1609     }
1610     var str = "<div class='plus'>-</div>";
1611     for(var i = year - 5; i < year + 6; i++){
1612         str += "<div value='" + i + "'";
1613         if(i == thisYear){
1614             str += " class='yearcombobox-thisyear'";
1615         }
1616         str += ">" + i + "</div>";
1617     }
1618     str += "<div class='plus'>+</div>";
1619     return str;
1620 };
1621 
1622 /**
1623  * Add event to calendar.
1624  * @private
1625  */
1626 JSCalender.PopCalender.prototype._addCalendarEvent = function(){
1627     var othis = this;
1628     var preYear = document.getElementById(this.calendarContainerId + "-preYear");
1629     preYear.onclick = function(){
1630         othis._preYear(false);
1631     };
1632     var nextYear = document.getElementById(this.calendarContainerId + "-nextYear");
1633     nextYear.onclick = function(){
1634         othis._nextYear(false);
1635     };
1636     var preMonth = document.getElementById(this.calendarContainerId + "-preMonth");
1637     preMonth.onclick = function(){
1638         othis._preMonth(false);
1639     };
1640     var nextMonth = document.getElementById(this.calendarContainerId + "-nextMonth");
1641     nextMonth.onclick = function(){
1642         othis._nextMonth(false);
1643     };
1644 
1645     var thisMonth = document.getElementById(this.calendarContainerId + "-thisMonth");
1646     thisMonth.onclick = function(){
1647         var monthCombobox = document.getElementById(othis.calendarContainerId + "-monthCombobox");
1648         monthCombobox.innerHTML = othis._createMonthCombobox();
1649         othis._addMonthComboboxEvent();
1650         monthCombobox.style.display = "block";
1651         var thisMonth = document.getElementById(othis.calendarContainerId + "-thisMonth");
1652         monthCombobox.style.left = thisMonth.offsetLeft + "px";
1653         monthCombobox.style.top = thisMonth.offsetHeight + (othis.Browser.IE?5:4) + "px";
1654         monthCombobox.style.width = thisMonth.offsetWidth + 15 + "px";
1655     };
1656 
1657     var thisYear = document.getElementById(this.calendarContainerId + "-thisYear");
1658     thisYear.onclick = function(){
1659         var yearCombobox = document.getElementById(othis.calendarContainerId + "-yearCombobox");
1660         yearCombobox.innerHTML = othis._createYearCombobox();
1661         othis._addYearComboboxEvent();
1662         yearCombobox.style.display = "block";
1663         var thisYear = document.getElementById(othis.calendarContainerId + "-thisYear");
1664         yearCombobox.style.left = thisYear.offsetLeft + "px";
1665         yearCombobox.style.top = thisYear.offsetHeight + (othis.Browser.IE?5:4) + "px";
1666         yearCombobox.style.width = thisYear.offsetWidth-2 + "px";
1667     };
1668 
1669     var rows = document.getElementById(this.calendarContainerId + "-bodypanel").childNodes[0].rows;
1670     for(var i = 1; i < rows.length; i++){
1671         var row = rows[i];
1672         row.onmouseover = function(){
1673             othis._addClass(this, "bodypanel-daterow-hover");
1674         };
1675         row.onmouseout = function(){
1676             othis._removeClass(this, "bodypanel-daterow-hover");
1677         };
1678         var cells = rows[i].cells;
1679         for(var j = 1; j < cells.length; j++){
1680             var date = cells[j];
1681             var dateValue = date.getAttribute("date");
1682             if(dateValue == this.selectedDateValue){
1683                 this._addClass(date, "bodypanel-date-select");
1684                 othis.selectedDate = date;
1685             }
1686             date.onclick = function(){
1687                 if(othis.selectedDate){
1688                     othis._removeClass(othis.selectedDate, "bodypanel-date-select");
1689                 }
1690                 othis._addClass(this, "bodypanel-date-select");
1691                 othis.selectedDate = this;
1692                 othis.selectedDateValue = this.getAttribute("date");
1693                 var month = parseInt(othis.selectedDateValue.split('-')[1],10);
1694                 var thisMonth = othis.month + 1;
1695                 if(thisMonth == 1 && month == 12){
1696                     othis._preMonth();
1697                 }
1698                 else if(thisMonth == 12 && month == 1){
1699                     othis._nextMonth();
1700                 }
1701                 else if(thisMonth > month){
1702                     othis._preMonth();
1703                 }
1704                 else if(thisMonth < month){
1705                     othis._nextMonth();
1706                 }
1707                 othis._print(othis.selectedDateValue);
1708                 othis._checkSlidePanel(othis.selectedDateValue);
1709             };
1710             date.ondblclick = function(){
1711                 this.onclick();
1712                 othis._hide();
1713             };
1714             date.onmouseover = function(){
1715                 othis._addClass(this, "bodypanel-date-hover");
1716             };
1717             date.onmouseout = function(){
1718                 othis._removeClass(this, "bodypanel-date-hover");
1719             };
1720         }
1721     }
1722 };
1723 
1724 /**
1725  * Add event to window.document.
1726  * @private
1727  */
1728 JSCalender.PopCalender.prototype._addDocumentEvent = function(){
1729     if(document.addEventListener){
1730         document.addEventListener("keypress",this._keyEvent,false);
1731         document.addEventListener("mousedown",this._clickCheck,false);
1732     }
1733     else{
1734         document.attachEvent("onkeydown",this._keyEvent);
1735         document.attachEvent("onmousedown",this._clickCheck);
1736     }
1737 };
1738 
1739 /**
1740  * Hide calendar or combobox when clicked
1741  * @private
1742  */
1743 JSCalender.PopCalender.prototype._clickCheck = function(event){
1744     var calendar = document.popCalendar;
1745     if (!calendar) {
1746         return;
1747     }
1748     event = window.event || event;
1749     var element = event.srcElement || event.target;
1750     var calendarDom = document.getElementById(calendar.calendarContainerId);
1751     var monthCombobox = document.getElementById(calendar.calendarContainerId + "-monthCombobox");
1752     var yearCombobox = document.getElementById(calendar.calendarContainerId + "-yearCombobox");
1753     for (; element != null && element != calendarDom; element = element.parentNode);
1754     if (element == null) {
1755         monthCombobox.style.display = "none";
1756         yearCombobox.style.display = "none";
1757         calendar._hide();
1758         return;
1759     }
1760     element = event.srcElement || event.target;
1761     for (; element != null && element != monthCombobox; element = element.parentNode);
1762     if (element == null) {
1763         monthCombobox.style.display = "none";
1764     }
1765     element = event.srcElement || event.target;
1766     for (; element != null && element != yearCombobox; element = element.parentNode);
1767     if (element == null) {
1768         yearCombobox.style.display = "none";
1769     }
1770 };
1771 
1772 /**
1773  * Check data to decide that whether show the slide panel
1774  * @param {String} date The date.
1775  * @private
1776  */
1777 JSCalender.PopCalender.prototype._checkSlidePanel = function(date){
1778     var dateInfo = this.config.dates[date];
1779     var defaultInfo = this.config.dates["default"];
1780     var slidePanelContainer = document.getElementById(this.calendarContainerId + "-slidePanel").parentNode.parentNode;
1781     if(dateInfo){
1782     	this._showSlidePanel(dateInfo.image, dateInfo.text, date);
1783     	slidePanelContainer.style.display = "";
1784     }
1785     else if(defaultInfo){
1786     	this._showSlidePanel(defaultInfo.image, defaultInfo.text, date);
1787     	slidePanelContainer.style.display = "";
1788     }
1789     else{
1790     	slidePanelContainer.style.display = "none";	
1791     }
1792 };
1793 
1794 /**
1795  * Process key event when press keyboard
1796  * @param {Object} event The event which comes from pressing keyboard.
1797  * @private
1798  */
1799 JSCalender.PopCalender.prototype._keyEvent = function(event){
1800     var othis = document.popCalendar;
1801     var KEY = {
1802         LEFT  : 37,
1803         UP    : 38,
1804         RIGHT : 39,
1805         DOWN  : 40,
1806         ESC   : 27,
1807         ENTER : 13,
1808         SPACE : 32
1809     };
1810     var code = event.keyCode || event.charCode;
1811     if(event.ctrlKey){
1812         switch(code)
1813         {
1814             case KEY.LEFT:
1815                 othis._preMonth();
1816                 break;
1817             case KEY.RIGHT:
1818                 othis._nextMonth();
1819                 break;
1820             case KEY.UP:
1821                 othis._preYear();
1822                 break;
1823             case KEY.DOWN:
1824                 othis._nextYear();
1825                 break;
1826             default:
1827                 break;
1828         }
1829     }
1830     else{
1831         switch(code){
1832             case KEY.LEFT:
1833                 othis._parseDate(1);
1834                 break;
1835             case KEY.RIGHT:
1836                 othis._parseDate(-1);
1837                 break;
1838             case KEY.UP:
1839                 othis._parseDate(7);
1840                 break;
1841             case KEY.DOWN:
1842                 othis._parseDate(-7);
1843                 break;
1844             case KEY.ESC:
1845                 othis._hide();
1846                 break;
1847             case KEY.ENTER:
1848                 othis._print(othis.selectedDateValue);
1849                 othis._hide();
1850                 break;
1851             case KEY.SPACE:
1852                 othis.selectedDateValue = othis._getDateString(othis.thisDay.getFullYear(),othis.thisDay.getMonth()+1,othis.thisDay.getDate());
1853                 othis.year = othis.thisDay.getFullYear();
1854                 othis.month = othis.thisDay.getMonth();
1855                 document.getElementById(othis.calendarContainerId + "-thisYear").innerHTML = othis.year;
1856                 document.getElementById(othis.calendarContainerId + "-thisMonth").innerHTML = othis.resource.monthArray[othis.month];
1857                 othis._freshDaysPanel();
1858                 othis._print(othis.selectedDateValue);
1859                 break;
1860             default: 
1861                 break;
1862         }
1863     }
1864     othis._checkSlidePanel(othis.selectedDateValue);
1865     if(othis.Browser.IE){
1866         return false;
1867     }
1868     else{
1869         event.preventDefault();
1870     }
1871 };
1872 
1873 /**
1874  * Get last year's calendar
1875  * @private
1876  */
1877 JSCalender.PopCalender.prototype._preYear = function(){
1878     this.year--;
1879     this._freshDaysPanel();
1880     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
1881 };
1882 
1883 /**
1884  * Get next year's calendar
1885  * @private
1886  */
1887 JSCalender.PopCalender.prototype._nextYear = function(){
1888     this.year++;
1889     this._freshDaysPanel();
1890     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
1891 };
1892 
1893 /**
1894  * Get last month's calendar
1895  * @private
1896  */
1897 JSCalender.PopCalender.prototype._preMonth = function(){
1898     if(this.month == 0){
1899         this.month = 11;
1900         this.year--;
1901         document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
1902     }
1903     else{
1904         this.month--;
1905     }
1906     this._freshDaysPanel();
1907     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
1908 };
1909 
1910 /**
1911  * Get next month's calendar
1912  * @private
1913  */
1914 JSCalender.PopCalender.prototype._nextMonth = function(){
1915     if(this.month == 11){
1916         this.month = 0;
1917         this.year++;
1918         document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
1919     }
1920     else{
1921         this.month++;
1922     }
1923     this._freshDaysPanel();
1924     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
1925 };
1926 
1927 /**
1928  * Fresh calendar when press keyboard
1929  * @param {Number} step The diff which compares with the selected date.
1930  * @private
1931  */
1932 JSCalender.PopCalender.prototype._parseDate = function(step){
1933     if(this.selectedDateValue){
1934         var arr = this.selectedDateValue.split('-');
1935         var date = new Date(new Date(arr[0],arr[1]-1,arr[2]) - 24*60*60*1000*step);
1936     }
1937     else{
1938         var date = new Date(this.thisDay - 24*60*60*1000*step);
1939     }
1940     this.year = date.getFullYear();
1941     this.month = date.getMonth();
1942     this.date = date.getDate();
1943     this.selectedDateValue = this._getDateString(this.year,this.month + 1,this.date);
1944     this._freshDaysPanel();
1945     document.getElementById(this.calendarContainerId + "-thisYear").innerHTML = this.year;
1946     document.getElementById(this.calendarContainerId + "-thisMonth").innerHTML = this.resource.monthArray[this.month];
1947 };
1948 
1949 /**
1950  * Convert Date to string
1951  * @param {Number} year The year.
1952  * @param {Number} month The month.
1953  * @param {Date} date The date.
1954  * @private
1955  */
1956 JSCalender.PopCalender.prototype._getDateString = function(year,month,date){
1957     return year + "-" + ((month < 10)?("0" + (month)):month) + "-" + ((date < 10)?("0" + (date)):date);
1958 };
1959 
1960 
1961 /**
1962  * Fresh calendar
1963  * @private
1964  */
1965 JSCalender.PopCalender.prototype._freshDaysPanel = function(){
1966     var str = "<table cellspacing='0' cellpadding='0' class='bodypanel'>"
1967             + this._createCalendarDays() + this._createCalendarDates()
1968             + "</table>";
1969     document.getElementById(this.calendarContainerId + "-bodypanel").innerHTML = str;
1970     this._addCalendarEvent();
1971     document.getElementById(this.calendarContainerId).focus();
1972 };
1973 
1974 /**
1975  * Show slide panel
1976  * @private
1977  */
1978 JSCalender.PopCalender.prototype._showSlidePanel = function(img, text, dateString){
1979 	var slidePanel = document.getElementById(this.calendarContainerId + "-slidePanel");
1980 	var imageContainer = slidePanel.rows[0].cells[0];
1981 	var topTextContainer = slidePanel.rows[0].cells[1];
1982 	var bottomTextContainer = slidePanel.rows[1].cells[0];
1983 	if(img){
1984 		imageContainer.style.display = "";
1985 		imageContainer.innerHTML = "<img class='slidepanel-img' alt='" 
1986 							     + dateString + "' src='" + img + "'/>";
1987 	}
1988 	else{
1989 		imageContainer.style.display = "none";
1990 	}
1991 	if(text){
1992 		var textArr = text.split('\n');
1993 		
1994 		if(textArr.length < 2){
1995 			topTextContainer.style.display = "";
1996 			bottomTextContainer.style.display = "none";
1997 			topTextContainer.innerHTML = textArr[0];
1998 		}
1999 		else{
2000 			topTextContainer.style.display = "";
2001 			bottomTextContainer.style.display = "";
2002 			topTextContainer.innerHTML = textArr[0];
2003 			textArr[0] = "";
2004 			bottomTextContainer.innerHTML = textArr.join(" ");
2005 		}
2006 	}
2007 	else{
2008 		topTextContainer.style.display = "none";
2009 		bottomTextContainer.style.display = "none";
2010 	}
2011 };
2012 
2013 /**
2014  * Add event to month combobox
2015  * @private
2016  */
2017 JSCalender.PopCalender.prototype._addMonthComboboxEvent = function(){
2018     var othis = this;
2019     var monthCombobox = document.getElementById(this.calendarContainerId + "-monthCombobox");
2020     for(var i = 0, len = monthCombobox.childNodes.length; i < len; i++){
2021         var row = monthCombobox.childNodes[i];
2022         row.onclick = function(){
2023             document.getElementById(othis.calendarContainerId + "-thisMonth").innerHTML = this.innerHTML;
2024             monthCombobox.style.display = "none";
2025             othis.month = parseInt(this.getAttribute("value"),10);
2026             othis._freshDaysPanel();
2027         };
2028         row.onmouseover = function(){
2029             othis._addClass(this, "monthcombobox-hover");
2030         };
2031         row.onmouseout = function(){
2032             othis._removeClass(this, "monthcombobox-hover");
2033         };
2034     }
2035 };
2036 
2037 /**
2038  * Add event to year combobox
2039  * @private
2040  */
2041 JSCalender.PopCalender.prototype._addYearComboboxEvent = function(){	
2042     var othis = this;
2043     var yearCombobox = document.getElementById(this.calendarContainerId + "-yearCombobox");
2044 
2045     for(var i = 0, len = yearCombobox.childNodes.length; i < len; i++){
2046         var row = yearCombobox.childNodes[i];
2047         if(i == 0){
2048             row.onclick = function(){
2049                 var yearCombobox = document.getElementById(othis.calendarContainerId + "-yearCombobox");
2050                 yearCombobox.innerHTML = othis._createYearCombobox(parseInt(yearCombobox.childNodes[5].innerHTML,10));
2051                 othis._addYearComboboxEvent();
2052             };
2053         }
2054         else if(i == len - 1){
2055             row.onclick = function(){
2056                 var yearCombobox = document.getElementById(othis.calendarContainerId + "-yearCombobox");
2057                 yearCombobox.innerHTML = othis._createYearCombobox(parseInt(yearCombobox.childNodes[5].innerHTML,10) + 2);
2058                 othis._addYearComboboxEvent();
2059             };
2060         }
2061         else{
2062             row.onclick = function(){
2063                 document.getElementById(othis.calendarContainerId + "-thisYear").innerHTML = this.innerHTML;
2064                 yearCombobox.style.display = "none";
2065                 othis.year = parseInt(this.getAttribute("value"),10);
2066                 othis._freshDaysPanel();
2067             };
2068         }
2069         row.onmouseover = function(){
2070             othis._addClass(this, "yearcombobox-hover");
2071         };
2072         row.onmouseout = function(){
2073             othis._removeClass(this, "yearcombobox-hover");
2074         };
2075     }
2076 };
2077 
2078 /**
2079  * Get left and top of element
2080  * @param {Object} el The element which will be get left and top.
2081  * @private
2082  */
2083 JSCalender.PopCalender.prototype._getPosition = function(el){
2084     var positionElement = el;
2085     var positionElementHeight = positionElement.offsetHeight;
2086     var positionElementWidth = positionElement.offsetWidth;
2087 
2088     var defaultTop = positionElement.offsetTop + positionElement.offsetHeight;
2089     var defaultLeft = positionElement.offsetLeft;
2090     while((positionElement = positionElement.offsetParent) != null){
2091         defaultTop += positionElement.offsetTop;
2092         defaultLeft += positionElement.offsetLeft;
2093     }
2094     return {top:defaultTop, left:defaultLeft};
2095 };
2096 
2097 /**
2098  * Add css class to element.
2099  * @param {Object} el The element where adds class.
2100  * @param {String} className The css class which to be added..
2101  * @private
2102  */
2103 JSCalender.PopCalender.prototype._addClass = function(el, className) {
2104     this._removeClass(el, className);
2105     el.className += " " + className;
2106 };
2107 
2108 /**
2109  * Remove css class of element.
2110  * @param {Object} el The element where removes class.
2111  * @param {String} className The css class which to be removed..
2112  * @private
2113  */
2114 JSCalender.PopCalender.prototype._removeClass = function(el, className) {
2115     if (!(el && el.className)) {
2116         return;
2117     }
2118     var cssArr = el.className.split(" ");
2119     var newArr = new Array();
2120     for (var i = 0, len = cssArr.length; i< len; i++){
2121         if (cssArr[i] != className) {
2122             newArr[newArr.length] = cssArr[i];
2123         }
2124     }
2125     el.className = newArr.join(" ");
2126 };
2127 
2128 /**
2129  * Remove evnent of window.document
2130  * @private
2131  */
2132 JSCalender.PopCalender.prototype._removeEvent = function() {
2133     if(document.removeEventListener){
2134         document.removeEventListener("keypress",this._keyEvent,false);
2135         document.removeEventListener("mousedown",this._clickCheck,false);
2136     }
2137     else{
2138         document.detachEvent("onkeydown",this._keyEvent);
2139         document.detachEvent("onmousedown",this._clickCheck);
2140     }
2141 };
2142 
2143 /**
2144  * Show calendar
2145  * @private
2146  */
2147 JSCalender.PopCalender.prototype._show = function() {
2148     this._addDocumentEvent();
2149     var calendar = document.getElementById(this.calendarContainerId);
2150     if(calendar){
2151         calendar.style.display = "";
2152     }
2153     var iframeShim = document.getElementById(this.calendarContainerId + "-iframeshim");
2154     if(iframeShim){
2155         iframeShim.style.display = "";
2156     }
2157 };
2158 
2159 /**
2160  * Hide calendar
2161  * @private
2162  */
2163 JSCalender.PopCalender.prototype._hide = function() {
2164     this._removeEvent();
2165     var calendar = document.getElementById(this.calendarContainerId);
2166     if(calendar){
2167         calendar.style.display = "none";
2168     }
2169     var iframeShim = document.getElementById(this.calendarContainerId + "-iframeshim");
2170     if(iframeShim){
2171         iframeShim.style.display = "none";
2172     }
2173 };
2174 
2175 /**
2176  * Remove calendar
2177  * @private
2178  */
2179 JSCalender.PopCalender.prototype._remove = function() {
2180     this._removeEvent();
2181     var calendarDom = document.getElementById(document.popCalendar.calendarContainerId);
2182     calendarDom.parentNode.removeChild(calendarDom);
2183     document.popCalendar = null;
2184 };
2185 
2186 /**
2187  * Output the selected date
2188  * @param {String} dateString The format of outputed date
2189  * @private
2190  */
2191 JSCalender.PopCalender.prototype._print = function(dateString) {
2192 	if(!dateString){
2193 		return;
2194 	}
2195     var arr = dateString.split('-');
2196     var printFormat = (this.config.printFormat || "").toLowerCase();
2197     printFormat = printFormat.replace("yyyy", arr[0]);
2198     printFormat = printFormat.replace("yy", arr[0].substr(2));
2199     printFormat = printFormat.replace("mm", arr[1]);
2200     printFormat = printFormat.replace("dd", arr[2]);
2201     var targetElement = document.getElementById(this.targetId);
2202     if(targetElement){
2203         targetElement.value = printFormat;
2204     }
2205 };
2206 
2207 /**
2208  * Set the config of calendar
2209  * @param {String} config The config which to be set
2210  * @public
2211  */
2212 JSCalender.PopCalender.prototype.setConfig = function(config) {
2213 	this.config = config;
2214 };
2215 
2216 /**
2217  * Set the language of calendar
2218  * @param {String} lang The language which to be set
2219  * @public
2220  */
2221 JSCalender.PopCalender.prototype.setLanguage = function(lang) {
2222 	this.resource = Calender_Resources[lang.toLowerCase()]|| Calender_Resources["en"];
2223 };
2224 
2225 /**
2226  * Set the css of calendar
2227  * @param {String} css The css which to be set
2228  * @public
2229  */
2230 JSCalender.PopCalender.prototype.setCss = function(css) {
2231 	this.config.css = css;
2232 };
2233 
2234 /**
2235  * Set the first day in week
2236  * @param {Number} day The day which to be set
2237  * @public
2238  */
2239 JSCalender.PopCalender.prototype.setFirstDayInWeek = function(day) {
2240 	this.firstDayInWeek = day;
2241 };
2242 
2243 /**
2244  * Set the export format
2245  * @param {String} printFormat The print format which to be set
2246  * @public
2247  */
2248 JSCalender.PopCalender.prototype.setPrintFarmat = function(printFormat) {
2249 	this.config.printFormat = printFormat;
2250 };
2251 
2252 /**
2253  * Set the export format
2254  * @param {String} date The date which to be set
2255  * @param {String} image The image which to be show in slide panel
2256  * @param {String} text The text which to be show in slide panel
2257  * @public
2258  */
2259 JSCalender.PopCalender.prototype.setSlideDate = function(date, image, text) {
2260 	this.config.dates[date] = {};
2261 	this.config.dates[date].text = text;
2262 	this.config.dates[date].image = image;
2263 };
2264