Skip to content

Instantly share code, notes, and snippets.

@swalberg
Created January 12, 2026 19:01
Show Gist options
  • Select an option

  • Save swalberg/76757409c2dd64fd9a9c346492fbe5b5 to your computer and use it in GitHub Desktop.

Select an option

Save swalberg/76757409c2dd64fd9a9c346492fbe5b5 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name K3Y Slot List – Time & Area Filter
// @namespace https://skccgroup.com/
// @version 2.1.0
// @description Adds an Eastern Time column and a filter for the Area column.
// @match https://skccgroup.com/k3y/slot_list.php*
// @match https://www.skccgroup.com/k3y/slot_list.php*
// @grant none
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
const TZ = 'America/New_York';
// Format a Date in the given time zone
function formatInTZ(date, timeZone) {
const parts = new Intl.DateTimeFormat('en-US', {
timeZone,
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false
}).formatToParts(date);
const get = type => (parts.find(p => p.type === type) || {}).value || '';
return `${get('month')} ${get('day')} ${get('hour')}:${get('minute')}`;
}
// Parse the year from the update line
let year = new Date().getUTCFullYear();
const update = document.querySelector('em');
if (update) {
const m = update.textContent.match(/(\d{4})-\d{2}-\d{2}/);
if (m) { year = Number(m[1]); }
}
const table = document.querySelector('table');
if (!table) return;
// Insert a new header cell for Eastern time
const headerRow = table.querySelector('tr');
const etHeader = document.createElement('th');
etHeader.textContent = 'Eastern (ET)';
etHeader.style.border = '1px solid';
etHeader.style.backgroundColor = '#c3d5ec';
headerRow.insertBefore(etHeader, headerRow.children[3]);
// Collect data rows
const rows = Array.from(table.querySelectorAll('tr')).slice(1);
// Build a set of unique area values
const areaSet = new Set();
rows.forEach(row => {
const cells = row.querySelectorAll('td');
if (cells.length < 3) return;
const day = parseInt(cells[0].textContent.trim(), 10);
const [sh, sm] = cells[1].textContent.trim().split(':').map(Number);
const [eh, emMin] = cells[2].textContent.trim().split(':').map(Number);
// Create start and end dates in UTC
const startDate = new Date(Date.UTC(year, 0, day, sh, sm));
let endDate = new Date(Date.UTC(year, 0, day, eh, emMin));
if (endDate <= startDate) {
endDate = new Date(endDate.getTime() + 24 * 60 * 60 * 1000);
}
const etRange = `${formatInTZ(startDate, TZ)}–${formatInTZ(endDate, TZ)}`;
// Insert Eastern time cell
const etCell = document.createElement('td');
etCell.textContent = etRange;
etCell.style.border = '1px solid';
row.insertBefore(etCell, cells[3]);
// Collect area values for the filter
const area = cells[3].textContent.trim();
areaSet.add(area);
});
// Create the area filter dropdown
const filterDiv = document.createElement('div');
filterDiv.style.margin = '8px 0';
const label = document.createElement('label');
label.textContent = 'Filter by Area: ';
const select = document.createElement('select');
const allOption = document.createElement('option');
allOption.value = '';
allOption.textContent = 'All';
select.appendChild(allOption);
Array.from(areaSet).sort().forEach(area => {
const option = document.createElement('option');
option.value = area;
option.textContent = area;
select.appendChild(option);
});
filterDiv.appendChild(label);
filterDiv.appendChild(select);
table.parentNode.insertBefore(filterDiv, table);
// Filter rows when selection changes
select.addEventListener('change', () => {
const value = select.value;
rows.forEach(row => {
const area = row.querySelectorAll('td')[4].textContent.trim();
if (!value || area === value) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment