I am trying to do a simple query for info from a database through an html page. I've got all the backend stuff working fine, but I'm having trouble on the client side. I currently have a form where the user submits their ID# to get some info on their case.
But with my current setup, it returns an entirely new page and I just want to read in a text string, process it and update the content on the current html page without opening up a new one and replacing the old one. How can this be done?
Here's my code so far:
function showInfo() { } // I want to make the request here instead
<form name="register" action="http://localhost:8080/testapp/authenticate" method="get">
<p><label for="badge">ID #:</label>
<input id="badge" name="ID" type="text" pattern="[0-9]{6}"
placeholder="xxxxxx">
<button id="checkButton" type="submit" onClick="showInfo()">Enter</button>
</p>
</form>
My guess is that you're actually submitting the form, which is posting back to the server. What you will want to do is cancel the form from submitting and submit it using AJAX (which is what I believe you want?).
To do so, your showInfo() function should do one of these three things (I can never remember which one)
return false;
cancel the event, something like e.preventDefault()
stop the propagation, something like e.stopPropagation()
Once you've successfully prevented the form from hard-submitting, you can then do what you'd like by submitting your data via AJAX and manipulating your response however you'd like.
1st - Jason is absolutely right that what you want for this situation is AJAX, below is an example in motion.
2nd - You should be using a Javascript library such as jQuery, which might look intimidating (as it did for me at first), but it is really easy and completely worth the small effort to get it going.
3rd - With jQuery, your application tidbits should look something like this, using the example you provided:
HTML -
<p>
<label for="badge">ID #:</label>
<input id="badge" name="ID" type="text" pattern="[0-9]{6}"
placeholder="xxxxxx">
// Please note that I removed the onClick section from the line below.
<button id="checkButton" type="button">Enter</button>
</p>
JQUERY -
// The default function you described to take information and display it.
function showInfo(data) {
// Insert your function here, probably using JSON as the Content Type
}
// This is the key AJAX function, using jQuery, that takes your info and gets a
// response from the server side, the sends it to the function above in order for it
// to be displayed on the page.
function processIdInfoCheck() {
$.ajax({
type: 'post',
url: '/http://localhost:8080/testapp/authenticate',
data: {
'id': $('#badge').val();
},
dataType: 'json',
success: displayIdInfoReturn,
error: function () {
alert("There was an error processing your request, please try again");
}
});
}
// When the page loads, the code below will trigger, and bind your button click
// with the action you want, namely triggering the AJAX function above
(function ($) {
$('#checkButton').bind('click', processIdInfoCheck);
})(jQuery);
Just remember, AJAX takes some effort to get the desired effect, but when you look at page load times, request numbers, etc... It is totally worth it. Please let me know if this was helpful and if you need any specifics.
Related
UPDATE 2
Looks like I am having trouble accessing document elements (including form) from within the callback (onSubmit function) registered with invisible reCAPTCHA. Updated code below.
In browser console, I get the error message below when JS reaches "document.getElementById("info_form").submit()" call in JS:
10:26:47.556 TypeError: document.getElementById(...).submit is not a function 1 selector.php:13:9
The image CAPTCHA when it comes up is solved correctly and alert dialog displays it correctly. But, I can't submit form explicitly within callback to my backend. Please note that as per Google instructions in link below in message, I need to call preventDefault() as specified below. If I delete it, the reCAPTCHA flow is interrupted.
UPDATE
So, it looks like the "event.preventDefault();" is the key line here. If I have it, the reCAPTCHA (i.e. the image selection grid) gets displayed and I can interact with the widget. However, the POST parameters don't get sent. If I comment out the preventDefault(), the POST goes through correctly - BUT the reCAPTCHA flow does not start. This means, that while the other POST params get sent, the important reCAPTCHA data does not get sent since that flow is not executed at all.
So, how do I go about this? Looks like I need to call "preventDefault" before "grecaptcha.execute()" to enable reCAPTCHA flow (as Google also shows in their snippet). But doing so, messes up the POST data somehow. I am also explicitly calling "document.getElementById("info_form").submit()", but not helping. Any ideas would be great. Thx!
Also, Google's invisible reCAPTCHA is a relatively new construct and still in beta. Could be some core issues re: that. What we are all regularly used to is their regular reCAPTCHA where we see the "I am not a robot" checkbox. Invisible reCAPTCHA does not have that first line UI widget - and only steps you up to image CAPTCHA if nedeeded.
ORIGINAL POST
I need your help in figuring out why my 1) button onclick = validate function and 2) my form POST cannot co-exist.
Specifically, if I comment out the "document.getElementById('submit').onclick = validate" below, my form POST goes through successfully. However, if I register the validate function, the form POST does not work. Google tells me (Google link provided below) that if I want to validate input before performing invisible reCAPTCHA, I need to call "grecaptcha.execute();" during button onclick event.
So, my general question is, after executing (or within) the button onclick = validate function, how I can make sure that the info_form is submitted normally via POST so I can see it in my backend PHP? Not necessarily that the POST "itself" isn't working - but the parameters that would get submitted via POST may be getting messed up somehow - just a thought.
Source code and further code specific comments below. Also, please note that I already have the other two forms of reCAPTCHA binding working in the Google link. The "grecaptcha.execute()" variant is the only one I am having trouble with.
<?php
include 'msg_recaptcha.php'; // use the debugMessage output
?>
<html>
<head>
<script>
function onSubmit(callbackInput)
{
var message = "g-recaptcha-response token successfully received.\n";
message += "Token = ";
message += callbackInput;
alert(message);
document.getElementById("info_form").submit();
}
function validate(event) {
event.preventDefault();
if (!document.getElementById('firstname').value) {
alert("Please enter name");
} else {
grecaptcha.execute();
}
}
</script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<form id='info_form' action="invisible_recaptcha_form.php" method="post">
First name: <input id="firstname" name="firstname">
Second name: <input id="secondname" name="secondname">
<div id='recaptcha' class="g-recaptcha"
data-sitekey="<Site key (public) from Google>"
data-callback="onSubmit"
data-size="invisible">
</div>
<button id='submit'>submit</button>
If I comment out the "onclick = validate" line below, my server PHP will receive the form details via POST - including first name. However, I can't comment it out in final solution, since I need to run the recaptcha "execute" function in validate() function as per Google's instructions https://developers.google.com/recaptcha/docs/invisible. The problem with Google's instructions is that, they don't show how to do the POST along with their grecaptcha.execute() requirements - and I would need both to ensure the payload from the reCAPTCHA operation gets sent in the POST to my backend, so that my backend can talk to Google server's to validate the reCAPTCHA payload.
<script>
document.getElementById('submit').onclick = validate;
</script>
<div id="debugmessage"><?=$debugMessage?> </div>
Thanks everyone!
You have to change your onSubmit JS function to execute form submit after recaptcha validation.
function onSubmit(token) {
alert('thanks ' + document.getElementById('firstname').value);
document.getElementById("info_form").submit();
}
UPDATE
When you call event.preventDefault() at your onsubmit eventHandler, you say to the browser to not execute form submit by default and that YOU will do it when you need.
I can see you are accepting parameter into validate function
function validate(event) {
event.preventDefault();
if (!document.getElementById('firstname').value) {
alert("Please enter name");
} else {
grecaptcha.execute();
}
but you are not passing any parameter to validate
document.getElementById('submit').onclick = validate
that is the reason its giving you error.
modify your validate function to take no argument. I'm thinking why you need to take argument into validate function when you are not using it anywhere?
I have an HTML form which submits to another page via POST. Nothing special about it, except that after the form validates I try to hide and/or disable the submit button so that it cannot be double-submit, while also telling the user the next page might take a while to load.
The relevant code is:
jQuery(document).ready(function () {
jQuery("form#form").submit(function() {
var result = validate();
jQuery(this).find('input[type=submit]').prop('disabled', true);
jQuery("#submit-button-wrapper").html(jQuery("#submit-button-wrapper").html()+
"<br/><br/><span style='margin: 25px; padding: 5px; background: yellow; "+
"width: 100%; font-weight: bold;'>Loading... this may take a few minutes! "+
"<i class='fa fa-spinner fa-spin' style='color: blue;'></i></span>");
return result;
});
});
function validate() {
return true; // Does stuff, then returns a simple true or false
}
By request, here is the (very simple) button wrapper HTML:
<div class="col-sm-12" id="submit-button-wrapper">
<input type="submit" value="One More Step" />
</div>
When the I remove the which changes the button wrapper's HTML, the form submits just as you'd expect. When I have that line in, however, it still calls the next page and executes that code, without the displayed page ever changing.
I have tested in both Chrome and Firefox, so I know it's not a browser issue, but this is really weird behavior. What am I doing wrong?
My goal: (1) validate the user's input, (2) give the user a clue that the page is going to take a while to load and (3) display the output from the action="complete.php" page once the PHP on it has run.
Maybe you can achieve this with $ajax and show results on the same page.
Send POST data to /some.php
After sending data, give feedback to user changing button behavior
When the task is complete, receive data and verify success or error and act accordingly. If OK, change button text to "complete!" or something else, and append response data to some div. If NOT OK, give feedback as well.
In code:
$("form#form").submit(function(e) {
e.preventDefault();
$.ajax({
method: "POST",
url: "some.php",
data: $(this).serialize(),
dataType : 'json',
timeout: 2000,
cache: false,
afterSend: function() {
/*change button behavior here*/
},
success: function(result) {
if (result === "ok"){
/*maybe append data to div and update button text to complete*/
} else {
/*if result not ok, send feedback*/
}
}
});
});
BTW: ajax documentation http://api.jquery.com/jquery.ajax/
When you return true (if validated) then the form is submitted. However, you're changing the DOM / submit button wrapper and essentially removing the submit button, right? Likely that is what is causing your problem. Leave the submit button wrapper alone. If you want to display a message display it as an overlay or hide the submit button wrapper and show the message wrapper in its place, don't remove the submit button altogether.
I know that you're just showing a slight jQuery and HTML portion of the script, but that isn't quite enough to figure out your problem. Since not all of it seems to be there because you mention action="complete.php" but I don't see that within your jQuery or HTML sample of code. So I have a few questions of my own.
Is the form small or large. If it's a small form then why aren't you displaying the output on the submit page? You could do that with what you currently have but a single PHP or ASP page could save you on amount of pages to make and what not. As a side note, depending on size of the form, you can do the validation on same page or continue to use action="" for it if large.
Do you have need for a database file or are you saving to one? If you do/are, you could write to the DB file, have the submit open the next page and view what was saved in the database on that new page. Again, you can probably use a single PHP or ASP page.
This last part sounds more valid for your purpose. You could use location.href="http://www.domain.com/home.html";
or use window.location("http://www.domain.com/home.html"); to redirect to the new page.
On another matter about some of the comments others made.
You don't exactly need the + unless you're dividing each of those out into their own separate lines when you could just use one line to do that. That's probably what confused Rajesh about the '. In fact I'm not sure why you yourself mentioned the + when referring to Rajesh comment about "concat string" and "append" ,because those two have nothing to do with the +. In fact to take a guess, he might have been referring to your jQuery("#submit-button-wrapper").html(jQuery("#submit-button-wrapper").html() which kinda looks like a concat string.
Speaking about append, not really needed unless for example you're doing something like giving the user the option to add rows to a form question.
I've been looking over an older post trying to work out a solution for showing the confirmation PHP in a lightbox.
As my knowledge on javascript and ajax is close to zero - well, it IS zero - I'm hoping someone might elaborate.
<form method="post" action="contact.php">
Is the basic form method. Would I be able to use something like Tinybox2 and simply add
TINY.box.show({url:'submit.php',post:'id=16',width:200,height:100,opacity:20,topsplit:3})
to the action, rather than a php?
Cheers, Trin
If you want to use TinyBox, you need to serialize your form before you post it. One of the fastest and nonpainful way to do this to use jQuery (Just add reference if you haven't done this.)
TINY.box.show({url: $("form").prop("action"), post:$('form').serialize(),width:200,height:100,opacity:20,topsplit:3})
First one grabs the "action" url from your form, and the second method makes your form to be posted with TinyBox.
This code should display a tinybox when user submits the form:
$("form").submit(function( event ) {
event.preventDefault();
TINY.box.show({
url: $("form").prop("action"),
post: $('form').serialize(),
width:200,
height:100,
opacity:20,
topsplit:3
});
return;
});
Just put this inside
<script type="text/javascript">
$(document).ready(function () {
// Here.
}
</script>
block.
I need to reload a page when clicking in a submit button. What the new page should show depends on the checkboxes selected previously to the reloading.
My problem is that, when I click "submit", $("button").click(function()... takes the correct values but $(document).ready(function ()... takes always the values true (which are selected as default).
How can I save those values before the reloading so that I can use them on $(document).ready(function ()...? Can I send them as data parameter
$(document).ready(function() {
var selectedCheckboxes = new Array();
$.ajax({
url: 'getNewForm.php?accion=value1',
data: 'selectedCheckboxes',
dataType: 'json',
error: function() {
alert("ERROR");
},
success: function(res) {
//Do something
}
}
});
$("button").click(function() {
var selectedCheckboxes = new Array();
selectedCheckboxes[0] = document.getElementById("checkbox1").checked;
selectedCheckboxes[1] = document.getElementById("checkbox1").checked;
});
});
Note: I did var selectedCheckboxes twice trying to get different results, donĀ“t know where I should do it.
You have several problems here:
You have a syntax error in your code sample. Make sure the code you post to StackOverflow compiles and runs without syntax errors (assuming you're not asking why a particular code snippet is generating syntax errors :) ).
The data attribute of your AJAX request is incorrectly specified as the literal string 'selectedCheckboxes', which means that your browser will send the literal string "selectedCheckboxes" as the payload to your server.
In addition, as you correctly surmise, you don't correctly handle the initialization of selectedCheckboxes. Variables initialized with var in JS are scoped to the containing function, which means the selectedCheckboxes declaration inside your click() handler are never going to be seen outside it.
Also, you're getting the value of "checkbox1" twice; you probably want to get something named "checkbox2" or similar. Related: If you are just serializing the only inputs in the form, use jquery's serialize() method so you have less code.
If you're really reloading the entire page anyway, don't use an AJAX request to do it? Using AJAX for form submissions is common when you do not want to reload the entire page (see below), but for your stated use case, it adds complexity you don't need. Just have a simple form with checkboxes and a submit button, and let the browser do it's default action.
Here's an example of using AJAX to submit a form behind the scenes, without reloading the entire page:
http://jsfiddle.net/Palpatim/rLeGv/
Given the HTML:
<form id="checkboxForm">
<input type="checkbox" name="check" value="check1" checked="checked" id="ch1"/>
<label for="ch1">check1</label>
<br/>
<input type="checkbox" name="check" value="check2" checked="checked" id="ch2" />
<label for="ch2">check2</label>
<br/>
<button>Click me</button>
</form>
This JS will submit a form when the button is clicked:
$(document).ready(function() {
$("button").click(function() {
$.ajax({
url: 'getNewForm.php?accion=value1',
data: $('#checkboxForm').serialize(),
dataType: 'json',
error: function() {
alert("ERROR");
},
success: function(res) {
alert("SUCCESS");
}
});
});
});
As far as loading a new page with the previous selections, you will have to maintain the state somehow. Your options include passing the state back from the server, storing the selections in the browser's local storage, or a cookie. I'd suggest passing the state back from the server, but your use case is a bit unclear.
so basic outline...
I have 'posts' pulled from the database and displayed like so:
<div class="blogtest">
<form action="process/updatepost.php" class="updatepost" method="post">
<input type="button" class='.$editenabled.' value="Edit">
<input type="submit" class="saveupdatebutton" value="Save">
<input type="hidden" class="postid" name="postid" value="'.$postID.'">
<div class="text">
<div class="buildtext">'.$text.'</div>
<div class="editor"><textarea name="ckeditor"id="ckeditor" class="ckeditor">'.$text.'</textarea></div>
</div>
</form>
</div>
Once the edit button is clicked, the buildtext class hides and the ckeditor is shown. Same for the edit and save button.
When save is clicked, a ajax call is made and then the data is updated. This works perfectly fine... however it only works perfectly fine if there is only 1 blog post on that page.
Here is the ajax for reference:
$(document).ready(function(){
$(".updatepost").submit(function(){
var $targetForm = $(this);
$targetForm.find(".error").remove();
$targetForm.find(".success").remove();
// If there is anything wrong with
// validation we set the check to false
var check = true;
// Get the value of the blog update post
var $ckEditor = $targetForm.find('.ckeditor'),
blogpost = $ckEditor.val();
// Validation
if (blogpost == '') {
check = false;
$ckEditor.after('<div class="error">Text Is Required</div>');
}
// ... goes after Validation
if (check == true) {
$.ajax({
type: "POST",
url: "process/updatepost.php",
data: $targetForm.serialize(),
dataType: "json",
success: function(response){
if (response.databaseSuccess)
$targetForm.find(".error").remove();
else
$ckEditor.after('<div class="error">Something went wrong!</div>');
}
});
}
return false;
});
});
So, if there is 2 blog posts on the page and i edit the 2nd (last) post, on clicking save the post is updated correctly.
However if i edit any other then it takes two submits for the data to be sent.
I checked on firebug and it shows that on the first click, the old value is sent, and then on the 2nd the new one.
Where am i going wrong?
Eventually (once working) the post will be refreshed on the success of the ajax call but for now its obviously vital that the user only has to click save once.
Thanks for any help! Any more code needed and ill post it here.
Craig :)
EDIT: After making ckeditor just a normal textarea it works fine. Must be ckeditor not updating as i know it doesnt litrally work as a textarea as such. Maybe ill have to use another rich editor...
I had a similar problem. Just to share my experience in case anyone ends up here with the same issue. The CKEditor wasn't updating the target textarea on the first click on the submit button and since I had data validation on the text area thankfully made me aware that the textarea wasn't being populated on the first submit. To overcome this I add this bit of code:
$('#accept-button').click(function (event) {
for (var i in CKEDITOR.instances) {
CKEDITOR.instances[i].updateElement();
}
}
As far as I can see from the integration guide, CKEditor most probably uses its own onsubmit event to actually send data back to the textarea. This would mean that those 2 events might fire up reversed order, first retrieving the old text from your code and only then updating the textarea.
You can always try and retrieve CKEditor's content using the following syntax:
var editor_data = CKEDITOR.instances.yourInstance.getData();
Also, are you using the jQuery adapter with CKEditor?
EDIT: the problem seems to be having same IDs on multiple textareas, all being called "ckeditor". This would result in unexpected behaviour across browsers, since ID must be always unique to a page.