I am a beginner on Javascript. I tried to change the travelling time on google map (both on suggested routes and the map) just for fun on my own computer. I use tampermonkey as medium. However, it is not working. Any seniors could hhelp me fix or tell me where is the problem. Thank you so much! I turn @ to ** because i cannot use the @
Here is the code:
// ==User Script==
// **name Google Maps Travel Time Extender
// **namespace tampermonkey's link
// **version 1.2
// **description Extends displayed travel times on Google Maps by a configurable percentage
// **match google map's link
// **grant GM_addStyle
// **grant GM_getValue
// **grant GM_setValue
// **grant GM_registerMenuCommand
// **require jquery's link
// ==/User Script==
(function() {
'use strict';
// Configuration
const DEFAULT_EXTENSION = 150; // 150% increase by default
const POLL_INTERVAL = 1000; // Check for new times every 1 second
// Load or initialize settings
let extensionPercentage = GM_getValue('extensionPercentage', DEFAULT_EXTENSION);
let enabled = GM_getValue('enabled', true);
// Add custom styles
GM_addStyle(`
#tt-extender-panel {
position: fixed;
bottom: 20px;
right: 20px;
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
z-index: 9999;
font-family: Arial, sans-serif;
width: 250px;
}
#tt-extender-panel h3 {
margin-top: 0;
color: #1a73e8;
border-bottom: 1px solid #eee;
padding-bottom: 8px;
}
#tt-extender-toggle {
margin: 10px 0;
display: flex;
align-items: center;
}
#tt-extender-toggle label {
margin-left: 8px;
}
#tt-extender-slider {
width: 100%;
margin: 10px 0;
}
#tt-extender-value {
text-align: center;
font-weight: bold;
margin-bottom: 10px;
}
.original-time {
text-decoration: line-through;
opacity: 0.7;
}
.extended-time {
font-weight: bold;
color: #1a73e8;
}
`);
// Create control panel
function createControlPanel() {
const panel = document.createElement('div');
panel.id = 'tt-extender-panel';
panel.innerHTML = `
<h3>Travel Time Extender</h3>
<div id="tt-extender-toggle">
<input type="checkbox" id="tt-extender-enabled" ${enabled ? 'checked' : ''}>
<label for="tt-extender-enabled">Enabled</label>
</div>
<div id="tt-extender-value">${extensionPercentage}% increase</div>
<input type="range" id="tt-extender-slider" min="0" max="100" value="${extensionPercentage}">
<div style="display: flex; justify-content: space-between;">
<span>0%</span>
<span>100%</span>
</div>
`;
document.body.appendChild(panel);
// Add event listeners
document.getElementById('tt-extender-enabled').addEventListener('change', function() {
enabled = this.checked;
GM_setValue('enabled', enabled);
if (enabled) {
extendAllTimes();
} else {
restoreOriginalTimes();
}
});
document.getElementById('tt-extender-slider').addEventListener('input', function() {
extensionPercentage = parseInt(this.value);
document.getElementById('tt-extender-value').textContent = `${extensionPercentage}% increase`;
GM_setValue('extensionPercentage', extensionPercentage);
if (enabled) {
extendAllTimes();
}
});
}
// Track original times
const originalTimes = new Map();
// Parse time string to minutes
function parseTimeToMinutes(timeStr) {
const hoursMatch = timeStr.match(/(\d+)\s*h/);
const minsMatch = timeStr.match(/(\d+)\s*min/);
let totalMinutes = 0;
if (hoursMatch) totalMinutes += parseInt(hoursMatch[1]) * 60;
if (minsMatch) totalMinutes += parseInt(minsMatch[1]);
return totalMinutes || parseInt(timeStr) || 0;
}
// Format minutes to "Xh Ymin" string
function formatMinutes(minutes) {
const hrs = Math.floor(minutes / 60);
const mins = minutes % 60;
let parts = [];
if (hrs > 0) parts.push(`${hrs}h`);
if (mins > 0 || hrs === 0) parts.push(`${mins}min`);
return parts.join(' ');
}
// Extend a single time element
function extendTimeElement(element) {
if (!element.textContent || element.dataset.extended) return;
const originalText = element.textContent.trim();
const originalMinutes = parseTimeToMinutes(originalText);
if (originalMinutes <= 0) return;
originalTimes.set(element, originalText);
const extendedMinutes = Math.round(originalMinutes * (1 + extensionPercentage / 100));
element.innerHTML = `
<span class="original-time">${originalText}</span>
<span class="extended-time">${formatMinutes(extendedMinutes)}</span>
`;
element.dataset.extended = 'true';
}
// Restore original time for an element
function restoreTimeElement(element) {
if (originalTimes.has(element)) {
element.textContent = originalTimes.get(element);
element.removeAttribute('data-extended');
}
}
// Find and extend all time elements on page
function extendAllTimes() {
if (!enabled) return;
// Main directions panel times
document.querySelectorAll('[aria-label*="hour"], [aria-label*="minute"], [class*="duration-"]').forEach(extendTimeElement);
// Alternative routes times
document.querySelectorAll('[role="option"] [aria-label*="hour"], [role="option"] [aria-label*="minute"]').forEach(extendTimeElement);
// Directions list times
document.querySelectorAll('div[role="list"] [aria-label*="hour"], div[role="list"] [aria-label*="minute"]').forEach(extendTimeElement);
}
// Restore all original times
function restoreOriginalTimes() {
document.querySelectorAll('[data-extended="true"]').forEach(restoreTimeElement);
}
// Main observer function
function observeChanges() {
if (!enabled) return;
// Initial run
extendAllTimes();
// Set up mutation observer
const observer = new MutationObserver(function(mutations) {
if (enabled) {
extendAllTimes();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
// Periodic check as fallback
setInterval(() => {
if (enabled) {
extendAllTimes();
}
}, POLL_INTERVAL);
}
// Add menu commands
GM_registerMenuCommand('Toggle Travel Time Extender', function() {
enabled = !enabled;
GM_setValue('enabled', enabled);
if (enabled) {
extendAllTimes();
} else {
restoreOriginalTimes();
}
alert(`Travel Time Extender ${enabled ? 'enabled' : 'disabled'}`);
});
GM_registerMenuCommand('Set Extension Percentage', function() {
const newValue = prompt('Enter new extension percentage (0-100):', extensionPercentage);
if (newValue !== null && !isNaN(newValue) && newValue >= 0 && newValue <= 100) {
extensionPercentage = parseInt(newValue);
GM_setValue('extensionPercentage', extensionPercentage);
if (enabled) {
extendAllTimes();
}
}
});
// Wait for page to load
window.addEventListener('load', function() {
createControlPanel();
observeChanges();
});
// Also run when navigating (for SPA behavior)
const pushState = history.pushState;
history.pushState = function() {
pushState.apply(history, arguments);
setTimeout(observeChanges, 500);
};
})();