If I were to optimize the original code by removing inline function calls and utilizing externally registered event handlers, it could potentially improve efficiency. The current SetTourLocationRecordId
function seems to have limited utility with the data it receives. Therefore, an alternative approach outlined below may offer more value.
<!DOCTYPE html>
<html>
<head>
<title>Distance Calculation</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr.highlighted {
background-color: blue;
color: white; /* For better visibility */
}
label,input,button{padding:0.25rem}
/* custom class to add to highlighted table rows... probably same as above? */
.row_highlight{
background:#1e90ff;
color:snow;
}
</style>
<script>
const destinationAddresses = {
destination1: {
Tour_Location: "Embassy Suites by Hilton Parsippany",
Display_Name: "Hilton Parsippany",
Address1: "909 Parsippany Blvd",
Address2: "",
City: "Parsippany",
State: "NJ",
Zip: "07054",
Tour_Location_Record_Id: "a1F1U000003VKSSUA4",
Phone: "(631) 260-1849",
},
destination2: {
Tour_Location: "Roosevelt Field Mall",
Display_Name: "Roosevelt Field Mall",
Address1: "2nd Floor - Next to Nordstrom",
Address2: "630 Old Country Rd",
City: "Garden City",
State: "NY",
Zip: "11530",
Tour_Location_Record_Id: "a1F1U000003UG8NUAW",
Phone: "(631) 260-1849",
},
destination3: {
Tour_Location: "Club Wyndham Midtown 45",
Display_Name: "Midtown 45",
Address1: "205 E 45th St",
Address2: "",
City: "New York",
State: "NY",
Zip: "10017",
Tour_Location_Record_Id: "a1F1U000003UbX8UAK",
Phone: "(555) 555-5555",
},
// Add more destination objects if needed
};
function init(){
const geocoder = new google.maps.Geocoder(); // only need to declare this once!</answer1>
<exanswer1><div class="answer" i="76913394" l="4.0" c="1692176785" a="UHJvZmVzc29yIEFicm9uc2l1cw==" ai="3603681">
<p>I would be tempted to modify the original code slightly as below to remove inline function calls and instead use externally registered event handlers. It seems that your <code>SetTourLocationRecordId
does lots of things but nothing really useful is done with the data passed in so an alternative approach below might be of interest.
<!DOCTYPE html>
<html>
<head>
<title>Distance Calculation</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr.highlighted {
background-color: blue;
color: white; /* For better visibility */
}
label,input,button{padding:0.25rem}
/* custom class to add to highlighted table rows... probably same as above? */
.row_highlight{
background:#1e90ff;
color:snow;
}
</style>
<script>
const destinationAddresses = {
destination1: {
Tour_Location: "Embassy Suites by Hilton Parsippany",
Display_Name: "Hilton Parsippany",
Address1: "909 Parsippany Blvd",
Address2: "",
City: "Parsippany",
State: "NJ",
Zip: "07054",
Tour_Location_Record_Id: "a1F1U000003VKSSUA4",
Phone: "(631) 260-1849",
},
destination2: {
Tour_Location: "Roosevelt Field Mall",
Display_Name: "Roosevelt Field Mall",
Address1: "2nd Floor - Next to Nordstrom",
Address2: "630 Old Country Rd",
City: "Garden City",
State: "NY",
Zip: "11530",
Tour_Location_Record_Id: "a1F1U000003UG8NUAW",
Phone: "(631) 260-1849",
},
destination3: {
Tour_Location: "Club Wyndham Midtown 45",
Display_Name: "Midtown 45",
Address1: "205 E 45th St",
Address2: "",
City: "New York",
State: "NY",
Zip: "10017",
Tour_Location_Record_Id: "a1F1U000003UbX8UAK",
Phone: "(555) 555-5555",
},
// Add more destination objects if needed
};
function init(){
const geocoder = new google.maps.Geocoder(); // only need to declare this once!
const getAddress=(o)=>`${o.Address1} ${o.Address2}, ${o.City}, ${o.State} ${o.Zip}`;
/*
What does this function actually do???
*/
const SetTourLocationRecordId=(e)=>{
const json=JSON.parse( e.target.closest('tr').dataset.json );
if( Object.keys( json ).length > 0 ){
Object.keys( json ).forEach(key=>{
console.log( 'Key:%s, Value:%s',key, json[key] )
});
}
};
const highlight_row=(e)=>{
let table=e.target.closest('table');// find the parent table from the click event target
table.querySelectorAll('tr').forEach(tr=>{//remove assigned className from each table-row
tr.classList.remove('row_highlight');
});
e.target.closest('tr').classList.add('row_highlight')// add chosen className to this table row
};
/*
define an event handler - this enables us to remove it.
You could do this in other ways but this is relatively clean.
*/
const tableclickhandler=(e)=>{
if( e.target!=e.currentTarget && e.target instanceof HTMLTableCellElement ){
SetTourLocationRecordId(e);
highlight_row(e);
}
}
function calculateDistance() {
const address1 = document.querySelector('input[name="address"]').value;
const div=document.getElementById('result');
geocoder.geocode({ address: address1 }, function (results1, status1) {
if (status1 === google.maps.GeocoderStatus.OK) {
const origin = results1[0].geometry.location;
const distanceService = new google.maps.DistanceMatrixService();
distanceService.getDistanceMatrix(
{
origins: [origin],
destinations: Object.values(destinationAddresses).map(
(destination) => getAddress(destination)
),
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL, // Use miles
},
function (response, status) {
if( status === google.maps.DistanceMatrixStatus.OK ) {
// remove the click handler to prevent multiple firings of the code.
div.removeEventListener('click',tableclickhandler)
let resultHtml = "<table id='display-table'>";
resultHtml +=`<tr>
<th>Display Name</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Distance</th>
<th>Drive Time</th>
</tr>`;
for( const key in destinationAddresses ) {
if( destinationAddresses.hasOwnProperty(key) ) {
const destination = destinationAddresses[key];
const address = getAddress( destination );
const distance = response.rows[0].elements[ parseInt( key.split("destination")[1] ) - 1 ].distance.text;
const duration = response.rows[0].elements[ parseInt( key.split("destination")[1] ) - 1 ].duration.text;
/*
Rather than adding each item as a parameter to the SetTourLocationRecordId
function you could simply supply the destination as a JSON string as a
dataset attribute.
Within the SetTourLocationRecordId function you can then access that dataset value
- though the original did nothing useful as far as I could see other than call the
highlight_row function. That highlight_row function has been simplified and uses
a className/classList rather than inline styles.
*/
const json=JSON.stringify( destination );
resultHtml += `
<tr data-json='${json}'>
<td><span>${destination.Display_Name}</span></td>
<td>${destination.City}</td>
<td>${destination.State}</td>
<td>${destination.Zip}</td>
<td>${distance}</td>
<td>${duration}</td>
</tr>`;
}
}
resultHtml += "</table>";
if( resultHtml ) {
div.innerHTML = resultHtml;
div.addEventListener('click',tableclickhandler )
} else {
div.innerHTML = "Unable to calculate distance for all addresses.";
}
} else {
div.innerHTML = "Error calculating distance.";
}
}
);
} else {
div.innerHTML = "Invalid origin address.";
}
});
}
document.querySelector('button[name="calc"]').addEventListener('click',calculateDistance );
}
</script>
</head>
<body>
<h1>Distance Calculation</h1><!-- hardcoded address for testing only -->
<label>Origin Address: <input type='text' name='address' value='Veterans Memorial Park, 1839 US-46, Parsippany, NJ 07054, United States' /></label>
<button name='calc'>Calculate Distance</button>
<div id='result'></div>
<script async defer src='//maps.googleapis.com/maps/api/js?key=AIzaSy...&libraries=places&callback=init'></script>
</body>
</html>