I have two PHP functions - one that builds a html form and another that handles it when it's submitted.
I want to add to the html a javascript onClick function that sends one of the form's fields to an external API (Google Maps) and saves the reply in a hidden field in the form so that the handling PHP function will get that data as well.
My question is - how do I make sure the handling PHP function only fires after the onClick function has finished?
Or maybe I can't and I have to use ajax?
You'll need 2 events to accomplish this.
the onClick event for your button that executes the google map request and saves the data into the local form
an onSubmit event for your form. You will use this event to see if the form is submittable. Basically, check to make sure that your google map request has been run and has completed before allowing the form to submit.
Example:
<script>
var googleMapsDone = false;
$('#gmap_button').click(function(event)
{
doGoogleMapThing(function()//callback from googlemaps
{
//save data to local form for processing by script once posted
googleMapsDone = true;
});
});
$('#form').submit(function(event)
{
//check to see if we did our google maps stuff, and that its done
if (false == googleMapsDone)
{
event.preventDefault();
return false;
}
});
</script>
With that code, any time the user is waiting for google maps and clicks submit, nothing will happen. They would have to wait on the response from GMaps, THEN click submit. This is okay for some things, but if you're trying to do background requests to GMaps that require no user input/interaction/feedback (maybe getting Long/Lat of their address when they submit a form), then you can modify the code a bit to post when you get the response. An example of that would be:
<script>
var googleMapsDone = false, submitWaiting = false;
$('#gmap_button').click(function(event)
{
doGoogleMapThing(function()//callback from googlemaps
{
//save data to local form for processing by script once posted
googleMapsDone = true;
/* check to see if submitWaiting is TRUE. If it is, automatically
post the form when we get the response.
*/
if (submitWaiting)
{
$('#form').submit();
}
});
});
$('#form').submit(function(event)
{
//check to see if we did our google maps stuff, and that its done
if (false == googleMapsDone)
{
event.preventDefault();
/* set our submitWaiting flag which we will use in our clalback
so when we get our google maps response, we post our form right
away
*/
submitWaiting = true;
/* You might want to display a modal or some other kind of notification
that the form post is 'working' or 'processing' so when the user
clicks it and doesn't see anything happening, they don't bail
or click it 800 times out of frustration
*/
return false;
}
});
</script>
edit: I realize my comment below on how this works are...hard to understand, so let me explain here, then show an alternative.
User fills out form
User clicks button to do stuff on google maps (example was written before I knew the scope/context of the GMaps request, so that's why it's done this way)
If user then clicks 'submit' before the GMap request is complete, we CANCEL the submit and set a flag submitWaiting
GMaps request returns, and executes our callback. Our callback knows how to look for submitWaiting and if it is set to true it submits the form
An alternative to this, instead of requiring user interaction for the GMaps request you could change the event to an onChange event for the input box of the address, or you can do it all via the submit button/event, like so:
<script>
$('#form').submit(function(event)
{
//lets look up our user's address!
doGoogleMapThing(function()//callback from googlemaps
{
//do stuff with your inputs, or whatever
$('#form').submit();
});
event.preventDefault();
return false;
});
</script>
edit note: the examples above assumes you're using jquery, and that your google map API request is done via javascript
If your google map api request is not using the google maps javascript library, this is STILL possible, just requires you to make a "proxy" script to the API via a php script on your local domain. (Browser restrictions). It'd be something like THIS:
<script>
function doGoogleMapThing(callback_when_done)
{
$.post("/path/to/proxy/script.php", { data: to, post: to_server }, function(response)
{
//check & parse response
callback_when_done(/* Data needed to populate form */);
});
}
</script>
note: both of these examples assume jquery usage. because...well..why wouldn't you.
Below is an implementation of your exact script. I changed it a bit to use jquery, because it makes things a bit less painful.
<script type=”text/javascript”
src=”http://maps.google.com/maps/api/js?sensor=false”></script>
<script type="text/javascript"
src="http://code.jquery.com/jquery-1.6.min.js"></script>
<script type=”text/javascript”>
function codeAddress(callback)
{
var address = $('#address').val();
geocoder.geocode( { 'address': address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
$('#latitude').val( results[0].geometry.location.latitude );
$('#longitude').val( results[0].geometry.location.longitude );
if (typeof callback != 'undefined') //call the callback.
{
callback(true);
}
}
});
/* Just in case google returns a bad response or doesn't return at all
we need to add a timeout that will call the callback after 10 seconds
just so we make sure our user doesn't hang.
*/
setTimeout(function(){
callback(false); //pass false indicating no/invalid response
}, 10000); //10000ms = 10s
}
/* We are using the reallySubmit variable as a flag here, to know when we finish
our call to google maps and that we want to really submit our form.
we have to do this because the form.submit() call fires the form's submit event
again, and we end up going into an infinite loop.
an alternative to this would be to bind your form processing to the form's submit
button's click event. that should also pick up any presses of the enter key, also.
the solution below also works.
*/
var reallySubmit = false;
$('#form').submit(function(event)
{
if (false == reallySubmit)
{
//lets look up our user's address!
codeAddress(function(success)//callback from googlemaps
{
reallySubmit = true;
$('#form').submit();
});
event.preventDefault();
return false;
}
});
</script>
This is fundamentally impossible - PHP runs on the server, JavaScript runs on the client. You will indeed need to use Ajax.
You can have a hidden IFRAME element where you load a php document as soon as your javascript ends. Simple, but effective (as long as your php document comes from the same URL).
AJAX is a must I am afraid. You need to redirect the user to a page with the script.
Once the server has run the PHP to generate the HTML, then sent it to the browser, there is no way to run it again, or indeed run anything from the server, without making a request to the server. That is the nature of a server side scripting language, of which PHP is.
Related
As you can see, this code takes the values from the forms, and put them in the database. Depending on the outcome, it returns either "False" or "Success!".
The only thing I can't understand, is how this jQuery function is displaying the outcome without having to reload the page. 'Info' is not attached to anything in the PHP file.
PHP source:
include_once('db.php');
$name = $_POST['name'];
$age = $_POST['age'];
$query = $conn->query("INSERT INTO user VALUES('$name','$age')");
if($query) {
echo 'Success!';
} else {
echo 'Fail';
}
Javascript source
$("#sub").click(function(){
$.post(
$("#myForm").attr("action"),
$("#myForm :input").serializeArray(),
function(info){
$("#result").html(info);
});
clearInput();
});
Read up a little on jQuery Ajax as well as .post().
Basically, an Ajax request means that the Javascript performs a new request to the server, without having to reload the page. Typically it loads a special page that only contains JSON or XML data, but it can be in whatever format you like. This is useful for updating the page content without modifying anything else on the page. Lots of websites use this, so learning it would be helpful for any future web development that you might do.
In the code, info is a parameter for the success callback of the XMLHttpRequest request to the server. It will be populated with the data returned from the background request to the PHP server.
The only thing I can't understand, is how this jQuery function is displaying the outcome without having to reload the page.
https://en.wikipedia.org/wiki/Ajax_(programming) & https://en.wikipedia.org/wiki/XMLHttpRequest
With Ajax, Web applications can send data to, and retrieve data from, a server asynchronously (in the background) without interfering with the display and behavior of the existing page. Data can be retrieved using the XMLHttpRequest object.
i am submitting a form using Ajax and storing the data in the database. It is storing the data in the database and without reloading the page it is giving alert box showing that that content has been added.
The same page is showing the content of the database, i need that part to refresh automatically without reloading the page so that it can also fetch the just added information.
<script type="text/javascript">
function GetXmlHttpObject()
{
if(window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
if(window.ActiveXobject)
{
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
function submitformwithajax()
{
var myAjaxPostrequest=new GetXmlHttpObject();
var coursename=document.getElementsByName('cvalue')[0].value;
var parameter="cvalue="+coursename;
myAjaxPostrequest.open("POST", "process/do_course.php", true);
myAjaxPostrequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
myAjaxPostrequest.send(parameter);
myAjaxPostrequest.onreadystatechange=function(){
if(myAjaxPostrequest.readyState==4){
if(myAjaxPostrequest.status==200){
if(myAjaxPostrequest.responseText=="true")
{
alert("Course Has Been Successfully Added To The Curiculum !");
var container = document.getElementById('c');
var refreshContent = container.innerHTML;
container.innerHTML = refreshContent;
}
}
else
document.getElementById("submitcourse").innerHTML="An error has occured making the request";
}
}
}
</script>
'c' is the ID of the div tag which has to be reloded.
Thanks
This seems a bit nonsense:
var refreshContent = container.innerHTML;
container.innerHTML = refreshContent;
That way you're not refreshing, the content is exactly the same.
I don't know exactly what do you mean by "DB content", assuming coursename is what you want to add to your DIV then you have to do something like:
container.innerHTML += '<p>'+ coursename +'</p>';
jQuery would benefit your work a lot, your current code via jQuery would look like
function submitformwithajax() {
var coursename = $("[name=cvalue]").val();
$.post("process/do_course.php", {cvalue: coursename}, function(response) {
if (response === "true")
{
alert("Course Has Been Successfully Added To The Curiculum !");
var container = $("#c");
// Not sure why you're setting the container to the container here
container.html(container.html());
}
else
$("#submitcourse").text("An error has occured making the request");
}, "text");
}
I don't know why you set the text of the container to the text in the container but that may be an issue you are having. If your server response returns the data that needs to be displayed in th area you can use jQuery (or if you really prefer, the DOM) to update the fields or elements (or add as needed) on the fly. If you need to refresh that section based off a GET request, then just make a GET request for the data in the success statement.
I would also recommend using JSON for the return type from the server instead of plain text. A {"success": true} will allow you to check if (response.success) instead of using string comparison there.
Also, as a final side note, in Javascript you should always prefer === over == as === verifies that value and type both match, the downside to this is that in Javascript 1 == "1" but 1 === "1" is not true.
EDIT
In response to your comment, should you not persue the jQuery route, you can still implement all of that which I have explained here however you'll have to manually parse the response:
var resposne = JSON.parse(myAjaxPostRequest.responseText);
From there you can still check if (response.success).
I, personally, recommend showing the students how to do it this long and complex way, and then teaching them how to do it with jQuery. Should any of them pursue a web development career then they will either use jQuery or something very similar in function to it and it's best they learn about these things early on instead of after they get hired. I also suggest JSON returns from the server because it's a more expressive way to return data, instead of just "true" (what is true?) you say {"success": true} so you can see the request was successful.
The easiest way to do this is going to be return the contents of the "c" element from the ajax call, and then replace the old contents of "c" with the content returned by the ajax call.
After seeing your code: You are not filling that table with AJAX. I can only give you this advice. Fill that table dynamically with Javascript.
Create function which will find div#c.
If div#c has some children, destroy them.
Create a new element table.
Fill that table with new rows.
This is how you can make a table dynamically with data from the server which is provided by Ajax. So after sending data from the form you can call this function and your table will be recreated.
I'm having a really difficult time understanding how this all works together. I've fiddled for a few days with this and have been unable to come up with any results. I'm trying to fill in a text field in a form, and when the form is submitted, I want to add the text to my sqlite db using ajax.
I understand that you need a $.get call in jquery which is triggered on the form's submit. That seems to work fine as I can trigger js alert boxes from there. However, when I pass the address of the php script which has lines to add to the sqlite db using PDO, nothing is added to the db. However, when I run this php script from using php cli, something will get added to the db.
I seem to be missing an essential step here. I would really appreciate it if someone could bridge this gap for me!
Edit:
As requested by Martin here's some code:
My php generates some list like this with a form in the middle:
<ul>
<li>hello</li>
<li id="formItem">
<form action="" method="post">
<input type=text name="content"/>
</form>
</li>
<li>world</li>
</ul>
Then my jquery code looks to add whatever is in the textbox right above it on the list does an ajax call. This is inside a $(document).ready(function(){.
$("form").submit(function() {
var inputText = $("input").val();
$.ajax({
type: "POST",
url: "add.php",
data: inputText,
success: function() {
$('#formItem').prev().after(
"<li>" + inputText + "</li>"
)}
});
});
My add.php file looks like this and it will insert something into my db if I execute the php script on the cli:
<?php
$base = new PDO('sqlite:todo.db');
$sql = $base->prepare("INSERT INTO ThisTable (content, priority) VALUES ('lolololol', 1);");
$sql->execute();
$base = null;
?>
Do not forget that HTTP is a stateless protocol. Each HTTP request you make to your webserver is treated the same. This stands for whether the HTTP request was made using AJAX or not.
What I'm trying to say is that AJAX is a client side implementation. All AJAX means is that you can interact with your webserver without having to reload your page. Implementing an AJAX request for the first time in JavaScript is often a brain bender, because the requirement of callbacks and the general asynchronous nature of the interaction makes it difficult to grasp.
On the server however, there should be nothing to worry about. An AJAX request is still an HTTP request, so whether you navigate to http://www.yourwebsite.com/ajax/interact.php?a=1&b=2 in your browser, or make a HTTP GET request using AJAX, your PHP script will still behave exactly the same. If you var_dump($_GET); in either situation, you will get an array whose a and b members equal 1 and 2 respectively.
If you can emulate the AJAX request in your browser successfully by navigating to the URL manually, that's the server work done.
Having established that, your JavaScript should look something like this:
$('#yourForm').bind('submit', function (event) {
jQuery.get('/ajax/interact.php', 'a=1&b=2', function (response) {
alert("AJAX request succeeded, response from the server was: " + response);
});
event.preventDefault();
});
Once you're confident using jQuery's AJAX methods, you might want to look at methods such as serialize() to help you out, and you can develop your jQuery code to something as follows:
$('form.ajax').live('submit', function (event) {
var self = $(this);
jQuery[(self.attr('method') || 'get').toLowerCase()](self.attr('action'), self.serialize(), function (response) {
alert("AJAX request succeeded, response from the server was: " + response);
});
event.preventDefault();
});
Hope this helps :)
Your submit function should return false;
So right now, I'm just using a basic form to check a password. I want it to check the password and basically remain on page.html so I can use JavaScript to alert incorrect password or something. I'm not really sure how to do that. It seems it would bring me to check.php. I'm not too sure on the whole process, any help appreciated! Thanks!
Page.html
<form action="check.php" method="post">
<input type="password" name="password" />
<input type="submit" value="Submit" />
</form>
check.php
<?php
$password = $_POST['password'];
if ( $password != "testing" ) {
die();
}
?>
PHP runs at the webserver which usually runs at a physically different machine (the server side) than where the webbrowser runs (the client side). The machines are usually connected by a network. HTTP is a network protocol. The webbrowser sends a HTTP request. The webserver retrieves a HTTP request whose URL indicates that it should be forwarded to PHP for further processing. PHP retrieves the HTTP request and does the processing and returns a HTTP response. Usually in flavor of a plain vanilla HTML page. The webserver sends HTTP response back to the webbrowser.
JavaScript runs at the webbrowser and knows nothing about PHP since it runs at the webserver. PHP in turn also knows nothing about JavaScript (although it can produce some JS code which is in turn to be sent to the webbrowser over HTTP). The only way to communicate between JS and PHP is HTTP. One of the ways to let JS fire a HTTP request and retrieve a HTTP response is using XMLHttpRequest. This is the core technique behind Ajax.
I see in your question history that you're already familiar with jQuery. It's a JS library with a lot of convenient functions to fire ajaxical requests. In this specific case you would like to use $.post. E.g.
$('#formId').submit(function() {
$.post('check.php', $(this).serialize(), function(valid) {
if (valid) {
alert('Valid!');
} else {
alert('Invalid!');
}
});
return false; // Important! This blocks form's default action.
});
With in check.php:
<?php
echo $_POST['password'] != "testing";
?>
This is however not unobtrusive. If the user has JS disabled, then all will fail. Your best bet is to check in PHP if an ajaxical request is been fired by jQuery or not and handle accordingly:
if ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
// Ajax.
} else {
// No ajax.
}
Alternatively you can let jQuery also reach a different URL or append an extra parameter.
Update: here is how the JavaScript would look like when not using jQuery:
document.getElementById('formId').onsubmit = function() {
var xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
if (xhr.responseText) {
alert('Valid!');
} else {
alert('Invalid!');
}
}
}
xhr.open('POST', 'check.php', true);
xhr.send(serialize(this));
return false; // Important! This blocks form's default action.
}
function serialize(form) {
var query = '';
for(var i = 0; i < form.elements.length; i++) {
var e = form.elements[i];
if (!e.disabled && e.name
&& ((e.type != 'checkbox' && e.type != 'radio') || e.checked)
&& (e.type != 'submit' || e == document.lastClicked))
{
if (query.length) query += '&';
query += e.name + '=' + encodeURIComponent(e.value);
}
}
return query;
}
document.onclick = function(e) {
e = e || event;
document.lastClicked = e.target || e.srcElement;
}
Bloated and verbose, yes ;)
You'll have to use ajax if you want to remain on the same page. I recommend using jquery and jquery's post function.
Basically you create a javascript function that gets called when the login button is clicked. The function will send a request to check.php. Check.php will output a status message (maybe 1 for succes, 0 for fail) that will be returned to the original script. From there you can output a message saying invalid password, or set a cookie if it was correct.
The simple solution to what you're trying to do (essentially AJAX) is:
Modify your php script to output something unique on success or failure.
Use JavaScript to submit the data to the php script, instead of the normal form POST.
Have the JavaScript alert the user if the password is invalid, or direct to an appropriate page if the password is valid.
Of course those are the broad strokes. In reality you'll need your php script to give one kind of response when an AJAX request (a request made by JavaScript) is made, and another response when the page is requested by a regular form POST - you do want it to work without JavaScript - right? You'll probably want the JavaScript to update the page contents instead of an alert box. You'll want your php script to set session variables so the next page they access knows they are logged in.
Broad strokes.
Reading the jQuery AJAX documentation may help.
When designing a web site, always add JavaScript after everything works fine without it. The reason for this is twofold. For one, some people browse without it turned on. The other reason is that JavaScript is always viewable and editable by the crackers out there.
This approach requires that you have a separate PHP file that validates the success of the password. Everything on the original page (HTML and JS) should only send the password and perhaps wait for the request. To keep things on the same page, you can use AJAX to send the input password and print out the response that it receives. jQuery makes AJAX easy if you don't want mind the overhead.
Using POST over HTTPS is better than using GET and HTTP. Of course, keep track of session variables and you might also want to limit the amount of time from when one first receives the form and when they actually submit it.
I have an issue going on here. I am using PHP to get values from a database in a php script. What I would ideally like to do is test to see if there is any data to display server side and if there is, pop up a javascript window with the values.
I have this working right now with javascript. Currently, the user can look up data and presses a submit button with an onclick event attached to it that opens the javascript window. I'm also using getemementbyID to grab the value posted in the parent window that gets passed to the child window. Basically, the php script is getting bypassed so I can't really do any checks of the data. Bottom line... I want to check to see if data is present BEFORE the window opens, if possible.
Any ideas?
your best option is to either make a request via ajax to check for data or make the request on the initial page load so you know already and can pass this to your click handler.
edit - This is an example using prototype (untested):
$('button').observe("click",clickCheck);
function clickCheck(){
new Ajax.Request("/remote/url", {
method: 'get',
onSuccess: function(transport) {
if (transport.responseText == 'results returned'){
// launch popup
}else{
// dont launch popup
}
}
});
}
I suggest using jQuery for making an ajax request. Something like:
$("#my-button").click(function(){
$.get('page_with_the_data.php', function(data, textStatus){
if (data) {
// Open the pop-up
// ..or just: alert(data)
} else {
// empty page
alert("No data returned");
}
})
})