Select all options in multiple select before submitting form - javascript

I've created a widget with two html multiple selects - "available" and "selected". User choose items from "available" and they are displayed in "selected", pretty simple stuff. I'monly interested in "selected" values (the other one simply doesn't have a name attribute) but for it to send all values they have to be selected.
I tried to select them all in jQuery "submit" event but for some reason it doesn't work. I can see they are all visualy selected before the form is sent but the data itself is not sent.
var form = this.$selectedSelect[0].form;
$(form).on('submit', function(e) {
this.$selectedSelect.find("option").prop("selected", true);
}.bind(this));
I'd like to avoid creating hidden fields for each "selected" entry.

You should prevent the original submit process and invoke a new one after selecting all items like this:
var form = this.$selectedSelect[0].form;
$(form).submit(function(e) {
e.preventDefault();
this.$selectedSelect.find("option").prop("selected", true);
this.submit();
});
UPDATE:
You don't even need to prevent the default vehaviour, the following sinmple solution is already sufficient:
var form = this.$selectedSelect[0].form;
$(form).submit(function(e) {
this.$selectedSelect.find("option").prop("selected", true);
});

you need something like this
<script>
$(document).ready(function() {
$("form").on("submit",function(eve){
eve.preventDefault();
$("select#someSelectId").find("option").prop("selected", true);
$(this).submit();
})
})
</script>

Related

Change event to check change on any form element

I have a from with disabled button, which gets enabled when the form is valid. With the function below I'm checking for changes and it works if the form consists only of inputs. How can I check for change on other elements like select or checkbox?
$("#create-rule-form").parsley();
$('input').on('keyup', function() {
$("#create-rule-form").parsley().validate();
if ($("#create-rule-form").parsley().isValid()) {
$('#create-rule-btn').prop('disabled', false);
} else {
$('#create-rule-btn').prop('disabled', 'disabled');
}
});
Use jQuery's :input selector, it matches all tags that are used for form input.
$(":input").on('edit change').function() {
// code here
});
You can use $('form').find('*') to select all of the form's children and grandchildren, and then apply the event to all of them like below.
Also, on a side note, I believe the event you should handle is change instead of keyup, as keyup will not work with checkboxes and dropdowns.
$('form').find('*').on('change', function() {
//do stuff
});

Disable button on form submission but post button value

I want to prevent multiple form submissions, but I need to have the value of the submit element posted back to the server (so that I know which button the user clicked on).
Most of the Internet Wisdom concerning suppression of multiple form submissions seems to involve disabling the submit button during form submission. This prevents the button from being clicked a second time, but also prevents its value from being posted.
I've found a few examples of JS code that hides the submit button(s), which allows their values to be posted. But those examples all replace the (now hidden) button with some sort of "processing..." message. I really want a solution that presents the user with a disabled button but still posts the button value.
I should add that I'd prefer a solution that works with standard HTML one would find in most forms. No magic IFrames, hidden fields, id or class names, etc. I want a JS function I can stash away in a library and reference from all of my existing forms to enable this new behavior.
(I have a solution, which I will post as an answer. But I had to ask the question to comply with the Zen of SO.)
Here is (yet another) answer to the question of how to deal with preventing the user from clicking on the form submission button more than once. This solution makes it appear that the button has been disabled.
Under the covers, it creates a disabled button to display to the user, and hides the actual button so that its value is posted. I also move the hidden button so that the extra element doesn't mess up CSS selectors.
Also note the check for invalid form fields. If you omit this check, and form validation fails, then the user winds up with a form that wasn't posted (because client-side validation failed) but the buttons are disabled.
// Disables buttons when form is submitted
$('form').submit(function () {
// Bail out if the form contains validation errors
if ($.validator && !$(this).valid()) return;
var form = $(this);
$(this).find('input[type="submit"], button[type="submit"]').each(function (index) {
// Create a disabled clone of the submit button
$(this).clone(false).removeAttr('id').prop('disabled', true).insertBefore($(this));
// Hide the actual submit button and move it to the beginning of the form
$(this).hide();
form.prepend($(this));
});
});
Because you can submit a form other ways than simply clicking the submit button it's better to add a listener to the form's submit event rather than the click event on the submit button. This jQuery event listener should work on any form and prevent it from being submitted more than once.
$('form').on('submit', function(e) {
if (!$(this).data('submitted')) {
$(this).data('submitted', true);
}
else {
e.preventDefault();
}
});
To make the form look disabled you could add some css that makes the form look disabled and then add the classname on form submission.
$('form').on('submit', function(e) {
if (!$(this).data('submitted')) {
$(this).data('submitted', true).addClass('disabled');
}
else {
e.preventDefault();
}
});
I wanted to stop the user from causing multiple form submissions by double clicking the submit button or hitting the enter key twice. I like this solution, because it doesn't require a hidden form field or hiding the submit button.
The two key points are:
Return true/false instead of using e.preventDefault() and form.submit(), because form.submit() doesn't know which button was clicked and therefore, can't pass the button name/value.
Disable the button with pointer-events: none; instead of disabled="disabled", because the disabled attribute won't send the button name/value. I believe pointer-events: none; is not supported by Internet Explorer 10 or below.
javascript/jquery code:
var form_selector = 'form',
button_selector = 'button, input[type=submit], input[type=button], input[type=reset]',
deactivated_classname = 'state-submitting',
deactivated_class = '.'+'state-submitting';
// Capture the submit event so it will handle both the
// enter key and clicking the submit button.
$(document).on('submit', form_selector, function(e) {
var form = e.target,
buttons = $( form ).find( button_selector );
// Returns, because the form is already being submitted by a previous attempt.
if( $( form ).find( deactivated_class ).length > 0 ) return false;
disableButtons( buttons );
// Safari (version 11) bugfix: Safari needs a timeout or it won't
// show the deactivated styles.
setTimeout(function() {
// Must use return true, because using form.submit(), won't pass the button value.
return true;
}, 50 );
});
function disableButtons( buttons ) {
// Disables all buttons in the form.
$( buttons ).each(function( index, elem ) {
$( elem ).addClass( deactivated_classname );
});
}
For AJAX forms, you will want to re-enable the buttons after the response is returned.
$( document ).on( 'ajax:complete', form_selector, function(e) {
var form = e.target,
buttons = $( form ).find( button_selector );
enableButtons( buttons );
});
function enableButtons( buttons ) {
$( buttons ).each(function( index, elem ) {
$( elem ).removeClass( deactivated_classname );
});
}
CSS:
// The button is disabled while it is submitting.
.state-submitting {
// Turns off hover and click events. Not supported in IE 10 and below.
pointer-events: none;
opacity: 0.5;
}
You can simulate disabled look behavior. E.g. if you have a button like this:
<input id="btn" type="button" onclick="disableMe(this)" value="Submit" />
You can define CSS like this
.disabled {
backround-color:grey;
color:darkgrey;
}
And JS like this
function disableMe(btn) {
btn.className = "disabled";
btn.onclick = function(){return false}
}
What will happen - on first click button will become grey (via applied CSS) and onclick event will change to "return false" for all the consecutive calls preventing future click actions. The button will appear and act as disabled, but will not be, so it will not prevent button submission.
Here's a couple options:
1. You could create hidden inputs and dynamically change the value of it before the form is submitted either onClick or onHover of the said button:
2. You could create an hidden iframe which is the target of the said form. Once the submit button is click, you could cancel the submit event, grab all of the data and send it programatically through the iframe instead.
I was having the same issue as OP, and I found that disabling the submit button(s) after a short (maybe 0 seconds) timeout via setTimeout does the trick. The submit button's name value is still posted with the rest of the form data as desired, but the button disables itself (almost) immediately, preventing further clicks.
The timeout is a bit ugly, but it seems preferable to more elaborate swapping/covering schemes.
This could be combined with also altering the form's onsubmit property for extra precaution, but I'm not doing that in the example below for clarity's sake. Either way, I like the appearance/behavior of a disabled button after the first submission click… the user experience seems better to me… it's more clear what's happening.
My form element's start tag:
<form onsubmit="return formSubmit(this);" method="post" action="">
In my JavaScript (sorry, I'm not up-to-date with the latest JS tech like jQuery, etc, so I'm posting this in old-fashioned-native-JavaScript-5-with-no-dependencies-compatible code):
function formSubmit(form) {
// MUST DELAY so as not to break input/button[type=submit] name submission
setTimeout(function () {
var els = form.elements;
for (var i = 0; i < els.length; i++) {
var el = els[i];
if (el.getAttribute('type') == 'submit') {
el.setAttribute('disabled', 'disabled');
}
}
}, 0);
return true;
}
I think better solution would be to use JQuery :
<form onsubmit="$('#submit').hide();" method="post" action="">
No chance of double clicking.
Sometimes we use name field in submit button for validation so if this is disabled then that could failed.
Using .hide() the button will be hidden.
so no chance of double clicking it.
Be honest with you I was not able to understand fully most of the posts on this page, but I think I have faced this problem before, and solved it by allowing the page to post the first time the button is clicked, so when the page comes back from server it has the new value assigned to it, and it looks clickable, and enabled. But if a 2nd attempt is made to press it, then it becomes disabled, and page will not post, and send to the server again by clicking this button. I hope this helps:
#section scripts
{
<script type="text/javascript">
$('#edit').click(function () {
if (document.getElementById("edit").value == '') {
// This portion should execute onlythe
// first time button is clicked, and it
// will assign a new value to the button,
//and posts the value
//to the server
}
else {
edit.disabled = true;
}
});
</script>
}
A much much much simpler way is to enclose whatever code you use to disable the button in a setTimeout() with 0 delay. That way the button is still enabled in the thread that handles the form submission while another parallel thread is spawned to do the disabling.
Example (using jQuery):
<form method="POST" onsubmit="javascript:setTimeout(() => $('*[type=submit]', this).attr('disabled', 'disabled'), 0)">

Disable Submit button if none of selector options is selected

I would like to disable the Submit button on a search form that only contains select dropdowns. There are several similar questions here but I most of them deal with fields. The closest thing to my case is Disable submit button if all three of three specific dropdown fields are empty. I modified the solution supplied in JSFiddle to feature an empty option, and did get it working -- but only in JSFiddle, not on my page.
I use the same code from the proposed answer (only changed IDs):
$('#submit').attr('disabled','disabled');
$('select').change(function(){
if ( $(this).hasClass('require_one') ){
$('#submit').removeAttr('disabled');
}
});
$('#submit').click(function() {
$('#searchform').submit();
});
I add the above code right after I include the jquery.js (v. 1.9.1).
I generate the form dynamically, but in JSFiddle I use exactly what is seen in the page source: http://jsfiddle.net/cheeseus/d5xz6aw8/8/
I have no idea why I can't get it to work on the actual page, hope those more knowledgeable can help sort it out.
And, if possible, I would also like the Submit button to be disabled again if all three selects are set to blank values again.
I usually don't like using the ID(3) for CSS selector since you can have only one ID selector with that name on the document and there might be another element already with the same ID. How about using the class hierarchy instead to pinpoint the button element?
In any case you need to re-check the count everytime what you select on what is empty:
var $submitButton=$('.selector .btn');
var $selectors=$('.selector select.require_one');
$submitButton.attr('disabled','disabled');
$('.selector select.require_one').change(function(){
var $empty=$selectors.filter(function() { return this.value == ""; });
if ( $selectors.filter(function() { return this.value == ""; }).length == $selectors.length ){
$submitButton.attr('disabled','disabled');
} else
{
$submitButton.removeAttr('disabled');
}
});
$submitButton.click(function() {
$('#searchform').submit();
});
JSFiddle code here
You can just use a simple count to see if you should display the button or not. Here is jQuery code.
var count = 0;
$('.require_one').change(function() {
count++;
if (count >= 3) {
$('#submit').removeAttr('disabled');
}
});
$('#submit').attr('disabled','disabled');
I think this is because you didn't check is your document ready.
I added few improvements:
caching jquery object in variables, makes your code a bit faster (you don't look for it everytime select is beeing changes).
used recommended way of binding events - 'on' function
'disabled' is property not an attribute, jQuery has dedicated method to use
on select change - check all selects if there is any not selected, it there is - set prop disabled to true, otherwise set false.
instead of disabling submit at initialization, trigger same action you do when selected is beeing changed (if you start with option selected in all select initial state won't be disabled).
$(document).ready(function () {
var $submit = $('#submit');
var $selects = $('select.require_one');
$submit.on("click", function() {
$('#searchform').submit();
});
$selects
.on("change", function(){
var $not_selected = $selects.filter(function() {
return !$(this).val();
});
$submit.prop('disabled', $not_selected.length ? true : false);
})
.first()
.triggerHandler('change');
});

Live data not submitting using MVC 4.5 unobtrusive validation

We have a form where a user can move items from one multi-select box to another. We are using MVC 4.5 and jquery validate with Microsoft's unobtrusive javascript.
The problem is, when submitting the form, the values within the select boxes don't get submitted because the user doesn't know after moving items that they have to also select all those items for submission.
So the solution sounds easy: use jquery to select all items upon submit.
After doing some research (thanks stackoverflow community), we were able to discover the necessary jquery code to intercept the submit process. However, the problem arises in that when the code selects the items, only pre-existing items in a select box are selected. Live (dynamic) items that have been moved do not get selected.
Here is the code that we first used:
$('#UserProfileForm').bind('invalid-form.validate',function(){
$(this).find('.selectbox option').each(function (i) {
$(this).attr("selected", "selected");
});
});
We discovered that using bind doesn't work but live should:
$('#UserProfileForm').live('invalid-form.validate',function(){
$(this).find('.selectbox option').each(function (i) {
$(this).attr("selected", "selected");
});
});
However, we are using jquery 1.9 and the live function has been removed. It has been replaced with this:
$(document).on('invalid-form.validate', 'form', function () {
$(this).find('.selectbox option').each(function (i) {
$(this).attr("selected", "selected");
});
});
However, this still doesn't work. So I replaced the selection function with an alert to see if it works at all:
$(document).on('invalid-form.validate', 'form', function () {
alert('test');
});
An alert does not pop up. Any ideas?
ADDITIONAL INFO
For those wondering why I'm referencing invalid-form.validate is because I am testing with invalid form data. The same scenario would apply if it was valid form data. I just haven't gotten to the point on how to bind live data to the valid form submission process either.
After inspecting the elements, I noticed that the jquery was adding the selected attribute to the options. However, the options weren't highlighted. This had me thinking that maybe the jquery call to add the selected attribute was wrong.
After some experimentation, I discovered that it was wrong. It appears that if you use the attr function of jquery, it doesn't actually set the option to selected in the DOM. Using the prop function does.
Here is the code:
$(document).on('submit', 'form', function (e) {
$(this).find('.selectbox option').each(function (i) {
$(this).prop("selected", true);
});
});
This allows the form to select all options as selected upon form submission whether the submit handler is valid or not. If you just want to select based on invalid info, use this:
$('form').bind('invalid-form.validate', function () {
$(this).find('.selectbox option').each(function (i) {
$(this).prop("selected", true);
});
});
Enjoy!

How to find the submit button in a specific form in jQuery

I try to get jQuery object of a submit button in a specific form (there are several forms on the same page).
I managed to get the form element itself. It looks something like this:
var curForm = curElement.parents("form");
The current Element has the context HTMLInputElement. The several techniques I tried to get the according submit element of the form:
var curSubmit = curForm.find("input[type='submit']");
var curSubmit = $(curForm).find("input[type='submit']");
var curSubmit = curForm.find(":submit");
var curSubmit = $(curForm).find(":submit");
var curSubmit = $(curSubmit, "input[type='submit']");
the result is always the same (and very strange). The result that I get is the same element as "curElement".
So how can I get the right submit button?
The following should work:
var submit = curElement.closest('form').find(':submit');
This should work:
var curSubmit = $("input[type=submit]",curForm);
EDIT: Note the missing ' in the selector
Using plain javascript (without relying on jquery):
var curSubmit = curForm.querySelector('button[type="submit"]');
This works for me:
var curSubmit = $("input[type=submit]",this);
where this mean current form submitted
for ex. to get the name of submitted button and all inputs submitted
$( "form" ).on( "submit", function( event ) {
event.preventDefault();
var data = $(this).serialize(); //all input variables
console.log(data); //print data in console
var submit = $("input[type=submit]",this).attr('name');
alert(submit); // name of submit button
});
Because a HTML5 submit button may be out of form tag http://www.w3.org/TR/html-markup/input.submit.html#input.submit.attrs.form, you can use the following code to find it:
$(curElement.closest('form').get(0).elements).filter(':submit')
In case you want to find the submit button of the form after it was submitted, you may find the following useful ... I use it to disable the submit button after the form was submitted to prevent multiple clicks.
$("form").submit(function () {
if ($(this).valid()) { // in case you have some validation
$(this).find(":submit").prop('disabled', true);
$("*").css("cursor", "wait"); // in case you want to show a waiting cursor after submit
}
});
BTW: Last selector looks weird. It selects each curSubmit(hm?) in every input[type=submit] tag. May be you mean var curSubmit = $("input[type=submit]", curForm);

Categories

Resources