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})();