您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button to give kudos to all visible activities on Strava and Garmin Connect.
// ==UserScript== // @name Strava and Garmin Kudos All (Working) // @namespace typpi.online // @version 2.2 // @description Adds a button to give kudos to all visible activities on Strava and Garmin Connect. // @author Nick2bad4u // @license Unlicense // @homepageURL https://github.com/Nick2bad4u/UserStyles/ // @grant none // @run-at document-end // @include https://www.strava.com/* // @include https://connect.garmin.com/modern/* // @icon https://i.gyazo.com/e2fabcfc9e9fd6d011e98215764c109c.png // @tag garmin // @tag strava // ==/UserScript== (function () { 'use strict'; // Function to get localized message function getMessage(messageName, substitutions) { const messages = { en: { kudo_all: 'Kudo All' }, es: { kudo_all: 'Dar Kudos a Todos' }, fr: { kudo_all: 'Féliciter Tout le Monde' }, de: { kudo_all: 'Allen Kudos geben' }, it: { kudo_all: 'Dai Kudos a Tutti' }, pt: { kudo_all: 'Dar Kudos a Todos' }, nl: { kudo_all: 'Geef Kudos aan Iedereen' }, ru: { kudo_all: 'Похвалить всех' }, zh: { kudo_all: '赞所有' }, ja: { kudo_all: '全員にKudos' }, ko: { kudo_all: '모두에게 칭찬하기' }, ar: { kudo_all: 'إعطاء Kudos للجميع' }, hi: { kudo_all: 'सभी को कुडोस दें' }, bn: { kudo_all: 'সবাইকে কুডোস দিন' }, ta: { kudo_all: 'அனைவருக்கும் குடோஸ் கொடுக்கவும்' }, kn: { kudo_all: 'ಎಲ್ಲರಿಗೂ ಕುದೋಸ್ ನೀಡಿ' }, mr: { kudo_all: 'सर्वांना कूडो द्या' }, pa: { kudo_all: 'ਸਭ ਨੂੰ ਕੂਡੋ ਦਿਓ' }, ml: { kudo_all: 'എല്ലാവരെയും കുഡോസ് നൽകുക' }, gu: { kudo_all: 'બધાને કૂડોસ આપો' }, ur: { kudo_all: 'سب کو کڈو دیں' }, vi: { kudo_all: 'Kudo Tất cả' }, zh_tw: { kudo_all: '給所有人Kudos' }, af: { kudo_all: 'Gee Kudos aan almal' }, zu: { kudo_all: 'Nike Kudos bonke' }, xh: { kudo_all: 'Nike Kudos bonke' }, he: { kudo_all: 'תן לכולם קודוס' }, id: { kudo_all: 'Berikan Kudos kepada Semua' }, ms: { kudo_all: 'Berikan Kudos kepada Semua' }, sw: { kudo_all: 'Toa Kudos kwa Wote' }, da: { kudo_all: 'Giv Kudos til Alle' }, no: { kudo_all: 'Gi Kudos til Alle' }, sv: { kudo_all: 'Ge Kudos till Alla' }, fi: { kudo_all: 'Anna Kudos kaikille' }, th: { kudo_all: 'ให้คุดดอกทุกคน' }, tr: { kudo_all: 'Herkese Kudos Ver' }, pl: { kudo_all: 'Pochwal wszystkich' }, cs: { kudo_all: 'Pošli Kudos všem' }, sk: { kudo_all: 'Pošli Kudos všetkým' }, hu: { kudo_all: 'Kudos Mindenkinek' }, ro: { kudo_all: 'Felicită pe Toată Lumea' }, hr: { kudo_all: 'Pošalji Kudos svima' }, sr: { kudo_all: 'Пошаљи Кудос свима' }, sl: { kudo_all: 'Pošlji Kudos vsem' }, et: { kudo_all: 'Saada Kudos kõigile' }, lv: { kudo_all: 'Sūtīt Kudos visiem' }, lt: { kudo_all: 'Siųsti Kudos visiems' }, bg: { kudo_all: 'Изпрати Кудос на всички' }, el: { kudo_all: 'Στείλτε Kudos σε όλους' }, uk: { kudo_all: 'Похвалити всіх' }, ka: { kudo_all: 'ყველას Kudos მიეცი' }, az: { kudo_all: 'Bütün Kudos göndər' }, kk: { kudo_all: 'Барлығына Kudos жіберу' }, tg: { kudo_all: 'Ба ҳама Kudos фиристед' }, tk: { kudo_all: 'Hemme Kudos iber' }, ky: { kudo_all: 'Бардыгына Kudos жөнөтүү' }, mn: { kudo_all: 'Бүгдэд Kudos илгээх' }, ne: { kudo_all: 'सबैलाई कूडोस दिनुहोस्' }, ku: { kudo_all: 'Herkese Kudos Bide' }, am: { kudo_all: 'ለሁሉም Kudos ይስጡ' }, ps: { kudo_all: 'ټولو ته Kudos ورکړئ' }, }; const userLanguage = (navigator.language || navigator.userLanguage || 'en').split('-')[0]; // Get the user's language const messageSet = messages[userLanguage] || messages['en']; // Default to English if language not supported return messageSet[messageName] || (typeof substitutions === 'string' ? substitutions : '') || messageName; } const Strava = { getStravaContainer, // Retrieves the Strava container element findStravaKudosButtons, // Finds Strava kudos buttons within a specified container or the entire document createStravaFilter, // Creates a filter function for Strava activities based on an athlete's link getStravaKudosButtons, // Retrieves Strava kudos buttons based on athlete link and activity filtering createStravaButton, // Creates a Strava button element with a specified label stravaKudoAllHandler, // Handles the event to click all Strava kudos buttons on the page stravaStandBy, // Initiates the Strava standby mode }; /** * Retrieves the Strava container element. * * @returns {HTMLElement | null} The Strava container element, or null if not found. */ function getStravaContainer() { const container = document.querySelector('[class="user-nav nav-group"]'); console.log('Strava: Found container:', container); return container; } /** * Finds Strava kudos buttons within a specified container or the entire document. * These buttons are identified by their data-testid attributes for 'kudos_button' and 'unfilled_kudos'. * * @param {HTMLElement} [container] - The HTML element to search within. If not provided, the entire document is searched. * @returns {HTMLElement[]} An array of HTML elements representing the Strava kudos buttons found. */ function findStravaKudosButtons(container) { // Find Strava kudos buttons const kudosButtonSelector = "button[data-testid='kudos_button']"; // Define the selector for the kudos button const unfilledKudosSelector = "svg[data-testid='unfilled_kudos']"; // Define the selector for the unfilled kudos icon const selector = `${kudosButtonSelector} > ${unfilledKudosSelector}`; // Combine the selectors const buttons = container ? Array.from(container.querySelectorAll(selector)) : document.querySelectorAll(selector); // Find the kudos buttons console.log('Strava: Found kudos buttons:', buttons); // Log the found kudos buttons return buttons; // Return the found kudos buttons } /** * Creates a filter function for Strava activities based on an athlete's link. * The filter function checks if an activity item contains a link to the specified athlete. * It utilizes caching to improve performance by storing the filter function and athlete link. * * @param {HTMLAnchorElement} athleteLink - The anchor element representing the athlete's link. * @returns {function(HTMLElement): boolean} A filter function that returns true if the activity item does NOT contain a link to the specified athlete, false otherwise. */ let cachedAthleteLink = null; // Cache the athlete link let cachedFilterFunction = null; // Cache the filter function function createStravaFilter(athleteLink) { // Create a filter function for Strava activities if (!athleteLink) { console.error('Strava: Athlete link is null or undefined.'); return () => false; // Return a default filter function } const url = new URL(athleteLink.href); // Get the athlete link URL const href = url.pathname; // Get the pathname from the URL if (cachedAthleteLink === href) { // Check if the filter is already cached console.log('Strava: Using cached filter for athlete link:', href); // Log the cached filter return cachedFilterFunction; // Return the cached filter function } console.log('Strava: Filter created for athlete link:', href); // Log the new filter cachedAthleteLink = href; // Cache the athlete link cachedFilterFunction = (item) => !item.querySelector(`a[href^="${href}"]`); // Create the filter function return cachedFilterFunction; // Return the filter function } /** * Finds the athlete link on the page. It first attempts to find the link in the athlete profile section. * If not found, it falls back to searching for any link that starts with '/athletes'. * As a last resort, it searches for any link that contains '/athletes'. * * @returns {HTMLAnchorElement | null} The athlete link element if found, otherwise null. */ function findAthleteLink() { // Find the athlete link // Attempt to find the athlete link in the profile or fallback locations let athleteLink = document.querySelector("#athlete-profile a[href^='/athletes']"); // Find the athlete link in the profile if (!athleteLink) { // If the athlete link is not found athleteLink = document.querySelector("a[href^='/athletes']"); // Find the athlete link in the feed console.log('Strava: Fallback athlete link:', athleteLink); // Log the fallback athlete link if (!athleteLink) { // If the fallback athlete link is not found athleteLink = document.querySelector("a[href*='/athletes']"); // Find the second fallback athlete link console.log('Strava: Second fallback athlete link:', athleteLink); // Log the second fallback athlete link } } console.log('Strava: Athlete link:', athleteLink); // Log the athlete link return athleteLink; // Return the athlete link } /** * Finds Strava activities based on the presence of athlete links within feed entries. * * @returns {NodeListOf<HTMLAnchorElement>} A NodeList of anchor elements representing activities. */ function findActivities() { // Find activities based on the athlete link let activities = document.querySelectorAll("div[data-testid='web-feed-entry'] > div > div > div > a[href^='/athletes']"); // Find activities based on the athlete link console.log('Strava: Found activities:', activities); // Log the found activities return activities; // Return the found activities } /** * Filters an array of activities based on a given athlete link. * * @param {string} athleteLink - The athlete link to filter activities by. * @param {HTMLElement[]} activities - An array of activity elements to filter. * @returns {HTMLElement[]} - A new array containing only the activities that match the athlete link. */ function filterActivities(athleteLink, activities) { // Filter activities based on athlete link activities = Array.from(activities).filter(createStravaFilter(athleteLink)); // Filter activities based on the athlete link console.log('Strava: Filtered activities:', activities); // Log the filtered activities return activities; // Return the filtered activities } /** * Collects kudos buttons from a list of activities. * It flattens the array of activities and finds Strava kudos buttons in each activity. * * @param {HTMLElement[]} activities - An array of HTML elements representing activities. * @returns {HTMLButtonElement[]} - An array of HTML button elements representing the kudos buttons found in the activities. */ function collectKudosButtons(activities) { // Collect kudos buttons from the filtered activities const buttons = activities.flatMap((activity) => findStravaKudosButtons(activity)); // Collect kudos buttons from the filtered activities console.log('Strava: Final kudos buttons:', buttons); // Log the final kudos buttons return buttons; // Return the final kudos buttons } /** * Retrieves Strava kudos buttons based on athlete link and activity filtering. * It attempts to find kudos buttons associated with activities of a specific athlete. * If athlete link or activities are not found, or if no activities remain after filtering, * it falls back to the default method of finding Strava kudos buttons. * * @returns {NodeListOf<HTMLButtonElement> | undefined} A collection of kudos buttons, * or undefined if no buttons are found. */ function getStravaKudosButtons() { const athleteLink = findAthleteLink(); // Find the athlete link // If athlete link is still not found, use the default kudos button finding method if (!athleteLink) { return findStravaKudosButtons(document); // Use the default kudos button finding method } const activities = findActivities(); // Find activities based on the athlete link // If no activities found, use the default kudos button finding method if (activities.length < 1) { return findStravaKudosButtons(); // Use the default kudos button finding method } const filteredActivities = filterActivities(athleteLink, activities); // Filter activities based on the athlete link // If no activities left after filtering, use the default kudos button finding method if (filteredActivities.length < 1) { return findStravaKudosButtons(); // Use the default kudos button finding method } return collectKudosButtons(filteredActivities); // Collect kudos buttons from the filtered activities } /** * Creates a Strava button element with a specified label. * * @returns {HTMLLIElement} The created Strava button as an `li` element. */ function createStravaButton() { const label = getMessage('kudo_all', 'Kudo All'); // Get the localized message for the button label console.log('Strava: Creating button with label:', label); // Log the button label const navItemLi = document.createElement('li'); // Create the button element const navItemA = document.createElement('a'); // Create the button link element navItemLi.className = 'nav-item'; // Set the button class navItemLi.style.marginRight = '10px'; // Set the button margin navItemA.href = '#'; // Set the button link href navItemA.className = 'btn btn-default btn-sm empty'; // Set the button link class const navItemIcon = document.createElement('span'); // Create the button icon element navItemIcon.className = 'app-icon icon-kudo'; // Set the button icon class navItemIcon.style.marginRight = '5px'; // Set the button icon margin const navItemText = document.createElement('span'); // Create the button text element navItemText.className = 'ka-progress text-caption1'; // Set the button text class navItemText.textContent = label; navItemA.append(navItemIcon); // Append the icon to the button link navItemA.append(navItemText); // Append the text to the button link navItemLi.append(navItemA); // Append the link to the button // Add hover effect navItemA.addEventListener('mouseover', () => { navItemA.style.backgroundColor = '#2ea44f'; // Change background color on hover navItemA.style.color = 'white'; // Change text color on hover navItemA.style.transform = 'scale(1.1)'; // Slightly enlarge the button on hover navItemA.style.transition = 'all 0.3s ease'; // Smooth transition for the effects navItemA.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)'; // Add a shadow effect }); navItemA.addEventListener('mouseout', () => { navItemA.style.backgroundColor = ''; // Reset background color navItemA.style.color = ''; // Reset text color navItemA.style.transform = 'scale(1)'; // Reset size navItemA.style.boxShadow = ''; // Remove shadow }); // Add click effect navItemA.addEventListener('click', () => { navItemA.style.transform = 'scale(0.95)'; // Shrink the button slightly on click navItemA.style.opacity = '0.9'; // Slightly fade the button on click setTimeout(() => { navItemA.style.transform = 'scale(1)'; // Reset size after click effect navItemA.style.opacity = '1'; // Reset opacity after click effect }, 150); // Duration of the click effect }); return navItemLi; // Return the button element } /** * Handles the event to click all Strava kudos buttons on the page. * * @param {Event} event - The event that triggered the handler (e.g., a button click). * @returns {void} */ function stravaKudoAllHandler(event) { // Handle the event to click all kudos buttons event.preventDefault(); // Prevent the default event behavior const icons = getStravaKudosButtons(); // Get the Strava kudos buttons console.log('Strava: Clicking all kudos buttons, count:', icons.length); // Log the number of kudos buttons let likedCount = 0; // Counter for the number of items liked icons.forEach((item) => { // Click all kudos buttons const parentItem = item?.parentElement; // Get the parent element of the kudos button if (parentItem) { // If the parent element exists parentItem.click(); // Click the parent element likedCount++; // Increment the counter } }); // Show a popup with the number of items liked showPopup(`You gave kudos 👍 to ${likedCount} activities!`); } /** * Initiates the Strava standby mode, which checks for the existence of a Kudo All button. * If the button does not exist, it creates and prepends the button to the Strava container. * The button is then attached with a click event listener to the stravaKudoAllHandler function. */ function stravaStandBy() { // Initiate the Strava standby mode console.log('Strava: Standby initiated'); // Log the initiation of the standby mode const buttonExisted = document.querySelector('div[class="ka-progress text-caption1"]'); // Check if the button already exists if (!buttonExisted) { // If the button does not exist console.log('Strava: Button does not exist, creating'); // Log the creation of the button const container = getStravaContainer(); // Get the Strava container if (container) { // If the container exists const button = createStravaButton(); // Create the button container.prepend(button); // Prepend the button to the container button.addEventListener('click', stravaKudoAllHandler); // Add a click event listener to the button } } } /** * @namespace GC * @description Namespace containing functions related to Garmin Connect integration. * @property {function} getGarminContainer - Retrieves the Garmin container element. * @property {function} findGarminKudosButtons - Finds Garmin kudos buttons within a specified container or the entire document. * @property {function} createGarminButton - Creates a new kudos button for Garmin. * @property {function} garminKudoAllHandler - Handles the "kudo all" action on Garmin. * @property {function} executeGarmin - Executes the Garmin integration logic. * @property {function} garminConnectStandBy - Sets up a standby observer for Garmin Connect. */ const GC = { getGarminContainer, // Retrieves the Garmin container element findGarminKudosButtons, // Finds Garmin kudos buttons within a specified container or the entire document createGarminButton, // Creates a new kudos button for Garmin garminKudoAllHandler, // Handles the "kudo all" action on Garmin executeGarmin, // Executes the Garmin integration logic garminConnectStandBy, // Sets up a standby observer for Garmin Connect }; /** * Retrieves the Garmin container element where the Kudo All button will be prepended. * It searches for a div with the class "header-nav", creates a new div element with specific classes and styles, * prepends it to the found container, and returns the newly created div element. * * @returns {HTMLElement|null} The newly created Kudo All navigation item element, or null if the container is not found. */ function getGarminContainer() { // Get the Garmin container const container = document.querySelector('div[class="header-nav"]'); // Find the Garmin container console.log('Garmin: Found container:', container); // Log the found container if (container) { const el = document.createElement('div'); // Create the new div element el.classList.add('kudo-all-nav-item', 'header-nav-item'); // Add classes to the new div element el.style.height = '60px'; // Set the height of the new div element el.style.width = '50px'; // Set the width of the new div element container.prepend(el); // Prepend the new div element to the container return document.querySelector('div[class^=kudo-all-nav-item]'); // Return the new div element } return null; // Return null if the container is not found } /** * Finds Garmin kudos buttons within a specified container or the entire document. * * @param {HTMLElement} [container] - The container element to search within. If not provided, the entire document is searched. * @returns {HTMLElement[]} An array of HTMLElement objects representing the Garmin kudos buttons found. */ function findGarminKudosButtons(container) { // Find Garmin kudos buttons const selector = ` button[class^="CommentLikeSection_socialIconWrapper"] > div[class*="CommentLikeSection_animateBox"] > i[class*=icon-heart-inverted] `; // Define the selector for the kudos buttons const buttons = container ? Array.from(container.querySelectorAll(selector)) : Array.from(document.querySelectorAll(selector)); // Find the kudos buttons console.log('Garmin: Found kudos buttons:', buttons); // Log the found kudos buttons return buttons; // Return the found kudos buttons } /** * Creates a Garmin-style button element. * * @returns {HTMLAnchorElement} The created Garmin-style button element. */ function createGarminButton() { // Create a Garmin-style button const label = getMessage('kudo_all', 'Kudo All'); // Get the localized message for the button label console.log('Garmin: Creating button with label:', label); // Log the button label const link = document.createElement('a'); // Create the button element link.href = '#'; // Set the button link href link.className = 'header-nav-link icon-heart-inverted'; // Set the button link class link.setAttribute('aria-label', label); // Set the button link aria-label link.setAttribute('data-original-title', label); // Set the button link data-original-title link.setAttribute('data-rel', 'tooltip'); // Set the button link data-rel // Add hover effect to fill the heart red link.addEventListener('mouseover', () => { link.style.color = 'red'; // Change the heart color to red on hover link.style.transform = 'scale(1.2)'; // Slightly enlarge the heart on hover link.style.transition = 'all 0.3s ease'; // Smooth transition for the effects link.style.boxShadow = '0 4px 8px rgba(255, 0, 0, 0.5)'; // Add a glowing red shadow }); link.addEventListener('mouseout', () => { link.style.color = ''; // Reset the heart color when not hovering link.style.transform = 'scale(1)'; // Reset the size when not hovering link.style.boxShadow = ''; // Remove the shadow when not hovering }); // Add click effect to briefly shrink the heart link.addEventListener('click', () => { link.style.transform = 'scale(0.9)'; // Shrink the heart slightly on click link.style.opacity = '0.8'; // Slightly fade the heart on click setTimeout(() => { link.style.transform = 'scale(1)'; // Reset the size after the click effect link.style.opacity = '1'; // Reset the opacity after the click effect }, 150); // Duration of the click effect }); // Add a pulsating animation effect const pulsateKeyframes = ` @keyframes pulsate { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } `; const styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerText = pulsateKeyframes; document.head.appendChild(styleSheet); link.addEventListener('mouseenter', () => { link.style.animation = 'pulsate 1s infinite'; // Start pulsating on hover }); link.addEventListener('mouseleave', () => { link.style.animation = ''; // Stop pulsating when not hovering }); return link; } /** * Handles the event to give all kudos on the Garmin newsfeed page. * Prevents default event behavior, checks if the current page is the newsfeed, * finds all kudos buttons, and clicks them. * * @param {Event} event - The event that triggered the handler. * @returns {void} */ function garminKudoAllHandler(event) { // Handle the event to give all kudos event.preventDefault(); // Prevent the default event behavior if (window.location.pathname !== '/modern/newsfeed') { // Check if the current page is the newsfeed console.log('Garmin: Not on the newsfeed page, redirecting'); // Log the redirect message window.location.href = 'https://connect.garmin.com/modern/newsfeed'; // Redirect to the newsfeed page return; // Abort the function } const icons = findGarminKudosButtons(); // Find all kudos buttons console.log('Garmin: Clicking all kudos buttons, count:', icons.length); // Log the number of kudos buttons let likedCount = 0; // Counter for the number of items liked icons.forEach((item) => { // Click all kudos buttons if (item) { item.click(); // Click the kudos button likedCount++; // Increment the counter } }); // Show a popup with the number of items liked showPopup(`You gave hearts ❤️ to ${likedCount} activities!`); } /** * Executes the Garmin functionality by injecting a "Kudo All" button into the Garmin page. * It first retrieves the container element where the button will be appended. * If the container is found, it creates the button, appends it to the container, * and attaches a click event listener to the button that triggers the garminKudoAllHandler function. */ function executeGarmin() { // Execute the Garmin functionality console.log('Garmin: Execute function called'); // Log the execution of the function const container = getGarminContainer(); // Get the Garmin container if (container) { // If the container exists const button = createGarminButton(); // Create the button container.append(button); // Append the button to the container button.addEventListener('click', garminKudoAllHandler); // Add a click event listener to the button } } /** * @function garminConnectStandBy * @description Initiates a standby mode for Garmin Connect, observing the DOM for the appearance of a specific element (`header-nav`) to trigger the execution of `executeGarmin`. * @listens MutationObserver * @returns {void} */ function garminConnectStandBy() { // Initiate the Garmin standby mode console.log('Garmin: Standby initiated'); // Log the initiation of the standby mode let loaded = false; // Set the loaded flag to false var observer = new MutationObserver(function (mutations) { // Create a new mutation observer mutations.forEach(function (mutation) { // For each mutation if (mutation.addedNodes.length > 0) { // If nodes are added mutation.addedNodes.forEach((node) => { if ( // If the target element is loaded !loaded && // Ensure it's not already loaded node.nodeType === 1 && // Ensure it's an element node.className && // Ensure it has a class name typeof node.className === 'string' && // Ensure the class name is a string node.className.startsWith('header-nav') // Ensure the class name starts with 'header-nav' ) { console.log('Garmin: Target element loaded, executing...'); // Log the execution of the function loaded = true; // Set the loaded flag to true executeGarmin(); // Execute the Garmin functionality observer.disconnect(); // Disconnect the observer } }); } }); }); if (!loaded) { observer.observe(document.body, { // Observe the body for mutations childList: true, // Observe child nodes subtree: true, // Observe all descendants }); } } // Check if the current host is Strava /** * Checks if the current hostname matches a Strava domain pattern. * * @returns {boolean} True if the hostname is a Strava domain, false otherwise. */ function isHostStrava() { // Check if the current host is Strava const currentHostname = window.location.hostname; // Get the current hostname const stravaDomainPattern = /^.*\.strava\.com$/; // Define the Strava domain pattern const isStrava = stravaDomainPattern.test(currentHostname); // Check if the current hostname matches the Strava domain pattern console.log('Host check: Is Strava?', isStrava); // Log the result of the check return isStrava; // Return the result of the check } // Check if the current host is Garmin /** * Checks if the current hostname matches a Garmin domain pattern. * * @returns {boolean} True if the hostname is a Garmin domain, false otherwise. */ function isHostGarmin() { // Check if the current host is Garmin Connect const currentHostname = window.location.hostname; // Get the current hostname const garminDomainPattern = /^.*\.garmin\.com$/; // Define the Garmin domain pattern const isGarmin = garminDomainPattern.test(currentHostname); // Check if the current hostname matches the Garmin domain pattern 444444444444444442 console.log('Host check: Is Garmin?', isGarmin); // Log the result of the check return isGarmin; // Return the result of the check } // Initialize script on window load window.onload = function () { console.log('Kudo All script initialization started.'); /** * Checks if the current host is Strava. * * @returns {boolean} True if the current host is Strava, false otherwise. */ const isStravaHost = isHostStrava(); // Check if the current host is Strava const isGarminHost = isHostGarmin(); // Check if the current host is Garmin Connect if (isStravaHost) { // If the current host is Strava console.log('Detected Strava domain. Initiating Strava standby...'); // Log the initiation of the Strava standby mode Strava.stravaStandBy(); // Initiate the Strava standby mode } else if (isGarminHost) { // If the current host is Garmin Connect console.log('Detected Garmin domain. Initiating Garmin standby...'); // Log the initiation of the Garmin standby mode GC.garminConnectStandBy(); // Initiate the Garmin standby mode } else { // If the current host is not recognized as Strava or Garmin console.log('Domain not recognized as Strava or Garmin. No actions will be performed.'); // Log the unrecognized domain } }; /** * Displays a popup message on the page. * * @param {string} message - The message to be displayed in the popup. */ function showPopup(message) { // Create a popup element const popup = document.createElement('div'); // Set the popup message popup.textContent = message; // Set the popup styles popup.style = ` position: fixed; top: 20px; right: 20px; background-color: #2ea44f; color: white; padding: 10px 20px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); z-index: 1000; font-size: 16px; `; // Append the popup to the body document.body.appendChild(popup); // Automatically remove the popup after 3 seconds setTimeout(() => { popup.remove(); }, 3000); } })();