Lodi Police Reports — Lodi 411 (2025)

Police Report Explorer

Welcome to Lodi Police Reports. This online system provides a transparent view into Lodi policing based on reports provided by Lodi PD. Our goal is to build trust and collaboration between Lodi PD and Lodi citizens through open data.

  • Not all reports are displayed -- only reports of general public interest while preserving the confidentiality of citizens and ongoing police investigations
  • Only the last 30 days worth of reports is available on this page. Initially the last 7 days for reports are displayed. You may choose to display the last 48 hours up to the past 30 days of reports. Please see the Police Report Trends page to understand crime trends and how policing is evolving in Lodi.
  • Locations displayed are approximate to protect the privacy of all those involved.

With this system, citizens can access information on police responses, see where incidents occur, and view crime trends in neighborhoods. The system displays incident reports for the previous day(s) as they are published. Users can view types of incidents and location data on a map or in charts and graphs.

Note: Animals Calls, Transient and Disturbance make up a significant number of Lodi PD reports, other calls related Code Violations and Suspicious events might not be interesting to the typical citizen. You can choose to ignore those calls by adding them to Ignore Offenses. You can explore categories of reports by selecting a category in Categories . You can also focus on (target) specific offense(s) by adding them to Target Offenses

Police Report Filters

The Map below shows currently selected Categories or Reports. It automatically zooms to show all selected reports.

When there are multiple nearby reports, the map will automatically cluster the reports and show a red or blue circle showing the number of reports contained. As you zoom the map, you'll see the individual reports.

  • Locate Me - Activated your devices GPS to find your current location -- you may need to approve access to location information. If approved, it will create a marker and zoom to that location so you can see all reports near that address
  • Address - Is an address autocomplete box where you can enter the address and then select the nearest match. Sorry no businesses...

You can download a Map Photo of the current Map as a PNG file by clicking on the button below. Note: iOS and Apple devices can take 30-90 seconds to create the image...

The Report Table below is a spreadsheet, similar in concept to Microsoft Excel or Google Sheets, that displays all selected Reports. You can export the data shown below in Excel format and then use in Microsoft Excel, Google Sheets or other applications that support the Excel Format to explore the data as you desire.

You can use the Report Table to organize and sort the data, independent of the Map. Dragging a Header to the Sort bar, will group all the reports by that header. It's most useful for Category or Code. It's best to set Items Per Page to All if you're sorting so you can quickly scroll through groups.

Clicking on a row in the Report Table, will display the corresponding report to the Map and zoom the Map to that Report

The TimeLine below enables you to explore all selected reports by Day.

Clicking on the actual Address will select that Report in the Map and then zoom to the Report. (You'll need to scroll up to the map to see it...)

The Total Reports Chart is Donut Chart that shows the percentage of individual reports from the all selected reports for the selected period. You can see which reports are most common and which are less frequent.

Click the Export button to save this chart as: 1) a PDF File, 2) a PNG file or 3) an SVG file.

`

The Weekly Report Bar Chart is most useful when you're viewing 2 or more weeks of data. It shows how individual reports vary from week as well as how the total number of reports vary from week to week

Clicking on an individual report in the Legend will hide that report, enabling you to customize it to explore just the reports you're interested in.

Click the Export button to save this chart as: 1) a PDF File, 2) a PNG file or 3) an SVG file.

`

The Category Trends is a spreadsheet that shows changes in the number of reports organized by category for current 30 days compared to the prior 30 days (31 - 60 days prior).

All categories of reports vary from week to week and month to month. Large percentage trends get rapid attention from Lodi PD and can benefit from citizen awareness and engagement.

The Weekly Category Bar Chart is most useful when you're viewing 2 or more weeks of data. It shows how Key Categories for Reports vary from week as well as how the total number of reports in Key Categories vary from week to week

Clicking on an individual Category in the Legend will hide that Category, enabling you to customize it to explore just the categories you're interested in.

Click the Export button to save this chart as: 1) a PDF File, 2) a PNG file or 3) an SVG file.

`

#if (data.incidentCode) {#

Case Number: #:incidentCode #

#}# #if (data.CFS_number) {#

CFS Number: #:CFS_number #

#}#

Category: #:category#

Address: #: address # location_on

Follow Up: Lodi Crime Stoppers link LodiPD Non Emergencycall

#= data.description #

Date/Time: #: formatDate#

' + '

Category: #:category #

' + '

Near: #: address #

' + '#if (data.incidentCode){#

Case Number: #:incidentCode#

#}#' + '#if (data.CFS_number){#

CFS Number: #:CFS_number#

#}#' + '

Follow Up: LodiPD Non Emergencycall Telephone Reportcall

' var template = kendo.template(templateString); const homeIcon = '\ue88a'; thisFilter.days = _filterDays; thisFilter.date = moment().subtract(_filterDays, "days").format("M/D/YYYY"); thisFilter.dateOrd = moment().subtract(_filterDays, "days").unix(); thisFilter.minOrd = moment().subtract(_maxDays, "days").unix(); thisFilter.minDate = moment().subtract(_maxDays, "days").format("M/D/YYYY"); const center = {lat: 38.130123, lng: -121.2807299}; var barchartData = { chartArray: [], legendArray: [], categoryArray: [], seriesArray: [] }; var categoryBarchartData = { chartArray: [], legendArray: [], categoryArray: [], seriesArray: [] }; /*function showActiveFilter (state) { activePanel.enable(true); activePanel.toggle(state); }*/ function clearPlaceAC() { var ac = document.getElementById("pac-input"); ac.value = ""; searchMarker.setMap(null); searchMarker = null; map.setCenter({ lat: 38.130123, lng: -121.2807299}); map.setZoom(13); } /* function showGeoFilter (state) { var elements = document.getElementsByClassName('pac-filter-geo-class'); var d = elements[0]; if (state) { d.style.visibility = 'visible'; } else { d.style.visibility = 'hidden'; } }*/ function showDateFilter (state) { var elements = document.getElementsByClassName('pac-filter-date-class'); var d = elements[0]; if (state) { d.style.visibility = 'visible'; } else { d.style.visibility = 'hidden'; } } function codeLatLng(lat, lng) { var latlng = new google.maps.LatLng(lat, lng); return new Promise(function(resolve, reject) { geocoder.geocode({'latLng': latlng}, function (results, status) { if (status === google.maps.GeocoderStatus.OK) { if (results[0] && results[0].formatted_address) { var addr = results[0].formatted_address; resolve(addr); } } else { reject(null); } }); }); } function getBounds () { var bounds = new google.maps.LatLngBounds(); return (bounds); } function mapPhoto() { var mapDiv = document.getElementById("map"); var fileName = null; var mapOptions = { backgroundColor: null, useCORS: true, imageTimeout: 0, width: 1024, height: 480, windowWidth: 1024, windowHeight: 480 }; var mapName = "crimemap"; var dateStr = moment().format("MMMDoYYYY"); fileName ="LodiPoliceReportMap-"+dateStr; map.setOptions({disableDefaultUI: true}); setTimeout(() => { html2canvas(mapDiv, mapOptions).then(function (canvas) { Canvas2Image.saveAsPNG(canvas, 1024, 480, fileName); map.setOptions({disableDefaultUI: false}); }); }, 1000); } function locateMe () { var infowindow = new google.maps.InfoWindow(); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { const pos = { lat: position.coords.latitude, lng: position.coords.longitude, }; var addr = null; codeLatLng(pos.lat, pos.lng).then(function (result) { addr = result; map.setCenter(pos); var markerObj = { position: position, title: "Current Location", name: "Current Location", address: addr } locateMarker = new google.maps.Marker({ map: map, title: "Your Location", name: "Your Location", position: new google.maps.LatLng(pos.lat, pos.lng), address: addr, label: { fontFamily: "Material Icons", color: "#ffffff", fontSize: "18px", text: homeIcon, } }); map.setCenter({ lat: pos.lat, lng: pos.lng}); map.setZoom(16); google.maps.event.addListener(locateMarker, 'click', function () { infoWindow.setContent(this.title + " " + this.address); infoWindow.open(map, this); }); currentBounds = getBounds(); }); }, () => { handleLocationError(true, infoWindow, map.getCenter()); currentBounds = getBounds(); } ); } else { // Browser doesn't support Geolocation handleLocationError(false, infoWindow, map.getCenter()); currentBounds = getBounds(); } } function handleLocationError(browserHasGeolocation, infoWindow, pos) { infoWindow.setPosition(pos); infoWindow.setContent( browserHasGeolocation ? "Error: The Geolocation service failed." : "Error: Your browser doesn't support geolocation." ); infoWindow.open(map); currentBounds = getBounds(); } function createExportButtons () { $("#report-chart-export").kendoDropDownButton({ icon: "export", items: [ { text: "Export PDF", icon: "file-pdf", click: function () { chartSave("report-chart", "pdf", "TotalReportsChart", "Total Police Reports Chart From Lodi 411", false) } }, { text: "Export Image", icon: "file-image", click: function () { chartSave("report-chart", "image", "TotalReportsChart", "Total Police Reports Chart From Lodi 411", false) } }, { text: "Export SVG", icon: "subreport", click: function () { chartSave("report-chart", "svg", "TotalReportsChart", "Total Police Reports Chart From Lodi 411", false) } } ], }); $("#report-barchart-export").kendoDropDownButton({ icon: "export", items: [ { text: "Export PDF", icon: "file-pdf", click: function () { chartSave("report-barchart", "pdf", "ReportsByWeekChart", "Weekly Police Reports Chart From Lodi 411", false) } }, { text: "Export Image", icon: "file-image", click: function () { chartSave("report-barchart", "image", "ReportsByWeekChart", "Weekly Police Reports Chart From Lodi 411", false) } }, { text: "Export SVG", icon: "subreport", click: function () { chartSave("report-barchart", "svg", "ReportsByWeekChart", "Weekly Police Reports Chart From Lodi 411", false) } } ], }); $("#category-barchart-export").kendoDropDownButton({ icon: "export", items: [ { text: "Export PDF", icon: "file-pdf", click: function () { chartSave("category-barchart", "pdf", "CategoryEyWeekChart", "Weekly Police Category Chart From Lodi 411", false) } }, { text: "Export Image", icon: "file-image", click: function () { chartSave("category-barchart", "image", "CategoryEyWeekChart", "Weekly Police Category Chart From Lodi 411", false) } }, { text: "Export SVG", icon: "subreport", click: function () { chartSave("category-barchart", "svg", "CategoryEyWeekChart", "Weekly Police Category Chart From Lodi 411", false) } } ], }); } function showFilterButton (state) { var d = document.getElementById('pac-filter-button'); if (state) { d.style.visibility = 'visible'; } else { d.style.visibility = 'hidden'; } } function showClearFilter (state) { var d = document.getElementById('pac-filter-clear-button'); if (state) { d.style.visibility = 'visible'; } else { d.style.visibility = 'hidden'; } } function clearFilter () { // remoteDataSource.read(); $('#pac-lat').text(""); $('#pac-lng').text(""); $('#pac-address').text(""); // $('#pac-date').text(""); input.value = ""; thisFilter.lat = null; thisFilter.lon = null; thisFilter.address = null; thisFilter.date = moment().subtract(_filterDays, "days").format("M/D/YYYY"); thisFilter.dateOrd = moment().subtract(_filterDays, "days").unix(); thisFilter.days = 7; thisFilter.ignore = null; thisFilter.include = null; thisFilter.active = false; filterDate = null; // showActiveFilter(false); showClearFilter(false);/* showFilterButton(false); showGeoFilter(false);*/ showDateFilter(false); map.setCenter({lat: 38.130123, lng: -121.280729}); map.setZoom(13); deleteMarkers(); } function setMapOnAll(map) { for (let i = 0; i < markers.length; i++) { markers[i].setMap(map); } } // Removes the markers from the map, but keeps them in the array. function hideMarkers() { setMapOnAll(null); } // Shows any markers currently in the array. function showMarkers() { setMapOnAll(map); } // Deletes all markers in the array by removing references to them. function deleteMarkers() { hideMarkers(); markers = []; } function findMarkerByHash (hash) { var found = null; markers.forEach(function (m) { if (m.reportHash === hash) { found = m; } }); return (found); } function displayMarkers (list) { var incidents = list; var bounds = new google.maps.LatLngBounds(); deleteMarkers(); //Load data. var features = []; var info = []; for (var i = 0; i < incidents.length; i++) { var item = { position: new google.maps.LatLng(incidents[i].geoloc.lat, incidents[i].geoloc.lon), offenseDescription: incidents[i].offenseDescription, } bounds.extend(item.position); features.push(item) if (incidents[i].source === "Lodi_Police_Departments") { incidents[i].source = "Lodi PD"; } var titleUrl = encodeURI(incidents[i].offenseDescription + " at " + incidents[i].approxaddress + " on " + incidents[i].formatDate ); var item_info = { offenseDescription: incidents[i].offenseDescription, offenseCode: incidents[i].offenseCode, formatDate: incidents[i].formatDate, incidentCode : incidents[i].incidentCode, approxaddress: incidents[i].approxaddress, category : incidents[i].category, CFS_number: incidents[i].CFS_number, incidentHash : incidents[i].incidentHash, titleUrl: titleUrl, address: incidents[i].address } info.push(item_info) } var infowindow = new google.maps.InfoWindow(); // Create markers. for (var i = 0; i < features.length; i++) { var t = features[i].offenseDescription.trim(); var icn ='https://llserver.herokuapp.com/crimeometer/static/icons/police.png'; if (icons[t] && icons[t].icon) { icn = icons[t].icon; } else { console.log("Missing :" + t); } var marker = new google.maps.Marker({ position: features[i].position, icon: icn, map: map }); marker.set('reportHash', info[i].incidentHash); marker.addListener( 'click', (function(marker, i) { return function() { var thisMarker = info[i]; var content = template(thisMarker); infowindow.setContent(content); infowindow.open(map, marker); } })(marker, i)); markers.push(marker); } map.fitBounds(bounds); const clusterOptions = { gridSize: 30, maxZoom: 13, onClusterClickHandler : function (event, cluster, map) { var evt = event; } } if (!markerCluster) { markerCluster = new markerClusterer.MarkerClusterer({ markers, map, clusterOptions }); } else { markerCluster.clearMarkers(); markerCluster.addMarkers(markers); //Update markercluster with new markers } } function buildCategoryBarchartDS(data) { var offHash = [], offDateHash = [], offKeys = [], offArray = [],catHash = [], catKeys = [], totalOffHash = [], totalOffKeys = []; barchartDateDataSource.data(data); barchartView = barchartDateDataSource.view(); categoryBarchartData.chartArray = []; categoryBarchartData.seriesArray = []; barchartView.forEach(function (b) { var bObj = { name : b.value, items : [], len : b.items.length } catHash[b.value] = b.value; b.items.forEach(function (bi) { if (_defaultCategories.includes(bi.category)) { if (!offHash[bi.category]) { offHash[bi.category] = 1; } else { offHash[bi.category] = offHash[bi.category] + 1; } totalOffHash[bi.category] = bi.category; } }); offKeys = Object.keys(offHash); offKeys.forEach(function (k) { if (_defaultCategories.includes(k)) { var biObj = { category: k, date: b.value, count: offHash[k] }; bObj.items[k]= offHash[k]; offArray.push(biObj); } }); categoryBarchartData.chartArray.push(bObj); }); catKeys = Object.keys(catHash); chartCatDataSource.data(offArray); var tempView = chartCatDataSource.view(); totalOffKeys = Object.keys(totalOffHash).sort(); categoryBarchartData.legendArray = totalOffKeys; categoryBarchartData.categoryArray = Object.keys(catHash); categoryView.forEach(function (g) { var dateArr = []; var gObj = { name : g.value, data : [] } if (_defaultCategories.includes(g.value)) { g.items.forEach(function (it) { if (thisFilter.chartRadix === "week") { if (dateArr[it.incidentWeekStr]) { dateArr[it.incidentWeekStr] = dateArr[it.incidentWeekStr] + 1; } else { dateArr[it.incidentWeekStr] = 1; } } else if (thisFilter.chartRadix === "month") { if (dateArr[it.incidentMonthStr]) { dateArr[it.incidentMonthStr] = dateArr[it.incidentMonthStr] + 1; } else { dateArr[it.incidentMonthStr] = 1; } } }); catKeys.forEach(function (cat) { if (dateArr[cat]) { gObj.data.push(dateArr[cat]); } else { gObj.data.push(0); } }) categoryBarchartData.seriesArray.push(gObj); } }); createCategoryChart(); } function buildBarchartDS(data) { var offHash = [], offDateHash = [], offKeys = [], offArray = [],catHash = [], catKeys = [], totalOffHash = [], totalOffKeys = []; barchartDateDataSource.data(data); barchartView = barchartDateDataSource.view(); barchartData.chartArray = []; barchartData.seriesArray = []; barchartView.forEach(function (b) { var bObj = { name : b.value, items : [], len : b.items.length } catHash[b.value] = b.value; b.items.forEach(function (bi) { if (!offHash[bi.offenseDescription]) { offHash[bi.offenseDescription] = 1; } else { offHash[bi.offenseDescription] = offHash[bi.offenseDescription] + 1; } totalOffHash[bi.offenseDescription] = bi.offenseDescription; }); offKeys = Object.keys(offHash); offKeys.forEach(function (k) { var biObj = { offense: k, date: b.value, count: offHash[k] }; bObj.items[k]= offHash[k]; offArray.push(biObj); }) barchartData.chartArray.push(bObj); }); catKeys = Object.keys(catHash); chartOffDataSource.data(offArray); var tempVew = chartOffDataSource.view(); totalOffKeys = Object.keys(totalOffHash).sort(); barchartData.legendArray = totalOffKeys; barchartData.categoryArray = Object.keys(catHash); groupView.forEach(function (g) { var dateArr = []; var gObj = { name : g.value, data : [] } g.items.forEach(function(it) { if (thisFilter.chartRadix === "week") { if (dateArr[it.incidentWeekStr]) { dateArr[it.incidentWeekStr] = dateArr[it.incidentWeekStr] + 1; } else { dateArr[it.incidentWeekStr] = 1; } } else if (thisFilter.chartRadix === "month") { if (dateArr[it.incidentMonthStr]) { dateArr[it.incidentMonthStr] = dateArr[it.incidentMonthStr] + 1; } else { dateArr[it.incidentMonthStr] = 1; } } }); catKeys.forEach(function (cat) { if (dateArr[cat]) { gObj.data.push(dateArr[cat]); } else { gObj.data.push(0); } }) barchartData.seriesArray.push(gObj); }); createBarChart(); } function setDate () { datePicker = $("#date-picker").data("kendoDatePicker"); datePicker.value(dateIn); datePicker.trigger("change"); filterIncidents(); } function setCategories () { var categoryselect = $("#category-picker").data("kendoMultiSelect"); categoryselect.value(categoriesIn); categoryselect.trigger("change"); }/* function fetchCategoryTree (days) { var url = "http://localhost:4444/lodicountcategories?days=30"+ days; $.ajax(url, { contentType: 'application/json; charset=utf-8', dataType: 'json', cors: true, method: 'get', processData: false, success: function (data) { _fullCategoryItems = data.items; data.name = "Report Categories Past 30 days"; var filterItems = []; data.items.forEach (function (item) { if (_defaultCategories.includes(item.name)) { filterItems.push(item); } }) data.items = filterItems.sort(function(a,b) {return (a.items > b.items) ? 1 : ((b.items > a.items) ? -1 : 0);}); categoryTreeObj = [data]; createTreeMap(); } }); } function createTreeMap() { $("#category-chart").kendoTreeMap({ theme: "blueOpal", // type: "vertical", dataSource: { data: categoryTreeObj, schema: { model: { children: "items" } } }, valueField: "value", textField: "name" }); var treeMap = $("#category-chart").getKendoTreeMap(); treeMap.resize(); }*/ function fetchCategoryTrends () { var start = moment().startOf('day').subtract(30,'days').format("MM/DD/YYYY"); var end = moment().startOf('day').subtract(1,'days').format("MM/DD/YYYY"); var url = "https://lodilab.com/lodicategorycompare?start="+ start +"&end=" + end + "&period=month"; $.ajax(url, { contentType: 'application/json; charset=utf-8', dataType: 'json', cors: true, method: 'get', processData: false, success: function (data) { categoryTrendsObj = data; var deltaArray = []; categoryTrendsObj.deltas.forEach(function (d) { if (_defaultCategories.includes(d.category)) { deltaArray.push(d); } }); categoryGridDataSource.data(deltaArray); } }); } function fetchIncidents (days, filter) { var url = "https://lodilab.com/lodicrime?days="+ days; $.ajax(url, { contentType: 'application/json; charset=utf-8', dataType: 'json', cors: true, method: 'get', processData: false, success: function (data) { if (data && data.length) { allIncidents = []; data.forEach(function (a) { var t = a.offenseDescription.trim(); a.image ='https://llserver.herokuapp.com/crimeometer/static/icons/police.png'; if (icons[t] && icons[t].icon) { a.image = icons[t].icon; } else { console.log("Missing :" + t); } if (a.approxaddress) { a.address = a.approxaddress; } var d = distance(a.geoloc.lat, a.geoloc.lon, center.lat, center.lng); a.lodiDistance = d; a.incidentDay = moment(a.incidentDate).startOf("day").format("MM/DD/YYYY"); a.incidentWeek = moment(a.incidentDate).week(); a.incidentWeekStr = moment(a.incidentDate).startOf("week").format("MM/DD/YYYY"); a.incidentMonth = moment(a.incidentDate).month(); a.incidentMonthStr = moment(a.incidentDate).startOf("month").format("MM/DD/YYYY"); // if (d <= 7) { allIncidents.push(a); // } }); groupDataSource.data(allIncidents); groupView = groupDataSource.view(); categoryDataSource.data(allIncidents); categoryView = categoryDataSource.view(); groupView.forEach(function (g) { var gObj = { name : g.value, items : g.items, len : g.items.length } offenseArray.push(gObj); var cObj = { offense: g.value, count: g.items.length } chartArray.push(cObj); }); offenseDS.data (offenseArray); ignoreDS.data (offenseArray); categoryDataSource.data(allIncidents); var catView = categoryDataSource.view(); var categoryArray = []; catView.forEach(function (c) { var cObj = { name : c.value, offenses: [] } var offenseHash = []; c.items.forEach(function (i) { var off = i.offenseDescription.trim(); offenseHash[off] = off; }); var offenseKeys = Object.keys(offenseHash).sort(); cObj.offenses = offenseKeys; categoryArray.push(cObj); }); categoryDS.data(categoryArray); createDonutChart(); /* groupView.forEach(function (g) { var dateArr = []; var gObj = { name : g.value, data : [] } g.items.forEach(function(it) { if (dateArr[it.incidentDay]) { dateArr[it.incidentDay] = dateArr[it.incidentDay] + 1; } else { dateArr[it.incidentDay] = 1; } }); catKeys.forEach(function (cat) { if (dateArr[cat]) { gObj.data.push(dateArr[cat]); } else { gObj.data.push(0); } }) barchartData.seriesArray.push(gObj); }); createBarChart();*/ if (filter) { if (dateIn) { setDate(); dateIn = null; } filterIncidents(); if (reportUrl) { setTimeout(function () { findMarkerAndZoom(reportUrl); $("#map").scrollTo({ top: 300, left: 100, behavior: "smooth" }); reportUrl = null; }, 2000); } else if (categoriesIn) { setCategories(); categoriesIn = null; } } else { gridDataSource.data(data); buildTimelineDS(data); buildBarchartDS(data); remoteDataSource.data(data); displayMarkers(data); if (dateIn) { setDate(); dateIn = null; } if (reportUrl) { // pause for 1 sec and then zoom to marker setTimeout(function(){ findMarkerAndZoom(reportUrl); $("#map").scrollTo({ top: 300, left: 100, behavior: "smooth" }); reportUrl = null; }, 2000); } else if (categoriesIn) { setCategories(); categoriesIn = null; } } } }, error: function (e) { console.log("Error: " + JSON.stringify(e)); } }); } function filterIncidents () { var array = allIncidents; filterArray = []; filterActive = true; array.forEach(function (a) { var t = a.offenseDescription.trim(); var reject = false; a.image ='https://llserver.herokuapp.com/crimeometer/static/icons/police.png'; if (icons[t] && icons[t].icon) { a.image = icons[t].icon; } else { console.log("Missing :" + t); } if (thisFilter.lat) { if (a.geoloc && a.geoloc.lat) { var d = distance(a.geoloc.lat, a.geoloc.lon, thisFilter.lat, thisFilter.lon); a.distance = d; if (d > thisFilter.radius) { reject = true; } } } if (thisFilter.dateOrd) { if (a.incidentTimestamp < thisFilter.dateOrd) { reject = true; } } if (thisFilter.include && thisFilter.include.length) { if (thisFilter.include.includes(t)) { } else { reject = true; } } if (thisFilter.ignore && thisFilter.ignore.length) { if (thisFilter.ignore.includes(t)) { reject = true; } } if (!reject) { filterArray.push(a); } }); remoteDataSource.data(filterArray); gridDataSource.data([]); gridDataSource.data(filterArray); buildTimelineDS(filterArray); buildChartDS(filterArray); buildBarchartDS(filterArray); buildCategoryBarchartDS(filterArray); showClearFilter(true); showFilterButton(false); displayMarkers(filterArray); } function buildChartDS (data) { chartArray = []; groupDataSource.data(data); groupView = groupDataSource.view(); groupView.forEach(function (g) { var gObj = { name : g.value, items : g.items, len : g.items.length } offenseArray.push(gObj); var cObj = { offense: g.value, count: g.items.length } chartArray.push(cObj); }); var chart = $("#report-chart").data("kendoChart"); var dataSource = new kendo.data.DataSource( { data:chartArray }); chart.setDataSource(dataSource); } function filterIncidentsByDate (ts) { var array = remoteDataSource.data(); var dateArray = []; if (array.length) { array.forEach(function (a) { if (a.incidentTimestamp >= ts) { dateArray.push(a) } }); remoteDataSource.data(dateArray); buildTimelineDS(dateArray); displayMarkers(dateArray); } } function buildTimelineDS (arr) { var ds = new kendo.data.DataSource({ schema: { model: { fields: { incidentDay: { type: "date" } } } }, group: {field: "incidentDay"}, sort: { field: "incidentTimestamp", dir: "desc" } }); ds.data(arr); var groups = ds.view(); var sArray = []; var id = 1; groups.forEach (function (g) { var dStr = "

    "; var count = g.items.length; if (g.source === "Lodi_Police_Departments") { g.source = "Lodi Police Department"; } var tl = { id: id, title: g.value, date: new Date(g.value), description: null, source: g.source, subtitle: count + " Incidents" } g.items.forEach(function (a) { var time = moment(a.incidentDate).format("hh:mm a"); a.time = time; var liStr = eventTemplate(a); dStr = dStr + liStr; }); dStr = dStr + "

"; tl.description = dStr; sArray.push(tl); id = id + 1; }); timelineDataSource.data(sArray); } function findMarkerAndZoom (hash) { var marker = findMarkerByHash(hash); if (marker) { zoomToMarker (marker); } } function zoomToMarker (marker) { map.setZoom(17); map.panTo(marker.position); google.maps.event.trigger(marker, 'click'); } function refreshFilterIncidents (lat, lng) { var array = allIncidents; filterActive = true; array.forEach(function (a) { if (a.geoloc && a.geoloc.lat) { var d = distance (a.geoloc.lat, a.geoloc.lon, lat, lng); a.distance = d if (d <= radius) { filterArray.push (a); } } }); remoteDataSource.data(filterArray); showClearFilter(true); displayMarkers(filterArray); } function distance(lat1, lon1, lat2, lon2) { if ((lat1 == lat2) && (lon1 == lon2)) { return 0; } else { var radlat1 = Math.PI * lat1 / 180; var radlat2 = Math.PI * lat2 / 180; var theta = lon1 - lon2; var radtheta = Math.PI * theta / 180; var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta); if (dist > 1) { dist = 1; } dist = Math.acos(dist); dist = dist * 180 / Math.PI; dist = dist * 60 * 1.1515; return dist; } } function createDonutChart() { $("#report-chart").kendoChart({ theme: "blueOpal", height: 920, dataSource: { data: chartArray }, legend: false, seriesDefaults: { labels: { template: "#= category # - #= kendo.format('{0:P}', percentage)#", position: "outsideEnd", visible: true, font: "16px sans-serif", background: "transparent" } }, series: [{ type: "donut", field: "count", categoryField: "offense", }], tooltip: { visible: true, template: "#= category # - #= kendo.format('{0:P}', percentage) #" } }); } function createBarChart() { $("#report-barchart").kendoChart({ theme: "blueOpal", legend: { visible: true, labels: { font: "16px Verdana" } }, seriesDefaults: { type: "column", stack: true, }, valueAxis: { /* max: 440,*/ line: { visible: false }, minorGridLines: { visible: true } }, series: barchartData.seriesArray, categoryAxis: { categories: barchartData.categoryArray, majorGridLines: { visible: false } }, tooltip: { visible: true, template: "#= series.name # - #=value #" } }); } function createCategoryChart() { $("#category-barchart").kendoChart({ theme: "blueOpal", legend: { visible: true, labels: { font: "16px Verdana" } }, seriesDefaults: { type: "column", stack: true, }, valueAxis: { /* max: 440,*/ line: { visible: false }, minorGridLines: { visible: true } }, series: categoryBarchartData.seriesArray, categoryAxis: { categories: categoryBarchartData.categoryArray, majorGridLines: { visible: false } }, tooltip: { visible: true, template: "#= series.name # - #=value #" } }); } gridDataSource = new kendo.data.DataSource({ schema: { model: { fields: { city: {type: "string"}, address: {type: "string"}, source: {type: "string"}, category: {type: "string"}, incidentCode: {type: "string"}, incidentDate: {type: "date"}, incidentTimestamp: {type: "number"}, offenseCode: {type: "string"}, offenseDescription: {type: "string"}, day: {type: "date"}, image: {type: "string"} } } }, pageSize: 10, sort: {field: "incidentTimestamp", dir: "desc"}, }); remoteDataSource = new kendo.data.DataSource( { /*transport: { read: { type: "GET", dataType: "json", url: "https://llserver.herokuapp.com/lodicrime" }, schema: { model: { fields: { city: {type: "string"}, address: {type: "string"}, source: {type: "string"}, incidentCode: {type: "string"}, incidentDate: {type: "date"}, incidentTimestamp: {type: "number"}, offenseCode: {type: "string"}, offenseDescription: {type: "string"}, crimeAgainst: {type: "string"}, day: {type: "date"}, image: {type: "string"} } } } },*/ pageSize: 10, schema: { model: { fields: { city: {type: "string"}, address: {type: "string"}, source: {type: "string"}, incidentCode: {type: "string"}, incidentDate: {type: "date"}, incidentTimestamp: {type: "number"}, offenseCode: {type: "string"}, offenseDescription: {type: "string"}, originalType: {type: "string"}, day: {type: "date"}, image: {type: "string"} } } }, sort: {field: "incidentTimestamp", dir: "desc"} /* change: function (e) { var data = this.data(); buildTimelineDS(data); displayMarkers(data); },*/ /* requestEnd: function (e) { //check the "response" argument to skip the local operations if (e.type === "read" && e.response) { var data = e.response; if (data && data.length) { data.forEach(function (a) { var t = a.offenseDescription; a.image = icons[t].icon; a.incidentDay = moment(a.incidentDate).startOf("day").format("MM/DD/YYYY"); }) if (!masterLoaded) { masterList = data; masterLoaded = true; allIncidents = data; groupDataSource.data(data); groupView = groupDataSource.view(); groupView.forEach(function (g) { var gObj = { name : g.value, items : g.items, len : g.items.length } offenseArray.push(gObj); var cObj = { category: g.value, value: g.items.length } chartArray.push(cObj); }); createDonutChart(); } buildTimelineDS(data); // remoteDataSource.data(allIncidents); displayMarkers(data); } } }*/ }); offenseDS = new kendo.data.DataSource(); ignoreDS = new kendo.data.DataSource(); categoryDS = new kendo.data.DataSource(); categoryGridDataSource = new kendo.data.DataSource({ sort: [ {field: "trend", dir: "desc"}, {field: "percent", dir: "desc"} ], pageSize: 10 }); groupDataSource = new kendo.data.DataSource({ sort: {field: "incidentTimestamp", dir: "desc"}, group: {field: "offenseDescription"} }); categoryDataSource = new kendo.data.DataSource({ sort: {field: "incidentTimestamp", dir: "desc"}, group: {field: "category"} }); categoryChartDataSource = new kendo.data.DataSource({ sort: {field: "incidentTimestamp", dir: "desc"}, group: {field: "category"} }); barchartDateDataSource = new kendo.data.DataSource({ sort: {field: "incidentTimestamp", dir: "desc"}, group: {field: "incidentWeekStr"} }); chartOffDataSource = new kendo.data.DataSource({ sort: {field: "offense", dir: "asc"}, group: {field: "offense"} }); chartCatDataSource = new kendo.data.DataSource({ sort: {field: "category", dir: "asc"}, group: {field: "category"} }); timelineDataSource = new kendo.data.DataSource({ schema: { model: { fields: { date: { type: "date" } } } }, sort: {field: "timestamp", dir: "desc"}, }); $(document).ready(function () { KendoLicensing.setScriptKey('141j044b041h541j4i1d542e581e4i1i4g260i2k0f2e0b30072907300a2i0g1b5k3i0a1j4f1h4k224f2c612i5a2k551d4j295d405f3a603e5g325c325g3d5h424i2h123d551g4c24511g572f562g614958315e3557395j3957365a4b562856344d452i092i4a5346553458385a3c4i3j4j43291961386037524b2f0f2f4b520e2h0328052j1a290h4f0h5f2b54214i1g611k3b5g10320a3g1c5c2k440j1e3e1h514550405d21'); $("#locateMe").kendoButton({ size: "small", click: function(e) { if (!located) { located = true; locateMe(); e.sender.element.context.innerText = "Hide Location" } else { located = false; locateMarker.setMap(null); locateMarker = null; map.setCenter({ lat: 38.130123, lng: -121.2807299}); map.setZoom(13); e.sender.element.context.innerText = "Locate Me!" } } }); eventTemplate = kendo.template($("#incident-template").html()); $("#date-options").kendoChipList({ selectable: "single", fillMode: "fill", itemSize : "small", rounded: "full", items: [{label: "Yesterday" }, {label: "Week"},{label: "Month"}], select: function(ev) { var targetDate = null; var item = ev.item; var selected = item.element.text(); switch (selected) { case "Yesterday": targetDate = moment().subtract(2,"day").startOf('day').format("MM/DD/YYYY"); break; case "Week": targetDate = moment().subtract(7,"day").startOf('day').format("MM/DD/YYYY"); break; case "Month": targetDate = moment().subtract(29,"day").startOf('day').format("MM/DD/YYYY"); break; } datePicker = $("#date-picker").data("kendoDatePicker"); datePicker.value(targetDate); datePicker.trigger("change"); filterIncidents(); } }); filterDate = moment().subtract(thisFilter.days, "days").unix(); var minDate = moment().startOf('day').subtract(_maxDays, "days").toDate(); var maxDate = moment().startOf('day').subtract(2, "days").toDate(); $("#date-picker").kendoDatePicker({ value : moment().subtract(thisFilter.days, "days").format("M/D/YYYY"), change: function() { var value = this.value(); var dateStr = moment(value).format("M/D/YYYY"); var ts = moment(value).startOf('day').unix(); if (ts < thisFilter.minOrd) { ts = thisFilter.minOrd; dateStr = moment(thisFilter.minOrd).format("M/D/YYYY"); datePicker = $("#date-picker").data("kendoDatePicker"); datePicker.value(dateStr); datePicker.trigger("change"); } if (thisFilter.dateOrd !== ts) { var currentDate = moment().startOf('day'); var targetDate = moment(value).startOf('day'); thisFilter.days = currentDate.diff(targetDate, 'days'); thisFilter.dateOrd = ts; thisFilter.date = moment(targetDate).format("M/D/YYYY"); filterIncidents(); } }, componentType: "modern" }); datePicker = $("#date-picker").data("kendoDatePicker"); // var min = datePicker.min(); datePicker.min(minDate); datePicker.max(maxDate); $("#category-picker").kendoMultiSelect({ dataSource: categoryDS, autoBind: false, maxSelectedItems: 4, dataTextField: "name", dataValueField: "name", placeholder: "Select Category", change : function (e) { var dataItems = this.dataItems(); var multiselect = $("#offense-picker").data("kendoMultiSelect"); var ignoreselect = $("#ignore-picker").data("kendoMultiSelect"); var tags = []; var offArray = []; if (dataItems.length) { thisFilter.include = []; thisFilter.ignore = []; ignoreselect.value([]); ignoreselect.trigger("change"); thisFilter.ignore = []; // Clear ignore not that user has picked a category dataItems.forEach(function (di) { di.offenses.forEach(function (o) { offArray.push(o); thisFilter.include.push(o); }); }) multiselect.value(offArray); } else { multiselect.value([]); thisFilter.include = []; } filterIncidents(); } }); $("#offense-picker").kendoMultiSelect({ dataSource: offenseDS, autoBind: false, dataTextField: "name", dataValueField: "name", placeholder: "Select Offense", change : function (e) { var dataItems = this.dataItems(); var tags = []; filterArray = []; thisFilter.include = []; if (dataItems.length) { dataItems.forEach(function (d) { thisFilter.include.push(d.name); }); } filterIncidents(); } }); $("#ignore-picker").kendoMultiSelect({ dataSource: ignoreDS, autoBind: false, dataTextField: "name", dataValueField: "name", placeholder: "Select offenses to ignore", value: thisFilter.ignore, change : function (e) { var dataItems = this.dataItems(); var tags = []; filterArray = []; thisFilter.ignore = []; if (dataItems.length) { dataItems.forEach(function (d) { thisFilter.ignore.push(d.name); }); } filterIncidents(); } }); $('#incident-info').kendoExpansionPanel({ title: 'Lodi Police Reports', subTitle: 'About', expanded: false }); $('#map-info').kendoExpansionPanel({ title: 'Report Map', subTitle: 'Details', expanded: false }); $('#report-table-info').kendoExpansionPanel({ title: 'Report Table (Spreadsheet)', subTitle: 'Details', expanded: false }); $('#total-reports-info').kendoExpansionPanel({ title: 'Total Reports Chart', subTitle: 'Details', expanded: false }); $('#report-timeline-info').kendoExpansionPanel({ title: 'Reports by Day (Timeline)', subTitle: 'Details', expanded: false }); $('#report-chart-info').kendoExpansionPanel({ title: 'Total Reports (Donut Chart)', subTitle: 'Details', expanded: false }); $('#category-grid-info').kendoExpansionPanel({ title: 'Report Category Trends', subTitle: 'Details', expanded: false }); $('#report-barchart-info').kendoExpansionPanel({ title: 'Reports by Week', subTitle: 'Details', expanded: false }); $('#category-barchart-info').kendoExpansionPanel({ title: 'Report Categories by Week', subTitle: 'Details', expanded: false }); $('#finetune-reports').kendoExpansionPanel({ title: 'Fine Tune Reports', subTitle: 'Drill down...', expanded: false }); $("#report-timeline").kendoTimeline({ dataSource: timelineDataSource, autoBind: false, orientation: "horizontal", navigatable: true, eventTemplate: kendo.template($("#eventTemplate").html()), alternatingMode: true, eventHeight: 520, collapsibleEvents: true }); $("#category-grid").kendoGrid({ toolbar: ["excel"], excel: { fileName: "LodiMonthDelta.xlsx", allPages: true }, columnMenu: { filterable: false }, dataSource: categoryGridDataSource, height: 680, pageSize: 10, sortable: { mode: "single" }, mobile: true, pageable: true, columns: [ { field: "category", title: "Category", width: 80, }, { field: "trend", title: "Trend", width: 60 },{ field: "percent", title: "% Change", width: 60, template: function(dataItem) { return (dataItem.percent + "%") ; } },{ field: "current", title: "Current 30 days", width: 80 },{ field: "prior", title: "Prior 30 Days", width: 80 } ] }); $("#incident-grid").kendoGrid({ toolbar: ["excel"], excel: { fileName: "LodiPoliceReports.xlsx", allPages: true }, columnMenu: { filterable: true }, dataSource: gridDataSource, height: 760, pageSize: 10, sortable: true, groupable: true, mobile: true, selectable: "single", pageable: { refresh: true, pageSizes: [6, 8, 10, "all"], buttonCount: 5 }, change: function(e) { var selectedRows = this.select(); var selectedDataItems = []; var dataItem = this.dataItem(selectedRows[0]); var incidentHash = dataItem.incidentHash; findMarkerAndZoom(incidentHash) }, filter: function(e) { if (e.filter == null) { /* The result can be observed in the DevTools(F12) console of the browser. */ displayMarkers(allIncidents); } else { var filters = e.filter; var allData = remoteDataSource.data(); var query = new kendo.data.Query(allData); var data = query.filter(filters).data; displayMarkers(data); } }, columns: [ { field: "address", title: "Address", width: 120, template: function(dataItem) { if (dataItem.address) { if (dataItem.address.length) { var len = dataItem.address.length; var str = dataItem.address; if (len > 40) { str = str.slice(0, 39); str += "..." } return (str); } else { return ("None provided..."); } } else { return ("None provided..."); } }, filterable: { cell: { enabled: false } } },{ field: "category", title: "Category", width: 64, filterable: { cell: { enabled: false } } }, /*{ field: "CFS_number", title: "CFS Number", width: 50, template: function(dataItem) { var code = dataItem.CFS_number ? dataItem.CFS_number : "None"; return (code) ; }, filterable: { cell: { enabled: false } } },{ field: "incidentCode", title: "Case Number", width: 50, template: function(dataItem) { var code = dataItem.incidentCode ? dataItem.incidentCode : "None"; return (code) ; }, filterable: { cell: { enabled: false } } },*/{ field: "offenseCode", title: "Code", width: 42 },{ field: "offenseDescription", title: "Offense Description", width: 160, template: function(dataItem) { return ('Lodi Police Reports — Lodi 411 (1)&nbsp' + dataItem.offenseDescription) ; }, }, { field: "incidentDay", title: "Day", width: 60, filterable: { cell: { enabled: false } } }/*{ field: "formatDate", title: "Date", template: function(dataItem) { return moment(dataItem.incidentDate).format("M/D/YYYY h:MM a"); }, width: 60, filterable: { cell: { enabled: false } } },, { field: "distance", title: "Distance", width: 80, template: function(dataItem) { if (dataItem.distance) { return(dataItem.distance.toFixed(4)) } else { return ("N/A"); } } }*/ ] }); }); function deleteThisMarker () { searchMarker.setMap(null); searchMarker = null; map.setZoom(13); } function chartSave (id, format, title, subject, landscape) { var chart = $("#"+id).getKendoChart(); var fullTitle = null; switch (format) { case "pdf": fullTitle = title + ".pdf"; var pdfOptions = { paperSize: "auto", creator: "Lodi411.com", subject: subject, landscape: landscape } chart.exportPDF(pdfOptions).done(function(data) { kendo.saveAs({ dataURI: data, fileName: fullTitle }); }); break; case "image": fullTitle = title + ".png"; chart.exportImage().done(function(data) { kendo.saveAs({ dataURI: data, fileName: fullTitle }); }); break; case "svg": fullTitle = title + ".svg"; chart.exportSVG().done(function(data) { kendo.saveAs({ dataURI: data, fileName: fullTitle }); }); break; } } $(window).resize(function() { var chart = $("#report-chart").data("kendoChart"); chart.refresh(); chart = $("#report-barchart").data("kendoChart"); chart.refresh(); chart = $("#category-barchart").data("kendoChart"); chart.refresh(); /* var treeMap = $("#category-chart").getKendoTreeMap(); treeMap.resize();*/ }); function initMap() { geocoder = new google.maps.Geocoder(); const params = new URLSearchParams(window.location.search); reportUrl = params.get("report"); categoryUrl = params.get ("categories"); if (categoryUrl && categoryUrl.length) { if (categoryUrl.indexOf(',') !== -1) { categoriesIn = categoryUrl.split(','); } else { categoriesIn = [categoryUrl]; } } dateUrl = params.get("date"); if (dateUrl && dateUrl.length) { var targetDate = null; var targetDateOrd = null; if (dateUrl && dateUrl.indexOf("/") !== -1) { var thisDate = moment(dateUrl); var lastDate = moment().subtract(30,'day').startOf("day"); if (thisDate.isBefore(lastDate)) { targetDate = lastDate.format("MM/DD/YYYY"); } else { targetDate = thisDate.format("MM/DD/YYYY"); } // this a specific date. Need to confirm date is within 30 days of today } else if (dateUrl === "yesterday") { targetDate = moment().subtract(1,"day").startOf('day').format("MM/DD/YYYY"); } else if (dateUrl === "week") { targetDate = moment().subtract(7,"day").startOf('day').format("MM/DD/YYYY"); } else if (dateUrl === "month") { targetDate = moment().subtract(30,"day").startOf('day').format("MM/DD/YYYY"); } targetDateOrd = moment(targetDate).unix(); dateIn = targetDate; dateInOrd = targetDateOrd; } fetchCategoryTrends(); fetchIncidents(_maxDays, true); // fetchCategoryTree(_maxDays); createExportButtons(); /* setTimeout(function () { var menu = $("#contextmenu"), original = menu.clone(true); original.find(".k-active").removeClass("k-active"); var initMenu = function () { menu = $("#contextmenu").kendoContextMenu({ target: "#map", animation: { open: {effects: "fadeIn"}, duration: 500 }, open: function(e) { var zoom = map.getZoom(); if (zoom < 15) e.preventDefault(); }, select: function (e) { var selected = e.item.innerText; // Do something on select var clone = original.clone(true); menu.getKendoContextMenu().destroy(); clone.appendTo("#map"); initMenu(); } }); }; initMenu(); /!*map.addListener('contextmenu', function(e) { var zoom = map.getZoom(); if (zoom >= 15) initMenu(); });*!/ }, 0);*/ infowindowContent = document.getElementById("infowindow-content"); map = new google.maps.Map(document.getElementById("map"), { center: { lat: 38.130123, lng: -121.280729 }, zoom: 13, mapTypeControl: true, });// Create a bounding box with sides ~10km away from the center point const defaultBounds = { north: center.lat + 0.1, south: center.lat - 0.1, east: center.lon + 0.1, west: center.lon - 0.1, }; const options = { bounds: defaultBounds, fields: ["address_components", "formatted_address","geometry", "name"], strictBounds: true/*, types: ["establishment"],*/ }; input = document.getElementById("pac-input"); const autocomplete = new google.maps.places.Autocomplete(document.getElementById("pac-input"), options); autocomplete.bindTo("bounds", map); google.maps.event.addListener(autocomplete, 'place_changed', function () { if (searchMarker) { searchMarker.setMap(null); } var place = autocomplete.getPlace(); var tempString = '

Report Search Near

#if (data.placeName) {#

#: placeName#

#}#

#: placeAddress#

'; var temp = kendo.template(tempString); var placeName = null; var placeAddress = null; if (!place.geometry) { // User entered the name of a Place that was not suggested and // pressed the Enter key, or the Place Details request failed. // Do anything you like with what was entered in the ac field. console.log('You entered: ' + place.name); return; } thisPlace = place; lat = place.geometry.location.lat(); $('#pac-lat').text(lat); lng = place.geometry.location.lng(); $('#pac-lng').text(lng); var addrArray = place.formatted_address.split(","); var addr = addrArray[0]; placeAddress = addr; thisFilter.address = addr; thisFilter.lat = lat; thisFilter.lon = lng; if (place.name && place.name.length > 2) { $('#pac-address').text(place.name); placeName = place.name; } else { placeName = "User Location"; $('#pac-address').text(addr); } var iwindow = new google.maps.InfoWindow(); var icn = "https://llserver.herokuapp.com/crimeometer/static/icons/pin.png"; var marker = new google.maps.Marker({ anchorPoint: new google.maps.Point(0, -29), icon: icn, map: map }); /* var marker = new google.maps.Marker({ map, anchorPoint: new google.maps.Point(0, -29), label:{ text: "\ue8b6", fontFamily: "Material Icons", color: "#ffffff", fontSize: "18px", } });*/ marker.setPosition(place.geometry.location); marker.setVisible(true); marker.placeName = placeName; marker.placeAddress = placeAddress; marker.radius = radius; marker.geoloc = {}; marker.geoloc.lat = lat; marker.geoloc.lon = lng; marker.inputStr = input.value; searchMarker = marker; var content = temp(marker); iwindow.setContent(content); google.maps.event.addListener(marker, 'click', function() { var tempString = '

Report Search Near

#: placeName#

'; var temp = kendo.template(tempString); var iwindow = new google.maps.InfoWindow(); var content = temp(marker); // Open InfoWindow - on click iwindow.setContent(content); /* input.text = marker.inputStr; $('#pac-lat').text(marker.geoloc.lat); $('#pac-lng').text(marker.geoloc.lon); refreshFilterIncidents(marker.geoloc.lat, marker.geoloc.lon);*/ iwindow.open(map, marker); }); map.setCenter({lat:lat, lng:lng}); if (radius <= 1) { map.setZoom(14); } else { map.setZoom(13); } // showActiveFilter(true); /* showGeoFilter(true); showFilterButton(true);*/ }); /*$("#pac-radius-input").on("change", function () { var rad = $(this).children("option:selected").val(); $('#pac-radius').text(rad); radius = rad; thisFilter.radius = rad; });*/ /* map.addListener("click", function (e) { var lat = e.latLng.lat(), lng = e.latLng.lon(); });*/ map.addListener("zoom_changed", function () { var zoom = map.getZoom(); if (zoom >= 15) { } else { } }); }

Lodi Police Reports — Lodi 411 (2025)
Top Articles
Latest Posts
Recommended Articles
Article information

Author: Mrs. Angelic Larkin

Last Updated:

Views: 5689

Rating: 4.7 / 5 (47 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Mrs. Angelic Larkin

Birthday: 1992-06-28

Address: Apt. 413 8275 Mueller Overpass, South Magnolia, IA 99527-6023

Phone: +6824704719725

Job: District Real-Estate Facilitator

Hobby: Letterboxing, Vacation, Poi, Homebrewing, Mountain biking, Slacklining, Cabaret

Introduction: My name is Mrs. Angelic Larkin, I am a cute, charming, funny, determined, inexpensive, joyous, cheerful person who loves writing and wants to share my knowledge and understanding with you.