-
-
Save swalberg/76757409c2dd64fd9a9c346492fbe5b5 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| // ==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