Amharic/HaHu Pronunciation Tooltip

Displays a tooltip with a pronunciation button for selected Amharic/HaHu characters on any website.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Amharic/HaHu Pronunciation Tooltip
// @description  Displays a tooltip with a pronunciation button for selected Amharic/HaHu characters on any website.
// @match       *://*/*
// @grant        none
// @version      1.6
// @license      MIT
// @author       @skatbr
// @namespace    https://github.com/skatbr
// ==/UserScript==

const amharicToEnglish = {
    ሀ: "ha",
    ሁ: "hu",
    ሂ: "hee",
    ሃ: "ha",
    ሄ: "hae",
    ህ: "heh",
    ሆ: "ho",
    ለ: "le",
    ሉ: "lu",
    ሊ: "lee",
    ላ: "la",
    ሌ: "lay",
    ል: "leh",
    ሎ: "lo",
    ሐ: "ha",
    ሑ: "hu",
    ሒ: "hee",
    ሓ: "ha",
    ሔ: "hae",
    ሕ: "heh",
    ሖ: "ho",
    መ: "muh",
    ሙ: "moo",
    ሚ: "mee",
    ማ: "ma",
    ሜ: "mae",
    ም: "mih",
    ሞ: "mo",
    ሠ: "seh",
    ሡ: "soo",
    ሢ: "see",
    ሣ: "sa",
    ሤ: "sae",
    ሥ: "sih",
    ሦ: "so",
    ረ: "reh",
    ሩ: "roo",
    ሪ: "ree",
    ራ: "ra",
    ሬ: "rae",
    ር: "rih",
    ሮ: "ro",
    ሰ: "seh",
    ሱ: "soo",
    ሲ: "see",
    ሳ: "sa",
    ሴ: "sae",
    ስ: "sih",
    ሶ: "so",
    ሸ: "sheh",
    ሹ: "shoo",
    ሺ: "shee",
    ሻ: "sha",
    ሼ: "shae",
    ሽ: "shih",
    ሾ: "sho",
    ቀ: "qeh",
    ቁ: "qoo",
    ቂ: "qee",
    ቃ: "qa",
    ቄ: "qae",
    ቅ: "qih",
    ቆ: "qo",
    በ: "beh",
    ቡ: "boo",
    ቢ: "bee",
    ባ: "ba",
    ቤ: "bae",
    ብ: "bih",
    ቦ: "bo",
    ቨ: "veh",
    ቩ: "voo",
    ቪ: "vee",
    ቫ: "va",
    ቬ: "vae",
    ቭ: "vih",
    ቮ: "vo",
    ተ: "teh",
    ቱ: "too",
    ቲ: "tee",
    ታ: "ta",
    ቴ: "tae",
    ት: "tih",
    ቶ: "to",
    ቸ: "cheh",
    ቹ: "choo",
    ቺ: "chee",
    ቻ: "cha",
    ቼ: "chae",
    ች: "chih",
    ቾ: "cho",
    ኀ: "ha",
    ኁ: "hu",
    ኂ: "hee",
    ኃ: "ha",
    ኄ: "hae",
    ኅ: "heh",
    ኆ: "ho",
    ነ: "neh",
    ኑ: "noo",
    ኒ: "nee",
    ና: "na",
    ኔ: "nae",
    ን: "nih",
    ኖ: "no",
    ኘ: "gneh",
    ኙ: "gnoo",
    ኚ: "gnee",
    ኛ: "gna",
    ኜ: "gnae",
    ኝ: "gnih",
    ኞ: "gno",
    አ: "aa",
    ኡ: "oo",
    ኢ: "ee",
    ኣ: "aa",
    ኤ: "ae",
    እ: "ih",
    ኦ: "o",
    ከ: "keh",
    ኩ: "koo",
    ኪ: "kee",
    ካ: "ka",
    ኬ: "kae",
    ክ: "kih",
    ኮ: "ko",
    ኸ: "huh",
    ኹ: "hu",
    ኺ: "hee",
    ኻ: "ha",
    ኼ: "hae",
    ኽ: "heh",
    ኾ: "ho",
    ወ: "weh",
    ዉ: "woo",
    ዊ: "wee",
    ዋ: "wa",
    ዌ: "wae",
    ው: "wih",
    ዎ: "wo",
    ዐ: "aa",
    ዑ: "oo",
    ዒ: "ee",
    ዓ: "aa",
    ዔ: "ae",
    ዕ: "ih",
    ዖ: "o",
    ዘ: "ze",
    ዙ: "zu",
    ዚ: "zee",
    ዛ: "zaa",
    ዜ: "zae",
    ዝ: "zih",
    ዞ: "zo",
    ዠ: "zjeh",
    ዡ: "zjoo",
    ዢ: "zjee",
    ዣ: "zjaa",
    ዤ: "zjae",
    ዥ: "zjih",
    ዦ: "zjo",
    የ: "ye",
    ዩ: "yu",
    ዪ: "yee",
    ያ: "yaa",
    ዬ: "yae",
    ይ: "yih",
    ዮ: "yo",
    ደ: "duh",
    ዱ: "doo",
    ዲ: "dee",
    ዳ: "daa",
    ዴ: "dae",
    ድ: "dih",
    ዶ: "do",
    ጀ: "je",
    ጁ: "joo",
    ጂ: "jee",
    ጃ: "jaa",
    ጄ: "jae",
    ጅ: "jih",
    ጆ: "jo",
    ገ: "guh",
    ጉ: "goo",
    ጊ: "gee",
    ጋ: "ga",
    ጌ: "gae",
    ግ: "gih",
    ጎ: "go",
    ጠ: "tte",
    ጡ: "ttu",
    ጢ: "ttee",
    ጣ: "ttaa",
    ጤ: "ttae",
    ጥ: "ttih",
    ጦ: "tto",
    ጨ: "chhe",
    ጩ: "chhoo",
    ጪ: "chhee",
    ጫ: "chhaa",
    ጬ: "chhae",
    ጭ: "chhih",
    ጮ: "cho",
    ጰ: "ppuh",
    ጱ: "ppoo",
    ጲ: "ppee",
    ጳ: "ppaa",
    ጴ: "ppae",
    ጵ: "ppih",
    ጶ: "ppo",
    ጸ: "tse",
    ጹ: "tsoo",
    ጺ: "tsee",
    ጻ: "tsaa",
    ጼ: "tsae",
    ጽ: "tsih",
    ጾ: "tso",
    ፀ: "tse",
    ፁ: "tsoo",
    ፂ: "tsee",
    ፃ: "tsaa",
    ፄ: "tsae",
    ፅ: "tsih",
    ፆ: "tso",
    ፈ: "fuh",
    ፉ: "foo",
    ፊ: "fee",
    ፋ: "faa",
    ፌ: "fae",
    ፍ: "fih",
    ፎ: "fo",
    ፐ: "peh",
    ፑ: "poo",
    ፒ: "pee",
    ፓ: "paa",
    ፔ: "pae",
    ፕ: "pih",
    ፖ: "po",
};

let button = null;
let tooltip = null;

const createButton = (text) => {
    const btn = document.createElement("button");
    btn.classList.add("mdl-button", "mdl-js-button", "mdl-button--fab", "mdl-js-ripple-effect", "mdl-button--colored");
    btn.innerHTML = `<i class="material-icons">volume_up</i>`;
    return btn;
};

const createTooltip = (text) => {
    const tip = document.createElement("div");
    tip.classList.add("mdl-tooltip");
    tip.setAttribute("data-mdl-for", `amharic-tooltip-button`);
    tip.innerHTML = text;
    tip.style.zIndex = "99999999";
    return tip;
};
let playbackSpeed = 1; // Default playback speed

// Function to create a dropdown menu for selecting playback speed
const createPlaybackSpeedMenu = () => {
    const menu = document.createElement("div");
    menu.classList.add("playback-speed-menu");
    menu.style.cssText = `
        position: fixed !important;
        z-index: 99999999 !important;
        top: ${window.pageYOffset + window.innerHeight - 50}px !important;
        left:${window.pageXOffset + window.innerWidth - 100}px !important;
        background-color:white !important;
        border-radius:5px !important;
        padding:5px !important;
        font-size:12px !important;
        font-weight:bold !important;
        box-shadow :0 0 10px rgba(0,0,0,0.2) !important;
        `;

    const label = document.createElement("span");
    label.classList.add("playback-speed-label");
    label.textContent = `Speed : `;
    menu.appendChild(label);

    const select = document.createElement("select");
    select.classList.add("playback-speed-select");
    const speeds = ["0.5x", "1x", "1.5x", "2x", "2.5x", "3x", "3.5x", "4x", "4.5x", "5x"];
    speeds.forEach((speed) => {
        const option = document.createElement("option");
        option.value = speed;
        option.textContent = speed;
        if (parseFloat(speed) === playbackSpeed) {
            option.selected = true;
        }
        select.appendChild(option);
    });
    select.addEventListener("change", (event) => {
        playbackSpeed = parseFloat(event.target.value);
    });
    menu.appendChild(select);

    return menu;
};

// if not playback-speed-menu found, create one
var playbackSpeedMenu = null;
if (!document.getElementById("playback-speed-menu")) {
    playbackSpeedMenu = createPlaybackSpeedMenu();
    document.body.appendChild(playbackSpeedMenu);
}

let audio = null; // Declare the audio variable outside of the playAudio function

document.addEventListener("click", (event) => {
    const selectedText = window.getSelection().toString().trim();
    const characters = selectedText.split("");

    if (characters.length > 0) {
        let audioIndex = 0;
        const playAudio = () => {
            const englishName = amharicToEnglish[characters[audioIndex]];
            if (!englishName) {
                audioIndex++;
                if (audioIndex < characters.length) {
                    setTimeout(() => {
                        playAudio();
                    }, 0); // delay between each audio clip
                }
                return;
            }

            const audioUrl = `https://s3.amazonaws.com/i.litcdn.com/dict/sounds/mp3/${englishName.toLowerCase()}.mp3`;
            if (audio) {
                audio.pause(); // Stop the previous audio clip
                audio.currentTime = 0; // Reset the current time of the audio clip
            }
            audio = new Audio(audioUrl);
            audio.playbackRate = playbackSpeed; // Set the playback speed
            audio.play();

            audio.addEventListener("ended", () => {
                audioIndex++;
                if (audioIndex < characters.length) {
                    setTimeout(() => {
                        playAudio();
                    }, 0); // delay between each audio clip
                }
            });

            if (button) {
                button.remove();
                tooltip?.remove();
            }

            button = createButton(characters[audioIndex]);
            button.setAttribute("id", `amharic-tooltip-button`);
            const range = window.getSelection().getRangeAt(0);
            const rect = range.getBoundingClientRect();
            button.style.top = `${rect.top + window.pageYOffset - 10}px`;
            button.style.left = `${rect.left + window.pageXOffset + rect.width}px`;

            document.body.appendChild(button);

            button.addEventListener("click", (event) => {
                event.stopPropagation();

                if (tooltip) {
                    tooltip.remove();
                }

                tooltip = createTooltip(englishName);
                const buttonRect = button.getBoundingClientRect();
                tooltip.style.top = `${buttonRect.top + window.pageYOffset + buttonRect.height / 2 - tooltip.offsetHeight / 2}px`;
                tooltip.style.left = `${buttonRect.left + window.pageXOffset + buttonRect.width}px`;

                document.body.appendChild(tooltip);
                componentHandler.upgradeElement(tooltip); // Upgrade the tooltip element to use Material Design
                audio.play();
            });
        };

        playAudio();
    } else {
        if (button) {
            button.style.display = "none";
            tooltip?.remove();
        }
    }
});

document.addEventListener("mousedown", (event) => {
    if (button && !button.contains(event.target)) {
        button.style.display = "none";
        tooltip?.remove();
    }
});