I have an AJAX request that can have two possible outcomes:
The server responds with a message which I should place in a <div>
The server responds with an HTML page, in this case I need to substitute current page with a new one and change the address (the client knows the address before a request).
What would be the solution if I have the AJAX request that needs to handle both of these cases?
url = "http://example.com"
ajax.request(callback)
function callback(response) {
if (case2(response)) {
history.pushState({}, "New page", url);
document.innerHTML = response
} else {
updateDiv(response)
}
}
I'm interested in a correct way to implement the first branch, or if the server can somehow compose a headers that will make browser to handle a response as a usual HTTP response and update a page location and content, something like redirect with given content.
I understand that the server can return a link instead of a page, but in this case one additional stage will be needed on a client - redirect and then populating the new page on the server.
Quite frankly, I think that approach is basically broken by design. You shouldn't have to make that decision at that place. For example, the ajax response could only signal that a whole new page should be loaded and the new content then be generated on a second (non-ajax) request to a new URL.
In case you're forced to take the way you already go, and provided the response content is not very large, you could try Javascript-URIs. Basically, an URI in the form of javascript:"string" will load a new page which that string is the source code for. So, if response already is a string, just assigning javascript:response to window.location.href should suffice. Maybe you have to do some escaping beforehand. And I don't know, how cross-browser-compatible this approach is.
load
is also possible.
A variant of this is building the URL not with the variable name, but with the actual string data. Like
function source2url(src) {
// make valid javascript string from source text
var esc1 = src
.replace(/\\/g, '\\\\')
.replace(/\'/g, '\\\'')
.replace(/\x0A/g, '\\x0A')
.replace(/\x0D/g, '\\x0D');
// make valid url from that
return "javascript:'" + encodeURIComponent(esc1) + "'";
}
window.location.href = source2url(response);
This will, of course, generate pretty large URIs. And you'll always have the Javascript-URI in the address bar.
UPDATE
A similar approach is to use base64 encoding in a data URI. The Wikipedia entry explains how it works, including a javascript example. However, you'd have to base64-encode the content somehow. (Note: You can use data URIs with or without the base64 encoding. You have to see what gives you shorter URIs for your specific content.)
I had a similar issue once. A full error page was returned instead of a simple HTML snippet. We eventually fixed this by changing the logic, but here is one of the solutions I found:
document.open();
document.write(responseText);
document.close();
The reason we abandoned this is that on IE there were some problems. I didn't loose any time to investigate why, but it threw an 'Access denied' exception when attempting to write the string. I think there were some <meta> tags that confused IE, or maybe conditional comments, I'm not sure. (It worked when I used some simple pages...)
Bottom line is: you shouldn't have to do this, but if there is nothing else you can do (like returning an url string) the code above might work.
It's really easy if the response is valid XML.
var new_doc = (new DOMParser).parseFromString(response, "application/xml");
document.replaceChild(document.adoptNode(new_doc.doctype), document.doctype);
document.replaceChild(document.adoptNode(new_doc.documentElement), document.documentElement);
Since the request is for an updated answer, here's my solution using HTML5's History API with jQuery. It should run easily by combining the PHP and HTML parts into one file.
My solution allows for AJAX to return the following:
A message through AJAX, which updates a <div> container.
A URL, which causes the browser to redirect to the URL
A complete HTML page, which calls the History API's history.pushState() to add the current URL to the browser's history and replaces the entire HTML on the page with the HTML returned from AJAX.
PHP
This is just a sample of what the PHP script will need to return when it is invoked via AJAX. It shows how to encode flags to determine whether the AJAX call should update the container or load a new page, and how to return its result via JSON through json_encode. For completeness, I named this script test.php.
<?php
// Random messages to return
$messages = array(
'Stack Overflow',
'Error Message',
'Testing'
);
// If the page was requested via AJAX
if( isset( $_POST['ajax']))
{
$response = array(
'redirect' => // Flag to redirect
( rand() % 2 == 0) ? true : false,
'load_html' => // Flag to load HTML or do URL redirect
( rand() % 2 == 0) ? true : false,
'html' => // Returned HTML
'<html><head><title>AJAX Loaded Title</title></head><body>It works!</body></html>',
'title' => 'History API previous title',
'message' => // Random message
$messages[ (rand() % count( $messages)) ]
);
echo json_encode( $response);
exit;
}
JS
Since I am using jQuery, lets start with that. The following submits an AJAX POST to the server, to the above PHP script at URL test.php. Note that it also sets the POST parameter ajax to be true, enabling the PHP script to detect that it received an AJAX request. The dataType field tells jQuery that the server's response will be in JSON, and that it should decode that JSON to a JSON object in the response callback. Finally, the success callback, which is fired when the AJAX response is successfully received, determines what to do based on the flags sent from the server.
$.ajax({
type: 'POST',
url: "/test.php",
data: {ajax : true},
dataType: "json",
success: function( json) {
if( json.redirect) {
if( json.load_html) {
// If the History API is available
if( !(typeof history.pushState === 'undefined')) {
history.pushState(
{ url: redirect_url, title: document.title},
document.title, // Can also use json.title to set previous page title on server
redirect_url
);
}
// Output the HTML
document.open();
document.write( json.html);
document.close();
}
else {
window.location = redirect_url;
}
}
else {
$('#message').html( json.message);
}
},
});
HTML
Here is the complete HTML source of my tested file. I tested it in FF4 - FF8. Note that jQuery provides the ready method to prevent the JS from executing until the DOM is loaded. I've also used Google's hosting of jQuery, so you do not need to upload a copy of jQuery to your server to test this.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js" type="text/javascript"></script>
<title>Default Page</title>
<script type="text/javascript"">
$( document).ready( function() {
$('#ajax_link').click( function() {
var redirect_url = "/test.php";
$.ajax({
type: 'POST',
url: "/test.php",
data: {ajax : true},
dataType: "json",
success: function( json) {
if( json.redirect) {
if( json.load_html) {
// If the History API is available
if( !(typeof history.pushState === 'undefined')) {
history.pushState(
{ url: redirect_url, title: document.title},
document.title, // Can also use json.title to set previous page title on server
redirect_url
);
}
document.open();
document.write( json.html);
document.close();
}
else {
window.location = redirect_url;
}
}
else {
$('#message').html( json.message);
}
},
});
})
});
</script>
</head>
<body>
<div id="message">The default contents of the message</div>
<a id="ajax_link" href="#">Fire AJAX</a>
</body>
</html>
Give an id to body <body id="page"> and your other div will be <div id="message"></div> now your ajax will look like
$.ajax({
url:'myAjax.php',
data:{datakey:datavalue},
dataType:"JSON",
success: function (response) {
if(response.message=="your message")
{
$('#message').html(response.content);
}
else
{
$('#page').html(response.content);
}
}
});
as T-Bull say... the whole process is wrong here....
you simply are over-complicating things and you know that infact:
I understand that the server can return a link instead of a page, but
in this case one additional stage will be needed on a client -
redirect and then populating the new page on the server.
stop complicating and start do it well...
Client open the page first time, so, track it $_SESSION['tmp_client_id'] = 'client_'.session_id(); obviously is better if the client is already subscribed, anyway, put stuff in temp table OR into another session var etc...
Client fill in the form;
Client submit the form;
Make the AJAX request;
Store $_POST variable inside tmp_client_tbl with it's unique tmp_client_id OR just $_SESSION['client_'.session_id()] = json_encode($_POST);
Outcome #1 ? display message in a </div>
Outcome #2 ? refresh page and check if( isset($_SESSION['client_'.session_id()])) { if so let's display the form again with filled fields: } else { display empty form;
SELECT * FROM tmp_client_tbl WHERE tmp_client_id = '{$_SESSION['tmp_client_id']}' OR json_decode($_SESSION['client_'.session_id()]);
$form_data = $mysql_rows; OR $json_array;
foreach($form_data as $name => $value) { echo "<input name='$name' value='$value' />" } in a ninja way that assume you have such kind of form builder array where $form = array('text' => array('name','lastname'), 'select' => array('countries'), ... ), OR simply by <input name='lastname' value='{$lastname}' /> where the fields values are pre-polutated with empty vars;
time elapsed, error occurred, browser closed? session_destroy(); or unset($_SESSION['client_'.session_id()]);
Related
I have an AJAX call on a page for administrators to e-sign. When a button (adminEsign_btn) is pressed, this jQuery is called:
$("#adminEsign_btn").click(function(e){//admin esign submitted
e.preventDefault();
//validate esign
var valid = true;
if($.trim($('#adminSignature').val()).length < 3){
valid = false;
}
//action
if(valid === false){
$('#adminEsignError').html('<span class="error">You must agree to the statement and sign.</span>');
}
else{//validation passed, submit data
var schoolID = <?php echo $schoolProfile['schoolID']; ?>;
var signature = $('#adminSignature').val();
$('#adminEsignLoader').css({'display':'inline-block'});
$('#submitForm').attr("disabled","disabled");
$('#submitForm').val("Updating...");
$.ajax({
type: "POST",
url: 'bin/schoolProfile.saveEsign.php',
data: { schoolID:schoolID, signature:signature}
}).done(function(response) {
//$('#debug').html(response);
//alert(response);
if(response.indexOf('success') >= 0){//if 'success' exists in the response text
$('#submitForm').removeAttr("disabled");
$('#submitForm').val("Update School Profile");
$('#adminEsignLoader').hide();
//disable the e-sign
$('#adminAgree').attr("disabled","disabled");
$('#adminSignature').attr("readonly","readonly");
$('#adminEsign_btn').attr("disabled","disabled");
}
});
$('#adminEsignError').html('');
}
});
I didn't write the original code, so I don't know exactly what is going on in the if statement:
if(response.indexOf('success') >= 0){//if 'success' exists in the response text
But the call isn't expecting a return other than an echo of success. The following php page (schoolProfile.saveEsign.php) is what is called:
<?php
include($_SERVER['DOCUMENT_ROOT'] . '/includes/init.php');
$Page->clearance('Admin');
$Main->saveSchoolAdminEsign($_POST['schoolID'], $_POST['signature']);
echo 'success';
?>
NOTE: $Main is initialized in init.php as well as is $Page.
This code worked up until today when I tested it again. It is supposed to post the data to schoolProfile.saveEsign.php and run a function to save the schoolID and signature to a mysql database.
I've used the javascript alert() function to post the results of the "response" and it always shows the code for the entire current page (schoolProfile.edit.php).
I've run the code in Chrome and it shows that the data is being posted. It has status 302 - Found. The size is 485 B (sounds reasonable for 2 variables with only text), but underneath size in Chrome Network Debugger is content and content is 0 B - empty. I don't know if this means the data isn't being sent or what.
I've tested setting a Session variable to see if the session gets saved and I haven't been able to change it's value so that may be a sign that the data isn't actually being pushed across. But when I view the header for the page being called, it shows the 2 variables - schoolID and signature - with values.
I'm new to Chrome Network Debugger so if there are any other things I can check or if anyone has any suggestions any help would be appreciated.
EDIT: I've also tested the success and error functions inside the ajax call and success is always called. Once again it only returns the entire code for the current page (schoolProfile.edit.php).
I found the issue. In my include($_SERVER['DOCUMENT_ROOT'] . '/includes/init.php'); The init.php document redirects the user to schoolProfile.edit.php if they haven't completed filling out the school profile and it also makes sure that they aren't already at that url using PHP's $_SERVER['REQUEST_URI'].
The issue was that when trying to call schoolProfile.saveEsign.php, this url was not in the "list" of okay'd URL's so the AJAX request was always being redirected to schoolProfile.edit.php - AKA the current page. That is why I would always see the current page code when I would do an alert.
For future reference for myself. Original code:
if($_SERVER['REQUEST_URI'] != '/settings/schoolProfile.edit?f='.$Main->encrypt("INCOMPLETE")) {
header("Location:/settings/schoolProfile.edit?f=".$Main->encrypt("INCOMPLETE"));
exit();
}
Fixed Code:
if($_SERVER['REQUEST_URI'] != '/settings/schoolProfile.edit?f='.$Main->encrypt("INCOMPLETE")
&& $_SERVER['REQUEST_URI'] != '/settings/bin/schoolProfile.saveEsign'
&& $_SERVER['REQUEST_URI'] != '/settings/bin/schoolProfile.saveEsign.php') {
header("Location:/settings/schoolProfile.edit?f=".$Main->encrypt("INCOMPLETE"));
exit();
}
I am new to UI technologies like JQuery, AJAX, PHP etc.
I am building a Google Instant like feature. My search engine infrastructure at backend is pretty fast and returns results even for Tera Bytes of data in super quick time.
I have a PHP function in a class that returns me an array:
solrsearch.php
class SolrSearch{
...
...
public function find( $q ){
...
...
return $found;
}
}
$found is a key value pair something like documentID=>Data
When I dry run it i.e. on a console (not on a browser) with a test string and not using $q input variable everything seems to be fine and I print $found and it prints the values.
Now my html file with embedded javascript looks like this, so basically here I am capturing each key press on the textbox and doing a get request
testjson.html
<html>
...
<body>
<div align="center"><p><font size = 7 face="Verdana"> Search: <input type="text" id="term" size = 60 style="font-size:22pt"/>
<table id="results">
</table>
<script>
$(document).ready( function() {
$('#term').keyup( function() {
$.get('search_json.php?q='+escape($('#term').val()), function(data) {
html = '<table id="results">';
$.each( data, function( index, val ) {
html += '<tr><td class="document"><b>'+index.key+'</b> ';
html += 'Dated '+val.value+'</td></tr>';
} );
html += '</html>';
$('#results').replaceWith( html );
} );
} );
} );
</script>
...
...
</html>
And then finally here is my
search_json.php
$s = new SolrSearch();
print json_encode( $s->find( $_REQUEST['q'] ) );
Even the json encoded string is working perfectly fine and prints the json though on a console (not on browser)
Here is the problem I am facing: On the browser when I run testjson.html which just has a textBox and I input some strings so I dont get any results displayed back on the browser. When I debug it using Fiddler (HTTP Debugging Proxy) I can see AJAX get requests in that.
Any help would be appreciated. If there is anything else I can add to the question which is required I will be more than happy to do that.
EDIT:
I further debugged and printed $q in the find function in solrsearch.php and it did not print the value that means the value is not getting passed from search_json.php however I can see the GET requests on Fiddler.
I guess that this line:
html += '</html>';
should be
html += '</table>';
By the way, instead of using $('#results').replaceWith( html ); try with $('#results').html( html );
Edited:
Instead of $.get(), try with $.ajax():
$.ajax({
url: 'search_json.php',
type: 'POST',
data: { q: escape($('#term').val() },
}).done(function(resp) {
//Your html code with response options
});
If your front end uses HTML you definitely have to take a look on AJAX-SOLR
AJAX Solr is a JavaScript library for creating user interfaces to Apache Solr
Play with the demo site
Follow the tutorial
Browse the wiki
Read the documentation
Explore the code
I'm trying to pass a collection of parameters to a PHP page to be processed, from a JavaScript function:
entries: "test data from JavaScript"
In my PHP page I'm trying to grab the value that was posted back to the page:
$_POST['entries']
but this keeps return 'emtpy', regardless of what I try to push through. I'm new to PHP so this might be a stupid thing to fix.
This is invoked from a button click like such:
$("#submitButton").click(function(){});
Should the be wrapped in a form, as I don't see the need for this?
Update [full code]
var proxy = new ServiceProxy("submit.php");
$("#submit").click(function () {
var store = $("#store_name").val();
var contact = $("#contact_person").val();
proxy.invoke("", { entries: store }, success, error, false);
return false;
});
Note on the ServiceProxy. This proxy class wraps the default $.ajax {...} into a neat little proxy class, thanks to Rick Strahl over at west-wind. I've used this proxy class successfully in numerous single HTML and ASP.Net solutions in the past, so I don't it's the proxy service that's causing the issue.
Looks like your using jQuery, so why not use their post function?
$.post("/file/location/post.php", { Name: "Hello", Email: "email#address.com" } );
Then in your php code you can use:
$_POST['Name'] and $_POST['Email']
Hope this helps.
Sorry, just seen your updated code - this should work:
$("#submit").click(function () {
var store = $("#store_name").val();
var contact = $("#contact_person").val();
$.post("submit.php", { entries: store } );
return false; });
Finally got my domain checker working. Now the question is I have a form (search-domains) when user types and submits at the moment it passes the query to process.php and that out puts:
echo "$Domain is/isn't available"
What I want is this to return on my results page (the results page also has a search form on it so if someone searches there it would display on same page). At the moment when user clicks it passes http://example.com/process.php?domain=domain.com(etc...).
What i think i need is Ajax to pull this url before it goes to process.php then ajax runs the query process sends result back to ajax an it outputs on the results page. Also I have another php script which displays the domain with different tlds and displays id they are available or not. So i also need ajax to run this and display aswell.
I am very new to ajax but looking for tutorials but most of them are for displaying success messages after contact forms and the like. If someone could point me in the right direction id much appreciate it.
EDIT
This is what i have but itsd still re-directing me to process.php
HTML
<form method="get" id="form">
<input type="text" class="searchdomains" onclick="if (this.value =='Domain Name Search...'){this.value=''}" value="Domain Name Search..." name="domain" id="search-domain-input">
<input type="image" src="<?php bloginfo('template_url'); ?>/inc/img/btn_up_search.png" class="search" name="Search" id="Submit">
</form>
JQuery
$.ajax(
{
type: 'GET',
url : "http://example.com/process.php?domain=",
// here you pass js object in convention: { 'query_string' : 'its value' }
data : { 'domain' : $('#search-domain-input').val() },
success: function (data) {
$("#results").html(data);
}
}
);
PHP
if(isset($avail)){
echo '<p>'.$avail.' is available to be registered</p>'
} else {
echo '<p>'.$avail.' is taken register with us for price</p>'
}
Thanks
Joe
in jquery (http://jquery.com/) you can make ajax requests by using the function :
$.ajax(
{
url : "url to fetch",
success: function (data) {
// data is variable that is returned from server as HTML by default, or you can use JSON format
$("#content").html(data);
}
}
);
If you dont want to use jquery javascript library, you need to create xmlhttprequest object and make helper functions for it, which i do not recommend, since jquery can be used for more stuff than just ajax calls.
EDIT :
#comment
simply create process.php where you will accept "domain" as query string - which will check if the domain exists, if not it should echo <p>'$result.'is/isn't available</p>, than in $.ajax({...}); pass that url and "data" will be available to you.
To pass GET params with $.ajax() you can use the following setting:
$.ajax(
{
type: 'GET',
url : "url to fetch",
// here you pass js object in convention: { 'query_string' : 'its value' }
data : { 'domain' : $('#domain_name_input_field').val() },
success: function (data) {
// data is variable that is returned from server as HTML by default, or you can use JSON format
$("#content").html(data);
}
}
);
I have this little code (part of my registration code) :
<?php
if (#$_POST['Submit'] == 'Register'){
if (strcmp(md5($_POST['user_code']),$_SESSION['ckey']))
{
die("Invalid code entered. Please enter the correct code as shown in the Image");
}
}
?>
<form name="form1" id="signupForm" method="post" action="register.php" style="padding:5px;">
<div class="reg_left">Security code:</div>
<div class="reg_right"><input name="user_code" type="text" size="10"> <img src="pngimg.php" align="middle" width="100" height="40"></div>
<div><input type="submit" name="Submit" class="submit" value="<?php echo $gomb_reg;?>"></div>
</form>
Unfortunately this is check if code is valid after post the form data. I would like to check before posting.
So I think I must use jQuery validation plugin (btw I use jQuery to validate the other fields like email, user, password). But as I'm not an expert in jQuery, I need help to write that php code above in jQuery.
Thank you.
I believe the basic jist would be:
Hook a function to the submit element
That JS function sends the user_code value to PHP script
The PHP script checks the value and and outputs (returns) a bool (or json)
The JS function allows the post if a good value is returned
(Note: Since the jQuery AJAX function do not stop the execution of the script, you'll have to stop the form from submitting, then submit the form in the AJAX callback.)
Look at the jQuery docs for
.post
or
.getJSON, use those function to sent the 'user_code' to be checked.
You can keep most of your php code the same, but you'll want to check for the request header type.
I'm pretty sure jQuery sends the X-Requested-With : XMLHttpRequest but I'm not entirely sure and its late, so to somewhat modify your php script it would look something like this
if (#$_POST['submit'] == 'Register') {
if (strcmp(md5($_POST['user_code']),$_SESSION['ckey']))
{
// check if the request was from an ajax call
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){
//if it is an ajax request we need to send back a json encoded array
$response = array('success' => 'true', 'message' => 'Invalid code';
// now we encode the array and echo it back
echo json_encode($response);
// exit the script for safety
exit();
} else {
// if the request wasn't ajax the respond business as usual
die("Invalid code entered. Please enter the correct code as shown in the Image");
}
}
}
As for the jQuery code it would probably look something like this:
$(document).ready(function(){
// this creates an event handler on the form submit
$('#signUpForm').submit(function(){
// you'll need to give your user_code input an id of user_code
var user_code = $('#user_code').val();
// I like to use the jQuery $.ajax method since it gives you more controll
$.ajax({
// send a post request
type : 'POST',
// the url you'll be sending the request too
url: 'register.php',
// the type of data you're expecting back
// i prefer json since its easier to work with for me
dataType : 'json',
// the data you want to send which would be your user_code data
// send this in a name/value pair
data : 'user_code=' + user_code + '&submit=Register',
// the success function is called when the ajax call has been
// completed, not whether the user_code matches the $_SESSION['ckey']
// the data variable will contain your json data
success : function(data, textStatus){
// since we json encoded the php array it will
// look something like this
//{ success : 'true', message : 'incorrect code'}
if(data.success == 'true'){
// what you plan on doing if the code is correct
alert(data.message);
} else {
// what you do if the code is incorrect
alert(data.message);
}
}
});
// stop the form from submitting
return false;
});
});
I think that should just about do it. the $.ajax method has a few other call back functions such as onError, complete and similar messages that are worth looking into here. The $.ajax method is a little daunting at first, but after using it a few times, I now prefer it over the other ajax methods they have ($.load,$.get, $.getJSON, or $.post)