Change the position of parsley-errors-list in parsleyjs - javascript

I am using parsleyjs.org to validate my forms.
The plugin creates a ui.parsley-errors-list when an input has a validation error.
The problem is that the .parsley-errors-list is being placed just after the form element's "input, textarea, radio etc.." breaking my layout as follows:
<fieldset>
<p>Checkboxs with a max</p>
<label class="checkbox parsley-error">
<input name="checkbox2" type="checkbox" required="" data-parsley-maxcheck="2" data-parsley-multiple="checkbox2" data-parsley-id="5492"> <span></span>
<p>Normal</p>
</label>
<ul class="parsley-errors-list filled" id="parsley-id-multiple-checkbox2">
<li class="parsley-required">This value is required.</li>
</ul>
<label class="checkbox">
<input name="checkbox2" type="checkbox" data-parsley-multiple="checkbox2" data-parsley-id="5492"> <span></span>
<p>Normal</p>
</label>
<label class="checkbox">
<input name="checkbox2" type="checkbox" data-parsley-multiple="checkbox2" data-parsley-id="5492"> <span></span>
<p>Normal</p>
</label>
</fieldset>
Instead, the .parsley-errors-list need to be positioned to be the last child/element within the container <fieldset>.
Is this achievable?

You can set the error container with (at least) two ways.
Change the container with DOM attributes
In cases where you only have one input (or group of inputs, like you do) and you want to change the container of the errors on those inputs, you can use data-parsley-errors-container="#element" (see the docs). Here is an example (jsfiddle demo)
<fieldset>
<label class="checkbox-inline">
<input type="checkbox" id="inlineCheckbox1" required data-parsley-maxcheck="2" data-parsley-multiple="checkbox2" value="option1" data-parsley-errors-container="#checkbox-errors" /> 1
</label>
<label class="checkbox-inline">
<input type="checkbox" id="inlineCheckbox2" data-parsley-maxcheck="2" data-parsley-multiple="checkbox2" value="option2" /> 2
</label>
<label class="checkbox-inline">
<input type="checkbox" id="inlineCheckbox3" data-parsley-maxcheck="2" data-parsley-multiple="checkbox2" value="option3" /> 3
</label>
<div id="checkbox-errors"></div>
</fieldset>
Note the attribute data-parsley-errors-container="#checkbox-errors" on the first checkbox and the element <div id="checkbox-errors"></div> at the end of the fieldset.
In this case you don't need to add the data-parsley-errors-container to all checkboxes because you're "grouping" them with data-parsley-multiple="checkbox2".
Set a custom configuration to be used by Parsley
In cases where you have a few or all inputs and you want to change the position of the default container. Lets say all your fields are placed inside a fieldset and you want to display the errors at the end of the fieldset.
This solution allows you to change the default container for each field (jsfiddle demo)
<fieldset>
<label class="checkbox-inline">
<input type="checkbox" id="inlineCheckbox1" required data-parsley-maxcheck="2" data-parsley-multiple="checkbox2" value="option1" /> 1
</label>
<label class="checkbox-inline">
<input type="checkbox" id="inlineCheckbox2" data-parsley-maxcheck="2" data-parsley-multiple="checkbox2" value="option2" /> 2
</label>
<label class="checkbox-inline">
<input type="checkbox" id="inlineCheckbox3" data-parsley-maxcheck="2" data-parsley-multiple="checkbox2" value="option3" /> 3
</label>
<div id="checkbox-errors"></div>
</fieldset>
<script>
$(document).ready(function() {
var parsleyConfig = {
errorsContainer: function(parsleyField) {
var fieldSet = parsleyField.$element.closest('fieldset');
if (fieldSet.length > 0) {
return fieldSet.find('#checkbox-errors');
}
return parsleyField;
}
};
$("form").parsley(parsleyConfig);
});
</script>
In this solution we've added the element <div id="checkbox-errors"></div> before the end of the fieldset and changed the errorsContainer option of Parsley. If our element is inside a fieldset the errors will be displayed inside the #checkbox-errors.
Based on this example, you are also able to set the same container for all fields. In this case your options would be something like this (jsfiddle demo):
var parsleyConfig = {
errorsContainer: function(parsleyField) {
return $('#errors');
}
};

For this kind of UI errors in the parsley js.
You can use the data-parsley-errors-container custom validator for placing the parsley error message as per your form needs.
<div>
<div class="radio radio-primary">
<input type="radio" id="cellPhone1" value="1" name="rd_cell_phone" required="" data-parsley-error-message="Please select an option" data-parsley-errors-container="#cell-phone-validation-error-block">
<label for="cellPhone1"> Yes </label>
</div>
<div class="radio radio-primary">
<input type="radio" id="cellPhone0" value="0" name="rd_cell_phone" required="" data-parsley-error-message="Please select an option" data-parsley-errors-container="#cell-phone-validation-error-block">
<label for="cellPhone0"> No </label>
</div>
</div>
<div class="margin-top10" id="cell-phone-validation-error-block"></div>

Try this:
$.listen('parsley:field:error', function(fieldInstance){
var fieldName = fieldInstance.$element.attr('name');
var field = $('input[name="'+fieldName+'"]');
var fieldWrapper = field.parents('fieldset');
if (fieldWrapper.find('.errors_container').length > 0) {
setTimeout(function(){
fieldWrapper.find('.errors_container').append(fieldWrapper.find('.parsley-errors-list'));
},100);
}
});
$('form').parsley();
}
Use class, because it works for many fields.

Related

How to fix margin between multiple radio when adding interactive elements between Bootstrap 3?

Whenever I try to add a so called additional-options element between the radios on my form, Bootstrap (BS3) causes different margins to be set on the radios. This is not unwanted, unless when hiding these additional options until the desired radio option has been selected (javascript interaction):
$(document).ready(function() {
$("#additional-options-1").css("display", "block");
$("input[type=radio][name=optionsRadios]").change(function() {
if (this.value == "option1") {
$("#additional-options-1").css("display", "block");
} else {
$("#additional-options-1").css("display", "none");
}
});
});
.additional-options {
display: none;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<p>
Try changing the following option and take a look at the margins of the available radios. What would be the supposed way to handle the margins? <br /><br />The radio element after the checkboxes requires a 'margin-top: -5px' according to the '.checkbox+.checkbox,
.radio+.radio' CSS rule (by Bootstrap 3) but does not seem to get it after the 'additional-options' element gets a 'display: none;' (by provided javascript).
</p>
<hr />
<div class="radio">
<label>
<input type="radio" name="optionsRadios" id="optionsRadios1" value="option1" checked>
Radio option one
</label>
</div>
<div class="additional-options" id="additional-options-1">
<div class="checkbox">
<label>
<input type="checkbox" value="">
Check option one
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" value="">
Check option two
</label>
</div>
</div>
<!--When additional-options is hidden:-->
<!--<div class="radio" style="margin-top: -5px;">-->
<!--Otherwise (no margin-top):-->
<div class="radio">
<label>
<input type="radio" name="optionsRadios" id="optionsRadios2" value="option2">
Radio option two
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="optionsRadios" id="optionsRadios3" value="option3">
Radio option three
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="optionsRadios" id="optionsRadios4" value="option4">
Radio option four
</label>
</div>
<div class="additional-options" id="additional-options-2">
<div class="checkbox">
<label>
<input type="checkbox" value="">
Check option one
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" value="">
Check option two
</label>
</div>
</div>
<!--When additional-options is hidden:-->
<!--<div class="radio" style="margin-top: -5px;">-->
<!--Otherwise (no margin-top):-->
<div class="radio">
<label>
<input type="radio" name="optionsRadios" id="optionsRadios5" value="option2">
radio option five
</label>
</div>
JSFiddle
As you can see in the example above, if the user selects any radio (but the first one), the margin betweem radios do not appear correct.
I tried setting in-line margin-top: -5px but this should also be removed again when concerning checkboxes are being shown. When the checkboxes are hidden, the <div class="radio"> right below the concerning <div class="additional-options" ... > should have a margin-top: -5px;. How am I to solve this "margin problem"?
customize bootstrap CSS like
.additional-options {
display: none;
}
.additional-options + .radio{
margin-top:-5px;
}
https://jsfiddle.net/lalji1051/h01wnqoz/2/
Different Margins are causing due to below Bootstrap Class.
.checkbox+.checkbox, .radio+.radio {
margin-top: -5px;
}
Override this class in your local CSS File as below and remove inline style "margin-top:-5px".
.checkbox+.checkbox, .radio+.radio {
margin-top: 10px;
}

jQuery multi-step form: disable 'next' button until input is filled in each section

I have a multi-step form with different input types inside each <fieldset>. I have a 'next' <button> which will trigger the next section of the form once the current fieldset has been completed.
Currently the next button is set to disabled until the user has met the criteria for that fieldset - ie: checked radios/checkboxes etc.
The issue I'm having is the jQuery I'm using to switch the button attribute to .prop('disabled', false); changes all of the buttons in the entire form to false. Is it possible to target the <button> within the current fieldset only?
Additionally, is it possible to disable the next button if a user goes back to a section and unchecks all inputs?
Here's a previous answer containing the script i'm currently using: Disable button until one radio button is clicked
I have a Codepen with a prototype of what I'm working on here: https://codepen.io/abbasarezoo/pen/jZgQOV - you can assume once live each one fieldset will show at a time.
Code below:
HTML:
<form>
<fieldset>
<h2>Select one answer</h2>
<label for="radio-1">Radio 1</label>
<input type="radio" id="radio-1" name="radio" />
<label for="radio-2">Radio 2</label>
<input type="radio" id="radio-2" name="radio" />
<label for="radio-2">Radio 3</label>
<input type="radio" id="radio-3" name="radio" />
<br />
<button disabled>Next</button>
</fieldset>
<fieldset>
<div class="radio-group">
<h2>Select one answer per row</h2>
<h3>Row 1</h3>
<label for="radio-4">Radio 1</label>
<input type="radio" id="radio-4" name="radio-row-1" />
<label for="radio-5">Radio 2</label>
<input type="radio" id="radio-5" name="radio-row-2" />
<label for="radio-6">Radio 3</label>
<input type="radio" id="radio-6" name="radio-row-3" />
</div>
<div class="radio-group">
<h3>Row 2</h3>
<label for="radio-7">Radio 1</label>
<input type="radio" id="radio-7" name="radio-row-4" />
<label for="radio-8">Radio 2</label>
<input type="radio" id="radio-8" name="radio-row-5" />
<label for="radio-9">Radio 3</label>
<input type="radio" id="radio-9" name="radio-row-6" />
</div>
<button disabled>Next</button>
</fieldset>
<fieldset>
<h2>Select multiple answers</h2>
<label for="checkbox-1">Checkbox 1</label>
<input type="checkbox" id="checkbox-1" name="checkbox" />
<label for="checkbox-2">Checkbox 2</label>
<input type="checkbox" id="checkbox-2" name="checkbox" />
<label for="checkbox-2">Checkbox 3</label>
<input type="checkbox" id="checkbox-3" name="checkbox" />
<br />
<button disabled>Next</button>
</fieldset>
</form>
JS:
$('fieldset').click(function () {
if ($('input:checked').length >= 1) {
$('button').prop("disabled", false);
}
else {
$('button').prop("disabled", true);
}
});
Thanks in advance for any help!
i have just change your js into this .. this will help you to enable current button in the fieldset not all of them
$('fieldset').click(function () {
if ($('input:checked').length >= 1) {
$(this).closest('fieldset').find('button').prop("disabled", false);
}
else {
$('button').prop("disabled", true);
}
});

Is there a way to find the closest element that isn't label and does not have a class

Giving an element, I need to find the closest element that isn't label and isn't an element that has a class of radio or checkbox
Here is what I have done
$parent = element.closest('div');
if($parent.hasClass('checkbox') || $parent.hasClass('radio'))
{
$parent = $parent.parent();
}
error.appendTo($parent);
The above code works for the most part except it only looks for a div not any element.
Also, is there a shorter way to write this code where I can avoid the condition statement? Perhaps, use the find() method to search but not sure how to use it.
Here is the html code that I am trying to search
<div class="form-group has-error">
<label for="gender" class="col-md-2 control-label">Gender</label>
<div class="col-md-10">
<div class="radio">
<label for="gender_">
<input id="gender_" required="1" name="gender" value="" aria-required="true" aria-describedby="gender-error" type="radio">
Please select your gender
</label>
</div>
<div class="radio">
<label for="gender_1">
<input id="gender_1" required="1" name="gender" value="1" aria-required="true" type="radio">
Male
</label>
</div>
<div class="radio">
<label for="gender_2">
<input id="gender_2" required="1" name="gender" value="2" aria-required="true" type="radio">
Female
</label>
</div>
</div>
</div>
I want to be able to appent to the div with the class "col-md-10".
Not it is not always a div or event the same class which is why I want to search for the closest element that isn't label of checkbox or radio class
Use :not(input, label, .checkbox, .radio) in the .closest() selector. I've added the input because .closest() starts the check with the element it's been used on (the input).
Note: If you know that you are looking for an element with the .col-md-10 class, you can use .closest('.col-md-10').
var result = $('input').closest(':not(input, label, .checkbox, .radio)');
console.log(result[0]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group has-error">
<label for="gender" class="col-md-2 control-label">Gender</label>
<div class="col-md-10">
<div class="radio">
<label for="gender_">
<input id="gender_" required="1" name="gender" value="" aria-required="true" aria-describedby="gender-error" type="radio">
Please select your gender
</label>
</div>
<div class="radio">
<label for="gender_1">
<input id="gender_1" required="1" name="gender" value="1" aria-required="true" type="radio">
Male
</label>
</div>
<div class="radio">
<label for="gender_2">
<input id="gender_2" required="1" name="gender" value="2" aria-required="true" type="radio">
Female
</label>
</div>
</div>
</div>

Default checked button

Below code is html produced from opencart 2
No radio button is selected when loading page.
How can i have selected the Value="2" as default checked. (javascript or CSS)
<div id="payment-custom-field1" class="form-group custom-field" data-sort="0">
<label class="control-label">Invoice</label>
<div id="input-payment-custom-field1">
<div class="radio">
<label>
<input type="radio" value="2" name="custom_field[1]">
Receipt
</label>
</div>
<div class="radio">
<label>
<input type="radio" value="1" name="custom_field[1]">
Invoice
</label>
</div>
</div>
</div>
Solution with javascript
(function() {
document.getElementsByName("custom_field[1]")[0].checked=true;
})();
<input type="radio" id="sample" value="2" name="custom_field[1]">
Receipt
</label>
Using javascript:
document.getElementById("sample").checked = true;
Using html:
You can simply add checked attribute to your html element
Using the element name:
(function() {
document.getElementsByName("custom_field[1]")[0].checked=true;
})();
https://jsfiddle.net/pandiyancool/vb73q59w/
You can simply add checked attribute
<input type="radio" value="2" name="custom_field[1]" checked>
The solution with javascript was the below code:
document.getElementsByName("custom_field[1]")[0].checked=tru‌​e;
Thank you Pandiyan Cool

How can I disable a checkbox once it has been checked?

I have a checkbox. First, I checked, then I want to change the check, and it's possible now.
However, I want to disable this. No one will be allowed to change that checkbox value once selected.
For this what can I do in my code:
view
<div class="control-group">
<label class="control-label">Language Known</label>
<div class="controls">
<label class="checkbox">
<input type="checkbox" value="1" name="lang_known"/> Hindi
</label>
<label class="checkbox">
<input type="checkbox" name="lang_known" value="2" /> French
</label>
</div>
</div>
You can achieve it by Jquery like this :
<input class="something" type="checkbox" value="1" />
In Jquery
//On click
$('.something').on('click', function() {
//disable if checked
$(this).prop("disabled", this.checked );
});
Reference Prop
JsFiddle

Categories