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);
...