]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/user.js
Merge remote-tracking branch 'upstream/pull/7053'
[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, lng } = OSM.cropLocation(L.latLng(e.lngLat.lat, e.lngLat.lng), map.getZoom() + 1);
74       $("#home_lat").val(lat);
75       $("#home_lon").val(lng);
76
77       clearDeletedText();
78       respondToHomeLatLonUpdate();
79     });
80     map.on("moveend", function () {
81       const lat = $("#home_lat").val().trim(),
82             lon = $("#home_lon").val().trim();
83       let location;
84
85       try {
86         if (lat && lon) {
87           location = new maplibregl.LngLat(lon, lat);
88         }
89       } catch (error) {
90         // keep location undefined
91       }
92
93       $("#home_show").prop("disabled", !location || isCloseEnoughToMapCenter(location));
94     });
95
96     $("#home_lat, #home_lon").on("input", function () {
97       clearDeletedText();
98       respondToHomeLatLonUpdate();
99     });
100
101     $("#home_location_name").on("input", function () {
102       homeLocationNameGeocoder.autofill = false;
103       clearDeletedText();
104
105       respondToHomeLatLonUpdate(false);
106     });
107
108     $("#home_show").click(function () {
109       const lat = $("#home_lat").val(),
110             lon = $("#home_lon").val();
111
112       map.flyTo({ center: [lon, lat], zoom: OSM.MapLibre.defaultHomeZoom });
113     });
114
115     $("#home_delete").click(function () {
116       const lat = $("#home_lat").val(),
117             lon = $("#home_lon").val(),
118             locationName = $("#home_location_name").val();
119
120       $("#home_lat, #home_lon, #home_location_name").val("");
121       deleted_lat = lat;
122       deleted_lon = lon;
123       deleted_home_name = locationName;
124
125       respondToHomeLatLonUpdate(false);
126       $("#home_undelete").trigger("focus");
127     });
128
129     $("#home_undelete").click(function () {
130       $("#home_lat").val(deleted_lat);
131       $("#home_lon").val(deleted_lon);
132       $("#home_location_name").val(deleted_home_name);
133       clearDeletedText();
134
135       respondToHomeLatLonUpdate(false);
136       $("#home_delete").trigger("focus");
137     });
138   }
139
140   function respondToHomeLatLonUpdate(updateLocationName = true) {
141     const lat = $("#home_lat").val().trim(),
142           lon = $("#home_lon").val().trim(),
143           locationName = $("#home_location_name").val().trim();
144     let location;
145
146     try {
147       if (lat && lon) {
148         location = new maplibregl.LngLat(lon, lat);
149         if (updateLocationName) {
150           if (savedLat && savedLon && $("#home_location_name").val().trim()) {
151             homeLocationNameGeocoder.updateHomeLocationName(false, savedLat, savedLon, () => {
152               savedLat = savedLon = null;
153               homeLocationNameGeocoder.updateHomeLocationName();
154             });
155           } else {
156             savedLat = savedLon = null;
157             homeLocationNameGeocoder.updateHomeLocationName();
158           }
159         }
160       }
161       $("#home_lat, #home_lon").removeClass("is-invalid");
162     } catch (error) {
163       if (lat && isNaN(lat)) $("#home_lat").addClass("is-invalid");
164       if (lon && isNaN(lon)) $("#home_lon").addClass("is-invalid");
165     }
166
167     $("#home_message").toggleClass("invisible", Boolean(location));
168     $("#home_show").prop("hidden", !location);
169     $("#home_delete").prop("hidden", !location && !locationName);
170     $("#home_undelete").prop("hidden", !(
171       (!location || !locationName) &&
172       ((deleted_lat && deleted_lon) || deleted_home_name)
173     ));
174     if (location) {
175       marker.setLngLat([lon, lat]);
176       marker.addTo(map);
177       map.panTo([lon, lat]);
178     } else {
179       marker.remove();
180     }
181   }
182
183   function isCloseEnoughToMapCenter(location) {
184     const inputPt = map.project(location);
185     const centerPt = map.project(map.getCenter());
186
187     return centerPt.dist(inputPt) < 10;
188   }
189
190   function clearDeletedText() {
191     deleted_lat = null;
192     deleted_lon = null;
193     deleted_home_name = null;
194   }
195
196   $("input#user_avatar").on("change", function () {
197     $("#user_avatar_action_new").prop("checked", true);
198   });
199
200   $("#content.user_confirm").each(function () {
201     $(this).hide();
202     $(this).find("#confirm").submit();
203   });
204
205   $("input[name=legale]").change(function () {
206     $("#contributorTerms").html("<div class='spinner-border' role='status'><span class='visually-hidden'>" + OSM.i18n.t("browse.start_rjs.loading") + "</span></div>");
207     fetch(this.dataset.url, { headers: { "x-requested-with": "XMLHttpRequest" } })
208       .then(r => r.text())
209       .then(html => { $("#contributorTerms").html(html); });
210   });
211
212   $("#read_ct").on("click", function () {
213     $("#continue").prop("disabled", !($(this).prop("checked") && $("#read_tou").prop("checked")));
214   });
215
216   $("#read_tou").on("click", function () {
217     $("#continue").prop("disabled", !($(this).prop("checked") && $("#read_ct").prop("checked")));
218   });
219 });