Finding the next instance of an element, regardless of relationship, using jQuery? - javascript

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.

Related

How to display only two buttons when radio button is checked?

I have a form that implements 3 buttons. Each button offers a different option for the user to select. The page only renders two of the buttons, the last one is hidden. I want to change the ones that display depending on the radio button input.
This is the HTML document that I am working with:
.hidden{
display: none;
}
<label for="pay">Payment Option</label>
<div class="row check">
<div class="col-sm-6">
<input type="radio" id="gcash" name="pay" value="gcash" checked="checked"/>
<label for="gcash" class="pay">Gcash</label>
</div>
<div class="col-sm-6">
<input type="radio" id="walk" name="pay" value="unpaid"/>
<label for="walk" class="pay">Walk In</label>
</div>
</div>
<div class="buttons">
Back
Proceed payment
<input type="submit" class="res-btn hidden" name="btn-submit" value="Submit">
</div>
radio.addEventListener('change', function() {
console.log(this.value)
});
use this handler for getting data of radio
then, find your element and use
element.classList.toggle("hidden");
for toggle class name, which uses in your css

How to reset all radio buttons except for the one with a checked attribute?

I am attempting to reset a form field by wiping all checked properties and then applying the checked property back to the one with a "checked = 'checked'"attribute.
However, I'm not sure how to only select the element that passes my if statement, as console.log(thingo) is logging all three checkboxes.
$('a').click(function () {
if ($(this).parents('.form-field').find('.form-check-input').length != 0) { // does the revert button belong to a group with radio button inputs?
$(this).parents('.form-field').find('.form-check-input').prop('checked', false); //clear all checkboxes
var thingo = $(this).parents('.form-field').find('.form-check-input'); //set checkboxes to thingo
if (thingo.attr('checked') != null) {
console.log(thingo);
thingo.prop('checked', true); //attempt to set all checkboxes with attribute checked to be checked
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"> </script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"/>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<div class="form-group form-field">
<label class="form-check-label">
Sex
<span>[Revert]</span>
</label>
<div class="form-check">
<input type="radio" class="form-check-input" value="0" checked="checked">
<label class="form-check-label">Male</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" value="1">
<label class="form-check-label">Female</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" value="2">
<label class="form-check-label">Unclear</label>
</div>
</div>
This can be quite simply solved by using Jquery's attribute selector. All I have to do is:
$(this).parents('.form-field').find('.form-check-input').prop("checked", false);
//^this line clears all existing checks
$(this).parents('.form-field').find("[checked = 'checked']").prop("checked", true);
//^this line finds the checked attribute with the attribute selector and sets it to checked
$('button').on('click',function () {
var formField = $(this).parents('.form-field');
var formFieldInputs = formField.find('.form-check-input');
if (formFieldInputs.length){
formFieldInputs.prop("checked", false); //clear all checkboxes
formField.find('.form-check-input-default').prop("checked", true);
}
});
HTML format, just add a default class
<div class="form-group form-field">
<label class="form-check-label">
Sex
<span>[<button>Revert</button>]</span>
</label>
<div class="form-check">
<input type="radio" class="form-check-input form-check-input-default" value="0" checked />
<label class="form-check-label">Male</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" value="1" />
<label class="form-check-label">Female</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" value="2" />
<label class="form-check-label">Unclear</label>
</div>
</div>
Some elements here:
Use button instead of a. Clicking on a button does do something though, when used in its natural environment
Use jQuery.on instead of jQuery.click see : Difference between .on('click') vs .click()
For checked attribute see : What's the proper value for a checked attribute of an HTML checkbox?
you don't need to write checked="checked" but its actually only checked
when you want some button to be true by default you just need to add checked
refer this link once:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio
I think this can help you

Access a Particular Div Without Changing Class Name

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

Radio boxes won't validate

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>

Jquery special selection

I have the following html code:
<div class="Radios">
<span class="radio">
<input type="radio" value="1"> yes
<input type="radio" value="0"> no
</span>
</div>
<div class="More">hello</div>
<div class="More">hello</div>
<div class="Radios">
<span class="radio">
<input type="radio" value="1"> yes
<input type="radio" value="0"> no
</span>
</div>
<div class="More">hello</div>
<div class="Radios">
<span class="radio">
<input type="radio" value="1"> yes
<input type="radio" value="0"> no
</span>
</div>
<div class="More">hello</div>
<div class="More">hello</div>
<div class="More">hello</div>
By default all the divs with class=more should be hidden. I use $('div.More').hide()
The difficult thing is that when a user clicks in a radio with value '1' all the divs.More next siblings to div.Radios should be shown (but only the inmediate siblings, not all the divs.More).
Until now, i have the parent of an element clicked, but i cannot select the next div.More elements until the next div.Radios.
Could you give me a hand?
Best Regards.
Jose
but i cannot select the next div.More elements until the next div.Radios.
Use nextUntil():
$('input[type=radio][value=1]').click(function () {
$(this).parents('.Radios').nextUntil('.Radios').show();
}
Well first off, the radio inputs that you click on are 2 levels down from the parent you care about, ".Radios".
So you want to be able to get that parent before you do anything else, something like this:
$("[type=radio]").click(function(){
var realParent = $(this).parents(".Radios");
});
Now that you have the parent you can easily get the .next() and .prev() sibling element:
$("[type=radio]").click(function(){
var realParent = $(this).parents(".Radios");
realParent.next().show();
realParent.prev().show();
});

Categories