Subversion Repositories ALCASAR

Rev

Details | Last modification | View Log

Rev Author Line No. Line
508 richard 1
/*****************************************************************************
2
Copyright (C) 2006  Nick Baicoianu
3
 
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
 
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
 
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17
*****************************************************************************/
18
//constructor for the main Epoch class (ENGLISH VERSION)
19
function Epoch(name,mode,targetelement,multiselect)
20
{
21
	this.state = 0;
22
	this.name = name;
23
	this.curDate = new Date();
24
	this.mode = mode;
25
	this.selectMultiple = (multiselect == true); //'false' is not true or not set at all
26
 
27
	//the various calendar variables
28
	//this.selectedDate = this.curDate;
29
	this.selectedDates = new Array();
30
	this.calendar;
31
	this.calHeading;
32
	this.calCells;
33
	this.rows;
34
	this.cols;
35
	this.cells = new Array();
36
 
37
	//The controls
38
	this.monthSelect;
39
	this.yearSelect;
40
 
41
	//standard initializations
42
	this.mousein = false;
43
	this.calConfig();
44
	this.setDays();
45
	this.displayYear = this.displayYearInitial;
46
	this.displayMonth = this.displayMonthInitial;
47
 
48
	this.createCalendar(); //create the calendar DOM element and its children, and their related objects
49
 
50
	if(this.mode == 'popup' && targetelement && targetelement.type == 'text') //if the target element has been set to be an input text box
51
	{
52
		this.tgt = targetelement;
53
		this.calendar.style.position = 'absolute';
54
		this.topOffset = this.tgt.offsetHeight; // the vertical distance (in pixels) to display the calendar from the Top of its input element
55
		this.leftOffset = 0; 					// the horizontal distance (in pixels) to display the calendar from the Left of its input element
56
		this.calendar.style.top = this.getTop(targetelement) + this.topOffset + 'px';
57
		this.calendar.style.left = this.getLeft(targetelement) + this.leftOffset + 'px';
58
		document.body.appendChild(this.calendar);
59
		this.tgt.calendar = this;
60
		this.tgt.onfocus = function () {this.calendar.show();}; //the calendar will popup when the input element is focused
61
		this.tgt.onblur = function () {if(!this.calendar.mousein){this.calendar.hide();}}; //the calendar will popup when the input element is focused
62
	}
63
	else
64
	{
65
		this.container = targetelement;
66
		this.container.appendChild(this.calendar);
67
	}
68
 
69
	this.state = 2; //0: initializing, 1: redrawing, 2: finished!
70
	this.visible ? this.show() : this.hide();
71
}
72
//-----------------------------------------------------------------------------
73
Epoch.prototype.calConfig = function () //PRIVATE: initialize calendar variables
74
{
75
	/* 
76
	------------------------------------------------------------------
77
	la majorité des modifications d'affichage du calendrier se font ici 
78
	modifications de configuration faites:
79
	1-Début du calendrier en 2011 à modifier au fur et à mesure
80
	2-Fin en 2037 c'est déjà pas mal
81
	3-jour de début de semaine "Lundi"
82
	4-Affichage du numéro de semaine "non"
83
	------------Commentaire ajouté par Geoffroy MUSITELLI-------------
84
	*/
85
	//this.mode = 'flat'; //can be 'flat' or 'popup'
86
	this.displayYearInitial = this.curDate.getFullYear(); //the initial year to display on load
87
	this.displayMonthInitial = this.curDate.getMonth(); //the initial month to display on load (0-11)
88
	this.rangeYearLower = 2011;
89
	this.rangeYearUpper = 2037;
90
	this.minDate = new Date(2011,0,1);
91
	this.maxDate = new Date(2037,0,1);
92
	this.startDay = 1; // the day the week will 'start' on: 0(Sun) to 6(Sat)
93
	this.showWeeks = false; //whether the week numbers will be shown
94
	this.selCurMonthOnly = false; //allow user to only select dates in the currently displayed month
95
	this.clearSelectedOnChange = true; //whether to clear all selected dates when changing months
96
 
97
	//flat mode-only settings:
98
	//this.selectMultiple = true; //whether the user can select multiple dates (flat mode only)
99
 
100
	switch(this.mode) //set the variables based on the calendar mode
101
	{
102
		case 'popup': //popup options
103
			this.visible = false;
104
			break;
105
		case 'flat':
106
			this.visible = true;
107
 
108
			break;
109
	}
110
	this.setLang();
111
};
112
//-----------------------------------------------------------------------------
113
Epoch.prototype.setLang = function()  //all language settings for Epoch are made here.  Check Date.dateFormat() for the Date object's language settings
114
{
115
	this.daylist = new Array('Su','Mo','Tu','We','Th','Fr','Sa','Su','Mo','Tu','We','Th','Fr','Sa'); /*<lang:en>*/
116
	this.months_sh = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
117
	this.monthup_title = 'Go to the next month';
118
	this.monthdn_title = 'Go to the previous month';
119
	this.clearbtn_caption = 'Clear';
120
	this.clearbtn_title = 'Clears any dates selected on the calendar';
121
	this.maxrange_caption = 'This is the maximum range';
122
};
123
//-----------------------------------------------------------------------------
124
Epoch.prototype.getTop = function (element) //PRIVATE: returns the absolute Top value of element, in pixels
125
{
126
    var oNode = element;
127
    var iTop = 0;
128
 
129
    while(oNode.tagName != 'BODY') {
130
        iTop += oNode.offsetTop;
131
        oNode = oNode.offsetParent;
132
    }
133
 
134
    return iTop;
135
};
136
//-----------------------------------------------------------------------------
137
Epoch.prototype.getLeft = function (element) //PRIVATE: returns the absolute Left value of element, in pixels
138
{
139
    var oNode = element;
140
    var iLeft = 0;
141
 
142
    while(oNode.tagName != 'BODY') {
143
        iLeft += oNode.offsetLeft;
144
        oNode = oNode.offsetParent;        
145
    }
146
 
147
    return iLeft;
148
};
149
//-----------------------------------------------------------------------------
150
Epoch.prototype.show = function () //PUBLIC: displays the calendar
151
{
152
	this.calendar.style.display = 'block';
153
	this.visible = true;
154
};
155
//-----------------------------------------------------------------------------
156
Epoch.prototype.hide = function () //PUBLIC: Hides the calendar
157
{
158
	this.calendar.style.display = 'none';
159
	this.visible = false;
160
};
161
//-----------------------------------------------------------------------------
162
Epoch.prototype.toggle = function () //PUBLIC: Toggles (shows/hides) the calendar depending on its current state
163
{
164
	if(this.visible) {
165
		this.hide();
166
	}
167
	else {
168
		this.show();
169
	}
170
};
171
//-----------------------------------------------------------------------------
172
Epoch.prototype.setDays = function ()  //PRIVATE: initializes the standard Gregorian Calendar parameters
173
{
174
	this.daynames = new Array();
175
	var j=0;
176
	for(var i=this.startDay; i< this.startDay + 7;i++) {
177
		this.daynames[j++] = this.daylist[i];
178
	}
179
 
180
	this.monthDayCount = new Array(31,((this.curDate.getFullYear() - 2000) % 4 ? 28 : 29),31,30,31,30,31,31,30,31,30,31);
181
};
182
//-----------------------------------------------------------------------------
183
Epoch.prototype.setClass = function (element,className) //PRIVATE: sets the CSS class of the element, W3C & IE
184
{
185
	element.setAttribute('class',className);
186
	element.setAttribute('className',className); //<iehack>
187
};
188
//-----------------------------------------------------------------------------
189
Epoch.prototype.createCalendar = function ()  //PRIVATE: creates the full DOM implementation of the calendar
190
{
191
	var tbody, tr, td;
192
	this.calendar = document.createElement('table');
193
	this.calendar.setAttribute('id',this.name+'_calendar');
194
	this.setClass(this.calendar,'calendar');
195
	//to prevent IE from selecting text when clicking on the calendar
196
	this.calendar.onselectstart = function() {return false;};
197
	this.calendar.ondrag = function() {return false;};
198
	tbody = document.createElement('tbody');
199
 
200
	//create the Main Calendar Heading
201
	tr = document.createElement('tr');
202
	td = document.createElement('td');
203
	td.appendChild(this.createMainHeading());
204
	tr.appendChild(td);
205
	tbody.appendChild(tr);
206
 
207
	//create the calendar Day Heading
208
	tr = document.createElement('tr');
209
	td = document.createElement('td');
210
	td.appendChild(this.createDayHeading());
211
	tr.appendChild(td);
212
	tbody.appendChild(tr);
213
 
214
	//create the calendar Day Cells
215
	tr = document.createElement('tr');
216
	td = document.createElement('td');
217
	td.setAttribute('id',this.name+'_cell_td');
218
	this.calCellContainer = td;	//used as a handle for manipulating the calendar cells as a whole
219
	td.appendChild(this.createCalCells());
220
	tr.appendChild(td);
221
	tbody.appendChild(tr);
222
 
223
	//create the calendar footer
224
	tr = document.createElement('tr');
225
	td = document.createElement('td');
226
	td.appendChild(this.createFooter());
227
	tr.appendChild(td);
228
	tbody.appendChild(tr);
229
 
230
	//add the tbody element to the main calendar table
231
	this.calendar.appendChild(tbody);
232
 
233
	//and add the onmouseover events to the calendar table
234
	this.calendar.owner = this;
235
	this.calendar.onmouseover = function() {this.owner.mousein = true;};
236
	this.calendar.onmouseout = function() {this.owner.mousein = false;};
237
};
238
//-----------------------------------------------------------------------------
239
Epoch.prototype.createMainHeading = function () //PRIVATE: Creates the primary calendar heading, with months & years
240
{
241
	//create the containing <div> element
242
	var container = document.createElement('div');
243
	container.setAttribute('id',this.name+'_mainheading');
244
	this.setClass(container,'mainheading');
245
	//create the child elements and other variables
246
	this.monthSelect = document.createElement('select');
247
	this.yearSelect = document.createElement('select');
248
	var monthDn = document.createElement('input'), monthUp = document.createElement('input');
249
	var opt, i;
250
	//fill the month select box
251
	for(i=0;i<12;i++)
252
	{
253
		opt = document.createElement('option');
254
		opt.setAttribute('value',i);
255
		if(this.state == 0 && this.displayMonth == i) {
256
			opt.setAttribute('selected','selected');
257
		}
258
		opt.appendChild(document.createTextNode(this.months_sh[i]));
259
		this.monthSelect.appendChild(opt);
260
	}
261
	//and fill the year select box
262
	for(i=this.rangeYearLower;i<=this.rangeYearUpper;i++)
263
	{
264
		opt = document.createElement('option');
265
		opt.setAttribute('value',i);
266
		if(this.state == 0 && this.displayYear == i) {
267
			opt.setAttribute('selected','selected');
268
		}
269
		opt.appendChild(document.createTextNode(i));
270
		this.yearSelect.appendChild(opt);		
271
	}
272
	//add the appropriate children for the month buttons
273
	monthUp.setAttribute('type','button');
274
	monthUp.setAttribute('value','>');
275
	monthUp.setAttribute('title',this.monthup_title);
276
	monthDn.setAttribute('type','button');
277
	monthDn.setAttribute('value','<');
278
	monthDn.setAttribute('title',this.monthdn_title);
279
	this.monthSelect.owner = this.yearSelect.owner = monthUp.owner = monthDn.owner = this;  //hack to allow us to access this calendar in the events (<fix>??)
280
 
281
	//assign the event handlers for the controls
282
	monthUp.onmouseup = function () {this.owner.nextMonth();};
283
	monthDn.onmouseup = function () {this.owner.prevMonth();};
284
	this.monthSelect.onchange = function() {
285
		this.owner.displayMonth = this.value;
286
		this.owner.displayYear = this.owner.yearSelect.value; 
287
		this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
288
	};
289
	this.yearSelect.onchange = function() {
290
		this.owner.displayMonth = this.owner.monthSelect.value;
291
		this.owner.displayYear = this.value; 
292
		this.owner.goToMonth(this.owner.displayYear,this.owner.displayMonth);
293
	};
294
 
295
	//and finally add the elements to the containing div
296
	container.appendChild(monthDn);
297
	container.appendChild(this.monthSelect);
298
	container.appendChild(this.yearSelect);
299
	container.appendChild(monthUp);
300
	return container;
301
};
302
//-----------------------------------------------------------------------------
303
Epoch.prototype.createFooter = function () //PRIVATE: creates the footer of the calendar - goes under the calendar cells
304
{
305
	var container = document.createElement('div');
306
	var clearSelected = document.createElement('input');
307
	clearSelected.setAttribute('type','button');
308
	clearSelected.setAttribute('value',this.clearbtn_caption);
309
	clearSelected.setAttribute('title',this.clearbtn_title);
310
	clearSelected.owner = this;
311
	clearSelected.onclick = function() { this.owner.resetSelections(false);};
312
	container.appendChild(clearSelected);
313
	return container;
314
};
315
//-----------------------------------------------------------------------------
316
Epoch.prototype.resetSelections = function (returnToDefaultMonth)  //PRIVATE: reset the calendar's selection variables to defaults
317
{
318
	this.selectedDates = new Array();
319
	this.rows = new Array(false,false,false,false,false,false,false);
320
	this.cols = new Array(false,false,false,false,false,false,false);
321
	if(this.tgt)  //if there is a target element, clear it too
322
	{
323
		this.tgt.value = '';
324
		if(this.mode == 'popup') {//hide the calendar if in popup mode
325
			this.hide();
326
		}
327
	}
328
 
329
	if(returnToDefaultMonth == true) {
330
		this.goToMonth(this.displayYearInitial,this.displayMonthInitial);
331
	}
332
	else {
333
		this.reDraw();
334
	}
335
};
336
//-----------------------------------------------------------------------------
337
Epoch.prototype.createDayHeading = function ()  //PRIVATE: creates the heading containing the day names
338
{
339
	//create the table element
340
	this.calHeading = document.createElement('table');
341
	this.calHeading.setAttribute('id',this.name+'_caldayheading');
342
	this.setClass(this.calHeading,'caldayheading');
343
	var tbody,tr,td;
344
	tbody = document.createElement('tbody');
345
	tr = document.createElement('tr');
346
	this.cols = new Array(false,false,false,false,false,false,false);
347
 
348
	//if we're showing the week headings, create an empty <td> for filler
349
	if(this.showWeeks)
350
	{
351
		td = document.createElement('td');
352
		td.setAttribute('class','wkhead');
353
		td.setAttribute('className','wkhead'); //<iehack>
354
		tr.appendChild(td);
355
	}
356
	//populate the day titles
357
	for(var dow=0;dow<7;dow++)
358
	{
359
		td = document.createElement('td');
360
		td.appendChild(document.createTextNode(this.daynames[dow]));
361
		if(this.selectMultiple) { //if selectMultiple is true, assign the cell a CalHeading Object to handle all events
362
			td.headObj = new CalHeading(this,td,(dow + this.startDay < 7 ? dow + this.startDay : dow + this.startDay - 7));
363
		}
364
		tr.appendChild(td);
365
	}
366
	tbody.appendChild(tr);
367
	this.calHeading.appendChild(tbody);
368
	return this.calHeading;	
369
};
370
//-----------------------------------------------------------------------------
371
Epoch.prototype.createCalCells = function ()  //PRIVATE: creates the table containing the calendar day cells
372
{
373
	this.rows = new Array(false,false,false,false,false,false);
374
	this.cells = new Array();
375
	var row = -1, totalCells = (this.showWeeks ? 48 : 42);
376
	var beginDate = new Date(this.displayYear,this.displayMonth,1);
377
	var endDate = new Date(this.displayYear,this.displayMonth,this.monthDayCount[this.displayMonth]);
378
	var sdt = new Date(beginDate);
379
	sdt.setDate(sdt.getDate() + (this.startDay - beginDate.getDay()) - (this.startDay - beginDate.getDay() > 0 ? 7 : 0) );
380
	//create the table element
381
	this.calCells = document.createElement('table');
382
	this.calCells.setAttribute('id',this.name+'_calcells');
383
	this.setClass(this.calCells,'calcells');
384
	var tbody,tr,td;
385
	tbody = document.createElement('tbody');
386
	for(var i=0;i<totalCells;i++)
387
	{
388
		if(this.showWeeks) //if we are showing the week headings
389
		{
390
			if(i % 8 == 0)
391
			{
392
				row++;
393
				tr = document.createElement('tr');
394
				td = document.createElement('td');
395
				if(this.selectMultiple) { //if selectMultiple is enabled, create the associated weekObj objects
396
					td.weekObj = new WeekHeading(this,td,sdt.getWeek(),row)
397
				}
398
				else //otherwise just set the class of the td for consistent look
399
				{
400
					td.setAttribute('class','wkhead');
401
					td.setAttribute('className','wkhead'); //<iehack>
402
				}
403
				td.appendChild(document.createTextNode(sdt.getWeek()));			
404
				tr.appendChild(td);
405
				i++;
406
			}
407
		}
408
		else if(i % 7 == 0) //otherwise, new row every 7 cells
409
		{
410
			row++;
411
			tr = document.createElement('tr');
412
		}
413
		//create the day cells
414
		td = document.createElement('td');
415
		td.appendChild(document.createTextNode(sdt.getDate()));// +' ' +sdt.getUeDay()));
416
		var cell = new CalCell(this,td,sdt,row);
417
		this.cells.push(cell);
418
		td.cellObj = cell;
419
		sdt.setDate(sdt.getDate() + 1); //increment the date
420
		tr.appendChild(td);
421
		tbody.appendChild(tr);
422
	}
423
	this.calCells.appendChild(tbody);
424
	this.reDraw();
425
	return this.calCells;
426
};
427
//-----------------------------------------------------------------------------
428
Epoch.prototype.reDraw = function () //PRIVATE: reapplies all the CSS classes for the calendar cells, usually called after chaning their state
429
{
430
	this.state = 1;
431
	var i,j;
432
	for(i=0;i<this.cells.length;i++) {
433
		this.cells[i].selected = false;
434
	}
435
	for(i=0;i<this.cells.length;i++)
436
	{
437
		for(j=0;j<this.selectedDates.length;j++) { //if the cell's date is in the selectedDates array, set its selected property to true
438
			if(this.cells[i].date.getUeDay() == this.selectedDates[j].getUeDay() ) {
439
				this.cells[i].selected = true;
440
			}
441
		}
442
 
443
		this.cells[i].setClass();
444
	}
445
	//alert(this.selectedDates);
446
	this.state = 2;
447
};
448
//-----------------------------------------------------------------------------
449
Epoch.prototype.deleteCells = function () //PRIVATE: removes the calendar cells from the DOM (does not delete the cell objects associated with them
450
{
451
	this.calCellContainer.removeChild(this.calCellContainer.firstChild); //get a handle on the cell table (optional - for less indirection)
452
	this.cells = new Array(); //reset the cells array
453
};
454
//-----------------------------------------------------------------------------
455
Epoch.prototype.goToMonth = function (year,month) //PUBLIC: sets the calendar to display the requested month/year
456
{
457
	this.monthSelect.value = this.displayMonth = month;
458
	this.yearSelect.value = this.displayYear = year;
459
	this.deleteCells();
460
	this.calCellContainer.appendChild(this.createCalCells());
461
};
462
//-----------------------------------------------------------------------------
463
Epoch.prototype.nextMonth = function () //PUBLIC: go to the next month.  if the month is december, go to january of the next year
464
{
465
 
466
	//increment the month/year values, provided they're within the min/max ranges
467
	if(this.monthSelect.value < 11) {
468
		this.monthSelect.value++;
469
	}
470
	else
471
	{
472
		if(this.yearSelect.value < this.rangeYearUpper)
473
		{
474
			this.monthSelect.value = 0;
475
			this.yearSelect.value++;
476
		}
477
		else {
478
			alert(this.maxrange_caption);
479
		}
480
	}
481
	//assign the currently displaying month/year values
482
	this.displayMonth = this.monthSelect.value;
483
	this.displayYear = this.yearSelect.value;
484
 
485
	//and refresh the calendar for the new month/year
486
	this.deleteCells();
487
	this.calCellContainer.appendChild(this.createCalCells());
488
};
489
//-----------------------------------------------------------------------------
490
Epoch.prototype.prevMonth = function () //PUBLIC: go to the previous month.  if the month is january, go to december of the previous year
491
{
492
	//increment the month/year values, provided they're within the min/max ranges
493
	if(this.monthSelect.value > 0)
494
		this.monthSelect.value--;
495
	else
496
	{
497
		if(this.yearSelect.value > this.rangeYearLower)
498
		{
499
			this.monthSelect.value = 11;
500
			this.yearSelect.value--;
501
		}
502
		else {
503
			alert(this.maxrange_caption);
504
		}
505
	}
506
 
507
	//assign the currently displaying month/year values
508
	this.displayMonth = this.monthSelect.value;
509
	this.displayYear = this.yearSelect.value;
510
 
511
	//and refresh the calendar for the new month/year
512
	this.deleteCells();
513
	this.calCellContainer.appendChild(this.createCalCells());
514
};
515
//-----------------------------------------------------------------------------
516
Epoch.prototype.addZero = function (vNumber) //PRIVATE: pads a 2 digit number with a leading zero
517
{
518
	return ((vNumber < 10) ? '0' : '') + vNumber;
519
};
520
//-----------------------------------------------------------------------------
521
Epoch.prototype.addDates = function (dates,redraw)  //PUBLIC: adds the array "dates" to the calendars selectedDates array (no duplicate dates) and redraws the calendar
522
{
523
	var j,in_sd;
524
	for(var i=0;i<dates.length;i++)
525
	{	
526
		in_sd = false;
527
		for(j=0;j<this.selectedDates.length;j++)
528
		{
529
			if(dates[i].getUeDay() == this.selectedDates[j].getUeDay())
530
			{
531
				in_sd = true;
532
				break;
533
			}
534
		}
535
		if(!in_sd) { //if the date isn't already in the array, add it!
536
			this.selectedDates.push(dates[i]);
537
		}
538
	}
539
	if(redraw != false) {//redraw  the calendar if "redraw" is false or undefined
540
		this.reDraw();
541
	}
542
};
543
//-----------------------------------------------------------------------------
544
Epoch.prototype.removeDates = function (dates,redraw)  //PUBLIC: adds the dates to the calendars selectedDates array and redraws the calendar
545
{
546
	var j;
547
	for(var i=0;i<dates.length;i++)
548
	{
549
		for(j=0;j<this.selectedDates.length;j++)
550
		{
551
			if(dates[i].getUeDay() == this.selectedDates[j].getUeDay()) { //search for the dates in the selectedDates array, removing them if the dates match
552
				this.selectedDates.splice(j,1);
553
			}
554
		}
555
	}
556
	if(redraw != false) { //redraw  the calendar if "redraw" is false or undefined
557
		this.reDraw();
558
	}
559
};
560
//-----------------------------------------------------------------------------
561
Epoch.prototype.outputDate = function (vDate, vFormat) //PUBLIC: outputs a date in the appropriate format (DEPRECATED)
562
{
563
	var vDay			= this.addZero(vDate.getDate()); 
564
	var vMonth			= this.addZero(vDate.getMonth() + 1); 
565
	var vYearLong		= this.addZero(vDate.getFullYear()); 
566
	var vYearShort		= this.addZero(vDate.getFullYear().toString().substring(3,4)); 
567
	var vYear			= (vFormat.indexOf('yyyy') > -1 ? vYearLong : vYearShort);
568
	var vHour			= this.addZero(vDate.getHours()); 
569
	var vMinute			= this.addZero(vDate.getMinutes()); 
570
	var vSecond			= this.addZero(vDate.getSeconds()); 
571
	return vFormat.replace(/dd/g, vDay).replace(/mm/g, vMonth).replace(/y{1,4}/g, vYear).replace(/hh/g, vHour).replace(/nn/g, vMinute).replace(/ss/g, vSecond);
572
};
573
//-----------------------------------------------------------------------------
574
Epoch.prototype.updatePos = function (target) //PUBLIC: moves the calendar's position to target's location (popup mode only)
575
{
576
	this.calendar.style.top = this.getTop(target) + this.topOffset + 'px'
577
	this.calendar.style.left = this.getLeft(target) + this.leftOffset + 'px'
578
}
579
//-----------------------------------------------------------------------------
580
 
581
/*****************************************************************************/
582
function CalHeading(owner,tableCell,dow)
583
{
584
	this.owner = owner;
585
	this.tableCell = tableCell;
586
	this.dayOfWeek = dow;
587
 
588
	//the event handlers
589
	this.tableCell.onclick = this.onclick;
590
}
591
//-----------------------------------------------------------------------------
592
CalHeading.prototype.onclick = function ()
593
{
594
	//reduce indirection:
595
	var owner = this.headObj.owner;
596
	var sdates = owner.selectedDates;
597
	var cells = owner.cells;
598
 
599
	owner.cols[this.headObj.dayOfWeek] = !owner.cols[this.headObj.dayOfWeek];
600
	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
601
	{
602
		if(cells[i].dayOfWeek == this.headObj.dayOfWeek && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //if the cell's DoW matches, with other conditions
603
		{
604
			if(owner.cols[this.headObj.dayOfWeek]) 		//if selecting, add the cell's date to the selectedDates array
605
			{
606
				if(owner.selectedDates.arrayIndex(cells[i].date) == -1) { //if the date isn't already in the array
607
					sdates.push(cells[i].date);
608
				}
609
			}
610
			else										//otherwise, remove it
611
			{
612
				for(var j=0;j<sdates.length;j++) 
613
				{
614
					if(cells[i].dayOfWeek == sdates[j].getDay())
615
					{
616
						sdates.splice(j,1);	//remove dates that are within the displaying month/year that have the same day of week as the day cell
617
						break;
618
					}
619
				}
620
			}
621
			cells[i].selected = owner.cols[this.headObj.dayOfWeek];
622
		}
623
	}
624
	owner.reDraw();
625
};
626
/*****************************************************************************/
627
function WeekHeading(owner,tableCell,week,row)
628
{
629
	this.owner = owner;
630
	this.tableCell = tableCell;
631
	this.week = week;
632
	this.tableRow = row;
633
	this.tableCell.setAttribute('class','wkhead');
634
	this.tableCell.setAttribute('className','wkhead'); //<iehack>
635
	//the event handlers
636
	this.tableCell.onclick = this.onclick;
637
}
638
//-----------------------------------------------------------------------------
639
WeekHeading.prototype.onclick = function ()
640
{
641
	//reduce indirection:
642
	var owner = this.weekObj.owner;
643
	var cells = owner.cells;
644
	var sdates = owner.selectedDates;
645
	var i,j;
646
	owner.rows[this.weekObj.tableRow] = !owner.rows[this.weekObj.tableRow];
647
	for(i=0;i<cells.length;i++)
648
	{
649
		if(cells[i].tableRow == this.weekObj.tableRow)
650
		{
651
			if(owner.rows[this.weekObj.tableRow] && (!owner.selCurMonthOnly || cells[i].date.getMonth() == owner.displayMonth && cells[i].date.getFullYear() == owner.displayYear)) //match all cells in the current row, with option to restrict to current month only
652
			{
653
				if(owner.selectedDates.arrayIndex(cells[i].date) == -1) {//if the date isn't already in the array
654
					sdates.push(cells[i].date);
655
				}
656
			}
657
			else										//otherwise, remove it
658
			{
659
				for(j=0;j<sdates.length;j++)
660
				{
661
					if(sdates[j].getTime() == cells[i].date.getTime())  //this.weekObj.tableRow && sdates[j].getMonth() == owner.displayMonth && sdates[j].getFullYear() == owner.displayYear)
662
					{
663
						sdates.splice(j,1);	//remove dates that are within the displaying month/year that have the same day of week as the day cell
664
						break;
665
					}
666
				}
667
			}
668
		}
669
	}
670
	owner.reDraw();
671
};
672
/*****************************************************************************/
673
//-----------------------------------------------------------------------------
674
function CalCell(owner,tableCell,dateObj,row)
675
{
676
	this.owner = owner;		//used primarily for event handling
677
	this.tableCell = tableCell; 			//the link to this cell object's table cell in the DOM
678
	this.cellClass;			//the CSS class of the cell
679
	this.selected = false;	//whether the cell is selected (and is therefore stored in the owner's selectedDates array)
680
	this.date = new Date(dateObj);
681
	this.dayOfWeek = this.date.getDay();
682
	this.week = this.date.getWeek();
683
	this.tableRow = row;
684
 
685
	//assign the event handlers for the table cell element
686
	this.tableCell.onclick = this.onclick;
687
	this.tableCell.onmouseover = this.onmouseover;
688
	this.tableCell.onmouseout = this.onmouseout;
689
 
690
	//and set the CSS class of the table cell
691
	this.setClass();
692
}
693
//-----------------------------------------------------------------------------
694
CalCell.prototype.onmouseover = function () //replicate CSS :hover effect for non-supporting browsers <iehack>
695
{
696
	this.setAttribute('class',this.cellClass + ' hover');
697
	this.setAttribute('className',this.cellClass + ' hover');
698
};
699
//-----------------------------------------------------------------------------
700
CalCell.prototype.onmouseout = function () //replicate CSS :hover effect for non-supporting browsers <iehack>
701
{
702
	this.cellObj.setClass();
703
};
704
//-----------------------------------------------------------------------------
705
CalCell.prototype.onclick = function () 
706
{
707
	//reduce indirection:
708
	var cell = this.cellObj;
709
	var owner = cell.owner;
710
	if(!owner.selCurMonthOnly || cell.date.getMonth() == owner.displayMonth && cell.date.getFullYear() == owner.displayYear)
711
	{
712
		if(owner.selectMultiple == true)  //if we can select multiple cells simultaneously, add the currently selected cell's date to the selectedDates array
713
		{
714
			if(!cell.selected) //if this cell has been selected
715
			{
716
				if(owner.selectedDates.arrayIndex(cell.date) == -1) {
717
					owner.selectedDates.push(cell.date);
718
				}
719
			}
720
			else		
721
			{
722
				var tmp = owner.selectedDates; // to reduce indirection
723
				//if the cell has been deselected, remove it from the owner calendar's selectedDates array
724
				for(var i=0;i<tmp.length;i++)
725
				{
726
					if(tmp[i].getUeDay() == cell.date.getUeDay()) {
727
						tmp.splice(i,1);
728
					}
729
				}
730
			}
731
		}
732
		else //if we can only select one cell at a time
733
		{
734
			owner.selectedDates = new Array(cell.date);
735
			if(owner.tgt) //if there is a target element to place the value in, do so
736
			{
737
				owner.tgt.value = owner.selectedDates[0].dateFormat();
738
				if(owner.mode == 'popup') {
739
					owner.hide();
740
				}
741
			}
742
		}
743
		owner.reDraw(); //redraw the calendar cell styles to reflect the changes
744
	}
745
};
746
//-----------------------------------------------------------------------------
747
CalCell.prototype.setClass = function ()  //private: sets the CSS class of the cell based on the specified criteria
748
{
749
	if(this.selected) {
750
		this.cellClass = 'cell_selected';
751
	}
752
	else if(this.owner.displayMonth != this.date.getMonth() ) {
753
		this.cellClass = 'notmnth';	
754
	}
755
	else if(this.date.getDay() > 0 && this.date.getDay() < 6) {
756
		this.cellClass = 'wkday';
757
	}
758
	else {
759
		this.cellClass = 'wkend';
760
	}
761
 
762
	if(this.date.getFullYear() == this.owner.curDate.getFullYear() && this.date.getMonth() == this.owner.curDate.getMonth() && this.date.getDate() == this.owner.curDate.getDate()) {
763
		this.cellClass = this.cellClass + ' curdate';
764
	}
765
 
766
	this.tableCell.setAttribute('class',this.cellClass);
767
	this.tableCell.setAttribute('className',this.cellClass); //<iehack>
768
};
769
/*****************************************************************************/
770
Date.prototype.getDayOfYear = function () //returns the day of the year for this date
771
{
772
	return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/86400000 + 1);
773
};
774
//-----------------------------------------------------------------------------
775
Date.prototype.getWeek = function () //returns the day of the year for this date
776
{
777
	return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/604800000 + 1);
778
};
779
/*function getISOWeek()
780
{
781
	var newYear = new Date(this.getFullYear(),0,1);
782
	var modDay = newYear.getDay();
783
	if (modDay == 0) modDay=6; else modDay--;
784
 
785
	var daynum = ((Date.UTC(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0) - Date.UTC(this.getFullYear()),0,1,0,0,0)) /1000/60/60/24) + 1;
786
 
787
	if (modDay < 4 ) {
788
	    var weeknum = Math.floor((daynum+modDay-1)/7)+1;
789
	}
790
	else {
791
	    var weeknum = Math.floor((daynum+modDay-1)/7);
792
	    if (weeknum == 0) {
793
	        year--;
794
	        var prevNewYear = new Date(this.getFullYear(),0,1);
795
	        var prevmodDay = prevNewYear.getDay();
796
	        if (prevmodDay == 0) prevmodDay = 6; else prevmodDay--;
797
	        if (prevmodDay < 4) weeknum = 53; else weeknum = 52;
798
	    }
799
	}
800
 
801
	return + weeknum;
802
}*/
803
//-----------------------------------------------------------------------------
804
Date.prototype.getUeDay = function () //returns the number of DAYS since the UNIX Epoch - good for comparing the date portion
805
{
806
	return parseInt(Math.floor((this.getTime() - this.getTimezoneOffset() * 60000)/86400000)); //must take into account the local timezone
807
};
808
//-----------------------------------------------------------------------------
809
Date.prototype.dateFormat = function(format)
810
{
811
	if(!format) { // the default date format to use - can be customized to the current locale
812
		format = 'd F Y'; //Changé pour avoir la date au format jour mois_long année_sur_4digits
813
	}
814
	LZ = function(x) {return(x < 0 || x > 9 ? '' : '0') + x};
815
< 0 || x >	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');
816
< 0 || x >	var DAY_NAMES = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
817
< 0 || x >	format = format + "";
818
< 0 || x >	var result="";
819
< 0 || x >	var i_format=0;
820
< 0 || x >	var c="";
821
< 0 || x >	var token="";
822
< 0 || x >	var y=this.getFullYear().toString();
823
< 0 || x >	var M=this.getMonth()+1;
824
< 0 || x >	var d=this.getDate();
825
< 0 || x >	var E=this.getDay();
826
< 0 || x >	var H=this.getHours();
827
< 0 || x >	var m=this.getMinutes();
828
< 0 || x >	var s=this.getSeconds();
829
< 0 || x >	var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
830
< 0 || x >	// Convert real this parts into formatted versions
831
< 0 || x >	var value = new Object();
832
< 0 || x >	//if (y.length < 4) {y=''+(y-0+1900);}
833
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['Y'] = y.toString();
834
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['y'] = y.substring(2);
835
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['n'] = M;
836
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['m'] = LZ(M);
837
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['F'] = MONTH_NAMES[M-1];
838
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['M'] = MONTH_NAMES[M+11];
839
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['j'] = d;
840
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['d'] = LZ(d);
841
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['D'] = DAY_NAMES[E+7];
842
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['l'] = DAY_NAMES[E];
843
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['G'] = H;
844
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['H'] = LZ(H);
845
< 0 || x >< 4) {y=''+(y-0+1900);}
	if (H==0) {value['g']=12;}
846
< 0 || x >< 4) {y=''+(y-0+1900);}
	else if (H>12){value['g']=H-12;}
847
< 0 || x >< 4) {y=''+(y-0+1900);}
	else {value['g']=H;}
848
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['h']=LZ(value['g']);
849
< 0 || x >< 4) {y=''+(y-0+1900);}
	if (H > 11) {value['a']='pm'; value['A'] = 'PM';}
850
< 0 || x >< 4) {y=''+(y-0+1900);}
	else { value['a']='am'; value['A'] = 'AM';}
851
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['i']=LZ(m);
852
< 0 || x >< 4) {y=''+(y-0+1900);}
	value['s']=LZ(s);
853
< 0 || x >< 4) {y=''+(y-0+1900);}
	//construct the result string
854
< 0 || x >< 4) {y=''+(y-0+1900);}
	while (i_format < format.length) {
855
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
		c=format.charAt(i_format);
856
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
		token="";
857
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
858
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
			token += format.charAt(i_format++);
859
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
			}
860
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
		if (value[token] != null) { result=result + value[token]; }
861
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
		else { result=result + token; }
862
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
		}
863
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
	return result;
864
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
};
865
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
/*****************************************************************************/
866
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
Array.prototype.arrayIndex = function(searchVal,startIndex) //similar to array.indexOf() - created to fix IE deficiencies
867
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
{
868
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
	startIndex = (startIndex != null ? startIndex : 0); //default startIndex to 0, if not set
869
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
	for(var i=startIndex;i
870
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
871
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
872
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
873
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
874
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
875
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
876
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
877
< 0 || x >< 4) {y=''+(y-0+1900);}
< format.length) {
< format.length)) {
*****************************************************************************/