tags:

views:

163

answers:

2

I've been asking similar questions here today, but I'm seeing I think the issue is with how I am calling my data?

I'm trying to replace a nav bar with ajax that will load contents into a div.

The nav bar is this:

<ul>
  <li><a href="javascript:void(0)" onclick="getData('/includes/view-monthly-calendar-ajax.php', 'targetDiv')">Monthly</a></li>
  <li><a href="javascript:void(0)" onclick="getData('/includes/agenda-ajax-include.php', 'targetDiv')">Daily</a></li>
  <li><a href="javascript:void(0)" onclick="getData('/includes/hello-include.php', 'targetDiv')">Admin</a></li>
  <li><a href="javascript:void(0)" onclick="getData('/includes/view-monthly-calendar-ajax.php', 'targetDiv')">Help</a></li>
</ul>

Then I have this to replace the div:

 <div id="targetDiv"></div>

the getData function is an innerHTML request:

   <script language = "javascript"> 
        function getData(dataSource, divID)
{
    $.ajax({
      url: dataSource,
      dataType: 'html',
      success: function(data) {
        $('#' + divID).html(data);
      }
    });
}
</script>

When I click the nav links, the HTML loads into the div, but the contents of my include files also contain PHP functions and jQuery that needs to execute when being loaded and they are just ignored. I've seen this question asked a lot here, but these seem to only relate to jQuery?

To be clear, when I click the nav links, I get a 200 OK in firebug console, but only HTML is coming back and populating div.

Here is my most recently cleaned include file with changes from Jonathan's suggestions. At this point, I am getting output up the the </tr> after the help button (line 15) but no output past that...

 <?php 
session_start();
?>

<table width='100%' border='0'>
 <tr class='twentyfivepxheight'><td></td></tr>
 <tr>
 <td width='40%' valign='top'>
 <div class='left_agenda_items'>
 <table width='80%' align='center' border='0'>
 <tr class='twentyfivepxheight'>
 <td align='left' class='title5 bottompadding unselectable'>Daily Agenda<a href="javascript:void(0)" class="supernote-click-note1">
 <img src="/images/help-sm.jpg" alt="Help Button" /></a>
</td>
</tr>

<?php


  $numric_time =  getNumericTime($_SESSION['userData']['timezone']);
  $query  =  "SELECT * FROM events WHERE date(convert_tz(StartDate,'+00:00','". $numric_time."'))='$currentDate' AND UserID='" . $_SESSION['userData']['UserID'] ."' ORDER BY StartTime";
  $result  =  mysql_query($query);
  if(mysql_num_rows($result))
  {
    while($row = mysql_fetch_assoc($result))
    {
      $eventID    =  $row['EventID'];
      $eventName    =  $row['EventName'];
      $startDate    =  $row['StartDate'];
      $description  =  $row['Description'];
      $assignedTo    =  $row['AssignedTo'];
      $PTLType    =  $row['PTLType'];
      $parentEventID  =  $row['ParentEventID'];
      $textclass    =  "greentext unselectable";
      $text      =  "Main event";
      //$url      =  SITE_URL ."/agenda-view-event.php?eventID=$eventID&date=$currentDate&day=$i&type=A&date=$currentDate";
      $url      =  SITE_URL ."/agenda-view-event.php";
      if($PTLType == 2) // To do's
      {
        //$divRed[]  =  $eventID;
        $url      =  SITE_URL ."/agenda-view-timeline.php";
        $textclass    =  "redtextDaily unselectable";
        $text      =  "To do";
        $html_todos .= '
                <tr id="redtext' . $eventID . '">
                <td id="rowbox'.$eventID.'" class="'. $textclass . '" width="30%" onclick="get_event_popup(\'' . $url . '\', \'agendaViewDiv\', \'agendaLoader\', \'eventID='.$eventID.'\', \'parentEventID='.$parentEventID.'\', \'type=A\', \'date='.$currentDate.'\');setbgagendabox(\''.$eventID.'\');return false">
                ' . $eventName . ' - (' . $text . ')
                </td>
                </tr>';
      }
      elseif($PTLType == 3) //Completed
      {
        //$divBlue[]  =  $eventID;
        $url      =  SITE_URL ."/agenda-view-timeline.php";
        $textclass    =  "blueTextDaily unselectable";
        $text      =  "Completed";
        $html_completed .= '<tr id="bluetext' . $eventID . '"><td style="display:none;" id="rowbox'.$eventID.'" class="' . $textclass . '" width="30%" onclick="get_event_popup(\'' . $url . '\', \'agendaViewDiv\', \'agendaLoader\', \'eventID='.$eventID.'\', \'parentEventID='.$parentEventID.'\', \'type=A\', \'date='.$currentDate.'\');setbgagendabox(\''.$eventID.'\');return false">' . $eventName . ' - (' . $text . ')</td></tr>';
      }  else  { //main events
        //$divMainEvent[] = $eventID;
        $html_main_events .= '<tr id="mainEvent' . $eventID . '"><td id="rowbox'.$eventID.'" class="' . $textclass . '" width="30%" onclick="get_event_popup(\'' . $url . '\', \'agendaViewDiv\', \'agendaLoader\', \'eventID='.$eventID.'\', \'date='.$currentDate.'\', \'day='.$i.'\', \'type=A\', \'date='.$currentDate.'\');setbgagendabox(\''.$eventID.'\');return false">' . $eventName . ' - (' . $text . ')</td></tr>';
      }
    }

    echo $html_main_events . $html_todos . $html_completed;

  } else  { 

    ?>
   <tr>
     <td>
     <span class="a_dateformat">You have no agenda items due today!</span>
     </td>
     </tr>

<?php
}

?>

</table>
</div>
<input type="hidden" id='lastselected' value='' style="" />
</td>
<td class='verticalborder'>&nbsp;</td>
<td width='59%' valign="top" align="center">
<div id="agendaLoader" style="display:none;">
<img src="images/ajax-loader-orange.gif" alt="wait" />
</div>
<div id="agendaViewDiv" style="display:none;"></div>
</td>
</tr>
<tr>
<td colspan="3">&nbsp;
</td>
</tr>
</table>

But see how I commented out the jQuery to make it work?

If that is not commented out, I don't get any output. The problem is that I need that jQuery to properly build the page.

+6  A: 

For anybody who stumbles across this "answer," please note that it was not intended to be so broken-up. Each portion of this answer was added at a later date following exchanges with the OP in the comments. The items on top are the latest additions whereas the furthest items down were earlier additions.

Jonathan Sampson

Call to undefined function

Because this page is typically included, and not called directly, there may be some things that won't be available when requested. You indicated in the comments that the function getNumericTime() doesn't exist, and is causing an error.

You'll want to make it exist, but you don't want to just redeclare it, or else that will cause problems for you when you request this page as an include-file to another page that already has that function. So what you'll want to do is check whether the function exists, and create it if it doesn't.

if (!function_exists("getNumericTime")) {
  function getNumericTime($foo) {
    // get the function logic and place it here
  }
}

Now, when you call the include-file directly, the function will be created if it doesn't exist. When you call the old-fashioned way, with this file being included, the if-statement will simply skip pass the new function declaration, since the function already exists.

If this function exists within a functions file, you can include it, but be sure to use include_once() instead of include(). include_once() will not include the file if it's already be included once before. Given the fact that this page is occasionally in another environment where the functions include has already taken place, we want to be sure not to include it again, so we use the include_once() method.

Missing connection and selection...

You're attempting to perform queries, yet there's no database connection on this page. There is also no mysql_select_db() call to select from a specific database. Without these, your queries won't succeed and your data won't be returned.

// Our connection to mysql
$conn = mysql_connect($host, $user, $pass) or die(mysql_error());
// Which database we're using
mysql_select_db($dbname) or die(mysql_error());

Once that connection is made (within index.php, for example) we could do an include:

include("foo.php");

The contents of foo.php now have a connection opened so they can perform queries, call stored-procedures, etc. This is only the case because it's being included into a page that has an open-connection.

If we were to access foo.php directly, which is what you're doing with your ajax-request, we wouldn't get the results we want, because foo.php doesn't provide its own database connection - it depends on index.php (which it is often times included into) to provide that connection.

From PHP to HTML to PHP...

One thing that often times causes problems outputting HTML progressively through a PHP Script. Often times you'll see numerous echo statements followed by HTML strings that are littered with back-slashes to escape certain output. Not only is this tedious to write, but it's a pain to search when problems arise. HTML rarely needs to be within PHP. When you need to output HTML, get out of your PHP tags for a moment:

<?php

  $result = mysql_query($sql) or die(mysql_error());
  if (mysql_num_rows($result)) {
    while ($row = mysql_fetch_assoc($result) { ?>

    <tr>
      <td>Data Here</td>
      <td><?php print $row["foo"]; ?></td>
    </tr>

    <?php }
  } else { ?>

    <tr>
      <td>No records found</td>
    </tr>

  <?php }
?>

Notice how it's easier to tell when my HTML is wrong someplace, and it's easy to jump from writing markup to writing PHP. Ideally, you wouldn't even do it this way, but this is an improvement over what you currently have.

Properly using $_SESSION

After giving a look at your code, I noticed that you're calling values out of $_SESSION, or trying to at least. You can only do this if you have called session_start() at the top of the page. Your code lacks this, which may be the reason you're not getting anything back as an integral part of your SQL Queries is missing. Add the following to the very top of your script:

<?php session_start(); ?>

PHP Code Not Executing?

If your PHP isn't executing, there's a problem with the script or the server, but not with jQuery. Check to make sure you have both the opening and closing PHP tags in the script you're requesting:

<?php

  /* and */

?>

Simplifying things

You could simplify and clean up your code a bit too. First of all, let's create a new nav-bar:

<ul id="nav">
  <li><a href="index.php">Index</a></li>
  <li><a href="about.php">About</a></li>
  <li><a href="contact.php">Contact</a></li>
</ul>

Note how I'm linking directly to the files, and not using any javascript to cancel out my clicks. This way, when a user stumbles onto my site without javascript enabled, they're not faced with a broken website, they can still get around.

Without interspersing javascript in our HTML, we'll bind up some logic to these nav-links:

$(function(){
  // Attach logic to all links
  $("#nav a").click(function(e){
    // Prevent link from redirecting page
    e.preventDefault();
    // Load next page into #targetDiv
    $("#targetDiv").html("").load($(this).attr("href"));
  });
});

And that's it. You're done.

Jonathan Sampson
+1 very nice and simple.
Pekka
Hi Jonathan. Thanks for your reply. This specific instance is on a web-based app that a user logs in to so there will (hopefully!!) be no stubbling upon. The whole site requires javascript to properly function (if it works for Google Calendar, it works for this app). You guys have all been so helpful, and I feel like I just must not be giving enough info. In general, the PHP is working in the ajax call, but any sort of functions, etc are not.
Joel
@Joel: I understand your frustration, we've all been there :) Try a more specific question. Rather than dealing with general concepts, give us specifics. What page are you requesting, what is the source of that page, what is coming back. What are you expecting, etc. Online examples that we can access are great too.
Jonathan Sampson
ok. Thanks for your understanding :) I included the above file to hopefully shed some light. I have to go take my daughter to get some food, but will be back shortly...
Joel
I added a login to check out the page I'm talking about.
Joel
@Joel: Try adding `session_start()` to the top of your file. You're trying to use sessions in the query, but you're lacking this function-call which is necessary before calling session data.
Jonathan Sampson
...writing from the car...the session start is in the root file iof the index page. Note-of o just include the above file without Ajax, it works fine. Do I need a second session start?
Joel
Ps-you can log into the regular "live" site and see the calendar without the Ajax. Just drop the /Dev2/
Joel
@Joel: If you're accessing the include file by itself, you will need to add another `session_start()` in there.
Jonathan Sampson
Well unfortunately, the session_start didn't do the trick. Nothing changed. Still a blank output. :(
Joel
@Joel: Temporarily clean out that file. Put in a single word "test" and then try your ajax again...
Jonathan Sampson
OK. Jonathan. I did, and I have applied it to the "admin" tab at the top right. text is showing up.
Joel
Alright, can you output any session data?
Jonathan Sampson
I'm afraid I don't know how to make that leap. I now have a blank file called test.php with the word test in it...I also have the big agenda include file with the session_start at the top that doesn't output anything. I unfortunately don't know well enough to make the test file output session information. If you're in the mood, you can email me directly or we can use google chat, and i can give you access to the files. Maybe this root.php file has a lot more session info that I need in the include? joel (at) rattletree (dot) com
Joel
@Joel: In your empty page, place the following: `<?php session_start(); print_r($_SESSION); ?>` See if your ajax requests spit back any session data.
Jonathan Sampson
ok. Yes it did. I spit back some arrays with the session info.
Joel
Excellent! So There's hope :) I'd like to suggest a better way to output loads of HTML from PHP. Stay tuned for an update to my answer above.
Jonathan Sampson
:) Ok. Thanks, Janathan!
Joel
Ok. So I'll make those markup changes and report back in a moment. I do want to claify again, though, that what I have does work now as it is when using it as an include-it's only by doing it in ajax that the trouble is happening.
Joel
@Joel: If that is the case, then the file has some foreign-dependency upon another file. Try accessing the include file directly through your browser - can you see the output that way?
Jonathan Sampson
@Jonathan if I navigate directly to the include file, I only see that same first html before the SQL stuff. In my question, I have now put in the exact include file (with the changes you suggested) there.
Joel
ugh...man-I think I'm out of my league here. these files are pulling everything from the database, and there are several include files in this one include file and THOSE all connect to the database too...:( I think I need a pro to look at these files to really make some sense of what's up. I really, really appreciate all your help.
Joel
@Joel: I don't see a database connection being established on this page...
Jonathan Sampson
So if I'm understanding correctly, it doesn't matter if I have already established a database connection on my index page...if I want to connect to the database, I also need to have all database connection within the requested include, is that correct?
Joel
Joel, keep in mind that the users computer is making the request for the page. No connection exists on the users computer with your database. When the user first requests your site, a connection is opened, the data is pulled, and the connection is closed. The data is then sent to the users browser. From there, any ajax requests don't have an open connection unless the page they request has it's own logic in place to provide its own connection.
Jonathan Sampson
ok. That makes sense. So as the program is now, there is a root.php that is at the top of every page. There are lots of conditionals there, as well as several include files (including connection.php for the db). The difficulty is that there is also lots of main page html (the head, body, and scripts, etc) in these includes. I guess that means I need to figure out exactly what info I need in order to properly connect and query the db. Using your provided code up there DID connect to the db but still didn't actually pull the info-it still only took me to that first HTML-but it did connect!
Joel
If you can connect, that's great. Connect, run your query, and see if you can print out the results of `mysql_num_rows($result)` to the screen.
Jonathan Sampson
OK. At least now, I'm getting an error :) : Fatal error: Call to undefined function getNumericTime() in /home/monkeyc4/public_html/Dev2/agenda-ajax-include2.php on line 26
Joel
Alright, now we have to be careful. If you redeclare that function in this file, it will cause problems when this file is loaded into another that already has the function. What you want to do is use php's `function_exists()` function to test whether "getNumericTime" exists. If it doesn't, you want to declare it in this file.
Jonathan Sampson
yes-it exists. It is in our functions/general.php folder. Can I just "include" that in the page below the database connection? Like just doing a : <?php include("/functions/general.php"); ?>
Joel
@Joel: I've updated my answer with an example of declaring functions in this manner.
Jonathan Sampson
@Joel: You can include it, but be sure to use `include_once("path/to/file.php")` instead of the regular `include()` as that would cause problems.
Jonathan Sampson
ok. made great progress. I got the page to load correctly. it looks like all that is missing is there is session information for the specific user not populating the calendar, but I believe this is because of something with properly loading the session information. I'm willing to see this as a victory. Thank you, Jonathan for sticking with this!
Joel
@Joel: Have I earned a check-mark yet? :)
Jonathan Sampson
@Joel: You've got my personal email address. If you need further help, don't hesitate to shoot me an email. (not an open-invitation to everybody to start emailing me programming questions, hehe.)
Jonathan Sampson
+4  A: 

This answer is in response to the follow part of the question:

When I click the nav links, the HTML loads into the div, but the contents of my include files also contain PHP functions and jQuery that needs to execute when being loaded and they are just ignored.

Note that the JavaScript that gets returned from XMLHttpRequestObject.responseText will not execute when inserted into the DOM text with innerHTML as you are doing.

You may want to check the following Stack Overflow post for a couple of solutions around this issue:


However, if you are using jQuery, you can replace all the code in getData() with the following:

function getData(dataSource, divID)
{
    $.ajax({
      url: dataSource,
      dataType: 'html',
      success: function(data) {
        $('#' + divID).html(data);
      }
    });
}

When the jQuery ajax() method is called with the dataType: 'html' option, included script tags are automatically evaluated when inserted in the DOM. You may want to check the following Stack Overflow post for further reading on this:

Daniel Vassallo
Thanks for that shorted code for the getData!
Joel