PageSourceSearch

https://gorodtokyo.ru/js/select-address.js?20261008155623

js gorodtokyo.ru collected 2026-10-08 13:53:42 UTC 9,497 bytes, 314 lines download raw bytes

1window.SelectAddressBlock = (function() {
2  const handlers = {
3    submit: function() { submit() },
4    change: function() { removeSuccess() }
5  };
6  // 0 - dataset.elem, 1 - òåêñòîâîå îáîçíà÷åíèå (åñëè íåò - â òåêñò íå äîáàâèòñÿ), òåêñò ñîñòàâèòñÿ ïî ïîðÿäêó ìàññèâà
7  const flatFieldsHelper = [
8    ['flat', 'êâ.'],
9    ['pod', 'ïîäúåçä'],
10    ['floor', 'ýòàæ'],
11    ['domophone', 'äîìîôîí'],
12    ['comment']
13  ];
14
15  let block, elements, map, suggestView, 
16    fields, flatFields, coords,
17    isSubmit, isSuccess;
18
19  function init() {
20    block = document.getElementById('selectAddressBlock');
21    if (!block) return;
22    elements = {};
23    [...block.querySelectorAll('[data-elem]')].forEach(el => elements[el.dataset.elem] = el);
24
25    $(block).on('click', '[data-action]', function(e) {
26      if (isSubmit) return;
27      const action = this.dataset.action;
28      action in handlers && handlers[action].call(this, e);
29    });
30
31    map = suggestView = null;
32    coords = elements.coords && elements.coords.value.split(' ');
33    isSuccess = block.classList.contains('is-success');
34    !isSuccess && initMapAndInput();
35  }
36
37  function initMapAndInput(query) {
38    query = query || coords || elements.addressString.textContent || $.cookie('city_name');
39
40    if (query) {
41      ymaps.geocode(query, {results: 1}).then(res => {
42        const geoObject = res.geoObjects.get(0);
43        if (!geoObject) {
44          initMap() && initInput();
45          return;
46        }
47        handleGeoObject(geoObject);
48        initMap(coords, fields.house ? 16 : 11);
49        initInput();
50        addPlacemark(geoObject);
51        elements.input.value = fields.text;
52      }).catch(err => alert(err.message));
53    } else {
54      initMap();
55      initInput();
56    }
57  }
58
59  function initMap(center = [55.755864, 37.617698], zoom = 11) {
60    if (!elements.map) return;
61
62    map = new ymaps.Map(elements.map, {
63      center,
64      zoom,
65      controls: ['geolocationControl', 'zoomControl']
66    }, {
67      suppressMapOpenBlock: true
68    });
69
70    map.events.add('click', function(e) {
71      ymaps.geocode(e.get('coords'), {kind: 'house', results: 1}).then(res => {
72        const geoObject = res.geoObjects.get(0);
73        if (!geoObject) return;
74        handleGeoObject(geoObject);
75        elements.input.value = fields.text;
76        return map.panTo(coords).then(() => map.getZoom() < 16 && map.setZoom(16));
77      }).catch(err => alert(err));
78    });
79
80    map.cursors.push('arrow');
81    return map;
82  }
83
84  function initInput() {
85    if (!elements.input) return;
86    elements.input.disabled = false;
87    suggestView = new ymaps.SuggestView(elements.input);
88    
89    suggestView.events.add('select', function(e) {
90      ymaps.geocode(e.get('item').value, {results: 1}).then(res => {
91        const geoObject = res.geoObjects.get(0);
92        if (!geoObject) return;
93        handleGeoObject(geoObject);
94        // map.setCenter(coords, fields.house ? 16 : 11);
95        return map.setBounds(geoObject.properties.get('boundedBy'));
96      }).catch(err => alert(err));
97    });
98  }
99
100  function handleGeoObject(geoObject) {
101    coords = geoObject.geometry.getCoordinates();
102    makeFields(geoObject);
103    updateElements();
104    addPlacemark(geoObject);
105  }
106
107  function makeFields(geoObject) {
108    fields = { text: geoObject.properties.get('text') };
109    geoObject.properties.get('metaDataProperty.GeocoderMetaData.Address.Components').forEach(({kind, name}) => {
110      fields[kind] = fields[kind] ? fields[kind]+', '+name : name
111    });
112  }
113
114  function updateElements() {
115    elements.btn.disabled = !fields.house;
116    elements.flatFields.hidden = !fields.house;
117    map && clearFlatFields();
118  }
119
120  function addPlacemark(geoObject) {
121    if (!map) {
122      return;
123    }
124    // geoObject.balloon.destroy();
125    geoObject.properties.set('iconCaption', geoObject.properties.get('name'));
126    map.geoObjects.getLength() && map.geoObjects.removeAll();
127    map.geoObjects.add(geoObject);
128  }
129
130  function makeFlatFields() {
131    flatFields = { text: '' };
132
133    flatFieldsHelper.forEach(([name, type]) => {
134      const val = elements[name] && elements[name].value || '';
135      flatFields[name] = val;
136      if (!type || !val) return;
137      flatFields.text = flatFields.text ? flatFields.text+', '+type+' '+val : type+' '+val;
138    });
139  }
140
141  function clearFlatFields() {
142    flatFields = null;
143    flatFieldsHelper.forEach(([name, type]) => elements[name] && (elements[name].value = ''));
144  }
145
146  function addSuccess() {
147    let text = fields.text;
148    if (flatFields && flatFields.text) text += ', '+flatFields.text;
149    elements.addressString.textContent = text;
150    destroyMapView();
151    block.classList.add('is-success');
152    isSuccess = true;
153    S2UBasket.prototype.updateDeliveryPayButtonDisabled();
154  }
155
156  function removeSuccess() {
157    isSuccess = false;
158    block.classList.remove('is-success');
159    initMapAndInput();
160    S2UBasket.prototype.updateDeliveryPayButtonDisabled();
161  }
162
163  function destroyMapView() {
164    map && map.destroy();
165    map = null;
166    suggestView && suggestView.destroy();
167    suggestView = null;
168    elements.input.disabled = true;
169    elements.btn.disabled = true;
170  }
171
172  function destroy() {
173    map && destroyMapView();
174    $(block).off('click');
175  }
176
177  function save(city_id) {
178    fields.city_id = city_id;
179    return new S2UAjax("S2U::Gorodtokyo::Frame::FO::BasketMapAddress", "set_address_from_map").addParams({
180      'area_map': fields.area || '',
181      'city_map': fields.locality || '',
182      'street_map': fields.street || fields.district || '',
183      'dom_map': fields.house || '',
184      'city_id_map': fields.city_id || '',
185      'coords': coords ? coords[0]+' '+coords[1] : '',
186      'flat': flatFields.flat,
187      'pod': flatFields.pod,
188      'floor': flatFields.floor,
189      'domophone': flatFields.domophone,
190      'comment': flatFields.comment
191    }).send();
192  }
193
194  function changeCity(id, name) {
195    destroy();
196    S2UCity.prototype.setCookie(id, name);
197    S2UCity.prototype.setCity();
198    S2UBasket.prototype.reloadDeliveryPay($());
199  }
200
201  function truncateString(str) {
202    return str.length > 13 ? str.slice(0, 13) : str;
203  }
204
205  function getDadata(api, data) {
206    data.count = 1;
207
208    return $.ajax({
209      method: 'POST',
210      url: 'https://suggestions.dadata.ru/suggestions/api/4_1/rs/'+api,
211      data: JSON.stringify(data),
212      headers: {
213        "Content-Type": "application/json",
214        "Accept": "application/json",
215        "Authorization": "Token " + "0206a6952c3be1d3e9df35f75d74a535fd0d16a0"
216      }
217    }).then(res => {
218      return res.suggestions.length ? res.suggestions[0].data : null;
219    });
220  }
221
222  function submit() {
223    if (isSubmit || !fields.house || !coords) return;
224    isSubmit = true;
225    block.classList.add('is-submit');
226
227    // ñíà÷àëà íóæíî ïîëó÷èòü êëàäð
228    getDadata('geolocate/address', { lat: coords[0], lon: coords[1] })
229
230    // íàøëè - îê, íåò - ïðîáóåì ïîëó÷èòü ÷åðåç àïè ïîäñêàçîê ïî ñòðîêå
231    .then(res => {
232      if (res && res.city_kladr_id) {
233        return res.city_kladr_id;
234      }
235
236      // ïðîáóåì suggestions
237      return getDadata('suggest/address', { query: fields.text })
238        .then(res => {
239
240          if (res) {
241            return truncateString(
242              res.city_kladr_id ||
243              res.settlement_kladr_id ||
244              res.kladr_id
245            );
246          }
247
248          // åñëè suggestions íè÷åãî íå âåðíóë —
249          // ïðîáóåì ñåðâåðíûé ìåòîä
250          return new S2UAjax(
251            "S2U::Gorodtokyo::Frame::FO::BasketMapAddress",
252            "get_info_dadata"
253          )
254          .addParams({
255            address_text: fields.text || ''
256          })
257          .send()
258          .then(res => {
259
260            if (!res) return null;
261
262            const kladr =
263              res.city_kladr_id ||
264              res.settlement_kladr_id ||
265              res.kladr_id;
266
267            if (!kladr) return null;
268
269            return truncateString(kladr);
270          });
271        });
272    })
273
274    // ïîòîì ïðîâåðèòü êëàäð
275    .then(res => {
276      if (!res) {
277        return { success: 0, msg: 'Êóðüåðñêàÿ äîñòàâêà íà ýòîò àäðåñ íå îñóùåñòâëÿåòñÿ. Âûáåðèòå áëèæàéøèé íàñåëåííûé ïóíêò.' };
278      }
279
280      return new S2UAjax('S2U::Frame::FO::RussianPost::PostalCode', 'get_city_info_by_kladr_id').addParams({
281        kladr_id: res
282      }).send();
283    })
284
285    // åñëè íå íàéäåí - âûõîäèì, åñëè íàéäåí - ñîõðàíÿåì, ïîòîì ôèêñèðóåì àäðåñ è ìåíÿåì ãîðîä
286    .then(res => {
287      if (res.success != 1) {
288        alert(res.msg || 'Êóðüåðñêàÿ äîñòàâêà íà ýòîò àäðåñ íå îñóùåñòâëÿåòñÿ.\nÂûáåðèòå áëèæàéøèé íàñåëåííûé ïóíêò.');
289        return;
290      }
291
292      makeFlatFields();
293
294      return save(res.city_id).done(() => {
295        addSuccess();
296        ($.cookie('city_id') != res.city_id)
297          ? changeCity(res.city_id, res.city_name)
298          : S2UBasket.prototype.getSaveDeliveryAdditionalBlockS2UAjax().send();
299      });
300    })
301
302    // ñíèìàåì ñîñòîÿíèå îòïðàâêè
303    .always(() => {
304      block.classList.remove('is-submit');
305      isSubmit = false;
306    })
307
308    .fail(function() {
309      console.log('Submit fail', arguments);
310    });
311  }
312
313  return { init, destroy, isSuccess: () => isSuccess }
314})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.