-1

I'm having an html file location.html and a file with data location.data both on the same webserver in the same directory. the contens of location.data is always the current location data in the form

{"lat":"44.17027","lon":"15.595542","timestamp":"1723663819127","hdop":"2.394","altitude":"510.35","speed":"0.73396146"}

it is written via json_encode() in another php file. Now I need to read this data in a javascript in location.html into an array to display it on a map via leaflet. (It has to be html)

I just can't manage to get this done. I tried XMLHttpRequest() with no success. Would appreciate any other (elegant) method.

<script>
var locx = new XMLHttpRequest();

locx.open('GET', 'location.data');

locx.onreadystatechange = function () {
   if (locx.readyState === 4 && locx.status === 200) {
       var locationData = locx.responseText;
   }
};

locx.send();
</script>
6
  • 4
    Using fetch is at least more modern than XMLHttpRequest, though there's nothing inherently wrong about using XMLHttpRequest. In what way is the code not working as expected and what debugging have you done? If you're not familiar with your browser's development/debugging tools, now is a great time to start. Commented Aug 15, 2024 at 12:45
  • I know that fetch is more modern, but I didn't get it to work, I really need some working code snippet. thnks Commented Aug 15, 2024 at 13:09
  • "I really need some working code snippet." - You appear to have already attempted to write your code. If it's not working as expected in some way, please elaborate on the problem you are observing and what debugging you have done. Commented Aug 15, 2024 at 13:22
  • 1
    "with no success" - please include any errors you get. Check the browser console and network tab. How exactly are you attempting to use var locationData after it's been set. Could be that you're trying to eat your pizza before it's been delivered. Where exactly is the problem occurring? (eg not making a network request, network request returns wrong data, locationData isn't set). Commented Aug 15, 2024 at 13:51
  • 1
    @fdomn-m Sorry you are correct. I am so used to seeing the send before the event handler. Commented Aug 15, 2024 at 14:11

2 Answers 2

2

If the fetch works (and it should), then the rest will look like this

Working example using PHP to generate JSON

https://plungjan.name/SO/leafletjson

const showMap = data => {
  const { lat, lon } = data;

  // Initialize the map
  const map = L.map('map').setView([lat, lon], 13); // 13 is zoom level

  // Add OpenStreetMap tile layer
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; OpenStreetMap contributors'
  }).addTo(map);

  // Add a marker to the map at the fetched coordinates
  L.marker([lat, lon]).addTo(map)
    .bindPopup(`Location: [${lat}, ${lon}]`)
    .openPopup();
};

showMap(data); // remove this line on your server and uncomment the fetch
/* 
fetch('location.data') // or fetch('jsonGeneratingPHP.php')
  .then(response => {
    if (!response.ok) { // added more fine grained error handling
      throw new Error(`Network response was not ok (status: ${response.status})`);
    }
    return response.json(); // Parse the JSON only if the response is ok
  })
 .then(showMap)
  .catch(error => console.error('Error fetching the location data:', error));
*/  
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<div id="map" style="height: 400px;"></div>



<script>
// delete this script on your server and uncomment the commented fetch 
// test data, remove when fetch works
const data = { "lat": "44.17027", "lon": "15.595542", "timestamp": "1723663819127", "hdop": "2.394", "altitude": "510.35", "speed": "0.73396146" };
</script>

Sign up to request clarification or add additional context in comments.

4 Comments

Some sort of this, thank you, but the step before IS the problem for me ...
What does the console say?
The code I posted WILL work if you run this in a web page from a web server.
^--- Good question 🤷‍♂️ The OP appears to have a couple of pretty comprehensive alternatives to code that may or may not have been failing in the first place. I doubt there's much else that can be done here.
1

You should be using fetch() to get the data via an HTTP GET request from the server and then parse the JSON into a JavaScript object. Then use the information in that object to display a marker on the map (or whatever you want to do) using leaflet.

Leaflet code part is based on mplungjan's answer and was added later to give you a full answer including all relevant parts of the question.

(async() => {
  async function fetchLocation(){
    const mockedApiResponse = `{"lat":"44.17027","lon":"15.595542","timestamp":"1723663819127","hdop":"2.394","altitude":"510.35","speed":"0.73396146"}`
    const response = await fetch("https://httpbin.org/post", {
      method: "POST",
      body: mockedApiResponse,
    })
    if (!response.ok) {
      throw new Error(`Failed to fetch location.data with status code ${response.status}`);
    }
    const locationData = await response.json()
    return locationData.json; // here I need to use .json since the HTTP Bin API returns more data, but this line will be unnecessary for you
  }
  
  function displayOnMap(location){
    const { lat, lon: lng } = location;
    // Initialize the map
    const zoomLevel = 15;
    const map = L.map("myMap")
                 .setView([lat, lng], zoomLevel);

    // Add OpenStreetMap tile layer
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '&copy; OpenStreetMap contributors' }).addTo(map);

    // Add a marker for location
    L.marker([lat, lng])
      .addTo(map)
      .bindPopup(`Coordinates: ${lat}, ${lng}`)
      .openPopup();
  }
  
  const location = await fetchLocation();
  displayOnMap(location);
})();
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<div id="myMap" style="height: 200px;"></div>

In fetchLocation() above there is some stuff I just needed to include to get a working example here on this page (e.g. use POST instead of GET, to allow for the API to return the data I give it etc.). In your case you can just replace the implementation of this function with the code below:

async function fetchLocation(){
  // assuming your file is within the web root otherwise change URL to match path where your file is stored
  const response = await fetch("location.data");
  if (!response.ok) {
    throw new Error(
      `Failed to fetch location.data with status code ${response.status}`
    );
  }
  return await response.json();
}

You should also add some error handling using try...catch.

4 Comments

Your displayonmap looks very familiar... I would personally not introduce await to someone who has trouble with a simple fetch. PS: Not my downvote
Yes, sorry, forgot the attribution as I was completing my answer. It's added now.
This is marvelous, works like a charm! Still how can i get 'const mockedApiResponse' read from a file, I haven't found a solution jet. But still many thanks for you super code ;)
@Shaun.M: All you'd have to do is (1) remove mockedApiResponse entirely, (2) remove the second argument to fetch entirely (it will default to a GET request and has no body), and (3) replace the URL in the fetch operation with your URL. If something in that AJAX operation is failing, your browser's development/debugging tools (specifically the network tab) can be used to find specific information about the problem.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.