PageSourceSearch

https://rowaves.com/wp-content/plugins/woot-ro/public/js/woot-city.js?ver=2.3.1

js rowaves.com collected 2026-10-08 07:40:37 UTC 6,759 bytes, 242 lines download raw bytes

1/**
2 * Woot.ro City Dropdown Handler
3 *
4 * Handles city dropdown based on country and county selection.
5 * County -> City cascade with AJAX loading.
6 */
7(function ($) {
8    'use strict';
9
10    if (typeof woot_city_params === 'undefined') {
11        return;
12    }
13
14    var params = woot_city_params;
15    var countriesWithCities = params.countries_with_cities || [];
16    var i18nSelectCity = params.i18n_select_city || 'Select a city…';
17    var i18nLoading = params.i18n_loading || 'Loading…';
18    var isInitialLoad = true;
19
20    /**
21     * Check if country has city nomenclature
22     */
23    function hasCities(countryCode) {
24        return countryCode && countriesWithCities.indexOf(countryCode.toUpperCase()) !== -1;
25    }
26
27    /**
28     * Get field elements for a prefix (billing/shipping)
29     */
30    function getFields(prefix) {
31        return {
32            country: $('#' + prefix + '_country'),
33            state: $('#' + prefix + '_state'),
34            city: $('#' + prefix + '_city')
35        };
36    }
37
38    /**
39     * Initialize selectWoo on a select element
40     */
41    function initSelectWoo($select) {
42        if (!$select.length || !$select.is('select')) {
43            return;
44        }
45
46        var selectFn = $.fn.selectWoo || $.fn.select2;
47        if (!selectFn) {
48            return;
49        }
50
51        try {
52            if ($select.data('select2')) {
53                $select.select2('destroy');
54            }
55        } catch (e) {}
56
57        selectFn.call($select, {
58            placeholder: $select.data('placeholder') || i18nSelectCity,
59            allowClear: true,
60            width: '100%'
61        });
62    }
63
64    /**
65     * Convert city field to select if it's a text input
66     */
67    function ensureSelect($field) {
68        if ($field.is('select')) {
69            return $field;
70        }
71
72        var $select = $('<select>')
73            .attr('name', $field.attr('name'))
74            .attr('id', $field.attr('id'))
75            .addClass('woot-city-select input-text')
76            .attr('data-placeholder', i18nSelectCity)
77            .html('<option value=""></option>');
78
79        $field.replaceWith($select);
80        return $('#' + $field.attr('id'));
81    }
82
83    /**
84     * Convert city field to text input
85     */
86    function ensureTextInput($field) {
87        if ($field.is('input[type="text"]')) {
88            return $field;
89        }
90
91        var currentVal = $field.val() || '';
92
93        try {
94            if ($field.data('select2')) {
95                $field.select2('destroy');
96            }
97        } catch (e) {}
98
99        var $input = $('<input type="text">')
100            .attr('name', $field.attr('name'))
101            .attr('id', $field.attr('id'))
102            .addClass('input-text')
103            .val(currentVal);
104
105        $field.replaceWith($input);
106        return $('#' + $field.attr('id'));
107    }
108
109    /**
110     * Load cities for a prefix
111     */
112    function loadCities(prefix, savedValue) {
113        var fields = getFields(prefix);
114        if (!fields.city.length) {
115            return;
116        }
117
118        var country = fields.country.val() || '';
119        var state = fields.state.val() || '';
120
121        // Country without city nomenclature - use text input
122        if (!hasCities(country)) {
123            ensureTextInput(fields.city);
124            return;
125        }
126
127        // Ensure it's a select
128        var $select = ensureSelect(fields.city);
129
130        // No state selected - disable and show placeholder
131        if (!state) {
132            $select.html('<option value=""></option>');
133            $select.prop('disabled', true).val('');
134            initSelectWoo($select);
135            return;
136        }
137
138        // Load cities via AJAX
139        $select.prop('disabled', true);
140        $select.html('<option value="">' + i18nLoading + '</option>');
141
142        try {
143            if ($select.data('select2')) {
144                $select.select2('destroy');
145            }
146        } catch (e) {}
147
148        $.post(params.ajax_url, {
149            action: 'woot_get_cities',
150            country: country,
151            state: state
152        }, function (response) {
153            var html = '<option value=""></option>';
154
155            if (response.success && response.data && response.data.cities) {
156                response.data.cities.forEach(function (city) {
157                    html += '<option value="' + $('<div>').text(city).html() + '">' + $('<div>').text(city).html() + '</option>';
158                });
159            }
160
161            $select.html(html);
162            $select.prop('disabled', false);
163
164            if (savedValue) {
165                $select.val(savedValue);
166            }
167
168            initSelectWoo($select);
169            $select.trigger('change');
170        });
171    }
172
173    /**
174     * Handle state/country change
175     */
176    function onFieldChange(prefix) {
177        if (isInitialLoad) {
178            return;
179        }
180        loadCities(prefix, '');
181    }
182
183    /**
184     * Initialize
185     */
186    function init() {
187        ['billing', 'shipping'].forEach(function (prefix) {
188            var fields = getFields(prefix);
189            if (!fields.city.length) {
190                return;
191            }
192
193            var country = fields.country.val() || '';
194            var savedValue = fields.city.data('saved-value') || fields.city.val() || '';
195
196            if (hasCities(country)) {
197                loadCities(prefix, savedValue);
198            }
199        });
200
201        // Mark initial load complete after a delay
202        setTimeout(function () {
203            isInitialLoad = false;
204        }, 500);
205    }
206
207    // Document ready
208    $(function () {
209        // Event handlers
210        $(document.body).on('change', '#billing_state', function () {
211            onFieldChange('billing');
212        });
213
214        $(document.body).on('change', '#shipping_state', function () {
215            onFieldChange('shipping');
216        });
217
218        $(document.body).on('change', '#billing_country, #shipping_country', function () {
219            var prefix = this.id.replace('_country', '');
220            onFieldChange(prefix);
221        });
222
223        $(document.body).on('country_to_state_changed', function (event, countryCode, $container) {
224            void event; void countryCode; // Unused but required by WooCommerce event signature
225            var prefix = $container.find('#billing_country').length ? 'billing' : 'shipping';
226            onFieldChange(prefix);
227        });
228
229        // Reinitialize selectWoo after checkout updates
230        $(document.body).on('updated_checkout', function () {
231            $('select.woot-city-select').each(function () {
232                if (!$(this).prop('disabled')) {
233                    initSelectWoo($(this));
234                }
235            });
236        });
237
238        // Start
239        setTimeout(init, 200);
240    });
241
242})(jQuery);

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.