🏗️ First time sync the css & js files from hexo theme NexT
This commit is contained in:
138
assets/js/schedule.js
Normal file
138
assets/js/schedule.js
Normal file
@@ -0,0 +1,138 @@
|
||||
/* global CONFIG */
|
||||
|
||||
// https://developers.google.com/calendar/api/v3/reference/events/list
|
||||
(function() {
|
||||
// Initialization
|
||||
const calendar = {
|
||||
orderBy : 'startTime',
|
||||
showLocation: false,
|
||||
offsetMax : 72,
|
||||
offsetMin : 4,
|
||||
showDeleted : false,
|
||||
singleEvents: true,
|
||||
maxResults : 250
|
||||
};
|
||||
|
||||
// Read config form theme config file
|
||||
Object.assign(calendar, CONFIG.calendar);
|
||||
|
||||
const now = new Date();
|
||||
const timeMax = new Date();
|
||||
const timeMin = new Date();
|
||||
|
||||
timeMax.setHours(now.getHours() + calendar.offsetMax);
|
||||
timeMin.setHours(now.getHours() - calendar.offsetMin);
|
||||
|
||||
// Build URL
|
||||
const params = {
|
||||
key : calendar.api_key,
|
||||
orderBy : calendar.orderBy,
|
||||
timeMax : timeMax.toISOString(),
|
||||
timeMin : timeMin.toISOString(),
|
||||
showDeleted : calendar.showDeleted,
|
||||
singleEvents: calendar.singleEvents,
|
||||
maxResults : calendar.maxResults
|
||||
};
|
||||
|
||||
const request_url = new URL(`https://www.googleapis.com/calendar/v3/calendars/${calendar.calendar_id}/events`);
|
||||
Object.entries(params).forEach(param => request_url.searchParams.append(...param));
|
||||
|
||||
function getRelativeTime(current, previous) {
|
||||
const msPerMinute = 60 * 1000;
|
||||
const msPerHour = msPerMinute * 60;
|
||||
const msPerDay = msPerHour * 24;
|
||||
const msPerMonth = msPerDay * 30;
|
||||
const msPerYear = msPerDay * 365;
|
||||
|
||||
let elapsed = current - previous;
|
||||
const tense = elapsed > 0 ? ' ago' : ' later';
|
||||
|
||||
elapsed = Math.abs(elapsed);
|
||||
|
||||
if (elapsed < msPerHour) {
|
||||
return Math.round(elapsed / msPerMinute) + ' minutes' + tense;
|
||||
} else if (elapsed < msPerDay) {
|
||||
return Math.round(elapsed / msPerHour) + ' hours' + tense;
|
||||
} else if (elapsed < msPerMonth) {
|
||||
return 'about ' + Math.round(elapsed / msPerDay) + ' days' + tense;
|
||||
} else if (elapsed < msPerYear) {
|
||||
return 'about ' + Math.round(elapsed / msPerMonth) + ' months' + tense;
|
||||
}
|
||||
|
||||
return 'about ' + Math.round(elapsed / msPerYear) + ' years' + tense;
|
||||
}
|
||||
|
||||
function buildEventDOM(tense, event, start, end) {
|
||||
const durationFormat = {
|
||||
weekday: 'short',
|
||||
hour : '2-digit',
|
||||
minute : '2-digit'
|
||||
};
|
||||
const relativeTime = tense === 'now' ? 'NOW' : getRelativeTime(now, start);
|
||||
const duration = start.toLocaleTimeString([], durationFormat) + ' - ' + end.toLocaleTimeString([], durationFormat);
|
||||
|
||||
let location = '';
|
||||
if (calendar.showLocation && event.location) {
|
||||
location = `<span class="event-location event-details">${event.location}</span>`;
|
||||
}
|
||||
let description = '';
|
||||
if (event.description) {
|
||||
description = `<span class="event-description event-details">${event.description}</span>`;
|
||||
}
|
||||
|
||||
const eventContent = `<section class="event event-${tense}">
|
||||
<h2 class="event-summary">
|
||||
${event.summary}
|
||||
<span class="event-relative-time">${relativeTime}</span>
|
||||
</h2>
|
||||
${location}
|
||||
<span class="event-duration event-details">${duration}</span>
|
||||
${description}
|
||||
</section>`;
|
||||
return eventContent;
|
||||
}
|
||||
|
||||
function fetchData() {
|
||||
const eventList = document.querySelector('.event-list');
|
||||
if (!eventList) return;
|
||||
|
||||
fetch(request_url.href).then(response => {
|
||||
return response.json();
|
||||
}).then(data => {
|
||||
if (data.items.length === 0) {
|
||||
eventList.innerHTML = '<hr>';
|
||||
return;
|
||||
}
|
||||
// Clean the event list
|
||||
eventList.innerHTML = '';
|
||||
let prevEnd = 0; // used to decide where to insert an <hr>
|
||||
const utc = new Date().getTimezoneOffset() * 60000;
|
||||
|
||||
data.items.forEach(event => {
|
||||
// Parse data
|
||||
const start = new Date(event.start.dateTime || (new Date(event.start.date).getTime() + utc));
|
||||
const end = new Date(event.end.dateTime || (new Date(event.end.date).getTime() + utc));
|
||||
|
||||
let tense = 'now';
|
||||
if (end < now) {
|
||||
tense = 'past';
|
||||
} else if (start > now) {
|
||||
tense = 'future';
|
||||
}
|
||||
|
||||
if (tense === 'future' && prevEnd < now) {
|
||||
eventList.insertAdjacentHTML('beforeend', '<hr>');
|
||||
}
|
||||
|
||||
eventList.insertAdjacentHTML('beforeend', buildEventDOM(tense, event, start, end));
|
||||
prevEnd = end;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fetchData();
|
||||
const fetchDataTimer = setInterval(fetchData, 60000);
|
||||
document.addEventListener('pjax:send', () => {
|
||||
clearInterval(fetchDataTimer);
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user