← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~trimardio/widelands-website/scheduling_module into lp:widelands-website

 

Trimardio has proposed merging lp:~trimardio/widelands-website/scheduling_module into lp:widelands-website.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~trimardio/widelands-website/scheduling_module/+merge/331477

Added the scheduling module.

Widelands games are long. And the player base is relatively small. Thus on IRC it is hard to find someone who has the time to play.

To solve that problem the goal of the scheduling module is to allow players to set the times at which they are available for a game and display it for other.

There are two pages for this module:
- the "find" page allows to see the avaibilities of all the players.
- the "schduling" page allow to set the times when the player will have time to play. It then allow hil to see who will be available at the same times.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~trimardio/widelands-website/scheduling_module into lp:widelands-website.
=== added file 'media/css/kalendae.css'
--- media/css/kalendae.css	1970-01-01 00:00:00 +0000
+++ media/css/kalendae.css	2017-09-28 09:52:14 +0000
@@ -0,0 +1,268 @@
+/** Base container **/
+.kalendae {
+	display: inline-block;zoom:1;*display:inline;
+	background:#eee;
+	padding:10px;
+	margin:5px;
+	border-radius:5px;
+	font-size:11px;
+	font-family:'Helvetica Neue', 'Helvetica';
+	cursor:default;
+	position:relative;
+	-moz-box-sizing: border-box;
+	box-sizing: border-box;
+}
+
+.kalendae * {
+	-moz-box-sizing: border-box;
+	box-sizing: border-box;
+}
+
+/** Popup Container for Kalendae.Input **/
+.kalendae.k-floating {
+	position:absolute;
+	top:0;
+	left:0;
+	z-index:100000;
+	margin:0;
+	box-shadow:0 1px 3px rgba(0,0,0,0.75);
+}
+
+/** Kalendae.Input's popup close button **/
+.kalendae .k-btn-close {
+	position:absolute;
+	top:-8px;
+	right:-8px;
+	width:20px;
+	height:20px;
+	background:white;
+	border:2px solid #ccc;
+	color:#999;
+	line-height:17px;
+	text-align:center;
+	font-size:13px;
+	border-radius:10px;
+	box-shadow:0 1px 3px rgba(0,0,0,0.75);
+	cursor:pointer;
+	text-decoration:none;
+}
+.kalendae .k-btn-close:after {content:"\2716";}
+.kalendae .k-btn-close:hover {
+	color:#7EA0E2;
+	background:white;
+	border-color:#7EA0E2;
+}
+
+/** Month Container **/
+.kalendae .k-calendar {display: inline-block;zoom:1;*display:inline;width:155px;vertical-align:top;}
+
+/** Month Separator **/
+.kalendae .k-separator {
+	display: inline-block;zoom:1;*display:inline;
+	width:2px;
+	vertical-align:top;
+	background:#ddd;
+	height:155px;
+	margin:0px 10px;
+}
+
+/** Month Title Row **/
+.kalendae .k-title {text-align:center;white-space:nowrap;position:relative;height:18px;}
+.kalendae .k-caption {font-size:12px;line-height:18px;}
+
+
+/** Month and Year Buttons **/
+.kalendae .k-btn-previous-month,
+.kalendae .k-btn-next-month,
+.kalendae .k-btn-previous-year,
+.kalendae .k-btn-next-year {
+	width:16px;
+	height:23px;
+	cursor:pointer;
+	position:absolute;
+	top:-3px;
+	color:#777;
+	font-size:32px;
+	line-height: 18px;
+	font-weight: bold;
+	font-family: arial;
+	text-decoration:none;
+}
+
+.kalendae .k-btn-previous-year {left:0;}
+.kalendae .k-btn-previous-month {left:16px;}
+.kalendae .k-btn-next-month {right:16px;}
+.kalendae .k-btn-next-year {right:0;}
+
+.kalendae .k-btn-previous-month:after {content:"\2039";}
+.kalendae .k-btn-next-month:after {content:"\203A";}
+
+.kalendae .k-btn-previous-year:after {content:"\00AB";}
+.kalendae .k-btn-next-year:after {content:"\00BB";}
+
+.kalendae .k-btn-previous-month:hover,
+.kalendae .k-btn-next-month:hover {color:#7EA0E2;}
+
+.kalendae .k-btn-previous-year:hover,
+.kalendae .k-btn-next-year:hover {color:#6FDF81;}
+
+/** Remove extra buttons when calendar shows multiple months **/
+.kalendae .k-first-month .k-btn-next-month,
+.kalendae .k-middle-month .k-btn-next-month,
+.kalendae .k-middle-month .k-btn-previous-month,
+.kalendae .k-last-month .k-btn-previous-month,
+.kalendae .k-first-month .k-btn-next-year,
+.kalendae .k-middle-month .k-btn-next-year,
+.kalendae .k-middle-month .k-btn-previous-year,
+.kalendae .k-last-month .k-btn-previous-year {display:none;}
+
+/** Disable year nav option **/
+.kalendae .k-title.k-disable-year-nav .k-btn-next-year,
+.kalendae .k-title.k-disable-year-nav .k-btn-previous-year { display: none; }
+.kalendae .k-title.k-disable-year-nav .k-btn-next-month { right: 0; }
+.kalendae .k-title.k-disable-year-nav .k-btn-previous-month { left: 0; }
+
+/** Force specific width for month container contents **/
+.kalendae .k-title,
+.kalendae .k-header,
+.kalendae .k-days {
+	width:154px;
+	display:block;
+	overflow:hidden;
+}
+
+
+/** Hide unusable buttons **/
+.kalendae.k-disable-next-month-btn .k-btn-next-month,
+.kalendae.k-disable-previous-month-btn .k-btn-previous-month,
+.kalendae.k-disable-next-year-btn .k-btn-next-year,
+.kalendae.k-disable-previous-year-btn .k-btn-previous-year {
+	display:none;
+}
+
+
+/** Week columns and day cells **/
+.kalendae .k-header span,
+.kalendae .k-days span {
+	float:left;
+	margin:1px 1px 2px 1px;
+}
+
+.kalendae .k-header span {
+	text-align:center;
+	font-weight:bold;
+	width:20px;
+	padding:1px 0;
+	color:#666;
+}
+
+.kalendae .k-header.k-active span {
+	cursor: pointer;
+	border-radius:3px;
+}
+
+.kalendae .k-days span {
+	text-align:right;
+	width:20px;
+	height:1.5em;
+	line-height:1em;
+	padding:2px 3px 2px 2px;
+	border:1px solid transparent;
+	border-radius:3px;
+	color:#999;
+}
+
+/** Today **/
+.kalendae .k-today {
+	text-decoration:underline;
+}
+
+/** Days inside of the month view **/
+.kalendae .k-days span.k-in-month.k-active {
+	border-color:#ddd;
+	background-color:#fff;
+	color:#333;
+}
+/** Days outside of the month view (before the first day of the month, after the last day of the month) **/
+.kalendae .k-days span.k-out-of-month {color:#ddd;}
+
+/** Selectable  **/
+.kalendae .k-days span.k-active {
+	cursor:pointer;
+}
+
+/** Selected day, when outside the selectable area **/
+.kalendae .k-days span.k-selected {
+	border-color:#1072A5;
+	color:#1072A5;
+}
+
+/** Selected day, when inside the selectable area **/
+.kalendae .k-days span.k-selected.k-active,
+.kalendae .k-header.k-active span.k-selected {
+	background:#7EA0E2;
+	color:white;
+}
+
+/** Days between the start and end points on a range, outside of the selectable area **/
+.kalendae .k-days span.k-range {
+	background:none;
+	border-color:#6DD4FE;
+}
+
+/** Days between the start and end points on a range, inside of the selectable area **/
+.kalendae .k-days span.k-range.k-in-month {
+	background:#C4D4F1;
+	border-color:#19AEFE;
+	color:#333;
+}
+
+/** Selectable day, hovered **/
+.kalendae .k-days span.k-active:hover,
+.kalendae .k-days span.k-active.k-day-hover-active {
+	border-color:#666;
+}
+
+/** Selectable week, hovered **/
+.kalendae .k-week:hover span.k-active {
+	border-color:#666;
+}
+
+.clearfix:after { visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0; }
+
+/*-------------------------------------IE8 ONLY CODE BELOW THIS LINE--------------------------------------------*/
+
+.kalendae.ie8.k-floating {
+	border:1px solid #ccc;
+}
+
+.kalendae.ie8 .k-btn-close {
+	width:20px;
+	height:20px;
+	border:none;
+	background:url('close.png') no-repeat top left;
+}
+.kalendae.ie8 .k-btn-close:after {display:none;}
+
+.kalendae.ie8 .k-btn-previous-month,
+.kalendae.ie8 .k-btn-next-month,
+.kalendae.ie8 .k-btn-previous-year,
+.kalendae.ie8 .k-btn-next-year {width:16px;height:16px;cursor:pointer;background:#777 url('arrows.png') no-repeat center left;position:absolute;top:0;}
+
+.kalendae.ie8 .k-btn-next-month,
+.kalendae.ie8 .k-btn-next-year {background-position:center right;}
+
+.kalendae.ie8 .k-btn-previous-month:hover,
+.kalendae.ie8 .k-btn-next-month:hover {background-color:#7EA0E2;}
+
+.kalendae.ie8 .k-btn-previous-year,
+.kalendae.ie8 .k-btn-next-year {background-color:#333;}
+
+.kalendae.ie8 .k-btn-previous-year:hover,
+.kalendae.ie8 .k-btn-next-year:hover {background-color:#6FDF81;}
+
+.kalendae.ie8 .k-btn-previous-month:after,
+.kalendae.ie8 .k-btn-next-month:after,
+.kalendae.ie8 .k-btn-previous-year:after,
+.kalendae.ie8 .k-btn-next-year:after {display:none;}
+

=== added file 'media/css/scheduling.css'
--- media/css/scheduling.css	1970-01-01 00:00:00 +0000
+++ media/css/scheduling.css	2017-09-28 09:52:14 +0000
@@ -0,0 +1,211 @@
+/* Main */
+
+.main-choices {
+    display: flex;
+    justify-content: space-around;
+    margin-top: 40px;
+}
+
+.main-choices button {
+    padding: 40px;
+    font-size: 1em;
+}
+
+/* actual scheduling module */
+#calandar {
+    display: flex;
+    justify-content: center;
+}
+
+/*  Hours of each day display for the user  */
+.day {
+    margin-bottom: 15px;
+    background-image: url("../img/black50.png");
+    padding: 10px;
+}
+
+.day-title h3{
+    color:white;
+    font-weight: bold;
+    margin-top: 0;
+}
+
+.hours-wrapper {
+    display: flex;
+}
+
+.hours-title-wrapper {
+    display: flex;
+    width: 100%;
+}
+
+.hours-title-wrapper p{
+    width: 42px;
+    user-select: none;
+}
+
+.hours {
+    border: 1px solid #909090;
+    height:40px;
+    width: 40px;
+    cursor: pointer;
+}
+
+.hours.selected {
+    background-color:#118811;
+}
+
+.hours:hover {
+    background-color:lightgreen;
+}
+
+.hidden-hour {
+    height:40px;
+    width: 40px;
+}
+
+
+/*  Display for the other users  */
+
+#other-users-wrapper {
+    display: flex;
+    flex-wrap: wrap;
+    padding: 1%;
+}
+
+.other-user-div{
+    width: 29%;
+    border: 1px solid black;
+    background-image: url("../img/black50.png");
+    padding: 11px;
+    margin-top: 5px;
+    margin-right: 5px;
+}
+
+.other-user-div > div {
+    margin-top: 14px;
+}
+
+.other-user-div .hours{
+    height: 10px;
+    width: 20px;
+}
+
+.other-user-div .title {
+    height: 36px;
+    display: flex;
+    justify-content: space-between;
+    margin-top: 0;
+}
+
+.other-user-div .title p {
+    font-size:20px;
+    margin-top: 5px;
+    text-transform: capitalize;
+    white-space: nowrap;
+    overflow: hidden !important;
+    text-overflow: ellipsis;
+    color:  #feea72;;
+    font-weight: bold;
+}
+
+.other-user-div .title button {
+    min-width: 114px;
+}
+
+.other-user-div .title button:hover {
+    background-color:#118811;;
+}
+
+.other-user-div .title img {
+    margin-right: 4px;
+}
+
+/* btn */
+
+#validate-btn {
+    margin-top: 10px;
+}
+
+
+/* Calandar stuff */
+.kalendae {
+    background: none;
+    background-image: url("../img/black50.png");
+    width: 100%;
+    height: 260px;
+    display: flex;
+    justify-content: center;
+}
+
+.kalendae .k-calendar {
+    width: 650px;
+    height: 191px;
+    margin-top: 25px;
+}
+
+.kalendae .k-caption {
+    font-size: 23px;
+}
+
+.kalendae a.k-btn-next-month,
+.kalendae a.k-btn-next-year,
+.kalendae a.k-btn-previous-month,
+.kalendae a.k-btn-previous-year {
+    color:#118811;
+    font-size: 40px;
+     width: 23px;
+
+}
+
+.kalendae .k-title {
+    width: 100%;
+    margin-bottom: 14px;
+}
+
+.kalendae .k-header{
+    display: flex;
+    width: 100%;
+}
+
+.kalendae .k-header span {
+    width: 100%;
+    font-size: 17px;
+    color: #118811;
+}
+
+.kalendae .k-days {
+    display: flex;
+    width: 100%;
+    flex-wrap: wrap;
+    justify-content: space-around;
+    height: 168px;
+    align-content: space-around;
+}
+
+.kalendae .k-days span {
+    width: calc(13% + 4px);
+    text-align: center;
+    font-size: 16px;
+    border-radius: 0;
+}
+
+
+.kalendae .k-in-month,
+.kalendae .k-out-of-month {
+    opacity: 0;
+}
+
+.kalendae .k-active {
+    opacity: 1;
+}
+
+.kalendae .k-days span.k-selected.k-active {
+    background-color:  #118811;
+    border: 1px solid black;
+}
+
+.kalendae .k-days span.k-active:hover,
+.kalendae .k-days span.k-active.k-day-hover-active {
+    background-color: #6eed6e;
+}
\ No newline at end of file

=== added file 'media/js/kalendae.min.js'
--- media/js/kalendae.min.js	1970-01-01 00:00:00 +0000
+++ media/js/kalendae.min.js	2017-09-28 09:52:14 +0000
@@ -0,0 +1,110 @@
+/********************************************************************
+ *	Kalendae, a framework agnostic javascript date picker           *
+ *	Copyright(c) 2013-2016 Jarvis Badgley (chipersoft@xxxxxxxxx)    *
+ *	http://github.com/ChiperSoft/Kalendae                           *
+ *	Version 0.6.1                                                   *
+ ********************************************************************/
+(function(ib){(function(n){"function"===typeof define&&define.amd?define([],n):"object"===typeof exports?module.exports=n():window.Kalendae=n()})(function(){var n,A=function(){return r.moment().startOf("day").yearDay()},r=function(b,c){if("function"===typeof document.addEventListener||e.isIE8()){var g=!1;try{g=b instanceof Element}catch(O){g=!!b&&1===g.nodeType}g||"string"===typeof b||(c=b);var f=this,k=f.classes,m=f.settings=e.merge(f.defaults,{attachTo:b},c||{}),g=f.container=e.make("div",{"class":k.container}),
+p=f.calendars=[],r=n().day(m.weekStart),t,D=[],v,u,q,x,P;v=[];u=0;t=m.months;e.isIE8()&&e.addClassName(g,"ie8");for(u=7;u--;)D.push(r.format(m.columnHeaderFormat)),r.add(1,"days");Q(f);if("object"===typeof m.subscribe)for(u in m.subscribe)m.subscribe.hasOwnProperty(u)&&f.subscribe(u,m.subscribe[u]);t=m.viewStartDate?n(m.viewStartDate,m.format):n();f.viewStartDate=t.date(1);f._sel=[];m.selected&&(f.setSelected(m.selected,!1),f.viewStartDate=n(f._sel[0]));(t={past:m.months-1,"today-past":m.months-1,
+any:2<m.months?Math.floor(m.months/2):0,"today-future":0,future:0}[this.settings.direction])&&n().month()==n(f.viewStartDate).month()&&(f.viewStartDate=n(f.viewStartDate).subtract({M:t}).date(1));f.defaultView=n(f.viewStartDate);if("function"===typeof m.blackout)f.blackout=m.blackout;else if(m.blackout){var A=K(m.blackout,m.parseSplitDelimiter,m.format);f.blackout=function(b){b=n(b).startOf("day").yearDay();if(1>b||!f._sel)return!1;for(var c=A.length;c--;)if(A[c].startOf("day").yearDay()===b)return!0;
+return!1}}else f.blackout=function(){return!1};f.direction=f.directions[m.direction]?f.directions[m.direction]:f.directions.any;for(t=Math.max(m.months,1);t--;){v=e.make("div",{"class":k.calendar},g);v.setAttribute("data-cal-index",t);1<m.months&&(t==Math.max(m.months-1,1)?e.addClassName(v,k.monthFirst):0===t?e.addClassName(v,k.monthLast):e.addClassName(v,k.monthMiddle));u=e.make("div",{"class":k.title},v);m.useYearNav||e.addClassName(u,k.disableYearNav);e.make("a",{"class":k.previousYear},u);e.make("a",
+{"class":k.previousMonth},u);e.make("a",{"class":k.nextYear},u);e.make("a",{"class":k.nextMonth},u);r=e.make("span",{"class":k.caption},u);q=e.make("div",{"class":k.header+" "+(1==m.dayHeaderClickable?k.dayActive:"")},v);u=0;do x=e.make("span",{"data-day":u},q),1==m.dayHeaderClickable&&"multiple"==m.mode&&(x.addEventListener("mouseover",function(b){daysToHover=b.target.parentNode.nextSibling.getElementsByClassName("k-day-week-"+b.target.getAttribute("data-day"));if(0<daysToHover.length)for(b=0;b<
+daysToHover.length;b++)e.hasClassName(daysToHover[b],k.dayActive)&&e.addClassName(daysToHover[b],"k-day-hover-active")}),x.addEventListener("mouseleave",function(b){daysToHover=b.target.parentNode.nextSibling.getElementsByClassName("k-day-week-"+b.target.getAttribute("data-day"));if(0<daysToHover.length)for(b=0;b<daysToHover.length;b++)e.hasClassName(daysToHover[b],k.dayActive)&&e.removeClassName(daysToHover[b],"k-day-hover-active")})),x.innerHTML=D[u];while(7>++u);x=e.make("div",{"class":k.days},
+v);u=0;v=[];do"week"==m.mode?(0===u%7&&(P=e.make("div",{"class":k.week+" clearfix"},x),v.push(P)),e.make("span",{},P)):v.push(e.make("span",{},x));while(42>++u);p.push({header:q,caption:r,days:v});t&&e.make("div",{"class":k.monthSeparator},g)}f.draw();e.addEvent(g,"mousedown",function(b,c){var g;if(e.hasClassName(c,k.nextMonth))f.disableNext||!1===f.publish("view-changed",f,["next-month"])||(f.viewStartDate.add(1,"months"),f.draw());else if(e.hasClassName(c,k.previousMonth))f.disablePreviousMonth||
+!1===f.publish("view-changed",f,["previous-month"])||(f.viewStartDate.subtract(1,"months"),f.draw());else if(e.hasClassName(c,k.nextYear))f.disableNext||!1===f.publish("view-changed",f,["next-year"])||(f.viewStartDate.add(1,"years"),f.draw());else if(e.hasClassName(c,k.previousYear))f.disablePreviousMonth||!1===f.publish("view-changed",f,["previous-year"])||(f.viewStartDate.subtract(1,"years"),f.draw());else if((e.hasClassName(c.parentNode,k.days)||e.hasClassName(c.parentNode,k.week))&&e.hasClassName(c,
+k.dayActive)&&(g=c.getAttribute("data-date"))){if(g=n(g,m.dayAttributeFormat).hours(12),!1!==f.publish("date-clicked",f,[g]))switch(m.mode){case "multiple":f.addSelected(g)||f.removeSelected(g);break;case "range":f.addSelected(g);break;case "week":f.weekSelected(g);break;default:f.addSelected(g)}}else if(e.hasClassName(c.parentNode,k.week)&&(g=c.getAttribute("data-date")))g=n(g,m.dayAttributeFormat).hours(12),!1!==f.publish("date-clicked",f,[g])&&"week"==m.mode&&f.weekSelected(g);else if(e.hasClassName(c.parentNode,
+k.header)&&"multiple"==m.mode&&1==m.dayHeaderClickable){g=e.hasClassName(c,k.daySelected);var p=c.parentNode.parentNode.getAttribute("data-datestart"),q=c.getAttribute("data-day");1==g?f.monthDaySelected(p,q,!0):f.monthDaySelected(p,q,!1)}return!1});(m.attachTo=e.$(m.attachTo))&&m.attachTo.appendChild(g)}};r.prototype={defaults:{attachTo:null,months:1,weekStart:0,direction:"any",directionScrolling:!0,viewStartDate:null,blackout:null,selected:null,mode:"single",dayOutOfMonthClickable:!1,dayHeaderClickable:!1,
+format:null,subscribe:null,columnHeaderFormat:"dd",titleFormat:"MMMM, YYYY",dayNumberFormat:"D",dayAttributeFormat:"YYYY-MM-DD",parseSplitDelimiter:/,\s*|\s+-\s+/,rangeDelimiter:" - ",multipleDelimiter:", ",useYearNav:!0,dateClassMap:{}},classes:{container:"kalendae",calendar:"k-calendar",monthFirst:"k-first-month",monthMiddle:"k-middle-month",monthLast:"k-last-month",title:"k-title",previousMonth:"k-btn-previous-month",nextMonth:"k-btn-next-month",previousYear:"k-btn-previous-year",nextYear:"k-btn-next-year",
+caption:"k-caption",header:"k-header",days:"k-days",week:"k-week",dayOutOfMonth:"k-out-of-month",dayInMonth:"k-in-month",dayActive:"k-active",daySelected:"k-selected",dayInRange:"k-range",dayInRangeStart:"k-range-start",dayInRangeEnd:"k-range-end",dayToday:"k-today",monthSeparator:"k-separator",disablePreviousMonth:"k-disable-previous-month-btn",disableNextMonth:"k-disable-next-month-btn",disablePreviousYear:"k-disable-previous-year-btn",disableNextYear:"k-disable-next-year-btn",disableYearNav:"k-disable-year-nav"},
+disablePreviousMonth:!1,disableNextMonth:!1,disablePreviousYear:!1,disableNextYear:!1,directions:{past:function(b){return n(b).startOf("day").yearDay()>=A()},"today-past":function(b){return n(b).startOf("day").yearDay()>A()},any:function(b){return!1},"today-future":function(b){return n(b).startOf("day").yearDay()<A()},future:function(b){return n(b).startOf("day").yearDay()<=A()}},getSelectedAsDates:function(){for(var b=[],c=0,g=this._sel.length;c<g;c++)b.push(this._sel[c].toDate());return b},getSelectedAsText:function(b){for(var c=
+[],g=0,f=this._sel.length;g<f;g++)c.push(this._sel[g].format(b||this.settings.format||"YYYY-MM-DD"));return c},getSelectedRaw:function(){for(var b=[],c=0,g=this._sel.length;c<g;c++)b.push(n(this._sel[c]));return b},getSelected:function(b){b=this.getSelectedAsText(b);switch(this.settings.mode){case "week":case "range":return b.splice(2),b.join(this.settings.rangeDelimiter);case "multiple":return b.join(this.settings.multipleDelimiter);default:return b[0]||null}},isSelected:function(b){b=n(b).startOf("day").yearDay();
+if(1>b||!this._sel||1>this._sel.length)return!1;switch(this.settings.mode){case "week":case "range":var c=this._sel[0]?this._sel[0].startOf("day").yearDay():0,g=this._sel[1]?this._sel[1].startOf("day").yearDay():0;return c===b||g===b?1:c&&g?b>c&&b<g||c<g&&b<c&&b>g?-1:!1:0;case "multiple":for(c=this._sel.length;c--;)if(this._sel[c].startOf("day").yearDay()===b)return!0;return!1;default:return this._sel[0]&&this._sel[0].startOf("day").yearDay()===b}},setSelected:function(b,c){var g,f=K(b,this.settings.parseSplitDelimiter,
+this.settings.format),k=K(this.getSelected(),this.settings.parseSplitDelimiter,this.settings.format);for(g=k.length;g--;)this.removeSelected(k[g],!1);for(g=f.length;g--;)this.addSelected(f[g],!1);!1!==c&&(f[0]&&(this.viewStartDate=n(f[0],this.settings.format)),this.draw())},addSelected:function(b,c){b=n(b,this.settings.format).hours(12);this.settings.dayOutOfMonthClickable&&"range"!==this.settings.mode&&this.makeSelectedDateVisible(b);switch(this.settings.mode){case "multiple":if(this.isSelected(b))return!1;
+this._sel.push(b);break;case "range":1!==this._sel.length?this._sel=[b]:b.startOf("day").yearDay()>this._sel[0].startOf("day").yearDay()?this._sel[1]=b:this._sel=[b,this._sel[0]];break;default:this._sel=[b]}this._sel.sort(function(b,c){return b.startOf("day").yearDay()-c.startOf("day").yearDay()});this.publish("change",this,[b]);!1!==c&&this.draw();return!0},weekSelected:function(b){var c=b.toDate(),g=n(c).startOf("week"),c=n(c).endOf("week").subtract(1,"day");this._sel=[g,c];this.publish("change",
+this,[b.day()]);this.draw()},monthDaySelected:function(b,c,g){c=n(b).startOf("month").weekday(c);var f=n(b).endOf("month");for(selected=[];c<=f;)c>=n(b).startOf("month")&&!this.direction(c)&&(g?this.removeSelected(n(c).hours(12)):this.addSelected(n(c).hours(12))),c.add(7,"d")},makeSelectedDateVisible:function(b){outOfViewMonth=n(b).date("1").diff(this.viewStartDate,"months");0>outOfViewMonth?this.viewStartDate.subtract(1,"months"):0<outOfViewMonth&&outOfViewMonth>=this.settings.months&&this.viewStartDate.add(1,
+"months")},removeSelected:function(b,c){b=n(b,this.settings.format).hours(12);for(var g=this._sel.length;g--;)if(this._sel[g].startOf("day").yearDay()===b.startOf("day").yearDay())return this._sel.splice(g,1),this.publish("change",this,[b]),!1!==c&&this.draw(),!0;return!1},draw:function(){var b=n(this.viewStartDate).startOf("month").add(12,"hours"),c,g=this.classes,f,k,m,p=0,F,t=0;c=0;var D,v,u,q=this.settings;F=this.calendars.length;do{c=n(b).date(1);c.day(c.day()<this.settings.weekStart?this.settings.weekStart-
+7:this.settings.weekStart);f=this.calendars[p];f.header.parentNode.setAttribute("data-datestart",b.format(this.settings.dayAttributeFormat));f.caption.innerHTML=b.format(this.settings.titleFormat);D=t=0;u=[];for(k=0;7>k;k++)e.removeClassName(f.header.children[k],g.daySelected),u[k]=0;do"week"==q.mode?(0===t%7&&0!==t&&D++,k=f.days[D].childNodes[t%7]):k=f.days[t],m=[],(v=this.isSelected(c))&&m.push({"-1":g.dayInRange,1:g.daySelected,"true":g.daySelected}[v]),"range"===q.mode&&(this._sel[0]&&this._sel[0].startOf("day").yearDay()===
+c.clone().startOf("day").yearDay()&&m.push(g.dayInRangeStart),this._sel[1]&&this._sel[1].startOf("day").yearDay()===c.clone().startOf("day").yearDay()&&m.push(g.dayInRangeEnd)),q.dayHeaderClickable&&"multiple"===q.mode&&(m.push("k-day-week-"+c.weekday()),1!=v&&1!=v||this.direction(c)||b.format("M")!=c.format("M")||(u[c.weekday()]=u[c.weekday()]+1)),c.month()!=b.month()?m.push(g.dayOutOfMonth):m.push(g.dayInMonth),(!(this.blackout(c)||this.direction(c)||c.month()!=b.month()&&!1===q.dayOutOfMonthClickable)||
+0<v)&&m.push(g.dayActive),c.clone().startOf("day").yearDay()===A()&&m.push(g.dayToday),v=c.format(this.settings.dayAttributeFormat),q.dateClassMap[v]&&m.push(q.dateClassMap[v]),k.innerHTML=c.format(q.dayNumberFormat),k.className=m.join(" "),k.setAttribute("data-date",v),c.add(1,"days");while(42>++t);k=0;if(0<u.length){do if(0<u[k]){t=r.moment(b).startOf("month").weekday(k);D=r.moment(b).startOf("month");endMonth=r.moment(b).endOf("month");c=0;do t>=D&&!this.direction(t)&&c++,t.add(7,"d");while(t<=
+endMonth);c==u[k]?e.addClassName(f.header.children[k],g.daySelected):e.removeClassName(f.header.children[k],g.daySelected)}while(++k<u.length)}b.add(1,"months")}while(++p<F);if(q.directionScrolling){f=n().startOf("day").hours(12);b=b.diff(f,"months",!0);if("today-past"===q.direction||"past"===q.direction)0>=b?(this.disableNextMonth=!1,e.removeClassName(this.container,g.disableNextMonth)):(this.disableNextMonth=!0,e.addClassName(this.container,g.disableNextMonth));else if("today-future"===q.direction||
+"future"===q.direction)b>q.months?(this.disablePreviousMonth=!1,e.removeClassName(this.container,g.disablePreviousMonth)):(this.disablePreviousMonth=!0,e.addClassName(this.container,g.disablePreviousMonth));if("today-past"===q.direction||"past"===q.direction)-11>=b?(this.disableNextYear=!1,e.removeClassName(this.container,g.disableNextYear)):(this.disableNextYear=!0,e.addClassName(this.container,g.disableNextYear));else if("today-future"===q.direction||"future"===q.direction)b>11+q.months?(this.disablePreviousYear=
+!1,e.removeClassName(this.container,g.disablePreviousYear)):(this.disablePreviousYear=!0,e.addClassName(this.container,g.disablePreviousYear))}}};var K=function(b,c,g){var f=[];"string"===typeof b?b=b.split(c):e.isArray(b)||(b=[b]);c=b.length;var k=0,m;do b[k]&&(m=n(b[k],g).hours(12),m.isValid()&&f.push(m));while(++k<c);return f};window.Kalendae=r;var e=r.util={isIE8:function(){return!(!/msie 8./i.test(navigator.appVersion)||/opera/i.test(navigator.userAgent)||!window.ActiveXObject||!XDomainRequest||
+window.msPerformance)},$:function(b){return"string"==typeof b?document.getElementById(b):b},$$:function(b){return document.querySelectorAll(b)},make:function(b,c,g){var f;b=document.createElement(b);if(c)for(f in c)c.hasOwnProperty(f)&&b.setAttribute(f,c[f]);g&&g.appendChild(b);return b},isVisible:function(b){return 0<b.offsetWidth||0<b.offsetHeight},getStyle:function(b,c){var g;b.currentStyle?g=b.currentStyle[c]:window.getComputedStyle&&(g=(g=window.getComputedStyle(b,null))?g[c]:"");return g},domReady:function(b){var c=
+document.readyState;"complete"===c||"interactive"===c?b():setTimeout(function(){e.domReady(b)},9)},addEvent:function(b,c,g){var f=function(c){c=c||window.event;var f=g.apply(b,[c,c.target||c.srcElement]);!1===f&&(c.preventDefault?c.preventDefault():(c.returnValue=!1,c.cancelBubble=!0));return f};b.attachEvent?b.attachEvent("on"+c,f):b.addEventListener(c,f,!1);return f},removeEvent:function(b,c,g){b.detachEvent?b.detachEvent("on"+c,g):b.removeEventListener(c,g,!1)},fireEvent:function(b,c){if(document.createEvent){var g=
+document.createEvent("HTMLEvents");g.initEvent(c,!0,!0);b.dispatchEvent(g)}else if(document.createEventObject)b.fireEvent("on"+c);else if("function"==typeof b["on"+c])b["on"+c]()},hasClassName:function(b,c){if(!(b=e.$(b)))return!1;var g=b.className;return 0<g.length&&(g==c||(new RegExp("(^|\\s)"+c+"(\\s|$)")).test(g))},addClassName:function(b,c){(b=e.$(b))&&!e.hasClassName(b,c)&&(b.className+=(b.className?" ":"")+c)},removeClassName:function(b,c){if(b=e.$(b))b.className=e.trimString(b.className.replace(new RegExp("(^|\\s+)"+
+c+"(\\s+|$)")," "))},isFixed:function(b){do if("fixed"===e.getStyle(b,"position"))return!0;while(b=b.offsetParent);return!1},scrollContainer:function(b){do{var c=e.getStyle(b,"overflow");if("auto"===c||"scroll"===c)return b}while((b=b.parentNode)&&b!=window.document.body);return null},getPosition:function(b,c){var g=b.offsetLeft,f=b.offsetTop,k={};if(!c)for(;b=b.offsetParent;)g+=b.offsetLeft,f+=b.offsetTop;k[0]=k.left=g;k[1]=k.top=f;return k},getHeight:function(b){return b.offsetHeight||b.scrollHeight},
+getWidth:function(b){return b.offsetWidth||b.scrollWidth},trimString:function(b){return b.replace(/^\s+/,"").replace(/\s+$/,"")},merge:function(){for(var b=!0===arguments[0],c={},g=b?1:0;g<arguments.length;g++){var f=c,k=arguments[g];if("object"===typeof k){var e=void 0;for(e in k)k.hasOwnProperty(e)&&(b&&"object"===typeof f[e]&&"object"===typeof k[e]?_update(f[e],k[e]):f[e]=k[e])}}return c},isArray:function(b){return"[object Array]"==Object.prototype.toString.call(b)}};"function"===typeof document.addEventListener&&
+r.util.domReady(function(){for(var b=e.$$(".auto-kal"),c=b.length,g,f;c--;)g=b[c],f=g.getAttribute("data-kal"),f=null==f||""==f?{}:(new Function("return {"+f+"};"))(),"INPUT"===g.tagName?new r.Input(g,f):new r(e.merge(f,{attachTo:g}))});r.Input=function(b,c){if("function"===typeof document.addEventListener||e.isIE8()){var g=this.input=e.$(b),f,k,m=!1;if(!g||"INPUT"!==g.tagName)throw"First argument for Kalendae.Input must be an <input> element or a valid element id.";var p=this,F=p.classes;k=p.settings=
+e.merge(p.defaults,c);this._events={};k.attachTo=window.document.body;k.selected?f=!0:k.selected=g.value;r.call(p,k);k.closeButton&&(k=e.make("a",{"class":F.closeButton},p.container),e.addEvent(k,"click",function(){g.blur()}));f&&(g.value=p.getSelected());f=p.container;var t=!1;f.style.display="none";e.addClassName(f,F.positioned);this._events.containerMouseDown=e.addEvent(f,"mousedown",function(b,c){t=!0});this._events.documentMousedown=e.addEvent(window.document,"mousedown",function(b,c){t=!1});
+this._events.inputFocus=e.addEvent(g,"focus",function(){m=!0;p.setSelected(this.value);m=!1;p.show()});this._events.inputBlur=e.addEvent(g,"blur",function(){t&&e.isIE8()?(t=!1,g.focus()):p.hide()});this._events.inputKeyup=e.addEvent(g,"keyup",function(b){m=!0;(b=K(this.value,p.settings.parseSplitDelimiter,p.settings.format))&&b.length&&b[0]&&1E3<b[0].year()?p.setSelected(this.value):(p.setSelected("",null),p.viewStartDate=n(p.defaultView),p.draw());m=!1});(F=e.scrollContainer(g))&&e.addEvent(F,"scroll",
+function(b){g.blur()});p.subscribe("change",function(){m||(g.value=p.getSelected(),e.fireEvent(g,"change"))})}};r.Input.prototype=e.merge(r.prototype,{defaults:e.merge(r.prototype.defaults,{format:"MM/DD/YYYY",side:"bottom",closeButton:!0,offsetLeft:0,offsetTop:0}),classes:e.merge(r.prototype.classes,{positioned:"k-floating",closeButton:"k-btn-close"}),show:function(){var b=this.container,c=b.style,g=this.input,f=e.getPosition(g),k=e.scrollContainer(g),m=k?k.scrollTop:0,k=k?k.scrollLeft:0,p=this.settings;
+c.display="";switch(p.side){case "left":c.left=f.left-e.getWidth(b)+p.offsetLeft-k+"px";c.top=f.top+p.offsetTop-m+"px";break;case "right":c.left=f.left+e.getWidth(g)-k+"px";c.top=f.top+p.offsetTop-m+"px";break;case "top":c.left=f.left+p.offsetLeft-k+"px";c.top=f.top-e.getHeight(b)+p.offsetTop-m+"px";break;case "bottom right":c.left=f.left-e.getWidth(b)+e.getWidth(g)+p.offsetLeft+"px";c.top=f.top+e.getHeight(g)+p.offsetTop-m+"px";break;default:c.left=f.left+p.offsetLeft-k+"px",c.top=f.top+e.getHeight(g)+
+p.offsetTop-m+"px"}c.position=e.isFixed(g)?"fixed":"absolute";this.publish("show",this)},hide:function(){this.container.style.display="none";this.publish("hide",this)},destroy:function(){var b=this.container,c=this.input;e.removeEvent(b,"mousedown",this._events.containerMousedown);e.removeEvent(window.document,"mousedown",this._events.documentMousedown);e.removeEvent(c,"focus",this._events.inputFocus);e.removeEvent(c,"blur",this._events.inputBlur);e.removeEvent(c,"keyup",this._events.inputKeyup);
+b.parentNode&&b.parentNode.removeChild(b)}});var Q=function(b){b||(b=this);var c=b.c_||{};b.publish=function(b,f,k){for(var e=(b=c[b])?b.length:0,p;e--;)if(p=b[e].apply(f,k||[]),"boolean"===typeof p)return p};b.subscribe=function(b,f,e){c[b]||(c[b]=[]);e?c[b].push(f):c[b].unshift(f);return[b,f]};b.unsubscribe=function(b){var f=c[b[0]];b=b[1];for(var e=f?f.length:0;e--;)f[e]===b&&f.splice(e,1)}};(function(b){function c(a,d,l){switch(arguments.length){case 2:return null!=a?a:d;case 3:return null!=a?
+a:null!=d?d:l;default:throw Error("Implement me");}}function g(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function f(a){!1===h.suppressDeprecationWarnings&&"undefined"!==typeof console&&console.warn&&console.warn("Deprecation warning: "+a)}function e(a,d){var l=!0;return v(function(){l&&(f(a),l=!1);return d.apply(this,arguments)},d)}function m(a,d){return function(l){return x(a.call(this,l),
+d)}}function p(a,d){return function(l){return this.localeData().ordinal(a.call(this,l),d)}}function n(){}function t(a,d){!1!==d&&ia(a);u(this,a);this._d=new Date(+a._d);!1===S&&(S=!0,h.updateOffset(this),S=!1)}function r(a){a=ja(a);var d=a.year||0,l=a.quarter||0,b=a.month||0,c=a.week||0,g=a.day||0;this._milliseconds=+(a.millisecond||0)+1E3*(a.second||0)+6E4*(a.minute||0)+36E5*(a.hour||0);this._days=+g+7*c;this._months=+b+3*l+12*d;this._data={};this._locale=h.localeData();this._bubble()}function v(a,
+d){for(var l in d)G.call(d,l)&&(a[l]=d[l]);G.call(d,"toString")&&(a.toString=d.toString);G.call(d,"valueOf")&&(a.valueOf=d.valueOf);return a}function u(a,d){var l,b,c;"undefined"!==typeof d._isAMomentObject&&(a._isAMomentObject=d._isAMomentObject);"undefined"!==typeof d._i&&(a._i=d._i);"undefined"!==typeof d._f&&(a._f=d._f);"undefined"!==typeof d._l&&(a._l=d._l);"undefined"!==typeof d._strict&&(a._strict=d._strict);"undefined"!==typeof d._tzm&&(a._tzm=d._tzm);"undefined"!==typeof d._isUTC&&(a._isUTC=
+d._isUTC);"undefined"!==typeof d._offset&&(a._offset=d._offset);"undefined"!==typeof d._pf&&(a._pf=d._pf);"undefined"!==typeof d._locale&&(a._locale=d._locale);if(0<M.length)for(l in M)b=M[l],c=d[b],"undefined"!==typeof c&&(a[b]=c);return a}function q(a){return 0>a?Math.ceil(a):Math.floor(a)}function x(a,d,l){for(var b=""+Math.abs(a);b.length<d;)b="0"+b;return(0<=a?l?"+":"":"-")+b}function A(a,d){var l={milliseconds:0,months:0};l.months=d.month()-a.month()+12*(d.year()-a.year());a.clone().add(l.months,
+"M").isAfter(d)&&--l.months;l.milliseconds=+d-+a.clone().add(l.months,"M");return l}function K(a,d){var l;d=T(d,a);a.isBefore(d)?l=A(a,d):(l=A(d,a),l.milliseconds=-l.milliseconds,l.months=-l.months);return l}function O(a,d){return function(l,b){var c;null===b||isNaN(+b)||(ka[d]||(f("moment()."+d+"(period, number) is deprecated. Please use moment()."+d+"(number, period)."),ka[d]=!0),c=l,l=b,b=c);c=h.duration("string"===typeof l?+l:l,b);ga(this,c,a);return this}}function ga(a,d,l,b){var c=d._milliseconds,
+g=d._days;d=d._months;b=null==b?!0:b;c&&a._d.setTime(+a._d+c*l);g&&la(a,"Date",U(a,"Date")+g*l);d&&ma(a,U(a,"Month")+d*l);b&&h.updateOffset(a,g||d)}function L(a){return"[object Array]"===Object.prototype.toString.call(a)}function R(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function ha(a,d,l){var b=Math.min(a.length,d.length),c=Math.abs(a.length-d.length),g=0,h;for(h=0;h<b;h++)(l&&a[h]!==d[h]||!l&&w(a[h])!==w(d[h]))&&g++;return g+c}function z(a){if(a){var d=a.toLowerCase().replace(/(.)s$/,
+"$1");a=Ea[a]||Fa[d]||d}return a}function ja(a){var d={},l,b;for(b in a)G.call(a,b)&&(l=z(b))&&(d[l]=a[b]);return d}function Q(a){var d,l;if(0===a.indexOf("week"))d=7,l="day";else if(0===a.indexOf("month"))d=12,l="month";else return;h[a]=function(c,g){var f,e,k=h._locale[a],m=[];"number"===typeof c&&(g=c,c=b);e=function(a){a=h().utc().set(l,a);return k.call(h._locale,a,c||"")};if(null!=g)return e(g);for(f=0;f<d;f++)m.push(e(f));return m}}function w(a){a=+a;var d=0;0!==a&&isFinite(a)&&(d=0<=a?Math.floor(a):
+Math.ceil(a));return d}function V(a,d){return(new Date(Date.UTC(a,d+1,0))).getUTCDate()}function na(a,d,l){return H(h([a,11,31+d-l]),d,l).week}function W(a){return 0===a%4&&0!==a%100||0===a%400}function ia(a){var d;a._a&&-2===a._pf.overflow&&(d=0>a._a[1]||11<a._a[1]?1:1>a._a[2]||a._a[2]>V(a._a[0],a._a[1])?2:0>a._a[3]||24<a._a[3]||24===a._a[3]&&(0!==a._a[4]||0!==a._a[5]||0!==a._a[6])?3:0>a._a[4]||59<a._a[4]?4:0>a._a[5]||59<a._a[5]?5:0>a._a[6]||999<a._a[6]?6:-1,a._pf._overflowDayOfYear&&(0>d||2<d)&&
+(d=2),a._pf.overflow=d)}function oa(a){null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&0>a._pf.overflow&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length&&a._pf.bigHour===b));return a._isValid}function pa(a){return a?a.toLowerCase().replace("_","-"):a}function qa(a){var d=null;if(!I[a]&&Ga)try{d=h.locale(),require("./locale/"+a),h.locale(d)}catch(l){}return I[a]}
+function T(a,d){var l,b;return d._isUTC?(l=d.clone(),b=(h.isMoment(a)||R(a)?+a:+h(a))-+l,l._d.setTime(+l._d+b),h.updateOffset(l,!1),l):h(a).local()}function Ha(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function Ia(a){var d=a.match(ra),l,b;l=0;for(b=d.length;l<b;l++)d[l]=B[d[l]]?B[d[l]]:Ha(d[l]);return function(c){var g="";for(l=0;l<b;l++)g+=d[l]instanceof Function?d[l].call(c,a):d[l];return g}}function X(a,d){if(!a.isValid())return a.localeData().invalidDate();d=sa(d,
+a.localeData());Y[d]||(Y[d]=Ia(d));return Y[d](a)}function sa(a,d){function l(a){return d.longDateFormat(a)||a}var b=5;for(N.lastIndex=0;0<=b&&N.test(a);)a=a.replace(N,l),N.lastIndex=0,--b;return a}function Ja(a,d){var l=d._strict;switch(a){case "Q":return ta;case "DDDD":return ua;case "YYYY":case "GGGG":case "gggg":return l?Ka:La;case "Y":case "G":case "g":return Ma;case "YYYYYY":case "YYYYY":case "GGGGG":case "ggggg":return l?Na:Oa;case "S":if(l)return ta;case "SS":if(l)return va;case "SSS":if(l)return ua;
+case "DDD":return Pa;case "MMM":case "MMMM":case "dd":case "ddd":case "dddd":return Qa;case "a":case "A":return d._locale._meridiemParse;case "x":return Ra;case "X":return Sa;case "Z":case "ZZ":return Z;case "T":return Ta;case "SSSS":return Ua;case "MM":case "DD":case "YY":case "GG":case "gg":case "HH":case "hh":case "mm":case "ss":case "ww":case "WW":return l?va:wa;case "M":case "D":case "d":case "H":case "h":case "m":case "s":case "w":case "W":case "e":case "E":return wa;case "Do":return l?d._locale._ordinalParse:
+d._locale._ordinalParseLenient;default:var l=RegExp,b;b=Va(a.replace("\\","")).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");return new l(b)}}function aa(a){a=(a||"").match(Z)||[];a=((a[a.length-1]||[])+"").match(Wa)||["-",0,0];var d=+(60*a[1])+w(a[2]);return"+"===a[0]?d:-d}function ba(a){var d,b,g=[],f;if(!a._d){f=new Date;f=a._useUTC?[f.getUTCFullYear(),f.getUTCMonth(),f.getUTCDate()]:[f.getFullYear(),f.getMonth(),f.getDate()];if(a._w&&null==a._a[2]&&null==a._a[1]){var e,k,m;e=a._w;null!=e.GG||null!=
+e.W||null!=e.E?(d=1,m=4,b=c(e.GG,a._a[0],H(h(),1,4).year),k=c(e.W,1),e=c(e.E,1)):(d=a._locale._week.dow,m=a._locale._week.doy,b=c(e.gg,a._a[0],H(h(),d,m).year),k=c(e.w,1),null!=e.d?(e=e.d,e<d&&++k):e=null!=e.e?e.e+d:d);var n=ca(b,0,1).getUTCDay(),n=0===n?7:n;m=7*(k-1)+((null!=e?e:d)-d)+(d-n+(n>m?7:0)-(n<d?7:0))+1;d=0<m?b:b-1;b=0<m?m:(W(b-1)?366:365)+m;a._a[0]=d;a._dayOfYear=b}a._dayOfYear&&(b=c(a._a[0],f[0]),a._dayOfYear>(W(b)?366:365)&&(a._pf._overflowDayOfYear=!0),b=ca(b,0,a._dayOfYear),a._a[1]=
+b.getUTCMonth(),a._a[2]=b.getUTCDate());for(b=0;3>b&&null==a._a[b];++b)a._a[b]=g[b]=f[b];for(;7>b;b++)a._a[b]=g[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[3]&&0===a._a[4]&&0===a._a[5]&&0===a._a[6]&&(a._nextDay=!0,a._a[3]=0);a._d=(a._useUTC?ca:Xa).apply(null,g);null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm);a._nextDay&&(a._a[3]=24)}}function Ya(a){var d;a._d||(d=ja(a._i),a._a=[d.year,d.month,d.day||d.date,d.hour,d.minute,d.second,d.millisecond],ba(a))}function da(a){if(a._f===h.ISO_8601)xa(a);
+else{a._a=[];a._pf.empty=!0;var d=""+a._i,l,c,g,f,e,k=d.length,m=0;g=sa(a._f,a._locale).match(ra)||[];for(l=0;l<g.length;l++){f=g[l];if(c=(d.match(Ja(f,a))||[])[0])e=d.substr(0,d.indexOf(c)),0<e.length&&a._pf.unusedInput.push(e),d=d.slice(d.indexOf(c)+c.length),m+=c.length;if(B[f]){c?a._pf.empty=!1:a._pf.unusedTokens.push(f);e=a;var n=void 0,p=e._a;switch(f){case "Q":null!=c&&(p[1]=3*(w(c)-1));break;case "M":case "MM":null!=c&&(p[1]=w(c)-1);break;case "MMM":case "MMMM":n=e._locale.monthsParse(c,f,
+e._strict);null!=n?p[1]=n:e._pf.invalidMonth=c;break;case "D":case "DD":null!=c&&(p[2]=w(c));break;case "Do":null!=c&&(p[2]=w(parseInt(c.match(/\d{1,2}/)[0],10)));break;case "DDD":case "DDDD":null!=c&&(e._dayOfYear=w(c));break;case "YY":p[0]=h.parseTwoDigitYear(c);break;case "YYYY":case "YYYYY":case "YYYYYY":p[0]=w(c);break;case "a":case "A":e._meridiem=c;break;case "h":case "hh":e._pf.bigHour=!0;case "H":case "HH":p[3]=w(c);break;case "m":case "mm":p[4]=w(c);break;case "s":case "ss":p[5]=w(c);break;
+case "S":case "SS":case "SSS":case "SSSS":p[6]=w(1E3*("0."+c));break;case "x":e._d=new Date(w(c));break;case "X":e._d=new Date(1E3*parseFloat(c));break;case "Z":case "ZZ":e._useUTC=!0;e._tzm=aa(c);break;case "dd":case "ddd":case "dddd":n=e._locale.weekdaysParse(c);null!=n?(e._w=e._w||{},e._w.d=n):e._pf.invalidWeekday=c;break;case "w":case "ww":case "W":case "WW":case "d":case "e":case "E":f=f.substr(0,1);case "gggg":case "GGGG":case "GGGGG":f=f.substr(0,2);c&&(e._w=e._w||{},e._w[f]=w(c));break;case "gg":case "GG":e._w=
+e._w||{},e._w[f]=h.parseTwoDigitYear(c)}}else a._strict&&!c&&a._pf.unusedTokens.push(f)}a._pf.charsLeftOver=k-m;0<d.length&&a._pf.unusedInput.push(d);!0===a._pf.bigHour&&12>=a._a[3]&&(a._pf.bigHour=b);d=a._a;g=a._locale;l=a._a[3];k=a._meridiem;null!=k&&(null!=g.meridiemHour?l=g.meridiemHour(l,k):null!=g.isPM&&((g=g.isPM(k))&&12>l&&(l+=12),g||12!==l||(l=0)));d[3]=l;ba(a);ia(a)}}function Va(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,g,e){return b||c||g||e})}function xa(a){var d,
+b,c=a._i,g=Za.exec(c);if(g){a._pf.iso=!0;d=0;for(b=ea.length;d<b;d++)if(ea[d][1].exec(c)){a._f=ea[d][0]+(g[6]||" ");break}d=0;for(b=fa.length;d<b;d++)if(fa[d][1].exec(c)){a._f+=fa[d][0];break}c.match(Z)&&(a._f+="Z");da(a)}else a._isValid=!1}function $a(a){xa(a);!1===a._isValid&&(delete a._isValid,h.createFromInputFallback(a))}function ab(a,d){var b=[],c;for(c=0;c<a.length;++c)b.push(d(a[c],c));return b}function bb(a){var d=a._i,l;d===b?a._d=new Date:R(d)?a._d=new Date(+d):null!==(l=cb.exec(d))?a._d=
+new Date(+l[1]):"string"===typeof d?$a(a):L(d)?(a._a=ab(d.slice(0),function(a){return parseInt(a,10)}),ba(a)):"object"===typeof d?Ya(a):"number"===typeof d?a._d=new Date(d):h.createFromInputFallback(a)}function Xa(a,d,b,c,g,e,f){d=new Date(a,d,b,c,g,e,f);1970>a&&d.setFullYear(a);return d}function ca(a){var d=new Date(Date.UTC.apply(null,arguments));1970>a&&d.setUTCFullYear(a);return d}function db(a,d,b,c,g){return g.relativeTime(d||1,!!b,a,c)}function H(a,d,b){d=b-d;b-=a.day();b>d&&(b-=7);b<d-7&&
+(b+=7);a=h(a).add(b,"d");return{week:Math.ceil(a.dayOfYear()/7),year:a.year()}}function ya(a){var d=a._i,c=a._f;a._locale=a._locale||h.localeData(a._l);if(null===d||c===b&&""===d)return h.invalid({nullInput:!0});"string"===typeof d&&(a._i=d=a._locale.preparse(d));if(h.isMoment(d))return new t(d,!0);if(c)if(L(c)){var e,f,k;if(0===a._f.length)a._pf.invalidFormat=!0,a._d=new Date(NaN);else{for(d=0;d<a._f.length;d++)if(c=0,e=u({},a),null!=a._useUTC&&(e._useUTC=a._useUTC),e._pf=g(),e._f=a._f[d],da(e),
+oa(e)&&(c+=e._pf.charsLeftOver,c+=10*e._pf.unusedTokens.length,e._pf.score=c,null==k||c<k))k=c,f=e;v(a,f||e)}}else da(a);else bb(a);a=new t(a);a._nextDay&&(a.add(1,"d"),a._nextDay=b);return a}function za(a,d){var b,c;1===d.length&&L(d[0])&&(d=d[0]);if(!d.length)return h();b=d[0];for(c=1;c<d.length;++c)d[c][a](b)&&(b=d[c]);return b}function ma(a,d){var b;if("string"===typeof d&&(d=a.localeData().monthsParse(d),"number"!==typeof d))return a;b=Math.min(a.date(),V(a.year(),d));a._d["set"+(a._isUTC?"UTC":
+"")+"Month"](d,b);return a}function U(a,d){return a._d["get"+(a._isUTC?"UTC":"")+d]()}function la(a,d,b){return"Month"===d?ma(a,b):a._d["set"+(a._isUTC?"UTC":"")+d](b)}function C(a,d){return function(b){return null!=b?(la(this,a,b),h.updateOffset(this,d),this):U(this,a)}}function eb(a){h.duration.fn[a]=function(){return this._data[a]}}for(var h,fb="undefined"===typeof global||"undefined"!==typeof window&&window!==global.window?this:global,J=Math.round,G=Object.prototype.hasOwnProperty,y,I={},M=[],
+Ga="undefined"!==typeof module&&module&&module.exports,cb=/^\/?Date\((\-?\d+)/i,gb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,hb=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,ra=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,N=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,wa=/\d\d?/,Pa=/\d{1,3}/,
+La=/\d{1,4}/,Oa=/[+\-]?\d{1,6}/,Ua=/\d+/,Qa=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Z=/Z|[\+\-]\d\d:?\d\d/gi,Ta=/T/i,Ra=/[\+\-]?\d+/,Sa=/[\+\-]?\d+(\.\d{1,3})?/,ta=/\d/,va=/\d\d/,ua=/\d{3}/,Ka=/\d{4}/,Na=/[+-]?\d{6}/,Ma=/[+-]?\d+/,Za=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ea=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",
+/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],fa=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],Wa=/([\+\-]|\d\d)/gi,Aa={Milliseconds:1,Seconds:1E3,Minutes:6E4,Hours:36E5,Days:864E5,Months:2592E6,Years:31536E6},Ea={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",Q:"quarter",y:"year",DDD:"dayOfYear",e:"weekday",
+E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Fa={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Y={},E={s:45,m:45,h:22,d:26,M:11},Ba="DDD w W M D d".split(" "),Ca="MDHhmswW".split(""),B={M:function(){return this.month()+1},MMM:function(a){return this.localeData().monthsShort(this,a)},MMMM:function(a){return this.localeData().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},
+dd:function(a){return this.localeData().weekdaysMin(this,a)},ddd:function(a){return this.localeData().weekdaysShort(this,a)},dddd:function(a){return this.localeData().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return x(this.year()%100,2)},YYYY:function(){return x(this.year(),4)},YYYYY:function(){return x(this.year(),5)},YYYYYY:function(){var a=this.year();return(0<=a?"+":"-")+x(Math.abs(a),6)},gg:function(){return x(this.weekYear()%100,2)},
+gggg:function(){return x(this.weekYear(),4)},ggggg:function(){return x(this.weekYear(),5)},GG:function(){return x(this.isoWeekYear()%100,2)},GGGG:function(){return x(this.isoWeekYear(),4)},GGGGG:function(){return x(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},
+h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return w(this.milliseconds()/100)},SS:function(){return x(w(this.milliseconds()/10),2)},SSS:function(){return x(this.milliseconds(),3)},SSSS:function(){return x(this.milliseconds(),3)},Z:function(){var a=this.utcOffset(),d="+";0>a&&(a=-a,d="-");return d+x(w(a/60),2)+":"+x(w(a)%60,2)},ZZ:function(){var a=this.utcOffset(),d="+";0>a&&(a=-a,d="-");return d+x(w(a/60),2)+x(w(a)%
+60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},x:function(){return this.valueOf()},X:function(){return this.unix()},Q:function(){return this.quarter()}},ka={},Da=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"],S=!1;Ba.length;)y=Ba.pop(),B[y+"o"]=p(B[y],y);for(;Ca.length;)y=Ca.pop(),B[y+y]=m(B[y],2);B.DDDD=m(B.DDD,3);v(n.prototype,{set:function(a){var d,b;for(b in a)d=a[b],"function"===typeof d?this[b]=d:this["_"+b]=d;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+
+"|"+/\d{1,2}/.source)},_months:"January February March April May June July August September October November December".split(" "),months:function(a){return this._months[a.month()]},_monthsShort:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a,d,b){var c,e;this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]);for(c=0;12>c;c++)if(e=h.utc([2E3,c]),b&&!this._longMonthsParse[c]&&
+(this._longMonthsParse[c]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[c]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),b||this._monthsParse[c]||(e="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[c]=new RegExp(e.replace(".",""),"i")),b&&"MMMM"===d&&this._longMonthsParse[c].test(a)||b&&"MMM"===d&&this._shortMonthsParse[c].test(a)||!b&&this._monthsParse[c].test(a))return c},_weekdays:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),
+weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun Mon Tue Wed Thu Fri Sat".split(" "),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su Mo Tu We Th Fr Sa".split(" "),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var d,b;this._weekdaysParse||(this._weekdaysParse=[]);for(d=0;7>d;d++)if(this._weekdaysParse[d]||(b=h([2E3,1]).day(d),b="^"+this.weekdays(b,"")+"|^"+this.weekdaysShort(b,"")+"|^"+this.weekdaysMin(b,
+""),this._weekdaysParse[d]=new RegExp(b.replace(".",""),"i")),this._weekdaysParse[d].test(a))return d},_longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},longDateFormat:function(a){var d=this._longDateFormat[a];!d&&this._longDateFormat[a.toUpperCase()]&&(d=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=d);return d},isPM:function(a){return"p"===(a+
+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,d,b){return 11<a?b?"pm":"PM":b?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,d,b){a=this._calendar[a];return"function"===typeof a?a.apply(d,[b]):a},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",
+M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,d,b,c){var e=this._relativeTime[b];return"function"===typeof e?e(a,d,b,c):e.replace(/%d/i,a)},pastFuture:function(a,d){var b=this._relativeTime[0<a?"future":"past"];return"function"===typeof b?b(d):b.replace(/%s/i,d)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",_ordinalParse:/\d{1,2}/,preparse:function(a){return a},postformat:function(a){return a},week:function(a){return H(a,this._week.dow,this._week.doy).week},
+_week:{dow:0,doy:6},firstDayOfWeek:function(){return this._week.dow},firstDayOfYear:function(){return this._week.doy},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}});h=function(a,d,c,e){var f;"boolean"===typeof c&&(e=c,c=b);f={_isAMomentObject:!0};f._i=a;f._f=d;f._l=c;f._strict=e;f._isUTC=!1;f._pf=g();return ya(f)};h.suppressDeprecationWarnings=!1;h.createFromInputFallback=e("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",
+function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))});h.min=function(){var a=[].slice.call(arguments,0);return za("isBefore",a)};h.max=function(){var a=[].slice.call(arguments,0);return za("isAfter",a)};h.utc=function(a,d,c,e){var f;"boolean"===typeof c&&(e=c,c=b);f={_isAMomentObject:!0,_useUTC:!0,_isUTC:!0};f._l=c;f._i=a;f._f=d;f._strict=e;f._pf=g();return ya(f).utc()};h.unix=function(a){return h(1E3*a)};h.duration=function(a,d){var b=a,c=null,e;h.isDuration(a)?b={ms:a._milliseconds,d:a._days,
+M:a._months}:"number"===typeof a?(b={},d?b[d]=a:b.milliseconds=a):(c=gb.exec(a))?(e="-"===c[1]?-1:1,b={y:0,d:w(c[2])*e,h:w(c[3])*e,m:w(c[4])*e,s:w(c[5])*e,ms:w(c[6])*e}):(c=hb.exec(a))?(e="-"===c[1]?-1:1,b=function(a){a=a&&parseFloat(a.replace(",","."));return(isNaN(a)?0:a)*e},b={y:b(c[2]),M:b(c[3]),d:b(c[4]),h:b(c[5]),m:b(c[6]),s:b(c[7]),w:b(c[8])}):null==b?b={}:"object"===typeof b&&("from"in b||"to"in b)&&(c=K(h(b.from),h(b.to)),b={},b.ms=c.milliseconds,b.M=c.months);b=new r(b);h.isDuration(a)&&
+G.call(a,"_locale")&&(b._locale=a._locale);return b};h.version="2.9.0";h.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";h.ISO_8601=function(){};h.momentProperties=M;h.updateOffset=function(){};h.relativeTimeThreshold=function(a,d){if(E[a]===b)return!1;if(d===b)return E[a];E[a]=d;return!0};h.lang=e("moment.lang is deprecated. Use moment.locale instead.",function(a,b){return h.locale(a,b)});h.locale=function(a,b){var c;a&&(c="undefined"!==typeof b?h.defineLocale(a,b):h.localeData(a))&&(h.duration._locale=h._locale=
+c);return h._locale._abbr};h.defineLocale=function(a,b){if(null!==b)return b.abbr=a,I[a]||(I[a]=new n),I[a].set(b),h.locale(a),I[a];delete I[a];return null};h.langData=e("moment.langData is deprecated. Use moment.localeData instead.",function(a){return h.localeData(a)});h.localeData=function(a){var b;a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr);if(!a)return h._locale;if(!L(a)){if(b=qa(a))return b;a=[a]}a:{b=0;for(var c,e,f,g;b<a.length;){g=pa(a[b]).split("-");c=g.length;for(e=(e=pa(a[b+1]))?
+e.split("-"):null;0<c;){if(f=qa(g.slice(0,c).join("-"))){a=f;break a}if(e&&e.length>=c&&ha(g,e,!0)>=c-1)break;c--}b++}a=null}return a};h.isMoment=function(a){return a instanceof t||null!=a&&G.call(a,"_isAMomentObject")};h.isDuration=function(a){return a instanceof r};for(y=Da.length-1;0<=y;--y)Q(Da[y]);h.normalizeUnits=function(a){return z(a)};h.invalid=function(a){var b=h.utc(NaN);null!=a?v(b._pf,a):b._pf.userInvalidated=!0;return b};h.parseZone=function(){return h.apply(null,arguments).parseZone()};
+h.parseTwoDigitYear=function(a){return w(a)+(68<w(a)?1900:2E3)};h.isDate=R;v(h.fn=t.prototype,{clone:function(){return h(this)},valueOf:function(){return+this._d-6E4*(this._offset||0)},unix:function(){return Math.floor(+this/1E3)},toString:function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=h(this).utc();return 0<a.year()&&9999>=a.year()?"function"===typeof Date.prototype.toISOString?
+this.toDate().toISOString():X(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):X(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){return[this.year(),this.month(),this.date(),this.hours(),this.minutes(),this.seconds(),this.milliseconds()]},isValid:function(){return oa(this)},isDSTShifted:function(){return this._a?this.isValid()&&0<ha(this._a,(this._isUTC?h.utc(this._a):h(this._a)).toArray()):!1},parsingFlags:function(){return v({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(a){return this.utcOffset(0,
+a)},local:function(a){this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(this._dateUtcOffset(),"m"));return this},format:function(a){a=X(this,a||h.defaultFormat);return this.localeData().postformat(a)},add:O(1,"add"),subtract:O(-1,"subtract"),diff:function(a,b,c){a=T(a,this);var e=6E4*(a.utcOffset()-this.utcOffset());b=z(b);if("year"===b||"month"===b||"quarter"===b){var e=12*(a.year()-this.year())+(a.month()-this.month()),f=this.clone().add(e,"months"),g;0>a-f?(g=this.clone().add(e-
+1,"months"),a=(a-f)/(f-g)):(g=this.clone().add(e+1,"months"),a=(a-f)/(g-f));a=-(e+a);"quarter"===b?a/=3:"year"===b&&(a/=12)}else a=this-a,a="second"===b?a/1E3:"minute"===b?a/6E4:"hour"===b?a/36E5:"day"===b?(a-e)/864E5:"week"===b?(a-e)/6048E5:a;return c?a:q(a)},from:function(a,b){return h.duration({to:this,from:a}).locale(this.locale()).humanize(!b)},fromNow:function(a){return this.from(h(),a)},calendar:function(a){a=a||h();var b=T(a,this).startOf("day"),b=this.diff(b,"days",!0),b=-6>b?"sameElse":
+-1>b?"lastWeek":0>b?"lastDay":1>b?"sameDay":2>b?"nextDay":7>b?"nextWeek":"sameElse";return this.format(this.localeData().calendar(b,this,h(a)))},isLeapYear:function(){return W(this.year())},isDST:function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();if(null!=a){a:{var c=this.localeData();if("string"===typeof a)if(isNaN(a)){if(a=c.weekdaysParse(a),"number"!==typeof a){a=
+null;break a}}else a=parseInt(a,10)}return this.add(a-b,"d")}return b},month:C("Month",!0),startOf:function(a){a=z(a);switch(a){case "year":this.month(0);case "quarter":case "month":this.date(1);case "week":case "isoWeek":case "day":this.hours(0);case "hour":this.minutes(0);case "minute":this.seconds(0);case "second":this.milliseconds(0)}"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1);"quarter"===a&&this.month(3*Math.floor(this.month()/3));return this},endOf:function(a){a=z(a);return a===
+b||"millisecond"===a?this:this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms")},isAfter:function(a,b){b=z("undefined"!==typeof b?b:"millisecond");return"millisecond"===b?(a=h.isMoment(a)?a:h(a),+this>+a):(h.isMoment(a)?+a:+h(a))<+this.clone().startOf(b)},isBefore:function(a,b){var c;b=z("undefined"!==typeof b?b:"millisecond");if("millisecond"===b)return a=h.isMoment(a)?a:h(a),+this<+a;c=h.isMoment(a)?+a:+h(a);return+this.clone().endOf(b)<c},isBetween:function(a,b,c){return this.isAfter(a,
+c)&&this.isBefore(b,c)},isSame:function(a,b){var c;b=z(b||"millisecond");if("millisecond"===b)return a=h.isMoment(a)?a:h(a),+this===+a;c=+h(a);return+this.clone().startOf(b)<=c&&c<=+this.clone().endOf(b)},min:e("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(a){a=h.apply(null,arguments);return a<this?this:a}),max:e("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(a){a=h.apply(null,
+arguments);return a>this?this:a}),zone:e("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",function(a,b){return null!=a?("string"!==typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}),utcOffset:function(a,b){var c=this._offset||0,e;return null!=a?("string"===typeof a&&(a=aa(a)),16>Math.abs(a)&&(a*=60),!this._isUTC&&b&&(e=this._dateUtcOffset()),this._offset=a,this._isUTC=!0,null!=e&&this.add(e,"m"),c!==a&&(!b||this._changeInProgress?
+ga(this,h.duration(a-c,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,h.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?c:this._dateUtcOffset()},isLocal:function(){return!this._isUTC},isUtcOffset:function(){return this._isUTC},isUtc:function(){return this._isUTC&&0===this._offset},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){this._tzm?this.utcOffset(this._tzm):"string"===
+typeof this._i&&this.utcOffset(aa(this._i));return this},hasAlignedHourOffset:function(a){a=a?h(a).utcOffset():0;return 0===(this.utcOffset()-a)%60},daysInMonth:function(){return V(this.year(),this.month())},dayOfYear:function(a){var b=J((h(this).startOf("day")-h(this).startOf("year"))/864E5)+1;return null==a?b:this.add(a-b,"d")},quarter:function(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)},weekYear:function(a){var b=H(this,this.localeData()._week.dow,this.localeData()._week.doy).year;
+return null==a?b:this.add(a-b,"y")},isoWeekYear:function(a){var b=H(this,1,4).year;return null==a?b:this.add(a-b,"y")},week:function(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")},isoWeek:function(a){var b=H(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")},weekday:function(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},isoWeeksInYear:function(){return na(this.year(),
+1,4)},weeksInYear:function(){var a=this.localeData()._week;return na(this.year(),a.dow,a.doy)},get:function(a){a=z(a);return this[a]()},set:function(a,b){var c;if("object"===typeof a)for(c in a)this.set(c,a[c]);else if(a=z(a),"function"===typeof this[a])this[a](b);return this},locale:function(a){if(a===b)return this._locale._abbr;a=h.localeData(a);null!=a&&(this._locale=a);return this},lang:e("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",
+function(a){return a===b?this.localeData():this.locale(a)}),localeData:function(){return this._locale},_dateUtcOffset:function(){return 15*-Math.round(this._d.getTimezoneOffset()/15)}});h.fn.millisecond=h.fn.milliseconds=C("Milliseconds",!1);h.fn.second=h.fn.seconds=C("Seconds",!1);h.fn.minute=h.fn.minutes=C("Minutes",!1);h.fn.hour=h.fn.hours=C("Hours",!0);h.fn.date=C("Date",!0);h.fn.dates=e("dates accessor is deprecated. Use date instead.",C("Date",!0));h.fn.year=C("FullYear",!0);h.fn.years=e("years accessor is deprecated. Use year instead.",
+C("FullYear",!0));h.fn.days=h.fn.day;h.fn.months=h.fn.month;h.fn.weeks=h.fn.week;h.fn.isoWeeks=h.fn.isoWeek;h.fn.quarters=h.fn.quarter;h.fn.toJSON=h.fn.toISOString;h.fn.isUTC=h.fn.isUtc;v(h.duration.fn=r.prototype,{_bubble:function(){var a=this._milliseconds,b=this._days,c=this._months,e=this._data,f=0;e.milliseconds=a%1E3;a=q(a/1E3);e.seconds=a%60;a=q(a/60);e.minutes=a%60;a=q(a/60);e.hours=a%24;b+=q(a/24);f=q(400*b/146097);b-=q(146097*f/400);c+=q(b/30);b%=30;f+=q(c/12);e.days=b;e.months=c%12;e.years=
+f},abs:function(){this._milliseconds=Math.abs(this._milliseconds);this._days=Math.abs(this._days);this._months=Math.abs(this._months);this._data.milliseconds=Math.abs(this._data.milliseconds);this._data.seconds=Math.abs(this._data.seconds);this._data.minutes=Math.abs(this._data.minutes);this._data.hours=Math.abs(this._data.hours);this._data.months=Math.abs(this._data.months);this._data.years=Math.abs(this._data.years);return this},weeks:function(){return q(this.days()/7)},valueOf:function(){return this._milliseconds+
+864E5*this._days+this._months%12*2592E6+31536E6*w(this._months/12)},humanize:function(a){var b;b=!a;var c=this.localeData(),e=h.duration(this).abs(),f=J(e.as("s")),g=J(e.as("m")),k=J(e.as("h")),m=J(e.as("d")),n=J(e.as("M")),e=J(e.as("y")),f=f<E.s&&["s",f]||1===g&&["m"]||g<E.m&&["mm",g]||1===k&&["h"]||k<E.h&&["hh",k]||1===m&&["d"]||m<E.d&&["dd",m]||1===n&&["M"]||n<E.M&&["MM",n]||1===e&&["y"]||["yy",e];f[2]=b;f[3]=0<+this;f[4]=c;b=db.apply({},f);a&&(b=this.localeData().pastFuture(+this,b));return this.localeData().postformat(b)},
+add:function(a,b){var c=h.duration(a,b);this._milliseconds+=c._milliseconds;this._days+=c._days;this._months+=c._months;this._bubble();return this},subtract:function(a,b){var c=h.duration(a,b);this._milliseconds-=c._milliseconds;this._days-=c._days;this._months-=c._months;this._bubble();return this},get:function(a){a=z(a);return this[a.toLowerCase()+"s"]()},as:function(a){var b;a=z(a);if("month"===a||"year"===a)return b=this._days+this._milliseconds/864E5,b=this._months+400*b/146097*12,"month"===
+a?b:b/12;b=this._days+Math.round(this._months/12*146097/400);switch(a){case "week":return b/7+this._milliseconds/6048E5;case "day":return b+this._milliseconds/864E5;case "hour":return 24*b+this._milliseconds/36E5;case "minute":return 1440*b+this._milliseconds/6E4;case "second":return 86400*b+this._milliseconds/1E3;case "millisecond":return Math.floor(864E5*b)+this._milliseconds;default:throw Error("Unknown unit "+a);}},lang:h.fn.lang,locale:h.fn.locale,toIsoString:e("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",
+function(){return this.toISOString()}),toISOString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),e=Math.abs(this.hours()),f=Math.abs(this.minutes()),g=Math.abs(this.seconds()+this.milliseconds()/1E3);return this.asSeconds()?(0>this.asSeconds()?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(e||f||g?"T":"")+(e?e+"H":"")+(f?f+"M":"")+(g?g+"S":""):"P0D"},localeData:function(){return this._locale},toJSON:function(){return this.toISOString()}});h.duration.fn.toString=
+h.duration.fn.toISOString;for(y in Aa)G.call(Aa,y)&&eb(y.toLowerCase());h.duration.fn.asMilliseconds=function(){return this.as("ms")};h.duration.fn.asSeconds=function(){return this.as("s")};h.duration.fn.asMinutes=function(){return this.as("m")};h.duration.fn.asHours=function(){return this.as("h")};h.duration.fn.asDays=function(){return this.as("d")};h.duration.fn.asWeeks=function(){return this.as("weeks")};h.duration.fn.asMonths=function(){return this.as("M")};h.duration.fn.asYears=function(){return this.as("y")};
+h.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,b=1===w(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+b}});fb.moment=h}).call(r);"undefined"!==typeof n&&(r.moment=n);if(!r.moment)if(window.moment)r.moment=window.moment;else throw"Kalendae requires moment.js. You must use kalendae.standalone.js if moment is not available on the page.";n=r.moment;n.fn.yearDay=function(b){var c=Math.floor(this._d/864E5);return"undefined"===typeof b?c:this.add({d:b-c})};
+"undefined"===typeof jQuery||"function"!==typeof document.addEventListener&&!e.isIE8()||(jQuery.fn.kalendae=function(b){this.each(function(c,e){"INPUT"===e.tagName?jQuery(e).data("kalendae",new r.Input(e,b)):jQuery(e).data("kalendae",new r(jQuery.extend({},{attachTo:e},b)))});return this});return r})})();

=== added file 'media/js/sheduling.js'
--- media/js/sheduling.js	1970-01-01 00:00:00 +0000
+++ media/js/sheduling.js	2017-09-28 09:52:14 +0000
@@ -0,0 +1,387 @@
+
+var lastSelectedDates = []
+
+document.addEventListener('DOMContentLoaded', function(){ 
+    pageIsScheduling = !!document.getElementById('day-template');
+    pageIsMain = !!document.getElementById('main-choices');
+
+    if (pageIsScheduling) {
+        var calendar = createCalandar();
+        addTimeZoneWarningIfNeeded();
+        addPreviousDateFromUser(calendar);
+        addOtherUsersAvailabilities();
+        
+        //Validate btn
+        document.getElementById('validate-btn').onclick = function () {
+            sendDataAsForm(calendar);
+        }
+    } else if (pageIsMain) {
+       console.log('this is main, no js to execute')
+    } else {
+         addTimeZoneWarningIfNeeded();
+         addOtherUsersAvailabilities();
+    }
+
+
+
+}, false);
+
+
+function createCalandar() {
+    return new Kalendae('calandar', {
+        mode: 'multiple',
+        direction: 'today-future',
+        subscribe: {
+            'change': function (date) {
+                selectedDate = this.getSelected().split(",");
+            
+                //Cleanup of whitespace
+                for (var i in selectedDate) {
+                    selectedDate[i] = selectedDate[i].replace(' ' , '');
+                }
+
+                
+                dateToUpdate = array_diff(lastSelectedDates, selectedDate);
+
+                
+                updateAvailableDate(dateToUpdate[0])
+                lastSelectedDates = selectedDate;
+            }
+        }
+    });
+}
+
+//Add warning in case of disparency between system and profil timezone
+function addTimeZoneWarningIfNeeded() {
+    var userTimeZone = document.getElementById('django-data').getAttribute('user-time-zone')
+    var systemTimeZone = - new Date().getTimezoneOffset()/60
+    if ( systemTimeZone != userTimeZone) {
+        document.getElementById('timezone-error').removeAttribute("hidden");
+
+
+        profilTime = document.getElementsByClassName('profil-time');
+        for (var element in profilTime) {
+            profilTime[element].innerHTML = cleanAndAddSign(userTimeZone);
+        }
+        document.getElementById('system-time').innerHTML = cleanAndAddSign(systemTimeZone);
+    }
+}
+
+function addPreviousDateFromUser(calendar) {
+    //Populate the current date with already filled date by the user
+    old_availabilities_string_JSON = document.getElementById('django-data').getAttribute('day-to-fill')
+    old_availabilities_list = stringJSONtoJSList(old_availabilities_string_JSON)
+    
+    if (!old_availabilities_list[0] == ""){
+        dateToAdd = []
+        for (var hour in old_availabilities_list) {
+            dateString = old_availabilities_list[hour].substring(1,11);
+            if (!existInList(dateToAdd, dateString)){
+                dateToAdd.push(dateString)
+            }
+            
+        }
+        dateStringList = dateToAdd.join(',')
+
+        calendar.setSelected(dateStringList);
+
+        for (var hour in old_availabilities_list) {
+            hourString = old_availabilities_list[hour].substring(12,14);
+            dateString = old_availabilities_list[hour].substring(1,11);
+            hourString = removeZeroIfUnderTen(hourString);
+            displayHourForDate(dateString, hourString);
+        }
+
+    }
+}
+
+
+function addOtherUsersAvailabilities() {
+    //Populate the result area showing other users and their disponibilities
+    if (document.getElementById('django-data').getAttribute('users-to-fill')) {
+        var otherPlayeravailabilitiesJSON = document.getElementById('django-data').getAttribute('users-to-fill');
+        otherPlayeravailabilities = JSON.parse(otherPlayeravailabilitiesJSON)
+    }
+    
+    noOtherUser = true;
+    for (var user in otherPlayeravailabilities) {
+        noOtherUser = false;
+        dateList = otherPlayeravailabilities[user]
+        for (var hour in dateList) {
+            createUserDivOrUpdateIt(user, dateList[hour])
+        }
+        
+    }
+    if (noOtherUser) {
+        document.getElementById('no-user-to-display').removeAttribute("hidden");
+    }
+
+    
+}
+
+
+function sendDataAsForm(calendar) {
+    //Get informations from selected hours
+    var selectedDates = calendar.getSelected().split(",");
+    var selectedDatesList = [];
+    for (var d in selectedDates) {
+        //remove whitespace
+        selectedDates[d] = selectedDates[d].replace(" ", "");
+
+        var dateID = 'day-' + selectedDates[d];
+        dateObj = document.getElementById(dateID);
+        if (dateObj) {
+            hoursList = dateObj.getElementsByClassName('hours');
+            selectedHours = dateObj.getElementsByClassName('selected');
+            if (selectedHours[0]){
+                for (var h in hoursList) {
+                    if (hasClass(hoursList[h] , 'selected')){
+                        var hourAsDate = new Date(selectedDates[d] + "T" + addZeroIfUnderTen(h) + ":00:00")
+                        // we remove the from js because we consider that it is false for now
+
+                        // we get the hour in utc time and remove unneeded informations
+                        stringDate = hourAsDate.toISOString().slice(0,13)
+                        selectedDatesList.push(stringDate);
+                    }
+                }
+            } 
+        }
+    }
+
+    //Send informations to server
+    post('.', selectedDatesList)
+}
+
+//Add or remove available dates in the ui.
+function updateAvailableDate(date) {
+    newDateID = "day-" + date
+    dateAlreadyExist = !!document.getElementById(newDateID);
+    document.getElementById('second-step').removeAttribute('hidden');
+
+    if (dateAlreadyExist) {
+        document.getElementById(newDateID).remove();
+    } else {
+        var original = document.getElementById('day-template');
+        
+        // We clone the date and fix different attributes
+        var newDate = original.cloneNode(true);
+        newDate.id = "day-" + date;
+        newDate.removeAttribute("hidden");
+        var textDate = new Date(date);
+        textDate = textDate.toDateString();
+        newDate.getElementsByClassName('day-title')[0].innerHTML = '<h3>' + textDate + '</h3>';
+        
+        //We add the listeners to each hours One for the click event, the other for the hover when the mouse is pressed
+        hoursObj = newDate.getElementsByClassName('hours');
+        for (var i = 0; i < hoursObj.length; i++) {
+            hoursObj[i].addEventListener('click', updateHour, false);
+            hoursObj[i].addEventListener("mouseover", function(e){
+                if(e.buttons == 1 || e.buttons == 3){
+                    updateHour(e);
+                }
+            })
+        }
+
+        //we look for the order the new date should be in
+        daysList = document.getElementById('days-wrapper').getElementsByClassName('days');
+
+
+        //We finally add the new date
+        document.getElementById('days-wrapper').appendChild(newDate);
+    }
+
+}
+
+function updateHour (event) {
+    var div = (event.fromElement ? event.fromElement : event.currentTarget);
+
+    isAlreadySelected = hasClass(div, 'selected');
+
+    if (isAlreadySelected) {
+        div.className = 'hours';
+    } else {
+        div.className += ' selected';
+    }
+}
+
+function displayHourForDate(date, hour, user) {
+    var dateDivID = 'day-' + date
+    if (user) {
+        dateDivID = user + '-day-' + date
+    }
+    dateDiv = document.getElementById(dateDivID);
+    hourDiv = dateDiv.getElementsByClassName('hours');
+    for (var hourInDiv in hourDiv) {
+        if (hourInDiv == hour) {
+            hourDiv[hourInDiv].className += ' selected';
+        }
+    }
+}
+
+
+function createUserDivOrUpdateIt(user, availTime) {
+
+    if (!document.getElementById("user-" + user)){
+        var original = document.getElementById('other-user-template');
+    
+        // We clone the date and fix different attributes
+        var otherUser = original.cloneNode(true);
+        otherUser.id = "user-" + user;
+        otherUser.removeAttribute("hidden");
+        
+        var jsEventHTML = "/messages/compose/" + user
+        var imageHTML = '<img src="/wlmedia/forum/img/send_pm.png" alt="" class="middle"><span class="middle">Send PM</span>'
+        //var usernameTitle = '<button onclick="window.location.href='  + jsEventHTML + ';">' + imageHTML + '</button>'
+
+        var userTitle = otherUser.children[0]
+        var button =  document.createElement("button");
+        button.innerHTML = imageHTML;
+        button.onclick = function(){
+            window.location.href = '/messages/compose/' + user;
+        }
+        var usernameP = document.createElement('p')
+        usernameP.innerHTML = user;
+        userTitle.appendChild(usernameP)
+        userTitle.appendChild(button)
+    } else {
+        otherUser = document.getElementById("user-" + user);
+    }
+
+    var dtavailTime = new Date(availTime + ":00:00");
+    //Remove timezone offset which js automatically add...
+    js_offset = dtavailTime.getTimezoneOffset()/60
+    dtavailTime = dtavailTime.addHours(js_offset);
+
+    textDate = dtavailTime.toDateString();
+    var dateFormated = dtavailTime.getFullYear() + "-" + dtavailTime.getMonth() + '-' + dtavailTime.getDay()
+    var availTimeFormated = dtavailTime.getHours()
+
+    var originalDay = document.getElementById('other-day-template')
+
+    if (!document.getElementById(user + "-day-" + dateFormated)) {
+        var day = originalDay.cloneNode(true);
+        day.id = user + "-day-" + dateFormated;
+        day.removeAttribute("hidden");
+        day.getElementsByClassName('day-title')[0].innerHTML = '<h3>' + textDate + '</h3>'; 
+        otherUser.appendChild(day);
+    }
+    
+    document.getElementById('other-users-wrapper').appendChild(otherUser);
+    displayHourForDate(dateFormated, availTimeFormated, user);
+    
+}
+
+/*****************************/
+/********* utilities *********/
+/*****************************/
+// read as "Stackoverflow coded this"
+
+//Return diff between two list
+function array_diff(a1, a2) {
+    var a = [], diff=[];
+
+    for (var i = 0; i < a1.length; i++) {
+        a[a1[i]] = true;
+    }
+
+    for (var i=0; i < a2.length; i++) {
+        if (a[a2[i]]) {
+            delete a[a2[i]];
+        } else {
+            a[a2[i]] = true;
+        }
+    }
+
+    for (var k in a) {
+        diff.push(k)
+    }
+
+    return diff
+}
+
+function hasClass(element, cls) {
+    return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
+}
+
+//We need a custom function to submit a form because our data isn't formated as a form.
+function post(path, params, method) {
+    method = method || "post"; // Set method to post by default if not specified.
+
+    // The rest of this code assumes you are not using a library.
+    // It can be made less wordy if you use one.
+    var form = document.createElement("form");
+    form.setAttribute("method", method);
+    form.setAttribute("action", path);
+
+
+    for(var key in params) {
+            var hiddenField = document.createElement("input");
+            hiddenField.setAttribute("type", "hidden");
+            hiddenField.setAttribute("name", key);
+            hiddenField.setAttribute("value", params[key]);
+
+            form.appendChild(hiddenField);
+    }
+
+    //CSRF token
+    var csrf_div = document.createElement("div");
+    csrf_div.innerHTML = document.getElementById('django-data').getAttribute('csrf-token')
+    form.appendChild(csrf_div);
+
+    document.body.appendChild(form);
+    form.submit();
+}
+
+function cleanJSONfromWhiteSpace(json) {
+    var name, newName;
+    for (var name in json) {
+        // Get the name without spaces
+        newName = name.replace(/ /g, "");
+        // If that's different...
+        if (newName != name) {
+            // Create the new property
+            json[newName] = json[name];
+            // Delete the old one
+            delete json[name];
+        }
+    }
+    return json;
+}
+
+function stringJSONtoJSList(json) {
+    //removes brackets
+    json = json.substring(1, json.length-1);
+    var jsonList= json.split(",")
+
+    for (var i in jsonList){
+        jsonList[i] = jsonList[i].replace(/\s/g, '');
+    }
+
+    return jsonList
+
+}
+
+function addZeroIfUnderTen(number) {
+    return ('0' + number).slice(-2)
+}
+
+function removeZeroIfUnderTen(number) {
+    return parseInt(number, 10);
+}
+
+Date.prototype.addHours = function(h) {    
+   this.setTime(this.getTime() + (h*60*60*1000)); 
+   return this;   
+}
+
+function existInList(list, value) {
+    return list.indexOf(value) > -1
+}
+
+function cleanAndAddSign(number) {
+    if (number < 0) {
+        return '- ' + parseInt(number)
+    } else {
+        return '+ ' + parseInt(number)
+    }
+}
\ No newline at end of file

=== modified file 'settings.py'
--- settings.py	2017-08-21 19:13:19 +0000
+++ settings.py	2017-09-28 09:52:14 +0000
@@ -94,6 +94,7 @@
     'wlmaps',
     'wlscreens',
     'wlggz',
+    'wlscheduling',
 
     # Modified 3rd party apps
     'wiki',  # This is based on wikiapp, but has some local modifications

=== modified file 'templates/navigation.html'
--- templates/navigation.html	2017-09-23 08:52:36 +0000
+++ templates/navigation.html	2017-09-28 09:52:14 +0000
@@ -55,6 +55,7 @@
 			<li><a href="https://bugs.launchpad.net/widelands-website"; target="_blank">Website Bugtracker</a></li>
 		</ul>
 	</li>
+	<li><a href="{% url 'scheduling_main' %}">Scheduling</a></li>	
 </ul>
 <div class="searchBox posRight">
 	<form method="post" action="/search/">

=== added directory 'templates/wlscheduling'
=== added file 'templates/wlscheduling/base.html'
--- templates/wlscheduling/base.html	1970-01-01 00:00:00 +0000
+++ templates/wlscheduling/base.html	2017-09-28 09:52:14 +0000
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+{% block extra_head %}
+
+<link  rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/kalendae.css" >
+<link  rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/scheduling.css" >
+
+<script src="{{ MEDIA_URL }}js/kalendae.min.js" type="text/javascript"></script>
+<script src="{{ MEDIA_URL }}js/sheduling.js" type="text/javascript"></script>
+{% endblock %}
\ No newline at end of file

=== added file 'templates/wlscheduling/find.html'
--- templates/wlscheduling/find.html	1970-01-01 00:00:00 +0000
+++ templates/wlscheduling/find.html	2017-09-28 09:52:14 +0000
@@ -0,0 +1,40 @@
+
+
+{% extends "wlscheduling/base.html" %}
+{% comment %}
+   vim:ft=htmldjango
+{% endcomment %}
+
+{% block content %}
+
+<div class="blogEntry">
+    <h1>Times other players are available</h1>
+    <div id="timezone-error" class="errormessage" hidden="hidden">WARNING! The time indicated by your system (UTC <span id="system-time"></span>) is different from the one stored in your profile (UTC <span id="profil-time"></span>). By default we will use the one stored in your profile.<br /> <a href="{% url 'profile_edit' %}">Edit Profile</a></div>
+    <div id="other-users-wrapper"></div>
+    <div id="no-user-to-display" hidden="hidden">Sorry currently there isn't anybody who has scheduled a gaming session. This shouldn't happen. Who doesn't want to play to widelands????!! :O :O</div>
+
+</div>
+
+<!-- TODO entirely in JS? -->
+<div id="other-day-template" hidden="hidden">
+    <div class="day-title"></div>
+    <div id="hours-wrapper" class="hours-wrapper" >
+        {% for i in "xxxxxxxxxxxxxxxxxxxxxxxx" %}
+            <div class="hours" title="{{ forloop.counter0 }} to {{ forloop.counter0|add:1 }} hour"></div>
+        {% endfor %}
+    </div>
+</div>
+
+
+<!-- TODO remove this template and do it entirely in js (it doesn't need any django value) -->
+<div id="other-user-template" class="other-user-div" hidden="hidden">
+    <div class="title"></div>
+</div>
+
+
+
+<!-- Div to send django data to js file -->
+<div id="django-data" user-time-zone="{{user.wlprofile.time_zone}}" users-to-fill="{{other_users_availabilities}}"></div>
+
+
+{% endblock %}
\ No newline at end of file

=== added file 'templates/wlscheduling/main.html'
--- templates/wlscheduling/main.html	1970-01-01 00:00:00 +0000
+++ templates/wlscheduling/main.html	2017-09-28 09:52:14 +0000
@@ -0,0 +1,21 @@
+
+{% extends "wlscheduling/base.html" %}
+{% comment %}
+   vim:ft=htmldjango
+{% endcomment %}
+
+{% block content %}
+
+<div class="blogEntry">
+    <h1>Welcome in the scheduling module!</h1>
+    <div id="main-choices" class="main-choices">
+        <a href="{% url 'scheduling_scheduling' %}" >
+            <button title="You know when you will be available to play and want to display when you're available and find other players that will be available at these hours">Define your playtime and find a game</button>
+        </a>
+        <a href="{% url 'scheduling_find' %}" >
+            <button title="You just want to know when everybody is going to be playing" >Show other users playtime</button>
+        </a>
+    </div>
+</div>
+
+{% endblock %}
\ No newline at end of file

=== added file 'templates/wlscheduling/scheduling.html'
--- templates/wlscheduling/scheduling.html	1970-01-01 00:00:00 +0000
+++ templates/wlscheduling/scheduling.html	2017-09-28 09:52:14 +0000
@@ -0,0 +1,67 @@
+
+{% extends "wlscheduling/base.html" %}
+{% comment %}
+   vim:ft=htmldjango
+{% endcomment %}
+
+
+{% block content %}
+
+<h1>Multiplayer</h1>
+
+<div class="blogEntry">
+    <h2>Select the dates you'll be available on</h2>
+    <h3 id="timezone-msg">You are currently noted as UTC <span class="profil-time"></span></h3>
+    <div id="timezone-error" class="errormessage" hidden="hidden">WARNING! The time indicated by your system (UTC <span id="system-time"></span>) is different from the one stored in your profile (UTC <span class="profil-time"></span>). By default we will use the one stored in your profile.<br /> <a href="{% url 'profile_edit' %}">Edit Profile</a></div>
+    <div id="calandar"></div>
+
+    <div id="second-step" hidden="hidden">
+        <h2>Select the hours you'll be available on these dates</h2>
+        <div id="days-wrapper"></div>
+        <h2>Players that are currently available at the same hours as you</h2>
+        <div id="other-users-wrapper"></div>
+        <div id="no-user-to-display" hidden="hidden">Sorry, there are currently no players available at these hours. But your availabilities are noted, and another user might want to play with you!</div>
+
+
+        <button id="validate-btn">Update</button>
+    </div>
+</div>
+
+<!-- Templates for the js script -->
+<!-- TODO entirely in JS? -->
+<div id="day-template" class="day" hidden="hidden">
+    <div class="day-title"></div>
+    <div class="hours-title-wrapper">
+        {% for i in "xxxxxxxxxxxxxxxxxxxxxxxxx" %}
+            <p>{{ forloop.counter0 }}</p>
+        {% endfor %}
+    </div>
+    <div class="hours-wrapper">
+    {% for i in "xxxxxxxxxxxxxxxxxxxxxxxx" %}
+        <div class="hours"></div>
+    {% endfor %}
+        <div class="hidden-hour"></div>
+    </div>
+</div>
+
+<!-- TODO entirely in JS? -->
+<div id="other-day-template" hidden="hidden">
+    <div class="day-title"></div>
+    <div id="hours-wrapper" class="hours-wrapper" >
+        {% for i in "xxxxxxxxxxxxxxxxxxxxxxxx" %}
+            <div class="hours" title="{{ forloop.counter0 }} to {{ forloop.counter0|add:1 }} hour"></div>
+        {% endfor %}
+    </div>
+</div>
+
+
+<!-- TODO remove this template and do it entirely in js (it doesn't need any django value) -->
+<div id="other-user-template" class="other-user-div" hidden="hidden">
+    <div class="title"></div>
+</div>
+
+<!-- Div to send django data to js file -->
+<div id="django-data" user-time-zone="{{user.wlprofile.time_zone}}" day-to-fill = "{{ current_user_availabilities }}" users-to-fill="{{other_users_availabilities}}" csrf-token = "{% csrf_token %}"></div>
+
+
+{% endblock %}

=== modified file 'urls.py'
--- urls.py	2016-12-16 08:26:01 +0000
+++ urls.py	2017-09-28 09:52:14 +0000
@@ -68,6 +68,7 @@
     url(r'^maps/', include('wlmaps.urls')),
     url(r'^screenshots/', include('wlscreens.urls')),
     url(r'^ggz/', include('wlggz.urls')),
+    url(r'^scheduling/', include('wlscheduling.urls')),
 ]
 
 try:

=== added directory 'wlscheduling'
=== added file 'wlscheduling/__init__.py'
=== added directory 'wlscheduling/migrations'
=== added file 'wlscheduling/migrations/0001_initial.py'
--- wlscheduling/migrations/0001_initial.py	1970-01-01 00:00:00 +0000
+++ wlscheduling/migrations/0001_initial.py	2017-09-28 09:52:14 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+from django.conf import settings
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Availabilities',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('avail_time', models.DateTimeField(default=0, verbose_name=b'one hour of availability')),
+                ('user', models.ForeignKey(related_name='availabilities', to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]

=== added file 'wlscheduling/migrations/__init__.py'
=== added file 'wlscheduling/models.py'
--- wlscheduling/models.py	1970-01-01 00:00:00 +0000
+++ wlscheduling/models.py	2017-09-28 09:52:14 +0000
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+from django.db import models
+from django.contrib.auth.models import User
+
+
+class Availabilities(models.Model):
+    user = models.ForeignKey(User, related_name='availabilities')
+    avail_time = models.DateTimeField(
+        ('one hour of availability'), default=0)
\ No newline at end of file

=== added file 'wlscheduling/urls.py'
--- wlscheduling/urls.py	1970-01-01 00:00:00 +0000
+++ wlscheduling/urls.py	2017-09-28 09:52:14 +0000
@@ -0,0 +1,10 @@
+#!/usr/bin/env python -tt
+# encoding: utf-8
+from django.conf.urls import *
+from views import scheduling, scheduling_main, scheduling_find
+
+urlpatterns = [
+    url(r'^scheduling/$', scheduling, name='scheduling_scheduling'),
+    url(r'^main/$', scheduling_main, name='scheduling_main'),
+    url(r'^find/$', scheduling_find, name='scheduling_find'),
+]

=== added file 'wlscheduling/views.py'
--- wlscheduling/views.py	1970-01-01 00:00:00 +0000
+++ wlscheduling/views.py	2017-09-28 09:52:14 +0000
@@ -0,0 +1,118 @@
+#!/usr/bin/env python -tt
+# encoding: utf-8
+#
+
+from django.shortcuts import render
+from models import Availabilities
+from django.contrib.auth.decorators import login_required
+import json
+from datetime import datetime, timedelta
+
+
+#########
+# Views #
+#########
+def scheduling_main (request):
+    return render(request, 'wlscheduling/main.html')
+
+@login_required
+def scheduling_find (request):
+    current_user = request.user
+    other_users_availabilities = {}
+    for a in Availabilities.objects.exclude(user=current_user).order_by('avail_time'):
+        user_utc_dt_avail_time = a.avail_time
+        if datetime.now() < user_utc_dt_avail_time:
+            other_user = a.user
+            current_user_timezone = current_user.wlprofile.time_zone
+            user_dt_avail_time = user_utc_dt_avail_time + timedelta(hours= current_user_timezone)
+            user_string_avail_time = datetime.strftime(user_dt_avail_time, '%Y-%m-%dT%H')
+                
+            if not other_user.username in other_users_availabilities:
+                other_users_availabilities[other_user.username] = []
+            other_users_availabilities[other_user.username].append(user_string_avail_time)
+        else:
+            a.delete()
+    return render(request, 'wlscheduling/find.html', {'other_users_availabilities': json.dumps(other_users_availabilities)})
+
+@login_required
+def scheduling(request):
+    current_user = request.user
+    current_user_availabilities = []
+    user_timezone = current_user.wlprofile.time_zone
+    
+    # remove obsoletes dates from db
+    for a in Availabilities.objects.filter(user=current_user):
+        if datetime.utcnow() > a.avail_time:
+            a.delete()
+        
+    # Update of user's availabilities when post mode
+    if request.method == 'POST':
+        request_avail_times = []
+        for r in request.POST:
+            if r != "csrfmiddlewaretoken":
+                request_avail_times.append(request.POST[r])
+
+
+        current_user_availabilities = []
+        for avail_time in request_avail_times:
+            dt_avail_time = datetime.strptime(avail_time, '%Y-%m-%dT%H')
+            utc_dt_avail_time =  dt_avail_time + timedelta(hours= - user_timezone)
+
+            # We append the string to the list because apparently datetime objects cannot be stored in a list?
+            utc_string_avail_time = datetime.strftime(utc_dt_avail_time, '%Y-%m-%dT%H')
+            current_user_availabilities.append(utc_string_avail_time)
+        
+        
+        for request_avail_time in request_avail_times:
+            dt_avail_time = datetime.strptime(request_avail_time, '%Y-%m-%dT%H')
+            # Actual change of timezone, we got back to UTC
+            utc_dt_avail_time =  dt_avail_time + timedelta(hours= - user_timezone)
+            avail_time_already_exist = False
+            for a in Availabilities.objects.filter(user=current_user, avail_time=utc_dt_avail_time):
+                avail_time_already_exist = True
+            
+            if not avail_time_already_exist:
+                a = Availabilities.objects.create(
+                    user=current_user,
+                    avail_time=utc_dt_avail_time
+                )
+                a.save()
+        
+        # We remove any previously stored date that is not present in the request anymore
+        for a in Availabilities.objects.filter(user=current_user):
+            utc_dt_avail_time = a.avail_time
+            to_remove = True
+            for utc_string_avail_time in current_user_availabilities:
+                request_utc_dt_avail_time = datetime.strptime(utc_string_avail_time, '%Y-%m-%dT%H')
+                if utc_dt_avail_time == request_utc_dt_avail_time:
+                    to_remove = False
+            if to_remove:
+                a.delete()
+
+        
+
+    current_user_availabilities = []
+    for a in Availabilities.objects.filter(user=current_user).order_by('-avail_time'):
+        utc_dt_avail_time = a.avail_time
+        # We display the time with current user timezone
+        dt_avail_time = utc_dt_avail_time + timedelta(hours=user_timezone)
+        string_avail_time = datetime.strftime(dt_avail_time, '%Y-%m-%dT%H')
+        current_user_availabilities.append(string_avail_time)
+
+    other_users_availabilities = {}
+    for current_user_a in Availabilities.objects.filter(user=current_user).order_by('-avail_time'):
+        current_user_utc_dt_avail_time = current_user_a.avail_time
+        for a in Availabilities.objects.filter(avail_time=current_user_utc_dt_avail_time).exclude(user=current_user).order_by('-avail_time'):
+            user_utc_dt_avail_time = a.avail_time
+            other_user = a.user
+            current_user_timezone = current_user.wlprofile.time_zone
+            user_dt_avail_time = user_utc_dt_avail_time + timedelta(hours= current_user_timezone)
+            user_string_avail_time = datetime.strftime(user_dt_avail_time, '%Y-%m-%dT%H')
+             
+            if not other_user.username in other_users_availabilities:
+                other_users_availabilities[other_user.username] = []
+            other_users_availabilities[other_user.username].append(user_string_avail_time)
+
+
+    return render(request, 'wlscheduling/scheduling.html', {'current_user_availabilities': json.dumps(current_user_availabilities),
+'other_users_availabilities': json.dumps(other_users_availabilities)})
\ No newline at end of file


Follow ups