]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/user.js
Restructure maplibre requiring hierarchy
[rails.git] / app / assets / javascripts / user.js
1 //= require maplibre/map
2 //= require ./home_location_name-endpoint
3
4 $(function () {
5   let map, marker, deleted_lat, deleted_lon, deleted_home_name, homeLocationNameGeocoder, savedLat, savedLon;
6
7   if ($("#social_links").length) {
8     $("#add-social-link").on("click", function () {
9       const newIndex = -Date.now();
10
11       $("#social_links template").contents().clone().appendTo("#social_links")
12         .find("input").attr("name", `user[social_links_attributes][${newIndex}][url]`).trigger("focus");
13
14       renumberSocialLinks();
15     });
16
17     $("#social_links").on("click", "button", function () {
18       const row = $(this).closest(".row");
19       const [destroyCheckbox] = row.find(".social_link_destroy input[type='checkbox']");
20
21       if (destroyCheckbox) {
22         destroyCheckbox.checked = true;
23         row.addClass("d-none");
24       } else {
25         row.remove();
26       }
27
28       renumberSocialLinks();
29     });
30
31     $(".social_link_destroy input[type='checkbox']:checked").each(function () {
32       $(this).closest(".row").addClass("d-none");
33     });
34
35     renumberSocialLinks();
36   }
37
38   function renumberSocialLinks() {
39     $("#social_links .row:not(.d-none)").each(function (i) {
40       const inputLabel = OSM.i18n.t("javascripts.profile.social_link_n", { n: i + 1 });
41       const removeButtonLabel = OSM.i18n.t("javascripts.profile.remove_social_link_n", { n: i + 1 });
42
43       $(this).find("input[type='text']")
44         .attr("placeholder", inputLabel)
45         .attr("aria-label", inputLabel);
46       $(this).find("button")
47         .attr("title", removeButtonLabel);
48     });
49   }
50
51   if ($("#map").length) {
52     map = new OSM.MapLibre.SecondaryMap();
53
54     savedLat = $("#home_lat").val();
55     savedLon = $("#home_lon").val();
56     homeLocationNameGeocoder = OSM.HomeLocationNameGeocoder($("#home_lat"), $("#home_lon"), $("#home_location_name"));
57
58     const position = $("html").attr("dir") === "rtl" ? "top-left" : "top-right";
59     const navigationControl = new OSM.MapLibre.NavigationControl();
60     const geolocateControl = new OSM.MapLibre.GeolocateControl();
61     map.addControl(new OSM.MapLibre.CombinedControlGroup([navigationControl, geolocateControl]), position);
62
63     marker = new OSM.MapLibre.Marker();
64
65     if (OSM.home) {
66       marker.setLngLat([OSM.home.lon, OSM.home.lat]);
67       marker.addTo(map);
68     }
69
70     map.on("click", function (e) {
71       if (!$("#updatehome").is(":checked")) return;
72
73       const [lat, lon] = OSM.cropLocation(e.lngLat, map.getZoom() + 1);
74
75       $("#home_lat").val(lat);
76       $("#home_lon").val(lon);
77
78       clearDeletedText();
79       respondToHomeLatLonUpdate();
80     });
81     map.on("moveend", function () {
82       const lat = $("#home_lat").val().trim(),
83             lon = $("#home_lon").val().trim();
84       let location;
85
86       try {
87         if (lat && lon) {
88           location = new maplibregl.LngLat(lon, lat);
89         }
90       } catch (error) {
91         // keep location undefined
92       }
93
94       $("#home_show").prop("disabled", !location || isCloseEnoughToMapCenter(location));
95     });
96
97     $("#home_lat, #home_lon").on("input", function () {
98       clearDeletedText();
99       respondToHomeLatLonUpdate();
100     });
101
102     $("#home_location_name").on("input", function () {
103       homeLocationNameGeocoder.autofill = false;
104       clearDeletedText();
105
106       respondToHomeLatLonUpdate(false);
107     });
108
109     $("#home_show").click(function () {
110       const lat = $("#home_lat").val(),
111             lon = $("#home_lon").val();
112
113       map.flyTo({ center: [lon, lat], zoom: OSM.MapLibre.defaultHomeZoom });
114     });
115
116     $("#home_delete").click(function () {
117       const lat = $("#home_lat").val(),
118             lon = $("#home_lon").val(),
119             locationName = $("#home_location_name").val();
120
121       $("#home_lat, #home_lon, #home_location_name").val("");
122       deleted_lat = lat;
123       deleted_lon = lon;
124       deleted_home_name = locationName;
125
126       respondToHomeLatLonUpdate(false);
127       $("#home_undelete").trigger("focus");
128     });
129
130     $("#home_undelete").click(function () {
131       $("#home_lat").val(deleted_lat);
132       $("#home_lon").val(deleted_lon);
133       $("#home_location_name").val(deleted_home_name);
134       clearDeletedText();
135
136       respondToHomeLatLonUpdate(false);
137       $("#home_delete").trigger("focus");
138     });
139   }
140
141   function respondToHomeLatLonUpdate(updateLocationName = true) {
142     const lat = $("#home_lat").val().trim(),
143           lon = $("#home_lon").val().trim(),
144           locationName = $("#home_location_name").val().trim();
145     let location;
146
147     try {
148       if (lat && lon) {
149         location = new maplibregl.LngLat(lon, lat);
150         if (updateLocationName) {
151           if (savedLat && savedLon && $("#home_location_name").val().trim()) {
152             homeLocationNameGeocoder.updateHomeLocationName(false, savedLat, savedLon, () => {
153               savedLat = savedLon = null;
154               homeLocationNameGeocoder.updateHomeLocationName();
155             });
156           } else {
157             savedLat = savedLon = null;
158             homeLocationNameGeocoder.updateHomeLocationName();
159           }
160         }
161       }
162       $("#home_lat, #home_lon").removeClass("is-invalid");
163     } catch (error) {
164       if (lat && isNaN(lat)) $("#home_lat").addClass("is-invalid");
165       if (lon && isNaN(lon)) $("#home_lon").addClass("is-invalid");
166     }
167
168     $("#home_message").toggleClass("invisible", Boolean(location));
169     $("#home_show").prop("hidden", !location);
170     $("#home_delete").prop("hidden", !location && !locationName);
171     $("#home_undelete").prop("hidden", !(
172       (!location || !locationName) &&
173       ((deleted_lat && deleted_lon) || deleted_home_name)
174     ));
175     if (location) {
176       marker.setLngLat([lon, lat]);
177       marker.addTo(map);
178       map.panTo([lon, lat]);
179     } else {
180       marker.remove();
181     }
182   }
183
184   function isCloseEnoughToMapCenter(location) {
185     const inputPt = map.project(location);
186     const centerPt = map.project(map.getCenter());
187
188     return centerPt.dist(inputPt) < 10;
189   }
190
191   function clearDeletedText() {
192     deleted_lat = null;
193     deleted_lon = null;
194     deleted_home_name = null;
195   }
196
197   $("input#user_avatar").on("change", function () {
198     $("#user_avatar_action_new").prop("checked", true);
199   });
200
201   $("#content.user_confirm").each(function () {
202     $(this).hide();
203     $(this).find("#confirm").submit();
204   });
205
206   $("input[name=legale]").change(function () {
207     $("#contributorTerms").html("<div class='spinner-border' role='status'><span class='visually-hidden'>" + OSM.i18n.t("browse.start_rjs.loading") + "</span></div>");
208     fetch(this.dataset.url, { headers: { "x-requested-with": "XMLHttpRequest" } })
209       .then(r => r.text())
210       .then(html => { $("#contributorTerms").html(html); });
211   });
212
213   $("#read_ct").on("click", function () {
214     $("#continue").prop("disabled", !($(this).prop("checked") && $("#read_tou").prop("checked")));
215   });
216
217   $("#read_tou").on("click", function () {
218     $("#continue").prop("disabled", !($(this).prop("checked") && $("#read_ct").prop("checked")));
219   });
220 });