Skip to content

Instantly share code, notes, and snippets.

@LemoNode
Last active March 6, 2020 16:02
Show Gist options
  • Save LemoNode/d332002cc3fdfbdd5d4ab5e6b89b266d to your computer and use it in GitHub Desktop.
Save LemoNode/d332002cc3fdfbdd5d4ab5e6b89b266d to your computer and use it in GitHub Desktop.
fart knockers 3
<head>
<title>Sommar 2020</title>
<meta charset="utf-8">
<style>
:root {
--width: 825px;
}
body {
margin: auto;
width: var(--width);
font: 12px arial;
text-rendering: optimizeSpeed;
}
#nav {
position: sticky;
top: 0;
background-color: #fff;
}
#months {
display: grid;
grid-template-columns: repeat(12, 66px);
margin-left: 50px;
}
.small {
font-size: 12px;
font-family: consolas;
}
.medium {
font-size: 12px;
font-family: consolas;
}
.large {
font-size: 14px;
font-family: consolas;
}
button {
border: 1px solid transparent;
padding: 5px 5px 5px 5px;
border-radius: 3px;
outline: none;
}
#save {
background-color: steelblue;
color: #fff;
}
input, select {
border: 1px solid #fff;
padding: 3px 5px 3px 5px;
background: #f0f0f0;
outline: none;
font-size: 12px;
width: auto;
margin-right: 5px;
}
/*svg {
border: 1px solid #333;
}*/
rect:hover {
cursor: pointer;
}
#add-things {
display: grid;
grid-template-columns: repeat(2, auto);
height: 50px;
align-items: center;
}
</style>
</head>
<body onload="main();">
<div id="nav">
<br>
<h2 style="font-weight: lighter;">Semester önskelista 2020!</h2>
<div id="add-things">
<div>
<input
type="text"
placeholder="vgr-id"
style="width: 75px;"
id="select-id"
>
<select id="select-team">
<option disabled="true" selected="true">Team</option>
<option value="team1">Team 1</option>
<option value="team2">Team 2</option>
<option value="team3">Team 3</option>
</select>
<button id="add">Lägg till</button>
</div>
<div style="margin-left: 450px;">
<p>
Status: <b id="status"></b>
<button id="save">Spara</button>
</p>
</div>
</div>
<div id="months"></div>
</div>
<div id="calendar"></div>
<script>
// helpers
const h = {};
h.taker = index => {
return values => values.constructor.from(index, i => values[i]);
}
h.filter = (values, test) => {
const I = [], n = values.length;
for (let i = 0; i < n; ++i) {
if (test(values[i], i, values)) {
I.push(i);
}
}
return I;
}
function range (start, stop, step) {
const n = arguments.length;
start = +start, stop = +stop, step = n < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
return Uint32Array.from({length: Math.ceil((stop - start) / step)}, (_, i) => start + i * step);
}
h.ascending = (a, b) => {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
h.descending = (a, b) => {
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}
h.sort = (values, order = h.ascending) => {
return range(values.length).sort((i, j) => order(values[i], values[j]));
}
h.sorti = (values, index, order = h.ascending) => {
return index.slice().sort((i, j) => order(values[i], values[j]));
}
// start of program
const dom = {
calendar: document.querySelector("#calendar"),
body: document.querySelector("body"),
months: document.querySelector("#months"),
html: document.querySelector("html"),
vgrid: document.querySelector("#select-id"),
team: document.querySelector("#select-team"),
status: document.querySelector("#status"),
};
var socket = new WebSocket("ws://" + document.location.host + "/echo");
socket.onopen = function(evt) {
dom.status.innerHTML = "Kopplad";
console.log("Yay!");
}
socket.onmessage = function(evt) {
if (evt.data == "added") {
location.reload();
} else if (evt.data == "success") {
dom.status.innerHTML = "<b style='color: green;'>Sparat!</b>"
window.setTimeout(function() { dom.status.innerHTML = "Kopplad" }, 1500);
}
console.log(evt.data)
}
const server = {
data: ({{.}}),
};
const team_table = {
"team1": "steelblue",
"team2": "darkorange",
"team3": "pink",
};
const svg = {
width: 825,
height: 105,
padding: 18,
};
const rect = {
size: 15,
color1: "#fff",
color2: "#f0f0f0",
prev: null,
stroke1: "#ccc",
stroke2: "#ddd",
single: "#ddd",
text1: "#fff",
text2: "#666",
shift: 10,
};
const flags = {
month_colored: false,
day_colored: false,
id: null,
};
const user = {
day: "crimson",
dates: null,
clicked: [],
};
is_weekend = date => [0, 6].includes(date.getDay()) ? true : false;
new_week = (date, week) => date.getDay() == 0 ? week += 1 : week;
check_fill = (data, value, month) => {
if (data.includes(value)) {
return user.day;
} else if (month % 2 == 0) {
return rect.color1;
} else {
return rect.color2;
}
}
gen_text_month = dates => {
let html = "";
let months = [
"Jan", "Feb", "Mar", "Apr", "Maj", "Jun",
"Jul", "Aug", "Sep", "Okt", "Nov", "Dec"
];
for (let i = 0; i < months.length; i++) {
html += `<text class="large">${months[i]}</text>`;
}
return html;
}
gen_rect = (dates, index) => {
let html = "";
let week = 0;
let user = server.data.dates[index].split(",");
for (let i = 0; i < dates.length; i++) {
week = new_week(dates[i], week);
if (!is_weekend(dates[i])) {
let month = +dates[i].toLocaleDateString('se-SE', { month: 'numeric' });
let value = dates[i].toLocaleDateString('se-SE', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
});
html += `<rect
width="${rect.size}"
height="${rect.size}"
x="${(week * rect.size) + (month) + svg.padding}"
y="${(dates[i].getDay() * rect.size) + (105 * index)}"
fill="${check_fill(user, value, month)}"
stroke="${rect.stroke1}"
value="${value}"
></rect>`;
}
}
return html;
}
gen_text_days = (dates, index) => {
let html = "";
let week = 0;
for (let i = 0; i < dates.length; i++) {
week = new_week(dates[i], week);
if (!is_weekend(dates[i])) {
let day = +dates[i].toLocaleDateString('se-SE', { day: 'numeric' });
let month = +dates[i].toLocaleDateString('se-SE', { month: 'numeric' });
let value = dates[i].toLocaleDateString('se-SE', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
});
html += `<text
x="${(week * rect.size) + (month ) + svg.padding}"
y="${(dates[i].getDay() * rect.size) + (105 * index)}"
dx="1"
dy="${rect.size - 3}"
class="small day"
fill="${rect.text1}"
pointer-events="none"
value="${value}"
>${day <= 9 ? "0" + day : day}</text>`
}
}
return html;
}
gen_text_weeek = (dates, index) => {
let html = "";
let team = server.data.teams[index];
let weeks = ["Må", "Ti", "On", "To", "Fr"];
for (let i = 0; i < weeks.length; i++) {
html += `<text
x="0"
y="${(i + 1) * rect.size + (105 * index)}"
dy="${rect.size - 3}"
class="small"
fill="${team_table[team]}"
>${weeks[i]}</text>`;
}
return html;
}
gen_text_vgrid = (id, index) => {
let html = `<text
x="0"
y="${(rect.size * 5) + svg.padding + rect.size + (105 * index)}"
class="medium"
fill="#111"
font-weight="bold"
>ID: ${id}</text>`;
return html;
}
gen_calendar = dates => {
let ids = server.data.vgrid;
let html = "";
html += `<svg
width="${svg.width}"
height="${svg.height * ids.length + svg.padding}"
>`;
for (var i = 0; i < ids.length; i++) {
html += `<g id="${ids[i]}">`;
html += gen_rect(dates, i);
html += gen_text_days(dates, i);
html += gen_text_weeek(dates, i);
html += gen_text_vgrid(ids[i], i);
html += "</g>";
}
html += "</svg>";
return html;
}
gen_dates = year => {
let start = new Date(year, 0, 1);
let end = new Date(year + 1, 0, 0);
let arr = [];
for (let date = start; date <= end; date.setDate(date.getDate() + 1)) {
arr.push(new Date(date));
}
return arr;
}
reset_color = id => {
let node = document.querySelector(`#${id}`);
let text = node.querySelectorAll(".day");
for (let i = 0; i < text.length; i++) {
text[i].attributes.fill.value = rect.text1;
}
return text;
}
color_text = (e, id) => {
let month = e.target.attributes.value.value.split("-")[1];
let text = reset_color(id);
for (let i = 0; i < text.length; i++) {
if (text[i].attributes.value == undefined) {
break;
}
let item_value = text[i].attributes.value.value.split("-")[1];
if (item_value == month) {
text[i].attributes.fill.value = rect.text2;
flags.month_colored = true;
flags.id = id;
}
}
}
mouse_move = e => {
let id = e.target.parentNode.id;
if (flags.month_colored && e.target.tagName != "rect") {
flags.month_colored = false;
reset_color(flags.id);
}
if (e.target.tagName == "rect") {
color_text(e, id);
} else if (rect.prev != null) {
rect.prev.target.attributes.fill.value = rect.color1;
rect.prev = null;
}
}
clicked_rect = e => {
if (e.target.tagName == "rect") {
let id = e.target.parentNode.id;
// coloring
if (e.target.attributes.fill.value == user.day) {
if (e.target.attributes.value.value.split("-")[1] % 2 == 0) {
e.target.attributes.fill.value = rect.color1;
} else {
e.target.attributes.fill.value = rect.color2;
}
} else {
e.target.attributes.fill.value = user.day;
}
rect.prev = null;
// adding
if (!user.clicked.includes(id)) {
user.clicked.push(id);
}
var index = user.dates[id].indexOf(e.target.attributes.value.value);
if (index > -1) {
user.dates[id].splice(index, 1);
} else {
user.dates[id].push(e.target.attributes.value.value);
}
}
}
clicked_save = e => {
if (e.target.id == "save" && user.clicked.length != 0) {
let result = "save||";
let ids = Object.keys(user.dates)
let counter = 0;
for (let i = 0; i < ids.length; i++) {
if (user.clicked.includes(ids[i])) {
var index = user.dates[ids[i]].indexOf("");
if (index > -1) {
user.dates[ids[i]].splice(index, 1);
}
if (counter > 0) {
result += " " + ids[i] + ":" + user.dates[ids[i]].join();
} else {
result += ids[i] + ":" + user.dates[ids[i]].join();
}
counter++;
}
}
user.clicked = [];
socket.send(result);
}
}
clicked_add = e => {
if (e.target.id == "add") {
if (dom.vgrid.value == "") {
alert("Måste skriva vgrid");
}
if (server.data["vgrid"].includes(dom.vgrid.value)) {
alert("Vgrid finns redan i listan!");
} else {
let id = dom.vgrid.value;
let teams = dom.team.querySelectorAll("option");
for (let i = 0; i < teams.length; i++) {
if (teams[i].selected == true && teams[i].value == "Team") {
alert("Måste välja team");
break;
} else if (teams[i].selected == true) {
let result = "add||";
result += id + ":" + teams[i].value;
socket.send(result);
}
}
}
}
}
mouse_click = e => {
clicked_rect(e);
clicked_save(e);
clicked_add(e);
}
get_ids = () => {
var objs = {};
for (let i = 0; i < server.data.vgrid.length; i++) {
objs[server.data.vgrid[i]] = [];
}
for (let i = 0; i < server.data.dates.length; i++) {
var ammount = server.data.dates[i].split(",");
for (let j = 0; j < ammount.length; j++) {
objs[server.data.vgrid[i]].push(ammount[j]);
}
}
return objs;
}
team_to_nr = teams => {
let arr = [];
for (let i = 0; i < teams.length; i++) {
if (teams[i] == "team1") arr.push(1);
if (teams[i] == "team2") arr.push(2);
if (teams[i] == "team3") arr.push(3);
}
return arr;
}
nr_to_team = teams => {
let arr = [];
for (let i = 0; i < teams.length; i++) {
if (teams[i] == 1) arr.push("team1");
if (teams[i] == 2) arr.push("team2");
if (teams[i] == 3) arr.push("team3");
}
return arr;
}
cleanup_data = () => {
let team_nr = team_to_nr(server.data["teams"])
let collection = [server.data["vgrid"], team_nr, server.data["dates"]]
let new_arr = collection.map(h.taker(h.sort(team_nr, h.ascending)))
let new_team = nr_to_team(new_arr[1]);
new_arr[1] = new_team;
server.data["vgrid"] = new_arr[0];
server.data["teams"] = new_arr[1];
server.data["dates"] = new_arr[2];
}
main = () => {
cleanup_data();
let dates = gen_dates(new Date().getFullYear());
user.dates = get_ids();
dom.calendar.innerHTML = gen_calendar(dates);
dom.months.innerHTML = gen_text_month(dates);
dom.html.onmousemove = e => mouse_move(e);
dom.body.onclick = e => mouse_click(e);
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment