Showing hidden form field when specific URL is passed - javascript

I have a form that is populated dynamically using URL parameters. The problem is that one of the parameters in the URL selects an option in a dropdown, which should then show a field. That field is not showing on page load.
Note that I have a simple check on page load that should show the field, so I am wondering if URL parameters are passed after the document.ready state.
Here is the URL that I am using:
https://donate.globaltc.org/#designation=3&missionary=Jerry%20Nance
The dropdown is selecting the correct option.
Here is my JS:
// Show or hide field
var $missionary = $('.missionary');
var $designation = $('#designation');
var $project = $('.project');
if($designation.val() != 3){
$missionary.hide();
} else {
$missionary.show();
}
// Handle URL parameters
var hashParams = window.location.hash.substr(1).split('&'); // substr(1) to remove the `#`
for(var i = 0; i < hashParams.length; i++){
var p = hashParams[i].split('=');
document.getElementById(p[0]).value = decodeURIComponent(p[1]);
}
HTML Form:
<div class="form-group col-sm-6">
<label for="exampleInputEmail1">How would you like this gift to be designated?</label>
<select class="form-control" id="designation" name="designation">
<option value="1" selected="selected">Most Urgent Need</option>
<option value="3">A Global Team Member</option>
</select>
</div>
<div class="form-group col-sm-6 missionary">
<label for="missionary">Name of Team Member</label>
<input type="text" class="form-control" id="missionary" name="missionary">
</div>

I found an error in my code, but it did not solve my issue. The error:
if($designation.val() != 3){ //Should be string not int
Here is the hacky way that I made this work.
setTimeout(function(){
if($designation.val() == '3'){
$missionary.show();
} else {
$missionary.hide();
}
}, 100);
I would still like a more definitive answer on why this is happening.

You can use var designationValue = parseInt($designation.val(), 10); to figure out what the int value of the field is before using it in your if statement.
Documentation for parseInt

Related

Compare input text with person name belongs to only one input number id

Im trying to write a validation for 2 groups of fields. I have 6 inputs, 3 for text name and 3 more for id number... the validation should do this "if input name="RE_SignedByID" has an input type name="RE_SignedByName", then other inputs name="RE_SignedByID", should NOT contain the same name="RE_SignedByName" More easy explanation... one ID number should have only one Person Name (Id number is unique for one person name). What can I use for that? Should I map() all the inputs?
Those are my inputs:
<div id="signedBy" class="clearfix">
<label>Signer, person ID & name</label>
<span id="signedByID" class="ids half">
<input type="text" name="RE_SignedByID" placeholder="personID, person1" data-validate="" tabindex="101" required>
<input type="text" name="RE_SignedByID" placeholder="personID, person2" data-validate="" tabindex="103">
<input type="text" name="RE_SignedByID" placeholder="personID, person3" data-validate="" tabindex="105">
</span>
<span class="names half">
<input type="text" name="RE_SignedByName" placeholder="name, person1" tabindex="102" required>
<input type="text" name="RE_SignedByName" placeholder="name, person2" tabindex="104">
<input type="text" name="RE_SignedByName" placeholder="name, person3" tabindex="106">
</span>
</div>
I guess it should also be an "on change" function? or can I make the validation on click? Some ideas...? Im actually compleatley lost here...
Thanks in advance!!!
Maybe use different class names for all 3 of them to make them unique?
<input class="name1">
<input class="name2">
<input class="name3">
I'm not sure what you mean but if you want to make the input types unique and not call them all when you write class="names half", then you should give them all unique class names.
So from my understanding you don't want multiple fields to have the same value.
My approach would be this:
let inputTimeout = null; //set an empty timeout object
let vars = [null, null, null, null]; // create an array containing as many nulls as you have inputs
$('.nameInput').on('keyup', function(){
let self = $(this);
clearTimeout(inputTimeout); //clear the timeout
inputTimeout = setTimeout(function(){ //set a timeout to check whether there is a dupe after the user has stopped typing
if (vars.indexOf(self.val()) == -1){ //check if the vals array contains the newly entered string
vars[self.attr('data-inputnum')] = self.val(); //insert the value into the array
}else{
//handle duplicates here
}
}, 500); //500ms is a sensible value for end of user input, change it if users complain that your app is too fast/slow
});
You then just have to edit your HTML a bit so that all name inputs have a class in common (i used .nameInput) and have a data-inputnum attr.
This would look something like this:
<input type="text" name="RE_SignedByName" placeholder="name, person1" tabindex="102" class='nameInput' data-whichinput='0'/>
<input type="text" name="RE_SignedByName" placeholder="name, person2" tabindex="103" class='nameInput' data-whichinput='1'/>
<!--and so on-->
Of course, never rely on JavaScript verification alone, always also check inside your backend. However this would be out of scope for this answer.
Hi Thanks all for the help, made me realize a couple of things till I got the answer. This is my working code:
var valSignedID = $("[name=SignedByID]").map(function() {
return this.value.trim();
}).get();
var valOwnersID = $("[name=OwnersID]").map(function() {
return this.value.trim();
}).get();
valSignedID.sort();
valOwnersID.sort();
for (var i = 0; i < valSignedID.length - 1; i++) {
if (valSignedID[i] == valSignedID[i + 1] && valSignedID[i] != "") {
alert(" You can not have duplicated signers ID's");
return false;
// break;
}
}
for (var i = 0; i < valSingedName.length; i++) {
if (valSingedName[i] == valSingedName[i + 1] && valSingedName[i] != "") {
alert(valSingedName[i] + " should not have different ID");
//return false;
}
}

Validating a form when either a "select" OR "input" is required

I have a page containing multiple forms, all different, and when one is submitted I use the function below to gather all the inputs from that form with the class "required" and check for empty values:
function validateForm(form) {
var inputs = form.getElementsByTagName('input');
var selects = form.getElementsByTagName('select');
var errors = 0;
for (var i = 0; i < inputs.length; i++) {
if(inputs[i].classList.contains('required')) {
if(inputs[i].value === "") {
inputs[i].classList.add("warning");
errors++;
} else {
inputs[i].classList.remove("warning");
}
}
}
if(errors) {
return false;
} else {
return true;
}
}
If it finds an empty value, it adds the class "warning" which just gives the input a red border, then returns false so the form doesn't get submitted.
Here's where I'm running into trouble: Some forms contain a <select> and a text input, ONE of which must be filled in, but not both, as well as various other text inputs. I'm trying to figure out how to modify the above function to handle this.
Let's say the form is for adding a new product. The select is dynamically populated with existing product "categories" and the text input is for if the user wants to create a new category. Here's a simplified version of the form:
<form method = "post" onsubmit = "return validateForm(this)">
<div class = "form-group">
<label>Product Name</label>
<input class = "form-control required" type = "text" name = "product" />
</div>
<div class = "form-group">
<select class = "form-control required" id = "category" name = "category[]">
<option value = "">Select Existing Category</option>
<option value = "Shirts">Shirts</option>
<option value = "Shoes">Shoes</option>
<option value = "Pants">Pants</option>
</select>
</div>
<div class = "form-group">
<label>Create New Category</label>
<input class = "form-control required" type = "text" name = "category[]" />
</div>
<div class = "form-group">
<input class = "btn btn-primary" type = "submit" value = "Submit" />
</div>
</form>
Since I'm using a for loop to go through the inputs - the select and the input are not going to have the same index, so I can't do something like this:
if((selects[i].value === "" && inputs[i].value === "") || (selects[i].value !== "" && inputs[i].value !== "")) {
// add the warning class to both
}
I feel the answer lies somewhere in using the name attribute, i.e. compare selects.name and inputs.name, but how do I get around the differing index in the loop? And also, it should only make this comparison when the select is encountered anyway. It doesn't necessarily exist, depending on the form.
Basically, I need to modify my function to do this:
I. Gather all inputs and selects (if any - some forms will not) from a submitted form
II. Make sure none of the inputs with the "required" class are blank (unless there's a corresponding select, in which case see III below)
III. If there's a select, find the text input with the same "name" (not a requirement to have the same name, but I assume this is the right way to do it). One of them, but not both, must have a value. If both are blank, or both have a value, they should get the "warning" class;
Any help anyone can offer will be greatly appreciated!
Here's a function that do exactly what you want and can handle any form you want, as long as they have the same HTML structure.
Notes:
I recommend avoiding inline event listeners as much as you can, in
the snippet below I used addEventListener method to attach submit
event to all the forms in the document, you can change this to just
some specific forms if you want.
Instead of only adding a border to the required elements, I suggest
you also add some text to tell what the problem is.
// getting all forms in the page you can also get specific forms based on their class-name
var forms = document.getElementsByTagName('form'),
l = forms.length,
i = 0;
// adding submit submit event listener to the referenced forms
for(; i < l; i++) {
forms[i].addEventListener('submit', validateForm);
}
function validateForm(e) {
var els = this.querySelectorAll('input.required'),
len = els.length,
err = false,
c = 0,
inpName = '';
// checking if the form has a select, if so, allow only the select or the input to be filled
var isSelect = this.getElementsByTagName('select');
if(isSelect[0] !== undefined && isSelect[0] !== null) {
var inp = isSelect[0].parentNode.nextElementSibling.querySelector('input.required');
inpName = inp.name;
if((isSelect[0].value == '' && inp.value.trim().length === 0) || (isSelect[0].value != '' && inp.value.trim().length > 0)) {
err = true;
isSelect[0].classList.add("warning");
inp.classList.add("warning");
} else {
isSelect[0].classList.remove("warning");
inp.classList.remove("warning");
}
}
// iterate through the rest of the inputs and check for empty one, thus trimming them before checking
for(; c < len; c++) {
if(els[c].name !== inpName) {
if(els[c].value.trim() == '') {
err = true;
els[c].classList.add("warning");
} else {
els[c].classList.remove("warning");
}
}
}
// based on the error variable, either submit the form or cancel submission
(!err) ? this.submit():e.preventDefault();
}
.warning {
border: 2px solid red;
}
<form method="post">
<div class="form-group">
<label>Product Name</label>
<input class="form-control required" type="text" name="product" />
</div>
<div class="form-group">
<select class="form-control required" id="category" name="category[]">
<option value="">Select Existing Category</option>
<option value="Shirts">Shirts</option>
<option value="Shoes">Shoes</option>
<option value="Pants">Pants</option>
</select>
</div>
<div class="form-group">
<label>Create New Category</label>
<input class="form-control required" type="text" name="category[]" />
</div>
<div class="form-group">
<input class="btn btn-primary" type="submit" value="Submit" />
</div>
</form>
Hope I pushed you further.
You may get a message saying: "The custom error module does not
recognize this error." when you successfully submit the form from the
snippet above, that due to StackOverflow's restrictions as they
don't allow/server side code (StackOverflow doesn't let the form to
be submitted).

Why is my js script creating more then one option tag based on amount of characters in a said field rather then once?

I had a drop down menu that hides different options until they were filled in or not in a text input box, the problem was in safari that options can not be styled ( I had them hidden with display:none) until they are filled in.So I went with adding them to document with js when they are filled in the form. Now when I fill in say a phone number the script is adding the number of options based on the amount of characters and not just once how I want in the said field. I'm fairly new to js so any help would be appreciated.
The Javascript
function contactPhone() {
var inputPhone = document.getElementById("inputPhone").value;
if (inputPhone !== "") {
var phone = document.createElement('option');
phone.id = "contact_phone"
phone.value ="phone"
phone.innerHTML = 'Phone';
document.getElementById("contact_option").appendChild(phone);
}
}
The input html for the phone number
<li>
Phone:
<input id="inputPhone" type="tel" name="phone" class="form-control" placeholder="Phone" oninput="contactPhone()">
</li>
Where the options should be added they add to the right spot but too many
I have one that always show which is in the html already when page loads
<div>
<label>What is the best way to contact you?</label>
<select id="contact_option" name="best_contact" onchange="jsContact()">
<option value="email" id="contact_email">Email</option>
</select>
</div>
The js that shows the options when the correct fields are filled in. Probably not needed for my answer but I figured id add it in just incase.
function jsContact(){
var contact = document.getElementById("contact_option").value;
if (contact == "mail" || contact == "email" || contact == "phone") {
document.getElementById("contact_submit").style.display = "block";
}
else {
document.getElementById("contact_submit").style.display = "none";
}
}
Here is a jsfiddle https://jsfiddle.net/ryqjtwcv/
So you could try to use onblur and as well you need to track the state of the options box.
In this case I just stuck a simple if statement in there to help you get the idea of where you could possibly check for the state of that options list
https://jsfiddle.net/qnj24hbn/10/
The Js
function contactPhone() {
var contact_opts = document.getElementById("contact_option");
// if it has more then 1 option in there don't do anything
if (contact_opts.options.length === 1) {
var inputPhone = document.getElementById("inputPhone").value;
if (inputPhone !== "") {
var phone = document.createElement('option');
phone.id = "contact_phone"
phone.value = "phone"
phone.innerHTML = 'Phone';
contact_opts.appendChild(phone);
}
}
}
The html
Phone:
<input id="inputPhone" type="tel" name="phone" class="form-control" placeholder="Phone" onchange="contactPhone()">
<div>
<label>What is the best way to contact you?</label>
<select id="contact_option" name="best_contact" onchange="jsContact()">
<option value="email" id="contact_email">Email</option>
</select>
</div>

If an input has a value, specific radio button should be checked

I want to check if an input (name="companyname") has a value and if so, it should check a radio button (id="Zakelijk"). If it does not have any value, it should check the other radio button (id="Particulier").
See my current code:
<script type="text/javascript">
function ShowHideDiv() {
var chkYes = document.getElementById("Zakelijk");
var dvPassport1 = document.getElementById("checkzakelijk");
var dvPassport2 = document.getElementById("checkzakelijk1");
var dvPassport3 = document.getElementById("checkzakelijk2");
var display = chkYes.checked ? "block" : "none";
dvPassport1.style.display = display;
dvPassport2.style.display = display;
dvPassport3.style.display = display;
}
</script>
<div class="col-md-12 check-business">
<div class="form-group form-group-xl">
<label for="Particulier"><input type="radio" id="Particulier"checked="checked" name="checkzakelijk" onclick="ShowHideDiv()" />Particulier</label>
<label for="Zakelijk"><input type="radio" id="Zakelijk" name="checkzakelijk" onclick="ShowHideDiv()" />Bedrijf</label>
</div>
</div>
<div class="col-md-12" id="checkzakelijk" style="display:none;">
<div class="form-group">
<label for="inputCompanyName" class="control-label">{$LANG.clientareacompanyname}</label>
<input type="text" name="companyname" id="inputCompanyName" value="{$clientcompanyname}"{if in_array('companyname', $uneditablefields)} disabled="disabled"{/if} class="form-control" />
</div>
</div>
There are other ways, but this should get you going:
$(function() {
if (($("#inputCompanyName").val() || "") != "")
{
$("#Zakelijk").prop("checked", true)
} else {
$("#Particulier").prop("checked", true)
}
});
This is based on your html where the input name='companyname' also has id 'inputCompanyName' and will clear the other radio because they have the same name=
Edit Working jsfiddle: https://jsfiddle.net/76x42os0/4
change input value in the code box (top left) and click run.
Update: Updated the fiddle to the indicated jquery version 3.1.0 and found the newer version of jquery needs id= to match #, while before it matched on name=
If you want to check it when the input is changed you can do
$("input[name='companyname']").change(function(){
var hasValue = $(this).val() === "";
$("#Zakelijk").prop("checked", hasValue);
$("#Particulier").prop("checked", !hasValue);
})
you can optimize the code, but this is more readable.
In case you need the solution in Javascript
if(document.getElementById("inputCompanyName").value !== ""){
document.getElementById("Zakelijk").checked = true;
document.getElementById("Particulier").checked = false;
}
else{
document.getElementById("Particulier").checked = true;
document.getElementById("Zakelijk").checked = false;
}
Here's a working example of what you're after (albeit without your HTML ids/layout in mind, but you can simply change the IDs within).
$("#text-box").on('change', function(){
if($(this).val() != ""){
$('#rd1').prop("checked", true)
}else{
$('#rd2').prop("checked", true)
}
});
https://jsfiddle.net/bm18hmLa/3/
It hooks into the changed event, so it would occur every time the text-box value has been changed.
After thought:
Changing
$("#text-box").on('change', function(){
to
$("#text-box").on('input', function(){
makes it a little "nicer" in terms of responsiveness.
https://jsfiddle.net/bm18hmLa/5/
and here's a version with your ID names too.
https://jsfiddle.net/bm18hmLa/6/

How to make jQuery output only one value at a time from .each iteration

I have the following jQuery conditional code which I forked from CodePen. I have extended the code to use a select field as well and everything works fine except that when I use multiple values in data-cond-val jQuery outputs all of the values and only the last value is executed.
For example in the code provided below, when I use data-cond-val="no, maybe", only maybe value is used/executed on event change whether its used on a select option, input check or input radio.
Here's the HTML code
<div id="demo">
<select name="" data-cond="example1">
<option name="example1" data-cond="example1" value="yes">Yes</option>
<option name="example1" data-cond="example1" value="no">No</option>
<option name="example1" data-cond="example1" value="maybe">Maybe</option>
</select>
<div class="conditional" data-cond-opt="example1" data-cond-val="yes">
<label><input type="checkbox" name="example2" data-cond="example2"><span></span> Are you sure?</label>
<label><input type="checkbox" name="example3" data-cond="example3"><span></span> Really super sure?</label>
<div class="conditional" data-cond-opt="example2" data-cond-val="on">
Hooray!
</div>
<div class="conditional" data-cond-opt="example3" data-cond-val="on">
Don't get cocky!
</div>
</div>
<div class="conditional" data-cond-opt="example1" data-cond-val="no, maybe">
<p>
That's a shame. Will you change your mind?
</p>
<label><input type="radio" name="example4" data-cond="example4" value="yes"><span></span> Yes</label>
<label><input type="radio" name="example4" data-cond="example4" value="no"><span></span> No</label>
<label><input type="radio" name="example4" data-cond="example4" value="maybe"><span></span> Maybe</label>
<div class="conditional" data-cond-opt="example4" data-cond-val="yes">
Great!
</div>
<div class="conditional" data-cond-opt="example4" data-cond-val="no, maybe">
Maybe
</div>
</div>
</div>
<script>
$('.conditional').conditionize();
</script>
Here's the jQuery code
(function($) {
$.fn.conditionize = function(options){
var settings = $.extend({
hideJS: true
}, options );
$.fn.showOrHide = function(listenTo, listenFor, $section) {
//checkbox and radio input types
if ($(listenTo + ":checked").val() == listenFor) {
$section.slideDown();
}
// select box
else if ($(listenTo + "option:selected").val() == listenFor) {
$section.slideDown();
} else {
$section.slideUp();
}
}
return this.each( function() {
var listenTo = "[data-cond=" + $(this).data('cond-opt') + "]";
// check if data att has multiple values
var multiVals = $(this).data('cond-val').split(' ').join(',');
var len = multiVals.indexOf(',');
// if data att has multiple values
if ( len > 0 ) {
// create an array from the values
var dataVals = $(this).data('cond-val').split(' ');
var listenFor;
$.each(dataVals, function (i, dataVal) {
listenFor = dataVals[i];
});
} else {
var listenFor = $(this).data('cond-val');
}
var $section = $(this);
//Set up event listener
$(listenTo).change(function() {
$.fn.showOrHide(listenTo, listenFor, $section);
});
//If setting was chosen, hide everything first...
if (settings.hideJS) {
$(this).hide();
}
//Show based on current value on page load
$.fn.showOrHide(listenTo, listenFor, $section);
});
}
}(jQuery));
The Question: How do I make jQuery to take each of the multiple values separately on each event change?
I'm not sure what am messing up in my syntax! I'll be glad if someone can help by showing me how to make it work.
Here is my CodePen forked DEMO - http://codepen.io/peter2015/pen/ZGoJom
In my demo above, When you select No and Maybe, they should both output the same section, but only Maybe option shows the section and No doesn't show anything when selected.
Not sure about this:var multiVals = $(this).data('cond-val').split(' ').join(',');.
A single split should be enough var multiVals = $(this).data('cond-val').split(',');
Or var multiVals = $(this).data('cond-val').replace(/ /g,'').split(','); if you wanna get rid of spaces in the attribute.
http://jsfiddle.net/pwjrev9v/

Categories

Resources