// ==UserScript== // @name D2L Auto-Advance v7.3 // @namespace d2l-autoadvance-v7 // @version 7.3 // @description Auto-advances D2L Brightspace. F7=Toggle UI, F8=Start/Stop, F9=Next // @match https://*.modernstates.org/* // @grant none // @run-at document-idle // ==/UserScript== (function () { 'use strict'; // ── Only run in the TOP frame, never in iframes ──────────────────── if (window !== window.top) return; // ── Kill any previous instance + nuke all old UIs ───────────────── document.querySelectorAll('#d2l-aa').forEach(e => e.remove()); if (window.__d2lAA) { try { window.__d2lAA.kill(); } catch (_) {} delete window.__d2lAA; } const MIN_MS = 3000, MAX_MS = 4000; const rand = () => MIN_MS + Math.floor(Math.random() * (MAX_MS - MIN_MS)); function getLinks() { const results = []; function walk(node) { if (!node) return; try { node.querySelectorAll('d2l-activity-link[href]').forEach(el => results.push(el)); node.querySelectorAll('*').forEach(el => { if (el.shadowRoot) walk(el.shadowRoot); }); } catch (_) {} } walk(document); return results; } function getCurrentIndex(links) { const i = links.findIndex(l => l.hasAttribute('is-current-activity')); return i >= 0 ? i : 0; } function clickLink(link) { if (!link) return; link.click(); try { const inner = link.shadowRoot?.querySelector('a, button, [role="link"]'); if (inner) inner.click(); } catch (_) {} link.scrollIntoView({ behavior: 'smooth', block: 'center' }); console.log('[D2L v7.3] →', link.getAttribute('href')?.split('/').pop()); } let idx = -1, running = false, mainT = null, tickT = null, secs = 0, uiVisible = true; // ── Build UI ─────────────────────────────────────────────────────── const ui = document.createElement('div'); ui.id = 'd2l-aa'; ui.style.cssText = ` position:fixed;bottom:18px;right:18px;z-index:2147483647; background:#0d1117;color:#cdd6e0; font:13px/1.5 "Segoe UI",Arial,sans-serif; padding:12px 15px;border-radius:11px; box-shadow:0 4px 24px rgba(0,0,0,.85); min-width:235px;border:1px solid #30363d; transition:opacity 0.3s,transform 0.3s; `; ui.innerHTML = `
⚡ D2L Auto-Advance
Scanning...
0 / 0
F7=Hide · F8=Start/Stop · F9=Next
`; document.body.appendChild(ui); const el = id => document.getElementById(id); const setS = (t, c='#8b949e') => { const e=el('d2l-aa-s'); if(e){e.textContent=t;e.style.color=c;} }; const setP = (i, n) => { const e=el('d2l-aa-p'); if(e) e.textContent=`${i} / ${n}`; }; const setC = t => { const e=el('d2l-aa-c'); if(e) e.textContent=t||' '; }; const setB = (t, bg) => { const e=el('d2l-aa-b0'); if(e){e.textContent=t;e.style.background=bg;} }; function clearTimers() { clearTimeout(mainT); clearInterval(tickT); mainT = tickT = null; } function advance() { const links = getLinks(); if (!links.length) { setS('⚠ No links found', '#e3b341'); return false; } if (idx < 0) idx = getCurrentIndex(links); else idx++; if (idx >= links.length) { setS('✅ All done!', '#3fb950'); setP(links.length, links.length); setC('Complete!'); running = false; clearTimers(); setB('▶ F8', '#238636'); return false; } clickLink(links[idx]); setS('▶ Running', '#3fb950'); setP(idx + 1, links.length); setC(`Activity ${links[idx].getAttribute('href')?.split('/').pop().split('?')[0] || ''}`); return true; } function schedule() { if (!running) return; clearTimers(); const ms = rand(); secs = Math.ceil(ms / 1000); setC(`Next in ${secs}s`); tickT = setInterval(() => { secs--; setC(secs > 0 ? `Next in ${secs}s` : 'Advancing…'); if (secs <= 0) clearInterval(tickT); }, 1000); mainT = setTimeout(() => { if (running && advance()) schedule(); }, ms); } function toggleAuto() { if (running) { running = false; clearTimers(); setS('⏸ Paused', '#e3b341'); setB('▶ F8', '#238636'); } else { const links = getLinks(); if (!links.length) { setS('⚠ No links — reload page', '#e3b341'); return; } if (idx < 0) idx = getCurrentIndex(links) - 1; running = true; setB('⏸ F8', '#e3b341'); if (advance()) schedule(); } } function manualNext() { clearTimers(); if (advance() && running) schedule(); } function reset() { running = false; idx = -1; clearTimers(); const links = getLinks(); setS('↺ Reset — press F8', '#8b949e'); setP(0, links.length); setC(' '); setB('▶ F8', '#238636'); } function toggleUI() { uiVisible = !uiVisible; ui.style.opacity = uiVisible ? '1' : '0'; ui.style.pointerEvents = uiVisible ? 'auto' : 'none'; ui.style.transform = uiVisible ? 'translateY(0)' : 'translateY(20px)'; } el('d2l-aa-b0').onclick = toggleAuto; el('d2l-aa-b1').onclick = manualNext; el('d2l-aa-b2').onclick = reset; function onKey(e) { if (e.key === 'F7') { e.preventDefault(); toggleUI(); } if (e.key === 'F8') { e.preventDefault(); toggleAuto(); } if (e.key === 'F9') { e.preventDefault(); manualNext(); } } document.addEventListener('keydown', onKey, true); function init(attempts = 0) { const links = getLinks(); if (links.length > 0) { idx = getCurrentIndex(links) - 1; setS(`✅ ${links.length} links — press F8`, '#3fb950'); setP(0, links.length); console.log(`[D2L v7.3] Ready. ${links.length} links found.`); } else if (attempts < 10) { setTimeout(() => init(attempts + 1), 1000); } else { setS('⚠ No links found', '#e3b341'); } } setTimeout(() => init(), 1500); window.__d2lAA = { initialized: true, kill() { running = false; clearTimers(); document.getElementById('d2l-aa')?.remove(); document.removeEventListener('keydown', onKey, true); delete window.__d2lAA; } }; })();