I face an issue. I have written the following code:
$(document).ready(function() {
$('.show-hide').hide();
$('.dependent').on('change', function() {
if ($(this).val() == 'Anders...')
{
$('.show-hide').show();
} else {
$('.show-hide').hide();
}
});
});
But for some reason I can't get it to work properly.
It's on here:
http://go.pardot.com/l/471061/2022-03-29/6fp8dp
I am trying to show the 'Anders...' field based on the value 'Anders...' in the dropdown. But for some reason it either shows up on all answers, it doesn't show up at all OR (my best thus far) it show's on the 'Anders...' value, but doesn't disappear anymore...
Note that I have to work with class selectors due to the form builder limitations.
Please help me out, I don't see what i'm doing wrong.
Thanks!
The example you pointed to in your link is not exactly an MCVE. Therefore my answer can only be guesswork. I picked out a few bits that seemed relevant to the question posted above:
$(document).ready(function() {
$('.show-hide').hide();
$('.dependent').on('change', function(ev) {
if ($("option:selected", ev.target.selected).text() == 'Anders...') {
$('.show-hide').show();
} else {
$('.show-hide').hide();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="form-field dependent Opleidingen_Amsterdam_Arenaboulevard_61_75 pd-select required required-custom form-field-secondary dependentFieldSlave dependentField">
<label class="field-label" for="471061_186248pi_471061_186248">Opleiding *</label>
<select name="471061_186248pi_471061_186248" id="471061_186248pi_471061_186248" class="select" onchange="">
<option value="" selected="selected"></option>
<option value="2692949">Manager handel (Filiaalmanager)</option>
<option value="2699837">Anders...</option>
</select>
</p>
<p class="form-field show-hide Opleidingen_Anders pd-text required required-custom ">
<label class="field-label" for="471061_186680pi_471061_186680">Anders *
<input type="text" name="471061_186680pi_471061_186680" id="471061_186680pi_471061_186680" value="" class="text" size="30" maxlength="65535" onchange="" onfocus="" /></label>
</p>
Your change event handler is attached to all elements with class dependent. The element I found was a <p> element with a <select> inside. So, whenever the event function is triggered the this will point to the <p> DOM element. If you want to compare the selected "value" (what you really want here is the .textContent of the selected option) to the string "Anders..." then you will need to do the following:
$("option:selected", ev.target.selected).text() == 'Anders...'
with ev.target being the changed <select> element inside the <p class="... dependent ..."> element.
Related
I recently came across a situation where I was working on a huge form with atleast 60 fields and I wanted that form to only submit if all fields were filled and if not, I wanted to show a custom message (Sweetalert) for every field not filled.
For example, If first name was left empty, show the message "Please enter your first name", If country of residence was not selected, show them the message that "Please select your country of residence" so on and so forth.
While I was writing tons of if and else statements to match every field using document.getElementById(), this thought of not doing things right came into my mind. I tried searching the web for this but was unable to find a suitable way of doing such things. Can anyone suggest me a better way rather then writing if else statements of 100 lines ?
By adding a specific class to your form controls you'd be able to retrieve them and iterate through them in order to check which ones are not filled.
Let's say this is your form:
<form id="myForm" name="myForm" novalidate>
<div>
<label for="control_1">Label_1:</label>
<input type="text" id="control_1" name="control_1" class="control" />
</div>
<div>
<label for="control_2">Label_2:</label>
<input type="text" id="control_2" name="control_2" class="control" />
</div>
<div>
<label for="control_3">Label_3:</label>
<input type="text" id="control_3" name="control_3" class="control" />
</div>
<div>
<label for="control_4">Label_4:</label>
<select id="control_4" name="control_4" class="control">
<option value="option_1">Option 1</option>
<option value="option_2">Option 2</option>
<option value="option_3">Option 3</option>
</select>
</div>
<div>
<input type="submit" value="Submit!" />
</div>
</form>
Then you can use the .control class to retrieve all controls and check them:
function onSubmit(e) {
e.preventDefault();
const controls = document
.getElementById("myForm")
.querySelectorAll(".control");
controls.forEach(control => {
if (!isControlFilled(control)) {
console.log(control.id);
// Do whatever you want with control's id
}
});
}
// This is just for illustrative purposes
// Should be adapted to cover all control types
function isControlFilled(control) {
return control.value ? true : false;
}
I'm trying to show my "Embossing" textbox only when the "Style" dropdown option "Embossing" is selected. I've added the below code in my new template, product-customizable-template.liquid, which created the textbox but I want to hide it unless "Embossing" is selected.
<p class="line-item-property__field">
<label for="embossing">Embossing</label>
<input required class="required" id="embossing" type="text" name="properties[Embossing]">
</p>
"Style" Dropdown
The Style textbox has the following code:
<select class="single-option-selector single-option-selector-product-customizable-template product-form__input" id="SingleOptionSelector-0" data-index="option1">
<option value="None" selected="selected">None</option>
<option value="Embossing">Embossing</option>
<option value="Stamp">Stamp</option>
</select>
I am still working on the site, so it is not active right now.
Any help would be greatly appreciated, thank you!
You need to check on-page load and on change of select box using Javascript and you can add and remove custom code to form easily
You can check and try the below snippet for a better idea
// on change test for your condition
document.getElementById('SingleOptionSelector-0').addEventListener('change', function (e) {
_checkAndAppend();
});
// run on page load and check the for value and add if selected value meet condition
_checkAndAppend();
function _checkAndAppend() {
var item = document.getElementById('SingleOptionSelector-0');
var itemValue = document.getElementById('SingleOptionSelector-0').value;
if (itemValue == 'Embossing') {
var input = `<p class="line-item-property__field _embossing">
<label for="embossing">Embossing</label>
<input required class="required" id="embossing" type="text" name="properties[Embossing]">
</p> `;
item.parentNode.insertAdjacentHTML('beforeend',input);
} else {
if(document.querySelector('._embossing')){
document.querySelector('._embossing').remove();
}
}
}
My Javascript function checks for radio button selection and displays the appropriate drop down box. but this code is not generic, i tried using "this" but it doesn't help.. can this actually be generic?
CODE:
function change(s)
{
if(document.getElementById("viewstate").checked==true)
{
document.getElementById("state").style.display="inline";
document.getElementById("cat").style.display="none";
}
else
{
document.getElementById("state").style.display="none";
if(document.getElementById("viewcat").checked==true)
{
document.getElementById("cat").style.display="inline";
}
else
document.getElementById("cat").style.display="none";
}
}
Front end radio button
<input type="radio" name="viewrecord" value="viewstate" onchange="change('state')" required="" id="viewstate"> View by State
<select name="stat" id="state" style="display:none;">
<option selected disabled>Select State</option>
<input type="radio" name="viewrecord" value="viewcat" required="" onchange="change('cat')" id="viewcat">View By Agency
<select id="cat" name="che" style="display:none" required="">
You can try with this snippet
JS
document.addEventListener('click',function(event){
var tar = event.target.id;
if(tar ==="viewstate"){
document.getElementById("state").style.display="inline";
document.getElementById("cat").style.display="none";
}
else if(tar==="viewcat"){
document.getElementById("state").style.display="none";
document.getElementById("cat").style.display="inline";
}
},false)
WORKING COPY
What else I tried?
My primary idea was to add a class to next select tag. For example if you select radio#viewstate it will add a class to closest select element. Then just loop through all the select tag and whoever dont have this class , hide them.
But since you are using display:none nextSibling will not work.For why nextSibling wont work you can take a look at difference between it visibility:hidden
Also note in the demo that I have used label tag with input
If by generic you mean to make the function to be able to work for any similar selection process without depending on the hard-coded values of the selection inputs, this is one way I thought of doing it :
function change(selectorId, selectorClass) {
// Get all the selector elements you use.
var rS = document.getElementsByClassName( selectorClass );
// Out of the elements you fetched above, make the one with
// id = selectorId visible, rest hidden.
for(var i = 0; i < rS.length; ++i)
rS[i].style.display = (rS[i].id == selectorId) ? "inline" : "none";
}
In the HTML part add a class to every select input you want to use with the radio values:
<input type="radio" name="viewrecord" value="viewstate" onchange="change('state', 'record-selector')" required="" id="viewstate"> View by State
<select class='record-selector' name="stat" id="state" style="display:none;">
<option selected disabled>Select State</option>
<input type="radio" name="viewrecord" value="viewcat" required="" onchange="change('cat', 'record-selector')" id="viewcat">View By Agency
<select class='record-selector' id="cat" name="che" style="display:none" required="">
With this you can use the same function for similar selection process on different forms.
So my problem is I have 2 anchors one called Add Spell one called Add General Change and I want general change inputs to append right after my general champion name input one by one and right now if you add any spells and then add general change it will append after that spell.
Here is working fiddle http://jsfiddle.net/e6y5903f/ and also on the webss http://89.69.172.125/cms2.0/
Most important bits of code
$('div#ChampionInput').on('click','a.AddGeneralChange', function(){
$(this).parent().children().last().after(
'<div class="GeneralChange">\
<textarea type="text" size="20" name="GeneralChangeDescription['+$(this).parent('div').data('id')+'][]" placeholder="Enter General Change Description" />\
<select name="GeneralChange['+$(this).parent('div').data('id')+'][]">\
<option value="buff">Buff</option>\
<option value="nerf">Nerf</option>\
<option value="new">New</option>\
<option value="change">Change</option>\
<option value="bugfix">Bugfix</option>\
</select>\
Remove General Change\
</div>');
});
The function above is the one that is giving me trouble it is $(this).parent().children().last().after( part I probably have to be more specyfic.
$('div#ChampionInput').on('click', 'a.RemoveGeneralChange',function(){
$(this).closest('.GeneralChange').remove();
});
There is one more minor issue which you can test out on the website every champion has a dropdown if you have 2 champions and you will delete the first one dropdown won't show up on the last one on the site but if you will add one more it will start working again that's bizzare.
Update HTML
Add Champion
<form name="second_form" id="second_form" method="POST">
<div id="ChampionInput">
<div class="GeneralChanges">
</div>
<div class="Spells">
</div>
</div>
<br><br>
<input type="submit" name="submit">
</form>
and what I've tried in jquery
$('div#ChampionInput').on('click','a.AddGeneralChange', function(){
$(this).parent('.GeneralChanges').append(
'<div class="GeneralChange">\
<textarea type="text" size="20" name="GeneralChangeDescription['+$(this).parent('div').data('id')+'][]" placeholder="Enter General Change Description" />\
<select name="GeneralChange['+$(this).parent('div').data('id')+'][]">\
<option value="buff">Buff</option>\
<option value="nerf">Nerf</option>\
<option value="new">New</option>\
<option value="change">Change</option>\
<option value="bugfix">Bugfix</option>\
</select>\
Remove General Change\
</div>');
});
The obvious solution is to do this:
$('div#ChampionInput').on('click','a.AddGeneralChange', function(){
$(this).parent().children('.GeneralChange').last().after(
This selects the last children of the parent (presumably Champion) having the class GeneralChange and adds a new element after it. Except this only works if there already is a GeneralChange element present. Since we start with none, we can't add any. We can fix it like this:
$('div#ChampionInput').on('click','a.AddGeneralChange', function(){
var elem = $(this).parent().children('.GeneralChange');
if(elem.length == 0) {
elem = $(this).parent().children();
}
elem.last().after(
But the mix of Spell and GeneralChange is pretty bad form and could lead to more annoyances regarding DOM manipulation. It also requires more logic to keep the order of elements.
A little restructuration is in order. We go from this:
<div class="Champion">
<div class="Spell"></div>
<div class="GeneralChange"></div>
</div>
To this:
<div class="Champion">
<div class="Spells">
<div class="Spell"></div>
</div>
<div class="GeneralChanges">
<div class="GeneralChange"></div>
</div>
</div>
Then, instead of targeting the last children of a specific class, we target the container in which they are supposed to go:
$('div#ChampionInput').on('click','a.AddGeneralChange', function(){
$(this).parent().children('.GeneralChanges').first().append(
Alternative code
$('div#ChampionInput').on('click','a.AddGeneralChange', function(){
$(this).siblings('.GeneralChanges').first().append(
Javascript
$(".show").change(function(){
if ($(this).val() == "1") {
$(".text_area").show();
}
else {
$(".text_area").hide();
}
});
I want to use this code for all element with this class but, when i select option with "value 1" that make effect to all elements. Please help. Thank you.
Here is demo Click here
use $(this).next():
$(".show").change(function () {
if ($(this).val() == "1") {
$(this).next(".text_area").show();
} else {
$(this).next(".text_area").hide();
}
});
You have to make use of keyword this. $(this) works within the event of context of your selector.
As you have class name as a selector, so you should note that it returns a collection. It means if you have more than one element then it will refer to all and this refers to the event applied on the current selector in the collection.
If you happen to change the order of the html, for example place text area before the select box, it would not work. So as an alternative for the previous answer, you can wrap your groups into a div:
<div class="container">
<select class="show">
<option value="0">NO</option>
<option value="1">YES</option>
</select>
<textarea class="form-control text_area" type="text" name="text_area" placeholder="Write something" rows="5" cols="50"></textarea>
</div>
and when you are going to display/hide the text areas, you can do:
$(this).closest('.container').find('.text_area').show();
or
$(this).closest('.container').find('.text_area').hide();
Here is a demo: http://jsfiddle.net/n1fjo6qu/13/