
- MODX 3
- PHP 8.2


The Free frontend is built from Fenom chunks, locator.css, and ES modules. Appearance uses BEM. Behavior uses data-yml-* attributes.
On narrow screens: single column, "List" / "Map" tabs. From 769px width: two columns, tabs hidden.
Tabs sit at the layout level, not inside the list panel. The map stays in the DOM: in list mode the map panel gets hidden. Before opening a balloon, JS switches the view to "Map".
| Block | Purpose |
|---|---|
yml-locator | Root, CSS variables |
yml-search | Search form |
yml-store | Location card |
yml-balloon | HTML inside the balloon |
State uses data attributes, not CSS modifiers like is-active.
| Attribute | Where | Purpose |
|---|---|---|
data-yml-root | .yml-locator | Root, initialization |
data-yml-view="list|map" | root | Mobile view mode |
data-yml-empty | root | Empty list |
data-yml-located | root | Geo filter active after locate() |
data-yml-parents | root | Parent IDs |
data-yml-search | form | Search |
data-yml-locate | button | "My location" / "All locations" |
data-yml-list / data-yml-map | panels | List and map |
data-yml-store-id | card | Location ID |
data-yml-lat, data-yml-lng | card | Coordinates |
Pro adds data-yml-open-now and badges .yml-store__status ("Open" / "Closed").
Search from the form and geolocation go to:
/assets/components/yandexmapslocator/search.php?parents=42&address=Omsk,%20Lenina%20st.,%2025&sortby=distanceSample response:
{
"success": true,
"data": [
{
"id": 15,
"pagetitle": "Store on Lenina",
"address": "Omsk, Lenina st., 25",
"latitude": 54.9893,
"longitude": 73.3682,
"phone": "+7 3812 00-00-00",
"distance": 0.4,
"distance_formatted": "0.4 km",
"context_key": "web"
}
],
"meta": { "total": 1 }
}Same-origin, no CORS or Bearer. The on-page locator calls REST api.php only when Pro is installed, api_enabled=Yes, and api_token is empty. If a token is set, REST is off, or Pro is missing, the frontend stays on search.php. The Bearer token is never written into page HTML.
An address query on search.php spends both the list bucket (api_list_rate_limit, 120/min) and the geocode bucket (api_geocode_rate_limit, 30/min).
const locator = new YandexMapsLocator('[data-yml-root]', { apiUrl, config, stores });
// Address search (form / custom UI)
locator.search({ address: 'Omsk, Lenina st., 25' });
// Browser geolocation → sort by distance
locator.locate();
// Clear geo filter ("All locations")
locator.clearLocation();
locator.on('store:click', ({ id }) => console.log('card', id));
locator.on('marker:click', ({ id }) => console.log('marker', id));
locator.on('balloon:build', (payload) => {
// you can extend balloon HTML
});JS events: store:click, marker:click, balloon:build, marker:options, search:start, search:complete, error. Public methods: search, locate, clearLocation, showStore, setStores, setCenter, getStores.
After locate() the button switches to "All locations" and clears the geo filter. On mobile, geolocation opens the "Map" tab.
const root = document.querySelector('[data-yml-root]');
const card = root.querySelector('[data-yml-store-id="15"]');
card?.querySelector('[data-yml-select]')?.click();Design tokens live on .yml-locator (CSS variables --yml-*). Override them in your site theme. Do not edit package files.
.yml-locator {
--yml-color-accent: #e11d48;
}
.yml-store[data-yml-active] {
outline: 2px solid var(--yml-color-accent);
}
.yml-store__status.is-open {
color: #15803d;
}
.yml-store__status.is-closed {
color: #b91c1c;
}