Created
May 22, 2015 16:22
-
-
Save jdavidbakr/b3ca1c63d596758b8af3 to your computer and use it in GitHub Desktop.
JavaScript: Calendar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This javascript draws a calendar object and updates the passed input elements with the value when a date is clicked. | |
*/ | |
var monthNames = [ | |
'Jan', | |
'Feb', | |
'Mar', | |
'Apr', | |
'May', | |
'Jun', | |
'Jul', | |
'Aug', | |
'Sep', | |
'Oct', | |
'Nov', | |
'Dec' | |
]; | |
var dayNames = [ | |
'Sun', | |
'Mon', | |
'Tue', | |
'Wed', | |
'Thu', | |
'Fri', | |
'Sat' | |
]; | |
var datepicker = { | |
visible: false, | |
selected_date: null, | |
visible_input: null, | |
hidden_input: null, | |
calendar: null, | |
clear_event: null, | |
current_view: null, | |
current_view_date: null, | |
header: null, | |
activate: function(event, input) { | |
if(this.visible) { | |
this.cancel(); | |
} | |
event.stopImmediatePropagation(); | |
this.visible = true; | |
this.visible_input = input; | |
this.hidden_input = document.getElementById(input.getAttribute('rel')); | |
if(this.visible_input.value) { | |
this.selected_date = new Date(this.visible_input.value); | |
} else { | |
this.selected_date = new Date(); | |
} | |
// Create the calendar object | |
this.calendar = document.createElement('div'); | |
this.calendar.setAttribute('class','datepicker'); | |
this.hidden_input.parentNode.insertBefore(this.calendar, this.hidden_input); | |
if(!this.clear_event) { | |
this.clear_event = this.cancel.bind(this); | |
} | |
// Initialize our view | |
this.current_view = 'days'; | |
this.current_view_date = new Date(this.selected_date); | |
// Draw the calendar | |
this.draw(); | |
// Add a click event to the document that closes our picker | |
document.addEventListener('click', this.clear_event); | |
// alert(this.selected_date); | |
return true; | |
}, | |
draw: function() { | |
// Clear any existing view | |
this.calendar.innerHTML = ''; | |
// Apply the header | |
this.header = document.createElement('div'); | |
this.header.setAttribute('class','header'); | |
this.calendar.appendChild(this.header); | |
var headerText; | |
switch(this.current_view) { | |
case 'days': | |
headerText = this.days_header(); | |
this.draw_days(); | |
break; | |
case 'months': | |
headerText = this.months_header(); | |
this.draw_months(); | |
break; | |
case 'years': | |
headerText = this.years_header(); | |
this.draw_years(); | |
break; | |
} | |
var title = document.createElement('div'); | |
this.header.appendChild(title); | |
title.setAttribute('class','title'); | |
var title_text = document.createElement('div'); | |
title_text.setAttribute('class','titleText'); | |
title_text.innerHTML = headerText; | |
title.appendChild(title_text); | |
title_text.addEventListener('click',this.change_view.bind(this)); | |
// Navigation | |
var previous = document.createElement('div'); | |
this.header.appendChild(previous); | |
previous.setAttribute('class','previous'); | |
previous.addEventListener('click', this.previous.bind(this)); | |
var next = document.createElement('div'); | |
this.header.appendChild(next); | |
next.setAttribute('class','next'); | |
next.addEventListener('click',this.next.bind(this)); | |
}, | |
days_header: function() { | |
return monthNames[this.current_view_date.getMonth()] + ' ' + (this.current_view_date.getFullYear()); | |
}, | |
months_header: function() { | |
return this.current_view_date.getFullYear(); | |
}, | |
years_header: function() { | |
var first_year = Math.floor(this.current_view_date.getFullYear()/20) * 20; | |
var last_year = first_year + 19; | |
return (first_year)+"-"+(last_year); | |
}, | |
draw_days: function() { | |
var table = document.createElement('table'); | |
table.setAttribute('class','days'); | |
this.calendar.appendChild(table); | |
var titles = document.createElement('tr'); | |
titles.setAttribute('class','titles'); | |
table.appendChild(titles); | |
for (var i = 0; i < dayNames.length; i++) { | |
var th = document.createElement('td'); | |
th.innerHTML = dayNames[i]; | |
th.setAttribute('class','day'); | |
titles.appendChild(th); | |
} | |
var current_date = new Date(this.current_view_date); | |
current_date.setDate(1); | |
var first_dow = current_date.getDay(); | |
current_date.setDate(1 - first_dow); | |
var week = 0; | |
var tr; | |
while(week <= 6) { | |
var dow = current_date.getDay(); | |
if(dow === 0) { | |
tr = document.createElement('tr'); | |
tr.setAttribute('class','week'); | |
table.appendChild(tr); | |
week++; | |
} | |
if(week <= 6) { | |
var td = document.createElement('td'); | |
var td_class = 'day'; | |
if(current_date.getMonth() != this.current_view_date.getMonth()) { | |
td_class += ' otherMonth'; | |
} | |
if(current_date.getFullYear() == this.selected_date.getFullYear() && | |
current_date.getDate() == this.selected_date.getDate() && | |
current_date.getMonth() == this.selected_date.getMonth()) { | |
td_class += ' selected'; | |
} | |
td.setAttribute('class',td_class); | |
td.setAttribute('date', current_date); | |
td.innerHTML = current_date.getDate(); | |
tr.appendChild(td); | |
current_date.setDate(current_date.getDate() + 1); | |
td.addEventListener('click',this.select_date.bind(this)); | |
} | |
} | |
}, | |
select_date: function(e) { | |
e.stopImmediatePropagation(); | |
var target = e.target; | |
var date = new Date(target.getAttribute('date')); | |
var actual_date = date.getFullYear()+'-'; | |
if(date.getMonth() < 9) { | |
actual_date += '0'; | |
} | |
actual_date += (date.getMonth()+1)+'-'; | |
if(date.getDate() < 10) { | |
actual_date += '0'; | |
} | |
actual_date += date.getDate(); | |
var pretty_date = (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear(); | |
this.hidden_input.value = actual_date; | |
this.visible_input.value = pretty_date; | |
this.cancel(); | |
}, | |
draw_months: function() { | |
var table = document.createElement('table'); | |
table.setAttribute('class','months'); | |
this.calendar.appendChild(table); | |
var tr; | |
for(var i = 0; i < monthNames.length; ++i) { | |
if(!i % 3) { | |
tr = document.createElement('tr'); | |
table.appendChild(tr); | |
} | |
var td = document.createElement('td'); | |
td.innerHTML = monthNames[i]; | |
var td_class = 'month'; | |
if(this.current_view_date.getFullYear() == this.selected_date.getFullYear() && | |
this.current_view_date.getMonth() == i) { | |
td_class += ' selected'; | |
} | |
td.setAttribute('class',td_class); | |
td.setAttribute('month',i); | |
td.addEventListener('click',this.select_month.bind(this)); | |
tr.appendChild(td); | |
} | |
}, | |
select_month: function(e) { | |
e.stopImmediatePropagation(); | |
var target = e.target; | |
var month = target.getAttribute('month'); | |
this.current_view_date.setDate(1); | |
this.current_view_date.setMonth(month); | |
this.current_view = 'days'; | |
this.draw(); | |
}, | |
draw_years: function() { | |
var first_year = Math.floor(this.current_view_date.getFullYear()/20) * 20; | |
var table = document.createElement('table'); | |
table.setAttribute('class','years'); | |
this.calendar.appendChild(table); | |
var tr; | |
for(var i = 0; i < 20; ++i) { | |
if(!i % 4) { | |
tr = document.createElement('tr'); | |
table.appendChild(tr); | |
} | |
var td = document.createElement('td'); | |
td.innerHTML = first_year + i; | |
var td_class ='year'; | |
if(first_year + i == this.selected_date.getFullYear()) { | |
td_class += ' selected'; | |
} | |
td.setAttribute('class',td_class); | |
td.setAttribute('year',first_year + i); | |
td.addEventListener('click',this.select_year.bind(this)); | |
tr.appendChild(td); | |
} | |
}, | |
select_year: function(e) { | |
e.stopImmediatePropagation(); | |
var target = e.target; | |
var year = target.getAttribute('year'); | |
this.current_view_date.setYear(year); | |
this.current_view = 'months'; | |
this.draw(); | |
}, | |
change_view: function(event) { | |
event.stopImmediatePropagation(); | |
switch(this.current_view) { | |
case 'days': | |
this.current_view = 'months'; | |
break; | |
case 'months': | |
this.current_view = 'years'; | |
break; | |
} | |
this.draw(); | |
}, | |
cancel: function() { | |
// Do what we need to do to clear the visible calendar | |
var parent = this.calendar.parentNode; | |
parent.removeChild(this.calendar); | |
this.visible = false; | |
document.removeEventListener('click', this.clear_event); | |
}, | |
previous: function(event) { | |
event.stopImmediatePropagation(); | |
this.navigate(-1); | |
this.draw(); | |
}, | |
next: function(event) { | |
event.stopImmediatePropagation(); | |
this.navigate(1); | |
this.draw(); | |
}, | |
navigate: function(amount) { | |
switch(this.current_view) { | |
case 'days': | |
this.current_view_date.setMonth(this.current_view_date.getMonth() + amount); | |
break; | |
case 'months': | |
this.current_view_date.setFullYear(this.current_view_date.getFullYear() + amount); | |
break; | |
case 'years': | |
this.current_view_date.setFullYear(this.current_view_date.getFullYear() + (amount * 20)); | |
break; | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment