Created
December 26, 2025 02:51
-
-
Save DinoChiesa/3193212bc6efd399a617bf02ddf31bc3 to your computer and use it in GitHub Desktop.
MIT OCW Show and Filter Dates #js
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 MIT OCW Date Inserter | |
| // @namespace mit-ocw | |
| // @version 1.2 | |
| // @description Extracts and displays the course date from the URL on MIT OCW search results. | |
| // @author Gemini | |
| // @match https://ocw.mit.edu/* | |
| // @match https://ocw.mit.edu/search/ | |
| // @match https://ocw.mit.edu/search/* | |
| // @match https://ocw.mit.edu/courses/* | |
| // @grant none | |
| // @run-at document-start | |
| // ==/UserScript== | |
| (function () { | |
| "use strict"; | |
| let minYear = localStorage.getItem("ocw-min-year") || 0; | |
| function createFilterUI() { | |
| if (document.getElementById("ocw-filter-container")) return; | |
| // Try to find a good spot: the search results count or the main content area | |
| const insertionPoint = | |
| document.querySelector(".search-results-header") || | |
| document.querySelector("main"); | |
| if (!insertionPoint) return; | |
| const container = document.createElement("div"); | |
| container.id = "ocw-filter-container"; | |
| container.style.cssText = | |
| "padding: 15px; background: #fff1f1; border: 2px solid #a31f34; margin: 10px 0; border-radius: 8px; display: flex; align-items: center; gap: 15px; font-family: sans-serif; z-index: 999; position: relative;"; | |
| container.innerHTML = ` | |
| <strong style="color: #a31f34;">Year Filter:</strong> | |
| <input type="number" id="ocw-year-input" placeholder="Min Year (e.g. 2020)" style="padding: 8px; border: 1px solid #a31f34; border-radius: 4px; width: 150px; font-size: 1rem;"> | |
| <span style="font-size: 0.9em; color: #333;">Showing courses from <span id="current-min-year" style="font-weight:bold;">All Years</span></span> | |
| `; | |
| insertionPoint.prepend(container); | |
| document.getElementById("ocw-year-input").addEventListener("input", (e) => { | |
| minYear = parseInt(e.target.value) || 0; | |
| if (minYear > 2000 && minYear < 2025) { | |
| localStorage.setItem("ocw-min-year", minYear); | |
| document.getElementById("current-min-year").innerText = | |
| minYear || "All Years"; | |
| applyFilterToAll(); | |
| } | |
| }); | |
| } | |
| function processCard(card) { | |
| const link = card.querySelector("a"); | |
| if (!link || !link.href) return; | |
| // Match for standard and IAP links | |
| const match = link.href.match( | |
| /(fall|spring|summer|january)(?:-iap)?-(\d{4})/i, | |
| ); | |
| if (match) { | |
| const dateName = match[1].toUpperCase(); | |
| const dateYear = parseInt(match[2]); | |
| // 1. ADD THE BADGE (if not already there) | |
| if (!card.querySelector(".ocw-custom-badge")) { | |
| // Look for the most reliable text targets in the card | |
| const target = | |
| card.querySelector(".course-number") || | |
| card.querySelector("h2") || | |
| card.querySelector("h3") || | |
| card.querySelector(".course-title"); | |
| if (target) { | |
| const dateLabel = document.createElement("span"); | |
| dateLabel.className = "ocw-custom-badge"; | |
| dateLabel.innerText = `${dateName} ${dateYear}`; | |
| dateLabel.style.cssText = ` | |
| background: #a31f34; | |
| color: white; | |
| padding: 2px 8px; | |
| border-radius: 4px; | |
| font-weight: bold; | |
| margin-left: 10px; | |
| font-size: 0.7em; | |
| display: inline-block; | |
| vertical-align: middle; | |
| `; | |
| target.appendChild(dateLabel); | |
| card.setAttribute("data-course-year", dateYear); | |
| } | |
| } | |
| // 2. APPLY FILTERING | |
| const storedYear = parseInt(card.getAttribute("data-course-year")); | |
| if (minYear > 0 && storedYear < minYear) { | |
| card.style.display = "none"; | |
| } else { | |
| card.style.display = ""; | |
| } | |
| } | |
| } | |
| function applyFilterToAll() { | |
| // MIT uses 'article' for search results and 'div.course-card' for others | |
| const cards = document.querySelectorAll("article, .course-card"); | |
| cards.forEach(processCard); | |
| } | |
| // Use a simplified observer | |
| const observer = new MutationObserver(() => { | |
| createFilterUI(); | |
| applyFilterToAll(); | |
| }); | |
| observer.observe(document.body, { childList: true, subtree: true }); | |
| // Initial run | |
| createFilterUI(); | |
| applyFilterToAll(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment