// ==UserScript==
// @name WME Enhanced Actions
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Enhance your editing experience by automating repetitive tasks, optimizing your workflow with keyboard shortcuts, and streamlining key actions. Designed to help Waze editors improve efficiency with customizable automation tools.
// @author Astheron
// @match https://www.waze.com/*
// @grant none
// @license MIT
// ==/UserScript==
/**
* License and Credits:
*
* This script is licensed under the MIT License:
* Copyright (c) 2024 Astheron
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this script and associated documentation files (the "Script"), to deal
* in the Script without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Script, and to permit persons to whom the Script is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Script.
*
* THE SCRIPT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SCRIPT OR THE USE OR OTHER DEALINGS IN THE
* SCRIPT.
*
* **Contact:** For more details or inquiries, you can contact the author, Astheron, on the Waze forum.
*/
(function() {
'use strict';
let autoSaveEnabled = JSON.parse(localStorage.getItem('autoSaveEnabled')) || false;
let saveKeyCombination = JSON.parse(localStorage.getItem('saveKeyCombination')) || [];
let addressPanelKeyCombination = JSON.parse(localStorage.getItem('addressPanelKeyCombination')) || [];
function getEditorLanguage() {
const url = window.location.href;
if (url.includes('/es/')) {
return 'es';
}
return 'en';
}
const lang = getEditorLanguage();
const isSpanish = lang === 'es';
const translations = {
en: {
title: 'WME Enhanced Actions',
description: 'Automate editing tasks with customizable auto-save and key combinations.',
setSaveKey: 'Set Save Key (or combination):',
saveHint: 'Use combinations of Ctrl, Alt, Shift with other keys.',
setAddressPanelKey: 'Set Address Panel Key (or combination):',
addressHint: 'Use combinations of Ctrl, Alt, Shift with other keys to open the address panel.',
by: 'Script developed by',
moreInfo: 'For more information, visit the Waze forum.',
},
es: {
title: 'WME Enhanced Actions',
description: 'Automatiza las tareas de edición con funciones de guardado automático y combinaciones de teclas personalizables.',
setSaveKey: 'Configurar tecla de guardado (o combinación):',
saveHint: 'Usa combinaciones de Ctrl, Alt, Shift con otras teclas.',
setAddressPanelKey: 'Configurar tecla para el panel de direcciones (o combinación):',
addressHint: 'Usa combinaciones de Ctrl, Alt, Shift con otras teclas para abrir el panel de direcciones.',
by: 'Script programado por',
moreInfo: 'Para más información, visita el foro de Waze.',
}
};
const t = isSpanish ? translations.es : translations.en;
function initializeSidebarTab() {
const { tabLabel, tabPane } = W.userscripts.registerSidebarTab("enhanced-actions");
tabLabel.innerText = t.title;
tabLabel.title = 'Configure Auto Save and Key Combos';
tabPane.innerHTML = `
<div style="font-family: Arial, sans-serif; padding: 10px; border: 1px solid #ccc; border-radius: 8px; background: #fafafa;">
<h2 style="color: #4CAF50; font-size: 1.5em; margin-bottom: 10px;">${t.title}</h2>
<p style="font-size: 0.9em; color: #666;">
${isSpanish ? 'Facilita el trabajo de los editores con automatización de tareas repetitivas, atajos de teclado personalizables y más herramientas para optimizar la experiencia de edición en Waze.' : 'Helps editors streamline their work with task automation, customizable keyboard shortcuts, and additional tools to enhance the Waze editing experience.'}
</p>
<hr style="border: none; border-top: 1px solid #eee; margin: 15px 0;">
<div style="margin-bottom: 15px;">
<label for="saveKeyInput" style="font-weight: bold;">${t.setSaveKey}</label>
<input type="text" id="saveKeyInput" readonly placeholder="Click to set keys"
style="width: 200px; padding: 5px; margin-left: 10px; border: 1px solid #ccc; border-radius: 4px;">
<p style="font-size: 0.85em; color: #888; margin-left: 20px;">${t.saveHint}</p>
</div>
<div style="margin-bottom: 15px;">
<label for="addressPanelKeyInput" style="font-weight: bold;">${t.setAddressPanelKey}</label>
<input type="text" id="addressPanelKeyInput" readonly placeholder="Click to set keys"
style="width: 200px; padding: 5px; margin-left: 10px; border: 1px solid #ccc; border-radius: 4px;">
<p style="font-size: 0.85em; color: #888; margin-left: 20px;">${t.addressHint}</p>
</div>
<hr style="border: none; border-top: 1px solid #eee; margin: 15px 0;">
<p style="font-size: 0.85em; color: #666;">
${t.by} <a href="https://www.waze.com/es/user/editor/Astheron" target="_blank" style="color: #4CAF50; text-decoration: none;">Astheron</a>.
</p>
<p style="font-size: 0.85em; color: #666;">
${t.moreInfo} <a href="https://www.waze.com/forum/viewtopic.php?t=413593" target="_blank" style="color: #4CAF50; text-decoration: none;">Waze forum</a>.
</p>
</div>
`;
const saveKeyInput = tabPane.querySelector('#saveKeyInput');
const addressPanelKeyInput = tabPane.querySelector('#addressPanelKeyInput');
saveKeyInput.value = saveKeyCombination.join('+');
addressPanelKeyInput.value = addressPanelKeyCombination.join('+');
saveKeyInput.addEventListener('focus', (event) => {
saveKeyInput.value = '';
startRecordingKeyCombination(saveKeyInput, 'save');
});
addressPanelKeyInput.addEventListener('focus', (event) => {
addressPanelKeyInput.value = '';
startRecordingKeyCombination(addressPanelKeyInput, 'addressPanel');
});
W.userscripts.waitForElementConnected(tabPane).then(() => {
console.log("Enhanced Actions tab connected.");
});
}
function startRecordingKeyCombination(inputField, type) {
let combination = [];
const keydownListener = (event) => {
event.preventDefault();
let key = event.key;
if (event.ctrlKey && !combination.includes('Ctrl')) {
combination.push('Ctrl');
}
if (event.altKey && !combination.includes('Alt')) {
combination.push('Alt');
}
if (event.shiftKey && !combination.includes('Shift')) {
combination.push('Shift');
}
if (!['Control', 'Shift', 'Alt', 'Meta'].includes(key)) {
combination.push(key);
}
inputField.value = combination.join('+');
};
const keyupListener = () => {
if (type === 'save') {
saveKeyCombination = combination;
localStorage.setItem('saveKeyCombination', JSON.stringify(saveKeyCombination));
autoSaveEnabled = combination.length > 0;
localStorage.setItem('autoSaveEnabled', JSON.stringify(autoSaveEnabled));
} else if (type === 'addressPanel') {
addressPanelKeyCombination = combination;
localStorage.setItem('addressPanelKeyCombination', JSON.stringify(addressPanelKeyCombination));
}
document.removeEventListener('keydown', keydownListener);
document.removeEventListener('keyup', keyupListener);
};
document.addEventListener('keydown', keydownListener);
document.addEventListener('keyup', keyupListener);
}
function blurActiveInput() {
const activeElement = document.activeElement;
if (activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA')) {
activeElement.blur();
}
}
function handleEnterPress(event) {
if (event.key === 'Enter' &&
!(document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA')) {
event.preventDefault();
blurActiveInput();
let applyButton = document.querySelector('wz-button.save-button');
if (applyButton) {
setTimeout(() => {
applyButton.click();
}, 100);
} else {
console.log("Apply button not found.");
}
}
}
function handleSaveKeyPress(event) {
if (document.activeElement.tagName === 'INPUT' ||
document.activeElement.tagName === 'TEXTAREA' ||
document.activeElement.isContentEditable) {
return;
}
const pressedCombination = [];
if (event.ctrlKey) pressedCombination.push('Ctrl');
if (event.altKey) pressedCombination.push('Alt');
if (event.shiftKey) pressedCombination.push('Shift');
if (!['Control', 'Shift', 'Alt', 'Meta'].includes(event.key)) {
pressedCombination.push(event.key);
}
if (JSON.stringify(pressedCombination) === JSON.stringify(saveKeyCombination) && autoSaveEnabled) {
event.preventDefault();
blurActiveInput();
let saveButton = document.querySelector('wz-button#save-button');
if (saveButton && saveButton.getAttribute('disabled') === "false") {
setTimeout(() => {
saveButton.click();
}, 100);
} else {
console.log("Save button not found or disabled.");
}
}
}
function handleAddressPanelKeyPress(event) {
if (document.activeElement.tagName === 'INPUT' ||
document.activeElement.tagName === 'TEXTAREA' ||
document.activeElement.isContentEditable) {
return;
}
const pressedCombination = [];
if (event.ctrlKey) pressedCombination.push('Ctrl');
if (event.altKey) pressedCombination.push('Alt');
if (event.shiftKey) pressedCombination.push('Shift');
if (!['Control', 'Shift', 'Alt', 'Meta'].includes(event.key)) {
pressedCombination.push(event.key);
}
if (JSON.stringify(pressedCombination) === JSON.stringify(addressPanelKeyCombination)) {
event.preventDefault();
let addressPanel = document.querySelector('.full-address-container');
if (addressPanel) {
let editButton = addressPanel.querySelector('.edit-button');
if (editButton) {
setTimeout(() => {
editButton.click();
}, 100);
} else {
console.log("Edit button not found.");
}
} else {
console.log("Address panel not found.");
}
}
}
function initializeMyUserscript() {
initializeSidebarTab();
document.addEventListener('keydown', handleEnterPress, true);
document.addEventListener('keydown', handleSaveKeyPress, true);
document.addEventListener('keydown', handleAddressPanelKeyPress, true);
}
if (W?.userscripts?.state.isReady) {
initializeMyUserscript();
} else {
document.addEventListener("wme-ready", initializeMyUserscript, { once: true });
}
})();