WME Rapid UR Reply

Shortcut keys to answer URs with the F8 key and closes them with the F9 -- also, F8 can approve PURs and lock at L3.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         WME Rapid UR Reply
// @description  Shortcut keys to answer URs with the F8 key and closes them with the F9 -- also, F8 can approve PURs and lock at L3.
// @author       TxAgBQ
// @version      2025120902
// @namespace    <https://greasyfork.org/en/users/820296-txagbq/>
// @icon         <https://www.google.com/s2/favicons?sz=64&domain=waze.com>
// @match        https://*.waze.com/*/editor*
// @match        https://*.waze.com/editor*
// @exclude      https://*.waze.com/user/editor*
// @require      https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
// @grant        none
// ==/UserScript==

/* global W */

(function() {
    'use strict';

    function insertCommentViaShadowDOM(textToInsert) {
        const textareaHosts = document.querySelectorAll('wz-textarea');
        for (const host of textareaHosts) {
            const shadow = host.shadowRoot;
            if (!shadow) continue;

            const textarea = shadow.querySelector('textarea');
            if (!textarea) continue;

            textarea.focus();
            textarea.value = textToInsert;
            textarea.dispatchEvent(new Event('input', { bubbles: true }));
            return true;
        }
        return false;
    }

    function clickSendButton() {
        // New method: Use more specific path to find the send button
        const sendBtnHost = document.querySelector('div.conversation-view form.new-comment-form wz-button.send-button');
        if (sendBtnHost && sendBtnHost.shadowRoot) {
            const actualButton = sendBtnHost.shadowRoot.querySelector('button');
            if (actualButton) {
                actualButton.click();
                return true;
            }
        }
        
        // Alternative: Try within conversation context
        const conversationView = document.querySelector('div.conversation-view');
        if (conversationView) {
            const sendBtn = conversationView.querySelector('form.new-comment-form wz-button.send-button');
            if (sendBtn && sendBtn.shadowRoot) {
                const actualButton = sendBtn.shadowRoot.querySelector('button');
                if (actualButton) {
                    actualButton.click();
                    return true;
                }
            }
        }
        
        // Fallback to old selector in case the UI varies
        const sendBtn = document.querySelector("#panel-container .mapUpdateRequest .body .conversation .new-comment-form .send-button");
        if (sendBtn) {
            sendBtn.click();
            return true;
        }
        
        return false;
    }

    function clickNextButton() {
        console.log('clickNextButton called');
        // Try specific path first
        const nextBtn = document.querySelector('div.footer--d1gls.actions div.navigation div.waze-plain-btn.next');
        if (nextBtn) {
            console.log('Clicking Next button (new selector)');
            nextBtn.click();
            return true;
        }
        
        // Fallback to old jQuery selector only if first method failed
        const $nextBtn = $('#panel-container .mapUpdateRequest .actions .navigation .waze-plain-btn');
        if ($nextBtn.length > 0) {
            console.log('Clicking Next button (old jQuery selector)');
            $nextBtn.click();
            return true;
        }
        
        console.log('No Next button found');
        return false;
    }

    function sendAndNext() {
        // Clicks send
        clickSendButton();

        // Clicks Next (for open URs)
        setTimeout(() => {
            clickNextButton();
        }, 100);
    }

    document.addEventListener('keydown', (event) => {
        if (event.key === 'F8') {
            // Inserts this text
            //let textToInsert = "I got your map issue report.  What issue did you experience? \n\nWould you please tell us your destination EXACTLY as selected in Waze? Click on 'Where to?' then scroll down to see recent destinations.  Include both the bold name and address underneath, with city. If it's spelled out, spell it out. If it's abbreviated, abbreviate it.  How to find your recent destination: <https://www.youtube.com/watch?v=PExNTIQfJI8>  \n\nWe don't receive email replies so please respond in the Waze inbox.";

            // First insert the text (if line is not commented out)
            if (typeof textToInsert !== 'undefined') {
                insertCommentViaShadowDOM(textToInsert);
            }

            // Always send and move to next after a short delay (whether text was inserted or not)
            setTimeout(sendAndNext, 250);

            // Approves PUR then sets to lock level 2
            // Click Add and edit
            setTimeout(() => {
                $('#panel-container .place-update-edit .actions .controls-container label[for="approved-true"]').click();
                // Clicks Next (for open PURs) - Commented out because sendAndNext already clicks Next
                // setTimeout(() => {
                //     clickNextButton();
                // }, 100);
            }, 500);
        }

        if (event.key === 'F9') {
            // Inserts this text
            // Comment to close out report
            let textToInsert = "You asked us to help you with a Map Issue report but you didn't respond back with the info we need to fix your problem, so we'll infer everything is okay and close your request. \n\nIf you were reporting a closure, the quickest way to get closures on the map is to use the Report > Closure feature built into the Waze. <https://support.google.com/waze/answer/13753511> \n\nIf you believe Waze should automatically detect closures on its own, rather than routing you into them, you can vote here <https://waze.uservoice.com/forums/59223-waze-suggestion-box/suggestions/47051794-autodetect-closures-and-closed-roads>";

            if (insertCommentViaShadowDOM(textToInsert)) {
                setTimeout(() => {
                    // Clicks send
                    clickSendButton();

                    // Clicks NI
                    setTimeout(() => {
                        // New method: Use specific path to find the NI label
                        let niClicked = false;
                        const niLabel = document.querySelector('div.footer--d1gls.actions form.controls-container label[for="state-not-identified"]');
                        if (niLabel) {
                            niLabel.click();
                            niClicked = true;
                        }
                        
                        // Fallback to old selector only if not clicked yet
                        if (!niClicked) {
                            const $niLabel = $('#panel-container .mapUpdateRequest .actions .controls-container label[for|="state-not-identified"]');
                            if ($niLabel.length > 0) {
                                $niLabel.click();
                            }
                        }

                        // Clicks Next (for open URs)
                        setTimeout(() => {
                            clickNextButton();
                        }, 100);
                    }, 100);
                }, 250);
            }
        }
    });
})();