1use crate::types::*;
2
3pub fn generate_map_id() -> String {
5 format!("dioxus_leaflet_map_{}", fastrand::u32(..))
6}
7
8pub fn generate_map_script(
10 map_id: &str,
11 initial_position: &MapPosition,
12 markers: &[MapMarker],
13 options: &MapOptions,
14) -> String {
15 let markers_json = serde_json::to_string(markers).unwrap_or_else(|_| "[]".to_string());
16 let escaped_markers = escape_json_for_js(&markers_json);
17
18 format!(
19 r#"
20 (function() {{
21 function initializeDioxusLeafletMap() {{
22 function tryInitialize() {{
23 if (typeof L === 'undefined') {{
24 setTimeout(tryInitialize, 100);
25 return;
26 }}
27
28 var mapElement = document.getElementById('{}');
29 if (!mapElement) {{
30 setTimeout(tryInitialize, 100);
31 return;
32 }}
33
34 try {{
35 // Initialize the map with options
36 var map = L.map('{}', {{
37 zoomControl: {},
38 scrollWheelZoom: {},
39 doubleClickZoom: {},
40 touchZoom: {},
41 dragging: {},
42 keyboard: {},
43 attributionControl: {}
44 }}).setView([{}, {}], {});
45
46 // Add tile layer
47 L.tileLayer('{}', {{
48 attribution: '{}',
49 maxZoom: {},
50 subdomains: {}
51 }}).addTo(map);
52
53 // Add markers
54 var markersData = "{}";
55 var markers = JSON.parse(markersData);
56
57 markers.forEach(function(markerData) {{
58 var markerOptions = {{}};
59
60 // Custom icon if provided
61 if (markerData.icon) {{
62 var iconOptions = {{
63 iconUrl: markerData.icon.icon_url
64 }};
65
66 if (markerData.icon.icon_size) {{
67 iconOptions.iconSize = markerData.icon.icon_size;
68 }}
69 if (markerData.icon.icon_anchor) {{
70 iconOptions.iconAnchor = markerData.icon.icon_anchor;
71 }}
72 if (markerData.icon.popup_anchor) {{
73 iconOptions.popupAnchor = markerData.icon.popup_anchor;
74 }}
75 if (markerData.icon.shadow_url) {{
76 iconOptions.shadowUrl = markerData.icon.shadow_url;
77 }}
78 if (markerData.icon.shadow_size) {{
79 iconOptions.shadowSize = markerData.icon.shadow_size;
80 }}
81
82 markerOptions.icon = L.icon(iconOptions);
83 }}
84
85 var marker = L.marker([markerData.lat, markerData.lng], markerOptions).addTo(map);
86
87 // Add popup if title or description exists
88 if (markerData.title || markerData.description) {{
89 var popupContent = '';
90 if (markerData.title) {{
91 popupContent += '<b>' + markerData.title + '</b>';
92 }}
93 if (markerData.description) {{
94 if (markerData.title) popupContent += '<br>';
95 popupContent += markerData.description;
96 }}
97
98 var popupOptions = {{}};
99 if (markerData.popup_options) {{
100 Object.assign(popupOptions, markerData.popup_options);
101 }}
102
103 marker.bindPopup(popupContent, popupOptions);
104 }}
105 }});
106
107 // Force resize to ensure proper display
108 setTimeout(function() {{
109 map.invalidateSize();
110 }}, 100);
111
112 // Store map reference for potential future use
113 window.dioxusLeafletMaps = window.dioxusLeafletMaps || {{}};
114 window.dioxusLeafletMaps['{}'] = map;
115
116 }} catch (error) {{
117 console.error('Error initializing Dioxus Leaflet map:', error);
118 }}
119 }}
120
121 tryInitialize();
122 }}
123
124 // Initialize when DOM is ready
125 if (document.readyState === 'loading') {{
126 document.addEventListener('DOMContentLoaded', initializeDioxusLeafletMap);
127 }} else {{
128 initializeDioxusLeafletMap();
129 }}
130 }})();
131 "#,
132 map_id,
133 map_id,
134 bool_to_js(options.zoom_control),
135 bool_to_js(options.scroll_wheel_zoom),
136 bool_to_js(options.double_click_zoom),
137 bool_to_js(options.touch_zoom),
138 bool_to_js(options.dragging),
139 bool_to_js(options.keyboard),
140 bool_to_js(options.attribution_control),
141 initial_position.lat,
142 initial_position.lng,
143 initial_position.zoom,
144 options.tile_layer.url,
145 options.tile_layer.attribution,
146 options.tile_layer.max_zoom,
147 serde_json::to_string(&options.tile_layer.subdomains).unwrap_or_else(|_| "[]".to_string()),
148 escaped_markers,
149 map_id
150 )
151}
152
153pub fn escape_json_for_js(json: &str) -> String {
155 json.replace('\\', "\\\\")
156 .replace('"', "\\\"")
157 .replace('\n', "\\n")
158 .replace('\r', "\\r")
159 .replace('\t', "\\t")
160}
161
162pub fn bool_to_js(value: bool) -> &'static str {
164 if value { "true" } else { "false" }
165}