Simple JQuery Calendar Widget using moment.js
A Pen by James Barnett on CodePen.
<h1>Simple Calendar Widget</h1> | |
<div class = "wrapper"> | |
<label for = "date">Date:</label> | |
<input id = "date"/> | |
<span class = "calendar-icon"></span> | |
<div class = "calendar"> | |
<span class = "month-prev"></span> | |
<h2 id = "month" class = "month"></h2> | |
<span class = "month-next"></span> | |
<ol class = "weekdays"> | |
<li>Sun</li> | |
<li>Mon</li> | |
<li>Tue</li> | |
<li>Wed</li> | |
<li>Thu</li> | |
<li>Fri</li> | |
<li>Sat</li> | |
</ol> | |
<div id = "days" class = "days"></div> | |
</div> |
Simple JQuery Calendar Widget using moment.js
A Pen by James Barnett on CodePen.
$(document).ready(function() { | |
var timeframe = moment(); | |
var dayOfWeekOffset = 0; | |
var date = moment(); | |
drawCalendar(); | |
function drawCalendar(){ | |
var output = "<ol>"; | |
var days = moment(timeframe).daysInMonth(); | |
var monthName = moment(timeframe).format("MMMM"); | |
var startOfMonth = moment(timeframe).startOf('month'); | |
/* Find the day of the week the month starting on | |
so we can calculate the offset for days of the week to line up correctly */ | |
dayOfWeekOffset = parseInt(moment(startOfMonth).format("d"),10); | |
/* draw offset */ | |
for (i = 0; i < dayOfWeekOffset; i++) { | |
output += "<li>"; | |
output += "</li>"; | |
} | |
/*** draw days ***/ | |
for (i = 1; i <= days; i++) { | |
output += "<li>"; | |
output += i; | |
output += "</li>"; | |
} | |
output += "</ol>"; | |
document.getElementById("days").innerHTML = output; | |
monthName = moment(timeframe).format("MMMM YYYY"); | |
document.getElementById("month").innerHTML = monthName; | |
markToday(); | |
getSelectedDay(); | |
} | |
function getSelectedDay(){ | |
$(".days li").click(function() { | |
var myDay = $(this).text(); | |
/* make sure user clicked on an actual day not one of the offset boxes */ | |
if (!isNaN(parseInt(myDay, 10))){ | |
var myMonth = moment(timeframe).format("M"); | |
var myYear = moment(timeframe).format("YY"); | |
$("input").val(myMonth + "/" + myDay + "/" + myYear); | |
styleDateValidation(); | |
styleSelectedDay(); | |
} | |
}); | |
} | |
function markToday(){ | |
var dayOfMonth = moment().format("D"); | |
var today = dayOfWeekOffset + parseInt(dayOfMonth, 10); | |
/* because today is calculated using the day of month, double check it's the current month */ | |
if (moment(timeframe).isSame(moment(), 'month')){ | |
$( ".days li:nth-Child(" + today + ")" ).addClass( "today" ); | |
} | |
} | |
/* parse date from input field & re-draw calendar*/ | |
function parseDate(){ | |
var dateRaw = $("input").val(); | |
date = moment(dateRaw).format("YYYY-MM-DD"); | |
if(date !== "Invalid date"){ | |
timeframe = moment(date); | |
drawCalendar(); | |
styleSelectedDay(); | |
return true; | |
} else { return false; } | |
} | |
/* style input box to indicate a valid/invalid date */ | |
function styleDateValidation(){ | |
if (parseDate() === true) { | |
if ($("input").hasClass( "valid-date" ) !== true) { | |
$("input").addClass("valid-date"); | |
} | |
if ($("input").hasClass( "invalid-date" ) === true) { | |
$("input").removeClass("invalid-date"); | |
} | |
} else { | |
if ($("input").hasClass( "invalid-date" ) !== true) { | |
$("input").addClass("invalid-date"); | |
} | |
if ($("input").hasClass( "valid-date" ) === true) { | |
$("input").removeClass("valid-date"); | |
} | |
} | |
} | |
function styleSelectedDay(){ | |
var selectedDayRaw = moment(date).format("D"); | |
if (!isNaN(parseInt(selectedDayRaw, 10))){ | |
var selectedDay = dayOfWeekOffset + parseInt(selectedDayRaw, 10); | |
$( ".days li:nth-Child(" + selectedDay + ")" ).addClass( "selected-day" ); | |
} | |
} | |
$(".calendar-icon").click(function() { | |
$(".calendar").toggle(); | |
}); | |
$("input").click(function() { | |
$(".calendar").show(); | |
}); | |
$("input").keyup(function() { | |
styleSelectedDay(); | |
styleDateValidation(); | |
}); | |
/*** change month on calendar ***/ | |
$(".month-next").click(function() { | |
timeframe = moment(timeframe).add('M', 1).format("YYYY-MM-DD"); | |
drawCalendar(); | |
}); | |
$(".month-prev").click(function() { | |
timeframe = moment(timeframe).subtract('M', 1).format("YYYY-MM-DD"); | |
drawCalendar(); | |
}); | |
}); |
@import url(http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css); | |
ol, li { margin: 0; padding: 0; list-style: none; } | |
.wrapper { | |
width: 330px; | |
margin: 10px 40px; | |
} | |
h1 { | |
font-size: 1.5em; | |
margin-left: 20px; | |
} | |
label { margin: auto; } | |
input { margin: 0 0 10px 10px;} | |
.calendar { | |
display: none; | |
margin-left: 5px; | |
width: 255px; | |
color: #525252; | |
} | |
.days li:hover, .month-prev:hover, .month-next:hover, .calendar-icon { cursor: pointer; } | |
.month, .month-prev, .month-next, .calendar-icon { font-size: 1.125em; } | |
.month { | |
width: 185px; | |
display: inline-block; | |
margin: 0; | |
text-align: center; | |
} | |
.month-prev, .month-next, .calendar-icon { | |
font-family: FontAwesome; | |
padding: 3px; | |
display: inline-block; | |
} | |
.calendar-icon:before { | |
content: "\f073"; | |
margin-left: 5px; | |
} | |
.month-prev:before { | |
content: "\f0a8"; | |
margin-left: 5px; | |
} | |
.month-next:before { | |
content: "\f0a9"; | |
margin-right: 5px; | |
} | |
.weekdays li, .days li { | |
font-size: 13px; | |
text-align: center; | |
} | |
.weekdays li { | |
width: 20px; | |
padding: 0 6px 5px 3px; | |
margin-left: 2px; | |
display: inline-block; | |
} | |
.days li { | |
width: 20px; | |
height: 20px; | |
float: left; | |
padding: 5px 5px 5px 10px; | |
font-size: 13px; | |
font-family: Tahoma, Verdana, sans-serif; | |
font-weight: bold; | |
} | |
.days li:hover { | |
color: royalblue; | |
background: whitesmoke; | |
} | |
.today { | |
color: indianred; | |
background: whitesmoke; | |
} | |
/*** draw borders ***/ | |
.days li { | |
border-bottom: 1px solid darkgrey; | |
border-right: 1px solid darkgrey; | |
} | |
.days li:nth-child(-n+7) { border-top: 1px solid darkgrey; } | |
.days li:nth-child(7n+1) { border-left: 1px solid darkgrey; } | |
/*** valid/invalid date field ***/ | |
.valid-date { | |
outline: none; | |
border: 2px solid green; | |
} | |
.invalid-date { | |
outline: none; | |
border: 2px solid red; | |
} | |
.selected-day { | |
background: whitesmoke; | |
color: green; | |
} |