您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Extract event details and display them on the calendar page
当前为
// ==UserScript== // @name RSROC Event Details // @namespace http://tampermonkey.net/ // @version 0.5 // @description Extract event details and display them on the calendar page // @author Cheng Hsien Tsou // @match https://www.rsroc.org.tw/action/* // @grant none // @license MIT // ==/UserScript== /* 這個script使用來擷取RSROC網站上的活動資訊,並將教育積分時數顯示在活動頁面上。 產生google calendar的連結,並在滑鼠懸停時顯示活動內容和聯絡資訊的tooltip。 */ // Immediately-invoked function expression (IIFE) to encapsulate the script (function() { 'use strict'; // Function to fetch event details from a given URL async function fetchEventDetails(url) { try { // Fetch the HTML content of the event page const response = await fetch(url); const html = await response.text(); // Parse the HTML string into a DOM document const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); // Initialize variables to store extracted details let educationPoints = ''; let recognizedHours = ''; let eventDateTime = ''; let eventLocation = ''; let eventTitle = ''; let eventContent = ''; let contactInfo = ''; // Select all table rows within the article content const rows = doc.querySelectorAll('.articleContent table tr'); // Iterate over each row to find specific details for (const row of rows) { const th = row.querySelector('th'); if (th) { // Check the header text to identify the data if (th.innerText.includes('活動日期')) { const td = row.querySelector('td'); if (td) eventDateTime = td.innerText.trim(); } if (th.innerText.includes('主辦單位')) { // Extract event title from caption const caption = doc.querySelector('.tableContent caption'); if (caption) eventTitle = caption.innerText.trim(); } if (th.innerText.includes('活動地點')) { const td = row.querySelector('td'); if (td) eventLocation = td.innerText.trim(); } if (th.innerText.includes('活動內容')) { const td = row.querySelector('td'); if (td) eventContent = td.innerText.trim(); } if (th.innerText.includes('教育積點')) { const td = row.querySelector('td'); if (td) educationPoints = td.innerText.replace('放射診斷科專科醫師', '').trim(); } if (th.innerText.includes('認定時數')) { const td = row.querySelector('td'); if (td) recognizedHours = td.innerText.trim(); } if (th.innerText.includes('聯絡資訊')) { const td = row.querySelector('td'); if (td) contactInfo = td.innerText.trim(); } } } // Return an object containing the extracted details return { educationPoints, recognizedHours, eventDateTime, eventLocation, eventTitle, eventContent, contactInfo }; } catch (error) { // Log any errors during fetching or parsing console.error('Error fetching event details:', error); // Return default values in case of an error return { educationPoints: 'N/A', recognizedHours: 'N/A', eventDateTime: '', eventLocation: '', eventTitle: 'Event', eventContent: '', contactInfo: '' }; } } // Function to format the date and time string for Google Calendar function formatGoogleCalendarDate(dateTimeString) { // Expected format: YYYY/MM/DD 星期X HH:MM ~ HH:MM // Use regex to extract date and time components const parts = dateTimeString.match(/(\d{4})\/(\d{2})\/(\d{2}).*?(\d{2}):(\d{2})\s*~*\s*(\d{0,2})*:*(\d{0,2})/); if (!parts) return null; // Return null if the format doesn't match // Extract components from regex parts const year = parts[1]; const month = parts[2]; const day = parts[3]; const startHour = parts[4]; const startMinute = parts[5]; const endHour = parts[6] || startHour; // Assume same hour if end hour is missing const endMinute = parts[7] || startMinute; // Assume same minute if end minute is missing // Google Calendar format: YYYYMMDDTHHMMSS/YYYYMMDDTHHMMSS const start = `${year}${month}${day}T${startHour}${startMinute}00`; const end = `${year}${month}${day}T${endHour}${endMinute}00`; // Return the formatted date string return `${start}/${end}`; } // Main function to add event details and Google Calendar links to the page async function addEventDetailsToCalendar() { // Select all event links on the page const eventLinks = document.querySelectorAll('.eventLink'); // Create tooltip element for displaying event content and contact info on hover const tooltip = document.createElement('div'); tooltip.style.cssText = ` position: absolute; background-color: #fff; border: 1px solid #ccc; padding: 10px; z-index: 1000; display: none; font-size: 0.9em; color: #333; max-width: 300px; word-wrap: break-word; pointer-events: none; /* Allow clicks to pass through */ `; document.body.appendChild(tooltip); // Iterate over each event link for (const link of eventLinks) { const url = link.href; const eventDiv = link.querySelector('.event'); const eventText = eventDiv.innerText; // Fetch details for the current event const details = await fetchEventDetails(url); // Store fetched details as data attributes on the eventDiv for later use (e.g., tooltip) eventDiv.dataset.eventContent = details.eventContent; eventDiv.dataset.contactInfo = details.contactInfo; eventDiv.dataset.eventTitle = details.eventTitle; eventDiv.dataset.eventDateTime = details.eventDateTime; eventDiv.dataset.eventLocation = details.eventLocation; // Check if there are education points, recognized hours, or event date/time to display if (details.educationPoints !== 'N/A' || details.recognizedHours !== 'N/A' || details.eventDateTime) { // Create a div to display more information const moreInfoDiv = document.createElement('div'); moreInfoDiv.classList.add('moreinfo'); moreInfoDiv.style.fontSize = '0.8em'; moreInfoDiv.style.color = 'gray'; // Display education points and recognized hours moreInfoDiv.innerHTML = `${details.educationPoints}<br/>時數: ${details.recognizedHours}`; // If event date/time is available, create a Google Calendar link if (details.eventDateTime) { const googleCalendarDate = formatGoogleCalendarDate(details.eventDateTime); if (googleCalendarDate) { const googleCalendarLink = document.createElement('a'); // Construct the details for the calendar event const calendarDetails = `活動內容: ${details.eventContent}\n\n聯絡資訊: ${details.contactInfo}\n\n原始連結: ${url}`; // Create the Google Calendar URL with event details googleCalendarLink.href = `https://calendar.google.com/calendar/render?action=TEMPLATE&text=${encodeURIComponent(details.eventTitle)}&dates=${googleCalendarDate}&details=${encodeURIComponent(calendarDetails)}&location=${encodeURIComponent(details.eventLocation)}`; googleCalendarLink.target = '_blank'; // Open link in a new tab googleCalendarLink.innerText = '📅'; // Calendar emoji as link text googleCalendarLink.style.marginLeft = '5px'; // Add some spacing moreInfoDiv.appendChild(googleCalendarLink); // Append the link to the info div } } // Append the more info div to the event div eventDiv.appendChild(moreInfoDiv); } // Add hover event listeners to the event div for showing/hiding the tooltip eventDiv.addEventListener('mouseover', (event) => { // Get event content and contact info from data attributes const content = event.target.dataset.eventContent || '無活動內容'; const contact = event.target.dataset.contactInfo || '無聯絡資訊'; // Set the tooltip content tooltip.innerHTML = `<strong>活動內容:</strong><br>${content}<br><br><strong>聯絡資訊:</strong><br>${contact}`; // Position the tooltip below the hovered element const rect = event.target.getBoundingClientRect(); tooltip.style.left = `${rect.left + window.scrollX}px`; tooltip.style.top = `${rect.bottom + window.scrollY + 5}px`; // 5px below the element tooltip.style.display = 'block'; // Show the tooltip }); eventDiv.addEventListener('mouseout', () => { tooltip.style.display = 'none'; // Hide the tooltip on mouse out }); } } // Run the script after the page has fully loaded window.addEventListener('load', addEventDetailsToCalendar); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址