calendar/calendar.js

302 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* Calendar Script
* Creates a calendar widget which can be used to select the date more easily than using just a text box
*
* Original: http://www.openjs.com/scripts/ui/calendar/
* Modified: http://svn.yourcmc.ru/viewvc.py/vitaphoto/js/{util.js,calendar.js,calendar.css}
* (uses addListener() and getOffset() from util.js)
* Version: 2017-05-03
* License: MIT-like, http://www.openjs.com/license.php
*
* Example:
* <input type="text" name="date" id="date" />
* <script type="text/javascript">
* Calendar.set("date");
* </script>
*/
if (!window.Calendar) {
window.Calendar = {
// Configuration:
month_names: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],
close_label: 'Закрыть',
weekdays: ["Пн","Вт","Ср","Чт","Пт","Сб","Вс"],
sunday: 6,
selectboxes: false, // true: use selectboxes for year and month, false: show months and years in table
years: {min: -70, max: 10}, // range of displayed years if selectboxes==true
format: 'd.m.Y', // either d.m.Y or Y-m-d, other formats are not supported
// State variables:
month_days: [31,28,31,30,31,30,31,31,30,31,30,31],
// Today's date
today: new Date(),
// Selected date
selected: new Date(),
opt: {},
data: [],
addedListener: false,
//Functions
/// Used to create HTML in a optimized way.
wrt:function(txt) {
this.data.push(txt);
},
fin:function() {
this.wrt("<a class='calendar-cancel' onclick='Calendar.hideCalendar();'>"+this.close_label+"</a>");
document.getElementById(this.opt['calendar']).innerHTML = this.data.join("");
this.data = [];
},
/// Called when the user clicks on a date in the calendar.
selectDate:function(year,month,day) {
var i = this.opt["input"];
var t = i.value.split(/\s+/, 2)[1]||'';
if (t)
t = ' '+t;
i.value = (this.format == 'Y-m-d' ? year + '-' + month + '-' + day : day + '.' + month + '.' + year) + t;
this.hideCalendar();
},
showMonths:function(year, month) {
var cur_y = this.today.getFullYear();
var cur_m = this.today.getMonth();
var sel_m = this.selected.getFullYear() == year ? this.selected.getMonth() : -1;
this.wrt("<table>");
this.wrt("<tr><th colspan='4' class='calendar-title'><a href='javascript:Calendar.showMonths("+(year-1)+")' title='"+(year-1)+"' class='prev'></a>");
this.wrt(" <a href='javascript:Calendar.showYears("+year+")'>"+year+"</a>");
this.wrt(" <a href='javascript:Calendar.showMonths("+(year+1)+")' title='"+(year+1)+"' class='next'></a></th></tr>");
this.wrt("<tr>");
for (var i in this.month_names) {
if (i && !(i % 3))
this.wrt("</tr><tr>");
var class_name = (year < cur_y || year == cur_y && i < cur_m ? 'past' :
(year > cur_y || year == cur_y && i > cur_m ? 'future' : 'today'))
+ (i == sel_m ? ' selected' : '');
this.wrt("<td class='months "+class_name+"'><a href='javascript:Calendar.makeCalendar("+year+","+i+")'>"+this.month_names[i]+"</a></td>");
}
this.wrt("</tr>");
this.wrt("</table>");
this.fin();
},
showYears:function(year) {
var beg = year & ~15;
var cur_y = this.today.getFullYear();
var sel_y = this.selected.getFullYear();
this.wrt("<table>");
this.wrt("<tr><th colspan='4' class='calendar-title'>");
this.wrt(" <a href='javascript:Calendar.showYears("+(year-16)+");' title='"+(beg-16)+" - "+(beg-1)+"' class='prev'></a>");
this.wrt(" <b>"+beg+" - "+(beg+15)+"</b>");
this.wrt(" <a href='javascript:Calendar.showYears("+(year+16)+");' title='"+(beg+16)+" - "+(beg+31)+"' class='next'></a>");
this.wrt("</th></tr>");
this.wrt("<tr>");
for (var i = 0; i < 16; i++) {
if (i && !(i % 4))
this.wrt("</tr><tr>");
var class_name = (beg+i < cur_y ? 'past' : (beg+i > cur_y ? 'future' : 'today'))
+ (beg+i == sel_y ? ' selected' : '');
this.wrt("<td class='years "+class_name+"'><a href='javascript:Calendar.showMonths("+(beg+i)+")'>"+(beg+i)+"</a></td>");
}
this.wrt("</tr>");
this.wrt("</table>");
this.fin();
},
/// Creates a calendar with the date given in the argument as the selected date.
makeCalendar:function(year, month) {
// Display the table
var next_month = month+1;
var next_month_year = year;
if (next_month >= 12) {
next_month = 0;
next_month_year++;
}
var previous_month = month-1;
var previous_month_year = year;
if (previous_month < 0) {
previous_month = 11;
previous_month_year--;
}
var current_year = this.today.getFullYear();
this.wrt("<table>");
this.wrt("<tr><th colspan='7' class='calendar-title'><a href='javascript:Calendar.makeCalendar("+previous_month_year+","+previous_month+");' title='"+this.month_names[previous_month]+" "+(previous_month_year)+"' class='prev'></a>");
if (!this.selectboxes) {
this.wrt(" <a href='javascript:Calendar.showMonths("+year+", "+month+")'>"+this.month_names[month]+"</a>");
this.wrt(" <a href='javascript:Calendar.showYears("+year+")'>"+year+"</a>");
} else {
this.wrt(" <select name='calendar-month' class='calendar-month' onChange='Calendar.makeCalendar("+year+",this.value);'>");
for (var i in this.month_names) {
this.wrt("<option value='"+i+"'");
if (i == month) this.wrt(" selected='selected'");
this.wrt(">"+this.month_names[i]+"</option>");
}
this.wrt("</select>");
this.wrt("<select name='calendar-year' class='calendar-year' onChange='Calendar.makeCalendar(this.value, "+month+");'>");
for (var i = current_year+this.years.min; i < current_year+this.years.max; i++) {
this.wrt("<option value='"+i+"'")
if (i == year) this.wrt(" selected='selected'");
this.wrt(">"+i+"</option>");
}
this.wrt("</select>");
}
this.wrt(" <a href='javascript:Calendar.makeCalendar("+next_month_year+","+next_month+");' title='"+this.month_names[next_month]+" "+next_month_year+"' class='next'></a></th></tr>");
this.wrt("<tr class='header'>");
for (var weekday = 0; weekday < 7; weekday++)
this.wrt("<td>"+this.weekdays[weekday]+"</td>");
this.wrt("</tr>");
// Get the first day of this month
var first_day = new Date(year,month,1);
var start_day = (first_day.getDay()+Calendar.sunday)%7;
var d = 1;
var flag = 0;
// Leap year support
if (!(year % 4) && ((year % 100) || !(year % 400)))
this.month_days[1] = 29;
else
this.month_days[1] = 28;
var days_in_this_month = this.month_days[month];
// Create the calendar
var yea = this.today.getFullYear();
var all_diff = (year - yea) || (month - this.today.getMonth());
var sel_day = year == this.selected.getFullYear() && month == this.selected.getMonth() ? this.selected.getDate() : -1;
for (var i = 0; i <= 5; i++) {
if (w >= days_in_this_month)
break;
this.wrt("<tr>");
for (var j = 0; j < 7; j++) {
if (d > days_in_this_month)
flag = 0; // If the days has overshooted the number of days in this month, stop writing
else if (j >= start_day && !flag)
flag = 1; // If the first day of this month has come, start the date writing
if (flag) {
var w = d, mon = month+1;
if (w < 10)
w = "0" + w;
if (mon < 10)
mon = "0" + mon;
// Is it today?
var class_name = '';
var diff = all_diff || (d - this.today.getDate());
if (diff < 0)
class_name = ' past';
else if (!diff)
class_name = ' today';
else
class_name = ' future';
if (d == sel_day)
class_name += ' selected';
class_name += " " + this.weekdays[j].toLowerCase();
this.wrt("<td class='days"+class_name+"'><a href='javascript:Calendar.selectDate(\""+year+"\",\""+mon+"\",\""+w+"\")'>"+d+"</a></td>");
d++;
}
else
this.wrt("<td class='days'>&nbsp;</td>");
}
this.wrt("</tr>");
}
this.wrt("</table>");
this.fin();
},
/// Display the calendar - if a date exists in the input box, that will be selected in the calendar.
showCalendar: function() {
var input = this.opt['input'];
//Position the div in the correct location...
var div = document.getElementById(this.opt['calendar']);
var xy = getOffset(input);
var width = input.clientWidth||input.offsetWidth;
var height = input.clientHeight||input.offsetHeight;
div.style.left = (xy.left-1)+"px";
div.style.top = (xy.top+height-1)+"px";
// Show the calendar with the date in the input as the selected date
this.selected = new Date();
var date_in_input = input.value.replace(/\s+.*$/, ''); //Remove time
if(date_in_input) {
// date format is HARDCODE
var selected_date = false;
var date_parts = date_in_input.split("-");
if (date_parts.length == 3) {
// Y-m-d
date_parts[1]--; //Month starts with 0
selected_date = new Date(date_parts[0], date_parts[1], date_parts[2]);
} else if (date_parts.length == 1) {
date_parts = date_in_input.split('.');
if (date_parts.length == 3) {
// d.m.Y
date_parts[1]--; //Month starts with 0
selected_date = new Date(date_parts[2], date_parts[1], date_parts[0]);
}
}
if (selected_date && !isNaN(selected_date.getFullYear())) { //Valid date.
this.selected = selected_date;
}
}
this.makeCalendar(this.selected.getFullYear(), this.selected.getMonth());
document.getElementById(this.opt['calendar']).style.display = "block";
},
/// Hides the currently show calendar.
hideCalendar: function() {
document.getElementById(this.opt['calendar']).style.display = "none";
},
/// Setup a text input box to be a calendar box.
set: function(input_or_id) {
if (typeof input_or_id == 'string')
input_or_id = document.getElementById(input_or_id);
if (!input_or_id)
return; // If the input field is not there, exit.
if (!Calendar.opt['calendar'] || !document.getElementById(Calendar.opt['calendar']))
Calendar.init();
addListener(input_or_id, 'focus', function(ev) {
Calendar.opt['input'] = this;
Calendar.showCalendar();
});
},
/// Will be called once when the first input is set.
init: function() {
if(!this.opt['calendar'] || !document.getElementById(this.opt['calendar'])) {
var div = document.createElement('div');
if(!this.opt['calendar'])
this.opt['calendar'] = 'calender_div_'+ Math.round(Math.random() * 100);
div.setAttribute('id',this.opt['calendar']);
div.className="calendar-box";
addListener(div, "mousedown", function(ev) {
ev = ev || window.event;
if (ev.stopPropagation)
ev.stopPropagation();
else
ev.cancelBubble = true;
return true;
});
document.getElementsByTagName("body")[0].insertBefore(div,document.getElementsByTagName("body")[0].firstChild);
if (!Calendar.addedListener) {
addListener(document, "mousedown", function() { Calendar.hideCalendar(); });
Calendar.addedListener = true;
}
}
}
}
}