I have a simple requirement: Based on the response of a user on a particular yes no question, show him another question.
The issue is I am using Bootstrap forms so all my div classes are named form-group, and this is the problem: If I rename the class to say, form-group1, my website shape gets disconfigured...some form items appear out of position.
<script src="http://code.jquery.com/jquery-latest.js" />
<script>
$(document).ready(function () {
$(".form-group1").hide();
$("#r1").click(function () {
$(".form-group1").show();
});
$("#r2").click(function () {
$(".form-group1").hide();
});
});
</script>
<form action="">
<input type="radio" name="gender" id="r1" value="female" onClick="getResults()">Single
<input type="radio" name="gender" id="r2" value="male">Married
<!-- Textarea -->
<div class="form-group1">
<label class="col-md-4 control-label" for="q2">By When is your marriage scheduled?</label>
<div class="col-md-4">
<textarea class="form-control" id="q2" name="Q2" placeholder="e.g. FY18 Q4"></textarea>
</div>
</div>
<br />
<br />
<input type="submit" value="Submit">
</form>
So my question is how can I access the particular div that contains the text-area without changing the class-name?
An element can have as many classes as you like.
So just as an alternative, rather than changing the class name, you can also add another class (separated by a space). That way your bootstrap styles are still applied (since you still have the form-group class), but you can also add your own.
<div class="form-group custom-form-group">
<label class="col-md-4 control-label" for="q2">
By When is your marriage scheduled?
</label>
<div class="col-md-4">
<textarea class="form-control" id="q2" name="Q2" placeholder="e.g. FY18 Q4"></textarea>
</div>
</div>
Then in your script you can target the custom-form group class and it should work as you intended.
You can access the div container by first accessing the ID you know and then traverse:
<input type="radio" name="gender" id="r1" data-div="q2" value="female">Female
<input type="radio" name="gender" id="r2" data-div="q2" value="male">Male
$("[name=gender]").on("click",function() {
$("#"+$(this).data("div")) // textarea with known ID from data attribute
.closest("div.form-group") // the container
.toggle(this.value=="male"); // show or hide
})
You can use DOM relationship to target the desired element, You can traverse up to common ancestor using .closest() then use .find() to get the target element.
$(this).closest("form").find(".form-group").show();
$(document).ready(function() {
$(".form-group").hide();
$("#r1").click(function() {
$(this).closest("form").find(".form-group").show();
});
$("#r2").click(function() {
$(this).closest("form").find(".form-group").hide();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="">
<input type="radio" name="gender" id="r1" value="female">Single
<input type="radio" name="gender" id="r2" value="male">Married
<!-- Textarea -->
<div class="form-group">
<label class="col-md-4 control-label" for="q2">By When is your marriage scheduled?</label>
<div class="col-md-4">
<textarea class="form-control" id="q2" name="Q2" placeholder="e.g. FY18 Q4"></textarea>
</div>
</div>
<br><br><input type="submit" value="Submit">
</form>
You can leave the class name unchanged and add an id to the form like this
<div id="form1" class="form-group">...</div>
And then in jQuery do this
$("#form1").show(); // showing the form
$("#form1").hide(); // hiding the form
Related
There are 3 <input type="file"> elements on a page.
Each element has a "change" event listener.
When I click on the 2nd or 3th element, the label of the first is logged to the console.
What am I doing wrong?
Sandbox: https://jsfiddle.net/x01e4kgu/3/
HTML
<form action="">
<div class="input--upload">
<label for="attachment">Upload 1</label>
<input type="file" name="attachment[]" id="attachment">
</div>
<div class="input--upload">
<label for="attachment">Upload 2</label>
<input type="file" name="attachment[]" id="attachment">
</div>
<div class="input--upload">
<label for="attachment">Upload 3</label>
<input type="file" name="attachment[]" id="attachment">
</div>
</form>
JS
const fileInputs = document.querySelectorAll('.input--upload input')
fileInputs.forEach(input => {
input.addEventListener('change', function(e) {
const label = e.target.parentNode.querySelector('label')
console.log(label)
})
})
this way
ID must be UNIQUE (you don't need any one in your code)
all your label elements use the same for attribute pointing on the same id which all concern only the first element having this id (the others are ignored)
use onchange to use an arrow function,
it's allow you to bypass e.target...
because it's allows you to stay within the scope of your local variable(s) (actualy only inEl)
<form action="">
<div class="input--upload">
<label>
Upload 1
<input type="file" name="attachment[]" >
</label>
</div>
<div class="input--upload">
<label>
Upload 2
<input type="file" name="attachment[]" >
</label>
</div>
<div class="input--upload">
<label >
Upload 3
<input type="file" name="attachment[]" ">
</label>
</div>
</form>
const fileInputs = document.querySelectorAll('div.input--upload input')
fileInputs.forEach( inEl =>
{
inEl.onchange = e =>
{
let el_Lb = inEl.closest('label')
console.log( el_Lb.textContent )
}
})
This is happening because they all have the same ids. The for attribute in labels tells that which input they are for. All of the 3 labels are for one input with id attribute attachment and the first occurrence of that is triggered. So in order to get what you need, you will have to assign different ids for each input and change the for in the labels accordingly. Its a common thing to NOT use the same id for more than 1 html element. So the updated code would be:
<form action="">
<div class="input--upload">
<label for="attachment1">Upload 1</label>
<input type="file" name="attachment[]" id="attachment1">
</div>
<div class="input--upload">
<label for="attachment2">Upload 2</label>
<input type="file" name="attachment[]" id="attachment2">
</div>
<div class="input--upload">
<label for="attachment3">Upload 3</label>
<input type="file" name="attachment[]" id="attachment3">
</div>
</form>
I have a series of radio groups, all with the same name because they are dynamically generated. I want them to be required, but nothing I'm doing is making that happen (including trying to count checked items with jquery).
I'm guessing this is due to some sort of ID conflict?
I have the radios marked as "required" in the HTML.
Or could this be due to the way I'm processing with jquery?
<div class="benchmark-question-title"><?php echo $atts['content']; ?></div>
<div class="row">
<div class="col-sm-6 col-xs-12">
<form class="benchmark-question-binary">
<label class="benchmark-yes-no"><input type="radio" name="yesno" value="yes" required>Yes</label>
<label class="benchmark-yes-no"><input type="radio" name="yesno" value="no" checked required>No</label>
</form>
</div>
<div class="col-sm-6 col-xs-12">
<span class="benchmark-move-forward italic">If yes, move on to the next movement</span>
</div>
</div>
When I attempt to see if any radio groups with name "yesno" are NOT checked with jquery, it doesn't appear to recognize the groups and counts every option individually.
$('input:radio[name=yesno]').each(function(){
if ( $(this).is(":checked") ){
console.log('checked')
}
else{
console.log('not checked');
}
});
$('input:radio[name=yesno]').each(function() {
if ($(this).is(":checked")) {
console.log('checked')
} else {
console.log('not checked');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="benchmark-question-title">
<?php echo $atts['content']; ?>
</div>
<div class="row">
<div class="col-sm-6 col-xs-12">
<form class="benchmark-question-binary">
<label class="benchmark-yes-no"><input type="radio" name="yesno" value="yes" required>Yes</label>
<label class="benchmark-yes-no"><input type="radio" name="yesno" value="no" checked required>No</label>
</form>
</div>
<div class="col-sm-6 col-xs-12">
<span class="benchmark-move-forward italic">If yes, move on to the next movement</span>
</div>
</div>
no need to itterate through, just check the checked state of the group.
$("input:radio[name='yesno']").is(":checked")
or
$("input:radio[name='yesno']:checked").val()
Using JQuery to check if no radio button in a group has been checked
I'm not following what exactly you're trying to accomplish, however if you're looking for the default functionality of only being able to select one radio at a time, you just need to add brackets to the name. Doing this, you also won't have to do any validation if you mark one of the radios as default (as they can't be deselected).
<input type="radio" name="yesno[]" value="yes" />
<input type="radio" name="yesno[]" value="no" checked />
You can use the form to base an event on. Here I used both the change and a validate event - so you can trigger the validate whenever you wish (like on a form submit?) and this shows an example how to do so.
$('form.benchmark-question-binary')
.on("change validate", 'input[type="radio"][name="yesno"]', function(event) {
let thisform = $(event.delegateTarget);
let radios = thisform.find('input[type="radio"][name="yesno"]');
let rChecked = radios.filter(":checked");
console.log(radios.length > rChecked.length);
console.log(radios.length, rChecked.length)
})
// now trigger the first one on startup
.find('input[type="radio"][name="yesno"]').first().trigger('validate');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="benchmark-question-title">
Am I the hero?
</div>
<div class="row">
<div class="col-sm-6 col-xs-12">
<form class="benchmark-question-binary">
<label class="benchmark-yes-no"><input type="radio" name="yesno" value="yes" required>Yes</label>
<label class="benchmark-yes-no"><input type="radio" name="yesno" value="no" checked required>No</label>
</form>
</div>
<div class="col-sm-6 col-xs-12">
<span class="benchmark-move-forward italic">If yes, move on to the next movement</span>
</div>
</div>
Given this html:
<form action="">
<div id="choices">
<input type="radio" name="stype" id="opt1" value="input1_div" checked=""/> Opt1
<input type="radio" name="stype" id="opt2" value="input2_div"/> Opt2
</div>
<div id="stypes">
<div id="input1_div">
<input type="text" id="input1" name="input1" placeholder="input1"/>
</div>
<div id="input2_div" style="display: none;">
<input type="text" id="input2" name="input2" placeholder="input2" disabled=""/>
</div>
</div>
<div id="#sbutton">
<input type="submit" id="input3" value="Submit"/>
</div>
</form>
I use following jQuery to hide/disable input fields based on selected radio buttons:
jQuery('#choices input').each(function() {
var item = this;
$(this).click(function() {
if($('input[type=radio][name=stype]').is(':checked')) {
$('#stypes > div').hide();
$('#stypes input').not("#sbutton").prop('disabled', true);
$('#' + $(item).val()).fadeIn();
$('#' + $(item).val() + ' input').prop('disabled', false);
}
});
});
All-in-One in this jsfiddle.
I'm particularly unsure about my technique to incorporate radio value into the id selector:
$('#' + $(item).val()).fadeIn();
$('#' + $(item).val() + ' input').prop('disabled', false);
What is the correct way to do it? Other tips regarding my jQuery?
First of all, you don't need a sophisticated jQuery.each loop to bind the click and to define this. In each event handler this will be the caller of the function. In your case it is enough to have click function for all of them.
As you said in comments, it's only matter of presentation. I prefer to have one field instead of two fields. Even I prefer to have a fixed name for this text input, though in order to make it very similar to your example I change the name and placeholder accordingly.
$(function(){
$('#choices input').click(function() {
var newName = $(this).val(),
newPlaceholder = $(this).attr("data-placeholder");
$('#interchangable_input[name!='+newName+']').hide()
.attr("name", newName)
.attr("placeholder", newPlaceholder)
.fadeIn();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="">
<div id="choices">
<input type="radio" name="stype" id="opt1" data-placeholder="Input one" value="input1" checked=""/> <label for="opt1">Opt1</label>
<input type="radio" name="stype" id="opt2" data-placeholder="Input two" value="input2"/> <label for="opt2">Opt2</label>
</div>
<div id="stypes">
<input type="text" id="interchangable_input" name="input1" placeholder="Input one"/>
</div>
<div id="#sbutton">
<input type="submit" id="input3" value="Submit"/>
</div>
</form>
Few more suggestions:
You can use <label for="target id"> for each option label in radio buttons or checkboxes. It will work fine with click event handler, even if the user clicks on the label instead of the button itself.
You can hid some information as data-* attribute in html5. You don't need to necessarily use value.
Update for multiple items
In case of group of multiple items in form, I can imagine a form with different sections or pages. The <fieldset> can be use to group these items. In HTML5 you could just disable the fieldset tag by <fieldset disabled> when you change the form page with jquery. (With exception of IE browsers). Because of this exception we need to disable all items in subforms. In order to handle this part, I defined a class .form-element which applies for all form inputs. You can also use <div> instead of <fieldset>, then you will need to track their enable/disable status.
$(function(){
// initialization by disabling form-elements and hiding them
$("#subforms fieldset[disabled]").hide();
$("#subforms fieldset[disabled] .form-element").attr('disabled','disabled');
// choice tracker
$('#choices input').click(function() {
var $target = $($(this).attr("data-subform")),
$oldElement = $("#subforms fieldset:not([disabled])");
$oldElement.attr('disabled','disabled').hide();
$oldElement.find(".form-element").attr('disabled','disabled');
$target.removeAttr("disabled");
$target.find(".form-element").removeAttr("disabled");
$target.fadeIn();
});
});
fieldset {
border: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="">
<div id="choices">
<input type="radio" name="stype" id="opt1" data-subform="#subform1" value="subform1" checked=""/> <label for="opt1">Opt1</label>
<input type="radio" name="stype" id="opt2" data-subform="#subform2" value="subform2"/> <label for="opt2">Opt2</label>
</div>
<div id="subforms">
<fieldset id="subform1" >
<input class="form-element" type="text" name="input1_1" placeholder="Input one"/>
<input class="form-element" type="text" name="input1_2" placeholder="Input two"/>
</fieldset>
<fieldset id="subform2" disabled>
<input class="form-element" type="text" name="input2_1" placeholder="Input one"/><br />
<textarea class="form-element" name="input2_2" placeholder="Input two"></textarea><br />
<input class="form-element" type="checkbox" name="input2_3" id="input2_3" /> <label for="input2_3">check this first</label>
</fieldset>
</div>
<div id="#sbutton">
<input type="submit" id="input3" value="Submit"/>
</div>
</form>
I am new to JavaScript.Could anybody suggest me how to change the text of label in below code
<div class="col-sm-6">
<div class="radio">
<label for="radioabc">
<input id="radioabc" type="radio" value="def" name="input_Radio">
abc
</label>
</div>
<div class="radio">
<label for="radioxyz">
<input id="radioxyz" type="radio" value="pqr" name="input_Radio">
xyz
</label>
</div>
</div>
I want to change text 'abc' and text 'xyz' to other values.
My approch to change text 'abc' to 'tvr'.
I've tried:
$($(".col-sm-6").children()[0]).children().text("tvr");
then it also removes input field.whats wrong in my approach or please suggest some other approach.
if you want to change text by Javascript:
var divs = document.getElementsByClassName('radio');//got all nodes in divs
divs[0].children[0].lastChild.data = "tvr"; // similar for second text...using divs[1]
JSFIDDLE DEMO
You can use jQuery and do it easily:
Example
html:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="col-sm-6">
<div class="radio">
<label for="radioabc">abc</label>
<input id="radioabc" type="radio" value="def" name="input_Radio" />
</div>
<div class="radio">
<label for="radioxyz">
xyz
</label>
<input id="radioxyz" type="radio" value="pqr" name="input_Radio" />
</div>
</div>
javascript:
<script>
$(function() {
$('label').on('click', function(){
$(this).text('something else');
})
});
</script>
I am working on the error messaging for my form and I am trying to figure out how to display the errors using one function. Unfortunately, the error message element's relationship to the field varies throughout my form. In some instances, it will be this:
<div class="col-sm-6">
<label for="first_name">First Name</label>
<input type="text" id="first_name" name="first_name" />
<div class="error">Please enter your first name.</div>
</div>
In which case, I can use $(this).next.show(); in order to display the error message.
However, in other instances, my fields are structured like this:
<div id="variants">
<div class="col-sm-6 col-lg-4">
<label><input type="radio" name="variant" value="red">Red</label><br/>
<label><input type="radio" name="variant" value="green">Green</label><br/>
<label><input type="radio" name="variant" value="blue">Blue</label>
</div>
<div class="col-sm-6 col-lg-4">
<label><input type="radio" name="variant" value="yellow">Yellow</label><br/>
<label><input type="radio" name="variant" value="brown">Brown</label><br/>
<label><input type="radio" name="variant" value="orange">Orange</label>
</div>
<div class="error">Please select a product variant.</div>
</div>
In this example, the above jQuery selector will not work since the .error element is the sibling of the parent of the input, instead of a direct sibling of the input.
My question is, is there any way to select the next closest instance of an element regardless of the relationship to the element it is being compared to? I was looking into .closest() but haven't been able to get it working.
Thanks!
You need to effectively search up and down at each level of the hierarchy.
$(this).parents().has('.error').first().find('.error');
This will check each parent in turn seeing when one has an error class, return the closest, then find the descendant error.
You might also be able to use something like this:
$(this).closest(':has(.error)').find('.error');
Here is a JSFiddle showing both working (to stop all the whining): http://jsfiddle.net/u37twowx/1/ :)
You will note this solution does not required a class to be added in the hierarchy.
Use a common class for each input element container div and target the error div using closest() and find().
For Example:
<div class="col-sm-6 element">
<label for="first_name">First Name</label>
<input type="text" id="first_name" name="first_name" />
<div class="error">Please enter your first name.</div>
</div>
<div id="variants" class="element">
<div class="col-sm-6 col-lg-4">
<label><input type="radio" name="variant" value="red">Red</label><br/>
<label><input type="radio" name="variant" value="green">Green</label><br/>
<label><input type="radio" name="variant" value="blue">Blue</label>
</div>
<div class="col-sm-6 col-lg-4">
<label><input type="radio" name="variant" value="yellow">Yellow</label><br/>
<label><input type="radio" name="variant" value="brown">Brown</label><br/>
<label><input type="radio" name="variant" value="orange">Orange</label>
</div>
<div class="error">Please select a product variant.</div>
</div>
and now with jquery:
$(this).closest(".element").find(".error").show();
Something that I have been using for quiet sometime is using the :after pseudo class, and then adding that class to the element that is receiving the error.
There are multiple ways to do it, especially if you want a custom message.
HTML
<input type="text" id="first_name" name="first_name" />
CSS
input.error:after, input.error::after {
content: '';
position: relative;
bottom: 0;
height: 20px;
background: red;
color: white;
}
#first_name.error:after, #first_name.error:after {
content: 'Please input first name.';
}
#last_name.error:after, #last_name.error:after {
content: 'Please input last name.';
}
.
.
.
jQuery
$('input').keypress(function(){
if(/*Conditional*/){
$(this).addClass('error');
}
});
This is a simple jQuery function, you just have to set it up to handle the error's accordingly.