Does form.submit() post checkbox data differently from standard submit button? - javascript

I just ran into an odd issue with my CodeIgniter app. I'm using a jQuery .on('submit') event handler to catch all form submissions and follows this procedure: grab the form object using this, stores the object for later, checks the user is logged in with an AJAX call, if logged in, gets the stored jQuery form object and submits the form with form.submit().
This works absolutely fine for all my forms (form validation works fine, returns validation errors correctly) except when I have a form with a checkbox. The checkbox is just ignored.
I use a required form validation rule to make sure the user ticks the checkbox before continuing and it works absolutely fine when this event handler is disabled however, the validation error only appears (oddly) when I add another input to the form that isn't a checkbox!
I'm wondering if there's someone that can understand the theory behind why this error is happening? I could post the code but I'm about 90% sure this is something to do with the way that JavaScript handles posting of checkbox data that I'm just not aware of.
Any ideas?

Javascript, by itself, doesn't actually post any form data.
In the standard HTML submit, if a checkbox is not checked, then there is no key/value submitted for that item.
I've learned the hard way that many Javascript form serializers (used by Ajax calls) are simply broken and don't follow the standards... I spend several days writing my own and my Qunit tests are almost longer than the code itself.
What you'll need to do is use your debugging tools (Firefox or Chrome) and watch the network tab -- see exactly what is submitted.

With very helpful advice from Jeremy J Starcher, I worked out the problem. CodeIgniter's form validation was not running since the $_POST array was empty. Usually, even with only one input field (a checkbox) the actual submit button's value is POSTed, therefore even if the checkbox isn't checked and no value for it is posted, the $_POST array is still populated by the submit button's value. However, when using Javascript to submit the form, the submit button's value is ignored and not POSTed (thanks to Jeremy for that vital info).
The solution was to add a blank, hidden input field (of a type that is always POSTed, regardless of value). There may be a nicer way to solve this using Javascript to create a blank POST variable or something and I welcome further answers relating to this.
As a side note, I was confused as to how CSRF validation was succeeding and yet the $_POST array was empty - I checked out CodeIgniter's Security Class and basically it checks the CSRF POST variable and if it's all good, it unsets it, so by the time the $_POST array was hitting the Form Validation Class, it was empty.

Related

avoid "undo" history entries for back button-ing over forms

to my surprise, I couldn't find any information on this topic, but then, searching for such things always yields a lot of similar but unrelated things...
Anyway, some notes to avoid misunderstandings:
- The question is about HTML, HTTP, Javascript, and Browser behavior. I'm intentionally not speaking about server-side technology because I think making that part work won't be a problem for me.
- I'm not aiming at security, nor do I want to restrict the user in what he/she does. In fact, I want to improve the UI.
Suppose we have an HTML page with a POST-redirect-GET form. Submitting the form causes server-side validation, followed either by results or validation errors. Now suppose it took a few attempts to get all values valid. The URL stays the same, though I have tried using changing URLs. Now the user looks at the result, then wants to go back to whatever page linked to the form. For a nice user interface, this should take 2 clicks on the back button, one to return from the results page to the form, and a second to return to the page before the form. Instead, however, the user has to click past each failed attempt to enter valid values.
How can I avoid this? Note again that I don't want to "hide" anything from the user, just there is no practical case where invalid form values are useful. I found hints that a "single-page application" suffers from related problems due to NOT filling the history, but that's actually the opposite problem, and my application is not "single-page".
As an alternative to avoiding history entries, I'm also perfectly fine with side-stepping the problem in some way, or even building a good user interface around it. But right now, the button says "back" (in the sense of navigation) but does "undo" (in the sense of changing values) to the form. People expect the back button to go back -- they already have ctrl-z for undo.
The straightforward solution -- though I couldn't find anything like that -- would be an HTTP header that says, "here's an updated version of the same resource you requested before, note how it has the same URL, so don't make it appear twice when back-button-ing".
I think the simplest approach would be to use ajax to process your form submission even if it is a multi-part form.
I would have a combination of client side validation to give quicker feedback to your user, and then handle server side validation errors when you receive your return data from the ajax request.
With this method your browser history should be relatively preserved and not filled with success/failure form submissions.
I personally like this client side bootstrap validator plugin:
https://github.com/1000hz/bootstrap-validator
I also use it to update the interface when I get an error message returned from the server.

Django - Dynamic number of ModelForms based on dropdown value

I have a form that registers teams of people. Based on a dropdown to select the number of members in the team, the form should show that many model forms, one for each member.
I am not particularly sure what the correct design patter for this is. Here are the solutions that I have come up with:
Use JS to generate the HTML for each member form and then use the Django ModelForm backend to parse each form. However, in this case I cannot use the inbuilt rendering functions of Django and validation notification becomes bothersome.
Send a GET request whenever the user changes the dropdown value, and the GET request specifies the number of members you want to add. But here it would result in any previously entered data being cleared.
Send a POST request via JS whenever the dropdown is updated, and then re-render the form with the appropriate values picked up from the POST request. I am not sure if this is the right way to do this and seems to be easy to get wrong.
Can you please advise on what is the best solution for this scenario?
I am pretty sure this has already been answered somewhere, but I can't seem to find it anywhere. If you have the link to the answer, please go ahead and mark this question as a duplicate.

pass javascript variable to ajax

I am working on a site with many forms . Most of the forms will be submitted via jquery AJAX.
I have implemented recaptcha for security but the client does not like it as the words are sometimes difficult to read.
As an alternate I am looking at honeytrap method for less important forms. As I understand In this method I keep a field in the form hidden from normal users via CSS. So legitimate users will leave the field blank while a bot will fill it .
Now my question is since I am using jQuery AJAX for form submission, instead of hidden field if form , can't I just pass an extra variable (along with form field variables) from javascript to AJAX. (like var secretword = 1) AJAX will check this variable( if secretword == 1 ) and if it is empty(bot will not use javascript to sumbit form so var will be empty) then the form will not be submitted.For legitimate users javascript function will add "1" value to the variable.Is my method as secure as honeytrap?
NOTE: Website does not work without javascript so need not go into what happens if javascript is disabled.
Please provide me your valuable advice on this.
You're really over-thinking this.
If you only do legitimate submission via AJAX, make the form's action attribute wrong, and you've effectively accomplished what your proposed solution does: Anybody directly submitting the form without JS will have their submission ignored.
This obviously won't deter anybody from figuring out where you AJAX submissions are going and just spamming that endpoint directly, but neither will your proposed secretword=1 solution or a traditional hidden field.

Checkbox Captcha

I'm initiating my first start-up. I can't stand attempting to read captchas when signing up for websites, don't want my users to. I looked for alternatives, and I found the checkbox captcha. How is this done, using JavaScript to load a checkbox, and validate it with the same code as would normally be used to make a sign up form?
Thanks.
I looked at the example linked from the article you posted. At first glance, it seems like this can be easily bypassed.
The checkbox captcha works on the basis that spam-bots don't parse or use JavaScript code embedded in webpages. Because of this, they will not find the captcha checkbox element within the form it is searching, and therefore will not send a post value for the checkbox along with the form, and on the server side, you would reject the form if the checkbox value wasn't sent.
The problem with this is:
The checkbox name is always the same (gasp_checkbox)
A bot could easily be "trained" to detect this javascript on your page and act accordingly
Even if you output a random name and value that must be used for the checkbox, it could still be detected
The outcome of those 3 problems means that this is much easier to break than image captchas or other methods. All a bot has to do when they submit your form is add: gasp_checkbox=on to their HTTP request.
That said, if you implement this for yourself on your own site, it is unlikely that any bots will able to get past it because its use is not widespread.
You could make it more secure by doing the following:
Generate unique name/value pairs for the checkbox on the server side, and output those values in obfuscated javascript to the client
Serve the script away from your form, preferably in an external javascript file that is generated by a script.
Verify that the values sent for the checkbox match a pair that was previously generated, and not used before.
If you do those things, I think you could have an effective checkbox captcha. If someone does catch on to it on your site, it may still be trivial to defeat, even with the above safeguards in place, but it may take a while, and still be effective for you most of the time.

JSP session problem

I am a newbie to writing JSPs.
In my JSP I have dynamically created a form with select boxes
(i.e. these fields are not in html)
In one of the selectboxes, I implemented a onchange method which passes the value as a parameter and re-displays the form. When the form is redisplayed the parameter I've passed, sets the value of another select box according to the parameter's value, using an external XML file.
One Problem is that after the onchange method as the current page is resent and reloaded, selected values of the other fields (around 10 fields) are lost.
Currently I use the following approach using the Session to address this problem
in my JSP; in the onchange method, I use javascript to load selected values and pass them as parameters to a servlet in a GET request. In the servlet, I receive the parameters and set attributes in the session.
In the JSP, I use getAttributes in the session and change the selected values during the dynamic creation of the form.
I wonder if there is a simpler way to do this as I have to create a lots of fields for this to work. Also I didnt make use of a databean in this case.
Since dynamic creation of fields is using java logic, Is it true that ajax can't be used?
Could you please advise me on the quality of my design? Am I staying true to the MVC design pattern?
If I am not wrong, your whole question basically boils (understatement) down to the following:
I have a form with a bunch of dropdowns. I am submitting a form during onchange of a dropdown. How do I retain the selected value of all other dropdows after submit?
Yes?
OK, just set the selected attribute whenever the dropdown option's value matches the submitted request parameter value. The below example assumes that you've a Map<String, String> as ${fooOptions}:
<select name="foo">
<c:forEach items="${fooOptions}" var="fooOption">
<option value="${fooOption.key}" ${fooOption.key == param.foo ? 'selected' : ''}>${fooOption.value}</option>
</c:forEach>
</select>
Do you see? When the form get submitted, the currently selected option of the dropdown with the name "foo" get sent as a request parameter and is in the server side available as request parameter ${param.foo}. While dynamically generating the options, you just check if the option's value equals to the request parameter value and if so, then just set the selected attribute.
Please note that this has nothing to do with sessions and such. They serve a different purpose, generally with regard to the current visitor in person, such as its login, preferences, shopping cart, etc. Do not use it to store form values. It'll only conflict whenever you've multiple browser windows/tabs open in the same session.
JavaScript is only helpful if you would like to do the ajax magic. But I guess that it's only another steep learning curve for you. Perhaps for later. In any way, you can find some kickoff examples in this answer: How to use Servlets and Ajax?

Categories