Removes all ads, hides login options, and adds PDF download buttons to content sections
Size
10.0 KB
Version
1.1.1
Created
Oct 29, 2025
Updated
about 2 months ago
1// ==UserScript==
2// @name Examveda Ad-Free with PDF Downloads
3// @description Removes all ads, hides login options, and adds PDF download buttons to content sections
4// @version 1.1.1
5// @match https://*.examveda.com/*
6// @icon https://www.examveda.com/favicon.ico
7// @grant GM.xmlhttpRequest
8// @require https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
9// @require https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
10// ==/UserScript==
11(function() {
12 'use strict';
13
14 console.log('Examveda Ad-Free Extension: Starting...');
15
16 // Function to remove all advertisements
17 function removeAds() {
18 console.log('Removing advertisements...');
19
20 // Remove Google AdSense ads
21 const adsbyGoogle = document.querySelectorAll('.adsbygoogle, ins.adsbygoogle');
22 adsbyGoogle.forEach(ad => {
23 console.log('Removing AdSense element:', ad);
24 ad.remove();
25 });
26
27 // Remove ad iframes
28 const adIframes = document.querySelectorAll('iframe[src*="ads"], iframe[src*="doubleclick"], iframe[src*="googlesyndication"]');
29 adIframes.forEach(iframe => {
30 console.log('Removing ad iframe:', iframe);
31 iframe.remove();
32 });
33
34 // Remove elements with ad-related IDs and classes
35 const adElements = document.querySelectorAll('[id*="ad-"], [class*="ad-container"], [id*="advertisement"], [class*="advertisement"]');
36 adElements.forEach(el => {
37 console.log('Removing ad element:', el);
38 el.remove();
39 });
40
41 // Remove parent containers that only contain ads
42 const pageShortcodes = document.querySelectorAll('.page-content.page-shortcode');
43 pageShortcodes.forEach(container => {
44 // If container only has ad content and no meaningful text
45 if (container.querySelector('.adsbygoogle') && container.textContent.trim().length < 50) {
46 console.log('Removing ad container:', container);
47 container.remove();
48 }
49 });
50
51 console.log('Advertisements removed successfully');
52 }
53
54 // Function to hide login and signup options
55 function hideLoginSignup() {
56 console.log('Hiding login/signup options...');
57
58 // Hide login links
59 const loginLinks = document.querySelectorAll('a[href*="login"], a[href*="signin"], button[class*="login"]');
60 loginLinks.forEach(link => {
61 console.log('Hiding login element:', link);
62 link.style.display = 'none';
63 });
64
65 // Hide signup/register links
66 const signupLinks = document.querySelectorAll('a[href*="signup"], a[href*="register"], button[class*="signup"], button[class*="register"]');
67 signupLinks.forEach(link => {
68 console.log('Hiding signup element:', link);
69 link.style.display = 'none';
70 });
71
72 console.log('Login/signup options hidden successfully');
73 }
74
75 // Function to add PDF download buttons to content sections
76 function addPDFDownloadButtons() {
77 console.log('Adding PDF download buttons...');
78
79 // Find all main content sections
80 const contentSections = document.querySelectorAll('.page-content.page-shortcode');
81
82 contentSections.forEach((section, index) => {
83 // Skip if this section only contains ads or is empty
84 if (section.querySelector('.adsbygoogle') || section.textContent.trim().length < 50) {
85 return;
86 }
87
88 // Check if button already exists
89 if (section.querySelector('.pdf-download-btn')) {
90 return;
91 }
92
93 // Find the title element
94 const titleElement = section.querySelector('.boxedtitle.page-title h2');
95 if (!titleElement) {
96 return;
97 }
98
99 // Create download button
100 const downloadBtn = document.createElement('button');
101 downloadBtn.className = 'pdf-download-btn';
102 downloadBtn.innerHTML = '📥 Download as PDF';
103 downloadBtn.style.cssText = `
104 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
105 color: white;
106 border: none;
107 padding: 10px 20px;
108 border-radius: 6px;
109 cursor: pointer;
110 font-size: 14px;
111 font-weight: 600;
112 margin: 10px 0;
113 display: inline-block;
114 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
115 transition: all 0.3s ease;
116 `;
117
118 // Add hover effect
119 downloadBtn.onmouseover = function() {
120 this.style.transform = 'translateY(-2px)';
121 this.style.boxShadow = '0 6px 12px rgba(0, 0, 0, 0.15)';
122 };
123 downloadBtn.onmouseout = function() {
124 this.style.transform = 'translateY(0)';
125 this.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
126 };
127
128 // Add click handler
129 downloadBtn.onclick = async function() {
130 const originalText = this.innerHTML;
131 this.innerHTML = '⏳ Generating PDF...';
132 this.disabled = true;
133
134 try {
135 await generatePDF(section, titleElement.textContent.trim());
136 this.innerHTML = '✅ Downloaded!';
137 setTimeout(() => {
138 this.innerHTML = originalText;
139 this.disabled = false;
140 }, 2000);
141 } catch (error) {
142 console.error('PDF generation error:', error);
143 this.innerHTML = '❌ Error - Try Again';
144 setTimeout(() => {
145 this.innerHTML = originalText;
146 this.disabled = false;
147 }, 2000);
148 }
149 };
150
151 // Insert button after the title
152 titleElement.parentElement.insertAdjacentElement('afterend', downloadBtn);
153 console.log('Added PDF download button to section:', index);
154 });
155
156 console.log('PDF download buttons added successfully');
157 }
158
159 // Function to generate PDF from content section
160 async function generatePDF(section, title) {
161 console.log('Generating PDF for:', title);
162
163 const { jsPDF } = window.jspdf;
164 const pdf = new jsPDF('p', 'mm', 'a4');
165
166 // Add title
167 pdf.setFontSize(18);
168 pdf.setFont(undefined, 'bold');
169 pdf.text(title, 15, 20);
170
171 // Use html2canvas to capture the content
172 const canvas = await html2canvas(section, {
173 scale: 2,
174 useCORS: true,
175 logging: false,
176 backgroundColor: '#ffffff'
177 });
178
179 const imgData = canvas.toDataURL('image/png');
180 const imgWidth = 180; // A4 width minus margins
181 const imgHeight = (canvas.height * imgWidth) / canvas.width;
182
183 let heightLeft = imgHeight;
184 let position = 30;
185
186 // Add first page
187 pdf.addImage(imgData, 'PNG', 15, position, imgWidth, imgHeight);
188 heightLeft -= (pdf.internal.pageSize.height - position);
189
190 // Add additional pages if needed
191 while (heightLeft > 0) {
192 position = heightLeft - imgHeight;
193 pdf.addPage();
194 pdf.addImage(imgData, 'PNG', 15, position, imgWidth, imgHeight);
195 heightLeft -= pdf.internal.pageSize.height;
196 }
197
198 // Generate filename from title
199 const filename = title.replace(/[^a-z0-9]/gi, '_').toLowerCase() + '.pdf';
200 pdf.save(filename);
201
202 console.log('PDF generated successfully:', filename);
203 }
204
205 // Add custom CSS to improve appearance
206 function addCustomStyles() {
207 const style = document.createElement('style');
208 style.textContent = `
209 /* Hide ad spaces */
210 .adsbygoogle,
211 ins.adsbygoogle,
212 [id*="ad-"],
213 [class*="ad-container"] {
214 display: none !important;
215 }
216
217 /* Improve content spacing after ad removal */
218 .page-content.page-shortcode {
219 margin-bottom: 20px;
220 }
221
222 /* PDF button responsive design */
223 @media (max-width: 768px) {
224 .pdf-download-btn {
225 width: 100%;
226 margin: 15px 0 !important;
227 }
228 }
229
230 /* Clean layout */
231 .main-content {
232 background: white;
233 }
234 `;
235 document.head.appendChild(style);
236 console.log('Custom styles added');
237 }
238
239 // Debounce function for MutationObserver
240 function debounce(func, wait) {
241 let timeout;
242 return function executedFunction(...args) {
243 const later = () => {
244 clearTimeout(timeout);
245 func(...args);
246 };
247 clearTimeout(timeout);
248 timeout = setTimeout(later, wait);
249 };
250 }
251
252 // Initialize the extension
253 function init() {
254 console.log('Initializing Examveda Ad-Free Extension...');
255
256 // Add custom styles
257 addCustomStyles();
258
259 // Remove ads
260 removeAds();
261
262 // Hide login/signup
263 hideLoginSignup();
264
265 // Add PDF download buttons
266 addPDFDownloadButtons();
267
268 // Watch for dynamic content changes
269 const debouncedUpdate = debounce(() => {
270 removeAds();
271 hideLoginSignup();
272 addPDFDownloadButtons();
273 }, 1000);
274
275 const observer = new MutationObserver(debouncedUpdate);
276 observer.observe(document.body, {
277 childList: true,
278 subtree: true
279 });
280
281 console.log('Examveda Ad-Free Extension: Initialized successfully!');
282 }
283
284 // Wait for page to load
285 if (document.readyState === 'loading') {
286 document.addEventListener('DOMContentLoaded', init);
287 } else {
288 init();
289 }
290
291})();