JSFiddle - React, Tailwind, and code Playground
by levchenko_d
HTML
<div id="timesheet">
</div>
<script type="text/javascript">
var App=(function(){var notificationSound=new Audio('/sounds/notification.mp3');notificationSound.volume=0.2;Event.prototype.kill=function(){var e=this;e.stopPropagation();e.preventDefault()};function q(selector){return selector?document.querySelector(selector):{}};function elQ(selector){return this.querySelector(selector)}
Element.prototype.q=elQ;function qa(selector){return document.querySelectorAll(selector)}
function elQa(selector){return this.querySelectorAll(selector)}
Element.prototype.qa=elQa;function toDOM(HTMLstring){var div=document.createElement('div');div.innerHTML=HTMLstring;return div.childNodes};function unwrap(){var _this=this,parent=_this.parentNode,list=[];while(_this.firstChild){list.push(parent.insertBefore(_this.firstChild,_this))};parent.removeChild(_this);return list};Element.prototype.unwrap=unwrap;function prepend(object,unwrap){if(!isElement(object)){var div=document.createElement('div');div.innerHTML=object;this.insertBefore(div,this.childNodes[0]);if(unwrap){object=div.childNodes;div.unwrap()}else{object=div}}else{this.insertBefore(object,this.childNodes[0])}
return object};Element.prototype.prepend=prepend;function isFn(fn){if(fn&&typeof(fn)==='function'){return fn}else{return function(){return!1}}};function isElement(obj){return(typeof HTMLElement==="object"?obj instanceof HTMLElement:obj&&typeof obj==="object"&&obj!==null&&obj.nodeType===1&&typeof obj.nodeName==="string")};function getScrollTop(obj){if(obj===document.body){return document.documentElement.scrollTop||document.body.scrollTop}else{return obj.scrollTop}};function isHover(id){return q(id)===q(id+':hover')};function parseIntSafe(n){return parseInt(n)||0};function viewportHeight(){return Math.max(parseIntSafe(document.documentElement.clientHeight),parseIntSafe(window.innerHeight)||0)+'px'};function viewportWidth(){return...
CSS
body{
background: #fff;
}
.timesheet-hour {
position: relative;
height: 40px;
margin-bottom: 20px;
}
.timesheet-hour-label {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 20px;
text-align: center;
line-height: 40px;
color: silver;
}
.timesheet-dec-wrapper{
margin-left: 30px;
}
.timesheet-dec-wrapper:before,
.timesheet-dec-wrapper:after{
content: '';
display: table;
clear: both;
}
.timesheet-dec{
float: left;
width:16.666666666666668%;
height: 40px;
text-align: center;
}
.timesheet-dec-content{
height: 30px;
margin: 5px 0;
background: #2C9EE4;
line-height: 30px;
color: #fff;
border-radius: 7px;
}
.timesheet-dec-content.has-prev{
margin-left: 0;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.timesheet-dec-content.has-next{
margin-right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.timesheet-dec-content.empty{
background: transparent;
color: silver;
}
JavaScript
var Timesheet = function(options){
var t = this;
t.o = options;
t.data = t.o.data || {};
t.wrapper = App.q(t.o.wrapper);
t.init();
};
Timesheet.prototype.buildDecs = function(decWrapper, hourData, prevHourHasLast, nextHourHasFirst){
var t = this;
function buildDec(decKey, decData){
var task = decData.task,
dec = App.create('div', {
'class' : 'timesheet-dec'
}),
prevData = hourData[parseInt(decKey)-10],
nextData = hourData[parseInt(decKey)+10],
isCompleted = task && task.status === 'done' ? ' is-completed ' : '',
prevClass = (prevData && prevData.task || (parseInt(decKey) === 10 && prevHourHasLast)) ? ' has-prev ' : '',
nextClass = (nextData && nextData.task || (parseInt(decKey) === 60 && nextHourHasFirst)) ? ' has-next ' : '',
isFirst = decKey === 10 ? ' is-first ' : '',
isLast = decKey === 60 ? ' is-last ' : '',
content = App.create('div', {
'class' : ('timesheet-dec-content' + prevClass + nextClass + isFirst + isLast + isCompleted + (task ? '' : ' empty ')).trim()
});
content.innerText = decKey;
dec.appendChild(content);
decWrapper.appendChild(dec);
};
for(var i=10; i<70; i += 10){
buildDec(i, hourData[i])
};
}
Timesheet.prototype.buildHours = function(){
var t = this;
function buildHour(hourKey, hourData){
var hour = App.create('div', {
'class' : 'timesheet-hour'
}),
label = App.create('div', {
'class' : 'timesheet-hour-label'
}),
decWrapper = App.create('div', {
'class' : 'timesheet-dec-wrapper'
}),
prevHour = t.data[parseInt(hourKey)-1],
nextHour = t.data[parseInt(hourKey)+1],
prevHourHasLast = !!(prevHour && prevHour['60'] && prevHour['60'].task),
nextHourHasFirst = !!(nextHour && nextHour['10'] && nextHour['10'].task);
label.innerHTML = hourKey;
hour.appendChild(label);
...