Résumé de liens Canopé

Affiche un résumé rapide des liens importants de la page

Size

8.9 KB

Version

1.2.1

Created

Nov 9, 2025

Updated

about 1 month ago

1// ==UserScript==
2// @name		Résumé de liens Canopé
3// @description		Affiche un résumé rapide des liens importants de la page
4// @version		1.2.1
5// @match		https://*.reseau-canope.fr/*
6// @icon		https://cdn.reseau-canope.fr/static-assets/Images/Favicon/rc/RC-favicon_FAV16.png
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('Extension Résumé de liens Canopé démarrée');
12
13    // Fonction pour extraire les liens importants de la page
14    function extractImportantLinks() {
15        const links = [];
16        const seenUrls = new Set();
17
18        // Extraire les liens du menu principal
19        const mainNav = document.querySelector('nav[role="navigation"][aria-label="Menu principal"]');
20        if (mainNav) {
21            const navLinks = mainNav.querySelectorAll('a[href]');
22            navLinks.forEach(link => {
23                const url = link.href;
24                const text = link.textContent.trim();
25                if (url && text && !seenUrls.has(url)) {
26                    seenUrls.add(url);
27                    links.push({ text, url, category: 'Navigation' });
28                }
29            });
30        }
31
32        // Extraire les liens des actualités
33        const newsCards = document.querySelectorAll('.card--is-link a.card__link');
34        newsCards.forEach(link => {
35            const url = link.href;
36            const text = link.textContent.trim();
37            if (url && text && !seenUrls.has(url)) {
38                seenUrls.add(url);
39                links.push({ text, url, category: 'Actualités' });
40            }
41        });
42
43        // Extraire les liens du contenu principal
44        const mainContent = document.querySelector('main#main-content');
45        if (mainContent) {
46            const contentLinks = mainContent.querySelectorAll('a[href]:not(.card__link)');
47            contentLinks.forEach(link => {
48                const url = link.href;
49                const text = link.textContent.trim();
50                // Filtrer les liens vides ou trop courts
51                if (url && text && text.length > 3 && !seenUrls.has(url)) {
52                    seenUrls.add(url);
53                    links.push({ text, url, category: 'Contenu' });
54                }
55            });
56        }
57
58        console.log(`${links.length} liens extraits de la page`);
59        return links;
60    }
61
62    // Fonction pour créer le bouton flottant
63    function createFloatingButton() {
64        const button = document.createElement('button');
65        button.id = 'canope-summary-btn';
66        button.innerHTML = '📋';
67        button.title = 'Afficher le résumé des liens';
68        button.style.cssText = `
69            position: fixed;
70            bottom: 20px;
71            right: 20px;
72            width: 60px;
73            height: 60px;
74            border-radius: 50%;
75            background: linear-gradient(135deg, #0066cc 0%, #004999 100%);
76            color: white;
77            border: none;
78            font-size: 28px;
79            cursor: pointer;
80            box-shadow: 0 4px 12px rgba(0, 102, 204, 0.4);
81            z-index: 9999;
82            transition: all 0.3s ease;
83            display: flex;
84            align-items: center;
85            justify-content: center;
86        `;
87
88        button.addEventListener('mouseenter', () => {
89            button.style.transform = 'scale(1.1)';
90            button.style.boxShadow = '0 6px 16px rgba(0, 102, 204, 0.6)';
91        });
92
93        button.addEventListener('mouseleave', () => {
94            button.style.transform = 'scale(1)';
95            button.style.boxShadow = '0 4px 12px rgba(0, 102, 204, 0.4)';
96        });
97
98        button.addEventListener('click', () => {
99            toggleSummaryPanel();
100        });
101
102        document.body.appendChild(button);
103        console.log('Bouton flottant créé');
104    }
105
106    // Fonction pour créer le panneau de résumé
107    function createSummaryPanel() {
108        const panel = document.createElement('div');
109        panel.id = 'canope-summary-panel';
110        panel.style.cssText = `
111            position: fixed;
112            top: 50%;
113            right: 20px;
114            transform: translateY(-50%) translateX(450px);
115            width: 400px;
116            max-height: 80vh;
117            background: white;
118            border-radius: 12px;
119            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
120            z-index: 10000;
121            overflow: hidden;
122            transition: transform 0.3s ease;
123            display: flex;
124            flex-direction: column;
125        `;
126
127        // En-tête du panneau
128        const header = document.createElement('div');
129        header.style.cssText = `
130            background: linear-gradient(135deg, #0066cc 0%, #004999 100%);
131            color: white;
132            padding: 20px;
133            font-size: 18px;
134            font-weight: bold;
135            display: flex;
136            justify-content: space-between;
137            align-items: center;
138        `;
139        header.innerHTML = `
140            <span>📋 Résumé des liens</span>
141            <button id="canope-close-panel" style="background: none; border: none; color: white; font-size: 24px; cursor: pointer; padding: 0; width: 30px; height: 30px;">×</button>
142        `;
143
144        // Contenu du panneau
145        const content = document.createElement('div');
146        content.id = 'canope-summary-content';
147        content.style.cssText = `
148            padding: 20px;
149            overflow-y: auto;
150            flex: 1;
151        `;
152
153        panel.appendChild(header);
154        panel.appendChild(content);
155        document.body.appendChild(panel);
156
157        // Événement pour fermer le panneau
158        document.getElementById('canope-close-panel').addEventListener('click', () => {
159            toggleSummaryPanel();
160        });
161
162        console.log('Panneau de résumé créé');
163        return panel;
164    }
165
166    // Fonction pour afficher les liens dans le panneau
167    function displayLinks(links) {
168        const content = document.getElementById('canope-summary-content');
169        if (!content) return;
170
171        if (links.length === 0) {
172            content.innerHTML = '<p style="color: #666; text-align: center;">Aucun lien trouvé sur cette page.</p>';
173            return;
174        }
175
176        // Grouper les liens par catégorie
177        const groupedLinks = {};
178        links.forEach(link => {
179            if (!groupedLinks[link.category]) {
180                groupedLinks[link.category] = [];
181            }
182            groupedLinks[link.category].push(link);
183        });
184
185        let html = '';
186        for (const [category, categoryLinks] of Object.entries(groupedLinks)) {
187            html += `
188                <div style="margin-bottom: 24px;">
189                    <h3 style="color: #0066cc; font-size: 16px; font-weight: bold; margin-bottom: 12px; border-bottom: 2px solid #0066cc; padding-bottom: 8px;">
190                        ${category} (${categoryLinks.length})
191                    </h3>
192                    <ul style="list-style: none; padding: 0; margin: 0;">
193            `;
194
195            categoryLinks.forEach(link => {
196                html += `
197                    <li style="margin-bottom: 8px;">
198                        <a href="${link.url}" 
199                           target="_blank" 
200                           style="color: #004999; text-decoration: none; display: block; padding: 8px; border-radius: 6px; transition: background 0.2s ease;"
201                           onmouseover="this.style.background='#f0f7ff'"
202                           onmouseout="this.style.background='transparent'">
203                            🔗 ${link.text}
204                        </a>
205                    </li>
206                `;
207            });
208
209            html += `
210                    </ul>
211                </div>
212            `;
213        }
214
215        content.innerHTML = html;
216        console.log('Liens affichés dans le panneau');
217    }
218
219    // Fonction pour basculer l'affichage du panneau
220    function toggleSummaryPanel() {
221        let panel = document.getElementById('canope-summary-panel');
222        
223        if (!panel) {
224            panel = createSummaryPanel();
225            const links = extractImportantLinks();
226            displayLinks(links);
227        }
228
229        const isVisible = panel.style.transform === 'translateY(-50%) translateX(0px)';
230        
231        if (isVisible) {
232            panel.style.transform = 'translateY(-50%) translateX(450px)';
233            console.log('Panneau masqué');
234        } else {
235            panel.style.transform = 'translateY(-50%) translateX(0px)';
236            console.log('Panneau affiché');
237        }
238    }
239
240    // Initialisation de l'extension
241    function init() {
242        console.log('Initialisation de l\'extension Résumé de liens Canopé');
243        
244        // Attendre que le DOM soit complètement chargé
245        if (document.readyState === 'loading') {
246            document.addEventListener('DOMContentLoaded', () => {
247                createFloatingButton();
248            });
249        } else {
250            createFloatingButton();
251        }
252    }
253
254    // Démarrer l'extension
255    init();
256})();
Résumé de liens Canopé | Robomonkey