PrepMart Question Freezer

Freeze questions and answer options in a floating panel for easy studying

Size

12.8 KB

Version

1.2.2

Created

Dec 29, 2025

Updated

4 months ago

1// ==UserScript==
2// @name		PrepMart Question Freezer
3// @description		Freeze questions and answer options in a floating panel for easy studying
4// @version		1.2.2
5// @match		https://*.prepmart.in/*
6// @icon		https://www.prepmart.in/prepmart-favicon.png?1764310267
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('PrepMart Question Freezer loaded');
12
13    // Add styles for the freeze panel and button
14    TM_addStyle(`
15        .freeze-question-btn {
16            position: fixed;
17            bottom: 20px;
18            right: 20px;
19            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
20            color: white;
21            border: none;
22            padding: 15px 25px;
23            border-radius: 50px;
24            cursor: pointer;
25            font-size: 16px;
26            font-weight: bold;
27            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
28            z-index: 9998;
29            transition: all 0.3s ease;
30        }
31
32        .freeze-question-btn:hover {
33            transform: translateY(-2px);
34            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
35        }
36
37        .frozen-panel {
38            position: fixed;
39            top: 50px;
40            right: 50px;
41            width: 450px;
42            max-height: 80vh;
43            background: white;
44            border: 3px solid #ffc107;
45            border-radius: 15px;
46            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
47            z-index: 9999;
48            overflow-y: auto;
49            display: none;
50        }
51
52        .frozen-panel.active {
53            display: block;
54            animation: slideIn 0.3s ease;
55        }
56
57        @keyframes slideIn {
58            from {
59                opacity: 0;
60                transform: translateX(100px);
61            }
62            to {
63                opacity: 1;
64                transform: translateX(0);
65            }
66        }
67
68        .frozen-panel-header {
69            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
70            color: white;
71            padding: 15px 20px;
72            border-radius: 12px 12px 0 0;
73            cursor: move;
74            display: flex;
75            justify-content: space-between;
76            align-items: center;
77            font-weight: bold;
78        }
79
80        .frozen-panel-close {
81            background: rgba(255, 255, 255, 0.2);
82            border: none;
83            color: white;
84            font-size: 24px;
85            cursor: pointer;
86            width: 30px;
87            height: 30px;
88            border-radius: 50%;
89            display: flex;
90            align-items: center;
91            justify-content: center;
92            transition: all 0.2s ease;
93        }
94
95        .frozen-panel-close:hover {
96            background: rgba(255, 255, 255, 0.3);
97            transform: rotate(90deg);
98        }
99
100        .frozen-panel-content {
101            padding: 20px;
102            color: #333;
103        }
104
105        .frozen-question {
106            font-size: 16px;
107            font-weight: 600;
108            margin-bottom: 20px;
109            line-height: 1.6;
110            color: #2c3e50;
111            border-left: 4px solid #667eea;
112            padding-left: 15px;
113        }
114
115        .frozen-options {
116            display: flex;
117            flex-direction: column;
118            gap: 12px;
119        }
120
121        .frozen-option {
122            display: flex;
123            align-items: flex-start;
124            padding: 12px 15px;
125            background: #f8f9fa;
126            border-radius: 8px;
127            border: 2px solid #e9ecef;
128            transition: all 0.2s ease;
129        }
130
131        .frozen-option:hover {
132            background: #fff3cd;
133            border-color: #ffc107;
134            transform: translateX(5px);
135        }
136
137        .frozen-option-prefix {
138            background: #ffc107;
139            color: #212529;
140            font-weight: bold;
141            padding: 5px 12px;
142            border-radius: 5px;
143            margin-right: 12px;
144            min-width: 30px;
145            text-align: center;
146        }
147
148        .frozen-option-text {
149            flex: 1;
150            line-height: 1.5;
151            color: #495057;
152        }
153
154        .frozen-panel-empty {
155            text-align: center;
156            padding: 40px 20px;
157            color: #6c757d;
158            font-style: italic;
159        }
160
161        .frozen-panel::-webkit-scrollbar {
162            width: 8px;
163        }
164
165        .frozen-panel::-webkit-scrollbar-track {
166            background: #f1f1f1;
167            border-radius: 10px;
168        }
169
170        .frozen-panel::-webkit-scrollbar-thumb {
171            background: #667eea;
172            border-radius: 10px;
173        }
174
175        .frozen-panel::-webkit-scrollbar-thumb:hover {
176            background: #764ba2;
177        }
178    `);
179
180    // Create the freeze button
181    function createFreezeButton() {
182        const btn = document.createElement('button');
183        btn.className = 'freeze-question-btn';
184        btn.textContent = '📌 Freeze Question';
185        btn.addEventListener('click', toggleFreezePanel);
186        document.body.appendChild(btn);
187        console.log('Freeze button created');
188    }
189
190    // Create the frozen panel
191    function createFrozenPanel() {
192        const panel = document.createElement('div');
193        panel.className = 'frozen-panel';
194        panel.id = 'frozen-panel';
195        
196        panel.innerHTML = `
197            <div class="frozen-panel-header" id="panel-header">
198                <span>📌 Frozen Question</span>
199                <button class="frozen-panel-close" id="close-panel">×</button>
200            </div>
201            <div class="frozen-panel-content" id="panel-content">
202                <div class="frozen-panel-empty">Click on a question to freeze it here</div>
203            </div>
204        `;
205        
206        document.body.appendChild(panel);
207        console.log('Frozen panel created');
208        
209        // Make panel draggable
210        makeDraggable(panel);
211        
212        // Close button functionality
213        document.getElementById('close-panel').addEventListener('click', () => {
214            panel.classList.remove('active');
215        });
216    }
217
218    // Make panel draggable
219    function makeDraggable(element) {
220        const header = element.querySelector('.frozen-panel-header');
221        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
222        
223        header.onmousedown = dragMouseDown;
224        
225        function dragMouseDown(e) {
226            e.preventDefault();
227            pos3 = e.clientX;
228            pos4 = e.clientY;
229            document.onmouseup = closeDragElement;
230            document.onmousemove = elementDrag;
231        }
232        
233        function elementDrag(e) {
234            e.preventDefault();
235            pos1 = pos3 - e.clientX;
236            pos2 = pos4 - e.clientY;
237            pos3 = e.clientX;
238            pos4 = e.clientY;
239            element.style.top = (element.offsetTop - pos2) + 'px';
240            element.style.left = (element.offsetLeft - pos1) + 'px';
241            element.style.right = 'auto';
242        }
243        
244        function closeDragElement() {
245            document.onmouseup = null;
246            document.onmousemove = null;
247        }
248    }
249
250    // Toggle freeze panel
251    function toggleFreezePanel() {
252        const panel = document.getElementById('frozen-panel');
253        
254        if (panel.classList.contains('active')) {
255            panel.classList.remove('active');
256        } else {
257            freezeCurrentQuestion();
258            panel.classList.add('active');
259        }
260    }
261
262    // Freeze the current question
263    function freezeCurrentQuestion() {
264        console.log('Attempting to freeze question');
265        
266        // Find all question containers
267        const questionContainers = document.querySelectorAll('.container .row.border.border-warning');
268        
269        if (questionContainers.length === 0) {
270            console.log('No questions found on page');
271            return;
272        }
273
274        // Get the first visible question (you can modify this to get a specific one)
275        let targetContainer = null;
276        
277        for (const container of questionContainers) {
278            const rect = container.getBoundingClientRect();
279            if (rect.top >= 0 && rect.top < window.innerHeight) {
280                targetContainer = container;
281                break;
282            }
283        }
284        
285        // If no visible question, use the first one
286        if (!targetContainer) {
287            targetContainer = questionContainers[0];
288        }
289
290        // Extract question text
291        const questionElement = targetContainer.querySelector('#question span, #question');
292        const questionText = questionElement ? questionElement.textContent.trim() : 'Question not found';
293        
294        // Extract options
295        const optionsContainer = targetContainer.querySelector('#game');
296        const options = [];
297        
298        if (optionsContainer) {
299            const choiceContainers = optionsContainer.querySelectorAll('.choice-container');
300            choiceContainers.forEach(choice => {
301                const prefix = choice.querySelector('.choice-prefix');
302                const text = choice.querySelector('.choice-text');
303                
304                if (prefix && text) {
305                    options.push({
306                        prefix: prefix.textContent.trim(),
307                        text: text.textContent.trim()
308                    });
309                }
310            });
311        }
312
313        console.log('Frozen question:', questionText);
314        console.log('Frozen options:', options);
315
316        // Update panel content
317        displayFrozenQuestion(questionText, options);
318    }
319
320    // Display frozen question in panel
321    function displayFrozenQuestion(questionText, options) {
322        const panelContent = document.getElementById('panel-content');
323        
324        let optionsHTML = '';
325        options.forEach(option => {
326            optionsHTML += `
327                <div class="frozen-option">
328                    <div class="frozen-option-prefix">${option.prefix}</div>
329                    <div class="frozen-option-text">${option.text}</div>
330                </div>
331            `;
332        });
333
334        panelContent.innerHTML = `
335            <div class="frozen-question">${questionText}</div>
336            <div class="frozen-options">
337                ${optionsHTML}
338            </div>
339        `;
340    }
341
342    // Add click listeners to all questions
343    function addQuestionClickListeners() {
344        const questionContainers = document.querySelectorAll('.container .row.border.border-warning');
345        
346        questionContainers.forEach((container, index) => {
347            container.style.cursor = 'pointer';
348            container.addEventListener('click', function(e) {
349                // Don't trigger if clicking on links or buttons
350                if (e.target.tagName === 'A' || e.target.tagName === 'BUTTON' || e.target.closest('a')) {
351                    return;
352                }
353                
354                console.log('Question clicked:', index);
355                freezeSpecificQuestion(container);
356                
357                const panel = document.getElementById('frozen-panel');
358                if (!panel.classList.contains('active')) {
359                    panel.classList.add('active');
360                }
361            });
362        });
363        
364        console.log(`Added click listeners to ${questionContainers.length} questions`);
365    }
366
367    // Freeze a specific question
368    function freezeSpecificQuestion(container) {
369        // Extract question text
370        const questionElement = container.querySelector('#question span, #question');
371        const questionText = questionElement ? questionElement.textContent.trim() : 'Question not found';
372        
373        // Extract options
374        const optionsContainer = container.querySelector('#game');
375        const options = [];
376        
377        if (optionsContainer) {
378            const choiceContainers = optionsContainer.querySelectorAll('.choice-container');
379            choiceContainers.forEach(choice => {
380                const prefix = choice.querySelector('.choice-prefix');
381                const text = choice.querySelector('.choice-text');
382                
383                if (prefix && text) {
384                    options.push({
385                        prefix: prefix.textContent.trim(),
386                        text: text.textContent.trim()
387                    });
388                }
389            });
390        }
391
392        displayFrozenQuestion(questionText, options);
393    }
394
395    // Initialize the extension
396    function init() {
397        console.log('Initializing PrepMart Question Freezer');
398        
399        // Wait for page to be ready
400        if (document.readyState === 'loading') {
401            document.addEventListener('DOMContentLoaded', init);
402            return;
403        }
404
405        // Create UI elements
406        createFreezeButton();
407        createFrozenPanel();
408        
409        // Add click listeners to questions
410        setTimeout(() => {
411            addQuestionClickListeners();
412        }, 1000);
413    }
414
415    // Start the extension
416    init();
417})();