Convert Ascent and Descent to Feet

Converts ascent and descent values from meters to feet on the for Strava Sauce users.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Convert Ascent and Descent to Feet
// @namespace   typpi.online
// @version     1.1
// @description Converts ascent and descent values from meters to feet on the for Strava Sauce users.
// @author      Nick2bad4u
// @license     UnLicense
// @match       https://www.strava.com/activities/*
// @resource    https://www.google.com/s2/favicons?sz=64&domain=strava.com
// @icon        https://www.google.com/s2/favicons?sz=64&domain=strava.com
// @icon64      https://www.google.com/s2/favicons?sz=64&domain=strava.com
// @grant       none
// @run-at      document-end
// ==/UserScript==

(function () {
	'use strict';

	// Function to convert meters to feet
	const metersToFeet = (meters) => {
		// Return converted value or 0 if invalid
		if (isNaN(meters) || meters === null || meters === '') {
			return 0; // Return 0 if value is invalid
		}
		return (meters * 3.28084).toFixed(2);
	};

	// Function to update the values in feet and insert them into the correct grid
	const updateValues = () => {
		console.log('updateValues called');

		// Select the elements using the given selectors
		const ascentElement = document.querySelector(
			'body > div.fancybox-overlay.fancybox-overlay-fixed > div > div > div > div > div > div:nth-child(17) > div.grid > table > tbody > tr:nth-child(1) > td:nth-child(2) > span',
		);
		const descentElement = document.querySelector(
			'body > div.fancybox-overlay.fancybox-overlay-fixed > div > div > div > div > div > div:nth-child(17) > div.grid > table > tbody > tr:nth-child(1) > td:nth-child(3) > span',
		);

		// Check if the elements exist on the page
		if (ascentElement && descentElement) {
			console.log('Ascent and descent elements found:', ascentElement, descentElement);

			// Extract the numeric values and convert them to feet
			const ascentValueInMeters = parseFloat(ascentElement.textContent.trim());
			const descentValueInMeters = parseFloat(descentElement.textContent.trim());

			// Convert ascent value and check if valid
			const ascentValueInFeet = metersToFeet(ascentValueInMeters);
			if (ascentValueInFeet !== 0) {
				console.log('Converted ascent value (feet):', ascentValueInFeet);
				ascentElement.innerHTML = `${ascentValueInFeet} <span class="gridUnits">ft</span><br><span class="gridTitle">Ascent</span>`;
			} else {
				console.log('Invalid Ascent value detected:', ascentValueInMeters);
			}

			// Convert descent value and check if valid
			const descentValueInFeet = metersToFeet(descentValueInMeters);
			if (descentValueInFeet !== 0) {
				console.log('Converted descent value (feet):', descentValueInFeet);
				descentElement.innerHTML = `${descentValueInFeet} <span class="gridUnits">ft</span><br><span class="gridTitle">Descent</span>`;
			} else {
				console.log('Invalid Descent value detected:', descentValueInMeters);
			}

			// Add the ascent and descent data to the same row in the grid
			const grid = document.querySelector(
				'#heading > div > div.row.no-margins.activity-summary-container > div.spans8.activity-stats.mt-md.mb-md > div.summaryGrid > table > tbody',
			);
			console.log('Adding ascent and descent values to the grid:', grid);

			const newRow = document.createElement('tr');
			newRow.innerHTML = `
                <td data-column="0" data-row="8">
                    <span class="summaryGridDataContainer" onclick="javascript:window.open(&quot;chrome-extension:/dhiaggccakkgdfcadnklkbljcgicpckn/app/index.html#/globalSettings?viewOptionHelperId=displayAdvancedPowerData&quot;,&quot;_blank&quot;);">
                        ${ascentValueInFeet} <span class="summaryGridUnits">ft</span><br><span class="summaryGridTitle">Ascent</span>
                    </span>
                </td>
                <td data-column="1" data-row="8">
                    <span class="summaryGridDataContainer" onclick="javascript:window.open(&quot;chrome-extension:/dhiaggccakkgdfcadnklkbljcgicpckn/app/index.html#/globalSettings?viewOptionHelperId=displayAdvancedPowerData&quot;,&quot;_blank&quot;);">
                        ${descentValueInFeet} <span class="summaryGridUnits">ft</span><br><span class="summaryGridTitle">Descent</span>
                    </span>
                </td>
            `;
			grid.appendChild(newRow);
			console.log('Ascent and Descent values added to grid:', newRow);

			// Disconnect the observer after updating the values
			observer.disconnect();
			console.log('Observer disconnected after values are updated');
		} else {
			console.log('Ascent or descent elements not found');
		}
	};

	// Debounce function to limit the frequency of function calls
	function debounce(func, wait) {
		let timeout;
		return function (...args) {
			clearTimeout(timeout);
			timeout = setTimeout(() => func.apply(this, args), wait);
		};
	}

	// Create a MutationObserver to watch for changes in the DOM
	const observer = new MutationObserver(() => {
		console.log('Mutation observed');
		// Run the update function when the elements are added to the DOM
		updateValuesDebounced();
	});

	// Wrap the updateValues function with debounce
	const updateValuesDebounced = debounce(updateValues, 1000); // Adjust the delay as needed

	// Observe changes to the document body
	observer.observe(document.body, {
		childList: true,
		subtree: true,
	});
	console.log('Observer is now watching for changes');
})();