Help me properly make an AJAX call - javascript

I have a JavaScript function that is being called. I need to have it call a PHP function and return a true/false.
The script with the function is in the file /db/cancel_hike.php
My current JS looks like this:
function uncancelHike( hike_id )
{
//var url = "/db/cancel_hike.php;
var success = null;
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.open("GET", url , true);
request.onreadystatechange = function()
{
if (request.readyState == 4)
{
var xmlDoc = request.responseXML;
// obtain the array of markers and loop through it
markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++)
{
// obtain the attribues of each marker
success = markers[i].getAttribute("success");
if ( success == "true" )
{
document.getElementById("success").style.display = 'block';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'error';
}
if ( success == "false" )
{
document.getElementById("success").style.display = 'none';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'block';
}
}
}
}
request.send(null);
return false;
}
What I am having trouble with is:
How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?

How to call an actual function in the PHP script?
You can't. You request URIs.
Write a PHP script that calls the function you want and place it at the URI you call.
(You can use query strings and the like as the input to an if statement that you use to conditionally call different functions)
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
You can return any kind of data you like.
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?
It's a library. You never need to make calls to it. It often simplifies the code you have to write.

How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
Well, you don't call the actual function. What you want to do is pass variables using GET, that is, by appending them to the URL like file_name.php?var1=this&var2=that to pass var1 of "this" and var2 equaling "that." You retrieve them in the PHP file with $_GET['this'] and $_GET['that']. Whatever PHP outputs to the page via echo, print_r, etc. is then sent back in a request object as part of its responseText property.
You just set url in request.open to a URL on your site. For example, in your .js file:
request.open("GET", "answer_me.php?hike_id=" + hike_id, true);
And in your .php file:
<?php
$hike_id = $_GET['hike_id'];
if ($hike_id < 5) {
echo "true"; // echo true would return "1", BTW
} else {
echo "false"; // echo false would return nothing
}
Note that that will just return a string value to request.responseText of false, thus you could do this:
var result = request.responseText;
if (result === "true") {
...
document.getElementById("success").style.display = "block";
...
} else {
...
document.getElementById("success").style.display = "none";
...
}
You do not need it to be XML, especially as it looks like you're not really using the loop (the same three DOM elements are being assigned values each time).
And honestly, for AJAX I'd recommend using a framework like jQuery (or YUI, although I don't find its AJAX stuff as intuitive). Your entire code would look like this:
var $success = $("#success");
var $error = $("#error");
function cancelHikeCallback(data) {
var is_success = (data === "true");
$success.toggle(is_success);
$error.toggle(!is_success);
}
function cancelHike(hikeIdToSend) {
$.get("/db/cancel_hike.php", {hike_id: hikeIdToSend}, cancelHikeCallback);
}
IMO things like jQuery's $.ajax ($.get is a specialized form of $.ajax) make this stuff much easier to read and debug.
jsFiddle Example

Related

Returning JSON from PHP, convert JSON to javascript array, return array from AJAX call

I am working on a project that uses a function I called AjaxRequest which handles all AJAX requests I make. I have no problems in making the request however getting the request back is the issue and placing it where I want it on my page is becoming stressful.
HTML BIT
<body onLoad="calling();">
<div id="status">Status: </div>
</body>
JAVASCRIPT BIT
function calling() {
var answer = ajaxRequest("testing", "test.php", "test=test");
document.getElementById("status").innerHTML += answer[1];
document.getElementById("status").innerHTML += " " + answer[3];
}
function ajaxRequest(app, location, credentials) {
var extras = "";
if(credentials === "" || credentials) {
extras = "&" + credentials;
}
var ajax = ajaxObj("POST", location);
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
var obj = JSON.parse(ajax.responseText);
var arrayObj = [];
for(var i in obj) { arrayObj.push([i, obj[i]]); }
return arrayObj;
}
}
ajax.send("app=" + app + extras);
}
there are two other functions running: ajaxObj and ajaxReturn but I excluded those because they is not the problem. Furthermore, I am trying to make ajaxRequest an efficient function that could be used by more than one application without having to rewrite all the code in more than one location. All error handling acquires before the actual use of ajaxRequest.
PHP BIT
<?php
if($_POST['app'] == "testing") {
$hey = array('success' => 1, 'message' => 'Successful');
echo json_encode($hey);
exit();
}
?>
I'm using calling as a javascript function that does all error handling, this is just basic for the whole of my project however I try to get the JSON from php and convert it to array and the issue is returning the array into calling. I try to display the information on the page yet nothing works.
I am not looking to use any JQuery for my project so I would like to exclude the use of it for this piece of code.
If you want, you could set the header before sending back the json.
header('Content-Type: application/json');
Usually you don't need it, but it will tell your javascript that it's json, and the array will be transform in a javascript object. It work with Jquery, but I assume it'll work without too

JavaScript global variable value does not change until after alerted

This is my first question and I hope I don't do anything wrong. First of all, thank you for reading.
And my problem is...
The design is to read some data in a text file with JavaScript, process them through a number of functions before creating the content to display in an HTML div.
After some searching, I figured that it could be done with XMLHttpRequest. Because the read data will be processed by some functions, I decided to store them to a global variable for easy access. The code seemed to be working fine at first and I could print the obtained data to a div. But then I noticed a strange bug. If I assign those data to a global variable and attempt to retrieve them later, I will get the initially assigned value or undefined. I try to alert that global variable's value and I see what I get above. However, if I alert again, the value changes to what I needed. I have just been learning JavaScipt for a short while, facing this error completely leaves me at lost.
The html file:
<html>
<head>
<meta charset="UTF-8">
<title>Read file</title>
<script>
var output = ["next"];
function edit()
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "test.txt", true);
rawFile.responseType = "text";
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
output[0] = rawFile.responseText;
//alert("Reading okay!");
}
}
};
rawFile.send(null);
console.log(output[0]); // initial value
alert(output[0]); // initial value
console.log(output[0]); // desired value
alert(output[0]); // desired value
}
</script>
</head>
<body>
<button onclick="edit()">Read test.txt</button>
</body>
</html>
The text file:
This is the content of the text file.
Temporarily, I have to alert every single time the text file is read which isn't a good idea to solve the problem.
My question is, with the above design, is there any better way to implement it without having to deal with this bug?
And here is the demo: html and text.
Thank you very much.
That's because the value changes asynchronously.
The alert is no guaranty, it's just a delay after which the AJAX callback could have been executed or not.
If you want to use the desired value, you must run your code in onreadystatechange.
Example:
function edit(callback)
{
/* ... */
rawFile.onreadystatechange = function () {
if(rawFile.readyState === 4 && (rawFile.status === 200 || rawFile.status == 0)) {
output[0] = rawFile.responseText;
//alert("Reading okay!");
callback();
}
};
/* ... */
}
fuunction afterEdit(){
alert(output[0]); // desired value
}
<button onclick="edit(afterEdit)">Read test.txt</button>
Since the AJAX call is asynchronous, it is being executed after your edit function returns... Since it sounds like you are passing your data through a series of functions, I suggest using a promise library (Q.js for instance). Here is a simple jsfiddle that demonstrates using Q.js.
Your AJAX call would simply resolve the promise, kicking off the chain of functions to execute. My example shows modifying the data at each step, but this is not necessary. The return value of the prior function will be used as the input for the next function. I've commented out the AJAX stuff and used setTimeout to mimic async call:
//Global variable for test.txt
var test;
function edit()
{
/*
var deferred = Q.defer();
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "test.txt", true);
rawFile.responseType = "text";
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
//resolve promise with responseText;
deferred.resolve(rawFile.responseText);
}
}
};
deferred.promise
.then(processStep1)
.then(processStep2)
.then(processStep3);
*/
//Imitating async call that will finish after 2 seconds
var deferred;
var promise;
//if we haven't read the file yet, then make async call
if (test === undefined) {
deferred = Q.defer();
setTimeout(function () {
test = "This is the content of the text file."
deferred.resolve(test);
}, 2000);
promise = deferred.promise;
}
//Else we've already read the file.
else {
promise = Q(test);
}
//Start adding your functions to process text here:
promise.then(processStep1)
.then(processStep2)
.then(processStep3);
}
function processStep1(data) {
alert("Step 1: " + data);
//adding some stuff onto data for example
data = data + "... And more data.";
return data;
}
function processStep2(data) {
alert("Step 2: " + data);
data = "Adding data to front. " + data;
return data;
}
function processStep3(data) {
alert("Step 3: " + data);
return data;
}
Above, I also use a global variable (test) for the data retrieved from async call. I check this value when deciding if I need to make an async call to get the value, or use the value that was already populated from the original async call. Use whatever pattern most fits your needs.
I would also recommend a library for doing the async calls as your project might get messy fast by doing raw AJAX calls.

Retrieving a specific link from url using javascript

I need to make a function in JavaScript to locate href inside the url that is given, and to return it as a string.
For example: http://stackoverflow.com/
So the function starts with: function example(url) {}
I want to find the first link inside this url that contain the words google.
In this page there is somewhere link like <a href:"http://google.com/asdasdadsa/asdada">
The function is to return the whole link as string.
So basically from what I can gather, you want to look at each link on the page and get the whole URL if it includes some string (i.e. google).
Here's a function that finds the first link matching a certain string:
function checkLinks( searchString ) {
var url;
// Go through each link
$('a').each( function ( ) {
// Check if the search string exists
if( $(this).attr('href').indexOf(searchString) != -1 ) {
url = $(this).attr('href');
// If we've found one, stop the each.
return false;
}
});
return url;
}
I've put together a jsfiddle showing an example of how this function could be used:
http://jsfiddle.net/K9KvS/1/
EDIT:
I've just seen you need to do this on a remote URL. You probably need to use AJAX to load in the code, then run this on the code you have. Unfortunately due to the same origin policy, you can't get this directly, so you'll need to run a server-side script on your server (e.g. using PHP) to load the content of the external page, then an AJAX call from your JS to pull it into your javascript.
Modified version to include an AJAX load of some code, then a find on that code:
// Create a function to do the actual search
function checkLinks( code, searchString ) {
var url;
// Search the code for all <a> tags, the loop over them
$(code).find('a').each( function ( ) {
// Check if there is a match (indexOf returns -1 if not)
if( $(this).attr('href').indexOf(searchString) != -1 ) {
// set the "url" variable to the href
url = $(this).attr('href');
// Stop looping
return false;
}
});
return url;
}
// Now, when the page loads, attach an AJAX call to a button with ID "linkchecker"
$( function ( ) {
$('#linkchecker').click( function( ) {
var code;
// Perform the AJAX call, load the data and call our function above to find "google.com"
$.get( 'load_code.php?url=http://www.google.com', function( data ) {
code = data;
alert( checkLinks( code, 'google.com' ) );
});
});
});
load_code.php would probably look something like this (probably with some error checking, etc):
<?php
$htm = file_get_contents($_GET['url']);
echo $htm;
?>
Update: Using Raw Javascript
We'll modify checkLinks from above to use raw Javascript:
function checkLinks( code, searchString )
{
var url;
// We need to create an HTML document element so we can use javascript dom functions on it.
var doc = document.createElement("html");
doc.innerHTML = code; // put the code into the document
// Get all links in the code
var links = doc.getElementsByTagName("a")
// Loop over all links
for (var i=0; i<links.length; i++) {
// Check if the search string (e.g "google.com") is found in the href of the link
if( links[i].getAttribute("href").indexOf(searchString) != -1 ) {
// Set it to the return value
url = links[i].getAttribute("href");
// stop looping
break;
}
}
return url;
}
So firstly, you need to set up the Ajax request object. The problem is this differs between browsers, so you need an unpleasant bit of code to generate it across them. The following is modified from the tiztag ajax tutorial:
function makeAJAXObject(){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
return ajaxRequest;
}
Ok, so now we've got our AJAX object, we want to get it to load a page, and tell it how to handle what we get back:
/*
* A function to load a given URL and process the code from it.
* It takes three arguments:
* php_handler The name of the PHP file that will load the code (or ASP, or whatever you choose to use)
* url The URL to be loaded.
* searchString The string to find in the links (e.g. "google.com").
*/
function load_page( php_handler, url, searchString )
{
// Get the ajax object using our function above.
window.ajax = makeAJAXObject( );
// Tell the AJAX object what to do when it's loaded the page
window.ajax.onreadystatechange = function(){
if(window.ajax.readyState == 4){ // 4 means it's loaded ok.
// For simplicity, I'll just alert this, but you would put your code to handle what to do when a match is found here.
alert(checkLinks( window.ajax.responseText, searchString ));
}
}
// Set up the variables you want to sent to your PHP page (namely, the URL of the page to load)
var queryString = "?url=" + url;
// Load the PHP script that opens the page
window.ajax.open("GET", php_handler + queryString, true);
window.ajax.send(null);
}
The final thing is to attach this to a button when the page has loaded:
window.onload = function( ) {
document.getElementById('linkchecker').onclick = function( ) {
load_page('load_page.php', 'http://www.example.com', 'google');
}
}
Please note, there's likely to be built in WinJS functions to handle some of the AJAX stuff, but I've never tried Win 8 app development, so I don't know them!

Why does this function not return JSON string?

function addphoto()
{
var ajaxRequest = initAjax();
if (ajaxRequest == false)
{
return false;
}
// Return Ajax result when the state changes later
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
alert(ajaxRequest.responseText);
return ajaxRequest.responseText;
}
}
// Capture form elements
var values = {
"category" : encodeURIComponent(document.addphoto.category.options[document.addphoto.category.selectedIndex].value),
"photo_title" : encodeURIComponent(document.addphoto.photo_title.value),
"photo_descrip" : encodeURIComponent(document.addphoto.photo_descrip.value)
}
var queryString = '?', i = 0;
for (var key in values)
{
if (i != 0)
{
queryString += '&'
}
queryString += key + '=' + values[key];
i++;
}
// Execute Ajax
ajaxRequest.open("POST", "ajaxcheckform.php" + queryString, true);
ajaxRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajaxRequest.setRequestHeader("Content-length", queryString.length);
ajaxRequest.setRequestHeader("Connection", "close");
ajaxRequest.send(null);
}
function ajaxCheckform(formname)
{
var response = addphoto(); // <--This is undefined and not sure why
var responseObj = JSON.parse(response);
if (responseObj.success == 1)
{
// Successful form!
alert(responseObj.success_text);
}
else
{
// Error!
alert(responseObj.error);
}
}
I'm sure I must be making some basic error somewhere, but I'm having trouble locating it. In this script, ajaxCheckform() is a function that executes one of several similar functions. Above, I included addphoto(), which is one of several functions I'll need that look like this.
On a side note, I'd love to know I can call upon a function dynamically. The addphoto() function will be only one such function being called up at that moment and I'm trying to find a way to pass formname as the function I need. I've searched Stackoverflow and Google. I've found nothing that works.
Note, I'm aware of jQuery, but I'm not there yet. I need this function to work first.
It is not addphoto() thats undefined but response is undefined. ajaxRequest is asynchronous and the addphoto() function will return before the request completes.
try this
function addphoto() {...
// Return Ajax result when the state changes later
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
alert(ajaxRequest.responseText);
var responseObj = JSON.parse(ajaxRequest.responseText);
if (responseObj.success == 1) {
// Successful form!
alert(responseObj.success_text);
}
else {
// Error!
alert(responseObj.error);
}
}
}
....
}
function ajaxCheckform(formname) {
addphoto();
}
That's because response is set to the return of addphoto(), which is nothing. What you want to do is have ajaxCheckForm get called when the AJAX call is completed:
// Return Ajax result when the state changes later
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
ajaxCheckform(ajaxRequest.responseText);
}
}
Then your ajaxCheckform will work with that data:
function ajaxCheckform(responseText)
{
var responseObj = JSON.parse(responseText);
if (responseObj.success == 1)
{
// Successful form!
alert(responseObj.success_text);
}
else
{
// Error!
alert(responseObj.error);
}
}
You can't return from an event handler (which onreadystatechange is).
You have to do the work inside that event handler.
addphoto() does not return anything (or rather, returns inconsistently) ... the onreadystatechange event's handler is returning the value, but there is no caller that will receive that json string.
I'd highly suggest that you abstract these details away with something like jquery ... just follow the docs for suggested usage and this code will be much simpler
You're sending a GET style parameter list to a POST method.
You need to send that string in the body of your HTTP request.
var response = addphoto(); // <--This is undefined and not sure why
The addphoto() function never has a return statement in it, so it returns undefined. And the ajaxRequest is asynchrous and wont return immediately.

JS to jQuery to the fullest

I have this:
function createObject() {
var request_type;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
request_type = new ActiveXObject("Microsoft.XMLHTTP");
} else {
request_type = new XMLHttpRequest();
}
return request_type;
}
var http = createObject();
var nocache = 0;
function insert() {
document.getElementById('insert_response').innerHTML = "To Sek .. "
var bID= encodeURI(document.getElementById('bID').value);
var kommentar= encodeURI(document.getElementById('kommentar').value);
nocache = Math.random();
http.open('get', 'insert.php?bID='+bID+'&kommentar=' +kommentar+'&nocache = '+nocache);
http.onreadystatechange = insertReply;
http.send(null);
}
function insertReply() {
if(http.readyState == 4){
var response = http.responseText;
document.getElementById('insert_response').innerHTML = response;
if ($("#box[value=1]").length > 0) { window.parent.showMessage("Video Is OK"); }
}
}
And i want to "shorten" the code, and make it use jQuery to the fullest. eg, i have heard of serialize(); instead of using http.open etc.., but how should i use it in this case?
And do i really need all that in createobject() to make the http?
Untested, but I'm pretty sure this is what you need:
function onInsertComplete(data,textstatus){
$("#insert_response").html(data);
}
function doInsert(){
$("#insert_response").html("To Sek...");
var nocache = '0';
var data = { bID : $("#bID").val(), kommentar: $("#kommentar").val(), nocache: nocache };
$.get('insert.php', data, onInsertComplete);
if ($("#box[value=1]").length > 0) {
window.parent.showMessage("Video Is OK");
}
}
Most of this can be cleaned up with a call to the get method in jQuery.
First, it will abstract away the browser-specific details for you, so you don't have to check how get XMLHttpRequest.
You can then use jQuery to get elements through selectors. To select any element by id, you would use the following syntax:
$("#<id>")
The hashtag indicates that you want to select the elements with the id specified. From there you can use some of the general attribute functions to get the values inside of specific elements.
Finally, you can use Javascript's ability to generate closures to create and pass one as the callback to the get function, which is executed when the call completes. You would then use the same selectors general attribute functions to change the values on the client side when the call completes.
Something on this line?
http://api.jquery.com/load/
$('#result').load('ajax/test.html', function() {
alert('Load was performed.');
});

Categories