Garmin Connect: sort activity course dropdown

Sort garmin connect activity course dropdown alphabetically

2025-07-13 기준 버전입니다. 최신 버전을 확인하세요.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

You will need to install an extension such as Tampermonkey to install this script.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==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);
})();