IXL Auto Skill Completer

Automatically solves IXL questions and completes skills

Size

5.4 KB

Version

1.0.1

Created

Feb 26, 2026

Updated

about 2 months ago

1// ==UserScript==
2// @name		IXL Auto Skill Completer
3// @description		Automatically solves IXL questions and completes skills
4// @version		1.0.1
5// @match		https://*.ixl.com/*
6// @icon		https://www.ixl.com/ixl-favicon.png
7// @grant		GM.getValue
8// @grant		GM.setValue
9// ==/UserScript==
10(function() {
11    'use strict';
12
13    console.log('IXL Auto Skill Completer loaded');
14
15    // Debounce function to prevent multiple rapid calls
16    function debounce(func, wait) {
17        let timeout;
18        return function executedFunction(...args) {
19            const later = () => {
20                clearTimeout(timeout);
21                func(...args);
22            };
23            clearTimeout(timeout);
24            timeout = setTimeout(later, wait);
25        };
26    }
27
28    // Function to extract the question text from the page
29    function getQuestionText() {
30        const questionSection = document.querySelector('.question-and-submission-view');
31        if (!questionSection) return null;
32
33        // Get the question text, excluding the input field and button
34        const clone = questionSection.cloneNode(true);
35        const inputs = clone.querySelectorAll('input');
36        inputs.forEach(input => input.remove());
37        const buttons = clone.querySelectorAll('button');
38        buttons.forEach(button => button.remove());
39
40        return clone.textContent.trim();
41    }
42
43    // Function to solve the question using AI
44    async function solveQuestion() {
45        try {
46            const questionText = getQuestionText();
47            if (!questionText) {
48                console.log('No question found');
49                return;
50            }
51
52            console.log('Question:', questionText);
53
54            // Use AI to solve the question
55            const answer = await RM.aiCall(
56                `Solve this math problem and provide ONLY the numerical answer (no explanation, no units, just the number): ${questionText}`,
57                {
58                    type: "json_schema",
59                    json_schema: {
60                        name: "math_answer",
61                        schema: {
62                            type: "object",
63                            properties: {
64                                answer: { type: "string" }
65                            },
66                            required: ["answer"]
67                        }
68                    }
69                }
70            );
71
72            console.log('AI Answer:', answer.answer);
73
74            // Fill in the answer
75            const inputField = document.querySelector('input.fillIn');
76            if (inputField) {
77                inputField.value = answer.answer;
78                inputField.dispatchEvent(new Event('input', { bubbles: true }));
79                inputField.dispatchEvent(new Event('change', { bubbles: true }));
80
81                // Wait a moment then submit
82                setTimeout(() => {
83                    const submitButton = document.querySelector('button.crisp-button');
84                    if (submitButton && submitButton.textContent.includes('Submit')) {
85                        console.log('Submitting answer...');
86                        submitButton.click();
87                    }
88                }, 500);
89            }
90
91        } catch (error) {
92            console.error('Error solving question:', error);
93        }
94    }
95
96    // Function to handle the "Continue" button after answering
97    function clickContinueIfPresent() {
98        const continueButton = document.querySelector('button.crisp-button');
99        if (continueButton && (continueButton.textContent.includes('Continue') || continueButton.textContent.includes('Next'))) {
100            console.log('Clicking continue button...');
101            setTimeout(() => {
102                continueButton.click();
103            }, 1000);
104        }
105    }
106
107    // Observer to watch for DOM changes
108    const observer = new MutationObserver(debounce(() => {
109        // Check if we're on a skill page
110        if (!window.location.pathname.includes('/math/') && !window.location.pathname.includes('/ela/')) {
111            return;
112        }
113
114        // Check for new question
115        const questionSection = document.querySelector('.question-and-submission-view');
116        const inputField = document.querySelector('input.fillIn');
117        const submitButton = document.querySelector('button.crisp-button');
118
119        if (questionSection && inputField && submitButton && submitButton.textContent.includes('Submit')) {
120            // New question detected, solve it
121            if (!inputField.value) {
122                console.log('New question detected, solving...');
123                solveQuestion();
124            }
125        } else {
126            // Check for continue button
127            clickContinueIfPresent();
128        }
129    }, 1000));
130
131    // Start observing
132    function init() {
133        console.log('Starting IXL Auto Skill Completer...');
134        
135        // Observe the entire document for changes
136        observer.observe(document.body, {
137            childList: true,
138            subtree: true
139        });
140
141        // Try to solve the current question if one exists
142        setTimeout(() => {
143            const inputField = document.querySelector('input.fillIn');
144            if (inputField && !inputField.value) {
145                solveQuestion();
146            }
147        }, 2000);
148    }
149
150    // Wait for page to be ready
151    if (document.readyState === 'loading') {
152        document.addEventListener('DOMContentLoaded', init);
153    } else {
154        init();
155    }
156
157})();