<input type="checkbox" name="Package1" value="packagename">
<input type="checkbox" name="Package2" value="packagename">
<input type="checkbox" name="Package3" value="packagename">
How to make any two checkboxes required for the user to submit the form. The user should not be able to submit the form unless he has checked atleast two checkboxes?
How to achieve that?
Rename checkboxes to name=package[] and values 1, 2, 3.
Then in PHP you'll have o condition (if you send form with GET method, just change POST to GET):
if (isset($_POST['package']) && count($_POST['package']) >= 2) {/* continue */}
If you want to validate it in browser (JS), than:
<script>
var i = 0;
$('[type="checkbox"]').each(function() {
if ($(this).is(':checked')) {
i++;
}
});
if (i <= 1) {
return false; // disable sending form when you've checked 1 checkbox in maximum
}
</script>
Add a class that refers only these checkboxes and then count how many are checked.
A quick and dirty way to validate the checkboxes using JavaScript:
JavaScript
checkCheckboxes = function() {
var numberOfCheckedCheckboxes = 0;
var checkbox1 = document.getElementsByName("Package1")[0];
var checkbox2 = document.getElementsByName("Package2")[0];
var checkbox3 = document.getElementsByName("Package3")[0];
if (checkbox1.checked)
{
numberOfCheckedCheckboxes++;
}
if (checkbox2.checked)
{
numberOfCheckedCheckboxes++;
}
if (checkbox3.checked)
{
numberOfCheckedCheckboxes++;
}
alert(numberOfCheckedCheckboxes >= 2);
}
DEMO: JSFiddle
This code isn't the cleanest block of code, however it does get the job done, and will return true if there are at least 2 checkboxes checked, and will return false otherwise. To make it cleaner, you can change the name value of each checkbox to the same name, such as "packages", and then use document.getElementByName("packages"), then use a for-each loop to loop through each element and check its checked state (I would provide a demo in JSFiddle or JSBin, however it seems that Google Chrome is blocking the script in that case). Using the for-each implementation would allow you to use the same amount of code, regardless of the number of checkboxes.
In HTML, you cannot.
You can impose restrictions in client-side JavaScript or in server-side processing of form data, or both. As usual, client-side restrictions are inherently unreliable and should be regarded as convenience to the user, not a reliable method of doing anything. Server-side processing depends on the server-side technology used.
Related
Does anyone know if it's possible to add a plus sign in a html input type=number field? I have a scenario whereby users need to enter a modifier value which is either +1 to +10 or -1 to -10. I want to make it very explicit to the user that their inputted value increments the resulting value. therefore it would be great if a + sign is prepended to a positive inputted value.
I'm using this input in an Angular2 reactive form with bootstrap styling. so an Angular2 directive, a boostrap style or even a jquery solution are welcome
What I've seen so far is about adding currency symbols inside the form control or about adding + and minus buttons to increment and decrement the value. But that's not what I want, so I doubt if this is possible at all.
I don't think it is possible to manipulate the input.
The default behavior is "-" for negative and no sign for positive numbers.
Even if you checked some custom UI frameworks like:
JQuery UI, Bootstrap, Angular Material ... you will not get the wished behavior.
I guess the only solution for this is to write your own custom code.
Two scenarios are possible:
1- An input with Text and the manipulating will be done in Javascript.
2- Create a pipe in angular2 and give it to the element which I think is much easier than the first one.
No it's not possible. The number field only accepts -, 0-9 and e to be entered. As a workaround you could place the + in the HTML before the input, eg:
+ <input type="number" />
Alternatively you could use a standard type="text" input, but that would mean creating your own validation logic which would make the code much more complex.
I hope this will help on you guys!!
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).on('keypress','#input',function (e) {
var keyCode = e.which;
if ($(this).val().trim().charAt(0) == "\u002B") {
if ( keyCode == 43 ) {
return false;
}
}
else{
for (var i = 1; i < $(this).val().length+1; i++) {
if(i!=0){
if ( keyCode == 43 ) {
return false;
}
}
}
}
});
$(document).on('input', '#input', function() {
this.value = this.value.replace(/[^+{1}|^0-9]/g,'');
});
</script>
I have a web app I am writing and wanted updates to write back to the server real time. On the client side I have this function running and capturing each input. The inputs are currently all checkboxes. The problem is that I can check the boxes faster than the script works on them and therefore end up with unexpected results. So I need to slow the user down between selections or make sure each server call completes before the next one begins. How do I do this?
This is the start of the client side script section. There are other functions such as the success and failure handlers.
<script>
$("form").change(function(e) {
if (e.target.type && e.target.type === 'checkbox') {
//A checkbox was changed, so act on it
var name = e.target.value.substr(0,e.target.value.lastIndexOf("_"));
var position = e.target.value.substr(e.target.value.lastIndexOf("_") + 1);
var passArray = [name, position];
if (e.target.checked) {
//Add the value to the person's Assigned Position
google.script.run.withSuccessHandler(editChangeReturnedFromServer).withFailureHandler(editFailed).setWSAssignedPosition(passArray);
} else {
//Remove the value from the peson's Assigned Position
google.script.run.withSuccessHandler(editChangeReturnedFromServer).withFailureHandler(editFailed).clearWSAssignedPosition(passArray);
}
return;
}
...(other functions)...
</script>
If the user checks boxes quickly, the calls to the server side setWSAssignedPosition() function seem to cross or even duplicate, as all the correct values are not added to the spreadsheet OR multiple copies of the same are added. If I slow the end user down with alert('I am changing that'); right before the google.script.run... line then all works fine. I actually watched as one line in the spreadsheet was replaced with an entry that came later. But that was intrusive and quickly became annoying.
I am not interested in a Submit or Apply button. I really want this to happen on the fly.
The server side function is:
//Set the Assigned Position for the person passed to the function
function setWSAssignedPosition(passedArray){
var name = passedArray[0];
var position = passedArray[1];
//Get the entries from the filled out Position Requests in the appropriate sheet
var validWSRequests = getValidWSRequests();
var foundWSRequest = false;
for (i in validWSRequests) {
if (validWSRequests[i].participantName === name){
ws_sheet.getRange(validWSRequests[i].sheetrow + 2 , ws_headers[0].indexOf("Assigned Position") + 1).setValue(position);
foundWSRequest = true;
break;
}
}
if (!foundWSRequest) {
var WSOthersAssigned = getRowsData(ws_norequests_sheet);
var WSOthersAssigned_headers = ws_norequests_sheet.getRange(1, 1, 1, ws_norequests_sheet.getLastColumn()).getValues();
//Get the first empty row on the sheet for those who didn't fill out the form in case we need it.
var firstEmptyRow = getFirstEmptyRowWholeRow(ws_norequests_sheet);
if (WSOthersAssigned.length < 1){
//No records exist at all, so add the first
ws_norequests_sheet.getRange(firstEmptyRow, WSOthersAssigned_headers[0].indexOf("Assigned Position") + 1).setValue(position);
ws_norequests_sheet.getRange(firstEmptyRow, WSOthersAssigned_headers[0].indexOf("PARTICIPANT NAME") + 1).setValue(name);
}else {
for (i in WSOthersAssigned){
var seeme = i;
if (WSOthersAssigned[i].participantName === name) {
//Found a record so edit it
ws_norequests_sheet.getRange(WSOthersAssigned[i].sheetrow + 2 , WSOthersAssigned_headers[0].indexOf("Assigned Position") + 1).setValue(position);
break;
} else {
//No record found, so append it
ws_norequests_sheet.getRange(firstEmptyRow, WSOthersAssigned_headers[0].indexOf("Assigned Position") + 1).setValue(position);
ws_norequests_sheet.getRange(firstEmptyRow, WSOthersAssigned_headers[0].indexOf("PARTICIPANT NAME") + 1).setValue(name);
break;
}
}
}
}
// This didn't help
// SpreadsheetApp.flush();
return [name, true, position];
}
ws_norequests_sheet and ws_norequests_sheet are defined globally to get the appropriate sheet in the spreadsheet where these items are stored. Depending on the initial source, the data is saved in one of two sheets. I am currently testing where all the data is going into the second sheet as these checkboxes are all stacked on top of each other and therefore quickly accessed
That's the nature of asynchronous server calls. You always need to be mindful that the calls may not return in the same order in which you sent them. You always need to take care and use the success and failure callbacks to properly respond.
There are several ways to deal with your issue (in the way that you want) and most involve preventing the user from triggering the change action on the form's elements and then allowing them to do so only after the server calls return.
One of the simpler ways would be to disable the form elements on change and the re-enable them in your callbacks.
So first disable them on change:
$("form").change(function(e) {
if (e.target.type && e.target.type === 'checkbox') {
$("input[type=checkbox]", "form").attr("disabled", "disabled");
//Your change code here
}
}
Then in both your success and fail handlers, re-enable them:
function editChangeReturnedFromServer(response) {
//your code here to work with server data
$("input[type=checkbox]", "form").removeAttr("disabled");
}
function editFailed(error) {
//your code here to handle error
$("input[type=checkbox]", "form").removeAttr("disabled");
}
Other options would be to use something like jQuery UI to create a modal dialog that would prevent the user from clicking options, which you could destroy on success. This is nice as it very clearly indicates to the user that something is happening where disabling inputs may not be as obvious to them.
Basically, you need to ensure that the user cannot trigger another change until the previous one has completed. Alternatively, you could in theory user a global variable to track the unprocessed checkbox values and another to track if a server call is in progress, but this is a lot of complexity for such a simple thing.
To be frank though, I don't really agree with your approach from a UI perspective. The expected behaviour of a checkbox is that it collects a user's input and only sends that to a server when a submit button is clicked. As an end user, I would expect to wait when 'submitting' something, but not when checking a box. Having to wait any amount of time (even fractions of a second) would personally annoy me. I would much rather check several options and wait for a longer submit.
Depending on what's actually being done with the return values, a more elegant solution might be to take care of the actions on the client side immediately without involving the server. Only sending it data once the user has finished their selections.
For example, if checking one box should show the user 3 inputs, you could:
$("#check1").click(function(){
$(".showOnCheck1").toggle(this.checked);
});
.showOnCheck1 {display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
<input type="checkbox" id="check1" value="check1"><label for="check1">Check box 1</label>
</p>
<p class="showOnCheck1">
<label for="text1">Text Box 1</label><input type="text" id="text1">
</p>
<p class="showOnCheck1">
<label for="text2">Text Box 2</label><input type="text" id="text2">
</p>
<p class="showOnCheck1">
<label for="text3">Text Box 3</label><input type="text" id="text3">
</p>
As you can see with the above, there's no delay at all and no need to slow the user down or wait for the server, but it does depend on what you're doing with the response. The more logic you can put on the client side, the less the user has to wait for the server.
I have created a form in HTML/CSS on my website.
Now, my idea is to give out links that would contain some string (basically like an affiliate link) and would like that string to be entered in a hidden form field to be submitted, or somehow else, have that string in the submitted data.
is there an easy way to do this?
There are two ways of approaching this, both of which use a GET variable in the link you distribute.
First off, let's assume that--for example's purpose--your special string is abc123. You would then distribute a link that follows the form http://example.com/my/form/?affiliate=abc123.
Assuming that, here are two solutions, one in PHP and another in Javascript.
PHP Solution
This one is fairly easy, as long as you're just setting a hidden field.
<input type='hidden' name='affiliate' value='<?= htmlspecialchars($_GET['affiliate'], ENT_QUOTES, 'UTF-8'); ?>' />
Update: Added htmlspecialchars() call to escape any input, to prevent security issues with users setting the GET variable manually.
Javascript Solution
HTML
<input type='hidden' id='affiliate-input' name='affiliate' />
Javascript
This solution relies on jQuery. If you want a pure JS solution, let me know.
var $_GET = {};
// When the page loads, set the input value
$(document).ready(function(){
setupGetVariables();
var affiliateId = $_GET["affiliate"];
$("#affiliate-input").val(affiliateId);
});
function setupGetVariables()
{
if(document.location.toString().indexOf('?') !== -1) {
var query = document.location
.toString()
// get the query string
.replace(/^.*?\?/, '')
// and remove any existing hash string (thanks, #vrijdenker)
.replace(/#.*$/, '')
.split('&');
for(var i=0, l=query.length; i<l; i++) {
var aux = decodeURIComponent(query[i]).split('=');
$_GET[aux[0]] = aux[1];
}
}
}
The setupGetVariables() method was helped by this answer.
On my website I have a reservation forum,
and I put that the person cannot submit the forum unless submitting their name and phone number.
<p><label>Phone #:<input type="text" id="phone" name="phone" placeholder="###-###-####" style="margin:10px; width:100px; height:15px" required>
It works perfect on every device besides any mobile device using safari, so I wanted to know what code can I use so it can work on all devices.
Any input/help/advice would be appreciated.
Mobile Safari validation isn't really up to par compared to all the other browsers. You can check out feature support by going to Can I use. What I would do to fix this issue is grab Modernizr.js or use some other feature detection to find out if form validation is supported. If it isn't, then just put it in a little JS snippet saying that the field is required.
Something like this should do if you use Modernizr.js and select "Input Attributes" under HTML5.
var jsRequired;
if (!Modernizr.input.required) {
jsRequired = true;
}
Then on the form submission:
$('#form-submit').on('click', (function(evt) { // this is the form submit button
evt.preventDefault(); // preventing reload of the page
if (jsRequired == true) {
var requiredInputs = $('input[required]');
for (var i = 0; i < requiredInputs.length; i++) {
if (requiredInputs[i].value == '') {
$('#submission-info').text('Whoa whoa whoa, you missed one...');
// highlight the missed one by adding a class
requiredInputs[i].className += " submission-error";
return false; //; stop the rest of the submission
}
}
}
var formData = $('form#contact-form').serialize(); // serialize data
$.ajax({
url: 'mail.php', // rename this to your php file
type: 'POST',
data: formData
}).done(function(response) {
// do stuff to to show the user that the form was submitted
$('#submission-info').text('Success, your information has been sent to us (and the NSA of course) and we will reply to you as soon as possible.');
}).fail(function(response, error) {
// tell the user what happened that caused the form submission to fail
$('#submission-info').text('Oh no, something happened. Maybe try again?');
});
});
Some of the code should be changed around to fit your stuff but otherwise it should be in the general direction of what you are looking to do.
Imagine you have a form where you switch visibility of several fields. And if the field is not displayed you don't want its value to be in request.
How do you handle this situation?
Setting a form element to disabled will stop it going to the server, e.g.:
<input disabled="disabled" type="text" name="test"/>
In javascript it would mean something like this:
var inputs = document.getElementsByTagName('input');
for(var i = 0;i < inputs.length; i++) {
if(inputs[i].style.display == 'none') {
inputs[i].disabled = true;
}
}
document.forms[0].submit();
In jQuery:
$('form > input:hidden').attr("disabled",true);
$('form').submit();
You could use javascript to set the disabled attribute. The 'submit' button click event is probably the best place to do this.
However, I would advise against doing this at all. If possible you should filter your query on the server. This will be more reliable.
What about:
$('#divID').children(":input").prop("disabled", true); // disable
and
$('#divID').children(":input").prop("disabled", false); // enable
To toggle all children inputs (selects, checkboxes, input, textareas, etc) inside a hidden div.
If you wanna disable all elements or certain elements within a hidden parent element, you can use
$("div").filter(":hidden").children("input[type='text']").attr("disabled", "disabled");
This example http://jsfiddle.net/gKsTS/ disables all textboxes within a hidden div
One very simple (but not always the most convenient) solution is to remove the "name" attribute -- the standard requires that browsers not send unnamed values, and all browsers I know abide to this rule.
I would either remove the value from the input or detach the input object from the DOM so it doesn't exist to be posted in the first place.
What I did was just remove the elements entirely when the form is submitted:
var myForm = document.getElementById('my-form')
myForm.addEventListener('submit', function (e) {
e.preventDefault()
var form = e.currentTarget
var hidden = form.getElementsByClassName('hidden')
while (hidden.length > 0) {
for (var i = 0; i < hidden.length; i++) {
hidden[i].remove()
}
}
form.submit()
})