JSFiddle - React, Tailwind, and code Playground
by tonyleeper
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/1.4.1/less.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<h1>Date Selector POC</h1>
<br />
<section class="day-selector" data-bind="dateSelector: null">
<div class="row">
<div class="cell">
<button class="left" data-bind="click: selectPreviousDate"> <i class="triangle-left"></i> </button>
</div>
<div class="cell">
<ul tabindex="0" data-bind="foreach: dates,
onKeyLeftArrow: selectPreviousDate,
onKeyRightArrow: selectNextDate
">
<li>
<div class="date" data-bind="
css: {
'month-start': date === 1,
'selected': $root.isSelectedDate($data)
},
click: $root.selectDate.bind($root)
">
<div data-bind="text: month, visible: date === 1 || $root.isSelectedDate($data)"></div>
<div data-bind="text: date"></div>
</div>
</li>
</ul>
</div>
<div class="cell">
<button class="right" data-bind="click: selectNextDate"> <i class="triangle-right"></i> </button>
</div>
</div>
</section>
<br />
<p data-bind="text: 'The selected date is ' + selectedDate().date + ' ' + selectedDate().month"></p>
<div class="dragTest" data-bind="dragTest: null"></div>
CSS
@height: 27px;
html, body {
height: 100%;
padding: 5px;
cursor: default;
}
* {
box-sizing: border-box;
-webkit-user-select: none;
padding: 0;
margin: 0;
}
.day-selector {
width: 100%;
min-width: 800px;
display: table;
table-layout: fixed;
font-family: arial;
font-size: 11px;
color: white;
font-weight: bold;
-webkit-transform: translateZ(0); /* speed hack */
}
.row {
display: table-row;
height: 100%;
}
.cell {
display: table-cell;
vertical-align: middle;
}
.cell:first-child, .cell:last-child {
width: 30px;
}
button {
width: 100%;
height: @height;
border: 1px solid #aaa;
background: -webkit-linear-gradient(top, #f4f4f4 4%, #e2e2e2 4%, #e2e2e2 96%, #d6d6d6 96%);
position: relative;
}
button.left {
border-radius: 0;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
}
button.right {
border-radius: 0;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
.date {
border: 0;
border-top: 1px solid #aaa;
border-bottom: 1px solid #aaa;
height: @height;
text-align: center;
background-color: #878787;
box-shadow: inset 0 1px 0 0 #454545, inset 0 -1px 0 0 #454545;
}
.date.month-start {
border-left: 1px solid #aaa;
box-shadow: inset 1px 0 0 0 #454545, inset 0 1px 0 0 #454545, inset 0 -1px 0 0 #454545;
}
li:first-child > .date {
box-shadow: inset 1px 0 0 0 #454545, inset 0 1px 0 0 #454545, inset 0 -1px 0 0 #454545;
border-left: 0;
}
li:last-child > .date {
box-shadow: inset -1px 0 0 0 #454545, inset 0 1px 0 0 #454545, inset 0 -1px 0 0 #454545;
}
li > .date.selected {
background-color: #e2e2e2;
color: black;
text-shadow: 0 1px #fff;
box-shadow: 0 7px 10px -10px #262c39, inset 0 -1px 0 0 #d6d6d6, inset 0 1px 0 0 #f4f4f4;
cursor: ew-resize;
border-left: 1px solid #878787;
border-right: 1px solid #878787;
&:hover {
background-color: #f4f4f4;
...
JavaScript
/**
Date Selector POC
*/
// LESS SHIM
(function () {
$('head style[type="text/css"]').attr('type', 'text/less');
less.refreshStyles();
}());
ko.keyBindings = [{
keyCode: 37,
binding: "onKeyLeftArrow"
}, {
keyCode: 38,
binding: "onKeyUpArrow"
}, {
keyCode: 39,
binding: "onKeyRightArrow"
}, {
keyCode: 40,
binding: "onKeyDownArrow"
}, {
keyCode: 13,
binding: "onKeyEnter"
}, {
keyCode: 32,
binding: "onKeySpace"
}, {
keyCode: 8,
binding: "onKeyBackspace"
}];
for (var i = 0; i < ko.keyBindings.length; i++) {
ko.bindingHandlers[ko.keyBindings[i].binding] = (function () {
var keyCode = ko.keyBindings[i].keyCode;
var binding = ko.keyBindings[i].binding;
return {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
element.addEventListener("keydown", function (event) {
if (event.keyCode === keyCode) {
allBindingsAccessor()[binding].call(viewModel);
event.preventDefault();
}
});
}
};
}());
}
(function($){
$.fn.draggable = function(onDrag) {
return this.each(function () {
var $this = $(this);
var element = this;
var $document = $(document);
$this.on("mousedown touchstart", function(event){
element.dragging = true;
// prevent scrolling on touch devices
if (event.type === 'touchstart') {
event.preventDefault();
}
});
$document.on("mouseup touchend", function () {
element.dragging = false;
});
$document.on("mousemove touchmove", function(event){
if (element.dragging){
// throttle drag events to 60 per second
...