3
Injecting code into UT Pages
Derek edited this page 2025-07-22 04:52:46 -05:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Code Injection Guide

This page documents how we inject code into supported pages across the UT Austin web ecosystem.

Choosing a page to inject on

Current URL is obtained through window.location.href by calling getSiteSupport

siteSupport

Contains enum to determine what page a user is on. For example

if (url.includes('my.utexas.edu/student/student/index') || url.includes('my.utexas.edu/student/')) {
    return SiteSupport.MY_UT;
}

renderComponent

Found in index.tsx in pages, the renderComponent function is a utility used by the extension to inject React components into websites (and other supported pages). It creates a new div and appends it to the document body. It then uses Reacts createRoot to render the React component inside this container.

const renderComponent = (Component: React.ComponentType) => {
    const container = document.createElement('div');
    container.id = 'extension-root';
    document.body.appendChild(container);

    createRoot(container).render(
        <React.StrictMode>
            <Component />
        </React.StrictMode>
    );
};

After a site is determined, components are rendered in index.tsx. For example

if (support === SiteSupport.COURSE_CATALOG_DETAILS || support === SiteSupport.COURSE_CATALOG_LIST) {
    renderComponent(() => <CourseCatalogMain support={support} />);
}

if (support === SiteSupport.MY_UT) {
    renderComponent(InjectedButton);
}

if (support === SiteSupport.COURSE_CATALOG_SEARCH) {
    renderComponent(DaysCheckbox);
}

Erasing elements on webpages

This can be accomplished easily through retrieving elements, for example using document.getElementById, and changing their innerHTML to ''

For example with DaysCheckbox

        const daysDropdown = document.getElementById('mtg_days_st') as HTMLSelectElement | null;
        if (!daysDropdown) {
            console.error('Days dropdown not found');
            return;
        }

        const formElement = daysDropdown.closest('.form_element')!;
        const checkboxContainer = document.createElement('div');

        // Create a hidden input to store the value
        const hiddenInput = document.createElement('input');
        hiddenInput.type = 'hidden';
        hiddenInput.name = 'mtg_days_st';
        hiddenInput.id = 'mtg_days_st_hidden';
        hiddenInput.value = daysDropdown.value;

        // Remove old dropdown
        formElement.innerHTML = '';

Examples

CourseCatalogMain

Relevant page: image

<ExtensionRoot> used to prevent the native page styles from being overridden with our own.

return (
        <ExtensionRoot>
            <NewSearchLink />
            <RecruitmentBanner />
            <TableHead>Plus</TableHead>
            {rows.map(
                row =>
                    row.course && (
                        <TableRow
                            key={row.course.uniqueId}
                            row={row}
                            isSelected={row.course.uniqueId === selectedCourse?.uniqueId}
                            activeSchedule={activeSchedule}
                            onClick={handleRowButtonClick(row.course)}
                        />
                    )
            )}
            <CourseCatalogInjectedPopup
                course={selectedCourse!} // always defined when showPopup is true
                show={showPopup}
                onClose={() => setShowPopup(false)}
                afterLeave={() => setSelectedCourse(null)}
            />
            {enableScrollToLoad && <AutoLoad addRows={addRows} />}
        </ExtensionRoot>
    );

AddAllButton

// Existing code above
    return ReactDOM.createPortal(
        <ExtensionRoot>
            <Button variant='filled' color='ut-burntorange' onClick={extractCoursesFromCalendar}>
                Add Courses to UT Registration+
            </Button>
        </ExtensionRoot>,
        container
    );