PageSourceSearch

https://www.taxes.gov.az/js/taxes-map.js

js taxes.gov.az collected 2026-10-02 04:42:51 UTC 10,322 bytes, 317 lines download raw bytes

1/*!
2 * taxes.gov.az — interactive map
3 * Replaces the map handlers from main.js (they are detached below).
4 *
5 * Starts on DOM ready (jQuery ready runs after main.js's own ready handlers,
6 * because this file is included after it), so the map works as soon as the
7 * page is shown — without waiting for images, iframes and CDN scripts.
8 * A guard makes sure it runs only once even if the file is included twice.
9 */
10(function () {
11    'use strict';
12
13    function initTaxesMap() {
14        if (window.__taxesMapReady) {
15            return;
16        }
17        window.__taxesMapReady = true;
18
19        var $ = window.jQuery;
20        if (!$) {
21            return;
22        }
23
24        var $map = $('#taxes-map');
25        if (!$map.length) {
26            return;
27        }
28
29        var tree = window.taxesMapTree || {};
30        var $wrap = $('.map-interactive');
31        var $popups = $('.popup-list .mypopup');
32        var $select = $('.tmap-select');
33        var svg = $map.closest('svg')[0];
34        var CIRCLE_R = '3.5';
35        var CIRCLE_R_ACTIVE = '5.5';
36        var MOBILE_QUERY = '(max-width: 575px)';
37
38        // Detach old handlers bound by main.js
39        $('.map-interactive .region-circle, .map-interactive .path-section').off('click');
40        $('.popup-close').off('click');
41        $('.select-region-mobil').off('change');
42
43        function isMobile() {
44            return window.matchMedia && window.matchMedia(MOBILE_QUERY).matches;
45        }
46
47
48        /* ----------------------------------------------------------------------
49           Mobile zoom (animated viewBox)
50           ---------------------------------------------------------------------- */
51
52        var FULL_VIEW = svg ? [svg.viewBox.baseVal.x, svg.viewBox.baseVal.y, svg.viewBox.baseVal.width, svg.viewBox.baseVal.height] : null;
53        var viewAnim = null;
54
55        function getView() {
56            var b = svg.viewBox.baseVal;
57            return [b.x, b.y, b.width, b.height];
58        }
59
60        function setView(v) {
61            svg.setAttribute('viewBox', v.join(' '));
62        }
63
64        function animateView(to) {
65            if (!svg) {
66                return;
67            }
68            if (viewAnim) {
69                window.cancelAnimationFrame(viewAnim);
70            }
71            var from = getView();
72            var start = null;
73            var duration = 450;
74
75            function step(ts) {
76                if (start === null) {
77                    start = ts;
78                }
79                var p = Math.min(1, (ts - start) / duration);
80                var e = 1 - Math.pow(1 - p, 3);
81                setView(from.map(function (f, i) {
82                    return f + (to[i] - f) * e;
83                }));
84                if (p < 1) {
85                    viewAnim = window.requestAnimationFrame(step);
86                }
87            }
88
89            viewAnim = window.requestAnimationFrame(step);
90        }
91
92        // Bounding box of a region (shape + its labels) in SVG user units
93        function regionBox(code) {
94            var group = $map.find('.path-hover[data-atrr="' + code + '"]')[0];
95            if (!group || !svg.getScreenCTM()) {
96                return null;
97            }
98            var r = group.getBoundingClientRect();
99            var m = svg.getScreenCTM().inverse();
100            var p1 = svg.createSVGPoint();
101            var p2 = svg.createSVGPoint();
102            p1.x = r.left;
103            p1.y = r.top;
104            p2.x = r.right;
105            p2.y = r.bottom;
106            p1 = p1.matrixTransform(m);
107            p2 = p2.matrixTransform(m);
108            return [p1.x, p1.y, p2.x - p1.x, p2.y - p1.y];
109        }
110
111        function zoomToRegion(code) {
112            if (!svg || !isMobile()) {
113                return;
114            }
115            var b = regionBox(code);
116            if (!b) {
117                return;
118            }
119            var ratio = FULL_VIEW[2] / FULL_VIEW[3];
120            var w = b[2] * 1.3;
121            var h = b[3] * 1.3;
122
123            if (w / h > ratio) {
124                h = w / ratio;
125            } else {
126                w = h * ratio;
127            }
128
129            // Limit the zoom so small regions (Bakı) do not become oversized
130            var minW = FULL_VIEW[2] / 4;
131            if (w < minW) {
132                w = minW;
133                h = w / ratio;
134            }
135
136            var cx = b[0] + b[2] / 2;
137            var cy = b[1] + b[3] / 2;
138
139            animateView([cx - w / 2, cy - h / 2, w, h]);
140            $wrap.addClass('tmap-zoomed');
141        }
142
143        function zoomReset() {
144            if (!svg) {
145                return;
146            }
147            if ($wrap.hasClass('tmap-zoomed')) {
148                animateView(FULL_VIEW.slice());
149            }
150            $wrap.removeClass('tmap-zoomed');
151        }
152
153
154        /* ----------------------------------------------------------------------
155           Popups and highlighting
156           ---------------------------------------------------------------------- */
157
158        function findPopup(code) {
159            return $popups.filter(function () {
160                return $(this).attr('data-map-popup') === code;
161            });
162        }
163
164        function regionOf(code, $el) {
165            if (tree[code]) {
166                return tree[code];
167            }
168            if ($el && $el.length) {
169                var $group = $el.closest('.path-hover');
170                if ($group.length) {
171                    return $group.attr('data-atrr');
172                }
173            }
174            return code;
175        }
176
177        function highlightRegion(regionCode) {
178            $map.find('.path-hover').removeClass('color-changed')
179                .filter('[data-atrr="' + regionCode + '"]').addClass('color-changed');
180        }
181
182        function markDistrict(code) {
183            $map.find('.region-circle').attr('r', CIRCLE_R);
184            if (code) {
185                $map.find('.region-circle[data-id="' + code + '"]').attr('r', CIRCLE_R_ACTIVE);
186            }
187        }
188
189        // Map preview iframes are loaded only when their popup is opened
190        function loadMapPreview($popup) {
191            $popup.find('iframe[data-src]').each(function () {
192                var $frame = $(this);
193                $frame.attr('src', $frame.attr('data-src')).removeAttr('data-src');
194            });
195        }
196
197        function showPopup($popup) {
198            loadMapPreview($popup);
199            $popups.not($popup).stop(true, true).hide();
200            $popup.stop(true, true).fadeIn(200).scrollTop(0);
201        }
202
203        function openCode(code, $el) {
204            if (!code) {
205                return;
206            }
207
208            var region = regionOf(code, $el);
209            var isDistrict = region !== code;
210            var $popup = findPopup(code);
211
212            // District without its own popup -> show its region popup
213            if (!$popup.length) {
214                $popup = findPopup(region);
215            }
216
217            highlightRegion(region);
218            markDistrict(isDistrict ? code : null);
219
220            if ($select.length) {
221                $select.val(region);
222            }
223
224            if (isMobile()) {
225                zoomToRegion(region);
226                $('html, body').stop(true).animate({ scrollTop: $wrap.offset().top - 12 }, 400);
227            }
228
229            if (!$popup.length) {
230                return;
231            }
232
233            showPopup($popup);
234            $wrap.addClass('map-click');
235
236            if ($(window).width() <= 1180 && !isMobile()) {
237                $('html, body').stop(true).animate({ scrollTop: $popup.offset().top - 100 }, 600);
238            }
239        }
240
241        function closeAll() {
242            $popups.stop(true, true).fadeOut(150);
243            $map.find('.path-hover').removeClass('color-changed');
244            markDistrict(null);
245            $wrap.removeClass('map-click');
246            zoomReset();
247            if ($select.length) {
248                $select.val('');
249            }
250        }
251
252
253        /* ----------------------------------------------------------------------
254           Events
255           ---------------------------------------------------------------------- */
256
257        // District dots and labels
258        $map.on('click', '.region-circle, .path-section', function (e) {
259            e.stopPropagation();
260            openCode($(this).attr('data-id'), $(this));
261        });
262
263        // Click on the region shape itself
264        $map.on('click', '.path-hover > path', function () {
265            openCode($(this).closest('.path-hover').attr('data-atrr'));
266        });
267
268        // District links inside a popup
269        $(document).on('click', '.popup-list [data-map-link]', function (e) {
270            e.preventDefault();
271            openCode($(this).attr('data-map-link'));
272        });
273
274        $(document).on('click', '.popup-list .popup-close', function () {
275            closeAll();
276        });
277
278        $(document).on('keyup', function (e) {
279            if (e.key === 'Escape' || e.keyCode === 27) {
280                closeAll();
281            }
282        });
283
284        // Mobile region picker
285        $select.on('change', function () {
286            var code = $(this).val();
287            if (code) {
288                openCode(code);
289            } else {
290                closeAll();
291            }
292        });
293
294        // Mobile "whole map" button
295        $('.tmap-reset').on('click', function () {
296            closeAll();
297        });
298
299        // Leaving the mobile layout (rotation / resize) restores the full map
300        var resizeTimer = null;
301        $(window).on('resize', function () {
302            window.clearTimeout(resizeTimer);
303            resizeTimer = window.setTimeout(function () {
304                if (!isMobile() && svg && $wrap.hasClass('tmap-zoomed')) {
305                    setView(FULL_VIEW.slice());
306                    $wrap.removeClass('tmap-zoomed');
307                }
308            }, 150);
309        });
310    }
311
312    if (window.jQuery) {
313        window.jQuery(initTaxesMap);
314    } else {
315        window.addEventListener('load', initTaxesMap);
316    }
317})();

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.