The purpose of the application is to show dates. The inputs are weekdays and weeks. Or alternative days as an integer.
Example:
Present me the Friday in 5 weeks!
Or
Present me the date of the day in 100 days!
// Global object on which everything else
// becomes attached.
var oo = {};
Object.defineProperty(oo, 'MILLI_SECONDS_DAY', {
value: 24 * 60 * 60 * 1000
});
Object.defineProperty(oo, 'DURATION_ANIMATION', {
value: 580
});
oo.elements = [];
oo.resultDate = document.getElementById('result-date');
oo.setDays = document.getElementById('set-days');
oo.elements[0] = document.getElementById('set-day');
oo.elements[1] = document.getElementById('set-weeks');
oo.radioControls = document.querySelectorAll('.radio-control');
oo.dateSelects = document.querySelectorAll('.date-select');
// Triggered by change of a radio-button.
// Disable all input- and select-elements except the
// elements in the chosen fieldset.
oo.toggleDisable = function() {
// The main parent node of the choosen fieldset.
var fieldset = this.parentNode.parentNode;
// The all input elements within it.
var selects = fieldset.querySelectorAll('.date-select');
// Disable all input elements.
Array.prototype.forEach.call(oo.dateSelects, function(dateSelect) {
if (!dateSelect.disabled) {
dateSelect.setAttribute('disabled', 'disabled');
dateSelect.parentNode.classList.remove('active-select');
}
});
// Re-Enable all inputs in the current chosen fieldset.
Array.prototype.forEach.call(selects, function(select) {
if (select.disabled && select !== this) {
select.removeAttribute('disabled');
select.parentNode.classList.add('active-select');
}
});
}
// Attach the function to the radio-buttons.
Array.prototype.forEach.call(oo.radioControls, function(radioControl) {
radioControl.addEventListener('change', oo.toggleDisable);
});
// Delete the value of the result text-input when
// a mouse-click occurs.
// -- Paremeter -----------------------------------------
// (Element) Object - The clicked control.
oo.deleteLastResult = function(control) {
control.addEventListener('mousedown', function() {
oo.resultDate.value = '';
});
}
// ---- Start - Attach the date-calculation method to the
// select-elements. -------------------------------------
for (var i = 0; i < oo.elements.length; i++) {
oo.deleteLastResult(oo.elements[i]);
oo.elements[i].addEventListener('change', function() {
oo.resultDate.value =
oo.getDayMonthYearDate(
oo.getDateBeforeIn(oo.elements[0].value,
oo.elements[1].value));
oo.playAnimation();
});
}
oo.setDays.addEventListener('change', function() {
oo.deleteLastResult(oo.setDays);
oo.resultDate.value =
oo.getDayMonthYearDate(
oo.getDateBeforeInDays(oo.setDays.value));
oo.playAnimation();
});
// Triggers the animation on the text input
// with the result.
oo.playAnimation = function() {
oo.resultDate.classList.add('result-present');
setTimeout(function() {
oo.resultDate.classList.remove('result-present');
}, oo.DURATION_ANIMATION);
}
// ---- End - Attach the date-calculation method -----------
// Fills a select-element with options.
// -- Parameter --------------------------------------------
// 1. (Element) Object - Select on which the options are
// appended.
// 2. Number - Number to start with.
// 3. Number - Upper limit (simultaneously last number to include).
oo.setOptions = function(selectElement, countOptionsStart, countOptionsEnd) {
for (var i = countOptionsStart; i <= countOptionsEnd; i++) {
var option = document.createElement('option');
var optionInner = document.createTextNode(i);
option.setAttribute('value', i);
if (i === 0) option.setAttribute('selected', 'selected');
option.appendChild(optionInner);
selectElement.appendChild(option);
}
}
oo.setOptions(oo.elements[1], -52, 52);
oo.setOptions(oo.setDays, -365, 365);
// Returns a Date Object which contains
// the date before/in n-days and
// before/in n-weeks.
// -- Parameter ----------------------------
// 1. String - The desired weekday as an
// abbreviation.
// Assign for ...
// Monday : 'mo'
// Tuesday : 'tu'
// Wednesday : 'we'
// Thursday : 'th'
// Friday : 'fr'
// Saturday : 'sa'
// Sunday : 'su'
// 2. Number - Positive number => n-weeks in
// the future.
// Negative number => n-weeks before.
// -- Return -------------------------------
// (Date) Object
oo.getDateBeforeIn = function(day, weeks) {
var currentDate = new Date();
var currentStamp = Date.now();
var weekdays = {
'mo': 1,
'tu': 2,
'we': 3,
'th': 4,
'fr': 5,
'sa': 6,
'su': 0
}
currentStamp += weeks * 7 * oo.MILLI_SECONDS_DAY;
currentStamp +=
(weekdays[day] - currentDate.getDay()) *
oo.MILLI_SECONDS_DAY;
return new Date(currentStamp);
}
oo.getDateBeforeInDays = function(days) {
var currentDate = new Date();
var currentStamp = Date.now();
currentStamp += days * oo.MILLI_SECONDS_DAY;
return new Date(currentStamp);
}
// Returns the Day, Month, Year of an
// JavaScript Date Object as as String
// in the Date format DMY.
// -- Parameter ----------------------------
// 1. Date-Object
// 2. String - Is used for separating
// Day-Year and Month-Year.
// -- Return -------------------------------
// String
oo.getDayMonthYearDate = function(dateObject, separator) {
separator = separator || '.';
return oo.getZeroPaddedNumber(dateObject.getDate(), 2) +
separator +
oo.getZeroPaddedNumber((dateObject.getMonth() + 1), 2) +
separator + dateObject.getFullYear();
}
oo.getZeroPaddedNumber = function(someNumber, desiredLength) {
someNumber = '00' + someNumber;
return someNumber.slice(desiredLength * -1);
}
body {
font-family: tahoma, helvetica, sans-serif;
background-color: rgba(245, 245, 245, 1.0);
}
#wrap {
max-width: 1000px;
width: 100%;
margin: 0 auto;
}
input,
select,
label {
margin: 10px;
}
input,
select {
font-family: tahoma;
padding: 0 4px 2px;
border-radius: 4px;
}
#form-set-date {
padding: 10px 20px;
background: linear-gradient(135deg, rgba(250, 250, 250, 1.0), rgba(220, 220, 220, 1.0));
border: 1px solid rgba(100, 100, 100, 0.6);
border-radius: 12px;
box-shadow: 1px 1px 3px rgba(200, 200, 200, 1.0);
}
.control-element {
margin: 10px 0;
height: 40px;
width: 300px;
background-color: rgba(250, 250, 250, 1.0);
border: 1px solid rgba(100, 100, 100, 0.5);
border-radius: 9px;
display: inline-block;
box-shadow: 1px 1px 1px rgba(100, 100, 100, 1.0);
text-shadow: 1px 1px 3px rgba(210, 210, 210, 1.0);
}
.active-select:hover {
border: 1px solid rgba(0, 180, 180, 1.0);
box-shadow: 0 0 4px rgba(0, 220, 220, 1.0);
}
.control-element label {
display: inline-block;
width: 100px;
}
.control-element .long-label {
width: 180px;
}
.read-only[disabled=disabled] {
background-color: rgba(255, 255, 255, 1.0);
color: rgba(0, 0, 0, 1.0);
text-align: center;
}
input[type=radio] {
width: 10px;
}
input[type=text],
select {
width: 110px;
}
fieldset:nth-of-type(n + 2) {
margin-top: 20px;
}
fieldset {
border: 1px solid rgba(100, 100, 100, 0.6);
background-color: rgba(240, 240, 240, 1.0);
box-shadow: 1px 1px 3px rgba(200, 200, 200, 1.0);
border-radius: 15px;
}
p {
font-family: georgia, serif;
}
p {
font-size: 1.2em;
padding-left: 5%;
text-shadow: 1px 1px 3px rgba(210, 210, 210, 1.0);
}
.result-present {
animation: expandShadow 0.6s 1;
}
@keyframes expandShadow {
0% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0);
}
10% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.2);
}
20% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.4);
}
30% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.6);
}
40% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.8);
}
50% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 1.0);
}
60% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.8);
}
70% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.6);
}
80% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.4);
}
90% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.2);
}
100% {
box-shadow: inset 0 0 20px rgba(0, 180, 180, 0.0);
}
}
<div id="wrap">
<p>Calculate date back or forward by defining weekday and weeks or days</p>
<form method="" action="" id="form-set-date">
<fieldset>
<div class="control-element active-select">
<input type="radio" id="by-days-weeks" value="daysWeeks" class="radio-control" checked="checked" name="radio-control" />
<label for="by-days-weeks" class="radio-label long-label">By weekday and week(s)</label>
</div>
<div class="control-element active-select">
<label>Weekday:</label>
<select id="set-day" class="date-select">
<option value="mo">Monday</option>
<option value="tu">Tuesday</option>
<option value="we">Wednesday</option>
<option value="th">Thursday</option>
<option value="fr">Friday</option>
<option value="sa">Saturday</option>
<option value="su">Sunday</option>
</select>
</div>
<div class="control-element active-select">
<label>Week(s):</label>
<select id="set-weeks" class="date-select"></select>
</div>
</fieldset>
<fieldset>
<div class="control-element active-select">
<input type="radio" id="by-days" value="days" class="radio-control" name="radio-control" />
<label for="by-days" class="radio-label">By days</label>
</div>
<div class="control-element">
<label>Days:</label>
<select id="set-days" class="date-select" disabled="disabled"></select>
</div>
</fieldset>
<fieldset>
<div class="control-element">
<label>Result:</label>
<input type="text" class="read-only" id="result-date" disabled="disabled" />
</div>
</fieldset>
</form>
</div>
Feedback & hints (concerning weaknesses) welcome.