Last active
April 19, 2020 15:27
-
-
Save dzfranklin/2120485e9594ad652a7fc0d999b91829 to your computer and use it in GitHub Desktop.
Adds a calendar to the wesmaps planning page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Add a Calendar to WesMaps</title> | |
<style> | |
body { | |
max-width: 600px; | |
margin-left: auto; | |
margin-right: auto; | |
margin-top: 80px; | |
margin-bottom: auto; | |
line-height: 1.5em; | |
} | |
.install-row { | |
text-align: center; | |
margin: 50px; | |
} | |
.install-button { | |
padding: 15px; | |
border-radius: 5px; | |
border: 1px solid hsl(0, 0%, 50.2%); | |
background-color: hsl(0, 100%, 40.6%); | |
color: white; | |
text-decoration: none; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Add a Calendar to WesMaps</h1> | |
<p> | |
Drag the button to your bookmarks toolbar to install. Click on the button on your bookmarks toolbar while visiting a wesmaps page that shows your schedule at the bottom and a calendar will appear. | |
</p> | |
<div class="install-row"> | |
<a class="install-button" href="javascript:(function(){let s=document.createElement('script');s.src='https://gist.githack.com/danielzfranklin/2120485e9594ad652a7fc0d999b91829/raw/a570f5280650e5103572296e497bd843e2690526/remote.js';document.head.append(s)})()">WesMaps Calendar</a> | |
</div> | |
<script> | |
document.querySelector('.install-button').addEventListener('click', e => { | |
e.preventDefault(); | |
alert('Drag the button to your bookmarks toolbar and then click on it when you visit a WesMaps page. Clicking on it here does nothing.'); | |
}); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function displayCalendar() { | |
let classes = parsePage(); | |
const DAYS = ['M', 'T', 'W', 'R', 'F']; | |
let calendar = document.createElement('div'); | |
calendar.className = 'calendar'; | |
let close = document.createElement('button'); | |
close.innerText = 'X'; | |
close.title = 'Close'; | |
close.className = 'calendar-close'; | |
close.addEventListener('click', () => { | |
document.body.removeChild(calendar); | |
}); | |
calendar.append(close); | |
for (let day_name of DAYS) { | |
let day = document.createElement('div'); | |
day.className = 'calendar-day calendar-' + day_name; | |
calendar.append(day); | |
} | |
for (let c of classes) { | |
for (let time of c.times) { | |
let period = document.createElement('div'); | |
period.className = 'calendar-period'; | |
let start = toPixels(time.from); | |
let height = toPixels(time.to) - start; | |
period.style.top = `${start}px`; | |
period.style.height = `${height}px`; | |
period.innerHTML = `<h2 class="calendar-period-name">${c.name}</h2> <p class="calendar-period-times">${time.from}-${time.to}</p>`; | |
calendar.querySelector('.calendar-' + time.day).append(period); | |
} | |
} | |
if (document.body.tagName === 'FRAMESET') { | |
let root = document.querySelector('html'); | |
let body = document.createElement('body'); | |
body.append(document.body); | |
root.append(body); | |
} | |
if (!document.querySelector('style.calendar-styles')) { | |
let styles = document.createElement('style'); | |
styles.className = 'calendar-styles'; | |
styles.innerText = ` | |
.calendar { | |
position: fixed; | |
top: 30px; | |
left: 30px; | |
right: 30px; | |
bottom: 30px; | |
background-color: white; | |
display: flex; | |
overflow: auto; | |
} | |
.calendar-close { | |
position: fixed; | |
z-index: 999; | |
top: 40px; | |
right: 40px; | |
background-color: red; | |
color: hsl(0, 76.5%, 93.3%); | |
border-radius: 1.5em; | |
font-size: 17px; | |
width: 1.5em; | |
height: 1.5em; | |
border: none; | |
} | |
.calendar-day, .calendar-period { | |
/* since period is absolute they both have the same parent for size purposes */ | |
width: 20%; | |
} | |
.calendar-period { | |
position: absolute; | |
background-color: lightblue; | |
overflow: auto; | |
box-sizing: border-box; /* so that the padding subtracts from the width */ | |
border-left: 5px solid white; | |
border-right: 5px solid white; | |
padding: 10px; | |
} | |
.calendar-period h2 { | |
font-size: 17px; | |
margin: 0; | |
margin-bottom: 5px; | |
} | |
.calendar-period p { | |
margin: 0; | |
} | |
`; | |
document.head.append(styles); | |
} | |
let prev_calendar = document.body.querySelector('.calendar'); | |
if (prev_calendar) { | |
document.body.removeChild(prev_calendar); | |
} | |
document.body.append(calendar); | |
} | |
function toPixels(time) { | |
const DAY_START = 8 * 60; | |
const PIXELS_PER_MINUTE = 1.2; | |
let [hours_part, minutes_part] = time.replace('AM', '').replace('PM', '').split(':'); | |
hours_part = Number.parseInt(hours_part, 10); | |
minutes_part = Number.parseInt(minutes_part, 10); | |
if (time.endsWith('PM')) { | |
if (hours_part !== 12) { | |
hours_part += 12; | |
} | |
} | |
let in_minutes = (hours_part * 60) + minutes_part - DAY_START; | |
return in_minutes * PIXELS_PER_MINUTE; | |
} | |
function parsePage() { | |
return parseTable(document.querySelector('frame[name=planning]').contentDocument.querySelector('#course_table')); | |
} | |
function parseTable(table) { | |
return Array.from(table.querySelectorAll('tr')).filter(e => e.id.indexOf('header') === -1).map(parseRow); | |
} | |
function parseRow(row) { | |
let name = parseName(row); | |
let times = parseTimes(row); | |
return { name, times }; | |
} | |
function parseName(row) { | |
let xlist = row.querySelector('.xlist_cell span'); | |
if (!xlist) { | |
xlist = row.querySelector('.xlist_cell select option[selected]'); | |
} | |
return `${xlist.innerText.replace(' ', '')}.${row.querySelector('span.section_cell').innerText} ${row.querySelector('.title_cell a').innerText}`; | |
} | |
function parseTimes(row) { | |
let s = row.querySelector('.meeting_cell').innerText; | |
let [dates, time_of_day] = s.split(';')[0].split(' '); | |
time_of_day = time_of_day.split('-'); | |
dates = dates.split(''); | |
let out = []; | |
for (let date of dates) { | |
if (date != '.') { | |
out.push({ 'day': date, 'from': time_of_day[0], 'to': time_of_day[1] }); | |
} | |
} | |
return out; | |
} | |
if (document.readyState == 'complete') { | |
displayCalendar(); | |
} else { | |
document.addEventListener('load', () => displayCalendar()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment