mirror of
https://github.com/next-theme/hexo-theme-next.git
synced 2026-01-18 18:33:42 +00:00
Create schedule.js
This commit is contained in:
parent
6814b16aba
commit
4f192213b3
3
.github/label-commenter-config.yml
vendored
3
.github/label-commenter-config.yml
vendored
@ -20,8 +20,7 @@ labels:
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
:wave: Hey there! we use the issue tracker exclusively for bug reports
|
||||
and feature requests. However, this issue appears to be a support request.
|
||||
:wave: Hey there! we use the issue tracker exclusively for bug reports and feature requests. However, this issue appears to be a support request.
|
||||
Please use our [support channels](https://github.com/next-theme/hexo-theme-next#feedback) to get help with the project.
|
||||
action: close
|
||||
- name: Wontfix
|
||||
|
||||
1
.github/stale.yml
vendored
1
.github/stale.yml
vendored
@ -10,7 +10,6 @@ exemptLabels:
|
||||
- Feature Request
|
||||
- Discussion
|
||||
- Help Wanted
|
||||
- Question
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
You can use internationalization to present your site in different languages. The default language is set by modifying the `language` setting in Hexo `_config.yml`. You can also set multiple languages and modify the order of default languages.
|
||||
|
||||
```yaml
|
||||
```yml
|
||||
language: en
|
||||
```
|
||||
|
||||
```yaml
|
||||
```yml
|
||||
language:
|
||||
- zh-CN
|
||||
- en
|
||||
@ -21,7 +21,7 @@ If you would like to customize the default translation, you do not need to modif
|
||||
1. Creat a `languages.yml` in `source/_data`.
|
||||
2. Insert following codes: (be careful about the two-space indent)
|
||||
|
||||
```yaml
|
||||
```yml
|
||||
# language
|
||||
zh-CN:
|
||||
# items
|
||||
|
||||
@ -1,138 +1,4 @@
|
||||
<script{{ pjax }}>
|
||||
(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, {{ theme.calendar | safedump }});
|
||||
|
||||
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 = 'https://www.googleapis.com/calendar/v3/calendars/' + calendar.calendar_id + '/events?' + Object.entries(params).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join('&');
|
||||
|
||||
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) {
|
||||
const start = event.start.dateTime;
|
||||
const end = event.end.dateTime;
|
||||
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).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>
|
||||
|
||||
data.items.forEach(event => {
|
||||
// Parse data
|
||||
const utc = new Date().getTimezoneOffset() * 60000;
|
||||
const start = event.start.dateTime = new Date(event.start.dateTime || (new Date(event.start.date).getTime() + utc));
|
||||
const end = event.end.dateTime = 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.innerHTML += '<hr>';
|
||||
}
|
||||
|
||||
eventList.innerHTML += buildEventDOM(tense, event);
|
||||
prevEnd = end;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fetchData();
|
||||
const fetchDataTimer = setInterval(fetchData, 60000);
|
||||
document.addEventListener('pjax:send', () => {
|
||||
clearInterval(fetchDataTimer);
|
||||
});
|
||||
})();
|
||||
CONFIG.calendar = {{ theme.calendar | safedump }};
|
||||
</script>
|
||||
{{- next_js('schedule.js', true) }}
|
||||
|
||||
@ -15,17 +15,17 @@ hexo.extend.helper.register('next_inject', function(point) {
|
||||
.join('');
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('next_js', function(url) {
|
||||
hexo.extend.helper.register('next_js', function(url, pjax = false) {
|
||||
const { next_version } = this;
|
||||
const { js } = this.theme;
|
||||
const { internal } = this.theme.vendors;
|
||||
let src = `${js}/${url}`;
|
||||
let src = this.url_for(`${js}/${url}`);
|
||||
if (internal === 'jsdelivr') {
|
||||
src = `//cdn.jsdelivr.net/npm/hexo-theme-next@${next_version}/source/js/${url}`;
|
||||
} else if (internal === 'unpkg') {
|
||||
src = `//unpkg.com/hexo-theme-next@${next_version}/source/js/${url}`;
|
||||
}
|
||||
return this.js(src);
|
||||
return `<script ${pjax ? 'data-pjax ' : ''}src="${src}"></script>`;
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('post_edit', function(src) {
|
||||
|
||||
@ -11,8 +11,8 @@
|
||||
flex: 1;
|
||||
|
||||
img {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
138
source/js/schedule.js
Normal file
138
source/js/schedule.js
Normal file
@ -0,0 +1,138 @@
|
||||
/* global CONFIG */
|
||||
|
||||
(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 = 'https://www.googleapis.com/calendar/v3/calendars/' + calendar.calendar_id + '/events?' + Object.entries(params).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join('&');
|
||||
|
||||
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) {
|
||||
const start = event.start.dateTime;
|
||||
const end = event.end.dateTime;
|
||||
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).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>
|
||||
|
||||
data.items.forEach(event => {
|
||||
// Parse data
|
||||
const utc = new Date().getTimezoneOffset() * 60000;
|
||||
const start = event.start.dateTime = new Date(event.start.dateTime || (new Date(event.start.date).getTime() + utc));
|
||||
const end = event.end.dateTime = 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.innerHTML += '<hr>';
|
||||
}
|
||||
|
||||
eventList.innerHTML += buildEventDOM(tense, event);
|
||||
prevEnd = end;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fetchData();
|
||||
const fetchDataTimer = setInterval(fetchData, 60000);
|
||||
document.addEventListener('pjax:send', () => {
|
||||
clearInterval(fetchDataTimer);
|
||||
});
|
||||
})();
|
||||
Loading…
x
Reference in New Issue
Block a user