0

I tried to create a small project to track flying over my area. Using python package for flight-radar24 API, I successfully got the needed data.

I've created systemd service to launch my python script every x seconds. This script output a html file named "data.html". Each plane output two div: One visible with few information, one invisible with more detailed information.

Second part of the project is to show the retrieved data. I proceed as follow:

  • 1/ simple webpage (index.html)
  • 2/ CSS file
  • 3/ A clock (JavaScript, just to show the time) on the "header" part of index.html
  • 4/ jQuery (to use jQuery, locally downloaded)
  • 5/ A reloading JavaScript (fetch and print data.html into the "datadiv" of index.html)
  • 6/ A "popup" manager, so you can see a nice div with additional information while clicking on a plane.

My problem is that I failed at stopping the auto-reloading mechanism when the "popup" is visible. If you click on a plane while the reloading is scheduled in 1 or 2 seconds, you don't have time to read.

I tried using "clearInterval/clearTimeout" in the click function without any success.

I tried the following:

  • Merging some js file, thinking I could have a variable scope issue.
  • Creating the "popup" div in index.html and keeping it empty, then just change the content using jQuery so this div exists before the data.html is loaded.
  • Using setTimeout instead of setInterval.
  • And to many thing I can't remember...

The popup code (each plane ("trigger") got it's own div ID with additional information (eXYZ)):

$(function() {

   $('.trigger').click(function(e) {
     $('.plane_info').hide();
     $('div#e'+this.id).show();
   });

   $('.trigger').mouseleave(function(e) {
     $('div#e'+this.id).hide();
   });

 });

The reloading code:

function setupRefresh()
{
    setInterval("refreshBlock();",5000);
}

function refreshBlock()
{
    $('#datadiv').load("../data.html");
}
setupRefresh();

isherwood
  • 58,414
  • 16
  • 114
  • 157
  • Does this answer your question? [JS - How to clear interval after using setInterval()](https://stackoverflow.com/questions/8266726/js-how-to-clear-interval-after-using-setinterval) – Daniel Beck Jul 17 '23 at 18:48

4 Answers4

1

Ah, I see you're facing an interesting challenge with your project! To address the issue of preventing automatic reloading when the "popup" is visible, you can modify the reloading code by adding a condition to check if the popup is currently visible before triggering the reload. Let's make the necessary adjustments:

<!DOCTYPE html>
<html>
<head>
  <title>Flight Radar</title>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <div id="header">
    <!-- Clock display here -->
  </div>
  <div id="datadiv">
    <!-- Data from data.html will be loaded here -->
  </div>

  <script src="jquery.js"></script>
  <script>
    $(function() {
      $('.trigger').click(function(e) {
        $('.plane_info').hide();
        $('div#e' + this.id).show();
        stopAutoReload();
      });

      $('.trigger').mouseleave(function(e) {
        $('div#e' + this.id).hide();
        restartAutoReload();
      });

      function setupRefresh() {
        intervalID = setInterval(refreshBlock, 5000);
      }

      function refreshBlock() {
        if ($('.plane_info').is(":hidden")) {
          $('#datadiv').load("../data.html");
        }
      }

      function stopAutoReload() {
        clearInterval(intervalID);
      }

      function restartAutoReload() {
        setupRefresh();
      }

      var intervalID; // Variable to store the interval ID
      setupRefresh(); // Start the automatic reloading initially
    });
  </script>
</body>
</html>
  • Almost working; The "trigger" div added by the reload are (I guess), not known at the time the script is ran. So it works when I create a dummy trigger (always here), but for "dynamic" load yet. – LouisMartin Jul 17 '23 at 20:25
1

You omitted the part of the code where you tried using clearInterval... but given that you aren't capturing the return value of setInterval, I can guess what went wrong:

In order to use clearInterval you need to capture the interval ID when setting the interval, so the browser can know which one to clear.

let foo = setInterval(refreshBlock,5000); // when you want to start refreshing

// ...

clearInterval(foo); // when you want to stop refreshing
Daniel Beck
  • 20,653
  • 5
  • 38
  • 53
  • I tried something like that, but I wasn't able to catch the interval ID in my "click" function. – LouisMartin Jul 17 '23 at 18:48
  • I'm not sure what that means; why weren't you able? The ID is just an integer variable, it'll follow the same scope rules as any other javascript variable. (nb you'll get much better answers if you include your question the specific code you wrote that isn't working, instead of including only the working code and describing the rest.) – Daniel Beck Jul 17 '23 at 18:51
  • One of my test was to just replace the "simple" reload by a code using a var. I wasn't able to clear. Then I moved the modified code within the popup.js, thinking of a scope related issue, and wasn't able to get the timer to stop neither – LouisMartin Jul 17 '23 at 19:01
  • OK, again: share your code. We can't debug what we can't see, and "I wasn't able to" isn't a clear problem description. I assume you had a variable scope issue but based on this description it's impossible to tell for sure. – Daniel Beck Jul 17 '23 at 19:32
0

Let's try a simple approach:

  • Have a variable called isVisible that tracks whether the popup is visible or not
  • Conditionally run refreshBlock if the popup is not visible

let isVisible = false;

function togglePopup( toggle ) {
  if ( toggle ){
    $(".content").show();
    isVisible = true;
  } else {
    $(".content").hide();
    isVisible = false;
  }
}
let counter = 0;

function refreshBlock(){
  if ( !isVisible ){
    console.log("Reloading...", ++counter);
  }
  // Alternatively, you can discard the isVisible variable, and just check
  // whether the popup element is visible or not:
  /*
  if ( $(".content").is(":hidden") ){
    console.log("Reloading...", ++counter);
  }
  */
}

setInterval(refreshBlock, 1000);
.content {
  position: absolute;
    top: 50%;
    left: 50%;
  width: 200px;
    height: 100px;
    background-color: #e8eae6;
    padding: 10px;
    z-index: 100;
    display: none;
}
        
.close-btn {
  position: absolute;
    right: 20px;
    top: 15px;
    background-color: black;
    color: white;
    padding: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <button onclick="togglePopup(true)">show popup</button>
    <div class="content">
        <div onclick="togglePopup(false)" class="close-btn">
            ×
        </div>
        <h3>Popup</h3>
    </div>
Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25
0

Done! I still have a few css think to fix (getting ride of dirty "
" used as padding to expand "hideall" buttons), but mixing the answers gave me something working.

I added a timeout so the popup close itself after a few seconds, and clicking out of a the popup and the flight list also close it. This part is dirty, done by using two buttons on top and bottom of flights list. A cleaner solution would have been clicking anywhere but the popup area (even if, clicking on flight list while popup is shown brings back the new popup, so that's not really dirty...)

Many thanks to the three if you!

<!DOCTYPE html>
<html>
<head>
  <title>Flight Radar</title>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<button class="trigger_close" onclick="hideall()">
  <div class="heading" id="clock"/>
    <script src="js/jquery-3.7.0.min.js"></script>
    <script src="js/clock.js"></script>
  </div>
  <br/>
  <div class="table_headings">
<table>
  <tr>
    <td width="280" style="text-align: center">CALLSIGN</td>
    <td width="200" style="text-align: center">&nbsp;FROM</td>
    <td width="250" style="text-align: center">&nbsp;&nbsp;&nbsp;&nbsp;TO</td>
    <td width="250" style="text-align: center">&nbsp;&nbsp;&nbsp;&nbsp;ALT</td>
  </tr>
</table>
  </div><br/><br/></button>
  <div id="datadiv">
    <!-- Data from data.html will be loaded here -->
  </div>
  <div class="plane_info" id="master"></div> 
  <script>

          function hideall(){
          if ($('div#master').is(":visible")) {

        restartAutoReload();
      }}

      function showplanedetails(flight_callsign,flight_number,ticket_aircraft,ticket_airline,ticket_country_ori_full,ticket_city_ori,ticket_country_dest_full,ticket_city_dest) {   
        $('div#master').hide();
        clearTimeout(timeoutID);
        $('div#master').html("<table class='ticket_table'><div class='plane_info_header'>"+ flight_callsign + " <img src='img/departingflights2.png' width='35' height='35' /> " + flight_number +"</div>"+
"<div class='plane_info_content'>Aicraft: " + ticket_aircraft + "</div><br>"+
"<div class='plane_info_content'>Airline: " + ticket_airline +"</div><br>"+
"<div class='plane_info_content'>From: " + ticket_country_ori_full + " - " + ticket_city_ori + " </div><br>"+
"<div class='plane_info_content'>Dest: " + ticket_country_dest_full + " - " + ticket_city_dest +"</div>");
        $('div#master').show();
        stopAutoReload();
      }

      function setupRefresh() {
        intervalID = setInterval(refreshBlock, 5000);
      }

      function refreshBlock() {
        if ($('div#master').is(":hidden")) {
          $('#datadiv').load("data.html");
        }
      }

      function stopAutoReload() {
        clearInterval(intervalID);
        timeoutID = setTimeout(restartAutoReload, 5000);
      }

      function restartAutoReload() {
        $('div#master').hide();
        setupRefresh();
      }

      var intervalID; // Variable to store the interval ID
      var timeoutID; // Variable to store the interval ID
      setupRefresh(); // Start the automatic reloading initially
  </script>
<button class="trigger_close" onclick="hideall()">
 <br/><br/><br/><br/>
 <br/><br/><br/><br/>
 <br/><br/><br/><br/>
 <br/><br/><br/><br/>
 <br/><br/><br/><br/>
</button>
</body>
</html>

The python script generating "data.html" now outputs buttons such as:

            html += f'<button class="trigger" onclick="showplanedetails(\'{flight_callsign}\',\'{flight_number}\',\'{ticket_aircraft}\',\'{ticket_airline}\',\'{ticket_country_ori_full}\',\'{ticket_city_ori}\',\'{ticket_country_dest_full}\',\'{ticket_city_dest}\')">'

Will try someday to create a git repository for this project. Main Flight Board

Flight Details