PageSourceSearch

https://www.sentaracareers.com/wp-content/plugins/cws/js/cws.map.js?ver=4.5.4-309

js sentaracareers.com collected 2026-10-05 00:58:05 UTC 28,509 bytes, 706 lines download raw bytes

1/*
2 Developed by Nick Bowman ([email protected])
3 Copyright 2015 Hodes
4 */
5var CWS = CWS || {};
6
7var previous_map = previous_map || null;
8var previous_router = previous_router|| null;
9var previous_map_router = previous_map_router || true;
10
11CWS.map = (function (w, $) {
12    var options = {
13            high_volume: false,
14            marker_clustering: true,
15            display_loading_bar: true, //CWS-4574/CWS-4576 added for showing and hiding loader
16            cluster_radius: 40,
17            custom_marker: false,
18            starting_coords: [39.2037532, -96.6201883],
19            starting_zoom: 3,
20            max_zoom: 13,
21            fit_bounds: true,
22            tilemap: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
23            api_url: 'http://jobsapi-internal.cert.m-cloud.io/api/map',
24            jobdetail_path: '/job',
25            org_id: 1927,
26            wait_for_searchform: false,
27            include_geolocation: true,
28            include_directions: true,
29            custom_popup: false
30        },
31        filters = {},
32        map,
33        markers,
34        geojson,
35        router,
36        router_on_map = false,
37        jobs = {},
38        stores = {},
39        stores_exist = false,
40        arrow_icon = '<span class="job-arrow avia-font-entypo-fontello">&#xe875</span>',
41        popup_loader,
42        current_criteria = {};
43
44
45    var search_jobs = function (criteria, loader) {
46        // Criteria should always be set, but just in case...
47        criteria = criteria || {};
48        criteria.Organization = options.org_id;
49
50        if (filters.length > 0) {
51            if (criteria['facet']) {
52                // Underscore's union() removes duplicate keys... probably not necessary but it's cleaner
53                criteria['facet'] = _.union(criteria['facet'], filters);
54            }
55            else {
56                // No existing filters from the search form exist
57                criteria['facet'] = filters;
58            }
59        }
60
61        if(CWS.jobs && CWS.jobs.get_option('filter_od')){
62            criteria.openeddate = CWS.jobs.get_option('filter_od');
63        }
64		
65        // Maxing out at 500, enable high_volume setting if
66        criteria.Limit = 500;
67        delete criteria.offset;
68        if(criteria.hasOwnProperty('facetlist')){
69            delete criteria.facetlist;
70        }
71
72        if (options.high_volume) {
73            criteria.Limit = 0;
74            if(!criteria.hasOwnProperty('facetlist')){
75                criteria['facetlist'] = [];
76            }
77            criteria['facetlist'].push('coordinates');
78        }
79
80        if(CWS.jobs && CWS.jobs.get_option('use_boolean_search')){
81            criteria.useBooleanKeywordSearch = 'true';
82        }
83
84        current_criteria = criteria;
85
86        $.ajax({
87            url: CWS.apply_filter('map_api_url', options.api_url),
88            data: CWS.apply_filter('map_criteria', criteria),
89            dataType: 'jsonp',
90            crossDomain: true,
91            cache: true,
92            jsonpCallback: 'CWS.map.mapCallback',
93            //success: display_jobs,
94            complete: function () {
95                if (loader) {
96                    loader.end();
97                    $('.widget-jobsearch-results').find('.search-results-table').attr("aria-busy","false");
98                }
99            }
100        });
101    };
102
103    var display_jobs = function (data) {
104        data = CWS.apply_filter('job_map_search_response', data);
105        if (markers) {
106            map.removeLayer(markers);
107            jobs = {};
108
109            if (router_on_map) {
110                map.removeControl(router);
111            }
112        }
113        if (options.marker_clustering) {
114            var cluster_options = {maxClusterRadius: options.cluster_radius};
115            cluster_options = CWS.apply_filter('marker_cluster_options', cluster_options);
116            markers = new Leaflet.MarkerClusterGroup(cluster_options);
117        }
118
119        stores_exist = false;
120
121        var dataset = options.high_volume ? ('markers' in data ? data.markers : data.aggregations.coordinates.buckets) : data.queryResult;
122
123        for (var i = 0, len = dataset.length; i < len; i++) {
124            var marker_opts = {};
125            if (options.custom_marker !== false) {
126                // I have it set so that the icon options format comes from the widget settings correctly
127                marker_opts.icon = new Leaflet.icon(CWS.apply_filter('marker_icon_options', options.custom_marker, dataset[i]));
128            }
129
130            // For now, only some clients can use the new coordinates-by-aggregation, so there's going to be some duplicating code
131            if (options.high_volume) {
132                CWS.apply_filter('map_marker_data', dataset[i]);
133                var job = dataset[i].key;
134                var coords = job.split(',');
135                var marker = new Leaflet.Marker([coords[1].trim(), coords[0]], CWS.apply_filter('marker_options', marker_opts, dataset[i]))
136                    .bindPopup('')
137                    .on('popupopen', get_jobs_at_coords);
138
139                marker.orig_coords = job;
140
141                marker = CWS.apply_filter('marker_init', marker, dataset[i]);
142
143                markers.addLayer(marker);
144            }
145
146            // Original endpoint
147            else {
148                var job = dataset[i];
149                if (job) {
150                    var coord_text = job.primary_location[1] + ',' + job.primary_location[0];
151                    // We're going to group jobs into an array if they have the same coordinates
152                    if (typeof jobs[coord_text] === 'undefined') {
153                        var marker = new Leaflet.Marker([job.primary_location[1], job.primary_location[0]], CWS.apply_filter('marker_options', marker_opts, dataset[i]))
154                            // We'll be setting popup content on-click
155                            .bindPopup('')
156                            .on('popupopen', popup_open);
157
158                        markers.addLayer(marker);
159
160                        jobs[coord_text] = [];
161                        jobs[coord_text].push(job);
162
163                        if (job.store_id) {
164                            stores_exist = true;
165                        }
166                    }
167                    else {
168                        jobs[coord_text].push(job);
169                    }
170                }
171            }
172        }
173
174        geojson = CWS.apply_filter('map_geojson', geojson, map, data);
175
176        // Unfortunately another loop is needed for stores
177        // But at least we check if there are any store ids in the first loop, so this'll be ignored for most clients
178        if (stores_exist) {
179            for (var coords in jobs) {
180                // Nifty underscore function
181                stores[coords] = _.groupBy(jobs[coords], function (jb) {
182                    return jb.store_id;
183                });
184            }
185        }
186
187        map.addLayer(markers);
188        if (markers.getLayers().length > 0 && options.fit_bounds) {
189            map.fitBounds(markers.getBounds(), {maxZoom: 12});
190        }
191        if (dataset.length == 0) {
192            map.setView(options.starting_coords, options.starting_zoom, {animate: true});
193        }
194
195        map = CWS.apply_filter('map_layers_complete', map, markers, geojson);
196        /*if (!initial==) {
197
198            initial.center = map.getCenter();
199            initial.zoom = map.getZoom();
200            map.setView(initial.center, initial.zoom)
201        }*/
202        
203            
204    };
205
206    var popup_open = function (popup, data) {
207        // to clear previous layer
208        if (previous_router != null && previous_map_router) {
209            previour_map.removeControl(previous_router);
210        } else {
211            previous_map_router = true;
212        }
213
214        if(CWS.buttons.theme() === 'zephyr'){
215            arrow_icon = '<i class="mdfi_navigation_chevron_right job-arrow"></i>';
216        }
217
218        // Well this is kinda stupid on Leaflet's part...
219        popup = popup.popup;
220        var html = '';
221        var count = 0;
222
223        if(options.custom_popup){
224            html = CWS.apply_filter('map_custom_popup', html, data);
225            popup.setContent(html);
226            popup.update();
227        }
228        else {
229            var coords = popup.getLatLng().lat + ',' + popup.getLatLng().lng;
230
231            var dataset = options.high_volume ? data.queryResult : jobs[coords];
232
233            var len = dataset.length;
234            var totalJobs = data.totalHits;
235            var $popup = $('<div/>').html(popup.getContent()).contents();
236
237            $popup.find('.location-jobcount').html(' - ' + totalJobs + ' opening' + (totalJobs > 1 ? 's' : ''));
238
239            // Popup pin variable search starts
240
241            var pinned_city = '';
242            var pinned_primary_city = '';
243            var pinned_state = '';
244            var pinned_primary_state = '';	
245            var pin_longitude = popup.getLatLng().lng;
246            var pin_latitude = popup.getLatLng().lat;
247
248            if(typeof pin_longitude !== 'undefined' && typeof pin_latitude !== 'undefined' ){    
249
250                var is_city_found = 0;
251
252                function find_jobs_with_add_locations(item, index){
253
254                    // It will check against only first item, if it does not have 'addtnl_locations' property defined (specifically for ES jobs API). Note: Google jobs API dataset object item pass blank string [] in case if it does not have any 'addtnl_locations' value that would let him to go into 'if' block.
255
256                    if (typeof item.addtnl_locations !== 'undefined'){
257
258                        if(item.addtnl_locations.length > 0){			
259
260                            function location_obj(item2, index2){
261                                
262                                if (typeof item2.addtnl_location !== 'undefined'){    
263
264                                    if( item2.addtnl_location.length == 2 ){
265                                        
266                                        if( item2.addtnl_location[0] == pin_longitude && item2.addtnl_location[1] == pin_latitude ){
267
268                                            if( typeof item2.addtnl_city !== 'undefined' && typeof item2.addtnl_state !== 'undefined' && typeof item2.addtnl_country !== 'undefined' ){
269
270                                                // if respective city/state is found, it will pass control out of location_obj iteration.
271
272                                                pinned_city = item2.addtnl_city;
273                                                pinned_state = item2.addtnl_country === 'US' ? item2.addtnl_state : item2.addtnl_country;
274                                                is_city_found = 1;
275                                                return true; 
276
277                                            }
278
279                                        }
280
281                                    }
282
283                                }    
284
285                            }
286                        
287                            item.addtnl_locations.find(location_obj);
288                            
289                            if(is_city_found == 1){
290                                return true;
291                            }
292                            
293                        }
294
295                    }else{
296                        // In case of ES API - There is no 'addtnl_locations' object property
297                        return true;
298                    }    
299                        
300                }
301                
302                dataset.find(find_jobs_with_add_locations);
303                
304                if ( pinned_city !== '' && pinned_state !== '' ) {
305                    pinned_primary_city = pinned_city;
306                    pinned_primary_state = pinned_state;
307                }else{
308                    pinned_primary_city = dataset[0].primary_city;
309                    pinned_primary_state = dataset[0].primary_country === 'US' ? dataset[0].primary_state : dataset[0].primary_country;
310                }	
311
312            }else{
313                // in case we don't get coordinates longitude and latitude values    
314                pinned_primary_city = dataset[0].primary_city;
315                pinned_primary_state = dataset[0].primary_country === 'US' ? dataset[0].primary_state : dataset[0].primary_country;
316            }    
317
318            // Popup pin variable search Ends
319
320            html += '<div class="location-header">' + pinned_primary_city + ', ' + pinned_primary_state + '<span class="location-jobcount"> - ' + totalJobs + ' ' + (totalJobs > 1 ? CWS._('openings') : CWS._('opening')) + '</span></div>'
321                + '<div id="map-jobs-container" class="map-jobs">';
322
323            if (stores_exist === false || (data && !data[0].store_id)) {
324
325                let result = processJobs(dataset, html, count);
326                html = result.html;
327                count = result.count;
328
329            }
330            // If we have store ids, they're grouped a bit differently
331            // TODO: repetitive code needs to be cleaned up
332            else {
333                var count = 0;
334                for (var store in stores[coords]) {
335                    // Jobs with missing store id are just empty strings, we want to do those last
336                    // We want store names bolded before its list of jobs, then go back and list ones without store names
337                    if (store != '') {
338                        for (var i = 0, len = stores[coords][store].length; i < len; i++) {
339                            var job = stores[coords][store][i];
340
341                            if (i === 0) {
342                                html += '<div class="store"><div class="store-name">' + store + '</div>';
343                            }
344
345                            var joburl = options.jobdetail_path + '/' + job.id + '/' + CWS.seo_url(job);
346                            html += '<a href="' + joburl + '" class="map-job ' + (i % 2 == 0 ? '' : 'alt') + '">'
347                                + arrow_icon
348                                + '<span class="title">' + job.title + '</span>'
349                                + '</a>';
350
351                            count++;
352                        }
353
354                        html += '</div>'; // .store
355                    }
356                }
357
358                // Ugh more repetition
359                // This ensures jobs without store names are last
360                if (stores[coords]['']) {
361                    if (html != '') {
362                        html += '<div class="no-stores"><div class="store-name">Other stores</div>';
363                    }
364
365                    for (var i = 0, len = stores[coords][''].length; i < len; i++) {
366                        var job = stores[coords][''][i];
367                        var joburl = options.jobdetail_path + '/' + job.id + '/' + CWS.seo_url(job);
368                        html += '<a href="' + joburl + '" class="map-job ' + (i % 2 == 0 ? '' : 'alt') + '">'
369                            + arrow_icon
370                            + '<span class="title">' + job.title + '</span>'
371                            + '</a>';
372
373                    }
374
375                    html += '</div>'; // .no-stores
376                }
377            }
378
379            html += '<div id="map-job-sentinel"></div> </div>'; // .map-jobs
380
381            popup.setContent(CWS.apply_filter('map_popup_html', html));
382            popup.update();
383
384            var dir_content = '&#xe843;', dir_class = 'directions';
385            if ($('body.l-body'.length)) {
386                dir_class = 'mdfi_maps_directions';
387                dir_content = '';
388            }
389            if (options.include_directions) {
390                $('.leaflet-popup').prepend('<a href="#" class="' + dir_class + '" title="Get Directions" onclick="CWS.map.directions([' + popup.getLatLng().lat + ',' + popup.getLatLng().lng + ']); return false;">' + dir_content + '</a>');
391            }
392
393            // CFD-40 - Lazy loading done from here
394            current_criteria['offset'] = count + 1;
395            const jobsContainer = document.getElementById('map-jobs-container');
396            const sentinel = document.getElementById('map-job-sentinel');
397
398            const observer = new IntersectionObserver((entries) => {
399                // If sentinel is visible and not all jobs have been loaded
400                if (entries[0].isIntersecting && current_criteria['offset'] < totalJobs) {
401                    load_jobs_with_offset(null, coords);
402                }
403            }, {
404                root: jobsContainer,
405                threshold: 1.0,
406                rootMargin: '0px'
407            });
408
409            observer.observe(sentinel);
410
411            document.querySelector('.leaflet-popup-close-button')?.addEventListener('click', function(event) {
412                observer.disconnect();
413            });
414
415        }
416    };
417
418
419    var get_jobs_at_coords = function (popup) {
420
421        var real_popup = popup.popup;
422        var coords = popup.target.orig_coords;
423
424        if(typeof current_criteria.facet !== 'object') {
425            current_criteria.facet = [];
426        }
427
428        var new_facets = [];
429        for(var facet in current_criteria.facet){
430            if(current_criteria.facet[facet].indexOf('coordinates:') === -1){
431                new_facets.push(current_criteria.facet[facet]);
432            }
433        }
434        current_criteria.facet = new_facets;
435        current_criteria.facet.push('coordinates:' + coords);
436
437        delete current_criteria['LocationRadius'];
438        delete current_criteria['latitude'];
439        delete current_criteria['longitude'];
440        delete current_criteria['Limit'];
441        delete current_criteria['offset'];
442        delete current_criteria['pageSize'];
443
444        // Failed experiment
445        real_popup.setContent('<div class="popup_loader_wrap"><div id="popup_loader" class="popup_loader"></div></div>');
446
447        if(CWS.jobs && CWS.jobs.get_option('use_boolean_search')){
448            current_criteria.useBooleanKeywordSearch = 'true';
449        }
450        load_jobs_with_offset(popup, coords);
451
452    };
453
454    function processJobs(dataset, html, count) {
455        try{
456            if (!Array.isArray(dataset) || dataset.length === 0) {
457                console.warn('No jobs available to process.');
458                return;
459            }
460            for (let i = 0; i < dataset.length; i++) {
461                let job = dataset[i];
462                let joburl = options.jobdetail_path + '/' + job.id + '/' + CWS.seo_url(job);
463
464                html += `<a href="${joburl}" class="map-job ${i % 2 === 0 ? '' : 'alt'}">
465                    ${arrow_icon}
466                    <span class="title">${job.title}</span>
467                 </a>`;
468                count++;
469            }
470            return { count, html };
471        }catch(e){
472            console.error('Error processing jobs:', e)
473        }
474
475    }
476
477    let extendPopup = function (data) {
478        try {
479            const sentinel = document.getElementById('map-job-sentinel');
480            let dataset = options.high_volume ? data.queryResult : {};
481            let len = dataset.length;
482            let html = '';
483            let count = 0;
484            let result = processJobs(dataset, html, count);
485            sentinel.insertAdjacentHTML('beforebegin', result.html);
486            current_criteria['offset'] += result.count;
487        } catch (e) {
488            console.error('Error extend popup:', e)
489        }
490    }
491
492    let load_jobs_with_offset = function (popup, coords ) {
493        $.ajax({
494            url: CWS.apply_filter('map_popup_url', options.api_url),
495            data: CWS.apply_filter('map_popup_criteria', current_criteria, coords),
496            dataType: 'jsonp',
497            crossDomain: true,
498            cache: true,
499            jsonpCallback: 'mapCallback',
500            success: function (data) {
501                data = CWS.apply_filter('map_popup_response', data);
502                if(popup){
503                    popup_open(popup, data);
504                }else{
505                    extendPopup(data);
506                }
507            },
508            complete: function () {
509                // Do Nothing
510            },
511            error: function (error) {
512                console.log('Error loading jobs for map', error);
513            }
514        });
515    }
516
517    var set_options = function (opts) {
518        // Underscore makes sure we don't lose our default options
519        options = _.defaults(opts, options);
520        options = CWS.apply_filter('map_script_options', options);
521    };
522
523    // Public vars/methods
524    return {
525        init: function (opts) {
526            if (opts) {
527                set_options(opts);
528            }
529
530            arrow_icon = '<span class="job-arrow ' + CWS.layout_builder.icons.class() + '">' + CWS.layout_builder.icons.icon('arrow-right') + '</span>';
531
532            // This is going to sound weird, but we want to move it below the "search results" header if it exists...
533            if ($('.widget-jobsearch-results,.widget-jobsearch-results-list').length > 0) {
534                var insert_before = '#search-filters';
535                var new_search_layout = CWS && CWS.jobs && CWS.jobs.layout() === 'new';
536                var mapPosition = CWS && CWS.jobs && CWS.jobs.mapPosition() == 'right';
537                if($('.widget-jobsearch-results.table_tile').length > 0){
538                    if(new_search_layout) {
539                        insert_before = '#widget-jobsearch-results-list';
540                    }
541                }
542                insert_before = CWS.apply_filter('insert_map_selector', insert_before);
543                $('.widget-job-map').insertBefore(insert_before);
544
545                // Might as well add the toggle button too
546                // Check to see if someone hid the map or left it to show by default
547                var icon = '&#xe8b1;';
548                if($('body.l-body').length){
549                    icon = '<span class="mdfi_social_public"></span>';
550                }
551                var button = '<span class="world-icon">' + icon + '</span><span class="toggle-text" aria-live="polite">' + ( $('#job-map').css('display') === 'none' ? CWS._('Show Map') : CWS._('Hide Map') ) + '</span>';
552                if(CWS.layout_builder.theme() === 'avada'){
553                    button = '<span class="world-icon fas fontawesome-icon fa-globe-americas" aria-hidden="true"></span><span class="toggle-text" aria-live="polite">' + ( $('#job-map').css('display') === 'none' ? CWS._('Show Map') : CWS._('Hide Map') ) + '</span>';
554                }
555
556                if(!new_search_layout) {
557                    if(mapPosition) {
558                        $('<a role="button" tabindex="0" href="javascript:void(0);"  id="job-map-toggle" class="' + CWS.layout_builder.buttons.class('primary', 'small') + '">'
559                            + button + '</a>').insertBefore('#live-results');
560                    }
561                    else {
562                        $('<a role="button" tabindex="0" style="float: left" href="javascript:void(0);" id="job-map-toggle" class="' + CWS.layout_builder.buttons.class('primary', 'small') + '">'
563                            + button + '</a>').insertAfter('#live-results');
564                    }
565
566                }
567                options.wait_for_searchform = true;
568            }
569
570            $(document).on('ready keyup mouseover', function(){
571                setTimeout( function(){
572                    if($('.widget-job-map').length > 0){
573                        if($('.leaflet-container').length > 0){
574                            $('.leaflet-container').find('.leaflet-tile-container > img:not([alt])').attr('alt','');
575                            $('.leaflet-container').find('.leaflet-shadow-
575pane > img:not([alt])').attr('alt','');
576                            $('.leaflet-container').find('.leaflet-marker-pane > img:not([alt])').attr('alt','');
577                        }
578                    } 
579                }, 2000);
580            });
581
582            var mapId = document.getElementById('job-map-toggle');
583            if(mapId) {
584                mapId.addEventListener("keydown", function (event) {
585                    if (event.keyCode === 13 || event.keyCode === 32) {
586                        event.preventDefault();
587                        mapId.click(CWS.map.toggle(this));
588                        return false;
589                    }
590                });
591
592                mapId.addEventListener("mousedown", function (event) {
593                    event.preventDefault();
594                    mapId.click(CWS.map.toggle(this));
595                    return false;
596                });
597            }
598
599            map = Leaflet.map('job-map', CWS.apply_filter('leaflet_map_options', {
600                maxZoom: options.max_zoom
601            })).setView(options.starting_coords, options.starting_zoom);
602            Leaflet.tileLayer(options.tilemap, {}).addTo(map);
603
604            // Geolocation
605            var icon = 'geolocation';
606            if($('body.l-body').length){
607                icon = 'mdfi_maps_my_location';
608            }
609            if (options.include_geolocation) {
610                Leaflet.control.locate({
611                    icon: icon,
612                    showPopup: false,
613                    metric: false,
614                    locateOptions: {
615                        maxZoom: 11
616                    }
617                }).addTo(map);
618            }
619
620            map = CWS.apply_filter('map_object', map);
621
622            if (!options.wait_for_searchform) {
623                search_jobs();
624            }
625        },
626        search: search_jobs,
627        set_options: set_options,
628        mapCallback: display_jobs,
629        set_geojson: function(json){
630            geojson = json;
631        },
632        set_view: function(coords, zoom){
633            map.setView(coords, zoom);
634        },
635        //loader: loader, // CWS-4574/CWS-4576 Job Map widget is going to use it
636        set_filters: function (opts) {
637            filters = opts;
638        },
639        toggle: function (el) {
640            if ($('#job-map').css('display') === 'none') {
641                $(el).children('.toggle-text').html(CWS._('Hide Map'));
642
643                // Need to fix the map after it's been resized
644                $('#job-map').slideDown(function () {
645                    map.invalidateSize();
646                    if (markers.getLayers().length > 0) {
647                        map.fitBounds(markers.getBounds());
648                    }
649                });
650            }
651            else {
652                $(el).children('.toggle-text').html(CWS._('Show Map'));
653                $('#job-map').slideUp();
654            }
655        },
656        directions: function (end, start) {
657            /*if(previous_router != null && previous_map_router){
658                previour_map.removeControl(previous_router);
659            }else{
660                previous_map_router = true;
661            }*/
662            var units = 'imperial', unit_switch = $('.unit-switch');
663            if ($('.unit-switch').length && $('.unit-switch').val() == 'km') {
664                units = 'metric';
665            }
666
667            // Nominatim is a geocoder with no rate limiting per day, we'll go with that.
668            var opts = {
669                lineOptions: {addWaypoints: false},
670                fitSelectedRoutes: true,
671                formatter: new Leaflet.Routing.Formatter({units: units})
672            };
673
674            // Use google if we've provided an api key
675            if (cws_opts && cws_opts.google_type && cws_opts.google_key) {
676                opts.geocoder = Leaflet.Control.Geocoder.google();
677            }
678            // Otherwise use a free service
679            else {
680                opts.geocoder = Leaflet.Control.Geocoder.nominatim();
681            }
682
683            // We want to make it so that this function can be called by anything, so start/end waypoints should be optional
684            opts.waypoints = [];
685            if (start) {
686                opts.waypoints.push(Leaflet.latLng(start[0], start[1]));
687            }
688            else opts.waypoints.push(null);
689            if (end) {
690                opts.waypoints.push(Leaflet.latLng(end[0], end[1]));
691            }
692
693            router = Leaflet.Routing.control(opts).addTo(map);
694            previour_map = map;
695            previous_router = router;
696            router_on_map = true;
697
698            $('.leaflet-routing-remove-waypoint').click(function () {
699                router_on_map = false;
700                previous_map_router = false;
701                map.removeControl(router);
702            });
703        }
704    };
705
706})(window, jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.