I've a jQuery code which show/hide some disabled fields, based on an user select option:
$('.fieldcontent').not('.info').hide();
$('#selector_cs').change(function() {
$('.fieldcontent').customFadeOut(100);
$('.' + $(this).val()).customFadeIn(900);
$('input').prop('disabled',false);
$('textarea').prop('disabled',false);
$('select').prop('disabled',false);
});
});
The big headache is: if one or more fields are fading in, these fields doesn't pass my php validation, nor submitting the form.
If javascript is disabled on all browsers, the form works perfectly.
PHP validation is
if(!isset($_POST['products'])) {
$products[2] = clean_var($_POST['products']);
}
else {
$error = 1;
$products[3] = 'color:#FF0000;';
}
for all fields
Is there any php /jquery solution (no ajax please, 'cause i won't make the whole form again, and don't know anything about ajax)?
Thanks in advance for help
EDIT: Just detected another error: If the jquery script fadein another section of the form, PHP doesn't validate it anymore. Why? Never had problems like this with php-jquery.
If you leave them enabled, but change the property type to hidden then PHP should see the fields when you submit them.
Update
How about the following scenario:
5 fields shown
start-hiding two fields (A+B)
'add' two type=hidden fields with the same name as A+B and copy their current value from A+B to `A+`B
PHP should see these two hidden fields instead of the fields that are currently fading out.
If the user did not submit while fading out, then when the fields have faded out remove the `A+`B fields and set the property of the two faded fields to hidden
Inverse this for showing them fields again.
Do take note that this is not a problem caused by PHP but caused by how/when a browser interprets a form field to be a valid form field to be send when submitting the form
Related
I've Googled and searched on SO quite a bit for this unique problem, but not really finding my exact solution.
I have a basic form with X number of inputs. At some point in the form, the user as the freedom to add inputs via button click if needed. When they submit the form, it goes to another page to collect the posted form data, but I want the ability for the user to click "Back" (or send them back programmatically) if the submit fails.
I have error checking setup prior to submit via javascript, but there are other things (such as a PHP mailer) that could fail and I want them to be able to resubmit their data.
The issue of course is when the browser clicks back, it - at best - refreshes the initial form that was in the DOM with input data, but I lose all of the dynamically added inputs.
I want to capture the form/data in a session and have it repopulate the DOM with the submitted version created by the user on click back.
The closest I've come is doing something like this on SUBMIT:
var theForm = $('#myForm');
sessionStorage.setItem('formData', JSON.stringify(theForm.clone(true).html().toString());
And this on postback/click back:
$('#myForm').replaceWith(JSON.parse(sessionStorage.getItem("formData")));
The problem here is I get my form, but not the data! Do I need to iterate over each input to get my data put back in the recreated form?? Why doesn't it grab the data when .clone(true)ed?
Here's the answer I ultimately got to work.
Upon form validation, I set the session to hold the form data like so:
var theForm = $('#MyForm');
sessionStorage.setItem('formHTML', JSON.stringify(theForm.clone(true).html()));
theForm.find('input,select,textarea').each(function(){
sessionStorage.setItem(this.name,this.value);
});
Then, when the DOM loads again, I have this that checks for the session and populates the form with data if it exists:
$(document).ready(function(){
if (sessionStorage.getItem("formHTML")) {
$('#MyForm').html($.parseJSON(sessionStorage.getItem("formHTML")));
}
$('#MyForm').find('input,select,textarea').each(function(i,elem){
var sessItem = elem.name, sessValue = '';
if (sessValue = sessionStorage.getItem(sessItem)) {
if(elem.type=='radio' && elem.value==sessValue){
alert(elem[i].type+' has value of "'+elem[i].value+'"');
$('[name='+sessItem+']')[i].prop('checked',true);
}
else if(elem.type=='textarea'){
alert(elem.type);
$('[name='+sessItem+']').val(sessValue);
}
else
{
$('[name='+sessItem+']').val(sessValue);
}
}
});
});
I use some jQuery on a current gravity form. However, when I submit the form and it comes back with bad validation, I lose some of the jQuery targets.
I'm curious how I can swap out $(document).ready(function() { with something that will call my jQuery once the fields are reloaded with bad validation.
I've tried $("#gform_submit_button_1").click(function() { however, that's too soon. It needs to happen when the new fields come back from ajax.
There is actually a hook provided for use here: gform_post_render
This jQuery hook is fired every time the form is rendered to allow custom jQuery to be executed. This includes initial form load, going to the next/previous page on multi-page forms, form rendered with validation errors, confirmation message displayed, etc.
jQuery(document).bind('gform_post_render', function(){
// code to trigger on AJAX form render
});
http://www.gravityhelp.com/documentation/gravity-forms/extending-gravity-forms/hooks/javascript/gform_post_render/
For some reason Gravity Forms still hasn't added a jQuery hook for failed form validation. What they recommend doing is checking for the existence of div.validation_error.
jQuery(document).on('gform_post_render', function(e, form_id) {
if ( jQuery('div.validation_error').length > 0 ) {
console.log('Form validation error.');
}
});
You'll notice I'm not specifying a parent when I check for the validation error element: jQuery('div.validation_error'). If you have multiple forms on the page this would cause issues. The form_id parameter that is returned contains the form's ID in the database (e.g. 1, 2, 35, etc.) but I'm not sure if this value matches the forms ID in the HTML, e.g. <form id="gform_1">. If it does match, then it's good practice to specify the parent, so you could do:
if ( jQuery('div.validation_error', '#gform_' + form_id).length > 0 ) {
Maybe somebody else could weigh in and let us know if the form's HTML ID will always match the form's database ID.
Gravity forms does supply a gform_confirmation_loaded hook, but I don't think this will work in your case since it's not loading the confirmation, but the error state form. They don't have a hook for this but I've had success using jquery delegated events. I use the .gform_wrapper as my first selector and then target the fields I want to actually target.
See this documentation for more info:
http://api.jquery.com/on/#direct-and-delegated-events
http://www.gravityhelp.com/documentation/gravity-forms/extending-gravity-forms/hooks/filters/gform_confirmation_loaded/
One solution is: catch the submit event and start a interval that checks your form for changes and then calls your function:
$('#your-form').submit(function(){
html = $('#your-form').html();
iv = setInterval(function(){
If($('#your-form').html != html){
yourfunc();
clearInterval(iv);
}
}, 200);
});
function yourfunc(){
//your stuff
}
This is however not very neat and it will only work if the html is actually changed after the Ajax call.
I tried giving all the forms on the page the same form id or individual form id's with a unique.submit function. Neither seemed to work, always only the first form would work all the rest, would just kick me back to the homepage. see my code. code works great on pages with just one form, but when I have multiples it causes problems.
$("#sQuote").submit(function() {
//Send the serialized data to mailer.php.
$.post("mailerS.php", $("#sQuote").serialize(),
//Take our repsonse, and replace whatever is in the "formResponse"
//div with it.
function(data) {
$("#sQuote").html( $("#formResponse").html() );
}
);
return false;
});
});
I tried this with all the form id's = sQuote and the named them individually sQuote1 ect... and added another .submit for that unique ID
For what it's worth, on every single page all used id attributes have to be unique. Having more than one id attribute with the same value will lead to all kind of failure.
Validate your document with the W3 validator and fix the errors as a start. Duplicate ids will be reported as errors there.
I think I got a classic problem but I was not able to find a working solution so far.
I have got a form , the user clicks "Send" and everything works fine using a PRG pattern and doing both client-side and server-side validation.
The problem arises when any user (let's assume he entered valid inputs) clicks more then once quickly before the server script ends its execution...
I do not get any duplicated entry because I took care of that but the browser does not go to my "thanks for submitting page".
Instead it re-submits the same page with the same values and what I get are the custom errors I set to warn the user he is trying to enter details already stored in the database. The details sent in the first place are all in the database but the user has no chance to know that.
I tried to disable the submit button on a submit event using jQuery but in that case the data are not submitted.
HTML
<div id="send-button-container">
<input id="send-emails" type="submit" name="send_emails" value="Send"/>
</div>
jQuery
$(document).ready(function(){
$('#mail-form').submit(function(){
$('#send-emails').attr('disabled','disabled');
});
});
I am wondering if I can force a submission using Javascript after disabling the button and also how to deal with UAs with Javascript disabled
Thanks in advance
Depending on server-side language, the submit button being disabled could cause problems. This is because disabled elements are not POSTed to the server. Languages like ASP.NET require the button value to be submitted so it knows what event handler to fire. What I usually do is hide the submit button, and insert a disabled dummy button after it, which appears identical to the user. Then in your onsubmit handler, you can return false and submit the form programmatically...
$('#mail-form').submit(function(){
var btn = $('#send-emails');
var disBtn = $("<input type='button'/>").val(btn.val()).attr("disabled", "disabled");
btn.hide().after(disBtn);
this.submit();
return false;
});
Contradictory to the other up-voted answers, please note that you do not need to explicitly return true from your submit handler for natural form submission: http://jsfiddle.net/XcS5L/3/
I assume this means you are depending on the value of the submit button to service the request? That is you are checking
$_REQUEST['send_emails'] == 'Send';
This is not good practice. You should never depend on the value of the submit button because that is the just what is displayed to the user. Instead, you should add a hidden input that contains the event you want to fire. After the form is submitted, you don't need to care what the value of the submit button is and you can disable it. All other non-disabled data in the form is still submitted.
You can indeed force the submission after disabling the button.
$(function () {
$("#mail-form").submit(function () {
$("#send-emails").attr('disabled', 'disabled');
window.location = '?' + $("#mail-form").serialize() + '&send_mails=Send';
return false;
});
});
Server side set a $_SESSION variable that keeps track of the last time they made a submission and block submissions within a certain time.
<?php
session_start();
if (isset($_REQUEST['send_emails'])) {
if (isset($_SESSION['mail_sent'])
&& strtotime($_SESSION['mail_sent']) < strtotime('5 seconds ago')
) {
redirect_to_thanks();
}
do_post();
}
function do_post() {
if (do_validate()) {
$_SESSION['mail_sent'] = time();
redirect_to_thanks();
}
else {
yell_at_user_a_lot();
}
}
?>
You have to return true; You could try this if u want a simple button to submit the form.
$(function(){
$('#submitID').one('click',function(){
$('#formTobeSubmitted').submit();
$(this).attr('disabled','disabled');
})
});
On server side, generate a random number into each form, store the number when the form is submitted, and discard the submit if that number has already been stored earlier. When the user has disabled javascript, this is the best you can do. (Concurrency issues can be tricky as the two identical requests are handled at the same time - make sure you use some sort of locking mechanism, such as a table with a unique field or the flock() command in PHP.)
On browser side, just set a flag when the form is submitted, and discard all later submits:
$('#mail-form').submit(function() {
if ($(this).data('submitted') {
return false;
} else {
$(this).data('submitted', true).addClass('submitted');
}
});
You can use the submitted class to make the buttons gray or something. This has a few advantages to simply disabling them; Josh already said one. Another is that Firefox likes to remember disabled states when you hit refresh, which can cause your users getting stuck in certain situations.
Im looking for a way to have a form in cakephp that the user can add and remove form fields before submitting, After having a look around and asking on the cake IRC the answer seems to be to use Jquery but after hours of looking around i cannot work out how to do it.
The one example i have of this in cake i found at - http://www.mail-archive.com/cake-php#googlegroups.com/msg61061.html but after my best efforts i cannot get this code to work correctly ( i think its calling controllers / models that the doesn't list in the example)
I also found a straight jquery example (http://mohdshaiful.wordpress.com/2007/05/31/form-elements-generation-using-jquery/) which does what i would like my form to do but i cannot work out how to use the cakephp form helper with it to get it working correctly and to get the naming correct. (obviously the $form helper is php so i cant generate anything with that after the browser has loaded).
I an new to cake and have never used jQuery and i am absolutely stumped with how to do this so if anyone has a cakephp example they have working or can point me in the right direction of what i need to complete this it would be very much appreciated.
Thanks in advance
I would take the straight jquery route, personally. I suppose you could have PHP generate the code for jquery to insert (that way you could use the form helper), but it adds complexity without gaining anything.
Since the form helper just generates html, take a look at the html you want generated. Suppose you want something to "add another field", that when clicked, will add another field in the html. Your html to be added will be something like:
<input type="text" name="data[User][field][0]" />
Now, to use jquery to insert it, I'd do something like binding the function add_field to the click event on the link.
$(document).ready( function() {
$("#link_id").click( 'add_field' );
var field_count = 1;
} );
function add_field()
{
var f = $("#div_addfield");
f.append( '<input type="text" name="data[User][field][' + field_count + ']" />' );
field_count++;
}
Of course, if a user leaves this page w/o submitting and returns, they lose their progress, but I think this is about the basics of what you're trying to accomplish.
This was my approach to remove elements:
In the view, I had this:
echo $form->input('extrapicture1uploaddeleted', array('value' => 0));
The logic I followed was that value 0 meant, not deleted yet, and value 1 meant deleted, following a boolean logic.
That was a regular input element but with CSS I used the 'display: none' property because I did not want users to see that in the form. Then what I did was that then users clicked the "Delete" button to remove an input element to upload a picture, there was a confirmation message, and when confirming, the value of the input element hidden with CSS would change from 0 to 1:
$("#deleteextrapicture1").click(
function() {
if (confirm('Do you want to delete this picture?')) {
$('#extrapicture1upload').hide();
// This is for an input element that contains a boolean value where 0 means not deleted, and 1 means deleted.
$('#DealExtrapicture1uploaddeleted').attr('value', '1');
}
// This is used so that the link does not attempt to take users to another URL when clicked.
return false;
}
);
In the controller, the condition $this->data['Deal']['extrapicture1uploaddeleted']!='1' means that extra picture 1 has not been deleted (deleting the upload button with JavaScript). $this->data['Deal']['extrapicture1uploaddeleted']=='1' means that the picture was deleted.
I tried to use an input hidden element and change its value with JavaScript the way I explained above, but I was getting a blackhole error from CakePHP Security. Apparently it was not allowing me to change the value of input elements with JavaScript and then submit the form. But when I used regular input elements (not hidden), I could change their values with JavaScript and submit the form without problems. My approach was to use regular input elements and hide them with CSS, since using input hidden elements was throwing the blackhole error when changing their values with JavaScript and then submitting the form.
Hopefully the way I did it could give some light as a possible approach to remove form fields in CakePHP using JavaScript.