PageSourceSearch

http://www.norfolkinsight.org.uk/wp-content/themes/ia-theme/js/dist/ia-quickprofile.js?_v=latest

js norfolkinsight.org.uk collected 2026-10-02 16:19:23 UTC 10,207 bytes, 214 lines download raw bytes

1jQuery(function () {
2    (function ($) {
3        const containers = document.querySelectorAll('.qp-container'),
4            firstConfig = JSON.parse(containers[0].getAttribute('data-config')); // Default config from first item (there may be more)
5
6        var regexGuid =
7            /^(\{){0,1}[0-9a-fA-F]{8}(\-){0,1}[0-9a-fA-F]{4}(\-){0,1}[0-9a-fA-F]{4}(\-){0,1}[0-9a-fA-F]{4}(\-){0,1}[0-9a-fA-F]{12}(\}){0,1}$/gi;
8        $.getCachedScript = function (url, options) {
9            // https://api.jquery.com/jquery.getscript/
10            // Allow user to set any option except for dataType, cache, and url
11            options = $.extend(options || {}, {
12                dataType: 'script',
13                cache: true,
14                url: url
15            });
16            // Use $.ajax() since it is more flexible than $.getScript
17            // Return the jqXHR object so we can chain callbacks
18            return $.ajax(options);
19        };
20
21        // GUID - AGOL map, deal with that...
22        if (regexGuid.test(firstConfig.map)) {
23            containers.forEach((container, idx) => {
24                container.setAttribute('class', container.getAttribute('class') + ' qp-container--' + idx);
25                const config = JSON.parse(container.getAttribute('data-config')),
26                    searchInput = container.querySelector('.qp-search-input'),
27                    qpSearchButton = container.querySelector('.qp-search-submit'),
28                    mapContainer = container.querySelector('.qp-map'),
29                    mapPanel = document.createElement('div'),
30                    tooltip = document.createElement('div'),
31                    targetLayerIndex = config.layer !== undefined ? config.layer : 1;
32                //searchInput.setAttribute('id', searchInput.getAttribute('id') + 'i' + idx);
33                if (searchInput !== null) {
34                    searchInput.addEventListener('keyup', debounce(searchInputHandler, 300));
35                }
36                if (qpSearchButton !== null) {
37                    const debouncedHandler = debounce(searchButtonHandler, 300);
38                    // When user clicks the button
39                    qpSearchButton.addEventListener('click', searchButtonHandler);
40                    // When user presses Enter/Space on button
41                    qpSearchButton.addEventListener('keyup', function (event) {
42                        if (event.key === 'Enter' || event.key === ' ') {
43                            debouncedHandler();
44                        }
45                    });
46                }
47                mapContainer.appendChild(mapPanel);
48                mapPanel.setAttribute('id', 'iaMap_' + config.map);
49                mapPanel.setAttribute(
50                    'style',
51                    'position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: 9999;'
52                );
53                tooltip.setAttribute('id', 'iaMap_' + config.map + '_root_mapTip');
54                tooltip.setAttribute('class', 'tooltip agoMapTip mapTooltip qp-map-tooltip ia-map-tooltip');
55                tooltip.appendChild(document.createElement('span'));
56                tooltip.firstChild.setAttribute('class', 'mapTooltipText map-tooltip-text tooltip-text');
57                mapContainer.appendChild(tooltip);
58                window.instantAtlasMapping
59                    .drawMap(config.map, mapPanel.getAttribute('id'), {
60                        activeLayerIndex: targetLayerIndex,
61                        scalebar: {
62                            units: 'metric'
63                        },
64                        sliderStyle: config.map_controls ? 'small' : 'none',
65                        sliderPosition: 'top-right',
66                        sliderOrientation: 'horizontal',
67                        tooltips: {
68                            enabled: true,
69                            field: config.name_prop || 'NAME'
70                        },
71                        navigate: {
72                            enabled: true,
73                            field: config.id_prop || 'WardCode',
74                            path: config.action.replace('{{id_prop}}', '#ID')
75                        }
76                    })
77                    .then((e) => {
78                        const tile = container.closest('.tile');
79                        if (tile !== null)
80                            tile.setAttribute('class', (tile.getAttribute('class') || '').replace(/tile-loading/g, ''));
81                        if (e !== undefined && e.layer !== undefined) {
82                        }
83                    });
84            });
85        } else {
86            alert('SVG mapping is no longer supported - contact Esri UK');
87        }
88
89        function interpolate_action(action, id_prop, obj) {
90            var action = action.replace('{{id_prop}}', obj.properties[id_prop]);
91            return action;
92        }
93
94        function debounce(func, wait) {
95            var timeout;
96            return function () {
97                var context = this,
98                    args = arguments;
99                var later = function () {
100                    timeout = null;
101                    func.apply(context, args);
102                };
103                clearTimeout(timeout);
104                timeout = setTimeout(later, wait);
105            };
106        }
107
108        /**
109         * Takes a string as input and attempts to format it as a postcode
110         * returns false if it fails
111         */
112        function formatPostcode(pc, allowFreeFormIfNotPostcode) {
113            var pcUp = pc.toUpperCase();
114            postcode = pcUp.match(/^([A-Z]{1,2}\d{1,2}[A-Z]?)\s*(\d[A-Z]{2})$/);
115            if (postcode instanceof Array) {
116                postcode.shift();
117                return postcode.join(' ');
118            }
119            return allowFreeFormIfNotPostcode ? pc : false;
120        }
121
122        function buildArcgisQuery(str, searchField, lookupField, filterField, filterValue) {
123            const baseEndpoint =
124                firstConfig.lookupUrl ??
125                'https://ons-inspire.esriuk.com/arcgis/rest/services/Postcodes/ONS_Postcode_Directory_Latest_Centroids/MapServer/0/';
126            const outFields = lookupField ? lookupField.split(',') : ['osward'];
127            let whereClause = searchField
128                .split(',')
129                .map((sf) => `${sf} = '${str}'`)
130                .join(' OR ');
131            if (typeof filterField !== 'undefined' && filterField !== null) {
132                outFields.push(filterField);
133                whereClause = `(${whereClause}) AND (${filterField} = '${filterValue}')`;
134            }
135            const query =
136                'query?where=' +
137                encodeURIComponent(whereClause) +
138                '&outFields=' +
139                encodeURIComponent(outFields.join(',')) +
140                '&returnDistinctValues=true&f=json';
141            return baseEndpoint + query;
142        }
143
144        function noop() {}
145
146        function searchButtonHandler(e) {
147            const $searchInput = $('.qp-search-input');
148            doSearch(e, $searchInput, true);
149        }
150
151        function searchInputHandler(e) {
152            const $searchInput = $(
153                e.currentTarget !== undefined && e.currentTarget !== null ? e.currentTarget : e.target
154            );
155            doSearch(e, $searchInput, false);
156        }
157
158        function doSearch(e, $searchInput, forceSubmit) {
159            const stripped = $.trim($searchInput.val());
160            const searchType = firstConfig.search_type ?? 'postcode'; // 'postcode' or 'free' (if 'free' then need to take care)
161            const searchText = formatPostcode(stripped, searchType === 'free');
162            const searchErrorMessage =
163                firstConfig.error_message ?? `${searchText} did not match an area. Please try again.`;
164
165            /**
166             * Build the query
167             */
168            const searchField = firstConfig.search_field ?? 'pcds';
169            const lookupField = firstConfig.lookup_field ?? 'osward';
170            const filterField = firstConfig.filter_field;
171            const filterValue = firstConfig.filter_value;
172            const lookup = buildArcgisQuery(searchText, searchField, lookupField, filterField, filterValue);
173
174            /**
175             * Handle the enter key
176             */
177            if (e.keyCode === 13 || forceSubmit) {
178                /**
179                 * Handle case where the postcode doesn't validate
180                 * This is a clunky check, bypassed if you are alowed to search on > 1 field
181                 */
182                if (!searchText || (searchField.indexOf(',') < 0 && searchText.length < 6)) {
183                    $('.qp-search-error')
184                        .text('The postcode you entered is invalid, please try again.')
185                        .addClass('active');
186                    return;
187                }
188                $('.qp-search-input').addClass('loading');
189                $.get(lookup, function (data) {
190                    const json = typeof data === 'object' ? data : JSON.parse(data);
191                    var lookupCode;
192                    try {
193                        lookupCode = json.features[0].attributes[lookupField];
194                        if (typeof filterField !== 'undefined' && typeof filterValue !== 'undefined') {
195                            const fc = json.features[0].attributes[filterField];
196                            if (fc !== filterValue) {
197                                throw new Error(
198                                    `Matched postcode or area '${lookupCode}' is not in '${filterValue}' - is in '${fc}'`
199                                );
200                            }
201                        }
202                    } catch (err) {
203                        $('.qp-search-input').removeClass('loading');
204                        $('.qp-search-error')
205                            .text(searchErrorMessage.replace('{{text}}', searchText))
206                            .addClass('active');
207                        return;
208                    }
209                    window.location = firstConfig.action.replace('{{id_prop}}', lookupCode);
210                });
211            }
212        }
213    })(jQuery);
214});

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.