Store Locator using Filters Controls ¶
This guide shows you how to add data filters to a store locator using controls.The finished example will look like this:
See the example fullscreen
When to use ¶
-
The entire store location data set is relatively big.
-
The data set can be filtered using properties or by distance.
What is needed ¶
-
Magic Lane API key token
-
Web server (an example is provided)
-
SVG file of the store logo (or use our sample SVG)
-
Store locator using Magic Lane JavaScript controls
Setup ¶
Get your Magic Lane API key token: if you do not have a token, see the Getting Started guide.
Adding controls ¶
To see how to add Studio Query data control, store list control, free text search control and distance control check out the guide Store Locator using Studio Query Data Source .
You can also use the filters controls with any data source of your choice from our use cases.
Adding category radio type filter ¶
A radio type filter has been added using the data property
rate
. To add this kind of filter
you can use the control
gem.control.CategoryFilterControl
with the option
style:
'radio'
.
The filter options are defined using
categories
and the property
name
should hold a unique identifier
for the filter control.
1 const categoryRadioRateFilter = new gem.control.CategoryFilterControl({
2 parentContainer: 'filter-category-rate',
3 name: 'byRate',
4 style: 'radio',
5 title: 'Filter by Rate',
6 categories: [
7 { label: 'any', filter: { key: '', value: '' } },
8 { label: '3', filter: { key: 'rate', value: '3' } },
9 { label: '3h', filter: { key: 'rate', value: '3h' } }
10 ]
11 }, studioQueryControl);
12 defaultAppScreen.addControl(categoryRadioRateFilter);
1...
2<div id="map-canvas" style="width: 75%; left: 25%; height: 100%; position: absolute; overflow: hidden">
3 <div id="filters-container" class="filters-container">
4 <div id="filter-category-rate" class="filter-category2"></div>
5 <div id="filter-distance" class="filter-distance"></div>
6 </div>
7</div>
8...
Adding category checkboxes filter ¶
A filter with the checkboxes style has been added using the data property
kinds
. To add this kind
of filter you can use the control
gem.control.CategoryFilterControl
with the option
style:
'checkboxes'
.
The filter options are defined using
categories
and the property
name
should hold a unique identifier
for the filter control.
1 const categoryCheckboxFilterControl = new gem.control.CategoryFilterControl({
2 parentContainer: 'filter-category-kind',
3 name: 'byKindCheckboxes',
4 style: 'checkboxes',
5 title: 'Filter by kind',
6 categories: [
7 {
8 label: 'Food', filter: { key: '', value: '' }, children:
9 [
10 { label: 'Cafes', filter: { key: 'kinds', value: 'cafes,foods,tourist_facilities' } },
11 { label: 'Restaurants', filter: { key: 'kinds', value: 'restaurants,foods,tourist_facilities' } },
12 { label: 'Restaurants, Historic Architecture', filter: { key: 'kinds', value: 'historic_architecture,architecture,interesting_places,restaurants,foods,tourist_facilities,other_buildings_and_structures' } }
13 ]
14 },
15 {
16 label: 'Visit', filter: { key: '', value: '' }, children:
17 [
18 { label: 'Art Galleries', filter: { key: 'kinds', value: 'national_museums,museums,cultural,interesting_places,art_galleries' } },
19 { label: 'Museums', filter: { key: 'kinds', value: 'museums,cultural,interesting_places,other_museums' } },
20 { label: 'Historic Monuments', filter: { key: 'kinds', value: 'fortifications,historic,monuments_and_memorials,interesting_places,castles,monuments' } }
21 ]
22 }
23 ]
24 }, studioQueryControl);
25 defaultAppScreen.addControl(categoryCheckboxFilterControl);
1...
2<div id="map-canvas" style="width: 75%; left: 25%; height: 100%; position: absolute; overflow: hidden">
3 <div id="filters-container" class="filters-container">
4 <div id="filter-category-kind" class="filter-category1"></div>
5 <div id="filter-category-rate" class="filter-category2"></div>
6 <div id="filter-distance" class="filter-distance"></div>
7 </div>
8</div>
9...
Complete example code ¶
1 // Start by setting your token from https://developer.magiclane.com/api/projects
2 if (gem.core.App.token === undefined) gem.core.App.token = '';
3
4 const defaultAppScreen = gem.core.App.initAppScreen({
5 container: 'map-canvas',
6 zoom: 10,
7 center: [48.8562, 2.3516, 100000]
8 });
9
10 const studioQueryControl = new gem.control.StudioQueryDataControl('1973209755' /* studio data source id */, '', {
11 markerBubble: {
12 title: ['name'],
13 image: ['preview']
14 }
15 });
16 defaultAppScreen.addControl(studioQueryControl);
17
18 const searchControl = new gem.control.DataQuerySearchControl({
19 highlightOptions: {
20 contourColor: { r: 0, g: 255, b: 0, a: 0 }
21 },
22 searchPreferences: {
23 maximumMatches: 3,
24 addressSearch: false,
25 mapPoisSearch: false,
26 setCursorReferencePoint: true
27 },
28 searchResults: {
29 initialPlaceSearch: 'Paris'
30 }
31 }, studioQueryControl);
32 defaultAppScreen.addControl(searchControl);
33
34 const listUIControl = new gem.control.ListControl({
35 sourceControl: studioQueryControl,
36 container: 'stores-list',
37 displayCount: true,
38 flyToItemAltitude: 250,
39 menuName: 'Store Locator Example',
40 titleProperties: ['name'],
41 detailsProperties: ['kinds'],
42 imageProperty: ['preview']
43 });
44 defaultAppScreen.addControl(listUIControl);
45
46 const distanceFilterControl = new gem.control.DistanceFilterControl({
47 parentContainer: 'filter-distance',
48 name: 'byRadius',
49 style: 'dropdown',
50 title: 'Search radius (km)',
51 thresholds: [10, 25, 50, 100, 200],
52 eUnit: 'km'
53 }, studioQueryControl);
54
55 const categoryCheckboxFilterControl = new gem.control.CategoryFilterControl({
56 parentContainer: 'filter-category-kind',
57 name: 'byKindCheckboxes',
58 style: 'checkboxes',
59 title: 'Filter by kind',
60 categories: [
61 {
62 label: 'Food', filter: { key: '', value: '' }, children:
63 [
64 { label: 'Cafes', filter: { key: 'kinds', value: 'cafes,foods,tourist_facilities' } },
65 { label: 'Restaurants', filter: { key: 'kinds', value: 'restaurants,foods,tourist_facilities' } },
66 { label: 'Restaurants, Historic Architecture', filter: { key: 'kinds', value: 'historic_architecture,architecture,interesting_places,restaurants,foods,tourist_facilities,other_buildings_and_structures' } }
67 ]
68 },
69 {
70 label: 'Visit', filter: { key: '', value: '' }, children:
71 [
72 { label: 'Art Galleries', filter: { key: 'kinds', value: 'national_museums,museums,cultural,interesting_places,art_galleries' } },
73 { label: 'Museums', filter: { key: 'kinds', value: 'museums,cultural,interesting_places,other_museums' } },
74 { label: 'Historic Monuments', filter: { key: 'kinds', value: 'fortifications,historic,monuments_and_memorials,interesting_places,castles,monuments' } }
75 ]
76 }
77 ]
78 }, studioQueryControl);
79
80 const categoryRadioRateFilter = new gem.control.CategoryFilterControl({
81 parentContainer: 'filter-category-rate',
82 name: 'byRate',
83 style: 'radio',
84 title: 'Filter by Rate',
85 categories: [
86 { label: 'any', filter: { key: '', value: '' } },
87 { label: '3', filter: { key: 'rate', value: '3' } },
88 { label: '3h', filter: { key: 'rate', value: '3h' } }
89 ]
90 }, studioQueryControl);
91
92 defaultAppScreen.addControl(distanceFilterControl);
93 defaultAppScreen.addControl(categoryCheckboxFilterControl);
94 defaultAppScreen.addControl(categoryRadioRateFilter);
1<!DOCTYPE html>
2<html lang="en-us">
3 <head>
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1, user-scalable=no, shrink-to-fit=no" />
6 <title>Store Locator Filters Controls - MagicLane Maps SDK for JavaScript</title>
7 <link rel="stylesheet" type="text/css" href="https://www.magiclane.com/sdk/js/gem.css" />
8 <link rel="stylesheet" href="/fonts/webfonts.css" type="text/css" media="all" />
9
10 <style>
11 .filters-container {
12 position: absolute;
13 width: 30%;
14 max-width: 300px;
15 right: 0px;
16 top: 50px;
17 margin: 8px;
18 z-index: 9;
19 font-size: 0.7rem;
20 background-color: white;
21 box-shadow: 0 2px 4px rgb(0 0 0 / 20%), 0 -1px 0 rgb(0 0 0 / 2%);
22 }
23 </style>
24 </head>
25
26 <body>
27 <div id="store-locator" style="width: 100%; height: 100%">
28 <div id="stores-list" class="menu-list-container" style="width: 25%; height: 100%; position: absolute"></div>
29 <div id="map-canvas" style="width: 75%; left: 25%; height: 100%; position: absolute; overflow: hidden">
30 <div id="filters-container" class="filters-container">
31 <div id="filter-category-kind" class="filter-category1"></div>
32 <div id="filter-category-rate" class="filter-category2"></div>
33 <div id="filter-distance" class="filter-distance"></div>
34 </div>
35 </div>
36 </div>
37
38 <script src="https://www.magiclane.com/sdk/js/gemapi.js"></script>
39 <script type="text/javascript" src="token.js"></script>
40 <script type="text/javascript" src="storeFiltersControls03.js"></script>
41 </body>
42</html>
Files ¶
The finished example consists of the project directory containing 2 files:
-
JavaScript code (
.js
file extension) -
HTML code (
.html
file extension)
To run the example, the HTML file is loaded in a browser.
Source code for this example:
JavaScriptHTML
right-click on the links and select Save As.