views:

662

answers:

4

I am trying to create an auto-refresh for a table using ajax/jquery, php/html, and Drupal 6.

Code once the database insert has finished and was successful:

echo "<script type='text/javascript'>autoRefresh()</script>";

Code for the link that eventually calls the javascript code that actually performs the refresh of the table:

    $block_content .= "<br><a id='refreshItemId' class='refreshItemLink' href='$host_url/refresh/projectitems/gid/$curr_gid/nid/$curr_nid'>Refresh List</a>";

Javascript code that is added to the page using PHP (I know it could be a javascript file and then include that, but that's for another day). This is the code I added to attempt to automatically make click() the link created above once a form is submitted and the item was successfully added to the database:

    $block_content .= "<script type='text/javascript'>
        function autoRefresh()
        {
            alert('Auto Refresh');
            //document.getElementById('refreshItemId').click();
        }
    </script>";

I thought this would have worked, but the autoRefresh() JS function never gets called. Any ideas?

A: 

You need to send the function definition before calling it.

The user agent (browser) otherwise tries to call a function that not yet exists which results in an error.

PvB
A: 

You need to wrap the AutoRefresh call in a "onload" event handler. Right now the function is running (or trying to run) as soon as it is output to the browser, so there isn't a button to click at that point.

In jquery:

<script type="text/javascrpt">
    $(function() {
        autoRefresh();
   });
</script>

Update:

If you want the refresh button to be clicked after the user has made changes via AJAX, do something like:

$.ajax({
  data: //data sent to script;
  url: //path to PHP script
  success: autoRefresh();
  }
});

If you want to only have it update when the PHP script sends some kind of "safe word" change the success function to something that reviews the server's response, and if it's the "all clear" signal, then does the autoRefresh.

Update 2:

Okay, having hashed this out, what you need is your own event handler tied to the function. So have the PHP output the following jquery script:

 <script type="text/javascript">

 $(function() {
     $("#refreshItemId").click(function() {
     $(this).delay('200');
     autoRefresh();
     });
 });

Couple of notes:

The delay method is new to jquery 1.4. If you have an older version, there are other methods that can be used to stall the function.

I haven't had a chance to mess with .delay() that much yet, so I may have messed up a bit.

But the overall idea should be clear: Bind the function to the link when the page loads; When the onclick event triggers the function, it waits .2 seconds for the Drupal ajax to finish; finally, it triggers the autoRefresh function.

Anthony
Well the page isn't re-loading ... otherwise I wouldn't need to this auto-refresh. The call is output to the browser at exactly the time I want to make the call and it is after the initial page is loaded and the function should be there.
Brian T Hannan
You are trying to run a reload script by injecting a call in the head of the document from PHP? So how is PHP outputting to the document so that the call is made?
Anthony
Do you just have the server in some kind of sleep state? What triggers it to wake up and output to the browser?
Anthony
I'm not sure what you mean. I have a form, and a table. The form lets you add items to the table. When a new item is added it makes a call to the database. When that calls to the DB is successful, then I want to auto-refresh the table. I have everything in place to refresh the table, but the user has to click on a link in order to do it. All I want to do is instead of manually clicking on that link ... just automatically call it somehow.
Brian T Hannan
All the code above is PHP code, but some of it outputs javascript code.
Brian T Hannan
Then you need to return some kind of success response to the ajax that calls the PHP and have the ajax autorefresh. The script that you are outputting is being handled by the ajax function, not the browser. I'll update my answer with what you need.
Anthony
If all of the code is PHP, where does the Ajax come in? that's where the autorefresh needs to happen. You can't output HTML to the browser via an ajax request. You can send HTML back to the ajax function and it can output to the browser.
Anthony
I was saying all the code I posted above is PHP code. The only javascript code I have is for the actual refreshing, which does work. The AJAX call is from a Drupal form of which I don't have access to b/c it's built into Drupal. I just need some way to trigger a javascript function from HTML for PHP code without user interaction and not during onload b/c it's too late at that point.
Brian T Hannan
Okay, so the page refreshes every time it reloads, that's normal. So do you want the page to refresh when a user does something (other than click a button)? What I mean is, what actually happens that makes you want the page to refresh? Is it something that happens independent of the user? Is the table just being updated all the time, like a stock ticker and you want those changes to trigger the page to refresh? None of the above will be as simple as the PHP just outputting some code. Keep me posted.
Anthony
If the table has updates that are just happening, not because the user input data into the table, etc, you have one of three options: 1) You can have some ajax function that pings the server at a steady interval and checks to see if its time to refresh, 2) you can create an open stream between the server and page so that any changes are "pushed" (it sounds like you don't want something this complicated) or 3) You can have the page auto refresh every minute or so whether it needs to or not.
Anthony
Otherwise this is what it sounds like you are saying: "I want a javascript function that auto-refreshes the page while the page is loading." Which doesn't make any sense, since the act of loading the page implies that any info is already refreshed. It sounds like you are trying to output new info via PHP to a page that is already loaded to put NEW info on the already loaded page, which isn't how HTTP or ajax works.
Anthony
Thanks for all your input, but I think we are different pages. My situation is strange and is a little difficult to explain. To answer your question, the user is inputing data that I want updated but the problem is that it's from a Drupal form. I'm not sure if you're familiar with Drupal forms but it's an abstraction that you don't really have access to the AJAX part when you tell it to use AJAX. So when the user clicks the Add button from the Drupal form I don't have any way from that code to trigger the refresh ... or do I? As far as I can tell I don't have access there.
Brian T Hannan
The reason why the button works and the other way doesn't is because the button has an "onclick" event tied to it. The page sits there quietly, but when the user clicks the button, that triggers some javascript to refresh the page. What you want is for this to happen with no button pushed, but there is also no event that triggers the page to refresh at all. You need something that tells the page when to do the function. Either an ajax function that asks the server, or just have the function run automatically on a timer.
Anthony
For more clarification, you can go to the website I'm working on: http://www.everybodyeco.com/content/solar-oven. I'll create an account for you with username: anthony and password: anthony, but change it as soon as you log in. It doesn't really matter I'm going to delete it after you access it. I have to make you a manufacturer of the project in order for you to see the add form.
Brian T Hannan
Ah! awesome. So the user clicks a button to add the data, some ajax happens, but you don't have access to that ajax to have it trigger the page to refresh. So instead, add your own ajax function that says that when the button is pushed, to wait 1 second and then refresh the page. You can tie two event handlers to the same event, the only thing you need to work out is the timing to make sure your function happens after the first one is done.
Anthony
Nice site, btw. Checking out the table now.
Anthony
Couldn't get to place to edit, but I did see the link that you are probably referring to. I'm pretty sure my solution in the last comment should do it. At least it will refresh the page, which is the first step.
Anthony
Thanks, my buddy and I have been working on this idea for a little while now! You now are a manufacturer of the project and should be able to see the add item form in the Build It tab.
Brian T Hannan
Yeah, it sounds like i can set up multiple event handlers for the Drupal form and it will work that way. I'll give it a shot.
Brian T Hannan
This actually still doesn't work for me. The multiple event handlers for the Drupal form won't do it. It would basically call a different php function but then I will have the same problem of how do I trigger the JavaScript function from PHP. This should be simple.
Brian T Hannan
The problem is that you are having Drupal set ajax event handlers, which isn't what you need. What you need is a second event handler that simply calls the autoRefresh function, like in my third example. PHP will not be able to talk to the browser after the page has loaded unless it is responding to an ajax function. Since can't modify the ajax function that Drupal is using, you have to make a separate event handler that doesn't do anything but the autoRefresh function. No ajax or PHP required.
Anthony
Try this (no jquery): `window.onload = function() { var tableSubmit = document.getElementById("refreshItemId"); tableSubmit.onclick = autoRefresh; };` Add that right below the autoRefresh function script. It may not show the changes submitted, it may even screw up the ajax getting called, but you will see how clicking the one button triggers the autorefresh function. Then it is just a matter of adding some kind of delay so that it reloads the page a split second after the other Drupal event handler starts.
Anthony
I'm not sure I understand where you are suggesting to put this.
Brian T Hannan
Even though I didn't get the solution I needed, your interaction was very helpful.
Brian T Hannan
A: 

If you are updating the content of the page using the innerHTML or similar, the code will not be executed when it is added to the DOM. Clever usage of eval() might fix this, although it may also open you up to potential XSS vulnerabilities. The safest route is to already have the function defined in the page, and then call it when the XHR successfully returns.

Dereleased
what are XSS, and XHR?
Brian T Hannan
XSS is Cross Site Scripting, its used to retrieve private information by injecting malicious code. And XHR is XMLHttpRequest, commonly used for AJAX calling with PHP.
Anthony Forloney
XHR is the XMLHttpRequest used to make AJAX requests. XSS is cross-site-scripting, a problem you tend to get when you don't escape your output strings properly, for example the completely insecure `echo "<div>$title</div>"` style of templating that forgets to call `htmlspecialchars` when inserting text into HTML.
bobince
A: 

EDIT! After re-reading the entire thread with Anthony:

Couple things:

  • See if you can add "eval()" on your return response.

    echo "<script type='text/javascript'>eval('autoRefresh()');</script>";

  • Try to put that autoRefresh() function in a global include JS file called in the head tag.

Another alternative would be to overwrite the functions already in your drupal library so you can add those things you wanna do in the Ajax call.

JONYC
The call is make via the <a> tag I posted above. There is a Drupal menu item that let's you goto a link and it then makes the AJAX call to refresh the table. The refreshing itself already works, but the user has to click on a link in order for that javascript code to be executed. I just need a way to trigger that javascript code without user interaction and without an onload event.
Brian T Hannan
Can I put this code into my PHP? Output it as Javascript and have it then be executed? I'm not sure how this all works b/c I'm still kinda new to AJAX and JQuery.
Brian T Hannan
Updated the above code to give you the full solution. Let me know if it works. :)
JONYC
It looks like a decent solution. Does $_REQUEST['myVar'] make the call to doSomeAjaxStuff()? I need a way to trigger that function from my PHP code.
Brian T Hannan
The ajaxScript.php will be the response script by itself. The other code (prototype + HTML) will go into the existing PHP page where you initiate the call.
JONYC
I think you have misunderstood the problem. I think Anthony got it. We'll see if that works.
Brian T Hannan
I read your whole thread with Anthony and I finally understand what you meant. The delay will not work. you need to tie it to the onSuccess because depending on your user connection, the amount of time given may not be enough "wait time"
JONYC
Try to put the autoRefresh() function in a JS file in the head tag?
JONYC
Yeah I agree, that won't work. Basically I have functioning code that refreshes the table (not the page). I need a way to trigger the click() function of the link without having to click it. Auto-clicking if you will. I have a spot in the PHP code when I know for a fact that the insert into the DB was successful and I just want to put something right there in the PHP to auto-click the link that already works for refreshing the table.
Brian T Hannan
By the way, I have already moved the autoRefresh() function into a JS file that gets included during the original page load.
Brian T Hannan
just updated... see if that "eval()" thing works for you.
JONYC
This whole thing is very hack-ary.. I like!
JONYC
The eval didn't work. I did this: if( db_query($insert_query) ) {//You successfully added the item to the project, try to do an auto-refresh here: echo "eval('autoRefresh()');"; }
Brian T Hannan
This is the part when the insert query actually get done and is successful. I just added the echo there, but it didn't call the javascript function.
Brian T Hannan
Did you put the script tag around it?
JONYC
script tag? like the javascript tag? echo is in php and so is the if statement i put it in between.
Brian T Hannan
yes. Sorry I just realize SO didn't block my code correctly. you'll see what I mean above in the answer.
JONYC
It looks like I might have to overwrite some library/module functions, but that was what I was trying to avoid. The reason I don't like that is if they make an update then I have to reconsider my code based on their changes. If they do a rewrite then so do I, yarg!
Brian T Hannan
Yeah.. but that's not too bad. Make sure you don't do it to the original code. Instead put it in a separate JS to overwrite by putting that include lower in the doc flow.
JONYC