Element not getting displayed on dynamic dropdown selection - javascript

This is my code, basically, on click of button, I want to call this method addpoc() which creates a block of input boxes and a dropdown. And on the selection of dropdown option personal/workmail an input box should appear.
It is happening for the first time where I have not creating any block dynamically but after that I can see the dropdown but input box is not coming as per the selected option in the dropdown. And also for some reason this undefined is coming as well.
function addpoc() {
let el;
el += '<div class="clearfix"><div class="name"><label for="fname">First name:</label><br><input type="text" id="fname" name="fname" placeholder="Ricky"></div><div class="name"><label for="lname">Last name:</label><br><input type="text" id="lname" name="lname" placeholder="Ju"></div></div><div class="parent" style="width: 100%;"><div id="one"><select id="contact method" onchange="showMail()"><option value="workmail" selected>Work email </option><option value="personalmail">Personal Email</option></select></div><div id="two" style="display: none;"><input type="email" name="email" placeholder="Work email"></div><div id="three" style="display: none;"><input type="email" name="email" placeholder="Personal email"></div></div>'
$('#addelement').append(el);
}
function showMail() {
let selecteop = document.getElementById("contact method");
if (selecteop.value == "workmail") {
$("#two").show();
$("#three").hide();
} else {
$("#three").show();
$("#two").hide();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="clearfix">
<div class="name">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" placeholder="Ricky">
</div>
<div class="name">
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" placeholder="Ju">
</div>
</div>
<div class="parent" style="width: 100%;">
<div id="one">
<select id="contact method" onchange="showMail()">
<option value="" disabled selected hidden>Preferred contact method</option>
<option value="workmail">Work email </option>
<option value="personalmail">Personal Email</option>
</select>
</div>
<div id="two" style="display: none;">
<input type="email" name="email" placeholder="Work email">
</div>
<div id="three" style="display: none;">
<input type="email" name="email" placeholder="Personal email">
</div>
</div>
<div>
<div id="addelement"></div>
<button id="addbtn" onclick="addpoc()">Add another point of contact</button>
</div>

The function showMail should take an input that indicates which SELECT element is changed. So the first thing is to switch to onchange="showMail(this)" to pass the changed element to the function. Next you need to target the closest TWO and THREE elements. Targeting an id with # sign will always select the first occurance in the document so you need to give those divs a class name e.g. .two and .three then using jquery selectors, target to the desired one. I used .closest(".parent").find(".two") but you may find another logic to to find the nearest divs.
about undefinded: Variables defined with let must be Declared before use even with an empty value.
function addpoc() {
let el='';
el += '<br><div class="clearfix"><div class="name"><label for="fname">First name:</label><br><input type="text" id="fname" name="fname" placeholder="Ricky"></div><div class="name"><label for="lname">Last name:</label><br><input type="text" id="lname" name="lname" placeholder="Ju"></div></div><div class="parent" style="width: 100%;"><div id="one"><select id="contact method" onchange="showMail(this)"><option disabled selected>Prefered contact method</option><option value="workmail">Work email </option><option value="personalmail">Personal Email</option></select></div><div class="two" id="two" style="display: none;"><input type="email" name="email" placeholder="Work email"></div><div class="three" id="three" style="display: none;"><input type="email" name="email" placeholder="Personal email"></div></div><br>'
$('#addelement').append(el);
}
//Creating first block instead of repeating codes in html
addpoc();
function showMail(selecteop) {
if (selecteop.value == "workmail") {
$(selecteop).closest(".parent").find(".two").show();
$(selecteop).closest(".parent").find(".three").hide();
} else {
$(selecteop).closest(".parent").find(".three").show();
$(selecteop).closest(".parent").find(".two").hide();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="addelement"></div>
<button id="addbtn" onclick="addpoc()">Add another point of contact</button>
</div>

Related

jQuery: How to show next section if the first section has completed with valid input

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')
}
})

How to trigger a change in CSS from a completed Javascript event?

I am trying to find a way to change the color of text in a form as a result of passing a validation by another JavaScript function. Is there an easy way to do this?
Example of the element I want to update the color for:
<form name="contact" method="post" action="send_form_email.php" novalidate>
<div class="row">
<div class="col">
<label for="nameInput">Name:*</label>
<input name="name" type="text" class="form-control" id="nameInput" placeholder="E.g. Alan Turing" oninput="bootstrapValidate('#nameInput', 'required:Please fill out this field')">
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-6">
<label for="emailInput">Email:*</label>
<input name="email" type="email" class="form-control" id="emailInput" placeholder="E.g. name#domain.com" oninput="bootstrapValidate('#emailInput', 'email:Enter a valid E-Mail!|required:Please fill out this field')">
</div>
<div class="col-sm-12 col-md-6">
<label for="telInput">Telephone:</label>
<input name="tel" type="tel" class="form-control" id="telInput" placeholder="E.g. (01452) 714 xxx">
</div>
</div>
<div class="form-group">
<label for="msgInput">Message:*</label>
<textarea name="msg" class="form-control" id="msgInput" placeholder="E.g. Hello world!" oninput="bootstrapValidate('#msgInput', 'required:Please fill out this field')"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
For example document. GetElementById('msgInput').style.color='#ABC666';
Another way is to toglle a class containing a rule like so:
JS: document. GetElementById('msgInput').classList.add('valid');
CSS: .valid { color: #ABC666; }
Aforementioned JS code has to be placed in the event listener.
You can add CSS class to your element:
// styles.css
.warning {
color: red;
}
// scripts.js
document.getElementById('msgInput').classList.add('warning');

Show/Hide div using bootstrap checkbox - require inputs to be entered only if checkbox is checked

Ok, I've been having a really weird problem using a checkbox which collapses a hidden div using bootstrap.
if I have data-toggle="collapse" in the checkbox input attribute section, the Div Collapses but requires that every single one of the inputs inside it be filled out.
If data-toggle="collapse" is not there, the hidden div doesn't collapse, and if the checkbox is checked it requires the inputs to be entered and if it's left unchecked I can submit the form without the inputs being entered. (desired action, but the div doesn't hide or show when the checkbox is checked)
How do I hide/show the div when the checkbox is unchecked/checked AND only require the inputs if the box is checked?
I'm using this as the HTML:
<div class="col-md-1">
<input type="checkbox" onclick="ChangeShip()" href="#moreabout" data-toggle="collapse" aria-expanded="false" aria-controls="moreabout" class="form-control" id="chShipAdd" name="chShipAdd" value="no">
</div>
<label for="chShipAdd" class="col-md-3 control-label">Shipping Information?</label>
<div id="shipadddiv" style="visibility: hidden;">
<div class="collapse" id="moreabout" >
<div class="form-group">
<div class="col-md-12">
<br>
<input id="sStreet" name="sStreet" type="text" placeholder="Street Name (required)" class="form-control shipClass" required>
</div>
</div>
<div class="form-group">
<div class="col-md-4">
<input id="sCity" name="sCity" type="text" placeholder="City (required)" required class="form-control shipClass">
</div>
<div class="col-md-4">
<input id="sState" name="sState" type="text" placeholder="State (required)" required class="form-control shipClass">
</div>
<div class="hidden-lg hidden-md"> </div>
<div class="col-md-4">
<input id="sZipcode" name="sZipcode" type="text" placeholder="Zip (required)" required class="form-control shipClass">
</div>
</div>
</div>
</div>
and the javascript:
function ChangeShip() {
if (!(document.getElementById('chShipAdd').checked)) {
document.getElementById('shipadddiv').style.visibility="hidden";
$(".shipClass").prop("disabled",true);
}
else {
document.getElementById('shipadddiv').style.visibility="visible";
$(".shipClass").prop("disabled",false);
}
}
Any solution that WORKS will be acceptable. I've bashed my brain all day trying to do this simple action. I've tried .prop .attribute .setAttribute .removeAttribute, and much much more.
Any Advice?
You can use jquery to solve this quickly. You can wrap your inputs for change ship and give it and id. And let jquery do the rest.
var form = $('#myForm'),
checkbox = $('#changeShip'),
chShipBlock = $('#changeShipInputs');
chShipBlock.hide();
checkbox.on('click', function() {
if($(this).is(':checked')) {
chShipBlock.show();
chShipBlock.find('input').attr('required', true);
} else {
chShipBlock.hide();
chShipBlock.find('input').attr('required', false);
}
});
See this jsfiddle for your problem. This should help you.
your click event will toggle the display and the disabled, but when the form is loaded you will have hidden content that is not disabled.
simply call the function on document.ready
function ChangeShip() {
var show = $('#chShipAdd').prop('checked');
$('#shipadddiv').toggle(show);
$("#shipadddiv .shipClass").prop("disabled", !show);
}
$(ChangeShip); // call on document.ready
or simply add the disabled attribute to those elements so that the initial form state is valid
If the [required] attribute is still triggered on a [disabled] element you could juggle the attribute value
function ChangeShip() {
var show = $('#chShipAdd').prop('checked');
$('#shipadddiv').toggle(show);
$("#shipadddiv .shipClass").each(function(){
if (!('_required' in this))
this._required = this.required;
this.disabled = !show;
this.required = (show) ? this._required : false;
});
}
Try to do this :
HTML :
<div class="col-md-1">
<input type="checkbox" onclick="ChangeShip()" href="#moreabout" data-toggle="collapse" aria-expanded="false" aria-controls="moreabout" class="form-control" id="chShipAdd" name="chShipAdd" value="no">
</div>
<label for="chShipAdd" class="col-md-3 control-label">Shipping Information?</label>
<div id="shipadddiv" style="visibility: hidden;">
<div class="collapse" id="moreabout" >
<div class="form-group">
<div class="col-md-12">
<br>
<input id="sStreet" name="sStreet" type="text" placeholder="Street Name (required)" class="form-control shipClass" required>
</div>
</div>
<div class="form-group">
<div class="col-md-4">
<input id="sCity" name="sCity" type="text" placeholder="City (required)" required class="form-control shipClass">
</div>
<div class="col-md-4">
<input id="sState" name="sState" type="text" placeholder="State (required)" required class="form-control shipClass">
</div>
<div class="hidden-lg hidden-md"> </div>
<div class="col-md-4">
<input id="sZipcode" name="sZipcode" type="text" placeholder="Zip (required)" required class="form-control shipClass">
</div>
</div>
</div>
</div>
JQUERY :
$('#chShipAdd').change(function() {
if ($('#chShipAdd').prop('checked')) {
$('#shipadddiv').show();
} else {
$('#shipadddiv').hide();
}
});

Adding Placeholder attributes base on input label with PURE JS - no jQuery

I need to get the label of each element and apply it to the input as a placeholder attribute, I get about half way though but cannot seem to get just the text of the element in order to add a attribute
Please note that i am not able to use jQuery in any regard
JS:
var elements = document.querySelectorAll('p.form-field');
Array.prototype.forEach.call(elements, function(el, i){
var chel = el.querySelectorAll('.field-label');
console.log(chel.textContent);
});
HTML:
<form accept-charset="UTF-8" method="post" action="nottelling" class="form" id="pardot-form">
<p class="form-field first_name pd-text required ">
<label class="field-label" for="25492_61334pi_25492_61334">First Name</label>
<input type="text" name="25492_61334pi_25492_61334" id="25492_61334pi_25492_61334" value="" class="text" size="30" maxlength="32" onchange="" />
</p>
<div id="error_for_25492_61334pi_25492_61334" style="display:none"></div>
<p class="form-field last_name pd-text required ">
<label class="field-label" for="25492_61336pi_25492_61336">Last Name</label>
<input type="text" name="25492_61336pi_25492_61336" id="25492_61336pi_25492_61336" value="" class="text" size="30" maxlength="32" onchange="" />
</p>
<div id="error_for_25492_61336pi_25492_61336" style="display:none"></div>
<p class="form-field email pd-text required ">
<label class="field-label" for="25492_61338pi_25492_61338">Email</label>
<input type="text" name="25492_61338pi_25492_61338" id="25492_61338pi_25492_61338" value="" class="text" size="30" maxlength="255" onchange="piAjax.auditEmailField(this, 25492, 61338, 12545572);" />
</p>
<div id="error_for_25492_61338pi_25492_61338" style="display:none"></div>
<p class="form-field company pd-text required ">
<label class="field-label" for="25492_61340pi_25492_61340">Company</label>
<input type="text" name="25492_61340pi_25492_61340" id="25492_61340pi_25492_61340" value="" class="text" size="30" maxlength="100" onchange="" />
</p>
<div id="error_for_25492_61340pi_25492_61340" style="display:none"></div>
<p style="position:absolute; width:190px; left:-9999px; top: -9999px;visibility:hidden;">
<label for="pi_extra_field">Comments</label>
<input type="text" name="pi_extra_field" id="pi_extra_field" />
</p>
<input name="_utf8" type="hidden" value="☃" />
<p class="submit">
<input type="submit" accesskey="s" value="Send Message" />
</p>
<input type="hidden" name="hiddenDependentFields" id="hiddenDependentFields" value="" />
</form>
var labels = document.querySelectorAll("label");
var i = labels.length;
while (i--) {
var label = labels.item(i);
var text = label.textContent;
label.parentNode.classList.contains("required") && (text += "*");
label.nextElementSibling.setAttribute("placeholder", text);
}
While the earlier answers work, I'd suggest a simpler approach, such as:
function placeholderLabels() {
// get <input> elements that are in a <p> and follow a <label>:
var inputs = document.querySelectorAll('p label + input');
// iterate over those <input> elements:
Array.prototype.forEach.call(inputs, function(input) {
// input is the current <input> from the NodeList over which we're
// iterating, here we set its placeholder property to either:
// the textContent of the first <label> associated with the <input>
// or to an empty string, if there's no associated <label>:
input.placeholder = input.labels.length ? input.labels[0].textContent.trim() : '';
});
}
placeholderLabels();
function placeholderLabels() {
var inputs = document.querySelectorAll('p label + input');
Array.prototype.forEach.call(inputs, function(input) {
input.placeholder = input.labels.length ? input.labels[0].textContent.trim() : '';
});
}
placeholderLabels();
label {
display: inline-block;
width: 7em;
}
p.required label::after {
content: '*';
}
<form accept-charset="UTF-8" method="post" action="nottelling" class="form" id="pardot-form">
<p class="form-field first_name pd-text required ">
<label class="field-label" for="25492_61334pi_25492_61334">First Name</label>
<input type="text" name="25492_61334pi_25492_61334" id="25492_61334pi_25492_61334" value="" class="text" size="30" maxlength="32" onchange="" />
</p>
<div id="error_for_25492_61334pi_25492_61334" style="display:none"></div>
<p class="form-field last_name pd-text required ">
<label class="field-label" for="25492_61336pi_25492_61336">Last Name</label>
<input type="text" name="25492_61336pi_25492_61336" id="25492_61336pi_25492_61336" value="" class="text" size="30" maxlength="32" onchange="" />
</p>
<div id="error_for_25492_61336pi_25492_61336" style="display:none"></div>
<p class="form-field email pd-text required ">
<label class="field-label" for="25492_61338pi_25492_61338">Email</label>
<input type="text" name="25492_61338pi_25492_61338" id="25492_61338pi_25492_61338" value="" class="text" size="30" maxlength="255" onchange="piAjax.auditEmailField(this, 25492, 61338, 12545572);" />
</p>
<div id="error_for_25492_61338pi_25492_61338" style="display:none"></div>
<p class="form-field company pd-text required ">
<label class="field-label" for="25492_61340pi_25492_61340">Company</label>
<input type="text" name="25492_61340pi_25492_61340" id="25492_61340pi_25492_61340" value="" class="text" size="30" maxlength="100" onchange="" />
</p>
<div id="error_for_25492_61340pi_25492_61340" style="display:none"></div>
<p style="position:absolute; width:190px; left:-9999px; top: -9999px;visibility:hidden;">
<label for="pi_extra_field">Comments</label>
<input type="text" name="pi_extra_field" id="pi_extra_field" />
</p>
<input name="_utf8" type="hidden" value="☃" />
<p class="submit">
<input type="submit" accesskey="s" value="Send Message" />
</p>
<input type="hidden" name="hiddenDependentFields" id="hiddenDependentFields" value="" />
</form>
It's worth reiterating at this point, however, that this is not a good user-interface; the placeholder should not replace the <label>, and if used should provide some guidance on what the <input> expects, such as the format or an expected value.
You’re close: the problem is just that you are trying to use the object returned by the second querySelectorAll as if it were an element. It returns a collection, even when there is just one matching element. If you know that only one element matches it, simply index it with a zero. The same way you can access the input element, if you know there is only one such element inside each p element. So the essential code can be as follows:
var elements = document.querySelectorAll('p.form-field');
Array.prototype.forEach.call(elements, function(el, i){
el.querySelectorAll('input')[0].placeholder =
el.querySelectorAll('.field-label')[0].textContent;
});
There are several possible approaches, depending on the assumptions you make about the source code.
Note: Duplicating label texts as placeholders is useless and disturbing. Replacing label text by placeholders is bad for accessibility and frowened upon in the HTML5 spec. But maybe the operation you are doing has some different purpose.

jQuery's val() returns empty string on bootstrap popover input field

I have a bootstrap popup form with a few input fields. I've added a submit button to the form, that triggers client-side JS validation. However, when the button is clicked, the current value of the input fields is not captured by jQuery's val() method: I just get an empty string.
Here is the markup:
<div class="popover fade right in" style="top: -154.5px; left: 249px; display: block;">
<div class="arrow">
</div>
<h3 class="popover-title">New Job Site contact</h3>
<div class="popover-content">
<form class="popover-form form-horizontal" id="newjobsite_contact_form" accept-charset="utf-8" method="post" action="http://dev.temperature/home/#">
<div class="form-group">
<div class=" required ">
<input type="text" class="form-control" id="popover-first_name" required="1" placeholder="First name" value="" name="first_name">
</div>
<div class=" required ">
<input type="text" class="form-control" required="1" placeholder="Surname" value="" name="surname">
</div>
<div class=" required ">
<input type="text" class="form-control" required="1" placeholder="Phone" value="" name="phone">
</div>
<div class="">
<input type="text" class="form-control" placeholder="Mobile" value="" name="mobile">
</div>
<div class="">
<input type="email" class="form-control" placeholder="Email" value="" name="email">
</div>
<div class="">
<input type="url" class="form-control" placeholder="Website" value="" name="website">
</div>
</div>
<div class="popover_buttons">
<button class="btn btn-success" onclick="submit_newjobsite_contact(); return false;" type="button" id="newjobsite_contact_submit">Submit</button>
<button class="btn btn-warning" onclick="close_newjobsite_contact(); return false;" type="button" id="newjobsite_contact_cancel">Cancel</button>
</div>
</form>
</div>
</div>
Here is the JS:
function submit_newjobsite_contact() {
errors_found = validate_popover_form($('#newjobsite_contact_form'));
if (errors_found.length == 0) {
// Form values submitted to PHP code through AJAX request here
} else {
error_msg = "Please check the following errors:\n";
$(errors_found).each(function(key, item) {
error_msg += "- "+item.message+"\n";
});
alert(error_msg);
}
}
function validate_popover_form(form_element) {
found_errors = [];
$('span.error').remove();
form_element.find('select,input').each(function(key, item) {
if ($(item).attr('required') && $(item).val().length == 0) {
found_error = true;
found_errors.push({elementname: $(item).attr('name'), message: "A value for "+$(item).attr('placeholder')+" is required"});
}
console.log($(item).val()); // More validation here, just putting debugging code instead
});
return found_errors;
}
What am I doing wrong? All other attributes for these input fields are being correctly retrieved by jQuery, just not the value after I've typed text into them.
The answer to this problem couldn't be found here because I didn't post the whole source JS, which is too large. What really happened is that I accidentally cloned the popover form, which led to a duplication of the input fields.
form_element.find('select,input').each(function(key, item) {
if ($(item).attr('required') && $(item).val().length == 0) {
found_error = true;
found_errors.push({elementname: $(item).attr('name'), message: "A value for "+$(item).attr('placeholder')+" is required"});
}
I Modified it to:
form_element.find('select,input').each(function(key, item) {
if ($(this).data('required') == '1' && $(this).val().length == 0) {
found_error = true;
found_errors.push({elementname: $(this).attr('name'), message: "A value for "+$(this).attr('placeholder')+" is required"});
}
Try using data attributes so instead of using required="1" use data-required="1"
<input type="text" class="form-control" required="1" placeholder="Surname" value="" name="surname">
so your input should be like this:
<input type="text" class="form-control" data-required="1" placeholder="Surname" value="" name="surname">

Categories