Two problems regarding AJAX

Blueray

I created a page which gets filled by a php databasequery (all rows are being read from the MySQL-table and written to the table in HTML). All 10 seconds the same PHP-script gets requested by jQuery AJAX and should refresh the current table content. The return-value of this function will then be used to change the table HTML-value.

There are some buttons in the table. When they're clicked, they toggle from on to off (or vice versa) and another PHP-file gets called with AJAX, which then controls 433MHz wireless sockets via shell commands. Purpose of these 10-seconds ajax-refresh is to synchronize the button with the actual state of the electrical socket (which is saved in the MySQL-database).

$(document).ready(function(){
  $(".toggle").click(function() {
    if($(this).hasClass("ein")) {
      $(this).removeClass("ein");
      $(this).html("aus");
      $.post("various/executeCode.php", {transmitted:true, id:$(this).attr('id'),  toggle:'0'}, function(result) {
      });
    } else {
      $(this).addClass("ein");
      $(this).html("ein");
      $.post("various/executeCode.php", {transmitted:true, id:$(this).attr('id'), toggle:'1'}, function(result) {
      });
     }
  });
});


window.setInterval("reloadPage()", 5000);
function reloadPage()
  {
    $.get('various/reloadPage.php', function(data) {
      $("#content").html(data);
  });
}

$stmt = $dbh->query("SELECT * FROM `funksteckdosen`");
$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($row as $r)
{  
  echo "<tr>";  
  echo "  <td>" . $r['name'] . "</td>";  
  echo "    <td><button id='" . $r['id'] . "' class='toggle" . ($r['toggle'] == 0 ? "" : " ein") . "'>"     
    . ($r['toggle'] == 0 ? "aus" : " ein") . "</button></td>";  
  echo "</tr>";
}  

Now I have the following problem: As soon as the page gets refreshed by AJAX the first time, the buttons stop working. Javascript doesn't execute the click()-function anymore. Why is that? Problem 2: The content of the table gets deleted and replaced by the new one. Am I somehow possible to fade new lines (or the button background-color) in, instead of just showing them? That would be the final touch.

I hope you understood my explanations.

David

The click handlers don't work anymore because the new buttons never had the handlers attached to them. When you attach a handler like this:

$(".toggle").click(function() {

What jQuery does is find all of the currently existing .toggle elements and, for each one, add that function as a handler. Since the new ones are added later via an AJAX call, they're not included in that set and, thus, never have that function attached to them.

The way jQuery address this is with the .on() function. The structure of using is it very similar:

$('body').on('.toggle', 'click', function() {

The difference here is the element which is actually getting the click event bound to the function. With this, the click event is actually being added to the body tag, which isn't changing from the AJAX call. Any unchanging common parent for the dynamic elements will work, 'body' and document are usually used as defaults since they're pretty top-level.

When any child element raises a click event, that event continues up all of the parent elements. So it eventually reaches a common parent, such as 'body'. The .on() function then also has a second selector as its first argument. That selector filters the originating elements of the click event before calling the function.

Benefits of using this approach include:

  • There's only one event handler function attached to a single common parent, instead of many attached to many elements, which can be a performance improvement on large or complex pages.
  • Child elements added to the common parent element later in the page's lifespan are still handled, since they will still send their click events to the parent regardless of when they were added. (This is the immediate benefit in your situation.)

As for fading in the content, if I understand the effect you're looking to achieve, you can try something like fading out what's already there, removing it, adding the new content, and then fading it in. Maybe something like this:

$.get('various/reloadPage.php', function(data) {
    $('#content').fadeOut(400, function() {
        $("#content").html(data);
        $('#content').fadeIn();
    });
});

There might be newer structures to accomplish this same thing with the relatively newer "promises" model, but essentially what this does is fade the content out and then include a call-back function to call when it's finished fading out. That call-back function replaces the HTML and then fades it back in. Depending on the structure of your HTML you might need to fade out/in a parent element instead of the one I'm targeting, but hopefully you get the idea here and can tweak it until it looks right.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related