I have a drop-down which allows multiple product selection and based on the products selected I want to show inputs for products extra and add a required attribute to those inputs.
var products = $('#products').select2({
tags: true
});
products.on('change', function() {
var ids = products.val();
setExtras(ids);
});
function setExtras(ids) {
$.each(ids, function(index, id) {
$('#extras .form-group').each(function() {
if ($(this).hasClass('extra_' + id)) {
$(this).show('fade').find('input').prop('required', true);
} else {
$(this).hide('fade').find('input').prop('required', false);
}
});
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6/js/select2.min.js"></script>
<div class="form-group">
<label for="products">Products</label>
<select multiple="" class="form-control select2" name="products[]" id="products">
<option value="1">Product One</option>
<option value="2">Product Two</option>
</select>
<span class="help-block">Please select your product</span>
</div>
<div id="extras">
<div style="display: none;" class="form-group extra_1">
<label for="1_1">
Product One(Message)
</label>
<input type="text" class="form-control" id="1_1" name="extras[1][1]" placeholder="Your message here">
</div>
<div style="display: none;" class="form-group extra_2">
<label for="2_2">
Product Two(Message)
</label>
<input type="text" class="form-control" id="2_2" name="extras[2][2]" placeholder="Your message here">
</div>
<div style="display: none;" class="form-group extra_2">
<label for="2_3">
Product Two(Tag Line)
</label>
<input type="text" class="form-control" id="2_3" name="extras[2][3]" placeholder="Your tag line here">
</div>
</div>
My current JS code only shows inputs for last selected product, please help me out to fix that.
P.S. The product extras will be variable, some products has one or more extra and some will have none.
You can try change code of function setExtras
function setExtras(ids) {
$('#extras .form-group').each(function () {
$(this).hide('fade').find('input').prop('required', false);
});
$.each(ids, function (index, id) {
$('#extras .form-group').each(function () {
if ($(this).hasClass('extra_' + id)) {
$(this).show('fade').find('input').prop('required', true);
}
});
});
}
This is a demo link: https://codepen.io/phuongnm153/pen/PvwoZg
Related
I am new to programming. I have got an issue with my jquery codes.
I have a form that I want to hide some sections of it and do not show until the first section which is input text, be completed then after clicking on the next button first check if all data inputs are completed then show the next section which is dropdown text (part2) and if I pick one of the dropdown text then show next section which is part3.
I tried this code.
<script>
$(".part2").hide()
$(".nextBtn").on("click", function(){
$('input').each(function() {
if(!$(this).val()){ alert('Some fields are empty'); return false; }
else{
$(".part2").show();}
});
});
</script>
<div class="form">
<div class="inputfield">
<label>First Name</label>
<input type="text" class="input" name="get[firstname]">
</div> <br/>
<div class="inputfield">
<label>Last Name</label>
<input type="text" class="input" name="get[lastname]">
</div> <br/>
<div class="inputfield">
<label>Email Address</label>
<input type="text" class="input" name="get[email]">
</div>
<div class="inputfield">
<label>Phone Number</label>
<input type="text" class="input" name="get[phone]">
</div>
<button class="nextBtn">Next</button>
<section class="part2">
<div class="inputfield">
<label for="text">Choose a text:</label>
<select name="text" id="text">
<option value="1">Text1</option>
<option value="2">Text2</option>
</select>
</div>
<section class="part3">
<div class="inputfield">
<label for="text">Choose a text:</label>
<select name="text" id="text">
<option value="1">Text1</option>
<option value="2">Text2</option>
</select>
</div>
Thanks.
Wrap all in sections as part2 and part3 and try this, and include one next button in each section in order to know the section will have to show
$('.nextBtn').click(function(){
if ($(this).closest('section').find('input').val() != '') {
$('section').hide();
$(this).closest('section').next().show();
}else {
console.log('Some fields are empty')
}
})
I tried to change the default empty value "" with friendly labels however I was not successful for subcategory and name selects since data is coming dynamically from django. category works fine since there is an empty option when page loads however subcategory and name load on select data-empty_label "----------" instead and no options are visible.
<div class="form-row">
<input type="hidden" name="csrfmiddlewaretoken" value="xxxxx">
<div class="form-group custom-control col-md-3">
<select name="category" class="custom-select custom-select-lg" required id="id_category">
<option value="" selected>---------</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
</div>
<div class="form-group custom-control col-md-3">
<select name="subcategory" disabled class="custom-select custom-select-lg chained-fk" required id="id_subcategory" data-chainfield="category" data-url="/chaining/filter/xxxxx" data-value="null" data-auto_choose="false" data-empty_label="--------" name="subcategory">
</select>
</div>
<div class="form-group custom-control col-md-3">
<select name="name" disabled class="custom-select custom-select-lg chained-fk" required id="id_name" data-chainfield="subcategory" data-url="/chaining/filter/xxxxx" data-value="null" data-auto_choose="false" data-empty_label="--------" name="name">
</select>
</div>
<div class="form-group col-md-3">
<input type="submit" value="Submit" class="btn-lg btn-success btn-block">
</div>
</div>
<script>
$(document).ready(function() {
$("select").on("change", function() {
if($("select[name='category']").val() == "") {
$("select[name='category'] > option:first-child").text('Category');
$("select[name='subcategory']").prop('disabled', 'disabled');
$("select[name='subcategory'] > option:first-child").text('Subcategory');
$("select[name='name']").prop('disabled', 'disabled');
$("select[name='name'] > option:first-child").text('Recipe');
} else {
$("select[name='subcategory']").removeAttr("disabled");
$("select[name='subcategory'] > option:first-child").text('Subcategory');
}
}).trigger('change');
$("select[name='subcategory']").on("change", function() {
$("select[name='subcategory'] > option:first-child").text('Subcategory');
if($(this).val() == "") {
$("select[name='name']").prop('disabled', 'disabled');
$("select[name='recipename'] > option:first-child").text('Recipe');
} else {
$("select[name='name']").removeAttr("disabled");
$("select[name='ename'] > option:first-child").text('Recipe');
}
}).trigger('change');
});
</script>
I currently have a dropdown field that onchange will input the value.
function CurrentStatusChanged() {
var currentS1 = document.getElementById("currentStatus1").value;
var currentS2 = document.getElementById("currentStatus2").value;
document.getElementById("currentStatusView1").innerHTML = "You selected: " + currentS1;
document.getElementById("currentStatusView2").innerHTML = "You selected: " + currentS2;
}
I have many fieldsets created and then correct fieldset needs to show dependent on the what selected in the dropdown box.
My question is:
What is the best approach? As I don't feel innerHTML then all of the code is good practise.
<fieldset class="employed">
<h2>Employed</h2>
<!-- Textarea -->
<div class="form-group">
<label class="col-md-4 control-label" for="partTime">If Part Time, please detail your contractual hours per week</label>
<div class="col-md-4">
<textarea class="form-control" id="partTime" name="partTime"></textarea>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="numberOfJobs">Number of Jobs</label>
<div class="col-md-4">
<input id="numberOfJobs" name="numberOfJobs" type="text" placeholder="" class="form-control input-md" required="">
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="jobDescriptionTitle">Job Description / Title</label>
<div class="col-md-4">
<input id="jobDescriptionTitle" name="jobDescriptionTitle" type="text" placeholder="" class="form-control input-md" required="">
</div>
</div>
I am trying to add a field set like the one above to a container, however i have at least 12 that change dependent on the drop-down. kindisch answer doesn't allow mt use the complete field set but is on the right track i believe.
Use templates for that. For example:
var storage = [],
select = document.getElementById("selection"),
container = document.getElementById("container");
select.addEventListener("change", function() {
var _id = select.value,
_tpl = document.getElementById(_id);
save();
container.innerHTML = _tpl.innerHTML;
update();
}, false);
// Save current state
function save() {
var _fields = container.getElementsByClassName("form-control");
for (var i = 0; i < _fields.length; i++) {
storage[_fields[i].name] = _fields[i].value;
}
}
// Fill input fields of element
function update() {
var _fields = container.getElementsByClassName("form-control");
for (var i = 0; i < _fields.length; i++) {
if (_fields[i].name in storage) {
_fields[i].value = storage[_fields[i].name];
}
}
}
<select id="selection">
<option value="status-one">One</option>
<option value="status-two">Two</option>
<option value="status-three">Three</option>
</select>
<div id="container"></div>
<script type="text/html" id="status-one">
<fieldset class="employed">
<h2>Employed</h2>
<!-- Textarea -->
<div class="form-group">
<label class="col-md-4 control-label" for="partTime">If Part Time, please detail your contractual hours per week</label>
<div class="col-md-4">
<textarea class="form-control" id="partTime" name="partTime"></textarea>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="numberOfJobs">Number of Jobs</label>
<div class="col-md-4">
<input id="numberOfJobs" name="numberOfJobs" type="text" placeholder="" class="form-control input-md" required="">
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="jobDescriptionTitle">Job Description / Title</label>
<div class="col-md-4">
<input id="jobDescriptionTitle" name="jobDescriptionTitle" type="text" placeholder="" class="form-control input-md" required="">
</div>
</div>
</script>
<script type="text/html" id="status-two">
<p>This is status two.</p>
</script>
<script type="text/html" id="status-three">
<p>This is status three.</p>
</script>
could you use html5 data attributes? https://jsfiddle.net/hj6bbgbd/
<select id="mySelect" onchange="myFunction()">
<option value="1" data-text = "text for choice one">One</option>
<option value="2" data-text = "text for choice two">Two</option>
<option value="3" data-text = "text for choice three">Three</option>
</select>
<fieldset>
<fieldset>
<legend>My Legend:</legend>
<p id="demo"> text for choice one </p>
</fieldset>
<script>
function myFunction() {
var sel = document.getElementById('mySelect');
var opt = sel.options[sel.selectedIndex];
document.getElementById("demo").innerHTML = opt.dataset.text;
}
</script>
So, what I want to accomplish here is to prevent people from entering the rest of the form until they focus on the first section by hiding the last section until the value of a certain field is greater than nothing.
Here is my HTML:
<div class="fieldcontainer">
<label>E-mail:</label>
<input type="email" name="email" maxlength="100" id="email" required>
</div>
<br><br>
<div id="projectinformation" style="display:none">
<h3>Project Information</h3>
<div class="fieldcontainer">
<label>Project Name:</label>
<input type="text" name="project_name" maxlength="70" required>
</div>
<br><br>
<div class="fieldcontainer">
<label>Project Number:</label>
<input type="text" name="project_number" required>
</div>
<br><br>
<div class="fieldcontainer">
<label>Business Unit:</label>
<select name="business_unit" required>
<option>--Select--</option>
</select>
</div>
<br><br>
<div class="fieldcontainer">
<label>Project Address:</label>
<input type="text" name="address" required>
</div>
<br><br>
<div class="fieldcontainer">
<label>Number of users on site:</label>
<select id="numberofstaff">
<option class="staffselection" value="">--Select--</option>
<option class="staffselection" value="smalljobsite">1-3 staff</option>
<option class="staffselection" value="mediumjobsite">4-7 staff</option>
<option class="staffselection" value="largejobsite">8+ staff</option>
</select>
</div>
</div>
Here is my JS:
while (document.getElementById('email').value > ""){
document.getElementById('projectinformation').style.display = 'initial';
}
You'd probably want an event handler for that, and check the inputs value length, then show the rest of the form
document.getElementById('email').addEventListener('input', function() {
if ( this.value.length > 0 ) {
document.getElementById('projectinformation').style.display = 'block';
}
}, false);
or in jQuery
$('#email').on('input', function() {
if (this.value.length > 0) $('#projectinformation').show();
});
Here is jQuery solution:
$("#email").keyup(function() {
if($(this).val().length)
$('#projectinformation').show();
else
$('#projectinformation').hide();
});
If you want to validate if it is a valid email and then show the form, you can do this: (https://stackoverflow.com/a/2855946/1845408):
function isValidEmailAddress(emailAddress) {
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))#((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
return pattern.test(emailAddress);
};
$("#email").keyup(function() {
if(isValidEmailAddress($(this).val())) {
$('#projectinformation').show();
else
$('#projectinformation').hide();
});
here is the situation the html
<div id="editUser-0" style="display: none;">
<form action="/admin/uactions.php" method="post" enctype="multipart/form-data" class="form-horizontal" id="userEditorForm-0">
<input type="hidden" name="id" id="id" value="0" />
<input type="hidden" name="action" id="action" value="edituser" />
<div class="control-group">
<label class="control-label" for="name">Име</label>
<div class="controls">
<input type="text" id="name-0" name="name" class="validate[required]" placeholder="Име" value="">
</div>
</div>
<div class="control-group" >
<label class="control-label" for="email-0">Имейл</label>
<div class="controls">
<input type="text" id="email-0" class="validate[required,custom[email]]" name="email" placeholder="Имейл" value="">
</div>
</div>
<div class="control-group">
<label class="control-label" for="type-0" >Тип</label>
<div class="controls">
<select name="type" id="type-0">
<option value="1" >Администратор</option>
<option value="100" >Потребител</option>
</select>
</div>
</div>
<div class="control-group hidden" id="avatarWarper-0">
<label class="control-label" for="avatar-0">Снимка</label>
<div class="controls">
<input type="file" name="avatar" id="avatar-0" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="typeinvestor-0">Тип инвеститор</label>
<div class="controls">
<select name="typeinvestor" id="typeinvestor-0" >
<option value="0">-</option>
<option value="1">Investor type 1</option>
<option value="2">Investor type 2</option>
<option value="3">Investor type 3</option>
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="phone-0" >Телефон</label>
<div class="controls">
<input type="text" id="phone-0" name="phone" placeholder="Телефон" class="validate[required]" value="">
</div>
</div>
<div class="control-group">
<label class="control-label" for="country-0">Държава</label>
<div class="controls">
<select name="country" id="country-0" class="validate[required]">
<option value="ZW">Zimbabwe</option>
</select>
</div>
</div>
</form>
</div>
and here is the javascript
function editUser(id) {
title = "Change user";
if (id === 0)
title = 'New user';
$('<div>' + $('#editUser-' + id).html() + '</div>').dialog({
modal: true,
width: 450,
title: title,
buttons: {
'Save': function() {
$('#userEditorForm-'+id).validationEngine('attach',{promptPosition : "inline", scroll: true});
if($('#userEditorForm-'+id).validationEngine('validate')){
$('#userEditorForm-'+id).submit();
}
},
'Cancel': function() {
$(this).dialog('close');
return false;
}
},
open: function(event, ui) {
$('.ui-dialog :button').blur();
$("select[id='type-"+id+"']").click(function(){
if($(this).val()==1){
$("div[id='avatarWarper-"+id+"']").removeClass('hidden');
}else{
$("div[id='avatarWarper-"+id+"']").addClass('hidden');
}
});
$('#type-'+id).click();
},
close: function(event, ui) {
$(this).dialog('destroy');
$(this).remove();
}
});
}
the problem is, when i use $("div[id='avatarWarper-"+id+"']").click(function(){}) it works but when i try to use $("#avatarWarper-"+id).click(function(){}); and this is only when in the open event of the dialog, but for example the submit and validate works both ways.
$("div[id='avatarWarper-"+id+"']")
and
$("#avatarWarper-"+id)
are both absolutely valid and look nearly equal but significantly differ in one point:
The first returns a set of Elements with ID 'avatarWarper-"+id while the latter gives you the first Element in the DOM with the given ID.
So the only error I could think if is that you assigned this ID to more than one elements in the dom (which is not allowed in terms of valid HTML but wont throw any obvious error).
You are creating a copy of the #editUser-*'s content ending up with invalid markup.
$('<div>' + $('#editUser-' + id).html() + '</div>').dialog({
...
});
When you should be using it directly, unless you have a strong reason not to.
$('#editUser-' + id).dialog({
...
});
jQuery Dialog always creates a copy of the HTML content and thus creates a repeated element with the same Id.
Using this selector $("#avatarWarper-"+id) will only obtain the element present when the page loaded and not the one dynamically created by the dialog.
I just had the same issue with Fancybox. My only solution was to use a class selector instead or div[id="theid"]