Greasy Fork is available in English.
Shows House Numbers on RPPs.
// ==UserScript==
// @name WME RPP
// @namespace https://greasyfork.org/users/velezss
// @version 1.0
// @description Shows House Numbers on RPPs.
// @author velezss
// @match https://beta.waze.com/*editor*
// @match https://www.waze.com/*editor*
// @exclude https://www.waze.com/user/editor*
// @require https://greasyfork.org/scripts/459348-wme-sdk/code/WME%20SDK.js
// @grant none
// ==/UserScript==
/* global W, OpenLayers, getWmeSdk */
(function () {
"use strict";
const SCRIPT_ID = "wme-rpp-hn-sdk-en";
const SCRIPT_NAME = "RPP Numbers";
// --- SDK Initialization Helper ---
function onceSdkReady(cb) {
const tick = () => {
if (window.getWmeSdk) {
if (window.SDK_INITIALIZED) {
window.SDK_INITIALIZED.then(cb).catch(console.error);
} else {
cb();
}
} else {
setTimeout(tick, 250);
}
};
tick();
}
// --- Main Logic ---
onceSdkReady(async () => {
const sdk = getWmeSdk({ scriptId: SCRIPT_ID, scriptName: SCRIPT_NAME });
// 1. Register Tab
const { tabLabel, tabPane } = await sdk.Sidebar.registerScriptTab();
tabLabel.textContent = "RPP #";
tabLabel.title = "RPP House Numbers";
// 2. Create UI (English)
const style = document.createElement("style");
style.textContent = `
#wrpp-root { padding: 12px; font-family: "Boing", "Open Sans", sans-serif; }
#wrpp-root .row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
#wrpp-root .status { font-size: 12px; color: #666; background: #f0f0f0; padding: 8px; border-radius: 6px; margin-top: 10px; }
#wrpp-root .switch { position: relative; display: inline-block; width: 40px; height: 20px; }
#wrpp-root .switch input { opacity: 0; width: 0; height: 0; }
#wrpp-root .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 20px; }
#wrpp-root .slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: white; transition: .4s; border-radius: 50%; }
input:checked + .slider { background-color: #2196F3; }
input:checked + .slider:before { transform: translateX(20px); }
`;
tabPane.appendChild(style);
const root = document.createElement("div");
root.id = "wrpp-root";
// UI Template: Checkbox is explicitly 'checked' to force ON state at startup
root.innerHTML = `
<div class="row">
<span style="font-weight:bold; color:#333;">Show Numbers</span>
<label class="switch">
<input type="checkbox" id="wrpp-toggle" checked>
<span class="slider"></span>
</label>
</div>
<div id="wrpp-status" class="status">Initializing...</div>
<div style="font-size:10px; color:#999; margin-top:15px; text-align:center;">Gemini SDK Edition</div>
`;
tabPane.appendChild(root);
// 3. Map Layer Logic
let labelLayer;
function setupLayer() {
try {
const oldLayers = W.map.getLayersByName("RPP_HouseNumbers_SDK");
oldLayers.forEach(l => W.map.removeLayer(l));
} catch(e) {}
labelLayer = new OpenLayers.Layer.Vector("RPP_HouseNumbers_SDK", {
displayInLayerSwitcher: false,
styleMap: new OpenLayers.StyleMap({
"default": new OpenLayers.Style({
label: "${label}",
fontColor: "#ffffff",
fontWeight: "bold",
fontSize: "12px",
fontFamily: "Arial, sans-serif",
labelOutlineColor: "#000000",
labelOutlineWidth: 3,
labelYOffset: -20
})
})
});
W.map.addLayer(labelLayer);
}
function updateRPPs() {
const toggle = document.getElementById('wrpp-toggle');
const statusBox = document.getElementById('wrpp-status');
// Safety check
if (!toggle) return;
// If user manually turns it off during session
if (!toggle.checked) {
if (labelLayer) labelLayer.removeAllFeatures();
if (statusBox) statusBox.textContent = "Visuals disabled.";
return;
}
if (!labelLayer) setupLayer();
labelLayer.removeAllFeatures();
// Object Fetching Strategy
let objects = [];
if (W.model.venues.getObjectArray) {
objects = W.model.venues.getObjectArray();
} else {
for (let id in W.model.venues.objects) {
objects.push(W.model.venues.objects[id]);
}
}
const rpps = objects.filter(p => p.isResidential && p.isResidential());
const features = [];
let countConNumero = 0;
rpps.forEach((rpp) => {
let hn = rpp.attributes.houseNumber;
// Handle empty or null numbers
if (!hn || hn.trim() === "") {
hn = "?";
} else {
countConNumero++;
}
const point = rpp.geometry.getCentroid();
const feature = new OpenLayers.Feature.Vector(point, {
label: hn.toString()
});
features.push(feature);
});
labelLayer.addFeatures(features);
if (statusBox) {
statusBox.innerHTML = `
<b>${rpps.length}</b> visible RPPs.<br>
<b>${countConNumero}</b> have numbers.
`;
}
}
// 4. Event Listeners
const toggleBtn = document.getElementById('wrpp-toggle');
toggleBtn.addEventListener('change', updateRPPs);
// Initial Setup
setupLayer();
// Waze Events
W.map.events.register("moveend", null, updateRPPs);
W.map.events.register("zoomend", null, updateRPPs);
W.model.events.register("mergeend", null, updateRPPs);
// Trigger first run
setTimeout(updateRPPs, 1000);
});
})();