UofT - Course Hover Popup

Show course details on hover

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         UofT - Course Hover Popup
// @namespace    https://gist.github.com/jackjona/bbdce489534ec873b0738cca10100fc2
// @homepageURL  https://gist.github.com/jackjona/bbdce489534ec873b0738cca10100fc2
// @supportURL   https://gist.github.com/jackjona/bbdce489534ec873b0738cca10100fc2
// @version      1.2
// @description  Show course details on hover
// @author       Jack Jona
// @match        https://artsci.calendar.utoronto.ca/*
// @icon         https://icons.duckduckgo.com/ip3/utoronto.ca.ico
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Add CSS for the popup
    GM_addStyle(`
        .course-popup {
            position: absolute;
            border: 1px solid #ccc;
            border-radius: 3px;
            background: #fff;
            padding: 10px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
            z-index: 1000;
            display: none;
            max-width: 580px;
        }
    `);

    // Create the popup element
    const popup = document.createElement('div');
    popup.className = 'course-popup';
    document.body.appendChild(popup);

    // Function to show the popup
    function showPopup(event, content) {
        popup.innerHTML = content;
        popup.style.top = `${event.pageY + 10}px`;
        popup.style.left = `${event.pageX + 10}px`;
        popup.style.display = 'block';
    }

    // Function to hide the popup
    function hidePopup() {
        popup.style.display = 'none';
    }

    // Function to extract course details
    function extractCourseDetails(html) {
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');

        // Data to extract
        const title = doc.querySelector('h1.page-title')?.innerText || 'N/A';
        const hours = doc.querySelector('div.field--name-field-hours .field__item')?.innerText || 'N/A';
        const descriptionElements = doc.querySelectorAll('div.node__content div.field--name-body.field--type-text-with-summary p');
        const description = Array.from(descriptionElements).map(p => p.innerText).join('<br><br>') || 'N/A';
        const prerequisites = doc.querySelector('div.field--name-field-prerequisite .field__item')?.innerText || 'N/A';
        const corequisites = doc.querySelector('div.field--name-field-corequisite .field__item')?.innerText || 'N/A';
        const requirement = doc.querySelector('div.field--name-field-breadth-requirements .field__item')?.innerText || 'N/A';

        // Displayed content
        return `
            <strong>Title:</strong> ${title}<br>
            <strong>Hours:</strong> ${hours}<br>
            <strong>Description:</strong> ${description}<br>
            <strong>Prerequisites:</strong> ${prerequisites}<br>
            <strong>Corequisites:</strong> ${corequisites}<br>
            <strong>Requirement (Breadth):</strong> ${requirement}
        `;
    }

    // Add event listeners to course links
    document.querySelectorAll('a[href^="/course/"]').forEach(link => {
        link.addEventListener('mouseover', event => {
            const url = link.getAttribute('href').toLowerCase();
            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                onload: function(response) {
                    const details = extractCourseDetails(response.responseText);
                    showPopup(event, details);
                }
            });
        });

        link.addEventListener('mouseout', hidePopup);
    });
})();