Sort garmin connect activity course dropdown alphabetically
当前为
// ==UserScript==
// @name Garmin Connect: sort activity course dropdown
// @namespace http://tampermonkey.net/
// @description Sort garmin connect activity course dropdown alphabetically
// @author You
// @match https://connect.garmin.com/modern/activity/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=garmin.com
// @grant none
// @license MIT
// @version 0.1-2025-06-02
// ==/UserScript==
(function() {
'use strict';
// Your code here...
function sortList(ul) {
let new_ul = ul.cloneNode(false);
let lis = [];
for (let i = ul.childNodes.length; i--;) {
if (ul.childNodes[i].nodeName === 'LI') {
lis.push(ul.childNodes[i]);
}
}
lis.sort(function (a, b) {
let aText = a.childNodes[0].textContent;
let bText = b.childNodes[0].textContent;
if (a.getAttribute("data-value") == -1) {
return -1;
}
if (b.getAttribute("data-value") == -1) {
return 1;
}
// sorts case-insensitively and handles numbers correctly (e.g. "7" < "10")
return aText.localeCompare(bText, undefined, {
numeric: true,
sensitivity: 'base'
});
});
for (let i = 0; i < lis.length; i++) {
new_ul.appendChild(lis[i]);
}
ul.parentNode.replaceChild(new_ul, ul);
}
var dropdownParent = "#course-dropdown + div.dropdown + div.dropdown";
// don't know of way to be sure that the drop-down was fully populated,
// so we sort on every click
function installHandler(elem) {
var dropdown = dropdownParent + " ul[role=menu]";
elem.addEventListener('click', function(e) {
sortList(elem.querySelector("ul[role=menu]"));
});
}
function runWhenReady(readySelector, callback) {
var numAttempts = 0;
var tryNow = function() {
var elem = document.querySelector(readySelector);
if (elem) {
callback(elem);
} else {
numAttempts++;
if (numAttempts >= 34) {
console.warn('Giving up after 34 attempts. Could not find: ' + readySelector);
} else {
setTimeout(tryNow, 250 * Math.pow(1.1, numAttempts));
}
}
};
tryNow();
}
runWhenReady(dropdownParent, installHandler);
})();