Calendar Slider
by samih
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<div style="width: 800px;margin: 100px auto; background-color: #FFF;border-radius: 10px;padding: 5px;border: 1px solid lightgray;">
<div>
<label data-bind="text: 'Slider - range ' + CONSTANTS.SLIDER_MIN + ' - ' + CONSTANTS.SLIDER_MAX + ' days'" >
</label>
</div>
<div class="slider-container" data-bind="uiSlider: true"></div>
<div class="table-container">
<div class="timeline-header months" data-bind="visible: daysRange() > CONSTANTS.WEEK_DAY_MAX,
style: {'width': 31*4*widthRatio() + 'px'},
foreach: months,
labelSwitch: daysRange(),
offsetPosition: daysRange()">
<div>
<span data-bind="text: $data.long" class="long"></span>
<span data-bind="text: $data.short" class="short"></span>
</div>
</div>
<div class="timeline-header weeks" data-bind="visible: daysRange() >= CONSTANTS.SLIDER_MIN,
style: {'width': (CONSTANTS.SLIDER_MAX/7 + 1) * 7 * widthRatio() + 'px'},
foreach: weeks,
labelSwitch: daysRange(),
offsetPosition: daysRange()">
<div>
<span data-bind="text: $data.long" class="long"></span>
<span data-bind="text: $data.short" class="short"></span>
</div>
</div>
<div class="timeline-header days" data-bind="visible: daysRange() <= CONSTANTS.WEEK_DAY_MAX,
...
CSS
.slider-container {
margin: 40px;
}
.table-container {
overflow: hidden;
}
.timeline-header {
display: table;
table-layout: fixed;
border-collapse: collapse;
border-spacing: 0;
width: 99%;
text-align: center;
border: 1px solid black;
position: relative;
}
.timeline-header > div {
display: table-cell;
border: 1px dotted gray;
overflow: hidden;
white-space: nowrap;
}
.short {
display: none;
}
.timeline-body {
height: 300px;
background-color: #FDFDFD;
position: relative;
}
.event {
position: absolute;
height: 10px;
background-color: #0000FF;
border-radius: 5px;
}
JavaScript
//constants
window.CONSTANTS = {
SLIDER_MAX: 120,
SLIDER_MIN: 0,
WEEK_DAY_MAX: 28,
MONTH_NAMES: [{long: "January", short: "Jan"},
{long: "February", short: "Feb"},
{long: "March", short: "Mar"},
{long: "April", short: "Apr"},
{long: "May", short: "May"},
{long: "June", short: "Jun"},
{long: "July", short: "Jul"},
{long: "August", short: "Aug"},
{long: "September", short: "Sep"},
{long: "October", short: "Oct"},
{long: "November", short: "Nov"},
{long: "December", short: "Dec"}],
DAY_NAMES: [{long: "Sunday", short: "S"},
{long: "Monday", short:"M"},
{long: "Tuesday", short: "T"},
{long: "Wednesday", short: "W"},
{long: "Thursday", short: "T"},
{long: "Friday", short: "F"},
{long: "Saturday", short: "S"}]
};
//custom knockout bindings
ko.bindingHandlers.uiSlider = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel){
//initialize the slider UI element
$(element).slider({
animate: "fast",
max: CONSTANTS.SLIDER_MAX,
min: CONSTANTS.SLIDER_MIN,
range: true,
values: [CONSTANTS.SLIDER_MIN, CONSTANTS.SLIDER_MAX],
slide: function(event, ui){
viewModel.rangeValues[0](ui.values[0]);
viewModel.rangeValues[1](ui.values[1]);
}
});
}
};
ko.bindingHandlers.labelSwitch = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var $tableCells = $(element).children('div');
var $longNameElements = $tableCells.children('.long');
var $shortNameElements = $tableCells.children(' .short');
var firstContainer = $tableCells[0];
...