jQuery and IE not playing nice - javascript

I have this section of code:
function createDownload() {
var category, format, specification, download;
$('#submitform').click(function() {
category = $('#cate').val();
format = $('#form').val();
specification = $('#spec').val();
if (category == "NULL" || format == "NULL" || specification == "NULL") {
alert("Please select all options.");
return false;
} else {
download = "pdfs/"+specification+format+category+".pdf";
window.open(download);
}
});
}
Now... In Internet Explorer it says there is an "Error on the page" - Message: 'return' statement outside of function and I have to click the button again.
In Firefox, Chrome and Safari - I have to click the button twice to get the PDF to appear... (and no errors)...
Now why could that be?!
As per request - My Form declaration:
<form method="post" action="javascript: return false;" onSubmit="createDownload();">

<form method="post" action="javascript: return false;" onSubmit="createDownload();">
Since you are using return false not in a function it is throwing the error. You will have to put that in an anynymous function.
Something like
<form method="post" action="javascript: function() {return false;}" onSubmit="createDownload();">
will work
Better to bind the event .submit() for the form
<form method="post" id="frm1"></form>
$("#frm1").submit(function(){
// your code
return false;
});

You need to change your action='javascript: return false;' and remove the onsubmit. It should become action='javascript: createDownload();'

Try removing the return. It seems you don't even need it, and if that's really the cause of the problem then what's the point keeping it there?

First, you need to remove the action from the form - it serves no purpose here. Also, assuming #submitForm refers to the form submit button, your first click will attach the click handler and the second click will actually call it. Instead, remove the onsubmit attribute and just attach the handler in the usual way to either the button click or form submit event, being sure to cancel the event in either case:
jQuery(function($) {
$('#submitform').click(function() {
// or: $('#formID').submit(function() {
var category, format, specification, download;
category = $('#cate').val();
format = $('#form').val();
specification = $('#spec').val();
if (category == "NULL" || format == "NULL" || specification == "NULL") {
alert("Please select all options.");
} else {
download = "pdfs/"+specification+format+category+".pdf";
window.open(download);
}
return false;
});
});

Related

Prevent submit form when focus is on input [duplicate]

How do you prevent an ENTER key press from submitting a form in a web-based application?
[revision 2012, no inline handler, preserve textarea enter handling]
function checkEnter(e){
e = e || event;
var txtArea = /textarea/i.test((e.target || e.srcElement).tagName);
return txtArea || (e.keyCode || e.which || e.charCode || 0) !== 13;
}
Now you can define a keypress handler on the form:
<form [...] onkeypress="return checkEnter(event)">
document.querySelector('form').onkeypress = checkEnter;
Here is a jQuery handler that can be used to stop enter submits, and also stop backspace key -> back. The (keyCode: selectorString) pairs in the "keyStop" object are used to match nodes that shouldn't fire their default action.
Remember that the web should be an accessible place, and this is breaking keyboard users' expectations. That said, in my case the web application I am working on doesn't like the back button anyway, so disabling its key shortcut is OK. The "should enter -> submit" discussion is important, but not related to the actual question asked.
Here is the code, up to you to think about accessibility and why you would actually want to do this!
$(function(){
var keyStop = {
8: ":not(input:text, textarea, input:file, input:password)", // stop backspace = back
13: "input:text, input:password", // stop enter = submit
end: null
};
$(document).bind("keydown", function(event){
var selector = keyStop[event.which];
if(selector !== undefined && $(event.target).is(selector)) {
event.preventDefault(); //stop event
}
return true;
});
});
Simply return false from the onsubmit handler
<form onsubmit="return false;">
or if you want a handler in the middle
<script>
var submitHandler = function() {
// do stuff
return false;
}
</script>
<form onsubmit="return submitHandler()">
//Turn off submit on "Enter" key
$("form").bind("keypress", function (e) {
if (e.keyCode == 13) {
$("#btnSearch").attr('value');
//add more buttons here
return false;
}
});
You will have to call this function whic will just cancel the default submit behaviour of the form. You can attach it to any input field or event.
function doNothing() {
var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
if( keyCode == 13 ) {
if(!e) var e = window.event;
e.cancelBubble = true;
e.returnValue = false;
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
}
The ENTER key merely activates the form's default submit button, which will be the first
<input type="submit" />
the browser finds within the form.
Therefore don't have a submit button, but something like
<input type="button" value="Submit" onclick="submitform()" />
EDIT: In response to discussion in comments:
This doesn't work if you have only one text field - but it may be that is the desired behaviour in that case.
The other issue is that this relies on Javascript to submit the form. This may be a problem from an accessibility point of view. This can be solved by writing the <input type='button'/> with javascript, and then put an <input type='submit' /> within a <noscript> tag. The drawback of this approach is that for javascript-disabled browsers you will then have form submissions on ENTER. It is up to the OP to decide what is the desired behaviour in this case.
I know of no way of doing this without invoking javascript at all.
In short answer in pure Javascript is:
<script type="text/javascript">
window.addEventListener('keydown', function(e) {
if (e.keyIdentifier == 'U+000A' || e.keyIdentifier == 'Enter' || e.keyCode == 13) {
if (e.target.nodeName == 'INPUT' && e.target.type == 'text') {
e.preventDefault();
return false;
}
}
}, true);
</script>
This only disables the "Enter" keypress action for input type='text'. Visitors can still use "Enter" key all over the website.
If you want to disable "Enter" for other actions as well, you can add console.log(e); for your your test purposes, and hit F12 in chrome, go to "console" tab and hit "backspace" on the page and look inside it to see what values are returned, then you can target all of those parameters to further enhance the code above to suit your needs for "e.target.nodeName", "e.target.type" and many more...
See my detailed answer for a similar question here
I've always done it with a keypress handler like the above in the past, but today hit on a simpler solution. The enter key just triggers the first non-disabled submit button on the form, so actually all that's required is to intercept that button trying to submit:
<form>
<div style="display: none;">
<input type="submit" name="prevent-enter-submit" onclick="return false;">
</div>
<!-- rest of your form markup -->
</form>
That's it. Keypresses will be handled as usual by the browser / fields / etc. If the enter-submit logic is triggered, then the browser will find that hidden submit button and trigger it. And the javascript handler will then prevent the submision.
All the answers I found on this subject, here or in other posts has one drawback and that is it prevents the actual change trigger on the form element as well. So if you run these solutions onchange event is not triggered as well. To overcome this problem I modified these codes and developed the following code for myself. I hope this becomes useful for others.
I gave a class to my form "prevent_auto_submit" and added the following JavaScript:
$(document).ready(function()
{
$('form.prevent_auto_submit input,form.prevent_auto_submit select').keypress(function(event)
{
if (event.keyCode == 13)
{
event.preventDefault();
$(this).trigger("change");
}
});
});
I've spent some time making this cross browser for IE8,9,10, Opera 9+, Firefox 23, Safari (PC) and Safari(MAC)
JSFiddle Example: http://jsfiddle.net/greatbigmassive/ZyeHe/
Base code - Call this function via "onkeypress" attached to your form and pass "window.event" into it.
function stopEnterSubmitting(e) {
if (e.keyCode == 13) {
var src = e.srcElement || e.target;
if (src.tagName.toLowerCase() != "textarea") {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
}
}
stopSubmitOnEnter (e) {
var eve = e || window.event;
var keycode = eve.keyCode || eve.which || eve.charCode;
if (keycode == 13) {
eve.cancelBubble = true;
eve.returnValue = false;
if (eve.stopPropagation) {
eve.stopPropagation();
eve.preventDefault();
}
return false;
}
}
Then on your form:
<form id="foo" onkeypress="stopSubmitOnEnter(e);">
Though, it would be better if you didn't use obtrusive JavaScript.
Preventing "ENTER" to submit form may inconvenience some of your users. So it would be better if you follow the procedure below:
Write the 'onSubmit' event in your form tag:
<form name="formname" id="formId" onSubmit="return testSubmit()" ...>
....
....
....
</form>
write Javascript function as follows:
function testSubmit(){
if(jQuery("#formId").valid())
{
return true;
}
return false;
}
(OR)
What ever the reason, if you want to prevent the form submission on pressing Enter key, you can write the following function in javascript:
$(document).ready(function() {
$(window).keydown(function(event){
if(event.keyCode == 13) {
event.preventDefault();
return false;
}
});
});
thanks.
To prevent form submit when pressing enter in a textarea or input field, check the submit event to find what type of element sent the event.
Example 1
HTML
<button type="submit" form="my-form">Submit</button>
<form id="my-form">
...
</form>
jQuery
$(document).on('submit', 'form', function(e) {
if (e.delegateTarget.activeElement.type!=="submit") {
e.preventDefault();
}
});
A better solution is if you don't have a submit button and you fire the event with a normal button. It is better because in the first examlple 2 submit events are fired, but in the second example only 1 submit event is fired.
Example 2
HTML
<button type="button" onclick="$('#my-form').submit();">Submit</button>
<form id="my-form">
...
</form>
jQuery
$(document).on('submit', 'form', function(e) {
if (e.delegateTarget.activeElement.localName!=="button") {
e.preventDefault();
}
});
In my case, this jQuery JavaScript solved the problem
jQuery(function() {
jQuery("form.myform").submit(function(event) {
event.preventDefault();
return false;
});
}
You will find this more simple and useful :D
$(document).on('submit', 'form', function(e){
/* on form submit find the trigger */
if( $(e.delegateTarget.activeElement).not('input, textarea').length == 0 ){
/* if the trigger is not between selectors list, return super false */
e.preventDefault();
return false;
}
});
How about:
<asp:Button ID="button" UseSubmitBehavior="false"/>
Add this tag to your form - onsubmit="return false;"
Then you can only submit your form with some JavaScript function.
Please check this article How to prevent ENTER keypress to submit a web form?
$(“.pc_prevent_submit”).ready(function() {
$(window).keydown(function(event) {
if (event.keyCode == 13) {
event.preventDefault();
return false;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form class=”pc_prevent_submit” action=”” method=”post”>
<input type=”text” name=”username”>
<input type=”password” name=”userpassword”>
<input type=”submit” value=”submit”>
</form>
You can trap the keydown on a form in javascript and prevent the even bubbling, I think. ENTER on a webpage basically just submits the form that the currently selected control is placed in.
This link provides a solution that has worked for me in Chrome, FF, and IE9 plus the emulator for IE7 and 8 that comes with IE9's developer tool (F12).
http://webcheatsheet.com/javascript/disable_enter_key.php
Another approach is to append the submit input button to the form only when it is supposed to be submited and replace it by a simple div during the form filling
Simply add this attribute to your FORM tag:
onsubmit="return gbCanSubmit;"
Then, in your SCRIPT tag, add this:
var gbCanSubmit = false;
Then, when you make a button or for any other reason (like in a function) you finally permit a submit, simply flip the global boolean and do a .submit() call, similar to this example:
function submitClick(){
// error handler code goes here and return false if bad data
// okay, proceed...
gbCanSubmit = true;
$('#myform').submit(); // jQuery example
}
I Have come across this myself because I have multiple submit buttons with different 'name' values, so that when submitted they do different things on the same php file. The enter / return button breaks this as those values aren't submitted.
So I was thinking, does the enter / return button activate the first submit button in the form?
That way you could have a 'vanilla' submit button that is either hidden or has a 'name' value that returns the executing php file back to the page with the form in it.
Or else a default (hidden) 'name' value that the keypress activates, and the submit buttons overwrite with their own 'name' values.
Just a thought.
How about:
<script>
function isok(e) {
var name = e.explicitOriginalTarget.name;
if (name == "button") {
return true
}
return false;
}
</script>
<form onsubmit="return isok(event);">
<input type="text" name="serial"/>
<input type="submit" name="button" value="Create Thing"/>
</form>
And just name your button right and it will still submit, but text fields i.e. the explicitOriginalTarget when you hit return in one, will not have the right name.
If none of those answers are working for you, try this. Add a submit button before the one that actually submits the form and just do nothing with the event.
HTML
<!-- The following button is meant to do nothing. This button will catch the "enter" key press and stop it's propagation. -->
<button type="submit" id="EnterKeyIntercepter" style="cursor: auto; outline: transparent;"></button>
JavaScript
$('#EnterKeyIntercepter').click((event) => {
event.preventDefault(); //The buck stops here.
/*If you don't know what this if statement does, just delete it.*/
if (process.env.NODE_ENV !== 'production') {
console.log("The enter key was pressed and captured by the mighty Enter Key Inceptor (⌐■_■)");
}
});
This worked for me.
onkeydown="return !(event.keyCode==13)"
<form id="form1" runat="server" onkeydown="return !(event.keyCode==13)">
</form>
Here's how I'd do it:
window.addEventListener('keydown', function(event)
{
if (event.key === "Enter" && event.target.tagName !== 'TEXTAREA')
{
if(event.target.type !== 'submit')
{
event.preventDefault();
return false;
}
}
});
put into javascript external file
(function ($) {
$(window).keydown(function (event) {
if (event.keyCode == 13) {
return false;
}
});
})(jQuery);
or somewhere inside body tag
<script>
$(document).ready(function() {
$(window).keydown(function(event) {
alert(1);
if(event.keyCode == 13) {
return false;
}
});
});
</script>
I had the same problem (forms with tons of text fields and unskilled users).
I solved it in this way:
function chkSubmit() {
if (window.confirm('Do you want to store the data?')) {
return true;
} else {
// some code to focus on a specific field
return false;
}
}
using this in the HTML code:
<form
action="go.php"
method="post"
accept-charset="utf-8"
enctype="multipart/form-data"
onsubmit="return chkSubmit()"
>
In this way the ENTER key works as planned, but a confirmation (a second ENTER tap, usually) is required.
I leave to the readers the quest for a script sending the user in the field where he pressed ENTER if he decide to stay on the form.

Why is the submit button value not included in the form data? [duplicate]

I'm trying to find the value of the submit button that triggered the form to submit
$("form").submit(function() {
});
I could possibly fire a $("input[type=submit]").click() event for each button and set some variable, but that seems less elegant than some how pulling the button off of the the form on submit.
I leveraged document.activeElement as sketched in this answer: How to get the focused element with jQuery?
$form.on('submit', function() {
var $btn = $(document.activeElement);
if (
/* there is an activeElement at all */
$btn.length &&
/* it's a child of the form */
$form.has($btn) &&
/* it's really a submit element */
$btn.is('button[type="submit"], input[type="submit"], input[type="image"]') &&
/* it has a "name" attribute */
$btn.is('[name]')
) {
console.log("Seems, that this element was clicked:", $btn);
/* access $btn.attr("name") and $btn.val() for data */
}
});
I take advantage of the fact, that the button is always the focused element after clicking it. This will not work, if you do a blur() right after the click.
#Doin has spotted another drawback. If a user submits the form via enter in a text field, the document.activeElement is not set. You'd need to watch out for this yourself, by handling keypress events in input[type="text"] and similar.
Update 2017-01: For my library Hyperform I chose not to use activeElement but to catch all events, that lead to form submission. The code for this is on Github.
If you happen to use Hyperform, this is how you would access the button that triggered the submit:
$(form).on('submit', function(event) {
var button = event.submittedVia;
});
I implemented this and I suppose it will do.
$(document).ready(function() {
$("form").submit(function() {
var val = $("input[type=submit][clicked=true]").val()
// DO WORK
});
and this is the submit button event that sets it up
$("form input[type=submit]").click(function() {
$("input[type=submit]", $(this).parents("form")).removeAttr("clicked");
$(this).attr("clicked", "true");
});
Thanks for the responses, but this isn't terribly inelegant...
There is now a standard submitter property in the submit event.
Already implemented in Firefox 75 and Chrome/Edge 81 !
document.addEventListener('submit',function(e){
console.log(e.submitter)
})
For browsers not supporting it, use this polyfill
Note: if you target older Browsers you need to polyfill other things like closest or matches. And ensure that the polyfill is loaded before adding your submit-events.
!function(){
var lastBtn = null
document.addEventListener('click',function(e){
if (!e.target.closest) return;
lastBtn = e.target.closest('button, input[type=submit]');
}, true);
document.addEventListener('submit',function(e){
if ('submitter' in e) return;
var canditates = [document.activeElement, lastBtn];
lastBtn = null;
for (var i=0; i < canditates.length; i++) {
var candidate = canditates[i];
if (!candidate) continue;
if (!candidate.form) continue;
if (!candidate.matches('button, input[type=button], input[type=image]')) continue;
e.submitter = candidate;
return;
}
e.submitter = e.target.querySelector('button, input[type=button], input[type=image]')
}, true);
}();
I created a test form and using Firebug found this way to get the value;
$('form').submit(function(event){
alert(event.originalEvent.explicitOriginalTarget.value);
});
Unfortunately, only Firefox supports this event.
Here's an approach that seems cleaner for my purposes.
First, for any and all forms:
$('form').click(function(event) {
$(this).data('clicked',$(event.target))
});
When this click event is fired for a form, it simply records the originating target (available in the event object) to be accessed later. This is a pretty broad stroke, as it will fire for any click anywhere on the form. Optimization comments are welcome, but I suspect it will never cause noticeable issues.
Then, in $('form').submit(), you can inquire what was last clicked, with something like
if ($(this).data('clicked').is('[name=no_ajax]')) xhr.abort();
According to this link, the Event object contains a field Event.target, which:
Returns a string representing the object that initiated the event.
I just created a page testing out what that value is, and it appears as though that representation is for the form itself, not for the button clicked. In other words, Javascript doesn't provide the facility to determine the clicked button.
As far as Dave Anderson's solution, it might be a good idea to test that in multiple browsers before using it. It's possible that it could work fine, but I can't say either way.
One clean approach is to use the click event on each form button.
Following is a html form with save,cancel and delete buttons:
<form name="formname" action="/location/form_action" method="POST">
<input name="note_id" value="some value"/>
<input class="savenote" type="submit" value="Save"/>
<input class="cancelnote" type="submit" value="Cancel"/>
<input class="deletenote" type="submit" value="Delete" />
</form>
Following is the jquery. I send the appropriate 'action' to the same server function depending on which button was clicked ('save' or 'delete'). If 'cancel', is clicked, I just reload the page.
$('.savenote').click(function(){
var options = {
data: {'action':'save'}
};
$(this).parent().ajaxSubmit(options);
});
$('.deletenote').click(function(){
var options = {
data: {'action':'delete'}
};
$(this).parent().ajaxSubmit(options);
});
$('.cancelnote').click(function(){
window.location.reload(true);
return false;
});
There's a submitter property for form's SubmitEvent. However, as of present time, this doesn't work on Safari.
<form id="form">
<button value="add" type="submit">Add</button>
<button value="remove" type="submit">Remove</button>
</form>
let form = document.getElementById('form');
form.onsubmit = (event) => {
e.preventDefault();
console.log(e.submitter.type);
}
A different approach that works across browsers. However, you have to rely on form element instead of the event object. This basically adds a 'submitter' property onto the form element object that can be referenced later on form submit.
<form id="form">
<button onclick="this.form.submitter = 'add'" type="submit">Add</button>
<button onclick="this.form.submitter = 'remove'" type="submit">Remove</button>
</form>
let form = document.getElementById('form');
form.onsubmit = (event) => {
e.preventDefault();
console.log(form.submitter);
}
I searched and found several ways to get the submit button name + value sent to the server using jQuery + AJAX. I didn't like them very much...
One of the bests was hunter's solution presented here!
But I wrote another one myself.
I want to share, because it is good, and, as I needed, it works also with forms loaded via ajax (after document.ready):
$(document).on('click', 'form input[type=submit]', function(){
$('<input type="hidden" />').appendTo($(this).parents('form').first()).attr('name', $(this).attr('name')).attr('value', $(this).attr('value'));
});
Simple! When the submit button is clicked, a hidden field is added to the form, using same name and value of the submit button.
EDIT: The version below is easier to read. Also, it takes care of removing previously appended hidden fields (in the case of submitting the same form twice, which is perfectly possible when using AJAX).
Improved code:
$(document).on('click', 'form input[type=submit]', function(){
var name = $(this).attr('name');
if (typeof name == 'undefined') return;
var value = $(this).attr('value');
var $form = $(this).parents('form').first();
var $input = $('<input type="hidden" class="temp-hidden" />').attr('name', name).attr('value', value);
$form.find('input.temp-hidden').remove();
$form.append($input);
});
( event )
function submForm(form,event){
var submitButton;
if(typeof event.explicitOriginalTarget != 'undefined'){ //
submitButton = event.explicitOriginalTarget;
}else if(typeof document.activeElement.value != 'undefined'){ // IE
submitButton = document.activeElement;
};
alert(submitButton.name+' = '+submitButton.value)
}
<form action="" method="post" onSubmit="submForm(this, event); return false;">
I did try some of the examples provided, but they didn't work for our purposes.
Here's a fiddle to show: http://jsfiddle.net/7a8qhofo/1/
I was faced with a similar issue, and this is how we solved the issue in our forms.
$(document).ready(function(){
// Set a variable, we will fill later.
var value = null;
// On submit click, set the value
$('input[type="submit"]').click(function(){
value = $(this).val();
});
// On data-type submit click, set the value
$('input[type="submit"][data-type]').click(function(){
value = $(this).data('type');
});
// Use the set value in the submit function
$('form').submit(function (event){
event.preventDefault();
alert(value);
// do whatever you need to with the content
});
});
Get the submitter object from the event object
You can simply get the event object when you submit the form. From that, get the submitter object. As below:
$(".review-form").submit(function (e) {
e.preventDefault(); // avoid to execute the actual submit of the form.
let submitter_btn = $(e.originalEvent.submitter);
console.log(submitter_btn.attr("name"));
}
I have explained in detail in this answer here: (https://stackoverflow.com/a/66334184/11320178)
Let me know if you have any doubts.
you can try this way with "event.originalEvent.x" and "event.originalEvent.y":
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<title>test</title>
</head>
<body>
<form id="is_a_form">
<input id="is_a_input_1" type="submit"><br />
<input id="is_a_input_2" type="submit"><br />
<input id="is_a_input_3" type="submit"><br />
<input id="is_a_input_4" type="submit"><br />
<input id="is_a_input_5" type="submit"><br />
</form>
</body>
</html>
<script>
$(function(){
$.fn.extend({
inPosition: function(x, y) {
return this.each(function() {
try{
var offset = $(this).offset();
if ( (x >= offset.left) &&
(x <= (offset.left+$(this).width())) &&
(y >= offset.top) &&
(y <= (offset.top+$(this).height())) )
{
$(this).css("background-color", "red");
}
else
{
$(this).css("background-color", "#d4d0c8");
}
}
catch(ex)
{
}
});
}
});
$("form").submit(function(ev) {
$("input[type='submit']").inPosition(ev.originalEvent.x ,ev.originalEvent.y);
return false;
});
});
</script>
jQuery doesn't seem to provide that data on the submit event. Looks like the method you proposed is your best bet.
Just another solution since no other met my requirements. The advantage is, that click and keypress (enter and space) are detected.
// Detects the Events
var $form = $('form');
$form.on('click keypress', 'button[type="submit"]', function (ev) {
// Get the key (enter, space or mouse) which was pressed.
if (ev.which === 13 || ev.which === 32 || ev.type === 'click') {
// Get the clicked button
var caller = ev.currentTarget;
// Input Validation
if (!($form.valid())) {
return;
}
// Do whatever you want, e.g. ajax...
ev.preventDefault();
$.ajax({
// ...
})
}
}
This worked best for me.
With a more specific event handler and JQuery, your event object is the button clicked. You can also get the delegating form from this event if needed.
$('form').on('click', 'button', function (e) {
e.preventDefault();
var
$button = $(e.target),
$form = $(e.delegateTarget);
var buttonValue = $button.val();
});
This Doc has everything you need to get started.
JQuery Doc.
I write this function that helps me
var PupulateFormData= function (elem) {
var arr = {};
$(elem).find("input[name],select[name],button[name]:focus,input[type='submit']:focus").each(function () {
arr[$(this).attr("name")] = $(this).val();
});
return arr;
};
and then Use
var data= PupulateFormData($("form"));
In working with web components where form elements are in the shadowRoot I adapted Tobias Buschor's excellent polyfill as follows to work in the following way via an imported module. Note this only provides compatibility in evergreen clients--edge, safari, chrome, firefox. Also, as noted by Mikko Rantalainen, this doesn't follow (and I/we can update at some point to follow) https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-submit
if( !('SubmitEvent' in self && 'submitter' in SubmitEvent.prototype) ){
// polyfill SubmitEvent.submitter (a Safari issue as-of 2021)
// https://developer.mozilla.org/docs/Web/API/SubmitEvent
const submitter = Symbol.for('submitter');
Event[ submitter ] = null;
const submitterSelector = 'input[type=submit], input[type=image], input[type=button], button';
Object.defineProperty(Event.prototype, 'submitter', {
get: function(){
if('submit' === this.type){
let node = Event[ submitter ];
const form = this.target;
if(!node || !form.contains(node)){
node = form.querySelector(submitterSelector);
}
// always return a node, default as though form.submit called
return node || form;
}
return undefined;
},
set: function(value){
if('submit' === this.type){
this.submitter = value;
}
}
});
self.addEventListener('click', function polyfill_SubmitEvent_submitter_click(event){
const node = event.composedPath()[0];
const closest = node.closest?.(submitterSelector) ?? null;
Event[ submitter ] = closest;
}, true);
}
$(document).ready(function() {
$( "form" ).submit(function (event) {
// Get the submit button element
let submit_button = event.handleObj;
//submit button has the object of the use clicked button
});
}
You can obtain the button id of the following HTML code:
<form id="theForm" action="" method="POST">
<button name="sbtn" id="sbtn" value="Hey button" type="submit">Submit</button>
</form>
using the following JavaScript (leveraging on the .val() attribute):
$('#theForm').on('click', 'button', function (e) {
e.preventDefault();
var
$button = $(e.target),
$form = $(e.delegateTarget);
var buttonValue = $button.val();
});
Without jquery
submit(e){
console.log(e.nativeEvent.submitter)
}
I was finally able to find a complete and easy answer to the question : How can I get the button that caused the submit from the form submit event ?
I'll give you a simple example :
CODE HTML : The form
<form id="myForm" enctype="multipart/form-data" method="post">
...
all input, select, textarea ...
....
<button id="bt1" value="add" type="submit">Add</button>
<button id="bt2" value="back" type="submit">Back</button>
<button id="bt3" value="remove" type="submit">Remove</button>
<button id="bt4" value="register" type="submit">Register</button>
</form>
CODE JAVASCRIPT : event listener and actions
var myFctSubmit = function(event){
var myTarget = event.target || event.srcElement;
var myButton = event.originalEvent.submitter;
var balise_form = $(myTarget).attr('id');
var balise_button = $(myButton).attr('id');
//Now you know the button and
//you can apply the script you want...
//here in this exemple :
//balise_form = myForm
//balise_button = {button that you click}
}
$('#myForm').bind('submit',myFctSubmit);
Therefore, the solution to this problem is to fetch the following element :
event.originalEvent.submitter
Good luck everyone

Stop redirect in JavaScript

I have a function which verifies if some fields have been filled out (if length > 0) before submitting. If it fails to submit, I don't want to redirect the client at all. Right now, I have the following:
function onSubmit()
{
if (verify()) //This function will throw alert statements automatically
{
document.getElementById('my_form').submit();
return void(0);
}
else
{
document.getElementById('my_form').action = null;
}
}
However, it doesn't matter if verify() returns true or not, I still redirect the client and wipe her inputted fields. How do I keep the client on the page if a required field is blank? (I don't want to lose her currently filled out form...)
Also, I can't use the slick JQuery libraries, since it's not supported on some older browsers. (I'm trying to capture the most general audience.)
This is how I would try to solve this:
document.getElementById('my_form').onsubmit = function( e ){
var event = e || window.event;
// function payload goes here.
event.returnValue = false;
if ( event.preventDefault ){ event.preventDefault(); }
return false;
}
Can be used with event delegation too.
return false to the form!
<form onsubmit="return onSubmit()">
function onSubmit()
{
if (verify()) //This function will throw alert statements automatically
{
return true;
}
else
{
return false;
}
}
to stop the form from submitting, return false from your onSubmit

Prevent form submission with enter key

I just wrote this nifty little function which works on the form itself...
$("#form").keypress(function(e) {
if (e.which == 13) {
var tagName = e.target.tagName.toLowerCase();
if (tagName !== "textarea") {
return false;
}
}
});
In my logic I want to accept carriage returns during the input of a textarea. Also, it would be an added bonus to replace the enter key behavior of input fields with behavior to tab to the next input field (as if the tab key was pressed). Does anyone know of a way to use the event propagation model to correctly fire the enter key on the appropriate element, but prevent form submitting on its press?
You can mimic the tab key press instead of enter on the inputs like this:
//Press Enter in INPUT moves cursor to next INPUT
$('#form').find('.input').keypress(function(e){
if ( e.which == 13 ) // Enter key = keycode 13
{
$(this).next().focus(); //Use whatever selector necessary to focus the 'next' input
return false;
}
});
You will obviously need to figure out what selector(s) are necessary to focus on the next input when Enter is pressed.
Note that single input forms always get submitted when the enter key is pressed. The only way to prevent this from happening is this:
<form action="/search.php" method="get">
<input type="text" name="keyword" />
<input type="text" style="display: none;" />
</form>
Here is a modified version of my function. It does the following:
Prevents the enter key from working
on any element of the form other
than the textarea, button, submit.
The enter key now acts like a tab.
preventDefault(), stopPropagation() being invoked on the element is fine, but invoked on the form seems to stop the event from ever getting to the element.
So my workaround is to check the element type, if the type is not a textarea (enters permitted), or button/submit (enter = click) then we just tab to the next thing.
Invoking .next() on the element is not useful because the other elements might not be simple siblings, however since DOM pretty much garantees order when selecting so all is well.
function preventEnterSubmit(e) {
if (e.which == 13) {
var $targ = $(e.target);
if (!$targ.is("textarea") && !$targ.is(":button,:submit")) {
var focusNext = false;
$(this).find(":input:visible:not([disabled],[readonly]), a").each(function(){
if (this === e.target) {
focusNext = true;
}
else if (focusNext){
$(this).focus();
return false;
}
});
return false;
}
}
}
From a usability point of view, changing the enter behaviour to mimic a tab is a very bad idea. Users are used to using the enter key to submit a form. That's how the internet works. You should not break this.
The post Enter Key as the Default Button describes how to set the default behaviour for enter key press. However, sometimes, you need to disable form submission on Enter Key press. If you want to prevent it completely, you need to use OnKeyPress handler on tag of your page.
<body OnKeyPress="return disableKeyPress(event)">
The javascript code should be:
<script language="JavaScript">
function disableEnterKey(e)
{
var key;
if(window.event)
key = window.event.keyCode; //IE
else
key = e.which; //firefox
return (key != 13);
}
</script>
If you want to disable form submission when enter key is pressed in an input field, you must use the function above on the OnKeyPress handler of the input field as follows:
<input type="text" name="txtInput" onKeyPress="return disableEnterKey(event)">
Source: http://www.bloggingdeveloper.com/post/Disable-Form-Submit-on-Enter-Key-Press.aspx
Set trigger for both the form and the inputs, but when the input events are triggered, stop the propagation to the form by calling the stopPropagation method.
By the way, IMHO, it's not a great thing to change default behaviors to anything any average user is used to - that's what make them angry when using your system. But if you insist, then the stopPropagation method is the way to go.
In my case i wanted to prevent it only in a dinamically created field, and activate some other button, so it was a little bit diferent.
$(document).on( 'keypress', '.input_class', function (e) {
if (e.charCode==13) {
$(this).parent('.container').children('.button_class').trigger('click');
return false;
}
});
In this case it will catch the enter key on all input's with that class, and will trigger the button next to them, and also prevent the primary form to be submited.
Note that the input and the button have to be in the same container.
The previous solutions weren't working for me, but I did find a solution.
This waits for any keypress, test which match 13, and returns false if so.
in the <HEAD>
function stopRKey(evt) {
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
if ((evt.which == 13) && (node.type == "text")) {
return false;
}
}
document.onkeypress = stopRKey;
I prefer the solution of #Dmitriy Likhten, yet:
it only worked when I changed the code a bit:
[...] else
{
if (focusNext){
$(this).focus();
return false; } //
}
Otherwise the script didn't work.
Using Firefox 48.0.2
I modified Dmitriy Likhten's answer a bit, works good. Included how to reference the function to the event. note that you don't include () or it will execute. We're just passing a reference.
$(document).ready(function () {
$("#item-form").keypress(preventEnterSubmit);
});
function preventEnterSubmit(e) {
if (e.which == 13) {
var $targ = $(e.target);
if (!$targ.is("textarea") && !$targ.is(":button,:submit")) {
var focusNext = false;
$(this).find(":input:visible:not([disabled],[readonly]), a").each(function () {
if (this === e.target) {
focusNext = true;
} else {
if (focusNext) {
$(this).focus();
return false;
}
}
});
return false;
}
}
}

What is the best way to track changes in a form via javascript?

I'd like to track changes in inputs in a form via javascript. My intent is (but not limited) to
enable "save" button only when something has changed
alert if the user wants to close the page and something is not saved
Ideas?
Loop through all the input elements, and put an onchange handler on each. When that fires, set a flag which lets you know the form has changed. A basic version of that would be very easy to set up, but wouldn't be smart enough to recognize if someone changed an input from "a" to "b" and then back to "a". If it were important to catch that case, then it'd still be possible, but would take a bit more work.
Here's a basic example in jQuery:
$("#myForm")
.on("input", function() {
// do whatever you need to do when something's changed.
// perhaps set up an onExit function on the window
$('#saveButton').show();
})
;
Text form elements in JS expose a .value property and a .defaultValue property, so you can easily implement something like:
function formChanged(form) {
for (var i = 0; i < form.elements.length; i++) {
if(form.elements[i].value != form.elements[i].defaultValue) return(true);
}
return(false);
}
For checkboxes and radio buttons see whether element.checked != element.defaultChecked, and for HTML <select /> elements you'll need to loop over the select.options array and check for each option whether selected == defaultSelected.
You might want to look at using a framework like jQuery to attach handlers to the onchange event of each individual form element. These handlers can call your formChanged() code and modify the enabled property of your "save" button, and/or attach/detach an event handler for the document body's beforeunload event.
Here's a javascript & jquery method for detecting form changes that is simple. It disables the submit button until changes are made. It detects attempts to leave the page by means other than submitting the form. It accounts for "undos" by the user, it is encapsulated within a function for ease of application, and it doesn't misfire on submit. Just call the function and pass the ID of your form.
This function serializes the form once when the page is loaded, and again before the user leaves the page. If the two form states are different, the prompt is shown.
Try it out: http://jsfiddle.net/skibulk/ev5rE/
function formUnloadPrompt(formSelector) {
var formA = $(formSelector).serialize(), formB, formSubmit = false;
// Detect Form Submit
$(formSelector).submit( function(){
formSubmit = true;
});
// Handle Form Unload
window.onbeforeunload = function(){
if (formSubmit) return;
formB = $(formSelector).serialize();
if (formA != formB) return "Your changes have not been saved.";
};
// Enable & Disable Submit Button
var formToggleSubmit = function(){
formB = $(formSelector).serialize();
$(formSelector+' [type="submit"]').attr( "disabled", formA == formB);
};
formToggleSubmit();
$(formSelector).change(formToggleSubmit);
$(formSelector).keyup(formToggleSubmit);
}
// Call function on DOM Ready:
$(function(){
formUnloadPrompt('form');
});
Try
function isModifiedForm(form){
var __clone = $(form).clone();
__clone[0].reset();
return $(form).serialize() == $(__clone).serialize();
}
Hope its helps ))
If your using a web app framework (rails, ASP.NET, Cake, symfony), there should be packages for ajax validation,
http://webtecker.com/2008/03/17/list-of-ajax-form-validators/
and some wrapper on onbeforeunload() to warn users taht are about to close the form:
http://pragmatig.wordpress.com/2008/03/03/protecting-userdata-from-beeing-lost-with-jquery/
Detecting Unsaved Changes
I answered a question like this on Ars Technica, but the question was framed such that the changes needed to be detected even if the user does not blur a text field (in which case the change event never fires). I came up with a comprehensive script which:
enables submit and reset buttons if field values change
disables submit and reset buttons if the form is reset
interrupts leaving the page if form data has changed and not been submitted
supports IE 6+, Firefox 2+, Safari 3+ (and presumably Opera but I did not test)
This script depends on Prototype but could be easily adapted to another library or to stand alone.
$(document).observe('dom:loaded', function(e) {
var browser = {
trident: !!document.all && !window.opera,
webkit: (!(!!document.all && !window.opera) && !document.doctype) ||
(!!window.devicePixelRatio && !!window.getMatchedCSSRules)
};
// Select form elements that won't bubble up delegated events (eg. onchange)
var inputs = $('form_id').select('select, input[type="radio"], input[type="checkbox"]');
$('form_id').observe('submit', function(e) {
// Don't bother submitting if form not modified
if(!$('form_id').hasClassName('modified')) {
e.stop();
return false;
}
$('form_id').addClassName('saving');
});
var change = function(e) {
// Paste event fires before content has been pasted
if(e && e.type && e.type == 'paste') {
arguments.callee.defer();
return false;
}
// Check if event actually results in changed data
if(!e || e.type != 'change') {
var modified = false;
$('form_id').getElements().each(function(element) {
if(element.tagName.match(/^textarea$/i)) {
if($F(element) != element.defaultValue) {
modified = true;
}
return;
} else if(element.tagName.match(/^input$/i)) {
if(element.type.match(/^(text|hidden)$/i) && $F(element) != element.defaultValue) {
modified = true;
} else if(element.type.match(/^(checkbox|radio)$/i) && element.checked != element.defaultChecked) {
modified = true;
}
}
});
if(!modified) {
return false;
}
}
// Mark form as modified
$('form_id').addClassName('modified');
// Enable submit/reset buttons
$('reset_button_id').removeAttribute('disabled');
$('submit_button_id').removeAttribute('disabled');
// Remove event handlers as they're no longer needed
if(browser.trident) {
$('form_id').stopObserving('keyup', change);
$('form_id').stopObserving('paste', change);
} else {
$('form_id').stopObserving('input', change);
}
if(browser.webkit) {
$$('#form_id textarea').invoke('stopObserving', 'keyup', change);
$$('#form_id textarea').invoke('stopObserving', 'paste', change);
}
inputs.invoke('stopObserving', 'change', arguments.callee);
};
$('form_id').observe('reset', function(e) {
// Unset form modified, restart modified check...
$('reset_button_id').writeAttribute('disabled', true);
$('submit_button_id').writeAttribute('disabled', true);
$('form_id').removeClassName('modified');
startObservers();
});
var startObservers = (function(e) {
if(browser.trident) {
$('form_id').observe('keyup', change);
$('form_id').observe('paste', change);
} else {
$('form_id').observe('input', change);
}
// Webkit apparently doesn't fire oninput in textareas
if(browser.webkit) {
$$('#form_id textarea').invoke('observe', 'keyup', change);
$$('#form_id textarea').invoke('observe', 'paste', change);
}
inputs.invoke('observe', 'change', change);
return arguments.callee;
})();
window.onbeforeunload = function(e) {
if($('form_id').hasClassName('modified') && !$('form_id').hasClassName('saving')) {
return 'You have unsaved content, would you really like to leave the page? All your changes will be lost.';
}
};
});
I would store each fields value in a variable when the page loads, then compare those values when the user unloads the page. If any differences are detected you will know what to save and better yet, be able to specifically tell the user what data will not be saved if they exit.
// this example uses the prototype library
// also, it's not very efficient, I just threw it together
var valuesAtLoad = [];
var valuesOnCheck = [];
var isDirty = false;
var names = [];
Event.observe(window, 'load', function() {
$$('.field').each(function(i) {
valuesAtLoad.push($F(i));
});
});
var checkValues = function() {
var changes = [];
valuesOnCheck = [];
$$('.field').each(function(i) {
valuesOnCheck.push($F(i));
});
for(var i = 0; i <= valuesOnCheck.length - 1; i++ ) {
var source = valuesOnCheck[i];
var compare = valuesAtLoad[i];
if( source !== compare ) {
changes.push($$('.field')[i]);
}
}
return changes.length > 0 ? changes : [];
};
setInterval(function() { names = checkValues().pluck('id'); isDirty = names.length > 0; }, 100);
// notify the user when they exit
Event.observe(window, 'beforeunload', function(e) {
e.returnValue = isDirty ? "you have changed the following fields: \r\n" + names + "\r\n these changes will be lost if you exit. Are you sure you want to continue?" : true;
});
I've used dirtyforms.js. Works well for me.
http://mal.co.nz/code/jquery-dirty-forms/
To alert the user before closing, use unbeforeunload:
window.onbeforeunload = function() {
return "You are about to lose your form data.";
};
I did some Cross Browser Testing.
On Chrome and Safari this is nice:
<form onchange="validate()">
...
</form>
For Firefox + Chrome/Safari I go with this:
<form onkeydown="validate()">
...
<input type="checkbox" onchange="validate()">
</form>
Items like checkboxes or radiobuttons need an own onchange event listener.
Attach an event handler to each form input/select/textarea's onchange event. Setting a variable to tell you if you should enable the "save" button. Create an onunload hander that checks for a dirty form too, and when the form is submitted reset the variable:
window.onunload = checkUnsavedPage;
var isDirty = false;
var formElements = //Get a reference to all form elements
for(var i = 0; len = formElements.length; i++) {
//Add onchange event to each element to call formChanged()
}
function formChanged(event) {
isDirty = false;
document.getElementById("savebtn").disabled = "";
}
function checkUnsavedPage() {
if (isDirty) {
var isSure = confirm("you sure?");
if (!isSure) {
event.preventDefault();
}
}
}
Here's a full implementation of Dylan Beattie's suggestion:
Client/JS Framework for "Unsaved Data" Protection?
You shouldn't need to store initial values to determine if the form has changed, unless you're populating it dynamically on the client side (although, even then, you could still set up the default properties on the form elements).
You can also check out this jQuery plugin I built at jQuery track changes in forms plugin
See the demo here and download the JS here
If you are open to using jQuery, see my answer a similar question:
Disable submit button unless original form data has changed.
I had the same challenge and i was thinking of a common solution. The code below is not perfect, its from initial r&d. Following are the steps I used:
1) Move the following JS to a another file (say changeFramework.js)
2) Include it in your project by importing it
3) In your html page, whichever control needs monitoring, add the class "monitorChange"
4) The global variable 'hasChanged' will tell, if there is any change in the page you working on.
<script type="text/javascript" id="MonitorChangeFramework">
// MONITOR CHANGE FRAMEWORK
// ALL ELEMENTS WITH CLASS ".monitorChange" WILL BE REGISTERED FOR CHANGE
// ON CHANGE IT WILL RAISE A FLAG
var hasChanged;
function MonitorChange() {
hasChanged = false;
$(".monitorChange").change(function () {
hasChanged = true;
});
}
Following are the controls where I used this framework:
<textarea class="monitorChange" rows="5" cols="10" id="testArea"></textarea></br>
<div id="divDrinks">
<input type="checkbox" class="chb monitorChange" value="Tea" />Tea </br>
<input type="checkbox" class="chb monitorChange" value="Milk" checked='checked' />Milk</br>
<input type="checkbox" class="chb monitorChange" value="Coffee" />Coffee </br>
</div>
<select id="comboCar" class="monitorChange">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<button id="testButton">
test</button><a onclick="NavigateTo()">next >>> </a>
I believe there can be huge improvement in this framework. Comment/Changes/feedbacks are welcome. :)

Categories

Resources