118 lines
3.7 KiB
JavaScript
118 lines
3.7 KiB
JavaScript
|
||
/**
|
||
*
|
||
* This bookmarklet extracts event data from the first four tables on a webpage,
|
||
* specifically looking for tables that contain 'date', 'venue', and 'location' headers.
|
||
* It processes the event data to identify special events and formats the dates.
|
||
* The extracted data is then used to create an iCalendar (.ics) file, which is
|
||
* automatically downloaded to the user's device.
|
||
*
|
||
* Functions:
|
||
* - extractEventData: Extracts event data from the first four tables on the webpage.
|
||
* - createICal: Creates an iCalendar (.ics) content string from the extracted event data.
|
||
* - downloadICal: Initiates the download of the iCalendar (.ics) file with the given content and filename.
|
||
*/
|
||
javascript: (() => {
|
||
function extractEventData() {
|
||
let tables = document.querySelectorAll('table');
|
||
if (tables.length > 4) {
|
||
tables = Array.from(tables).slice(0, 4);
|
||
}
|
||
const data = [];
|
||
|
||
tables.forEach(table => {
|
||
const headers = [];
|
||
const rows = table.querySelectorAll('tr');
|
||
|
||
const firstRow = rows[0];
|
||
firstRow.querySelectorAll('td').forEach(td => {
|
||
headers.push(td.textContent.trim().toLowerCase());
|
||
});
|
||
|
||
if (
|
||
headers.includes('date') &&
|
||
headers.includes('venue') &&
|
||
headers.includes('location')
|
||
) {
|
||
Array.from(rows)
|
||
.slice(1)
|
||
.forEach(row => {
|
||
const cells = row.querySelectorAll('td');
|
||
const rowData = {};
|
||
|
||
if (
|
||
Array.from(cells).some(cell =>
|
||
cell.querySelector('span[style*="color: #2dc26b"]')
|
||
)
|
||
) {
|
||
rowData.specialEvent = true;
|
||
}
|
||
cells.forEach((cell, j) => {
|
||
const header = headers[j];
|
||
let cellText = cell.innerHTML.replace(/<br\s*\/?>/gi, ', ').trim();
|
||
cellText = cellText.replace(/<\/?[^>]+(>|$)/g, '').trim();
|
||
|
||
if (header === 'date') {
|
||
const month = cellText.split(' ')[0];
|
||
const year = cellText.split(',')[1].trim();
|
||
const startDay = cellText
|
||
.split(' ')[1]
|
||
.split(cellText.includes(' – ') ? ' – ' : '–')[0]
|
||
.trim();
|
||
const endDay = cellText
|
||
.split(cellText.includes(' – ') ? ' – ' : '–')[1]
|
||
.split(',')[0]
|
||
.trim();
|
||
rowData.startDate = `${month} ${startDay}, ${year}`;
|
||
rowData.endDate = `${month} ${endDay}, ${year}`;
|
||
} else if (header === 'venue') {
|
||
rowData.venue = cellText;
|
||
} else if (header === 'location') {
|
||
rowData.location = cellText;
|
||
}
|
||
});
|
||
|
||
data.push(rowData);
|
||
});
|
||
}
|
||
});
|
||
|
||
return data;
|
||
}
|
||
|
||
const data = extractEventData(tables);
|
||
|
||
function createICal(events) {
|
||
let icalContent =
|
||
'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//FragginWagon//P!P //Regional-Special-Championships\n';
|
||
|
||
events.forEach(event => {
|
||
icalContent += 'BEGIN:VEVENT\n';
|
||
icalContent += `DTSTART:${new Date(event.startDate).toISOString().replace(/[-:]/g, '').split('.')[0]}Z\n`;
|
||
icalContent += `DTEND:${new Date(event.endDate).toISOString().replace(/[-:]/g, '').split('.')[0]}Z\n`;
|
||
icalContent += `SUMMARY:${event.specialEvent ? 'Special Event' : 'Regional'} - ${event.venue} \n`;
|
||
icalContent += `LOCATION:${event.location}\n`;
|
||
icalContent += 'END:VEVENT\n';
|
||
});
|
||
|
||
icalContent += 'END:VCALENDAR';
|
||
|
||
return icalContent;
|
||
}
|
||
|
||
function downloadICal(content, filename) {
|
||
const blob = new Blob([content], { type: 'text/calendar' });
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = filename;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
document.body.removeChild(a);
|
||
URL.revokeObjectURL(url);
|
||
}
|
||
|
||
const newIcalContent = createICal(extractEventData());
|
||
downloadICal(newIcalContent, 'play_pokemon_regional_special_events.ics');
|
||
})();
|