Skip to content

Instantly share code, notes, and snippets.

@nil2013
Last active September 19, 2018 01:52
Show Gist options
  • Save nil2013/d7efe95733b063932e09eeb745b03eed to your computer and use it in GitHub Desktop.
Save nil2013/d7efe95733b063932e09eeb745b03eed to your computer and use it in GitHub Desktop.
予定表を作成するSPA
<html>
<head>
<title>スケジュール表</title>
<style>
div.row {
position: relative;
outline: 1px solid #aaa;
}
div.row:nth-child(even) {
background: #eee;
}
div.row:nth-child(odd) {
background: #fff;
}
div.row>div.col {
position: absolute;
border: 1px solid #aaa;
border-radius: 5px;
box-sizing: border-box;
width: 90%;
margin-left:5%;
}
div.row>div.col.h {
position: absolute;
border: none;
border-top: 1px dashed #000;
border-radius: 0;
width: 100%;
height: 7.5%;
text-align: center;
}
div.row>div.col.h:last-child {
border-bottom: 1px dashed #000;
}
div.row>div.col:nth-child(odd) {
background: #eee;
}
div.row>div.col:nth-child(even) {
background: #fff;
}
div.time > span.from:after {
content: "~";
}
div.row_header {
position: relative;
opacity: 0.5;
color: #444;
top: 0;
text-align: center;
}
@media print {
a#copy_json,
button,
form#schedule_form {
display: none !important;
}
div.row>div.col {
border: 1px solid #888;
padding: 3px;
}
div.row > div.col .title {
text-decoration: underline;
font-size:0.9em;
}
div.row_header {
opacity: 1;
}
}
</style>
<script type="application/javascript">
const defaultSchedules = [];
Element.prototype.removeChildren = function() {
while (this.firstChild) this.removeChild(this.firstChild);
return this;
};
</script>
</head>
<body>
<div id="schedule_table" class="pure-g" style="height:100%">
<div class="pure-u-1-8 row">
<!-- 08:00-21:00 -->
<div class="col h" style="top: 1.0%;">08:00</div>
<div class="col h" style="top: 8.5%;">09:00</div>
<div class="col h" style="top: 16.0%;">10:00</div>
<div class="col h" style="top: 23.5%;">11:00</div>
<div class="col h" style="top: 31.0%;">12:00</div>
<div class="col h" style="top: 38.5%;">13:00</div>
<div class="col h" style="top: 46.0%;">14:00</div>
<div class="col h" style="top: 53.5%;">15:00</div>
<div class="col h" style="top: 61.0%;">16:00</div>
<div class="col h" style="top: 68.5%;">17:00</div>
<div class="col h" style="top: 76.0%;">18:00</div>
<div class="col h" style="top: 83.5%;">19:00</div>
<div class="col h" style="top: 91.0%;">20:00</div>
</div>
<div id="月曜" class="pure-u-1-8 row"></div>
<div id="火曜" class="pure-u-1-8 row"></div>
<div id="水曜" class="pure-u-1-8 row"></div>
<div id="木曜" class="pure-u-1-8 row"></div>
<div id="金曜" class="pure-u-1-8 row"></div>
<div id="土曜" class="pure-u-1-8 row"></div>
<div id="日曜" class="pure-u-1-8 row"></div>
</div>
<div style="padding: 10px;" id="forms">
<h2>Schedule List <a href="#" id="copy_json"><small style="margin-left: 20px">copy to clipboard</small></a></h2>
<div class="pure-g" style="text-align:center;">
<div class="pure-u-1-6">Date</div>
<div class="pure-u-1-3">Title</div>
<div class="pure-u-1-6">From</div>
<div class="pure-u-1-6">To</div>
</div>
<div id="schedule_queue">
</div>
<form class="pure-form pure-form-stacked" id="schedule_form">
<fieldset>
<div class="pure-g">
<div class="pure-u-1-6">
<!-- Row -->
<select class="pure-u-22-24" name="row"></select>
</div>
<div class="pure-u-1-3">
<!-- Title -->
<input class="pure-u-23-24" type="text" name="title" placeholder="Title">
</div>
<div class="pure-u-1-6">
<!-- From -->
<div class="pure-u-3-8"><input class="pure-input-1" type="number" name="from.h" /></div>
<div class="pure-u-1-8" style="text-align:center;"> : </div>
<div class="pure-u-3-8"><input class="pure-input-1" type="number" name="from.m" /></div>
</div>
<div class="pure-u-1-6">
<!-- To -->
<div class="pure-u-3-8"><input class="pure-input-1" type="number" name="to.h" /></div>
<div class="pure-u-1-8" style="text-align:center;"> : </div>
<div class="pure-u-3-8"><input class="pure-input-1" type="number" name="to.m" /></div>
</div>
<div class="pure-u-1-6">
<!-- Submit -->
<button type="submit" class="pure-button pure-button-primary">Add</button>
</div>
</div>
</fieldset>
</form>
</div>
</body>
<script>
const zeroPadding = function(num, length) {
if(num < 10**length) {
var padding = "";
for(var i = 0; i < length; i ++) { padding += "0"; }
return (padding + num).slice(-length);
} else {
return num;
}
}
const min = 99.0 / 780;
const queue = document.getElementById("schedule_queue");
// console.log(`${min}%/min`);
const addScheduleDom = function(s) {
console.log(s);
const title = document.createElement("div");
title.innerText = s.title;
title.classList.add("title");
const from = document.createElement("span");
from.innerText = `${s.from.h}:${zeroPadding(s.from.m, 2)}`;
const to = document.createElement("span");
to.innerText = `${s.to.h}:${zeroPadding(s.to.m, 2)}`;
const time = document.createElement("div");
time.appendChild(from).classList.add("from");
time.appendChild(to);
time.classList.add("time");
const column = document.createElement('div');
column.classList.add("col");
const start = (s.from.h - 8) * 60 + s.from.m;
const span = (s.to.m - s.from.m) + ((s.to.h - s.from.h) * 60);
console.log(`${s.from.h}:${s.from.m} ~ ${s.to.h}:${s.to.m}, start: ${start}, span: ${span}`);
column.style.top = `${1 + start * min}%`;
column.style.height = `${span * min}%`;
// column.innerText = s.title;
column.appendChild(title);
column.appendChild(time);
console.log(column);
document.querySelector(`#${s.row}`).appendChild(column);
}
document.querySelectorAll("div#schedule_table > div").forEach(div => {
if (div.id != undefined && div.id != "") {
const header = document.createElement('div');
header.classList.add("row_header");
header.innerText = div.id;
div.appendChild(header);
}
});
document.querySelectorAll("select[name='row']").forEach(sel => {
Array.prototype.slice.call(document.querySelectorAll("div.row")).forEach(r => {
if (r.id && r.id != "") {
const opt = document.createElement('option');
opt.innerText = r.id;
opt.value = r.id;
sel.appendChild(opt);
}
})
});
const parse = function(form) {
const map = {};
Array.prototype.slice.call(form.elements).forEach(elem => {
if (elem && elem.name && !elem.name.isEmpty) {
map[elem.name] = elem.value;
}
});
return map;
};
const createNewForm = function(from) {
const newForm = document.importNode(from, true);
newForm.id = "";
const btn = newForm.querySelector("button");
btn.innerText = "Update";
btn.onclick = function() {
updateSchedule();
return false
};
return newForm;
}
const pressAddSchedule = function(ev) {
const form = this;
const map = parse(form);
// console.log(map);
const newForm = createNewForm(form);
newForm.querySelector(`option[value='${map.row}']`).selected = "selected";
queue.appendChild(newForm);
document.body.scrollTop = document.body.scrollHeight;
Array.prototype.slice.call(form.elements).forEach(elem => elem.value = "");
form.querySelector("select").focus();
updateSchedule();
return false;
};
const parseJson = (json => addScheduleAll(JSON.parse(json)));
const addScheduleAll = function(schedules) {
queue.removeChildren();
schedules.forEach(entry => {
const newForm = createNewForm(document.getElementById("schedule_form"));
newForm.querySelector(`option[value='${entry.row}']`).selected = "selected";
newForm.querySelector(`input[name='title']`).value = entry.title;
newForm.querySelector(`input[name='from.h']`).value = entry.from.h;
newForm.querySelector(`input[name='from.m']`).value = entry.from.m;
newForm.querySelector(`input[name='to.h']`).value = entry.to.h;
newForm.querySelector(`input[name='to.m']`).value = entry.to.m;
queue.appendChild(newForm);
});
updateSchedule();
}
const getSchedules = function() {
return Array.prototype.slice.call(queue.children).filter(elem => elem.tagName.toLowerCase() == "form").map(parse).map(data => {
return {
row: data.row,
from: {
h: parseInt(data["from.h"]),
m: parseInt(data["from.m"])
},
to: {
h: parseInt(data["to.h"]),
m: parseInt(data["to.m"])
},
title: data.title
};
});
}
const updateSchedule = function() {
document.querySelectorAll("schedule_table > div").forEach(row => {
if (row && row.id && !row.id.isEmpty) {
row.removeChildren();
}
});
console.log("json: " + JSON.stringify(getSchedules()));
getSchedules().forEach(addScheduleDom);
}
const throwToClipboard = function(text) {
var input = document.createElement('input');
input.setAttribute('id', 'copyinput');
document.body.appendChild(input);
input.value = text;
input.select();
document.execCommand('copy');
document.body.removeChild(input);
};
const copyJson = function() {
const json = JSON.stringify(getSchedules());
// コピー
throwToClipboard(json);
return false;
}
document.querySelector("a#copy_json").onclick = copyJson;
document.querySelectorAll("form").forEach(form => form.onsubmit = pressAddSchedule);
addScheduleAll(defaultSchedules);
</script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment