您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add RPPs with incrementing HNs.
// ==UserScript== // @name WME Quick RPP // @namespace https://github.com/WazeDev/wme-quick-rpp // @version 0.0.2 // @description Add RPPs with incrementing HNs. // @author Gavin Canon-Phratsachack (https://github.com/gncnpk) // @match https://beta.waze.com/*editor* // @match https://www.waze.com/*editor* // @exclude https://www.waze.com/*user/*editor/* // @exclude https://www.waze.com/discuss/* // @icon https://www.google.com/s2/favicons?sz=64&domain=waze.com // @grant none // @license MIT // @contributionURL https://github.com/WazeDev/Thank-The-Authors // ==/UserScript== (function() { 'use strict'; // Shortcut storage configuration const STORAGE_KEY = 'WME_QuickRPP_Shortcuts'; // Modifier key mappings for WME shortcuts const KeyModifiers = { 1: "C", // Ctrl 2: "S", // Shift 3: "CS", // Ctrl+Shift 4: "A", // Alt 5: "AC", // Alt+Ctrl 6: "AS", // Alt+Shift 7: "ACS" // Alt+Ctrl+Shift }; // Default shortcut definitions const defaultDefs = [ { shortcutId: 'wme-quick-rpp-create', description: 'Create RPP with Incremented HN', callback: duplicateRPP, shortcutKeys: null }, { shortcutId: 'wme-quick-rpp-toggle-bulk-add', description: 'Toggle Bulk Creation', callback: toggleBulkAdd, shortcutKeys: null } ]; let sdk; let increment = localStorage.getItem("WQR_HN_INCREMENT") || 0; let lockLevel = localStorage.getItem("WQR_LOCK_LEVEL") || 1; let NewRPPHNElement; let toggleBulkAddElement; let isBulkAdd; if (localStorage.getItem("WQR_BULK_ADD_ENABLED") === 'true') { isBulkAdd = true; } else { isBulkAdd = false; } window.SDK_INITIALIZED.then(init); /** * Convert WME-style "modMask,keyCode" string to human-readable form * @param {string|null} shortcutKeys - WME format like "2,85" or null * @returns {string|null} - Human readable like "S+85" or null */ function convertShortcutKeys(shortcutKeys) { // Handle null input if (shortcutKeys == null) { return null; } // If not "number,number" format, assume already human-readable if (!/^\d+,\d+$/.test(shortcutKeys)) { return shortcutKeys; } // Parse and convert WME format to human-readable const [maskStr, keyCode] = shortcutKeys.split(","); const mask = parseInt(maskStr, 10); const modString = KeyModifiers[mask] || ""; return modString ? `${modString}+${keyCode}` : keyCode; } function loadStoredShortcuts() { let storedList = [] try { storedList = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]') } catch (e) { console.warn('WME Quick RPP: Could not parse stored shortcuts, resetting to defaults') storedList = [] } return storedList; } function storeShortcuts() { console.log("WME Quick RPP: Storing shortcuts..."); // Get IDs of shortcuts managed by this script const ours = new Set(defaultDefs.map(d => d.shortcutId)) // Filter and format shortcuts for storage const toStore = sdk.Shortcuts .getAllShortcuts() .filter(s => ours.has(s.shortcutId)) .map(s => ({ shortcutId: s.shortcutId, description: s.description, shortcutKeys: s.shortcutKeys })) // Save to localStorage localStorage.setItem(STORAGE_KEY, JSON.stringify(toStore)) } function init() { sdk = window.getWmeSdk({ scriptId: 'wme-quick-rpp', scriptName: 'WME Quick RPP' }); // Load stored shortcuts and register them const existingIds = sdk.Shortcuts .getAllShortcuts() .map(s => s.shortcutId); let storedList = loadStoredShortcuts(); if (storedList.length) { console.log('WME Quick RPP: Importing stored shortcuts'); for (const st of storedList) { const def = defaultDefs.find(d => d.shortcutId === st.shortcutId); if (!def) { console.warn(`WME Quick RPP: Unknown shortcutId ${st.shortcutId}`); continue; } const toCreate = { shortcutId: def.shortcutId, description: def.description, callback: def.callback, shortcutKeys: convertShortcutKeys(st.shortcutKeys) }; if (!existingIds.includes(def.shortcutId)) { sdk.Shortcuts.createShortcut(toCreate); } } } else { console.log('WME Quick RPP: No stored shortcuts, registering defaults'); for (const def of defaultDefs) { if (!existingIds.includes(def.shortcutId)) { sdk.Shortcuts.createShortcut(def); } } } // Set up automatic storage when shortcuts are edited sdk.Events.on({ eventName: 'wme-after-edit', eventHandler: storeShortcuts }); sdk.Sidebar.registerScriptTab().then(async (res) => { res.tabLabel.innerText = "Quick RPP"; res.tabPane.innerHTML = ` <div> <label for="WQRLockLevel">Lock Level</label> <input type="number" id="WQRLockLevel" value="${lockLevel}" style="width: 100%;" min="1" max="6" /> </div> <div> <label for="WQRHNIncrement">HN Increment</label> <input type="number" id="WQRHNIncrement" value="${increment}" style="width: 100%;" /> </div> <div> <label for="WQRToggleBulkAdd">Toggle Bulk Creation</label> <input type="checkbox" id="WQRToggleBulkAdd" value="${isBulkAdd}" /> </div> <div id="NewRPPHouseNumber" style="margin-top:8px;font-weight:bold;">New RPP HN: </div> `; res.tabPane.querySelector("#WQRLockLevel").addEventListener("input", (e) => { lockLevel = parseInt(e.target.value); localStorage.setItem("WQR_LOCK_LEVEL", lockLevel); }); res.tabPane.querySelector("#WQRHNIncrement").addEventListener("input", (e) => { increment = parseInt(e.target.value); localStorage.setItem("WQR_HN_INCREMENT", increment); }); res.tabPane.querySelector("#WQRToggleBulkAdd").addEventListener("input", (e) => { isBulkAdd = e.target.checked; localStorage.setItem("WQR_BULK_ADD_ENABLED", isBulkAdd); }); NewRPPHNElement = res.tabPane.querySelector("#NewRPPHouseNumber"); toggleBulkAddElement = res.tabPane.querySelector("#WQRToggleBulkAdd"); if (isBulkAdd === true) { toggleBulkAddElement.checked = true; } else { toggleBulkAddElement.checked = false; } }); } function toggleBulkAdd() { if (isBulkAdd === 'true' || isBulkAdd === true) { console.log(`WME Quick RPP: Bulk creation mode disabled!`); toggleBulkAddElement.checked = false; isBulkAdd = false; } else { console.log(`WME Quick RPP: Bulk creation mode enabled!`); toggleBulkAddElement.checked = true; isBulkAdd = true; } localStorage.setItem("WQR_BULK_ADD_ENABLED", isBulkAdd); } async function duplicateRPP() { let actualLockLevel = lockLevel - 1; let selection = sdk.Editing.getSelection(); if (selection === null) { return; } let originalRPPId = selection.ids[0]; let originalRPP = sdk.DataModel.Venues.getById({ "venueId": originalRPPId }); if (!originalRPP.isResidential) { return } let originalRPPAddress = sdk.DataModel.Venues.getAddress({ "venueId": originalRPPId }); let originalRPPHouseNumber = parseInt(originalRPPAddress.houseNumber); let originalRPPStreetId = originalRPPAddress.street.id; if (isBulkAdd === 'true' || isBulkAdd === true) { while (isBulkAdd === 'true' || isBulkAdd === true) { let newRPPHouseNumber = parseInt(originalRPPHouseNumber) + parseInt(increment); NewRPPHNElement.innerText = (`New RPP HN: ${newRPPHouseNumber}`); let newRPPGeometry = await sdk.Map.drawPoint(); let newRPPId = sdk.DataModel.Venues.addVenue({ category: "RESIDENTIAL", geometry: newRPPGeometry }); sdk.DataModel.Venues.updateAddress({ houseNumber: `${newRPPHouseNumber}`, streetId: originalRPPStreetId, venueId: `${newRPPId}` }); sdk.DataModel.Venues.replaceNavigationPoints({ navigationPoints: [{ isEntry: true, isPrimary: true, point: newRPPGeometry }], venueId: `${newRPPId}` }); sdk.DataModel.Venues.updateVenue({ venueId: `${newRPPId}`, lockRank: actualLockLevel }); originalRPPHouseNumber = parseInt(newRPPHouseNumber); sdk.Editing.setSelection({selection: {ids: [`${newRPPId}`], objectType: "venue"}}); } } else { let newRPPHouseNumber = parseInt(originalRPPHouseNumber) + parseInt(increment); NewRPPHNElement.innerText = (`New RPP HN: ${newRPPHouseNumber}`); let newRPPGeometry = await sdk.Map.drawPoint(); let newRPPId = sdk.DataModel.Venues.addVenue({ category: "RESIDENTIAL", geometry: newRPPGeometry }); sdk.DataModel.Venues.updateAddress({ houseNumber: `${newRPPHouseNumber}`, streetId: originalRPPStreetId, venueId: `${newRPPId}` }); sdk.DataModel.Venues.replaceNavigationPoints({ navigationPoints: [{ isEntry: true, isPrimary: true, point: newRPPGeometry }], venueId: `${newRPPId}` }); sdk.DataModel.Venues.updateVenue({ venueId: `${newRPPId}`, lockRank: actualLockLevel }); sdk.Editing.setSelection({selection: {ids: [`${newRPPId}`], objectType: "venue"}}); } } })();