PageSourceSearch

https://www.scottishwater.co.uk/sites/scottishwater/js/plugins/mtc_google_maps.js

js scottishwater.co.uk collected 2026-09-24 09:04:31 UTC 48,748 bytes, 1,164 lines download raw bytes

1/*!
2 *
3 * mtcGoogleMaps.js - A jQuery plugin for google maps
4 * Version : 1.0
5 * Author(s) : Valdis Ceirans, Lee Methven
6 *
7 * Docs: http://wiki.mtcmedia.co.uk/index.php?title=Jquery_Plugin_-_mtc_google_maps
8 * Website: http://www.mtcmedia.co.uk
9 *
10 */
11
12
13/*
14 * Function for handling the enabling / disabling of filters
15 */
16
17function labelFilters(plugin) {
18    $('.js_mapLabel').each(function () {
19        var category_code = $(this).data('category-code'),
20            state = true;
21
22        if ($(this).hasClass('off')) {
23            state = false;
24            // hide ones within list view too
25            $('li[data-category-code="' + category_code + '"]').fadeOut();
26        } else {
27            state = true;
28            // show ones within list view too
29            $('li[data-category-code="' + category_code + '"]').fadeIn();
30        }
31
32        $.each(plugin.places, function (i, value) {
33            if (typeof (value.category_code) !== 'undefined' && value.category_code === category_code) {
34                value.marker.setVisible(state);
35            }
36        });
37    });
38}
39
40function initGoogleMaps() {
41    'use strict';
42
43    var js_path = "/sites/scottishwater/js/plugins/includes/";
44
45    $.getScript(js_path + "infobox.js", function (data, textStatus, jqxhr) {
46        $('.googleMap').each(function (i, elem) {
47            $(elem).data('plugin_mtcGoogleMaps').init();
48        });
49    });
50
51    $('body').on('click', '.js_focusMarker', function (e) {
52
53        e.preventDefault();
54
55        var anchor = $(this),
56            plugin, place, map,
57            toShow = anchor.closest('li').find('.stockistInfoWrap'),
58            toHide = $('#stockistResults .stockistInfoWrap:not(#' + toShow.attr('id') + ')');
59
60        //hide showing stockist, show clicked
61        toHide.stop(true, true).slideUp();
62        toShow.stop(true, true).slideDown();
63
64        map = $('#map' + $(this).data('map-id'));
65
66        plugin = map.data('plugin_mtcGoogleMaps');
67
68        place = plugin.places[$(this).data('place-id')];
69
70        plugin.google_map.panTo(place.marker.getPosition());
71
72    });
73}
74
75; (function ($, window, document, undefined) {
76
77   
78    // Create the defaults once
79    var plugin_name = "mtcGoogleMaps",
80        data_key = "plugin_" + plugin_name;
81
82    $.fn[plugin_name] = function (options) {
83        var load_called = $('body').hasClass('hasGMapsApi'),
84            plugin = this,
85            plugin_api_key,
86            script;
87
88        // Pop out the error message
89        if (this.length === 0) {
90            return this;
91        }
92
93        //  call init
94        if (this.length > 0) {
95            //load google js async
96            if (!load_called) {
97                if (typeof google === 'undefined' || typeof google.maps === 'undefined') {
98                    plugin_api_key = $('body').data('maps-api-key');
99                    script = document.createElement('script');
100                    script.type = 'text/javascript';
101                    script.src = '//maps.googleapis.com/maps/api/js?key=' + plugin_api_key + '&libraries=places&callback=initGoogleMaps';
102                    document.body.appendChild(script);
103                } else {
104                    initGoogleMaps();
105                }
106                $('body').addClass('hasGMapsApi');
107            }
108            //for each of the elements call plugin
109            return this.each(function (index, el) {
110                var plugin, _name;
111                plugin = $.data(this, data_key);
112                if (typeof options === 'string') {
113                    return plugin !== null ? typeof plugin[_name = options] === "function" ? plugin[_name]() : void 0 : void 0;
114                } else if (!plugin) {
115                    $(el).addClass('googleMap');
116                    return $.data(this, data_key, new Plugin(el, options));
117                }
118            });
119
120        }
121
122    };
123    //sort points by proximity
124    function sortPointsByProximity(location, places, search_distance) {
125
126        var points_sorted = [],
127            index,
128            marker_place,
129            dif;
130
131        for (index = 0; index < places.length; index++) {
132
133            marker_place = places[index].marker.getPosition();
134            dif = PythagorasEquirectangular(location.lat(), location.lng(), marker_place.lat(), marker_place.lng());
135
136            if (search_distance >= dif) {
137                points_sorted.push({
138                    dif: dif,
139                    id: index
140                });
141            }
142        }
143
144        points_sorted.sort(compareByDif);
145        return points_sorted;
146    }
147    //compare 2 distances
148    function compareByDif(a, b) {
149        if (a.dif < b.dif) {
150            return -1;
151        }
152        if (a.dif > b.dif) {
153            return 1;
154        }
155        return 0;
156    }
157
158    function getFirstKey(data) {
159        for (elem in data) {
160            return elem;
161        }
162    }
163    //calculate distance
164    function PythagorasEquirectangular(lat1, lon1, lat2, lon2) {
165        lat1 = Deg2Rad(lat1);
166        lat2 = Deg2Rad(lat2);
167        lon1 = Deg2Rad(lon1);
168        lon2 = Deg2Rad(lon2);
169        var R = 6371; // km
170        var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
171        var y = (lat2 - lat1);
172        var d = Math.sqrt(x * x + y * y) * R;
173        return d;
174    }
175    // Convert Degress to Radians
176    function Deg2Rad(deg) {
177        return deg * Math.PI / 180;
178    }
179    // The actual plugin constructor
180    function Plugin(elem, options) {
181        this.element = elem;
182        this.settings = null;
183        this.options = options;
184        this._name = plugin_name;
185        this.map_id = 0;
186        this.places = [];
187        this.places_count = 0;
188        this.google_map = null;
189        this.info_box = null;
190        map_count = 0;
191        geocoder = null;
192    }
193
194    Plugin.prototype = {
195        //init funciton
196        init: function () {
197            var plugin = this,
198                autocomplete,
199                defaults = {
200                    marker: {
201                        icon: null,
202                        width: null,
203                        height: null,
204                        origin_x: null,
205                        origin_y: null,
206                        anchor_x: null,
207                        anchor_y: null,
208                        optimized: null
209                    },
210                    info_box: {
211                        close_button_markup: '<button>x</button>',
212                        width: 200,
213                        offset_x: -100,
214                        offset_y: -50,
215                        align_bottom: true,
216                        close_on_click: true,
217                        disable_auto_pan: false,
218                        info_box_class: 'infobox'
219                    },
220                    search: {
221                        distance: 100,
222                        max_results: 3,
223                        no_results_markup: '<p>Sorry, no places nearby were found.</p>',
224                        nothing_found_markup: '',
225                        result_zoom: 8,
226                        search_results: '',
227                        search_form: '',
228                        autocomplete: false,
229                        clear_button_class: 'buttonAlt buttonOutline',
230                        clear_button_text: 'Clear Results',
231                        url_query_check: false,
232                        url_query_param: ''
233                    },
234                    directions: false,
235                    directions_options: {
236                        directions_form: '.js_googleMapsSearchForm',
237                        directions_output: '.js_mapOutputPanel',
238                        onDirectionsLoad: function () { }
239                    },
240                    map_options: {
241                        mapTypeId: google.maps.MapTypeId.ROADMAP,
242                        disableDefaultUI: false,
243                        scrollwheel: false,
244                        fullscreenControl: false,
245                        streetViewControl: false,
246                        mapTypeControl: false
247                    },
248                    styles: null,
249                    responsive: [
250                        {
251                            breakpoint: 640,
252                            settings: {
253                            }
254                        }
255                    ],
256                    custom_overlay: false
257                };
258
259            this.map_id = map_count;
260            ++map_count;
261
262            // read the settings and sort them by breakpoints
263            plugin.all_settings = $.extend(true, {}, defaults, this.options);
264            plugin.settings = null;
265            plugin.readAllOptions();
266            plugin.checkBreakpoints();
267
268            // trigger map load
269            plugin.loadMaps();
270
271            // stockist search
272            plugin.initSearch();
273
274            if ($(plugin.settings.directions_options.directions_form).length > 0 && plugin.settings.directions === true) {
275                plugin.initDirections();
276            }
277        },
278
279        fitAllBounds: function (b) {
280            var plugin = this;
281            // Get north east and south west markers bounds coordinates
282            var ne = b.getNorthEast(),
283                sw = b.getSouthWest(),
284                map = plugin.google_map;
285            // Get the current map bounds
286            var mapBounds = map.getBounds();
287            // Check if map bounds contains both north east and south west points
288            if (mapBounds.contains(ne) && mapBounds.contains(sw)) {
289                // Everything fits
290                return;
291            } else {
292                var mapZoom = map.getZoom();
293                if (mapZoom > 0) {
294                    // Zoom out
295                    map.setZoom(mapZoom - 1);
296                    // Try again
297                    plugin.fitAllBounds(b);
298                }
299            }
300        },
301
302        initSearch: function () {
303            var plugin = this,
304                search_settings = plugin.settings.search,
305                search_form = $(search_settings.search_form),
306                search_input = search_form.find('input'),
307                search_button = search_form.find('button'),
308                clear_button,
309                results_place = $(search_settings.search_results);
310
311            if (search_form.length > 0 && $(search_settings.search_results).length > 0) {
312
313                //aadd clear results button
314                clear_button = $('<a class="js_clearMapResults ' + search_settings.clear_button_class + '" href="#"></a>');
315                clear_button.html(search_settings.clear_button_text);
316                search_form.append(clear_button);
317
318                //hide the button initially
319                clear_button.hide();
320
321                //button click
322                search_button.on('click', function (e) {
323                    e.preventDefault();
324                    plugin.findAddress();
325
326                    $('.js_error').remove();
327
328                    if (plugin.settings.in_your_area_map === true) {
329                        // reset filter markers
330                        $('.js_mapLabel').removeClass('off');
331                        $('.js_mapLabel .labelToggle').removeClass('off');
332                    }
333
334                });
335
336                $('.js_clearMapResults').on('click', function (e) {
337
338                    var initialLat = $('#initLat').val();
339                    var initialLng = $('#initLong').val();
340
341                    e.preventDefault();
342
343                    //reset the map
344                    plugin.resetMap();
345
346                    // set zoom to focus on Scotland more
347                    plugin.google_map.setZoom(8);
348
349                     // set location to initial lat / lng set in sitecore
350                    var clear_map_position = new google.maps.LatLng(initialLat, initialLng);
351                    plugin.google_map.setCenter(clear_map_position);
352
353                    //clear results
354                    results_place.html('');
355
356                    if (plugin.settings.in_your_area_map === true) {
357                        results_place.html(plugin.settings.search.nothing_found_markup);
358                    }
359
360                    //clear search
361                    search_input.val('');
362                    search_input.focus();
363
364                    //hide the clear button
365                    $('.js_clearMapResults').hide();
366
367                    $('.js_error').remove();
368
369                    if (plugin.settings.in_your_area_map === true) {
370                        // reset filter markers
371                        $('.js_mapLabel').removeClass('off');
372                        $('.js_mapLabel .labelToggle').removeClass('off');
373                    }
374
375                });
376
377                //set autocomplete via geocoder
378                if (search_settings.autocomplete === true) {
379                    autocomplete = new google.maps.places.Autocomplete(search_input.get(0));
380
381                    autocomplete.bindTo('bounds', plugin.google_map);
382
383                    google.maps.event.addListener(autocomplete, 'place_changed', function () {
384                        plugin.findAddress();
385                    });
386                }
387            }
388        },
389
390        initDirections: function () {
391            var plugin = this,
392                directions_options = plugin.settings.directions_options,
393                directions_form = directions_options.directions_form,
394                directions_output = directions_options.directions_output;
395
396            autocomplete = new google.maps.places.Autocomplete($(directions_form).find('input').get(0));
397
398            $('body').on('submit', directions_form, function (e) {
399
400                e.preventDefault();
401
402                // reset the map and directions
403                $(directions_output).empty();
404
405                plugin.loadMaps();
406
407                var directionsDisplay = new google.maps.DirectionsRenderer,
408                    directionsService = new google.maps.DirectionsService,
409                    origin = $(directions_form).find('input').val(),
410                    destination;
411
412                directionsDisplay.setMap(plugin.google_map);
413
414                directionsDisplay.setPanel($(directions_output)[0]);
415
416                destination = plugin.places[0].marker.getPosition().lat() + ", " + plugin.places[0].marker.getPosition().lng();
417
418                plugin.calculateAndDisplayRoute(directionsService, directionsDisplay, origin, destination);
419
420                // callback for when the directions has been added to the map
421                directions_options.onDirectionsLoad();
422            });
423        },
424
425        // calcualte the route between two points
426        calculateAndDisplayRoute: function (directionsService, directionsDisplay, origin, destination) {
427            var plugin = this;
428
429            directionsService.route({
430                origin: origin,
431                destination: destination,
432                travelMode: google.maps.TravelMode.DRIVING,
433                unitSystem: google.maps.UnitSystem.IMPERIAL
434
435            }, function (response, status) {
436                if (status === google.maps.DirectionsStatus.OK) {
437                    directionsDisplay.setDirections(response);
438                } else {
439                    $(plugin.settings.search.directions_output).html('<p class="error">No directions found for this request.</p>');
440                }
441            });
442
443        },
444
445        //resets map state to inital after search
446        resetMap: function () {
447
448            var plugin = this,
449                bounds;
450
451            if (plugin.places.length > 0) {
452                bounds = new google.maps.LatLngBounds();
453                bounds.extend(plugin.places[0].marker.getPosition());
454
455                //if 'you' position is there hide it
456                if (typeof plugin.places.you !== 'undefined') {
457                    plugin.places.you.setVisible(false);
458                }
459
460                //if loop through all places
461                $.each(plugin.places, function () {
462
463                    //set visible
464                    this.marker.setVisible(true);
465
466                    bounds.extend(this.marker.getPosition());
467                    plugin.fitAllBounds(bounds);
468                });
469            }
470        },
471
472        resetMarkers: function () {
473            var plugin = this;
474
475            if (plugin.places.length > 0) {
476
477                //if 'you' position is there, don't hide it
478                if (typeof plugin.places.you !== 'undefined') {
479                    plugin.places.you.setVisible(true);
480                }
481
482                //if loop through all places
483                $.each(plugin.places, function () {
484                    // bring back markers
485                    this.marker.setVisible(true);
486                });
487            }
488        },
489
490        // prepare the responsive array
491        readAllOptions: function () {
492            var plugin = this,
493                previous_breakpoints_settings = plugin.all_settings;
494
495
496            if (plugin.all_settings.responsive) {
497
498                // loop through responsive settings
499                $.each(plugin.all_settings.responsive, function (i, value) {
500                    // extend breakpoints settings to include ones from previous
501                    value.settings = $.extend(true, {}, previous_breakpoints_settings, value.settings);
502                    // get rid of responsive duplicate
503                    delete value.settings.responsive;
504                    // previous now become the current ones
505                    previous_breakpoints_settings = value.settings;
506                });
507
508            }
509        },
510        // go through the responsive settings and find the appropriate
511        checkBreakpoints: function () {
512            var window_width = $(window).width(),
513                plugin = this;
514
515            // set the default as desktop
516            plugin.settings = plugin.all_settings;
517            // iterate through settings and find the right one
518            if (plugin.all_settings.responsive) {
519
520                // loop through responsive settings
521                $.each(plugin.all_settings.responsive, function (i, value) {
522                    // find one that is active
523                    if (matchesMediaQuery(0, value.breakpoint)) {
524                        plugin.settings = value.settings;
525                    }
526                });
527            }
528
529        },
530
531
532        //plugin data to google maps
533        initMap: function (map) {
534            var plugin = this,
535                zoom = 8,
536                mapOptions,
537                infobox_options,
538                bounds = new google.maps.LatLngBounds(),
539                myLatlng,
540                contentString;
541
542            var initialLat = $('#initLat').val();
543            var initialLng = $('#initLong').val();
544
545            // handle on / off of map labels and also showing / hiding these within list view
546            $('body').on('swipe click', '.js_mapLabel', function (e) {
547                e.preventDefault();
548               
549                var category_code = $(this).data('category-code'),
550                    state = true;
551
552                $(this).toggleClass('off');
553                $(this).children('.labelToggle').toggleClass('off');
554
555                if ($(this).hasClass('off')) {
556                    state = false;
557                    // hide ones within list view too
558                    $('li[data-category-code="' + category_code + '"]').fadeOut();
559                } else {
560                    state = true;
561                    // show ones within list view too
562                    $('li[data-category-code="' + category_code + '"]').fadeIn();
563                }
564
565                $.each(plugin.places, function (i, value) {
566                    if (typeof (value.category_code) !== 'undefined' && value.category_code === category_code) {
567                        value.marker.setVisible(state);
568                    }
569                });
570            });
571
572            plugin.google_map = new google.maps.Map(map, plugin.settings.map_options);
573
574            // show markers on drag end, but only if filter is not selected / enabled
575            google.maps.event.addListener(plugin.google_map, 'dragend', function () {
576                labelFilters(plugin);
577            });
578
579            if (plugin.places > 0) {
580                plugin.google_map.setCenter(new google.maps.LatLng(plugin.places[0].coords[0], plugin.places[0].coords[1]));
581            }
582
583            if (typeof ($(map).data('zoom')) !== "undefined") {
584                zoom = $(map).data('zoom');
585            }
586
587            plugin.google_map.setZoom(zoom);
588
589            if (typeof (plugin.settings.styles) !== 'undefined') {
590                plugin.google_map.setOptions({
591                    styles: plugin.settings.styles
592                });
593            }
594
595            infobox_options = {
596                alignBottom: plugin.settings.info_box.align_bottom,
597                content: 'loading..',
598                disableAutoPan: plugin.settings.disable_auto_pan,
599                maxWidth: 0,
600                pixelOffset: new google.maps.Size(plugin.settings.info_box.offset_x, plugin.settings.info_box.offset_y),
601                zIndex: null,
602                boxStyle: {
603                    width: plugin.settings.info_box.width + "px"
604                },
605                closeBoxMargin: "0",
606                closeButtonMarkup: plugin.settings.info_box.close_button_markup,
607                infoBoxClearance: new google.maps.Size(1, 1),
608                isHidden: false,
609                pane: "floatPane",
610                enableEventPropagation: false,
611                boxClass: plugin.settings.info_box.info_box_class
612            };
613
614            plugin.info_box = new InfoBox(infobox_options);
615
616            $.each(plugin.places, function (i, value) {
617
618                var marker_icon, marker_image = null;
619
620                // if no specific marker icon for coordinates
621                if (typeof (value.marker_icon) !== 'undefined') {
622                    marker_icon = value.marker_icon;
623
624                    // if icon is defined in settings
625                } else if (typeof (plugin.settings.marker.icon) !== 'undefined') {
626                    marker_icon = plugin.settings.marker.icon;
627                }
628
629                myLatlng = new google.maps.LatLng(value.coords[0], value.coords[1]);
630
631                value.marker = new google.maps.Marker({
632                    position: myLatlng,
633                    map: plugin.google_map,
634                    optimized: false
635                });
636
637                if (typeof (marker_icon) !== 'undefined' && plugin.settings.marker.width !== null) {
638                    marker_image = {
639                        url: marker_icon,
640                        size: new google.maps.Size(plugin.settings.marker.width, plugin.settings.marker.height),
641                        origin: new google.maps.Point(plugin.settings.marker.origin_x, plugin.settings.marker.origin_y),
642                        anchor: new google.maps.Point(plugin.settings.marker.anchor_x, plugin.settings.marker.anchor_y),
643                        scaledSize: new google.maps.Size(plugin.settings.marker.width, plugin.settings.marker.height)
644                    };
645                    value.marker.setIcon(marker_image);
646                } else if (typeof (marker_icon) !== 'undefined') {
647                    marker_image = marker_icon;
648                    value.marker.setIcon(marker_image);
649                }
650
651                bounds.extend(value.marker.getPosition());
652
653                //add title and description
654                if (typeof (value.description) !== 'undefined' || typeof (value.title) !== 'undefined') {
655                    value.marker.addListener('click', function () {
656                        var titleMarkup = "",
657                            descriptionMarkup = "";
658
659                        if (typeof (value.description) !== 'undefined') {
660                            descriptionMarkup = value.description;
661                        }
662
663                        if (typeof (value.title) !== 'undefined') {
664                            titleMarkup = '<h3>' + value.title + '</h3>';
665                        }
666
667                        plugin.info_box.setContent('<div class="info_boxContent">' + titleMarkup + descriptionMarkup + '</div>');
668                        plugin.info_box.open(plugin.google_map, value.marker);
669                    });
670                }
671
672                // custom marker type, used within in your area map
673                if (plugin.settings.in_your_area_map === true) {
674                    if (typeof (value.category_code) !== 'undefined' || typeof (value.marker_id) !== 'undefined') {
675                        value.marker.addListener('click', function () {
676                            var marker_type = value.marker_type,
677                                marker_id = value.marker_id,
678                                overlay_content = value.overlay_content,
679                                title = overlay_content.overlay_title,
680                                content = overlay_content.overlay_content,
681                                link = overlay_content.link;
682                                incidentNumber = overlay_content.incident_number;
683
684                            // handle custom overlay if setting is true, built from json
685                            if (plugin.settings.custom_overlay !== false && overlay_content !== '') {
686                                $.openMtcOverlay({
687                                    no_ajax: true,
688                                    target: '#inAreaMapOverlay',
689                                    content_class: 'contentOverlayWrap',
690                                    perfect_scroll: false,
691                                    max_width: 820,
692                                    button_html: '<div class="overlayCloseButton"><a href="#" class="closeButton"><img src="/sites/scottishwater/images/svgs/close-icon.svg" alt="Close"></a></div>',
693                                    beforeOpen: function () {
694                                        var element = $('.contentOverlay');
695
696                                        element.find('h2').html(title);
697                                        element.find('.pageContent').html(content);
698
699                                        // if link is empty in json
700                                        if (link === '') {
701                                            element.find('.button').hide();
702                                        } else {
703                                            element.find('.button').show().attr('href', link);
704                                        }
705                                        if (incidentNumber == '' || incidentNumber == undefined) {
706                                            element.find('.btnIncident').hide();
707                                        } else {
708                                            var crmlink = $('#crmLink').val();
709                                            if (crmlink == undefined || crmlink == null || crmlink == '') {
710                                                crmlink = 'https://swcustomerportal.microsoftcrmportals.com/ReportAProblem?casenumber=';
711                                            }
712                                            var url = crmlink + incidentNumber;
713                                            element.find('.btnIncident').show().attr('href', url);
714                                        }
715                                    }
716                                });
717                            }
718                        });
719                    }
720                }
721            });
722
723            if (plugin.settings.info_box.close_on_click === true) {
724                google.maps.event.addListener(plugin.google_map, 'click', function () {
725                    plugin.info_box.close();
726                });
727            }
728
729            if (plugin.places.length > 1) {
730                plugin.google_map.fitBounds(bounds);
731                plugin.google_map.panToBounds(bounds);
732            }
733
734            google.maps.event.addDomListener(window, "resize", function () {
735                var center = plugin.google_map.getCenter();
736                google.maps.event.trigger(plugin.google_map, "resize");
737                plugin.google_map.setCenter(center);
738            });
739
740            // check for query string in first instance, if none, fall back to cookie check, before falling back to default location
741            if (plugin.settings.search.url_query_check === true && plugin.settings.search.url_query_param !== '' && $.QueryString[plugin.settings.search.url_query_param]) {
742                var query_param = $.QueryString[plugin.settings.search.url_query_param];
743
744                if (query_param) {
745                    plugin.findAddress(query_param);
746
747                    // in your area map, populate location field
748                    if (plugin.settings.in_your_area_map === true) {
749                        $('.js_inYourAreaLocationInput').val(query_param);
750                    }
751                }
752            } else if (Cookies.getJSON('HTML5GeoLocation')) {
753                var cookie = Cookies.getJSON('HTML5GeoLocation'),
754                    user_postcode;
755
756                if (cookie.UserEnteredPostalCode === null) {
757                    user_postcode = cookie.PostalCode;
758                } else {
759                    user_postcode = cookie.UserEnteredPostalCode;
760                }
761
762                plugin.findAddress(user_postcode);
763
764                // in your area map, populate location field
765                if (plugin.settings.in_your_area_map === true) {
766                    $('.js_inYourAreaLocationInput').val(user_postcode);
767                }
768            } else {
769                // set component restriction to false so lat / long can be used for location detection
770                var component_restriction = false;
771                plugin.findAddress(initialLat + ',' + initialLng, component_restriction);
772
773                // show markers on zoom in / out, but only on initial load
774                google.maps.event.addListener(plugin.google_map, 'zoom_changed', function () {
775                    labelFilters(plugin);
776                });
777            }
778        },
779
780        //reads data to plugin
781        loadMaps: function () {
782
783            google.maps.visualRefresh = true;
784
785            var mapEl = $(this.element),
786                mapMode,
787                plugin = this,
788                place,
789                mapId;
790
791            geocoder = new google.maps.Geocoder();
792            //for each map
793            mapEl.each(function (index, map) {
794                var place = {},
795                    zoomListener;
796
797                place.map_id = plugin.id;
798
799                // one or multiple coordinates
800                if ($(map).data('coords')) {
801                    mapMode = 'single';
802                } else if ($(map).data('coords-array')) {
803                    mapMode = 'multiple';
804                } else if ($(map).data('json-array')) {
805                    mapMode = 'json';
806                } else if ($(map).data('json-markers-array')) {
807                    mapMode = 'markers';
808                }
809
810                mapId = map_count - 1;
811
812                $(map).attr('id', 'map' + mapId);
813
814                //set map options
815                if (mapMode === 'single') {
816
817                    place.coords = $(map).data('coords').split(',');
818
819                    if (typeof ($(map).data('marker-icon')) !== 'undefined') {
820                        place.marker_icon = $(map).data('marker-icon');
821                    }
822                    if (typeof ($(map).data('title')) !== 'undefined') {
823                        place.title = $(map).data('title');
824                    }
825                    if (typeof ($(map).data('description')) !== 'undefined') {
826                        place.description = $(map).data('description');
827                    }
828
829                    plugin.places[plugin.places_count] = jQuery.extend({}, place);
830                    ++plugin.places_count;
831
832                } else if (mapMode === 'multiple') {
833                    var coordsArrayHolder = $($(this).data('coords-array')),
834                        coordsArray = coordsArrayHolder.find('[data-coords]');
835
836                    if (coordsArray.length > 0) {
837                        coordsArray.each(function (i, el) {
838                            place.coords = $(this).data('coords').split(',');
839
840                            place.marker_icon = $(this).data('marker-icon');
841
842                            if (typeof ($(map).data('title-selector')) !== 'undefined') {
843                                place.title = $(this).find($(map).data('title-selector')).html();
844                                var link = $('<a/>', {
845                                    href: "#",
846                                    "data-map-id": map_count - 1,
847                                    "data-place-id": i,
848                                    class: 'js_focusMarker'
849                                });
850
851                                $(this).find($(map).data('title-selector')).wrapInner(link);
852                            }
853
854                            if (typeof ($(map).data('description-selector')) !== 'undefined') {
855                                place.description = $(this).find($(map).data('description-selector')).html();
856                            }
857
858                            // $(this).data('marker-id', plugin.places.length);
859                            plugin.places[plugin.places_count] = jQuery.extend({}, place);
860                            ++plugin.places_count;
861                        });
862                    }
863
864                } else if (mapMode === 'json') {
865                    var arr = window[$(this).data('json-array')];
866                    $.each(arr, function (i, el) {
867                        place.coords = el.coords.split(',');
868
869                        if (typeof (el.marker_icon) !== 'undefined') {
870                            place.marker_icon = el.marker_icon;
871                        }
872
873                        if (typeof (el.title) === 'string') {
874                            place.title = el.title;
875                        }
876
877                        if (typeof (el.description) === 'string') {
878                            place.description = el.description;
879                        }
880
881                        plugin.places[plugin.places_count] = jQuery.extend({}, place);
882                        ++plugin.places_count;
883                    });
884                } else if (mapMode === 'markers') {
885                    var arr = window[$(this).data('json-markers-array')];
886
887                    $.each(arr, function (i, el) {
888                        place.coords = el.coords.split(',');
889
890                        if (typeof (el.marker_icon) !== 'undefined') {
891                            place.marker_icon = el.marker_icon;
892                        }
893
894                        if (typeof (el.title) === 'string') {
895                            place.title = el.title;
896                        }
897
898                        if (typeof (el.description) === 'string') {
899                            place.description = el.description;
900                        }
901
902                        // add custom data to places, specific to in your area map
903                        if (plugin.settings.in_your_area_map === true) {
904                            if (typeof (el.category_code) === 'string') {
905                                place.category_code = el.category_code;
906                            }
907
908                            if (typeof (el.marker_id) !== 'undefined') {
909                                place.marker_id = el.marker_id;
910                            }
911
912                            if (typeof (el.overlay_content) !== 'undefined') {
913                                place.overlay_content = el.overlay_content;
914                            }
915
916                            if (typeof (el.group) === 'string') {
917                                place.group = el.group;
918                            }
919                        }
920
921                        plugin.places[plugin.places_count] = jQuery.extend({}, place);
922                        ++plugin.places_count;
923                    });
924                }
925
926                plugin.initMap(map);
927
928            });
929        },
930
931        findAddress: function (address, component_restriction) {
932            var plugin = this,
933                address = (address != undefined) ? address : $(plugin.settings.search.search_form + ' input').val(),
934                results_place = $(plugin.settings.search.search_results),
935                i,
936                place,
937                html,
938                you_icon,
939                request;
940
941            if (component_restriction === false && component_restriction !== undefined) {
942                // remove restriction as this will only be used with direct lat / long set by scottish water
943                request = {
944                    address: address
945                };
946            } else {
947
948                // pass country restriction on search terms via google api component restrictions
949                // limits search queries to the UK only
950                request = {
951                    address: address,
952                    componentRestrictions: {
953                        country: 'UK'
954                    }
955                };
956            }
957            geocoder.geocode(request, function (results, status) {
958
959                var bounds = new google.maps.LatLngBounds();
960
961                if (status === google.maps.GeocoderStatus.OK) {
962
963                    if (typeof plugin.places.you !== 'undefined') {
964                        plugin.places.you.setMap(null);
965                        delete plugin.places.you;
966                    }
967
968                    you_icon = {
969                        url: '/sites/scottishwater/images/svgs/map_markers/map-marker-you.svg',
970                        scaledSize: new google.maps.Size(20, 27)
971                    };
972
973                    plugin.places.you = new google.maps.Marker({
974                        position: results[0].geometry.location,
975                        map: plugin.google_map,
976                        icon: you_icon,
977                        title: 'You',
978                        address: results[0].formatted_address,
979                    });
980
981                    var sorted_points = sortPointsByProximity(results[0].geometry.location, plugin.places, plugin.settings.search.distance),
982                        nearest_point_key = getFirstKey(sorted_points);
983                    //reset results
984
985                    results_place.html('');
986
987                    $.each(plugin.places, function () {
988                        this.marker.setVisible(false);
989                    });
990
991                    //start bounds from search place
992                    bounds.extend(plugin.places.you.getPosition());
993
994                    //if results then show
995                    if (sorted_points.length > 0) {
996
997                        // very specific grouping and list view markup for in your area map
998                        if (plugin.settings.in_your_area_map === true) {
999
1000                            // set up grouping for list items based on "group" json value being the same
1001                            var grouped = [],
1002                                inner_html;
1003
1004                            for (var i in sorted_points) {
1005                                if (i >= plugin.settings.search.max_results) {
1006                                    return false;
1007                                };
1008
1009                                // make sorted points usable
1010                                place = plugin.places[sorted_points[i].id];
1011
1012                                // push them to grouped variable
1013                                grouped.push(place);
1014                            }
1015
1016                            // set up grouping, puts matching elements in same array, with "group" from json as key
1017                            var final_groups = grouped.reduce(function (result, current) {
1018                                result[current.group] = result[current.group] || [];
1019                                result[current.group].push(current);
1020                                return result;
1021                            }, {});
1022
1023                            // loop through groups to generate appropriate markup for list
1024                            $.each(final_groups, function (index, value) {
1025                                // empty inner html to avoid duplicates
1026                                inner_html = '';
1027
1028                                // loop through coords individually to get usable list elements
1029                                $.each(value, function (i, data) {
1030                                    inner_html += '<li data-category-code="' + data.category_code + '"><a href="#" class="js_inYourAreaOverlay" data-no-ajax="true" data-marker-id="' + data.marker_id + '"><span class="areaMapIcon"><img src="' + data.marker_icon + '" alt="' + data.category_code + ' Icon"></span>' + data.overlay_content.overlay_title + ' <i class="fa fa-angle-right" aria-hidden="true"></i></a></li>';
1031
1032                                    bounds.extend(data.marker.getPosition());
1033
1034                                    //plugin.google_map.fitBounds(bounds);
1035                                    // Center and fit all bounds in view
1036                                    if (typeof plugin.places.you !== 'undefined') {
1037                                        plugin.google_map.setCenter(plugin.places.you.getPosition());
1038                                    }
1039                                    plugin.google_map.setZoom(14);
1040                                    plugin.fitAllBounds(bounds);
1041
1042                                    data.marker.setVisible(true);
1043                                });
1044
1045                                // build html from above loops
1046                                html = '<div class="areaMapList js_areaMapList"><h2>' + index + '</h2><ul>' + inner_html + '</ul></div>';
1047
1048                                // append to page
1049                                results_place.append(html);
1050                            });
1051                            // Bound changed listener
1052                            google.maps.event.addListenerOnce(plugin.google_map, 'bounds_changed', function () {
1053                                var current_zoom = this.getZoom();
1054                                // Min zoom level when only 1 marker within radius
1055                                if (grouped.length < 2) {
1056                                    this.setZoom(Math.min(8, current_zoom));
1057                                }
1058                            });
1059
1060                        } else {
1061                            // generic list view markup
1062                            for (var i in sorted_points) {
1063
1064                                if (i >= plugin.settings.search.max_results) {
1065                                    return false;
1066                                };
1067
1068                                place = plugin.places[sorted_points[i].id];
1069
1070                                html = '<li><h3><a href="" data-map-id="' + plugin.map_id + '" data-place-id="' + sorted_points[i].id + '" class="js_focusMarker">' + place.title + ' <i class="fa fa-caret-right"></i></a></h3><div class="description">' + place.description + '</div></li>'
1071
1072                                bounds.extend(place.marker.getPosition());
1073
1074                                plugin.google_map.fitBounds(bounds);
1075
1076                                results_place.append(html);
1077
1078                                place.marker.setVisible(true);
1079
1080                            }
1081                        }
1082
1083                        if (plugin.settings.in_your_area_map === true) {
1084                            $('.js_nothingInAreaText').remove();
1085                            $('.js_mapNothingFound').remove();
1086                        }
1087
1088                        //show clear results button
1089                        $('.js_clearMapResults').show();
1090
1091                        //if no results
1092                    } else {
1093                        plugin.google_map.setCenter(plugin.places.you.getPosition());
1094
1095                        if (component_restriction === false && component_restriction !== undefined) {
1096                            // if initial value is being used (as no location or search done) then set zoom a little higher
1097                            plugin.google_map.setZoom(7);
1098                        } else {
1099                            // else, just work as normal
1100                            plugin.google_map.setZoom(plugin.settings.search.result_zoom);
1101                        }
1102                        if (plugin.settings.in_your_area_map === true) {
1103                            if ($('.js_nothingInAreaText').length < 1) {
1104                                $(plugin.settings.search.search_form).append(plugin.settings.search.no_results_markup);
1105                            }
1106                            results_place.html(plugin.settings.search.nothing_found_markup);
1107                            $('.js_clearMapResults').hide();
1108                        } else {
1109                            results_place.append(plugin.settings.search.no_results_markup);
1110                        }
1111                    }
1112
1113                    // hide these
1114                    $('.js_error').remove();
1115
1116                    if (plugin.settings.in_your_area_map === true) {
1117                        // reset filter markers
1118                        $('.js_mapLabel').removeClass('off');
1119                        $('.js_mapLabel .labelToggle').removeClass('off');
1120                    }
1121
1122                } else if (status === google.maps.GeocoderStatus.ZERO_RESULTS) {
1123                    if ($('.js_error').length < 1) {
1124                        $(plugin.settings.search.search_form).append('<p class="error js_error">Please enter a valid location.</p>');
1125                        $('.js_clearMapResults').hide();
1126                    }
1127
1128                    if (plugin.settings.in_your_area_map === true) {
1129                        $('.js_nothingInAreaText').remove();
1130                    }
1131
1132                    if (plugin.settings.in_your_area_map === true) {
1133                        // reset filter markers
1134                        $('.js_mapLabel').removeClass('off');
1135                        $('.js_mapLabel .labelToggle').removeClass('off');
1136                    }
1137
1138                } else if (status === google.maps.GeocoderStatus.INVALID_REQUEST) {
1139                    if ($('.js_error').length < 1) {
1140                        $(plugin.settings.search.search_form).append('<p class="error js_error">Please enter your location.</p>');
1141                        $('.js_clearMapResults').hide();
1142                    }
1143
1144                    if (plugin.settings.in_your_area_map === true) {
1145                        $('.js_nothingInAreaText').remove();
1146                    }
1147
1148                    if (plugin.settings.in_your_area_map === true) {
1149                        // reset filter markers
1150                        $('.js_mapLabel').removeClass('off');
1151                        $('.js_mapLabel .labelToggle').removeClass('off');
1152                    }
1153
1154                }
1155            });
1156            return false;
1157        },
1158
1159        setOptions: function (options) {
1160            var currentOptions = this.settings;
1161            this.settings = $.extend(true, {}, currentOptions, options);
1162        }
1163    }
1164}(jQuery, window, document));

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.