server: apache http server 2.2
problem: code does not load my text file
hello people. im currently trying to learn javascript and am following several tutorials. written below is a code off of w3schools. what its supposed to do is change the displayed text upon clicking the button. however, this does not work for me. the html file where the code below is save and the text file im trying to open are in the same folder.
im accessing the html file off of chrome using this: http://localhost/ajaxtutorial.html. while it does display the html file correctly, upon clicking the button nothing happens. ive tried changing the file to php and making an equivalent php file to the said text file but still nothing happens. please help.
<html>
<script type="text/javascript">
//comments are from http://www.tizag.com/ajaxTutorial/ajaxxmlhttprequest.php
function loadXMLDoc(url , cfunc)
{
var xmlhttp;
//XMLHttpRequest object is used to exchange data with a server behind the scenes
//creates an xmlhttprequest object
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//The XMLHttpRequest object has a special property called onreadystatechange
//onreadystatechange stores the function that will process the response from the server
//every time the "ready state" changes, this function will be executed
xmlhttp.onreadystatechange=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
function myFunction()
{
loadXMLDoc
("ajax_info.txt",
function()
{
//The XMLHttpRequest object has another property called readyState
//This is where the status of our SERVER'S RESPONSE is stored
//The SERVER RESPONSE can be processing, downloading or completed
//When the property readyState is 4 that means the response is complete and we can get our data
//Download worked as intended, data request successful if status property = 200
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
);
}
</script>
<div id="myDiv">
<h2>Let AJAX change this text</h2>
</div>
<button type="button" onclick="myFunction()">Change Content</button>
In myFunction the xmlhttp variable is not in the scope of the function. This should be causing a JavaScript error, which you can view in Chrome by going to Menu > Tools > JavaScript console. One way to fix this would be to pass the xmlhttp object as a parameter.
function loadXMLDoc(url , cfunc) {
//some code...
xmlhttp.onreadystatechange=function() {
//pass xmlhttp as a parameter to this function and preserve the context
//see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
cfunc.call(this, xmlhttp);
}
//some more code...
}
function myFunction() {
loadXMLDoc("ajax_info.txt", function(xmlhttp) {
//xmlhttp is now in scope because we passed it as a parameter
});
}
Update
I created a working example at http://jsfiddle.net/6rPgE/
As for your question about the modifications I suggested...
The second parameter to the loadXMLDoc method (cfunc) is a function. In this case, an anonymous function is created inside myFunction which will be passed as the cfunc parameter to loadXMLDoc. When the onreadystatechange callback is invoked, the cfunc function is called with xmlhttp as the first parameter. This parameter is passed into the anonymous function defined inside myFunction, and is responsible for actually doing something with the AJAX response. On an entirely different note, I highly recommend using a debugger (Chrome has one built-in) and the information provided by the browser's error console to assist you in debugging these issues in the future. Learning how to use a debugger will save you countless hours of banging your head against the wall.
Update 2
Just thought it would be nice to look at how this can be done using jQuery with quite a bit less code. AJAX is one area where it can be really nice to use a library that abstracts away the details.
Another example that uses jQuery at http://jsfiddle.net/j9QvE/1/
Update 3
Note that in my code I replaced the path to ajax_info.txt with a path specifically used for testing AJAX functionality in jsFiddle (/echo/js/?js=Success!). This was necessary because ajax_info.txt does not exist on the jsFiddle servers, so requesting it would have resulted in a 404 error. Don't forget to change the path to point to an appropriate resource on your own domain.
Related
I am pretty new to creating web applications, so I am very unfamiliar with working over a web server. Just to let everyone know, I am implementing html, javascript, strawberry perl, AJAX, and running over an APACHE 2 web server. I finally have my web app working, I have an html file that calls a perl script that is in my htdocs directory. Here is a mock up of my .html file for reference, this one simply alerts the user of the output printed by the perl script:
<!DOCTYPE html>
<html>
<head>
<script>
function loadXMLDoc() {
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
var str;
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
// Get output from perl script and print it
str = xmlhttp.responseText;
alert(str);
}
}
xmlhttp.open("GET","http://localhost/try.pl" , false); //perl script
xmlhttp.send();
}
</script>
</head>
<body>
<h2>Example</h2></div>
<button type="button" onclick="loadXMLDoc()">Display</button>
</body>
</html>
So this file test.html calls a perl script [try.pl] within the same directory. Also, the perl script just prints a number so this alerts the user of the number. This is just an example of my implementation. My actual perl script and java script [inside the ready state block] is much more complicated. Now I have to add functionality to my web app, so to my questions:
I am looking to run a second and separate perl script when a different event happens. For example, when a button is clicked this perl script is being ran. I am going to have another different event, say a double click on an icon or something, that will need to call this second perl script. Will I simply have the new event call a different function [the first is called Loadxmldoc()] that is almost identical to the one I have here except it will have different code in the ready state block and call a different perl script at the end of it? I am a little confused as to how to implement this.
Also, If I have a list of file names within my javascript code, I need to process EACH of the files using a perl script. Currently I am only processing one so calling the perl script as I have here is fine. I have looked all over the internet to try to find how I would do this but it seems every explanation just covers how to call "a" CGI script. So within my code, say where I am "alerting" the user, I am going to have an array that stores the file names. I need to iterate over this array and for each filename [array element] I need to call the same perl script to process that file. How should I go about implementing this? Currently, my html file is only calling the perl script once and I do not know how I could call it for EACH file since my GET command is outside of my ready state block...
Any help or direction would be appreciated. I am expected to deliver soon and have been spending way too much time sifting through repetitive examples that haven't helped me...:/
As far as generalizing your AJAX request, you can create a function (or rather, a set of functions) that would process different types of responses, as follows:
var requests = [];
requests['script1'] = "http://localhost/try.pl";
requests['script2'] = "http://localhost/try2.pl";
var response_processing = [];
response_processing['script1'] = function (xmlhttp) {
var str = xmlhttp.responseText;
alert(str);
};
// Here, you can add more functions to do response processing for other AJAX calls,
under different map keys.
Now, in your AJAX code, you call an appropriate request AND appropriate response processor, based on your script name (passed to loadXMLDoc() call as follows): loadXMLDoc("script1");
function loadXMLDoc(script_name) {
// Your generic AJAX code as you already implemented
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
response_processing[script_name](xmlhttp);
// Careful so script_name doesn't get closured in onreadystatechange()
}
}
xmlhttp.open("GET", requests[script_name], false); //perl script
xmlhttp.send();
}
What I have:
- A database table called 'orders' that is constantly populated by some java module on the back-end.
- A website running on Grails that displays those orders. More precisely - a list.gsp in the Orders view.
- the list.gsp will display new orders if the refresh button is pressed on the browser.
What I need:
- Some way for the .gsp page on a client to get refreshed automatically when a new order is placed on the database.
- The autorefresh needs only to autorefresh the .gsp page when the client is already in the .gsp page. i.e. if a client is on the show.gsp for a particular order, then no need for autorefresh.
Things I though might help:
option1: Having a grails service that will periodically (every 5sec.) query the database to see if there are any new orders. If there are, then somehow from the .gsp page call again and re-render the .gsp page ??!
- suboption1-1: create and destroy a new connection every 5 sec.
- suboption1-2: create and keep a connection alive ... forever
option2: Have the java module that places the orders call a refreshController thru the web and somehow re-render the .gsp page. i.e. Have the refreshController notify all clients currently in the .gsp page that a refresh is needed.
=================================================================================
Follow up:
How can I call a controller from java script?:
function checkDB()
{
t = setTimeout("com.mypackage.DBChecker.checkdbController.checkAction()", 5000)
}
==================================================================================
Follow up 2:
So I almost got what I wanted working except that I can't figure out how to AJAX back to my list.gsp page only part of itself. I dont want to refresh the whole page, but only a division with id="refresh table". i.e. .
I have the following code at the moment that is not working:
<script type="text/javascript">
function checkDB()
{
var xmlhttp;
var xmlDoc;
var x;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
xmlDoc=xmlhttp.responseText;
x=xmlDoc.getElementsByTagId("refreshTable");
for (i=0;i<x.length;i++)
{
txt = x[i].childNodes[0].nodeValue;
}
document.getElementById("refreshTable").innerHTML=txt;
}
else
{
}
}
xmlhttp.open("GET","http://localhost:8080/Orderlord/checkdb/checkdb",true);
xmlhttp.send();
}
window.load = checkDB();
</script>
=================================================================
Follow up 3:
I succeed in returning only a partial page through my ajax call by copy/paste the div that i wanted to a separate gsp. I dont know how It is working - it's a bit of a magic to me, but everything works, except for when I try to sort the columns of my table. Then, only that partial gsp is rendered on my browser, without the rest of the initial page resulting, in a simple tabulated text page. Also once I end up in that kind of html page - the autorefresh doesnt work anymore, but as long as I will stay in the checkDB list view, the page will refresh every 5 seconds.
...So , how do I fix my problem
Another thing i cant figure out is how to return True/False from a controller to a javascript function in the gsp and how exactly did you have in mind for me to use it?
And lastly, I am currently using 'window.load = timeDB' inside my tag to call the timer function. I tried using , but for some reason I cant get it to work no matter what. Is there something I should keep in mind when using ?
Very lastly: What can I do to simply refresh part of the gsp every 5 sec?
You could take the approach of setting a timer on the page via javascript. You would then invoke a lightweight ajax call from your gsp page back to your controller that would yield a true/false to indicate if you needed a full refresh. This is a fairly simple approach but you would want to be careful that the back end target of the ajax call is optimized as it will be called every 5 seconds for each user on that page. It also generates quite a bit of traffic.
I might explore the publish subscribe plugins from the earlier answer before falling back to this approach, however I have implemented the simple timer / ajax call (in the java struts world) on a medium size website with pretty good results.
What you're explaining is a typical publish - subscribe model.
There are a few plugins in grails that will help you do this. Look at Atmosphere and cometD for this. Both options provide this kind of pub/sub.
If they feel a little too heavy for what you want, you should checkout Pusher and the associated Grails plugin. It is a little nicer because you can just integrate a javascript library in your gsp page and do the push from the server side whenever an order is created. Feels slightly lighter than the 2 libraries above. It uses HTML5 web sockets.
So the following piece of code in my list.gsp did it for me. I decided that just refreshing the 'div id="myDiv"' under question every 5sec it's good enough, otherwise I would have hit the server every 5 seconds anyway since I am querying the database.
<script type="text/javascript">
function ajaxrefresh()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//alert("aaaaaaa")
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
else
{
//alert("state: "+xmlhttp.readyState)
//alert("status: "+xmlhttp.status)
}
}
xmlhttp.open("GET","http://${localHostAddress}:12080/Orderlord/refresh/refreshactiveorders",true);
xmlhttp.send();
var t=setTimeout(ajaxrefresh,5000);
}
window.load = ajaxrefresh();
</script>
Here's a sample XMLHttpRequest I cobbled together from w3schools
<html>
<head>
<script type="text/javascript">
function loadXMLDoc()
{
var T="nothing";
xmlhttp=new XMLHttpRequest();
xmlhttp.overrideMimeType('text/plain'); // don't sc
xmlhttp.onreadystatechange=function()
{
alert ("rdystate: " + xmlhttp.readyState);
alert ("status: " + xmlhttp.status);
alert ("Text: " + xmlhttp.statusText);
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
T = xmlhttp.responseText;
}
}
xmlhttp.open("GET","SBL_PROBES.htm",true);
xmlhttp.send(null);
//T = xmlhttp.responseText;
alert(T);
}
</script>
</head>
<body>
<h2>Using the XMLHttpRequest object</h2>
<div id="myDiv"></div>
<button type="button" onclick="loadXMLDoc()">CHange Content</button>
</body>
</html>
XMLHttpRequest always returns a zero status.
Nothing shows up in Firefox's error console.
If I change the request to synchronous one by changing the line
xmlhttp.open("GET","SBL_PROBES.htm",true);
to
xmlhttp.open("GET","SBL_PROBES.htm",false);
and un-comment the line
//T = xmlhttp.responseText;
The text of the requested file is returned.
The HTM and the file reside in the same directory. If you try this you will need a file SBL_PROBES.htm there also, it's contents are irrelevant.
I'm using Firefox 3.6.22.
Could this be a cross domain problem? If so, why does it work as a synchronous request?
You can use a function inside the if statement. This function is executed when readystate changes to 4.
var handleResponse = function (status, response) {
alert(response)
}
var handleStateChange = function () {
switch (xmlhttp.readyState) {
case 0 : // UNINITIALIZED
case 1 : // LOADING
case 2 : // LOADED
case 3 : // INTERACTIVE
break;
case 4 : // COMPLETED
handleResponse(xmlhttp.status, xmlhttp.responseText);
break;
default: alert("error");
}
}
var xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=handleStateChange;
xmlhttp.open("GET","SBL_PROBES.htm",true);
xmlhttp.send(null);
Your old code did a asynchronous call and continued just with the alert Statement. T was empty at this time.
Ok, I'll explain a little bit how this whole thing works:
First we define two callback functions, which we call later in the request, named handleResponse and handleStateChange.
Afterwards we create a Object, which represents the XMLHttpRequest
var xmlhttp=new XMLHttpRequest();
This results in an Object as follows (simplyfied):
XMLHttpRequest { status=0, readyState=0, multipart=false, onreadystatechange=handleEvent()}
With the open(...) function call you set parameters for the request:
xmlhttp.open("GET","SBL_PROBES.htm",true);
This means, do a asynchronous GET Request to fetch the Page SBL_PROBES.htm
Then the send(...) function is called which fires the request itself.
We registered a callback function for the onreadystatechange, as you can imagine, this is actually an eventHandler. Each time the state changes this function is called. (It is the same as if you register a callback function to an onKeyUp Event in a form, this callback is triggered each time your key goes up :) )
The only case which is of interest for your problem is state 4. Therefor the handleRequest callback function is called only in state 4. At this time you Request has actually a result, and further a status. (Status means your webserver returned a status code 200=ok, 404=not found etc.)
That is not all the magic which is behind the ajax stuff, but should give you a simplified overview, what is actually happening behind the scenes.
It is important that you test this on a webserver, do not use file:// for testing.
If you need more in detail info, just let me know.
Status Zero happens for two reasons.
You are running off the file protocol.
Something is posting back the page when the Ajax request is active.
I believe you are seeing #2 here. SO you need to cancel the button click.
<button type="button" onclick="loadXMLDoc(); return false;">CHange Content</button>
In your code above that alert(T) will always say nothing when the request is asynchronous.
Its because async returns before the request returns. Synchronous requests return after the request returns.
Try manipulating your logic in here.
xmlhttp.onreadystatechange=function()
{
alert ("rdystate: " + xmlhttp.readyState);
alert ("status: " + xmlhttp.status);
alert ("Text: " + xmlhttp.statusText);
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
T = xmlhttp.responseText;
alert(T);
}
}
I've battled the problem of not getting a result when using asynchronous XMLHttpRequest open statement. Since this question is the first I found when using google, here is how I solved it:
If you use a button that is inside a form, make sure it is set to type="submit" and onclick="return myFunction()". And in myFunction(), make sure you return false, not true! By returning true from the function, you reload the page and the XML object disappears. If you return false, the XML request gets the time it needs to complete and the onreadystatechange function will be run.
Source: Flask Mailing List
I have now received the good response to this common problem. The response follow:
This is a very common problem when developing for the web. There's two ways around it.
The first is to use JSONP, which our API supports when you add a query parameter ("?callback=foo"). This should get you up and running right away and is great for development, but it isn't secure for production use since users get access to your API key.
The second (which is what we use on Forecast, and is the best method for production) is to set up a proxy server on your own domain which can make requests to Forecast on the user's behalf. This sidesteps the browser's same-origin policy, prevents users from accessing your API key (which can be stored server-side), and also allows you to make use of request caching, if desired. (Our favorite web server, NGINX, supports this out of the box and is really easy to configure. If you need some sample configurations, let us know!)
I'm trying to use JavaScript to manipulate page content in a dummy webpage I'm building.
To that end, I wrote a little function called writeText(file_name, location) that gets a HTML file specified by the file name, and prints the content of that file to the innerHTML of a pair of <div> tags whose id attribute correspond to the location field.
I then wrapped the calls in other functions to automate building full pages like this.
So I call something that looks like this:
function displayHome() {
writeText('homeMain.html', 'mainFrame');
writeText('homeSide.html', 'sideFrame');
}
...to display the home page.
However, when I call this function, the display only updates the 'sideFrame' object and doesn't make any changes to the content of 'mainFrame'. But if I interrupt the function with an alert("Dummy") between the two writeText() calls, then both of the contentFrames update correctly.
I was wondering if anyone has seen anything like this before, and if anyone knows how to fix it.
For completeness' sake (this was copied nearly verbatim from the w3schools website):
function writeText(script_file, location) {
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
document.getElementById(location).innerHTML = xmlhttp.responseText;
}
xmlhttp.open("GET",script_file,true);
xmlhttp.send();
}
You are using a global variable xmlhttp, so it gets clobbered the 2nd time the function runs. The request itself is asynchronous, so the second call runs while the first one is still running.
To fix this, use a local variable instead (so each call to the function has its own xmlhttp) by using the "var" keyword before xmlhttp:
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
I am calling a ajax method to update a div. It contains links and functions which require java script files. But these methods and functions are not getting called properly as java script files are not getting included through ajax call. For example, i am trying to call a light box function, but it gets redirected to different page and not in light box.
Thanks in advance, Anubhaw Prakash
The Ajax framework in prototype will properly execute the text content of <script> tags, but will not import new script files via <script src="somefile.js"/>. The only solution I came up with is to import all javascript files I need in the head of the page. That way the functions in the imported file are available to the inline javascript code executed in the Ajax response.
I had a similar problem, where I did want to postload some javascript. What I did is separating loading the html-fragment and loading the script into two calls. For loading the script I call the following function (I have JQuery handling the ajax part):
function loadModule(name, callback) {
$.ajax({type: "POST"
, url: "/js/" + name
, dataType: "script"
, success: callback
});
}
I see you're using Ruby on Rails — does that mean you're using Prototype on the client? If so, Prototype's Ajax.Updater will ignore script tags that reference external files (it will evaluate script tags that have their contents inline). So to add those external files to your page, you'll have to hook into the process via the onSuccess callback, look in the responseText for script tags with src attributes, and handle those yourself. Once you've identified the relevant script tags and extracted their src attributes, you can include them by dynamically adding the scripts as described in this article from the unofficial Prototype & script.aculo.us wiki.
<script> tags written to innerHTML are not executed at write-time. You can do element.getElementsByTagName('script') to try to get hold of them and execute their scripts manually, but it's very ugly and not reliable.
There are tedious browser differences to do with what happens to a <script> element written to innerHTML which is then (directly or via an ancestor) re-inserted into the document. You want to avoid this sort of thing: just don't write <script>s to innerHTML at all.
Then you also don't have to worry about executing scripts twice, which is something you never want to do with library scripts. You don't want to end up with two copies of a function/class that look the same but don't compare equal, and which hold hooks onto the page that don't play well with each other. Dynamically-inserted library scripts are a recipe for confusing failure.
Much better to include your scripts statically, and bind them to page elements manually after writing new elements to the page. If you really need to you can have your AJAX calls grab a JSON object containing both the new HTML to add and a stringful of script to execute.
May want to try running some prepatory javascript in the :before option to setup a variable with the correct files?
hey i found a way to add it....:)
NOTE- this is a synchronous process so you dont have to worry about that the script is loaded or not.... the script will always load the instance u call the function and you can start using the loaded script instantaneously..
lets use these 2 functions
1) first one is the ajax function to retrieve the values
where async should be true to send the request synchronously
// AJAX FUNCTION
function loadXMLDoc(reqt,url,reqp,cfunc,async)
{
var xmlhttp;
try// code for IE7+, Firefox, Chrome, Opera, Safari
{
xmlhttp=new XMLHttpRequest();
}
catch(err)// code for IE6, IE5
{
try{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e){
try{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch(E){}
}
}
if(!xmlhttp)
{
alert("error");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4 && xmlhttp.status==200)
{
cfunc(xmlhttp.responseText);
}
}
if(reqt=='GET')
{
url+=(reqp!=""?"?":"")+reqp;
xmlhttp.open("GET",url,(async?false:true));
xmlhttp.send();
}
else if(reqt=='POST')
{
xmlhttp.open("POST",url,(async?false:true));
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(reqp);
}
else
{
return false;
}
}
/*use this function
loadXMLDoc(reqt,url,reqp,function(response){
});
*/
2)then we use ajax to load the js file as string and then append it to the new script tag's innerHTML and then append it to the head section and one more thing to ensure file is already loaded i used the id of script tag as the path to the file which makes it really easy task to check for the duplicate...:)
//add new script dynamically
function add_script(src)
{
if(!document.getElementById(src))
{
loadXMLDoc("GET",src,"",function(jsresp){
var head = document.getElementsByTagName("head")[0];
var script=document.createElement("script");
script.type='text/javascript';
script.id=src;
script.text=jsresp;
head.appendChild(script);
},true);
}
}
thanks for all help i used to get and will get from this site and its users for the development purposes...
regards VIPIN JAIN
include static scripts on pages that need to use them (IE contain a lightbox, then include the lightbox script)
Problem solved. Do not load scripts using AJAX
Make necessary function calls to the static scripts using AJAX callbacks