views:

191

answers:

4

I have the following jQuery code in my PHP file (edited Jan 19 2010 @ 10:40 MST):

<?php
   $count = 0;
   foreach($attachments as $attachment) :
      echo '<script type="text/javascript">
               $(\'#a_'.$count.'\').click(function() {
                  $(\'#d_'.$count.'\').show(200);
               });

               // if "no" is clicked
               $(\'#d_'.$count.' .no\').click(function() {
                  $(\'#d_'.$count.'\').hide(200);
               });

               // if "yes" is clicked
               $(\'#d_'.$count.' .yes\').click(function() {
                  $(\'#d_'.$count.'\').hide(200);

                  // update database table -- this is why I need the script inside the for loop!
                  var jsonURL = \'http://path/to/update_db_script.php\';
                  $.getJSON(jsonURL, {\'post_id\' : '.$attachment->ID.'}, function(data) {
                     alert(\'Thank you. Your approval was received.\');
                  });
                  $(\'#a_'.$count.'\').replaceWith(\'<span>Approved</span>\');
               });
            </script>';

      echo '<li>';
         if($attachment->post_excerpt == 'approved') {
            // Check the proof's status to see if it reads "approved"
            echo '<span>Approved</span>';
         } else { ?>
            // If not yet approved, show options
            <a class="approve" id="a_<?php echo $count; ?>" href="#">Click to Approve</a>
            <div class="confirm-approval" id="d_<?php echo $count; ?>">
               <p>Please confirm that you would like to approve this proof:</p>
               <a class="yes" href="#">Yes, I approve</a>
               <a class="no" href="#">No, not yet</a>
            </div><?php
         } ?>
      </li>
   <?php $count++;
endforeach; ?>

The page in question is available here. The "click to approve" links do not work (that's my problem).

When I view source, the PHP variables appear to have echoed properly inside the jQuery:

<script type="text/javascript">
   $('#a_0').click(function() {
      $('#d_0').show(200);
   });
   ... etc ...
</script>

This looks correct, but nothing happens when I click any of the links. However, when I replace the PHP echo statements with plain numbers (0, 1, etc.) the click functions work as expected.

You may be asking: why on earth do you have this inside a for loop? The reason is that I need to retrieve the attachment->ID variable and pass it to an external PHP script. When someone clicks "approve" and confirms, the external script takes the attachment->ID and updates a database value to read "approved".

Why won't the click function fire when PHP is in place? Is there some kind of greater force at work here (e.g., hosting limitation), or am I missing a fundamental piece of how PHP and JavaScript interact?

+5  A: 

Since you didn't post your HTML its a little hard to troubleshoot.

First, I am not sure why one is working and the other is not since the code it is outputting looks correct. Either way, I still would make some changes. Move your a_0,a_1, etc and d_0,d_1, etc into the id attribute instead of a class:

<div><a href="#" id="a_0" class="approve">Click Me</a></div>
<div class="confirm_approval" id="d_0">Show Me</div>
<div><a href="#" id="a_1" class="approve">Click Me</a></div>
<div class="confirm_approval" id="d_1">Show Me</div>

Now, instead of outputting your code in a loop in PHP, place this jQuery code once on your page:

$(document).ready(function(){
   $("a.approve[id^='a_']").click(function(e){
      var id = this.id.replace('a_',''); // Get the id for this link
      $('#d_' + id + '.confirm-approval').show(200);
      e.preventDefault();
   });
});

This code finds any a element with the approve class that has an id that starts with a_. When this is clicked, it grabs the number off the id a_0 = 0 and uses that id to find the confirm-approval element and show it.

Doug Neiner
I agree that this is a much better way to bind the links with their corresponding divs.
grossvogel
Doug, that's a fantastic way of doing things; thank you. I still don't understand why echoing PHP into the jQuery would cause it to fail, while replacing the variables with a fixed number allows it to succeed. So while I now have a great solution for future reference, I'm still at an impasse in this case.
Ryan
I updated my question to include additional relevant code. The idea is to show everyone why I included the jQuery inside a for loop instead of just once in the <head>.
Ryan
A: 

It seems that the problem is in jQuery selectors. Instead of dynamically binding click() events on multiple objects with an output of PHP code, use just one class selector and bind to objects with this class. And you can specify an id attribute to make them unique.

Darmen
Darmen, I just updated my code so that everything has unique IDs. Unfortunately, that doesn't appear to be the problem; variables echoed by PHP still cause trouble, while static numbers work fine.
Ryan
+2  A: 

Since the javascript is run on the client and has no way of knowing whether the script was generated using PHP or not, I think that particular part is a wild goose chase...

When I replace the PHP echo statements with plain numbers (0, 1, etc.) the click function works as expected.

Do this again and compare the actual output using view-source in a browser. I'll bet you find that there is a difference between the working and failing scripts, other than one of them being generated by PHP.

grossvogel
Grossvogel, thanks for the response. I checked the source code for both PHP and plain text output, and they are identical. If I'm correct, PHP is parsed before the page hits the browser, so either way JavaScript should see just a plain number.
Ryan
A: 

Something strange too is to have the script tag and the

$(document).ready(function()

in the loop. I don't know if this causes any problems, but it's sure not very efficient, one time is enough.

kaklon
I know...you're right, but the overall script (not shown) is more complicated. The reason I have the jQuery piece inside a for loop is because I need PHP a variable that's only present in this loop. The variable is sent via .getJSON to another PHP script. I haven't yet come up with a creative way to get this variable outside of the for loop.
Ryan