diff options
Diffstat (limited to 'modules/datumpjeprik')
-rw-r--r-- | modules/datumpjeprik/datumpjeprik.html | 168 | ||||
-rw-r--r-- | modules/datumpjeprik/datumpjeprik.js | 66 |
2 files changed, 234 insertions, 0 deletions
diff --git a/modules/datumpjeprik/datumpjeprik.html b/modules/datumpjeprik/datumpjeprik.html new file mode 100644 index 0000000..46a21d3 --- /dev/null +++ b/modules/datumpjeprik/datumpjeprik.html @@ -0,0 +1,168 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Datumpje-prik</title> +<script> +var today,periodStart,periodEnd,periodWeekStart,periodWeekEnd,periodLength, + days,clicked,cantClick=false; + +//Sorry. Prototypes are fun. Using dollars to at least separate these from the built-in methods. +Date.prototype.$dayOfWeek=function(){return (this.getDay()+6)%7;} //monday..sunday = 0..6 +Date.prototype.$startOfDay=function(){return new Date(this-(((this.getHours()*60+this.getMinutes())*60+this.getSeconds())*1000+this.getMilliseconds()));} +Date.prototype.$addDays=function(n){return new Date(this.valueOf()+n*24*3600*1000);} +Date.prototype.$addWeeks=function(n){return new Date(this.valueOf()+n*7*24*3600*1000);} +Date.prototype.$naturalDate=function(){return this.getFullYear()+"-"+("00"+(this.getMonth()+1)).slice(-2)+"-"+("00"+this.getDate()).slice(-2);} + +function diffDays(d1,d2){return ~~(Math.abs(d1-d2)/1000/3600/24);} + +function localDateStringToDate(s){return new Date(s+"T00:00:00");} + +function appendPath(s,p){ + if(s.length==0)return p; + if(p.length==0)return s; + if(s[s.length-1]=="/"){ + if(p[0]=="/")return s+p.slice(1); + else return s+p; + } else { + if(p[0]=="/")return s+p; + else return s+"/"+p; + } +} + +function setupCalendar(){ + var cal=document.getElementById("calendar"), + maxnum=Math.max.apply(null,days)+1, + startOffset=diffDays(periodWeekStart,periodStart), + tr,td,span,w,d,idx; + cal.innerHTML=""; + tr=document.createElement("tr"); + for(d=0;d<7;d++){ + td=document.createElement("td"); + td.innerHTML=["mon","tue","wed","thu","fri","sat","sun"][d]; + tr.appendChild(td); + } + cal.appendChild(tr); + for(w=0;w<~~(periodLength/7);w++){ + tr=document.createElement("tr"); + for(d=0;d<7;d++){ + td=document.createElement("td"); + if(7*w+d>=startOffset){ + idx=7*w+d-startOffset; + span=document.createElement("span"); + span.classList.add("calendar-day-fillspan"); + span.setAttribute("style","width:"+(days[idx]+clicked[idx])/maxnum*100+"%"); + td.appendChild(span); + span=document.createElement("span"); + span.classList.add("calendar-day-datelabel"); + span.appendChild(document.createTextNode(periodStart.$addDays(idx).$naturalDate())); + td.appendChild(span); + if(!cantClick&&!localStorage.getItem("hasSubmitted")) + (function(idx){ + td.addEventListener("click",function(){ + clicked[idx]=!clicked[idx]; + setTimeout(setupCalendar,0); + },false); + })(idx); + } + tr.appendChild(td); + } + cal.appendChild(tr); + } + if(localStorage.getItem("hasSubmitted")){ + document.getElementById("status").innerHTML="You have already submitted!"; + document.getElementById("submitbtn").setAttribute("disabled",""); + } else { + document.getElementById("status").style.display="none"; + document.getElementById("submitbtn").removeAttribute("disabled"); + } +} + +function submitdays(){ + var xhr; + cantClick=true; + xhr=new XMLHttpRequest(); + xhr.addEventListener("readystatechange",function(ev){ + var result; + if(this.readyState!=4)return; + alert(this.responseText); + result=JSON.parse(this.responseText); + if(result==true){ + alert("Submitted successfully!"); + localStorage.setItem("hasSubmitted","true") + } else alert("Error while submitting!"); + },false); + xhr.open("POST",location.protocol+"//"+location.host+appendPath(location.pathname,"/adddays")); + xhr.send(JSON.stringify(clicked)); +} + + +(function(){ + var xhr; + today=new Date().$startOfDay(); + xhr=new XMLHttpRequest(); + xhr.addEventListener("readystatechange",function(ev){ + var result; + if(this.readyState!=4)return; + result=JSON.parse(this.responseText); + periodStart=new Date(localDateStringToDate(result["periodStart"])); + periodEnd=new Date(localDateStringToDate(result["periodEnd"])); + periodWeekStart=periodStart.$addDays(-periodStart.$dayOfWeek()); + periodWeekEnd=periodEnd.$addDays(6-periodEnd.$dayOfWeek()); + periodLength=diffDays(periodStart,periodEnd)+1; + days=Array.apply(null,new Array(periodLength)).map(function(){return 0;}); + clicked=days.map(function(){return false;}); + setupCalendar(); + },false); + xhr.open("GET",location.protocol+"//"+location.host+appendPath(location.pathname,"/dates")); + xhr.send(); + + xhr=new XMLHttpRequest(); + xhr.addEventListener("readystatechange",function(ev){ + var result; + if(this.readyState!=4)return; + days=JSON.parse(this.responseText); + setupCalendar(); + },false); + xhr.open("GET",location.protocol+"//"+location.host+appendPath(location.pathname,"/days")); + xhr.send(); +})(); + +window.addEventListener("load",function(){ + ; +},false); +</script> +<style> +tbody#calendar > tr{ + height:40px; +} +tbody#calendar > tr > td{ + position:relative; + width:80px; + height:inherit; + text-align:center; + vertical-align:middle; + border:1px #ddd solid; +} +.calendar-day-fillspan{ + display:inline-block; + position:absolute; + background-color:#6f6; + opacity:40%; + left:0; + top:0; + height:100%; + z-index:-10000; +} +.calendar-day-datelabel{ + color:#888; + font-size:8pt; +} +</style> +</head> +<body> +<div id="status"></div> +<table><tbody id="calendar"><tr><td>Loading...</td></tr></tbody></table> +<input id="submitbtn" type="button" onclick="submitdays()" value="Submit your days"> +</body> +</html> diff --git a/modules/datumpjeprik/datumpjeprik.js b/modules/datumpjeprik/datumpjeprik.js new file mode 100644 index 0000000..dc56759 --- /dev/null +++ b/modules/datumpjeprik/datumpjeprik.js @@ -0,0 +1,66 @@ +var cmn=require("../$common.js"); +var persist=require("node-persist"), + util=require("util"); + +//Sorry. Prototypes are fun. Using dollars to at least separate these from the built-in methods. +Date.prototype.$dayOfWeek=function(){return (this.getDay()+6)%7;} //monday..sunday = 0..6 +Date.prototype.$startOfDay=function(){return new Date(this-(((this.getHours()*60+this.getMinutes())*60+this.getSeconds())*1000+this.getMilliseconds()));} +Date.prototype.$addDays=function(n){return new Date(this.valueOf()+n*24*3600*1000);} +Date.prototype.$addWeeks=function(n){return new Date(this.valueOf()+n*7*24*3600*1000);} +Date.prototype.$naturalDate=function(){return this.getFullYear()+"-"+("00"+(this.getMonth()+1)).slice(-2)+"-"+("00"+this.getDate()).slice(-2);} + +function diffDays(d1,d2){return ~~(Math.abs(d1-d2)/1000/3600/24);} + +function localDateStringToDate(s){return new Date(s+"T00:00:00");} + + +var periodStart="2015-04-09",periodEnd="2015-07-05", + periodLength=diffDays(localDateStringToDate(periodStart),localDateStringToDate(periodEnd))+1; + +persist=persist.create({ + dir:"persist/datumpjeprik", + continuous:false, + interval:false +}); +persist.initSync(); + +function ensureInitialised(){ + var days; + days=persist.getItem("days"); + if(!days||days.length!=periodLength){ + days=Array.apply(null,new Array(periodLength)).map(function(){return 0;}); + persist.setItemSync("days",days); + } +} +ensureInitialised(); + +module.exports=function(app,io,moddir){ + app.get("/datumpjeprik",function(req,res){ + res.set("Content-Type","text/html"); + res.sendFile(moddir+"/datumpjeprik.html"); + }); + app.get("/datumpjeprik/dates",function(req,res){ + res.set("Content-Type","text/json"); + res.send('{"periodStart":"'+periodStart+'","periodEnd":"'+periodEnd+'"}'); + }); + app.get("/datumpjeprik/days",function(req,res){ + ensureInitialised(); + res.set("Content-Type","text/json"); + res.send(persist.getItem("days")); + }); + app.post("/datumpjeprik/adddays",function(req,res){ + var newdays; + console.log(req.body); + try{ + newdays=JSON.parse(req.body); + if(newdays.length!=periodLength)throw new Error("length mismatch"); + if(!newdays.map(function(v){return typeof v=="boolean";}).reduce(function(a,b){return a&&b;}))throw new Error("not all bools"); + ensureInitialised(); + persist.setItemSync("days",persist.getItem("days").map(function(v,i){return v+newdays[i];})); + res.send("true"); + } catch(e){ + res.send("[false,\""+e.message+"\"]"); + return; + } + }); +}; |