Last active
December 24, 2015 14:09
-
-
Save leftclickben/6810286 to your computer and use it in GitHub Desktop.
Knockout date selector - use three `<select>` elements and compute a date, also restrict date within certain range
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
<!doctype html> | |
<html> | |
<head> | |
<title>Knockout Date Selector</title> | |
</head> | |
<body style="background-color:#eee;font-family:sans-serif;"> | |
<article style="width:600px;background-color:#fff;margin:1em auto;border:1px solid #000;padding:1em;"> | |
<h1>Knockout Date Selector</h1> | |
<p> | |
Date of birth: | |
<select data-bind="value: dateOfBirthDay, options: dateOfBirthDayOptions, optionsCaption: ' '"></select> / | |
<select data-bind="value: dateOfBirthMonth, options: dateOfBirthMonthOptions, optionsText: 'name', optionsValue: 'value', optionsCaption: ' '"></select> / | |
<select data-bind="value: dateOfBirthYear, options: dateOfBirthYearOptions, optionsCaption: ' '"></select> | |
</p> | |
<p>Date of birth (Y-M-D): <strong data-bind="text: dateOfBirthText"></strong><strong style="color:red" data-bind="visible: dateOfBirthUnset">You have not set your date of birth</strong></p> | |
<p>Earliest valid: <strong data-bind="text: earliestValidDateOfBirthText"></strong></p> | |
<p>Latest valid: <strong data-bind="text: latestValidDateOfBirthText"></strong></p> | |
</article> | |
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script> | |
<script type="text/javascript"> | |
(function (ko) { | |
var AppViewModel = function() { | |
var year, | |
now = new Date(), | |
earliestValidDateOfBirth = new Date(now.getFullYear() - 84 - (now.getMonth() < 6 ? 1 : 0), ((now.getMonth() + 6) % 12), now.getDate()), | |
latestValidDateOfBirth = new Date(now.getFullYear() - 18, now.getMonth(), now.getDate()), | |
allDays = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 ], | |
allMonths = [ | |
{ name: 'Jan', value: '0' }, | |
{ name: 'Feb', value: '1' }, | |
{ name: 'Mar', value: '2' }, | |
{ name: 'Apr', value: '3' }, | |
{ name: 'May', value: '4' }, | |
{ name: 'Jun', value: '5' }, | |
{ name: 'Jul', value: '6' }, | |
{ name: 'Aug', value: '7' }, | |
{ name: 'Sep', value: '8' }, | |
{ name: 'Oct', value: '9' }, | |
{ name: 'Nov', value: '10' }, | |
{ name: 'Dec', value: '11' } | |
], | |
pad = function (value, length) { | |
value = value.toString(); | |
while (value.length < length) { | |
value = '0' + value; | |
} | |
return value; | |
}; | |
// Watch the input fields | |
this.dateOfBirthDay = ko.observable(); | |
this.dateOfBirthMonth = ko.observable(); | |
this.dateOfBirthYear = ko.observable(); | |
// Dynamically compute the options available in the input fields | |
this.dateOfBirthDayOptions = ko.computed(function () { | |
if (this.dateOfBirthYear() <= earliestValidDateOfBirth.getFullYear() && this.dateOfBirthMonth() <= earliestValidDateOfBirth.getMonth()) { | |
return allDays.slice(earliestValidDateOfBirth.getDate() - 1); | |
} else if (this.dateOfBirthYear() >= latestValidDateOfBirth.getFullYear() && this.dateOfBirthMonth() >= latestValidDateOfBirth.getMonth()) { | |
return allDays.slice(0, latestValidDateOfBirth.getDate()); | |
} else { | |
return allDays; | |
} | |
}, this); | |
this.dateOfBirthMonthOptions = ko.computed(function () { | |
if (this.dateOfBirthYear() <= earliestValidDateOfBirth.getFullYear()) { | |
return allMonths.slice(earliestValidDateOfBirth.getMonth()); | |
} else if (this.dateOfBirthYear() >= latestValidDateOfBirth.getFullYear()) { | |
return allMonths.slice(0, latestValidDateOfBirth.getMonth() + 1); | |
} else { | |
return allMonths; | |
} | |
}, this); | |
this.dateOfBirthYearOptions = ko.computed(function () { | |
var year, years = []; | |
for (year=earliestValidDateOfBirth.getFullYear(); year<=latestValidDateOfBirth.getFullYear(); year++) { | |
years.push(year); | |
} | |
return years; | |
}, this); | |
// Display the earliest and latest date | |
this.earliestValidDateOfBirthText = ko.computed(function () { | |
return earliestValidDateOfBirth.getFullYear() + '-' + pad(earliestValidDateOfBirth.getMonth() + 1, 2) + '-' + pad(earliestValidDateOfBirth.getDate(), 2); | |
}, this); | |
this.latestValidDateOfBirthText = ko.computed(function () { | |
return latestValidDateOfBirth.getFullYear() + '-' + pad(latestValidDateOfBirth.getMonth() + 1, 2) + '-' + pad(latestValidDateOfBirth.getDate(), 2); | |
}, this); | |
// Display the selected date or error message | |
this.dateOfBirthUnset = ko.computed(function() { | |
return this.dateOfBirthDay() === undefined || this.dateOfBirthMonth() === undefined || this.dateOfBirthYear() === undefined; | |
}, this); | |
this.dateOfBirthText = ko.computed(function() { | |
// Ensure that all the input values are up to date | |
this.dateOfBirthDay.valueHasMutated(); | |
this.dateOfBirthMonth.valueHasMutated(); | |
this.dateOfBirthYear.valueHasMutated(); | |
// Determine the text value | |
return this.dateOfBirthUnset() ? '' : this.dateOfBirthYear() + '-' + pad(parseInt(this.dateOfBirthMonth(), 10) + 1, 2) + '-' + pad(this.dateOfBirthDay(), 2); | |
}, this); | |
} | |
ko.applyBindings(new AppViewModel()); | |
}(ko)); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment