The highlight_row function seems to be delayed, as it does not trigger on the initial onClick but works on subsequent clicks. How can I ensure it works properly right from the first click?

I developed an application using the Google JavaScript Maps API to calculate distances between addresses. I've encountered a bug where the row in the table is not highlighted on the first click, requiring a second click for the highlighting to take effect when calling the function highlight_row().

I have tried adding the highlight_row() function to the global scope and calling it separately in the onClick event, but it still doesn't style the row on the first click. Any suggestions or assistance on why this behavior occurs would be highly appreciated. Thank you.

Additionally, I attempted adding the onclick event inside the span element of the table cell, and it only triggers when the display name cell is clicked. Surprisingly, adding onClick in the span successfully styles the selected row on the first click. What could be the reason behind this difference in behavior when placed in different tags?

Below, I will provide the code snippet for reference. To test locally, please insert your own Google Maps API key.

<!DOCTYPE html>
<!-- Rest of the HTML code remains the same -->
</body>
</html>

Answer №1

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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The initial return value of $(document).height may be inaccurate, but is accurate upon recalculation

I am working on implementing a pop-up screen and I would like to darken the background when it opens. Below is the Javascript code: $(document).on('click', '.item', function(){ $("#popUp").css("display" , "block"); ...

The functionality of the AngularJS nested router is not functioning properly

I am encountering some challenges with Angular routing, specifically when using nested routes: The current 'abc' state works flawlessly for the route /admin/team/:teamId .state('admin', { url: '/admin', controller: & ...

Having issues with Vue.js and the splice method not functioning properly on an array row

Having an Object array, I noticed that when I try to remove an object from the array list, only items are deleted from the end. <div class="hours" v-for="(time, index) in hour" :key="index"> So, I decided to place a cli ...

Tips for updating multiple divs after submitting content with jQuery

My screen contains various widgets, each enclosed with different divs. Currently, I have a form that updates using AJAX when posted through jQuery. However, I am looking to refresh two additional divs located outside the form upon a single jQuery AJAX pos ...

Is Javascript Functioning Properly?

Similar Question: How do I determine if JavaScript is turned off? Can we identify whether javascript has been disabled and then redirect to a different page? I am currently working on a project using JSPs, where I have integrated various advanced java ...

aligning two elements within a container to have equal heights

I need to position 2 divs inside a container div. Their height should always be the same, regardless of content. To achieve this, I am using absolute positioning with top and bottom set to 0. Currently, the container div #three collapses and hides the cont ...

JSON endpoint in Express route experiencing timeouts

I am relatively inexperienced with Node, React, and Express, although I have previously deployed a React application with a Node server successfully. This time, however, I am deploying on AWS for the first time and encountering some differences compared to ...

Encountering a 'TypeError: app.address is not a function' error while conducting Mocha API Testing

Facing an Issue After creating a basic CRUD API, I delved into writing tests using chai and chai-http. However, while running the tests using $ mocha, I encountered a problem. Upon executing the tests, I received the following error in the terminal: Ty ...

What is the process for converting the output of cryptoJS.sha256 to binary in a Postman pre-request script?

Seeking assistance in creating an HMAC signature using a pre-request script in Postman. While troubleshooting, it has become apparent that there is an issue with the signature generation process. Although a proof of concept example provides expected result ...

Utilizing React Native to dynamically generate buttons through a loop

I am currently working on retrieving data from the Eventbrite API. The information I am hoping to extract is the event names, which will then be added to a list. Within the render function, I aim to dynamically create buttons based on the number of event ...

LineChart component from MUI not adapting to various screen sizes

My current implementation of the MUI X Line Chart is causing responsiveness issues. <div className="grid sm:col-span-full lg:grid-cols-2 lg:grid-rows-3 lg:gap-8"> <div className="overflow:hidden"> <LineChart xAxis ...

Set the class of the list item to "active" class

My approach to styling involves using a UL and li class to contain form selection options. I plan on hiding the radio button and using its value upon form submission. I have managed to enable checking the radio box when the <li> is clicked, but for s ...

The supported browser is unable to import ES6 modules

Attempting to incorporate moment.js as an es6 module. The most recent version of Chrome is being utilized. Referring to the conversation here, I experimented with the src path (es6) import * as moment from './node_modules/moment/src/moment' A ...

collaborating with numerous JavaScripts

I am currently working on a project that involves several JavaScript functionalities such as an image viewer, carousel, and toggles. Now, I need to implement a pop-up form, but when I add the JavaScript for the pop-up, the entire page stops working. I wou ...

Is there a method to introduce a line break for each piece of data that is shown?

I am currently working with an array and have successfully displayed it on the screen. My inquiry is whether it is feasible to insert a line break for each of the data points it presents. { name: "cartItems", label: "Product Name ...

Executing Javascript within an iframe

Is there a way to include a script in an iframe? I came up with the following solution: doc = $frame[0].contentDocument || $frame[0].contentWindow.document; $body = $("body", doc); $head = $("head", doc); $js = $("<script type='text/javascript&a ...

The Angular Table row mysteriously vanishes once it has been edited

Utilizing ng-repeat within a table to dynamically generate content brings about the option to interact with and manage the table contents such as edit and delete. A challenge arises when editing and saving a row causes it to disappear. Attempts were made ...

Formatting a pair of elements side by side in MUI Select

Currently, I am tackling the challenge of organizing elements in MUI Select v4. My goal is to display these elements in two columns rather than just one column within the dropdown. Despite attempting to override certain styles within MUI, I have not been ...

Activate the zoom feature in jquery mobile

I am looking to implement the standard zooming effect in jquery mobile for my iOS iPhone app using jqm 1.3.2. After attempting the following: <meta name="viewport" id="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-s ...

Issues with babel plugin-proposal-decorators failing to meet expectations

I recently included these two devDependencies in my package.json: "@babel/plugin-proposal-class-properties": "^7.1.0", "@babel/plugin-proposal-decorators": "^7.1.6", In the configuration file .babelrc, I have listed them as plugins: { "presets": ["m ...