Examveda Ad-Free with PDF Downloads

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})();
Examveda Ad-Free with PDF Downloads | Robomonkey