`,
].join(' ')
);
return $section.html();
}
function buildAllItemOptions() {
let html = '';
for (let i = 1; i <= 10; i++) {
html += buildItemOption(i);
}
html += `
You can bind keyboard shortcuts using WME's native shortcuts section.
`;
setTimeout(() => {
for (let i = 1; i <= 10; i++) {
loadPOIShortcutItem(i);
//legacy shortcuts key added from here
// Populate shortcut input with the actual shortcut key
const shortcutKey = i === 10 ? 'Ctrl+0' : `Ctrl+${i}`;
$(`#poiShortcut${i}`).val(shortcutKey);
// legacy shortcuts key added until above
// Save on change
$(`#poiItem${i},#poiLock${i},#poiGeom${i}`)
.off('change.wmepoi')
.on('change.wmepoi', function () {
savePOIShortcutItem(i);
// Prevent duplicate category selection
if (this.id.startsWith('poiItem')) {
const selectedCategories = [];
for (let j = 1; j <= 10; j++) {
const val = $(`#poiItem${j}`).val();
if (val) selectedCategories.push(val);
}
for (let j = 1; j <= 10; j++) {
$(`#poiItem${j} option`).prop('disabled', false).removeAttr('title');
}
for (let j = 1; j <= 10; j++) {
const currentVal = $(`#poiItem${j}`).val();
for (const cat of selectedCategories) {
if (cat !== currentVal) {
$(`#poiItem${j} option[value='${cat}']`).prop('disabled', true).attr('title', 'this category is already selected.');
}
}
}
}
});
}
// Initial duplicate prevention
const selectedCategories = [];
for (let j = 1; j <= 10; j++) {
const val = $(`#poiItem${j}`).val();
if (val) selectedCategories.push(val);
}
for (let j = 1; j <= 10; j++) {
$(`#poiItem${j} option`).prop('disabled', false).removeAttr('title');
}
for (let j = 1; j <= 10; j++) {
const currentVal = $(`#poiItem${j}`).val();
for (const cat of selectedCategories) {
if (cat !== currentVal) {
$(`#poiItem${j} option[value='${cat}']`).prop('disabled', true).attr('title', 'this category is already selected.');
}
}
}
}, 0);
return html;
}
/*
// --- wmeSDK Shortcuts Setup ---
// TODO: Re-enable when wmeSDK fixes shortcuts persistence after page refresh
/*
function setupShortcuts(wmeSDK) {
// Create 10 POI shortcut actions, one for each item
for (let i = 1; i <= 10; i++) {
// Assign shortcutKeys: C1-C9, C0 for 10
const shortcutKey = i === 10 ? 'C0' : `C${i}`;
const shortcutId = `create-poi-shortcut-${i}`;
// Remove previous shortcut if registered
if (wmeSDK.Shortcuts.isShortcutRegistered({ shortcutId })) {
wmeSDK.Shortcuts.deleteShortcut({ shortcutId });
}
// Check if shortcut keys are in use
if (wmeSDK.Shortcuts.areShortcutKeysInUse({ shortcutKeys: shortcutKey })) {
console.warn(`Shortcut keys ${shortcutKey} already in use, skipping registration for POI Shortcut #${i}`);
continue;
}
wmeSDK.Shortcuts.createShortcut({
callback: () => {
// Get selected values from the UI for this item
const cat = $(`#poiItem${i}`).val();
const lock = parseInt($(`#poiLock${i}`).val(), 10);
const geomType = $(`#poiGeom${i}`).val();
// Geometry: area = drawPolygon, point = drawPoint
let drawPromise = geomType === 'point' ? wmeSDK.Map.drawPoint() : wmeSDK.Map.drawPolygon();
drawPromise.then((geometry) => {
let newVenue = wmeSDK.DataModel.Venues.addVenue({
category: cat,
geometry: geometry,
});
wmeSDK.Editing.setSelection({
selection: {
ids: [newVenue.toString()],
objectType: 'venue',
},
});
// Only set lock if lock > 0 (lockRank 1-4)
if (!isNaN(lock) && lock > 0) {
wmeSDK.DataModel.Venues.updateVenue({
venueId: newVenue.toString(),
lockRank: lock,
});
}
// Nepal-specific logic for Gas Station
const topCountry = wmeSDK.DataModel.Countries.getTopCountry();
if (topCountry && (topCountry.name === 'Nepal' || topCountry.code === 'NP') && cat === 'GAS_STATION') {
wmeSDK.DataModel.Venues.updateVenue({
venueId: newVenue.toString(),
name: 'NOC',
brand: 'Nepal Oil Corporation',
});
}
});
},
description: `Create POI Shortcut #${i}`,
shortcutId,
shortcutKeys: shortcutKey,
});
}
// Shortcuts that click on WME's existing UI buttons for POI creation/modification
wmeSDK.Shortcuts.createShortcut({
callback: () => {
$("wz-icon[name='toll-booth']").parent().trigger('click');
},
description: 'Add Toll Booth',
shortcutId: 'add-toll-booth',
shortcutKeys: null,
});
wmeSDK.Shortcuts.createShortcut({
callback: () => {
$("wz-icon[name='railway-crossing']").parent().trigger('click');
},
description: 'Add Level Crossing',
shortcutId: 'add-level-crossing',
shortcutKeys: null,
});
wmeSDK.Shortcuts.createShortcut({
callback: () => {
$("wz-icon[name='school-zone']").parent().trigger('click');
},
description: 'Create School Zone',
shortcutId: 'create-school-zone',
shortcutKeys: null,
});
}
*/
/***********************************************legacy shortcuts below*********************************************** */
// --- Legacy Shortcuts Setup (Temporary until wmeSDK fixes shortcuts persistence) ---
function setupShortcuts(wmeSDK) {
// Legacy shortcuts configuration - maps shortcut numbers to keyboard combos
var shortcutsConfig = [
{
handler: 'WME-POI-Shortcuts_poi1',
title: 'POI Shortcut 1',
func: function (ev) {
createPOIFromShortcut(1, wmeSDK);
},
key: null,
arg: { slotNumber: 1 },
},
{
handler: 'WME-POI-Shortcuts_poi2',
title: 'POI Shortcut 2',
func: function (ev) {
createPOIFromShortcut(2, wmeSDK);
},
key: null,
arg: { slotNumber: 2 },
},
{
handler: 'WME-POI-Shortcuts_poi3',
title: 'POI Shortcut 3',
func: function (ev) {
createPOIFromShortcut(3, wmeSDK);
},
key: null,
arg: { slotNumber: 3 },
},
{
handler: 'WME-POI-Shortcuts_poi4',
title: 'POI Shortcut 4',
func: function (ev) {
createPOIFromShortcut(4, wmeSDK);
},
key: null,
arg: { slotNumber: 4 },
},
{
handler: 'WME-POI-Shortcuts_poi5',
title: 'POI Shortcut 5',
func: function (ev) {
createPOIFromShortcut(5, wmeSDK);
},
key: null,
arg: { slotNumber: 5 },
},
{
handler: 'WME-POI-Shortcuts_poi6',
title: 'POI Shortcut 6',
func: function (ev) {
createPOIFromShortcut(6, wmeSDK);
},
key: null,
arg: { slotNumber: 6 },
},
{
handler: 'WME-POI-Shortcuts_poi7',
title: 'POI Shortcut 7',
func: function (ev) {
createPOIFromShortcut(7, wmeSDK);
},
key: null,
arg: { slotNumber: 7 },
},
{
handler: 'WME-POI-Shortcuts_poi8',
title: 'POI Shortcut 8',
func: function (ev) {
createPOIFromShortcut(8, wmeSDK);
},
key: null,
arg: { slotNumber: 8 },
},
{
handler: 'WME-POI-Shortcuts_poi9',
title: 'POI Shortcut 9',
func: function (ev) {
createPOIFromShortcut(9, wmeSDK);
},
key: null,
arg: { slotNumber: 9 },
},
{
handler: 'WME-POI-Shortcuts_poi10',
title: 'POI Shortcut 10',
func: function (ev) {
createPOIFromShortcut(10, wmeSDK);
},
key: null,
arg: { slotNumber: 10 },
},
{
handler: 'WME-POI-Shortcuts_toll-booth',
title: 'Add Toll Booth',
func: function (ev) {
$("wz-icon[name='toll-booth']").parent().trigger('click');
},
key: -1, // No default key, user can set custom
arg: {},
},
{
handler: 'WME-POI-Shortcuts_level-crossing',
title: 'Add Level Crossing',
func: function (ev) {
$("wz-icon[name='railway-crossing']").parent().trigger('click');
},
key: -1, // No default key, user can set custom
arg: {},
},
{
handler: 'WME-POI-Shortcuts_school-zone',
title: 'Create School Zone',
func: function (ev) {
$("wz-icon[name='school-zone']").parent().trigger('click');
},
key: -1, // No default key, user can set custom
arg: {},
},
];
// Register legacy shortcuts
for (var i = 0; i < shortcutsConfig.length; ++i) {
WMEKSRegisterKeyboardShortcut('WME-POI-Shortcuts', 'WME POI Shortcuts', shortcutsConfig[i].handler, shortcutsConfig[i].title, shortcutsConfig[i].func, shortcutsConfig[i].key, shortcutsConfig[i].arg);
}
WMEKSLoadKeyboardShortcuts('WME-POI-Shortcuts');
window.addEventListener(
'beforeunload',
function () {
WMEKSSaveKeyboardShortcuts('WME-POI-Shortcuts');
},
false
);
}
// Function to create POI from shortcut slot
function createPOIFromShortcut(slotNumber, wmeSDK) {
try {
// Get selected values from the UI for this item
const cat = $(`#poiItem${slotNumber}`).val();
const lock = parseInt($(`#poiLock${slotNumber}`).val(), 10);
const geomType = $(`#poiGeom${slotNumber}`).val();
if (!cat || cat === '') {
console.warn(`POI Shortcut ${slotNumber}: No category selected`);
return;
}
// Geometry: area = drawPolygon, point = drawPoint
let drawPromise = geomType === 'point' ? wmeSDK.Map.drawPoint() : wmeSDK.Map.drawPolygon();
drawPromise.then((geometry) => {
let newVenue = wmeSDK.DataModel.Venues.addVenue({
category: cat,
geometry: geometry,
});
wmeSDK.Editing.setSelection({
selection: {
ids: [newVenue.toString()],
objectType: 'venue',
},
});
// Only set lock if lock > 0 (lockRank 1-4)
if (!isNaN(lock) && lock > 0) {
wmeSDK.DataModel.Venues.updateVenue({
venueId: newVenue.toString(),
lockRank: lock,
});
}
// Nepal-specific logic for Gas Station
const topCountry = wmeSDK.DataModel.Countries.getTopCountry();
if (topCountry && (topCountry.name === 'Nepal' || topCountry.code === 'NP') && cat === 'GAS_STATION') {
wmeSDK.DataModel.Venues.updateVenue({
venueId: newVenue.toString(),
name: 'NOC',
brand: 'Nepal Oil Corporation',
});
}
});
} catch (error) {
console.error(`Error creating POI from shortcut ${slotNumber}:`, error);
}
}
// --- Legacy Keyboard Shortcuts System (from WME Street to River PLUS) ---
function WMEKSRegisterKeyboardShortcut(scriptName, shortcutsHeader, newShortcut, shortcutDescription, functionToCall, shortcutKeysObj, arg) {
try {
I18n.translations[I18n.locale].keyboard_shortcuts.groups[scriptName].members.length;
} catch (c) {
(W.accelerators.Groups[scriptName] = []),
(W.accelerators.Groups[scriptName].members = []),
(I18n.translations[I18n.locale].keyboard_shortcuts.groups[scriptName] = []),
(I18n.translations[I18n.locale].keyboard_shortcuts.groups[scriptName].description = shortcutsHeader),
(I18n.translations[I18n.locale].keyboard_shortcuts.groups[scriptName].members = []);
}
if (functionToCall && 'function' == typeof functionToCall) {
(I18n.translations[I18n.locale].keyboard_shortcuts.groups[scriptName].members[newShortcut] = shortcutDescription),
W.accelerators.addAction(newShortcut, {
group: scriptName,
});
var i = '-1',
j = {};
(j[i] = newShortcut),
W.accelerators._registerShortcuts(j),
null !== shortcutKeysObj && ((j = {}), (j[shortcutKeysObj] = newShortcut), W.accelerators._registerShortcuts(j)),
W.accelerators.events.register(newShortcut, null, function () {
functionToCall(arg);
});
} else alert('The function ' + functionToCall + ' has not been declared');
}
function WMEKSLoadKeyboardShortcuts(scriptName) {
console.log('WMEKSLoadKeyboardShortcuts(' + scriptName + ')');
if (localStorage[scriptName + 'KBS'])
for (var shortcuts = JSON.parse(localStorage[scriptName + 'KBS']), i = 0; i < shortcuts.length; i++)
try {
W.accelerators._registerShortcuts(shortcuts[i]);
} catch (error) {
console.log(error);
}
}
function WMEKSSaveKeyboardShortcuts(scriptName) {
console.log('WMEKSSaveKeyboardShortcuts(' + scriptName + ')');
var shortcuts = [];
for (var actionName in W.accelerators.Actions) {
var shortcutString = '';
if (W.accelerators.Actions[actionName].group == scriptName) {
W.accelerators.Actions[actionName].shortcut
? (W.accelerators.Actions[actionName].shortcut.altKey === !0 && (shortcutString += 'A'),
W.accelerators.Actions[actionName].shortcut.shiftKey === !0 && (shortcutString += 'S'),
W.accelerators.Actions[actionName].shortcut.ctrlKey === !0 && (shortcutString += 'C'),
'' !== shortcutString && (shortcutString += '+'),
W.accelerators.Actions[actionName].shortcut.keyCode && (shortcutString += W.accelerators.Actions[actionName].shortcut.keyCode))
: (shortcutString = '-1');
var shortcutObj = {};
(shortcutObj[shortcutString] = W.accelerators.Actions[actionName].id), (shortcuts[shortcuts.length] = shortcutObj);
}
}
localStorage[scriptName + 'KBS'] = JSON.stringify(shortcuts);
}
/******************************************legacy shortcuts until here above************************************ */
function getGasStationCategoryKey() {
// Use I18n to get the correct category key for gas station
// Fallback to 'GAS_STATION' if not found
let locale = typeof I18n !== 'undefined' && I18n.currentLocale ? I18n.currentLocale() : 'en';
let categories = I18n?.translations?.[locale]?.venues?.categories || {};
// Find the key for 'Gas Station' or 'Petrol Station' in the current language
for (const key in categories) {
if (categories[key] === 'Gas Station' || categories[key] === 'Petrol Station') {
return key;
}
}
// Fallback to 'GAS_STATION'
return 'GAS_STATION';
}
function swapPrimaryAndAliasNames(wmeSDK, aliasIndex = 0) {
// Only run if a venue is selected
const selection = wmeSDK.Editing.getSelection();
if (!selection || selection.objectType !== 'venue' || !selection.ids || selection.ids.length !== 1) {
console.warn('No venue selected for name swapping');
return;
}
const venueId = selection.ids[0];
const venue = wmeSDK.DataModel.Venues.getById({ venueId });
if (!venue) {
console.warn('Venue not found');
return;
}
// Check if venue has a name and at least one alias
if (!venue.name || !venue.aliases || venue.aliases.length === 0) {
console.warn('Venue must have both a primary name and at least one alias to swap');
return;
}
// Validate alias index
if (aliasIndex < 0 || aliasIndex >= venue.aliases.length) {
console.warn(`Invalid alias index: ${aliasIndex}. Available aliases: ${venue.aliases.length}`);
return;
}
// Get current primary name and target alias
const currentPrimaryName = venue.name;
const targetAlias = venue.aliases[aliasIndex];
// Create new aliases array with the old primary name replacing the target alias
const newAliases = [...venue.aliases];
newAliases[aliasIndex] = currentPrimaryName;
try {
// Update venue with swapped names
wmeSDK.DataModel.Venues.updateVenue({
venueId: venueId,
name: targetAlias,
aliases: newAliases,
});
console.log(`Swapped names: "${currentPrimaryName}" ↔ "${targetAlias}" (alias index: ${aliasIndex})`);
} catch (error) {
console.error('Error swapping venue names:', error);
}
}
function injectSwapNamesButton(wmeSDK) {
// Only run if a venue is selected
const selection = wmeSDK.Editing.getSelection();
if (!selection || selection.objectType !== 'venue' || !selection.ids || selection.ids.length !== 1) return;
const venueId = selection.ids[0];
const venue = wmeSDK.DataModel.Venues.getById({ venueId });
if (!venue) return;
// Wait for the venue aliases section to exist
function tryInjectSwapButton() {
// Look for the aliases list and inject button into ALL alias items' actions containers
const $aliasesList = $('.aliases-list');
let foundAliases = false;
if ($aliasesList.length > 0) {
// Find ALL alias items and add swap button to each
$aliasesList.find('wz-list-item').each(function (index) {
const $aliasItem = $(this);
const $actionsContainer = $aliasItem.find('div[slot="actions"].alias-item-actions');
if ($actionsContainer.length > 0) {
// Check if swap button already exists in this specific alias item
if ($actionsContainer.find('.swap-names-btn').length === 0) {
foundAliases = true;
// Check if venue has both name and aliases before showing button
const hasSwappableNames = venue.name && venue.aliases && venue.aliases.length > 0;
if (!hasSwappableNames) return true; // Continue to next iteration
// Create swap button for this specific alias (swap with the alias at this index)
const buttonHtml = `
`;
$actionsContainer.prepend(buttonHtml);
}
}
});
}
// Fallback method if no aliases found
if (!foundAliases) {
const $nameField = $('input[placeholder*="name" i], input[name*="name" i], .venue-name input, .place-name input');
if ($nameField.length > 0) {
const $targetContainer = $nameField.closest('.form-group, .field-group, .control-group').first();
if ($targetContainer.length > 0 && $('.swap-names-btn').length === 0) {
const hasSwappableNames = venue.name && venue.aliases && venue.aliases.length > 0;
if (hasSwappableNames) {
const buttonHtml = `
Swap Names
`;
$targetContainer.after(buttonHtml);
foundAliases = true;
}
}
}
}
if (!foundAliases) {
setTimeout(tryInjectSwapButton, 100);
return;
}
// Button click handler for all swap buttons
$('.swap-names-btn')
.off('click.swapnames')
.on('click.swapnames', function (e) {
e.preventDefault();
const aliasIndex = parseInt($(this).attr('data-alias-index') || '0', 10);
swapPrimaryAndAliasNames(wmeSDK, aliasIndex);
});
}
tryInjectSwapButton();
}
function injectNOCButtonIfNepalGasStation(wmeSDK) {
// Only run if a venue is selected
const selection = wmeSDK.Editing.getSelection();
if (!selection || selection.objectType !== 'venue' || !selection.ids || selection.ids.length !== 1) return;
const venueId = selection.ids[0];
const venue = wmeSDK.DataModel.Venues.getById({ venueId });
const topCountry = wmeSDK.DataModel.Countries.getTopCountry();
const gasStationKey = getGasStationCategoryKey();
// Check if venue.categories (array) contains the gas station key and country is Nepal or Pakistan
const isNepal = !!topCountry && (topCountry.name === 'Nepal' || topCountry.code === 'NP');
const isPakistan = !!topCountry && (topCountry.name === 'Pakistan' || topCountry.code === 'PK');
const isGasStation = !!venue && Array.isArray(venue.categories) && venue.categories.includes(gasStationKey);
if (!(isGasStation && (isNepal || isPakistan))) return;
// Show brand buttons for Nepal and Pakistan gas stations
function tryInjectBrandButtons() {
const $catControl = $('.categories-control');
if ($catControl.length === 0) {
setTimeout(tryInjectBrandButtons, 150);
return;
}
// Prevent duplicate buttons
if ($('.gas-station-brand-btn').length > 0) return;
// Determine country and get only relevant brands
let countryBrands = null;
if (isNepal) {
countryBrands = GAS_STATION_BRANDNAME.Nepal.brandnames;
} else if (isPakistan) {
countryBrands = GAS_STATION_BRANDNAME.Pakistan.brandnames;
}
if (!countryBrands) return;
// Log current brand value for Pakistan gas stations
if (isPakistan) {
console.log('[Brand Debug] Current venue brand value (Pakistan):', venue.brand);
}
// Build buttons for each brand
let buttonsHtml = `