root/afridex/plugins/Flutter/js/epoch_classes.js @ 21

Revision 21, 40.7 kB (checked in by admin, 18 years ago)
RevLine 
[21]1/*!!
2Epoch DHTML JavaScript Calendar - Version 2.0.2
3English Edition
4Primary JavaScript File
5(c) 2006-2007 MeanFreePath
6Free for NON-COMMERCIAL use - see website for details and updates
7http://www.meanfreepath.com/javascript_calendar/index.html
8!!*/
9
10/**
11* The main Epoch class.  All publicly-accessible methods and properties are called from this class
12*/
13function Epoch(name,mode,targetelement,multiselect, m_afterHide, m_afterHideParam, m_dateformat) {
14        var self = this; //workaround due to varying definitions of "this" in variable scopes. see http://www.meanfreepath.com/support/epoch/epoch.html#self for details
15        //DEFINE PRIVATE METHODS
16        //-----------------------------------------------------------------------------
17        /**
18        * Declares and initializes the calendar variables.  All the variables here can be safely changed
19        * (within reason ;) by the developer
20        */
21        function calConfig() {
22                self.versionNumber = '2.0.2';
23                self.displayYearInitial = self.curDate.getFullYear(); //the initial year to display on load
24                self.displayMonthInitial = self.curDate.getMonth(); //the initial month to display on load (0-11)
25                self.displayYear = self.displayYearInitial;
26                self.displayMonth = self.displayMonthInitial;
27
28                var d = new Date();
29                var curr_year = d.getFullYear();
30                self.minDate = new Date(curr_year-5,0,1);
31//              self.maxDate = new Date(2012,11,31);
32                self.maxDate = new Date(parseInt(curr_year)+parseInt(10),11,31);
33
34                self.startDay = 0; // the day the week will 'start' on: 0(Sun) to 6(Sat)
35                self.showWeeks = true; //whether the week numbers will be shown
36                self.selCurMonthOnly = true; //allow user to only select dates in the currently displayed month
37        }
38        //-----------------------------------------------------------------------------
39        /**
40        * All language settings for Epoch are made here.
41        * Check Date.dateFormat() for the Date object's language settings
42        */
43        function setLang() {
44                self.daylist = new Array('S','M','T','W','T','F','S','S','M','T','W','T','F','S');
45                self.months_sh = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
46                self.monthup_title = 'Go to the next month';
47                self.monthdn_title = 'Go to the previous month';
48                self.clearbtn_caption = 'Clear';
49                self.clearbtn_title = 'Clears any dates selected on the calendar';
50                self.maxrange_caption = 'This is the maximum range';
51                self.closebtn_caption = 'Close';
52                self.closebtn_title = 'Close the calendar';
53        }
54        //-----------------------------------------------------------------------------
55        /**
56        * Initializes the standard Gregorian Calendar parameters
57        */
58        function setDays() {
59                self.daynames = new Array();
60                var j=0;
61                for(var i=self.startDay;i<self.startDay + 7;i++) {
62                        self.daynames[j++] = self.daylist[i];
63                }
64                self.monthDayCount = new Array(31,((self.curDate.getFullYear() - 2000) % 4 ? 28 : 29),31,30,31,30,31,31,30,31,30,31);
65        }
66        //-----------------------------------------------------------------------------
67        /**
68        * Creates the full DOM implementation of the calendar
69        */
70        function createCalendar() {
71                var tbody, tr, td;
72                self.calendar = document.createElement('table');
73                self.calendar.setAttribute('id',self.name+'_calendar');
74                setClass(self.calendar,'calendar');
75                self.calendar.style.display = 'none'; //default to invisible
76                //to prevent IE from selecting text when clicking on the calendar
77                addEventHandler(self.calendar,'selectstart', function() {return false;});
78                addEventHandler(self.calendar,'drag', function() {return false;});
79                tbody = document.createElement('tbody');
80
81                //create the Main Calendar Heading
82                tr = document.createElement('tr');
83                td = document.createElement('td');
84                td.appendChild(createMainHeading());
85                tr.appendChild(td);
86                tbody.appendChild(tr);
87
88                //create the calendar Day Heading & the calendar Day Cells
89                tr = document.createElement('tr');
90                td = document.createElement('td');
91                self.calendar.celltable = document.createElement('table');
92                setClass(self.calendar.celltable,'cells');
93                self.calendar.celltable.appendChild(createDayHeading());
94                self.calendar.celltable.appendChild(createCalCells());
95                td.appendChild(self.calendar.celltable);
96                tr.appendChild(td);
97                tbody.appendChild(tr);
98
99                //create the calendar footer
100                tr = document.createElement('tr');
101                td = document.createElement('td');
102                td.appendChild(createFooter());
103                tr.appendChild(td);
104                tbody.appendChild(tr);
105
106                //add the tbody element to the main calendar table
107                self.calendar.appendChild(tbody);
108
109                //and add the onmouseover events to the calendar table
110                addEventHandler(self.calendar,'mouseover',cal_onmouseover);
111                addEventHandler(self.calendar,'mouseout',cal_onmouseout);
112        }
113        //-----------------------------------------------------------------------------
114        /**
115        * Creates the primary calendar heading, with months & years
116        */
117        function createMainHeading() {
118                //create the containing <div> element
119                var container = document.createElement('div');
120                setClass(container,'mainheading');
121                //create the child elements and other variables
122                self.monthSelect = document.createElement('select');
123                self.yearSelect = document.createElement('select');
124                var monthDn = document.createElement('input'), monthUp = document.createElement('input');
125                var opt, i;
126                //fill the month select box
127                for(i=0;i<12;i++) {
128                        opt = document.createElement('option');
129                        opt.setAttribute('value',i);
130                        if(self.displayMonth == i) {
131                                opt.setAttribute('selected','selected');
132                        }
133                        opt.appendChild(document.createTextNode(self.months_sh[i]));
134                        self.monthSelect.appendChild(opt);
135                }
136                //and fill the year select box
137                var yrMax = self.maxDate.getFullYear(), yrMin = self.minDate.getFullYear();
138                for(i=yrMin;i<=yrMax;i++) {
139                        opt = document.createElement('option');
140                        opt.setAttribute('value',i);
141                        if(self.displayYear == i) {
142                                opt.setAttribute('selected','selected');
143                        }
144                        opt.appendChild(document.createTextNode(i));
145                        self.yearSelect.appendChild(opt);
146                }
147                //add the appropriate children for the month buttons
148                monthUp.setAttribute('type','button');
149                monthUp.setAttribute('value','>');
150                monthUp.setAttribute('title',self.monthup_title);
151                monthDn.setAttribute('type','button');
152                monthDn.setAttribute('value','<');
153                monthDn.setAttribute('title',self.monthdn_title);
154                self.monthSelect.owner = self.yearSelect.owner = monthUp.owner = monthDn.owner = self;  //hack to allow us to access self calendar in the events (<fix>??)
155
156                //assign the event handlers for the controls
157                function selectonchange()       {
158                        if(self.goToMonth(self.yearSelect.value,self.monthSelect.value)) {
159                                self.displayMonth = self.monthSelect.value;
160                                self.displayYear = self.yearSelect.value;
161                        }
162                        else {
163                                self.monthSelect.value = self.displayMonth;
164                                self.yearSelect.value = self.displayYear;
165                        }
166                }
167                addEventHandler(monthUp,'click',function(){self.nextMonth();});
168                addEventHandler(monthDn,'click',function(){self.prevMonth();});
169                addEventHandler(self.monthSelect,'change',selectonchange);
170                addEventHandler(self.yearSelect,'change',selectonchange);
171
172                //and finally add the elements to the containing div
173                container.appendChild(monthDn);
174                container.appendChild(self.monthSelect);
175                container.appendChild(self.yearSelect);
176                container.appendChild(monthUp);
177                return container;
178        }
179        //-----------------------------------------------------------------------------
180        /**
181        * Creates the footer of the calendar - goes under the calendar cells
182        */
183        function createFooter() {
184                var container = document.createElement('div');
185                var clearSelected = document.createElement('input');
186                clearSelected.setAttribute('type','button');
187                clearSelected.setAttribute('value',self.clearbtn_caption);
188                clearSelected.setAttribute('title',self.clearbtn_title);
189                clearSelected.owner = self;
190                addEventHandler(clearSelected,'click',function() {self.resetSelections(false);});
191                container.appendChild(clearSelected);
192                if(self.mode == 'popup') {
193                        var closeBtn = document.createElement('input');
194                        closeBtn.setAttribute('type','button');
195                        closeBtn.setAttribute('value',self.closebtn_caption);
196                        closeBtn.setAttribute('title',self.closebtn_title);
197                        addEventHandler(closeBtn,'click',function(){self.hide();});
198                        setClass(closeBtn,'closeBtn');
199                        container.appendChild(closeBtn);
200                }
201                return container;
202        }
203        //-----------------------------------------------------------------------------
204        /**
205        * Creates the heading containing the day names
206        */
207        function createDayHeading() {
208                //create the table element
209                self.calHeading = document.createElement('thead');
210                setClass(self.calHeading,'caldayheading');
211                var tr = document.createElement('tr'), th;
212                self.cols = new Array(false,false,false,false,false,false,false);
213
214                //if we're showing the week headings, create an empty <td> for filler
215                if(self.showWeeks) {
216                        th = document.createElement('th');
217                        setClass(th,'wkhead');
218                        tr.appendChild(th);
219                }
220                //populate the day titles
221                for(var dow=0;dow<7;dow++) {
222                        th = document.createElement('th');
223                        th.appendChild(document.createTextNode(self.daynames[dow]));
224                        if(self.selectMultiple) { //if selectMultiple is true, assign the cell a CalHeading Object to handle all events
225                                th.headObj = new CalHeading(self,th,(dow + self.startDay < 7 ? dow + self.startDay : dow + self.startDay - 7));
226                        }
227                        tr.appendChild(th);
228                }
229                self.calHeading.appendChild(tr);
230                return self.calHeading;
231        }
232        //-----------------------------------------------------------------------------
233        /**
234        * Creates the table containing the calendar day cells
235        */
236        function createCalCells() {
237                self.rows = new Array(false,false,false,false,false,false);
238                self.cells = new Array();
239                var row = -1, totalCells = (self.showWeeks ? 48 : 42);
240                var beginDate = new Date(self.displayYear,self.displayMonth,1);
241                var endDate = new Date(self.displayYear,self.displayMonth,self.monthDayCount[self.displayMonth]);
242                var sdt = new Date(beginDate);
243                sdt.setDate(sdt.getDate() + (self.startDay - beginDate.getDay()) - (self.startDay - beginDate.getDay() > 0 ? 7 : 0) );
244                //create the table element to hold the cells
245                self.calCells = document.createElement('tbody');
246                var tr,td;
247                var cellIdx = 0, cell, week, dayval;
248
249                for(var i=0;i<totalCells;i++) {
250                        if(self.showWeeks) { //if we are showing the week headings
251                                if(i % 8 == 0) {
252                                        row++;
253                                        week = sdt.getWeek(self.startDay);
254                                        tr = document.createElement('tr');
255                                        td = document.createElement('td');
256                                        if(self.selectMultiple) { //if selectMultiple is enabled, create the associated weekObj objects
257                                                td.weekObj = new WeekHeading(self,td,week,row)
258                                        }
259                                        else {//otherwise just set the class of the td for consistent look
260                                                setClass(td,'wkhead');
261                                        }
262                                        td.appendChild(document.createTextNode(week));
263                                        tr.appendChild(td);
264                                        i++;
265                                }
266                        }
267                        else if(i % 7 == 0) { //otherwise, new row every 7 cells
268                                row++;
269                                week = sdt.getWeek(self.startDay);
270                                tr = document.createElement('tr');
271                        }
272                        //create the day cells
273                        dayval = sdt.getDate();
274                        td = document.createElement('td');
275                        td.appendChild(document.createTextNode(dayval));
276                        cell = new CalCell(self,td,sdt,row,week);//,'normal',sdt.getTime() >= self.minDate.getTime() && sdt.getTime() <= self.maxDate.getTime());
277                        self.cells[cellIdx] = cell;
278                        td.cellObj = cell;
279                        tr.appendChild(td);
280                        self.calCells.appendChild(tr);
281                        self.reDraw(cellIdx++); //and paint the cell according to its properties
282                        sdt.setDate(dayval + 1); //increment the date
283                }
284                return self.calCells;
285        }
286        //-----------------------------------------------------------------------------
287        /**
288        * Runs all the operations necessary to change the mode of the calendar
289        * @param HTMLInputElement targetelement
290        */
291        function setMode(targetelement) {
292                if(self.mode == 'popup') { //set positioning to absolute for popup
293                        self.calendar.style.position = 'absolute';
294                }
295                //if a target element has been set, append the calendar to it
296                if(targetelement) {
297                        switch(self.mode) {
298                                case 'flat':
299                                        self.tgt = targetelement;
300                                        self.tgt.appendChild(self.calendar);
301                                        self.visible = true;
302                                        break;
303                                case 'popup':
304                                        self.calendar.style.position = 'absolute';
305                                        document.body.appendChild(self.calendar);
306                                        self.setTarget(targetelement,false);
307                                        break;
308                        }
309                }
310                else { //otherwise, add the calendar to the document.body (useful if targetelement will not be defined until after the calendar is initialized)
311                        document.body.appendChild(self.calendar);
312                        self.visible = false;
313                }
314        }
315        //-----------------------------------------------------------------------------
316        /**
317        * Removes the calendar table cells from the DOM (does not delete the cell objects associated with them)
318        */
319        function deleteCells() {
320                self.calendar.celltable.removeChild(self.calendar.celltable.childNodes[1]); //remove the tbody element from the cell table
321        }
322        //-----------------------------------------------------------------------------
323        /**
324        * Sets the CSS class of the element, W3C & IE
325        * @param HTMLElement element
326        * @param string className
327        */
328        function setClass(element,className) {
329                element.setAttribute('class',className);
330                element.setAttribute('className',className); //<iehack>
331        }
332        /**
333        * Updates a cell's data, including css class and selection properties
334        * @param int cellindex
335        */
336        function setCellProperties(cellindex) {
337                var cell = self.cells[cellindex];
338                var date;
339                idx = self.dateInArray(self.dates,cell.date);
340                if(idx > -1) {
341                        date = self.dates[idx]; //reduce indirection
342                        cell.date.selected = date.selected || false;
343                        cell.date.type = date.type;
344                        cell.date.canSelect = date.canSelect;
345                        cell.setTitle(date.title);
346                        cell.setURL(date.href);
347                        cell.setHTML(date.cellHTML);
348                }
349                else {
350                        cell.date.selected = false; //if the cell's date isn't in the dates array, set it's selected value to false
351                }
352                //make all cells lying outside the min and max dates un-selectable
353                if(cell.date.getTime() < self.minDate.getTime() || cell.date.getTime() > self.maxDate.getTime()) {
354                        cell.date.canSelect = false;
355                }
356                cell.setClass();
357        }
358        //-----------------------------------------------------------------------------
359        function cal_onmouseover() {
360                self.mousein = true;
361        }
362        //-----------------------------------------------------------------------------
363        function cal_onmouseout()       {
364                self.mousein = false;
365        }
366        //-----------------------------------------------------------------------------
367        /**
368         * Updates the calendar's selectedDates pointer array
369         */
370        function updateSelectedDates() {
371                var idx = 0;
372                self.selectedDates = new Array();
373                for(i=0;i<self.dates.length;i++) {
374                        if(self.dates[i].selected) {
375                                self.selectedDates[idx++] = self.dates[i];
376                        }
377                }
378        }
379        //PUBLIC METHODS
380        //-----------------------------------------------------------------------------
381        /**
382        * Find a date in the given array, returning its index if found, -1 if not
383        * @param array arr
384        * @param Date searchVal
385        * @param int startIndex
386        * @return int
387        */
388        self.dateInArray = function(arr,searchVal,startIndex) {
389                startIndex = (startIndex != null ? startIndex : 0); //default startIndex to 0, if not set
390                for(var i=startIndex;i<arr.length;i++) {
391                        if(searchVal.getUeDay() == arr[i].getUeDay()) {
392                                return i;
393                        }
394                }
395                return -1;
396        };
397        //-----------------------------------------------------------------------------
398        /**
399        * Changes the target element of this calendar to another input.
400        * Many thanks to Jake Olefsky - jake@olefsky.com
401        * @param HTMLInputElement targetelement
402        * @param bool focus
403        */
404        self.setTarget = function (targetelement, focus)
405        {
406                //if this is a popup calendar
407                if(self.mode == 'popup') {
408                        //declare the event handlers for the target element
409                        function popupFocus() {
410                                self.show();
411                        }
412                        function popupBlur() {
413                                if(!self.mousein){
414                                        self.hide();
415                                }
416                        }
417                        function popupKeyDown() {
418                                self.hide();
419                        }
420                        //unset old target element event handlers (if there is one yet)
421                        if(self.tgt) {
422                                removeEventHandler(self.tgt,'focus',popupFocus);
423                                removeEventHandler(self.tgt,'blur',popupBlur);
424                                removeEventHandler(self.tgt,'keydown',popupKeyDown);
425                        }
426                        //and set the new target element
427                        self.tgt = targetelement;
428                        //create a pointer to the INPUT's date object and init the new data array
429                        var dto = self.tgt.dateObj,pdateArr = new Array;
430                        //if a date is set for the target element
431                        if(dto) {
432                                if(self.tgt.value.length) { //load it into the calendar...
433                                        pdateArr[0] = dto;
434                                }
435                                self.goToMonth(dto.getFullYear(),dto.getMonth()); //...and go to the target's month/year
436                        }
437                        self.selectDates(pdateArr,true,true,true);
438
439                        self.topOffset = self.tgt.offsetHeight; // the vertical distance (in pixels) to display the calendar from the Top of its input element
440                        self.leftOffset = 0;                                    // the horizontal distance (in pixels) to display the calendar from the Left of its input element
441                        self.updatePos(self.tgt);
442                        //and add the event handlers to the new element
443                        addEventHandler(self.tgt,'focus',popupFocus);
444                        addEventHandler(self.tgt,'blur',popupBlur);
445                        addEventHandler(self.tgt,'keydown',popupKeyDown);
446                        if(focus !== false) { //focus the target element immediately, unless otherwise specified
447                                popupFocus();
448                        }
449                }
450                else { //if this is a flat or inline calendar
451                        //if the target is already set, remove the calendar's DOM representation from it
452                        if(self.tgt) {
453                                self.tgt.removeChild(self.calendar);
454                        }
455                        //now, set the calendar's target to the new target element, and show the calendar
456                        self.tgt = targetelement;
457                        self.tgt.appendChild(self.calendar);
458                        self.show();
459                }
460        };
461        //-----------------------------------------------------------------------------
462        /**
463        * Go to the next month.  if the month is December, go to January of the next year
464        * Returns true if the month will be incremented
465        * @return bool
466        */
467        self.nextMonth = function () {
468                var month = self.displayMonth;
469                var year = self.displayYear;
470                //increment the month/year values, provided they're within the min/max ranges
471                if(self.displayMonth < 11) { //i.e. if currently in the year
472                        month++;
473                }
474                else if(self.yearSelect.value < self.maxDate.getFullYear()) { //if not, increment the year as well
475                        month = 0;
476                        year++;
477                }
478                return self.goToMonth(year,month);
479        };
480        //-----------------------------------------------------------------------------
481        /**
482        * Go to the previous month - if the month is January, go to December of the previous year.
483        * Returns true if the month will be decremented
484        * @return bool
485        */
486        self.prevMonth = function () {
487                var month = self.displayMonth;
488                var year = self.displayYear;
489                //increment the month/year values, provided they're within the min/max ranges
490                if(self.displayMonth > 0) { //i.e. if currently in the year
491                        month--;
492                }
493                else { //if not, decrement the year as well
494                        month = 11;
495                        year--;
496                }
497                return self.goToMonth(year,month);
498        };
499        //-----------------------------------------------------------------------------
500        /**
501        * Sets the calendar to display the requested month/year, returning true if the
502        * date is within the minimum and maximum allowed dates
503        * @param int year
504        * @param int month
505        * @return bool
506        */
507        self.goToMonth = function (year,month) {
508                var testdatemin = new Date(year, month, 31);
509                var testdatemax = new Date(year, month, 1);
510                if(testdatemin >= self.minDate && testdatemax <= self.maxDate) {
511                        self.monthSelect.value = self.displayMonth = month;
512                        self.yearSelect.value = self.displayYear = year;
513                        //recreate the calendar for the new month
514                        createCalCells();
515                        deleteCells();
516                        self.calendar.celltable.appendChild(self.calCells);
517                        return true;
518                }
519                else {
520                        alert(self.maxrange_caption);
521                        return false;
522                }
523        };
524        //-----------------------------------------------------------------------------
525        /**
526        * Moves the calendar's position to the target element's location (popup mode only)
527        */
528        self.updatePos = function (target) {
529                if(self.mode == 'popup') {
530                        self.calendar.style.top = getTop(target) + self.topOffset + 'px';
531                        self.calendar.style.left = getLeft(target) + self.leftOffset + 'px';
532                }
533        };
534        //-----------------------------------------------------------------------------
535        /**
536        * Displays the calendar
537        */
538        self.show = function () {
539                self.updatePos(self.tgt); //update the calendar position, in case the page layout has changed since loading
540                self.calendar.style.display = 'block'; //'table'; //<iehack> 'table' is the W3C-recommended spec, but IE isn't a fan of those
541                self.visible = true;
542        };
543        //-----------------------------------------------------------------------------
544        /**
545        * Hides the calendar
546        */
547        self.hide = function () {
548                self.calendar.style.display = 'none';
549                self.visible = false;
550                eval(m_afterHide +"('" + m_afterHideParam + "');");
551        };
552        //-----------------------------------------------------------------------------
553        /**
554        * Toggles (shows/hides) the calendar depending on its current state
555        */
556        self.toggle = function () {
557                self.visible ? self.hide() : self.show();
558        };
559        //-----------------------------------------------------------------------------
560        /**
561        * Adds the array "dates" to the calendar's dates array, removing duplicate dates,
562        * and redraws the calendar if redraw is true
563        * @param array dates
564        * @param bool redraw
565        */
566        self.addDates = function (dates,redraw) {
567                var i;
568                for(i=0;i<dates.length;i++) {
569                        if(self.dateInArray(self.dates,dates[i]) == -1) { //if the date isn't already in the array, add it!
570                                self.dates[self.dates.length] = dates[i];
571                        }
572                }
573                //now rebuild the selectedDates pointer array
574                updateSelectedDates();
575                if(redraw != false) { //redraw  the calendar if "redraw" is false or undefined
576                        self.reDraw();
577                }
578        };
579        //-----------------------------------------------------------------------------
580        /**
581        * Removes the dates from the calendar's dates array and redraws the calendar
582        * if redraw is true
583        * @param array dates
584        * @param bool redraw
585        */
586        self.removeDates = function (dates,redraw) {
587                var idx;
588                for(var i=0;i<dates.length;i++) {
589                        idx = self.dateInArray(self.dates,dates[i]);
590                        if(idx != -1) { //search for the dates in the dates array, removing them if the dates match
591                                self.dates.splice(idx,1);
592                        }
593                }
594                updateSelectedDates();
595                if(redraw != false) { //redraw  the calendar if "redraw" is true or undefined
596                        self.reDraw();
597                }
598        };
599        //-----------------------------------------------------------------------------
600        /**
601        * Selects or Deselects an array of dates
602        * @param Array inpdates
603        * @param bool selectVal
604        * @param bool redraw
605        * @param bool removeothers
606        */
607        self.selectDates = function (inpdates,selectVal,redraw,removeothers) {
608                var i, idx;
609                if(removeothers == true) {
610                        for(i=0;i<self.dates.length;i++) {
611                                self.dates[i].selected = false;
612                        }
613                }
614                for(i=0;i<inpdates.length;i++) {
615                        idx = self.dateInArray(self.dates,inpdates[i]);
616                        if(selectVal == true) {
617                                inpdates[i].selected = true;
618                                if(idx == -1) { //if the date does not exist in the calendar's dates array, add it
619                                        self.dates[self.dates.length] = inpdates[i];
620                                }
621                                else { //if not, just select it
622                                        self.dates[idx].selected = true;
623                                }
624                        }
625                        else { //if deselecting...
626                                if(idx > -1) { //if the date is found, deselect and/or remove it from the calendar's dates array
627                                        self.dates[idx].selected = inpdates[i].selected = false;
628                                        if(self.dates[idx].type == 'normal') { //remove 'normal' dates from the dates array, since they're useless unless selected
629                                                self.dates.splice(idx,1);
630                                        }
631                                }
632                        }
633                }
634                //now rebuild the selectedDates pointer array
635                updateSelectedDates();
636                if(redraw != false) { //redraw the calendar if "redraw" is false or undefined
637                        self.reDraw();
638                }
639        };
640        //-----------------------------------------------------------------------------
641        /**
642        * Adds the dates in dates as hidden inputs to the form "form".  inputname
643        * is the name of each hidden element. "form" can either be a pointer to the form's
644        * DOM element or its id string.
645        * @param mixed form
646        * @param string inputname
647        */
648        self.sendForm = function(form,inputname) {
649                var inpname = inputname || 'epochdates', f, inp;
650                f = (typeof(form) == 'string' ? document.getElementById(form) : form);
651                if(!f) {
652                        alert('ERROR: Invalid form input');
653                        return false;
654                }
655                for(var i=0;i<self.dates.length;i++) {
656                        inp = document.createElement('input');
657                        inp.setAttribute('type','hidden');
658                        inp.setAttribute('name',inpname + '['+i+']');
659                        inp.setAttribute('value',encodeURIComponent(self.dates[i].dateFormat('Y-m-d')));  //default to the ISO date format
660                        f.appendChild(inp);
661                }
662                return true;
663        };
664        //-----------------------------------------------------------------------------
665        /**
666        * Erases the dates array and resets the calendar's selection variables to defaults.
667        * If retMonth is true, the calendar will return to the initial default month/year
668        * @param bool retMonth
669        */
670        self.resetSelections = function (retMonth) {
671                var dateArray = new Array();
672                var dt = self.dates;
673                for(var i=0;i<dt.length;i++) {
674                        if(dt[i].selected) {
675                                dateArray[dateArray.length] = dt[i];
676                        }
677                }
678                self.selectDates(dateArray,false,false);
679                self.rows = new Array(false,false,false,false,false,false,false);
680                self.cols = new Array(false,false,false,false,false,false,false);
681                if(self.mode == 'popup') { //hide the calendar and clear the input element if in popup mode
682                        self.tgt.value = '';
683                        self.hide();
684                }
685                retMonth == true ? self.goToMonth(self.displayYearInitial,self.displayMonthInitial) : self.reDraw();
686        };
687        //-----------------------------------------------------------------------------
688        /**
689        * Reapplies all the CSS classes for the calendar cells - usually called after changing their state
690        * If index is specified, it will redraw that cell only.
691        * @param int index
692        */
693        self.reDraw = function (index) {
694                self.state = 1;
695                var len = index ? index + 1 : self.cells.length;
696                for(var i = index || 0;i<len;i++) {
697                        setCellProperties(i);
698                }
699                self.state = 2;
700        };
701        //-----------------------------------------------------------------------------
702        /**
703        * Returns the index of the cell whose date value matches "date", or -1 if not found
704        * @param Date date
705        * @return int
706        */
707        self.getCellIndex = function(date) {
708                for(var i=0;i<self.cells.length;i++) {
709                        if(self.cells[i].date.getUeDay() == date.getUeDay()) {
710                                return i;
711                        }
712                }
713                return -1;
714        };
715        //-----------------------------------------------------------------------------
716        //begin constructor code:
717
718        //PUBLIC VARIABLES
719        self.state = 0;
720        self.name = name;
721        self.curDate = new Date();
722        self.mode = mode;
723        self.selectMultiple = (multiselect == true); //'false' if not true or not set at all
724        //the various calendar variables
725        self.dates = new Array();
726        self.selectedDates = new Array();
727
728        self.calendar;
729        self.calHeading;
730        self.calCells;
731        self.rows;
732        self.cols;
733        self.cells = new Array();
734        //The controls
735        self.monthSelect;
736        self.yearSelect;
737        self.mousein = false;
738
739        //Initialize the calendar and its variables{
740        calConfig();
741        setLang();
742        setDays();
743        createCalendar(); //create the calendar DOM element and its children, and their related objects
744        targetelement = typeof(targetelement) == 'string' ? document.getElementById(targetelement) : targetelement;
745        setMode(targetelement);
746        self.state = 2; //0: initializing, 1: redrawing, 2: finished!
747        self.visible ? self.show() : self.hide();
748
749        self.afterHide = m_afterHide;
750        self.afterHideParam = m_afterHideParam;
751        self.dateformat = m_dateformat;
752}
753//-----------------------------------------------------------------------------
754/*****************************************************************************/
755/**
756* Object that contains the methods and properties for the calendar day headings
757*/
758function CalHeading(owner,tableCell,dayOfWeek) {
759        //-----------------------------------------------------------------------------
760        function DayHeadingonclick() {//selects/deselects the days for this object's day of week
761                //reduce indirection:
762                var sdates = owner.dates;
763                var cells = owner.cells;
764                var dateArray = new Array();
765                owner.cols[dayOfWeek] = !owner.cols[dayOfWeek];
766                for(var i=0;i<cells.length;i++) { //cycle through all the cells in the calendar, selecting all cells with the same dayOfWeek as this heading
767                        if(cells[i].dayOfWeek == dayOfWeek && cells[i].date.canSelect && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) { //if the cell's DoW matches, with other conditions
768                                dateArray[dateArray.length] = cells[i].date;
769                        }
770                }
771                owner.selectDates(dateArray,owner.cols[dayOfWeek],true);
772        }
773        //-----------------------------------------------------------------------------
774        var self = this;
775        self.dayOfWeek = dayOfWeek;
776        addEventHandler(tableCell,'mouseup',DayHeadingonclick);
777}
778/*****************************************************************************/
779/**
780* Object that contains the methods and properties for the calendar week headings
781*/
782function WeekHeading(owner,tableCell,week,tableRow) {
783        //-----------------------------------------------------------------------------
784        function weekHeadingonclick() {
785                //reduce indirection:
786                var cells = owner.cells;
787                var sdates = owner.dates;
788                var dateArray = new Array();
789                owner.rows[tableRow] = !owner.rows[tableRow];
790                for(var i=0;i<cells.length;i++) {
791                        if(cells[i].tableRow == tableRow && cells[i].date.canSelect && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) { //if the cell's DoW matches, with other conditions)
792                                dateArray[dateArray.length] = cells[i].date;
793                        }
794                }
795                owner.selectDates(dateArray,owner.rows[tableRow],true);
796        }
797        //-----------------------------------------------------------------------------
798        var self = this;
799        self.week = week;
800        tableCell.setAttribute('class','wkhead');
801        tableCell.setAttribute('className','wkhead'); //<iehack>
802        addEventHandler(tableCell,'mouseup',weekHeadingonclick);
803}
804/*****************************************************************************/
805/**
806* Object that holds all data & code related to a calendar cell
807*/
808/**
809 * The CalCell constructor function
810 * @param Epoch owner
811 * @param HTMLTableCellElement tableCell
812 * @param Date dateObj
813 * @param int row
814 * @param int week
815 */
816function CalCell(owner,tableCell,dateObj,row,week) {
817        var self = this;
818        //-----------------------------------------------------------------------------
819        function calCellonclick() {
820                if(self.date.canSelect) {
821                        if(owner.selectMultiple == true) { //if we can select multiple cells simultaneously, add the currently selected self's date to the dates array
822                                owner.selectDates(new Array(self.date),!self.date.selected,false);
823                                self.setClass(); //update the current cell's style to reflect the changes - a full redraw isn't necessary
824                        }
825                        else { //if we can only select one date at a time
826                                owner.selectDates(new Array(self.date),true,false,true);
827                                if(owner.mode == 'popup') { //update the target element's value and hide the calendar if in popup mode
828                                        //owner.tgt.value = self.date.dateFormat(); //use the default date format defined in dateFormat
829                                        owner.tgt.value = self.date.dateFormat(owner.dateformat);
830                                        owner.tgt.dateObj = new Date(self.date); //add a Date object to the target element for later reference
831                                        owner.hide();
832                                }
833                                owner.reDraw(); //redraw all the calendar cells
834                        }
835                }
836        }
837        //-----------------------------------------------------------------------------
838        /**
839        * Replicate the CSS :hover effect for non-supporting browsers <iehack>
840        */
841        function calCellonmouseover() {
842                if(self.date.canSelect) {
843                        tableCell.setAttribute('class',self.cellClass + ' hover');
844                        tableCell.setAttribute('className',self.cellClass + ' hover');
845                }
846        }
847        //-----------------------------------------------------------------------------
848        /**
849        * Replicate the CSS :hover effect for non-supporting browsers <iehack>
850        */
851        function calCellonmouseout() {
852                self.setClass();
853        }
854        //-----------------------------------------------------------------------------
855        /**
856        * Sets the CSS class of the cell based on the specified criteria
857        */
858        self.setClass = function ()
859        {
860                if(self.date.canSelect !== false) {
861                        if(self.date.selected) {
862                                self.cellClass = 'cell_selected';
863                        }
864                        else if(owner.displayMonth != self.date.getMonth() ) {
865                                self.cellClass = 'notmnth';
866                        }
867                        else if(self.date.type == 'holiday') {
868                                self.cellClass = 'hlday';
869                        }
870                        else if(self.dayOfWeek > 0 && self.dayOfWeek < 6) {
871                                self.cellClass = 'wkday';
872                        }
873                        else {
874                                self.cellClass = 'wkend';
875                        }
876                }
877                else {
878                        self.cellClass = 'noselect';
879                }
880                //highlight the current date
881                if(self.date.getUeDay() == owner.curDate.getUeDay()) {
882                        self.cellClass = self.cellClass + ' curdate';
883                }
884                tableCell.setAttribute('class',self.cellClass);
885                tableCell.setAttribute('className',self.cellClass); //<iehack>
886        };
887        //-----------------------------------------------------------------------------
888        /**
889        * Sets the cell's hyperlink, if declared
890        * @param string href
891        * @param string type ('anchor' or 'js' - default 'anchor')
892        */
893        self.setURL = function(href,type) {
894                if(href) {
895                        if(type == 'js') { //Make the WHOLE cell be a clickable link
896                                addEventHandler(self.tableCell,'mousedown',function(){window.location.href = href;});
897                        }
898                        else { //make only the date number of the cell a clickable link:
899                                var url = document.createElement('a');
900                                url.setAttribute('href',href);
901                                url.appendChild(document.createTextNode(self.date.getDate()));
902                                self.tableCell.replaceChild(url,self.tableCell.firstChild); //assumes the first child of the cell DOM node is the date text
903                        }
904                }
905        };
906        //-----------------------------------------------------------------------------
907        /**
908        * Sets the title (i.e. tooltip) that appears when a user holds their mouse cursor over a cell
909        * @param string titleStr
910        */
911        self.setTitle = function(titleStr) {
912                if(titleStr && titleStr.length > 0) {
913                        self.title = titleStr;
914                        self.tableCell.setAttribute('title',titleStr);
915                }
916        };
917        //-----------------------------------------------------------------------------
918        /**
919        * Sets the internal html of the cell, using a string containing html markup
920        * @param string html
921        */
922        self.setHTML = function(html) {
923                if(html && html.length > 0) {
924                        if(self.tableCell.childNodes[1]) {
925                                self.tableCell.childNodes[1].innerHTML = html;
926                        }
927                        else {
928                                var htmlCont = document.createElement('div');
929                                htmlCont.innerHTML = html;
930                                self.tableCell.appendChild(htmlCont);
931                        }
932                }
933        };
934        //-----------------------------------------------------------------------------
935        self.cellClass;                 //the CSS class of the cell
936        self.tableRow = row;
937        self.tableCell = tableCell;
938        self.date = new Date(dateObj);
939        self.date.canSelect = true; //whether this cell can be selected or not - always true unless set otherwise externally
940        self.date.type = 'normal';  //i.e. normal date, holiday, etc - always true unless set otherwise externally
941        self.date.selected = false;     //whether the cell is selected (and is therefore stored in the owner's dates array)
942        self.date.cellHTML = '';
943        self.dayOfWeek = self.date.getDay();
944        self.week = week;
945        //assign the event handlers for the table cell element
946        addEventHandler(tableCell,'click', calCellonclick);
947        addEventHandler(tableCell,'mouseover', calCellonmouseover);
948        addEventHandler(tableCell,'mouseout', calCellonmouseout);
949        self.setClass();
950}
951/*****************************************************************************/
952Date.prototype.getDayOfYear = function () //returns the day of the year for this date
953{
954        return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/86400000 + 1);
955};
956//-----------------------------------------------------------------------------
957/**
958 * Returns the week number for this date.  dowOffset is the day of week the week
959 * "starts" on for your locale - it can be from 0 to 6. If dowOffset is 1 (Monday),
960 * the week returned is the ISO 8601 week number.
961 * @param int dowOffset
962 * @return int
963 */
964Date.prototype.getWeek = function (dowOffset) {
965        dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 0; //default dowOffset to zero
966        var newYear = new Date(this.getFullYear(),0,1);
967        var day = newYear.getDay() - dowOffset; //the day of week the year begins on
968        day = (day >= 0 ? day : day + 7);
969        var weeknum, daynum = Math.floor((this.getTime() - newYear.getTime() - (this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
970        //if the year starts before the middle of a week
971        if(day < 4) {
972                weeknum = Math.floor((daynum+day-1)/7) + 1;
973                if(weeknum > 52) {
974                        nYear = new Date(this.getFullYear() + 1,0,1);
975                        nday = nYear.getDay() - dowOffset;
976                        nday = nday >= 0 ? nday : nday + 7;
977                        weeknum = nday < 4 ? 1 : 53; //if the next year starts before the middle of the week, it is week #1 of that year
978                }
979        }
980        else {
981                weeknum = Math.floor((daynum+day-1)/7);
982        }
983        return weeknum;
984};
985//-----------------------------------------------------------------------------
986Date.prototype.getUeDay = function () //returns the number of DAYS since the UNIX Epoch - good for comparing the date portion
987{
988        return parseInt(Math.floor((this.getTime() - this.getTimezoneOffset() * 60000)/86400000)); //must take into account the local timezone
989};
990//-----------------------------------------------------------------------------
991var __DATE_FORMAT = 'm/d/Y';
992Date.prototype.dateFormat = function(format)
993{
994        if(!format) { // the default date format to use - can be customized to the current locale
995                format = __DATE_FORMAT;
996        }
997        LZ = function(x) {return(x < 0 || x > 9 ? '' : '0') + x};
998        var MONTH_NAMES = new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
999        var DAY_NAMES = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
1000        var result="";
1001        var i_format=0;
1002        var c="";
1003        var token="";
1004        var y=this.getFullYear().toString();
1005        var M=this.getMonth()+1;
1006        var d=this.getDate();
1007        var E=this.getDay();
1008        var H=this.getHours();
1009        var m=this.getMinutes();
1010        var s=this.getSeconds();
1011        value = {
1012                Y: y.toString(),
1013                y: y.substring(2),
1014                n: M,
1015                m: LZ(M),
1016                F: MONTH_NAMES[M-1],
1017                M: MONTH_NAMES[M+11],
1018                j: d,
1019                d: LZ(d),
1020                D: DAY_NAMES[E+7],
1021                l: DAY_NAMES[E],
1022                G: H,
1023                H: LZ(H)
1024        };
1025        if (H==0) {value['g']=12;}
1026        else if (H>12){value['g']=H-12;}
1027        else {value['g']=H;}
1028        value['h']=LZ(value['g']);
1029        if (H > 11) {value['a']='pm'; value['A'] = 'PM';}
1030        else { value['a']='am'; value['A'] = 'AM';}
1031        value['i']=LZ(m);
1032        value['s']=LZ(s);
1033        //construct the result string
1034        while (i_format < format.length) {
1035                c=format.charAt(i_format);
1036                token="";
1037                while ((format.charAt(i_format)==c) && (i_format < format.length)) {
1038                        token += format.charAt(i_format++);
1039                }
1040                if (value[token] != null) { result=result + value[token]; }
1041                else { result=result + token; }
1042        }
1043        return result;
1044};
1045/*****************************************************************************/
1046//-----------------------------------------------------------------------------
1047function addEventHandler(element, type, func) { //unfortunate hack to deal with Internet Explorer's horrible DOM event model <iehack>
1048        if(element.addEventListener) {
1049                element.addEventListener(type,func,false);
1050        }
1051        else if (element.attachEvent) {
1052                element.attachEvent('on'+type,func);
1053        }
1054}
1055//-----------------------------------------------------------------------------
1056function removeEventHandler(element, type, func) { //unfortunate hack to deal with Internet Explorer's horrible DOM event model <iehack>
1057        if(element.removeEventListener) {
1058                element.removeEventListener(type,func,false);
1059        }
1060        else if (element.attachEvent) {
1061                element.detachEvent('on'+type,func);
1062        }
1063}
1064//-----------------------------------------------------------------------------
1065function getTop(element) {//returns the absolute Top value of element, in pixels
1066        var oNode = element;
1067        var iTop = 0;
1068
1069        while(oNode.tagName != 'HTML') {
1070                iTop += oNode.offsetTop || 0;
1071                if(oNode.offsetParent) { //i.e. the parent element is not hidden
1072                        oNode = oNode.offsetParent;
1073                }
1074                else {
1075                        break;
1076                }
1077        }
1078        return iTop;
1079}
1080//-----------------------------------------------------------------------------
1081function getLeft(element) { //returns the absolute Left value of element, in pixels
1082        var oNode = element;
1083        var iLeft = 0;
1084        while(oNode.tagName != 'HTML') {
1085                iLeft += oNode.offsetLeft || 0;
1086                if(oNode.offsetParent) { //i.e. the parent element is not hidden
1087                        oNode = oNode.offsetParent;
1088                }
1089                else {
1090                        break;
1091                }
1092        }
1093        return iLeft;
1094}
1095//-----------------------------------------------------------------------------
Note: See TracBrowser for help on using the browser.