PageSourceSearch

https://www.midcounties.coop/static/js/storeLocator.js

js midcounties.coop collected 2026-10-02 03:17:01 UTC 22,194 bytes, 541 lines download raw bytes

1"use strict";
2
3(function() {
4    var map,
5        stores,
6        circle,
7        infoWindow,
8        userLocation,
9        markers = [],
10        matchedStores = [],
11        numStoresToList = 5,
12        selectedMarker;
13
14    function isMobile() {
15        return window.matchMedia && window.matchMedia("screen and (max-width: 767px)").matches;
16    }
17
18    var icons = {
19        1: "food",
20        2: "travel",
21        3: "funeral",
22        4: "childcare",
23        5: "healthcare",
24        6: "postoffice"
25    };
26
27    var services = {
28        1: "Food",
29        2: "Travel",
30        3: "Funeralcare",
31        4: "Childcare",
32        5: "Healthcare",
33        6: "Post Office"
34    };
35
36    function createTimePair(open, close) {
37        if (open == "Closed" || close == "Closed") {
38            return "Closed";
39        }
40        if (!open || !close) return "-";
41
42        var openString = open.replace(".", ":");
43        var closeString = close.replace(".", ":");
44
45        if (openString == "24:00") {
46            openString = "00:00";
47        }
48
49        if (openString.length == 4) openString = "0" + openString;
50        if (closeString.length == 4) closeString = "0" + closeString;
51
52        return openString + " - " + closeString;
53    }
54
55    function getPhone(marker) {
56        var phone = "";
57        if (marker.data.telephone) {
58            phone = '<p>Telephone: <a href="tel:' + marker.data.telephone.replace(/ /g, "") + '"><strong>' + marker.data.telephone + '</strong></a></p>';
59        }
60        return phone;
61    }
62
63    function getAdditionalInfo(marker) {
64        var additionalInfo = "";
65        if (marker.data.text) {
66            additionalInfo = "<p class=\"additionalInfo\">" + marker.data.text + "</p>";
67        }
68        return additionalInfo;
69    }
70
71    function getStoreType(marker) {
72        return '<strong class="' + icons[marker.data.tradingGroupId] + '">' + services[marker.data.tradingGroupId] + '</strong>'
73    }
74
75    function getStoreName(marker) {
76        return '<h2 style="margin-top: 0;">' + (marker.data.name ? marker.data.name : marker.data.town) + '</h2>'
77    }
78
79    function getAddress(marker) {
80        var addresslines = [];
81        if (marker.data.addressLine1) { addresslines.push(marker.data.addressLine1); }
82        if (marker.data.addressLine2) { addresslines.push(marker.data.addressLine2); }
83        if (marker.data.addressLine3) { addresslines.push(marker.data.addressLine3); }
84        if (marker.data.town) { addresslines.push(marker.data.town); }
85        if (marker.data.county) { addresslines.push(marker.data.county); }
86        if (marker.data.postcode) { addresslines.push(marker.data.postcode); }
87
88        return '<p>' + addresslines.join(", ") + '</p>';
89    }
90
91    function getOpeningHours(marker) {
92        var times = "";
93        if (marker.data.mondayOpen && marker.data.mondayClose) {
94            var extraText = '';
95            if (marker.data.byAppointmentOnly) {
96                extraText = '<h3 class="openingHours" style="margin-top:0;">By Telephone Appointment Only</h3>';
97            }
98            times = '<h3 class="openingHours">Opening Hours:</h3>' + extraText +
99                '<table class="table">' +
100                    '	<tr><td><strong>Monday</strong></td><td> ' + createTimePair(marker.data.mondayOpen, marker.data.mondayClose) + '</td></tr> ' +
101                    '	<tr><td><strong>Tuesday</strong></td><td> ' + createTimePair(marker.data.tuesdayOpen, marker.data.tuesdayClose) + '</td></tr> ' +
102                    '	<tr><td><strong>Wednesday</strong></td><td> ' + createTimePair(marker.data.wednesdayOpen, marker.data.wednesdayClose) + '</td></tr> ' +
103                    '	<tr><td><strong>Thursday</strong></td><td> ' + createTimePair(marker.data.thursdayOpen, marker.data.thursdayClose) + '</td></tr> ' +
104                    '	<tr><td><strong>Friday</strong></td><td> ' + createTimePair(marker.data.fridayOpen, marker.data.fridayClose) + '</td></tr> ' +
105                    '	<tr><td><strong>Saturday</strong></td><td> ' + createTimePair(marker.data.saturdayOpen, marker.data.saturdayClose) + '</td></tr> ' +
106                    '	<tr><td><strong>Sunday</strong></td><td> ' + createTimePair(marker.data.sundayOpen, marker.data.sundayClose) + '</td></tr>' +
107                    '</table>';
108        }
109        return times;
110    }
111
112    function largestBoundingArea(b1, b2) {
113        var b1size = google.maps.geometry.spherical.computeDistanceBetween(b1.getNorthEast(), b1.getSouthWest
113());
114        var b2size = google.maps.geometry.spherical.computeDistanceBetween(b2.getNorthEast(), b2.getSouthWest());
115
116        if (b1size > b2size) {
117            return b1;
118        }
119
120        return b2;
121    }
122
123    function shiftMarker(marker, x, y) {
124        var markerpos = new google.maps.LatLng(marker.getPosition().lat() + y, marker.getPosition().lng() + x);
125        marker.setPosition(markerpos);
126    }
127
128
129    jQuery(function ($) {
130        var url = $("#storesMap").data("json-uri"),
131            icon = $("#storesMap").data("icon");
132
133        function getRadius() {
134            var radius;
135
136            if ($("#radius").val()) {
137                radius = parseInt($("#radius").val(), 10) / 0.621371 * 1000;
138            }
139            return radius;
140        }
141
142        if (!navigator.geolocation) {
143            $(".storesMapControlUseMyLocation").hide();
144        } else {
145            $(".storesMapControlUseMyLocation .btn").click(function (e) {
146                e.preventDefault();
147
148                var btn = $(this);
149                if (typeof(ga) != "undefined") {
150                    ga('send', 'event', 'StoreLocator', 'Search', 'Geolocation');
151                }
152
153                btn.addClass("active");
154
155                navigator.geolocation.getCurrentPosition(function (position) {
156                    $("#postcode").val("");
157                    btn.removeClass("active");
158                    var pos = {
159                        location: new google.maps.LatLng(position.coords.latitude, position.coords.longitude)
160                    };
161
162                    map.setCenter(pos.location);
163
164                    search(pos, getRadius());
165                }, function (err) {
166                    btn.removeClass("active");
167                    alert("Sorry, the geolocation service failed to fetch your current location. Error: " + err.message);
168                }, {
169                    maximumAge: 60000,
170                    timeout: 5000,
171                    enableHighAccuracy: true
172                });
173            });
174        }
175        
176        function filterStores(index, matchedStores) {
177            var matchedStoresNumber = matchedStores.length;
178            var filteredStores = matchedStores.slice(index, index + numStoresToList);
179            $(".storesMapResults ul").html("");
180
181            for (var j in filteredStores) {
182                var storeResult = $($("#storeResult").html()
183                    .replace("{name}", filteredStores[j].name)
184                    .replace("{type}", services[filteredStores[j].tradingGroupId])
185                    .replace("{typeClass}", icons[filteredStores[j].tradingGroupId])
186                    .replace("{mileage}", Math.round(filteredStores[j].distance * 10) / 10 + " miles"));
187                storeResult.data("marker", filteredStores[j].marker);
188                $(".storesMapResults ul").append(storeResult);
189            }
190
191            var showPrev = index >= numStoresToList;
192            var showNext = index + filteredStores.length < matchedStores.length;
193
194            if (showPrev || showNext) {
195
196                $(".storesMapResults ul").append("<li class='list-group-item storesMapResultsPager'></li>");
197
198                if (index >= numStoresToList) {
199                    $(".storesMapResultsPager")
200                        .append("<a href='#' class='storesMapResultsViewPage storesMapResultsViewPrevious' data-index='" + (Math.max(index - numStoresToList, 0)) + "'><span class='fa fa-chevron-left'></span> Previous</a>");
201                }
202
203                if (index + filteredStores.length < matchedStores.length) {
204
205                    $(".storesMapResultsPager")
206                        .append("<a href='#' class='storesMapResultsViewPage storesMapResultsViewNext' data-index='" + (index + filteredStores.length) + "'>Next <span class='fa fa-chevron-right'></span></a>");
207
208                }
209
210            }
211
212            $(".storesMapResults ul").append("<li class='visible-xs list-group-item storesMapResultsViewMap'><span class='fa fa-chevron-right'></span>View results on a map</li>");
213
214            $(".storesMapResultsViewPage").click(function (e) {
215                e.preventDefault();
216                e.stopPropagation();
217                filterStores($(this).data("index"), matchedStores);
218            });
219
220            $(".storesMapResultsNumber").html("<strong>" + matchedStoresNumber + "</strong> store" + (matchedStoresNumber == 1 ? " was" : "s were") + " matched:");
221
222            $(".storesMapResults").show();
223
224            if (isMobile()) {
225                $(window).scrollTop($(".storesMapResults").offset().top - 15);
226            }
227        };
228
229        function search(position, radius) {
230            var distances = [];
231            var closest = -1;
232
233            var tradingGroup;
234            if ($("#business").val()) {
235                tradingGroup = parseInt($("#business").val(), 10);
236            }
237
238            $(".gm-style").animate({
239                opacity: 1
240            }, 500);
241
242            matchedStores = [];
243
244            for (var i = 0; i < markers.length; i++) {
245                var distance = google.maps.geometry.spherical.computeDistanceBetween(position.location, markers[i].position);
246
247                if ((!radius || distance < radius) && (!tradingGroup || markers[i].data.tradingGroupId == tradingGroup)) {
248                    markers[i].data.distance = distance * 0.621371 / 1000;//meters to miles
249                    distances[i] = distance;
250                    if (closest == -1 || distance < distances[closest]) {
251                        closest = i;
252                    }
253                    markers[i].data.marker = markers[i];
254                    matchedStores.push(markers[i].data);
255                    markers[i].setMap(map);
256                } else {
257                    markers[i].setMap(null);
258                    delete markers[i].data.distance;
259                }
260            }
261
262            matchedStores.sort(function (a, b) {
263                if (!a.distance && !b.distance) return 0;
264                if (!a.distance && b.distance) return 1;
265                if (a.distance && !b.distance) return -1;
266                return a.distance - b.distance;
267            });
268
269            if (matchedStores.length > 0) {
270                filterStores(0, matchedStores);
271            } else {
272                $(".storesMapResults").show();
273                $(".storesMapResults ul").html("");
274                $(".storesMapResultsNumber").html("<strong>0</strong> stores were matched");
275            }
276
277            var home_marker_image = new google.maps.MarkerImage(
278                icon.replace("{type}", "location"),
279                new google.maps.Size(37, 55),
280                new google.maps.Point(0, 0),
281                new google.maps.Point(18, 54)
282            );
283
284            if (circle) circle.setMap(null);
285            if (radius && !$("body").hasClass("ie6-8")) {
286                circle = new google.maps.Circle({
287                    center: position.location,
288                    radius: radius,
289                    fillOpacity: 0.1,
290                    fillColor: "#0051a1",
291                    strokeOpacity: 0.4,
292                    strokeColor: "#0051a1",
293                    map: map,
294                    clickable: false
295                });
296            }
297
298            if (userLocation) {
299                userLocation.setMap(null);
300            }
301            userLocation = new google.maps.Marker({
302                position: new google.maps.LatLng(position.location.lat(), position.location.lng()),
303                map: map,
304                title: "Your Location",
305                icon: home_marker_image
306            });
307
308            if (closest >= 0) {
309                //  Create a new viewpoint bound
310                var bounds = new google.maps.LatLngBounds();
311
312                bounds.extend(markers[closest].position);
313                bounds.extend(position.location);
314                //  Fit these bounds to the map
315                if (position.bounds) {
316                    map.fitBounds(largestBoundingArea(position.bounds, bounds));
317                }
318                else {
319                    map.fitBounds(bounds);
320                }
321            }
322        }
323
324        function showStoreResult(marker) {
325            if (selectedMarker) selectedMarker.setAnimation(null);
326            selectedMarker = marker;
327            setTimeout(function () { marker.setAnimation(google.maps.Animation.BOUNCE) }, 10);
328            map.setCenter(marker.position);
329
330            $(".storesMapResultInfo").html("")
331                .append(getStoreName(marker))
332                .append(getStoreType(marker))
333                .append(getPhone(marker))
334                .append(getAddress(marker).replace(/, /ig, "<br/>"))
335                .append(getOpeningHours(marker))
336                .append(getAdditionalInfo(marker));
337            $(".storesMapResultOpeningHours").html(getOpeningHours(marker));
338            $(".storesMapResultButtonDirections").attr("href", "https://www.google.co.uk/maps/dir/" + encodeURIComponent($("#postcode").val()) + "/" + encodeURIComponent(marker.data.latitude + "," + marker.data.longitude));
339
340            if (typeof (marker.data.branchNumber) != "undefined") {
341                $(".storesMapResultButtonEvents").show();
342                $(".storesMapResultButtonEvents").attr("href", $(".storesMapResultButtonEvents").attr("href").replace(/branch=.*/, "branch=" + marker.data.branchNumber));
343            } else {
344                $(".storesMapResultButtonEvents").hide();
345            }
346
347            $(".storesMapResult").show();
348            $(".storesMapResults").hide();
349
350            if (isMobile()) {
351                $(window).scrollTop($(".storesMapResult").offset().top - 15);
352            }
353
354            if (typeof(ga) != "undefined") {
355                ga('send', 'event', 'StoreLocator', 'Store Click', services[marker.data.tradingGroupId], marker.data.branchNumber);
356            }
357        }
358
359        $(window).resize(function () {
360            if (!isMobile()) {
361                $("#map").show();
362            }
363        });
364
365        window.initMap = function () {
366            var stacks = {};
367
368            map = new google.maps.Map(document.getElementById('map'), {
369                center: { lat: 52.0587023, lng: -1.01720467 },
370                zoomControl: true,
371                scrollwheel: false,
372                streetViewControl: false,
373                zoom: 8
374            });
375
376            function markerPopup() {
377                showStoreResult(this);
378            };
379
380            function fadeIn() {
381                $(".gm-style").animate({
382                    opacity: 1
383                }, 500);
384            }
385
386            map.addListener("click", fadeIn);
387            map.addListener("center_changed", fadeIn);
388
389            $("#mapSearch").submit(function (e) {
390                e.preventDefault();
391
392                if (typeof(ga) != "undefined") {
393                    ga('send', 'event', 'StoreLocator', 'Search', 'Postcode');
394                }
395
396                var locationName = $("#postcode").val();
397                
398                if (locationName) {
399                    var geocoder = new google.maps.Geocoder();
400                    geocoder.geocode({ address: locationName + ", UK" }, function (result, status) {
401                        if (status == "OK") {
402                            search(result[0].geometry, getRadius());
403                        }
404                    });
405                } else {
406                    alert("Please enter a postcode or town");
407                }
408            });
409
410            $(document).on("click", ".storesMapResultClose", function (e) {
411                e.preventDefault();
412                $(".storesMapResult").hide();
413                if (matchedStores.length > 0) $(".storesMapResults").show();
414            });
415
416            $(document).on("click", ".storesMapResults li", function (e) {
417                e.preventDefault();
418
419                if (!$(this).is(".storesMapResultsPager")) {
420
421                    var marker = $(this).data("marker");
422                    if (marker) {
423                        showStoreResult(marker);
424                    } else {
425                        $("#map").show();
426                        $(this).remove();
427                        google.maps.event.trigger(map, 'resize');
428                        map.setCenter(userLocation.position);
429                        map.setZoom(13);
430                        $(".btnBackToResults").show();
431                        if (isMobile()) {
432                            $(window).scrollTop($("#map").offset().top - 15);
433                        }
434                    }
435                }
436            });
437
438            $(".btnBackToResults").click(function (e) {
439                e.preventDefault();
440                if (isMobile()) {
441                    $(window).scrollTop($(".storesMapFilters").offset().top + $(".storesMapFilters").outerHeight());
442                }
443            });
444
445            $.ajax({
446                url: url,
447                dataType: 'json',
448                error: function(err) {
449                    alert("There was an error loading our store data, please try again.")
450                },
451                success: function (data) {
452                    stores = data.stores;
453
454                    for (var i in stores) {
455                        var iconType = icons[stores[i].tradingGroupId];
456
457                        var marker = new google.maps.Marker({
458                            position: { lat: stores[i].latitude, lng: stores[i].longitude },
459                            map: map,
460                            title: stores[i].name,
461                            icon: icon.replace("{type}", iconType),
462                            data: stores[i]
463                        });
464
465                        marker.showInfo = markerPopup;
466
467                        google.maps.event.addListener(marker, 'click', function (event) {
468                            this.showInfo();
469                        });
470
471                        var dupeId = marker.data.latitude + "," + marker.data.longitude;
472                        if (!stacks[dupeId]) {
473                            stacks[dupeId] = [];
474                        }
475                        stacks[dupeId].push(marker);
476
477                        markers.push(marker);
478                    }
479
480                    var stackCount = 0;
481                    for (i in stacks) {
482                        stackCount++;
483                        if (stacks[i].length == 1) {
484                            delete stacks[i];
485                            stackCount--;
486                        } else {
487                            //pull any stacks apart
488                            switch (stacks[i].length) {
489                                case 2:
490                                    shiftMarker(stacks[i][0], -0.0001, 0);
491                                    shiftMarker(stacks[i][1], 0.0001, 0);
492                                    break;
493                                case 3:
494                                    shiftMarker(stacks[i][0], -0.00011, 0);
495                                    shiftMarker(stacks[i][1], 0, 0.0001);
496                                    shiftMarker(stacks[i][2], 0.00011, 0);
497
498                                
499                                    break;
500                                case 4:
501                                    shiftMarker(stacks[i][0], -0.0001, 0.00007);
502                                    shiftMarker(stacks[i][1], 0.0001, 0.00007);
503                                    shiftMarker(stacks[i][2], -0.0001, -0.00007);
504                                    shiftMarker(stacks[i][3], 0.0001, -0.00007);
505                                    break;
506                                case 5:
507                                    shiftMarker(stacks[i][0], 0, 0.0001);
508                                    shiftMarker(stacks[i][1], 0.0001, 0.00008);
509                                    shiftMarker(stacks[i][2], -0.0001, -0.00008);
510                                    shiftMarker(stacks[i][3], 0.00009, -0.00003);
511                                    shiftMarker(stacks[i][4], -0.00009, -0.00003);
512                                    break;
513                            }
514                        }
515                    }
516
517                    if (window.urlParams && window.urlParams["$location"] && window.urlParams["$location"] != "") {
518                        $("#postcode").val(window.urlParams["$location"]);
519                    }
520
521                    if (window.urlParams && window.urlParams["$service"] && window.urlParams["$service"] != "") {
522                        var oldservices = {
523                            "food" : 1,
524                            "travel" : 2,
525                            "funeralcare" : 3,
526                            "childcare" : 4,
527                            "pharmacy" : 5,
528                            "postoffice" : 6
529                        };
530                        $("#business").val(oldservices[window.urlParams["$service"]]);
531                    }
532
533                    if ($("#postcode").val()) {
534                        $(".btnStoresSearch").click();
535                    }
536                }
537            });
538        }
539    });
540
541})();

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.