PageSourceSearch

https://genatsvale-arbat.com/wp-content/plugins/woo2iiko/src/Featu…/js/iiko-suggestions.js?ver=1791061862

js genatsvale-arbat.com collected 2026-10-04 07:45:58 UTC 12,804 bytes, 324 lines download raw bytes

1/**
2 * iiko Legacy Street Suggestions
3 * Подсказки улиц для legacy режима iiko
4 */
5
6jQuery(document).ready(function ($) {
7    // Проверяем наличие конфигурации
8    if (typeof iikoLegacy === 'undefined') {
9        console.warn('iikoLegacy configuration not found');
10        return;
11    }
12
13    // Сброс поля улицы при смене города
14    $('[name="billing_city"]').on('change', function () {
15        $('[name="billing_street"]').val('').change();
16        $('[name="billing_street_id"]').val('').change();
17    });
18
19    // Инициализация автокомплита для улиц
20    initStreetAutocomplete();
21
22    function initStreetAutocomplete() {
23        let address = $('[name="billing_street"]');
24        
25        if (address.length === 0) {
26            console.log('billing_street field not found');
27            return;
28        }
29
30        // Устанавливаем начальные значения из конфигурации только если поля пустые
31        let streetIdField = $('[name="billing_street_id"]');
32        if (streetIdField.length > 0 && !streetIdField.val()) {
33            streetIdField.val(iikoLegacy.streetId || '');
34        }
35        if (!address.val()) {
36            address.val(iikoLegacy.streetName || '');
37        }
38
39        // Оборачиваем поле в wrapper для правильного позиционирования dropdown
40        if (!address.parent().hasClass('iiko-autocomplete-wrapper')) {
41            address.wrap('<div class="iiko-autocomplete-wrapper"></div>');
42        }
43
44        let wrapper = address.closest('.iiko-autocomplete-wrapper');
45        if (wrapper.length === 0) {
46            console.error('Failed to create wrapper for street autocomplete');
47            return;
48        }
49
50        // Удаляем старый load_info если существует
51        wrapper.next('.load_info').remove();
52        wrapper.after('<div class="load_info"></div>');
53        let load_info = wrapper.next('.load_info');
54
55        let arr_iiko = [];
56        let dropdown = null;
57        let selectedIndex = -1;
58
59        // Создаём dropdown вручную без jQuery UI
60        function createDropdown(items) {
61            // Удаляем старый dropdown если есть
62            if (dropdown) {
63                dropdown.remove();
64            }
65
66            if (items.length === 0) {
67                return null;
68            }
69
70            dropdown = $('<ul class="iiko-suggestions-dropdown"></ul>');
71
72            items.forEach(function(item, index) {
73                let displayText = item.name || item; // Поддержка обоих форматов
74                let itemId = item.id || index;
75
76                let li = $('<li class="suggestion-item"></li>')
77                    .text(displayText)
78                    .data('index', index)
79                    .data('id', itemId)
80                    .data('value', displayText)
81                    .on('click', function() {
82                        selectStreet(index, itemId, displayText);
83                    })
84                    .on('mouseenter', function() {
85                        dropdown.find('.suggestion-item').removeClass('active');
86                        $(this).addClass('active');
87                        selectedIndex = index;
88                    });
89
90                dropdown.append(li);
91            });
92
93            wrapper.append(dropdown);
94            selectedIndex = -1;
95            return dropdown;
96        }
97
98        function selectStreet(index, streetId, streetName) {
99            if (arr_iiko[index]) {
100                console.log('Selected street:', {index: index, id: streetId, name: streetName});
101                address.val(streetName);
102                
103                // Установка ID улицы
104                let streetIdField = $('[name="billing_street_id"]');
105                if (streetIdField.length > 0) {
106                    streetIdField.val(streetId).change();
107                }
108                
109                // Установка адреса
110                let addressField = $('[name="billing_address_1"]');
111                if (addressField.length > 0) {
112                    addressField.val(streetName).change();
113                }
114                
115                // Очистка координат
116                let coordField = $('[name="billing_coordinates"]');
117                if (coordField.length > 0) {
118                    coordField.val('').change();
119                }
120                
121                hideDropdown();
122
123                // 1. Сначала устанавливаем billing_delivery_type = '0' (доставка) в DOM
124                // Это критично чтобы сервер получил правильное значение при AJAX запросе
125                if (typeof window.iikoSetDeliveryTypeValue === 'function') {
126                    window.iikoSetDeliveryTypeValue('0', false);
127                } else {
128                    var $deliveryTypeField = $('[name="billing_delivery_type"], #delivery_type, [name="delivery_type"]');
129                    $deliveryTypeField.filter('select, input[type="hidden"]').val('0');
130                    $deliveryTypeField.filter('input[type="radio"][value="
1300"]').prop('checked', true);
131                }
132                console.log('iiko Suggestions: billing_delivery_type selected as delivery');
133
134                // 2. Переключаем WC-метод доставки на доставку, чтобы WC не вернул local_pickup из сессии
135                if (typeof chooseWooShippingByDeliveryType === 'function') {
136                    chooseWooShippingByDeliveryType('0'); // 0 = доставка
137                    console.log('iiko Suggestions: chooseWooShippingByDeliveryType(0) called');
138                }
139
140                // 3. Даём время на обновление DOM и сессии, затем вызываем update_checkout
141                setTimeout(function() {
142                    $(document.body).trigger('update_checkout');
143                    console.log('iiko Suggestions: update_checkout triggered');
144                }, 50);
145            } else {
146                console.warn('Street not found in arr_iiko at index:', index);
147            }
148        }
149
150        function hideDropdown() {
151            if (dropdown) {
152                dropdown.hide();
153            }
154        }
155
156        function showDropdown() {
157            if (dropdown) {
158                dropdown.show();
159            }
160        }
161
162        // Обработка ввода с debounce
163        let searchTimeout;
164        address.on('input', function() {
165            let query = $(this).val().trim();
166
167            // Если поле содержит полный адрес (с номером дома), и пользователь вводит короткий текст (вероятно новую улицу),
168            // очистим поле от старого полного адреса
169            if (query.length >= 2 && query.length < 10 && !/\d/.test(query) && /\s+(?:д|дом|д\.)\s+\d+/i.test(address.val())) {
170                address.val(query);
171            }
172
173            // Очищаем предыдущий таймер
174            if (searchTimeout) {
175                clearTimeout(searchTimeout);
176            }
177
178            if (query.length < 2) {
179                hideDropdown();
180                load_info.empty();
181                return;
182            }
183
184            load_info.text(iikoLegacy.i18n.searching);
185
186            // Добавляем debounce для оптимизации
187            searchTimeout = setTimeout(function() {
188                performSearch(query);
189            }, 300);
190        });
191
192        function performSearch(query) {
193            // iiko Legacy не поддерживает REST API геокодирования
194            // Используем только старый AJAX обработчик
195            performLegacySearch(query);
196        }
197
198        function performLegacySearch(query) {
199            $.ajax({
200                url: iikoLegacy.ajaxUrl,
201                method: 'post',
202                dataType: 'json',
203                data: {
204                    action: 'kladr_street',
205                    city: $('[name="billing_city"] option:selected').val(),
206                    street: query,
207                    nonce: iikoLegacy.nonce,
208                },
209                cache: true,
210                timeout: 5000
211            }).done(function (data) {
212                // Преобразуем в формат REST API
213                let response = {
214                    success: true,
215                    data: {
216                        suggestions: []
217                    }
218                };
219
220                if (Array.isArray(data)) {
221                    response.data.suggestions = data.map(function(item) {
222                        return {
223                            value: item.name || item,
224                            data: {
225                                id: item.id || '',
226                                name: item.name || item
227                            }
228                        };
229                    });
230                } else if (typeof data === 'object') {
231                    // Объект вида {id: name, id: name, ...}
232                    for (let id in data) {
233                        if (data.hasOwnProperty(id)) {
234                            response.data.suggestions.push({
235                                value: data[id],
236                                data: {
237                                    id: id,
238                                    name: data[id]
239                                }
240                            });
241                        }
242                    }
243                }
244
245                handleSearchResponse(response);
246            }).fail(function(jqXHR, textStatus, errorThrown) {
247                console.error('Legacy AJAX search error:', textStatus, errorThrown);
248                showSearchError();
249            });
250        }
251
252        function handleSearchResponse(response) {
253            let items = [];
254            
255            if (response.success && response.data && response.data.suggestions) {
256                items = response.data.suggestions.map(function(suggestion) {
257                    return {
258                        id: suggestion.data.id,
259                        name: suggestion.value
260                    };
261                });
262            }
263
264            arr_iiko = items;
265            console.log('Street search response:', response, 'Items:', items);
266
267            if (!items || items.length === 0) {
268                load_info.html(
269                    '<span style="color:red;">
269' + iikoLegacy.i18n.notFound + '</span>'
270                );
271                hideDropdown();
272            } else {
273                load_info.empty().hide();
274                createDropdown(items);
275                showDropdown();
276            }
277        }
278
279        function showSearchError() {
280            load_info.html(
281                '<span style="color:red;">' + iikoLegacy.i18n.searchError + '</span>'
282            );
283            hideDropdown();
284        }
285
286        // Обработка клавиш
287        address.on('keydown', function(e) {
288            if (!dropdown || dropdown.is(':hidden')) {
289                return;
290            }
291
292            let items = dropdown.find('.suggestion-item');
293
294            if (e.keyCode === 40) { // Arrow Down
295                e.preventDefault();
296                selectedIndex = Math.min(selectedIndex + 1, items.length - 1);
297                items.removeClass('active').eq(selectedIndex).addClass('active');
298            } else if (e.keyCode === 38) { // Arrow Up
299                e.preventDefault();
300                selectedIndex = Math.max(selectedIndex - 1, -1);
301                if (selectedIndex >= 0) {
302                    items.removeClass('active').eq(selectedIndex).addClass('active');
303                } else {
304                    items.removeClass('active');
305                }
306            } else if (e.keyCode === 13) { // Enter
307                e.preventDefault();
308                if (selectedIndex >= 0 && arr_iiko[selectedIndex]) {
309                    let item = arr_iiko[selectedIndex];
310                    selectStreet(selectedIndex, item.id, item.name);
311                }
312            } else if (e.keyCode === 27) { // Escape
313                hideDropdown();
314            }
315        });
316
317        // Закрытие при клике вне
318        $(document).on('click', function(e) {
319            if (!$(e.target).closest('.iiko-autocomplete-wrapper').length) {
320                hideDropdown();
321            }
322        });
323    }
324});

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.