I have two related drop-down lists, in which the contents in the second drop-down list depends on the selection made in the first one. For example, in the following HTML code, you will choose application method first. If you choose Aerial as the application method, then you will answer further question such as aerial size dist. Otherwise, you need to answer ground spray type.
So once the webpage is loaded, the two second level drop-down lists (aerial size dist., and ground spray type.) are hidden. They will appear only when related choice is made in the first one (application method).
I am able to achieve this feature in jQuery (below jQuery code). But my approach is pretty stupid. My question is:
Is there a way to select the whole row, without using counting its sequence (nth-child())? Can I choose the whole row, based on selecting an element ID ? For example, can I first select $('#id_A') and then expand my selection to the whole row?
Is there a better way (a loop?) to achieve this hide or show feature rather than comparing all the possible choices (($(this).val() == "X") )?
Thanks!
Here is the HTML code, and the form is generated by Django:
<div class="articles">
<form method="GET" action=_output.html>
<table align="center">
<tr><th><label for="id_application_method">Application method:</label></th><td><select name="application_method" id="id_application_method">
<option value="">Pick first</option>
<option value="A">Aerial</option>
<option value="B">Ground</option>
</select></td></tr>
<tr><th><label for="id_A">Aerial Size Dist:</label></th><td><select name="aerial_size_dist" id="id_A">
<option value="A1" selected="selected">A1</option>
<option value="A2">A2</option>
</select></td></tr>
<tr><th><label for="id_B">Ground spray type:</label></th><td><select name="ground_spray_type" id="id_B">
<option value="B1" selected="selected">B1</option>
<option value="B2">B2</option>
</select></td></tr>
</table>
</form>
</div>
Here is the jQuery code:
<script type="text/javascript" src=" https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
<script>$(function() {
$("tr:nth-child(2)").hide();
$("tr:nth-child(3)").hide();
$('#id_application_method').change(function() {
($(this).val() == "A") ?
$("tr:nth-child(2)").show() : $("tr:nth-child(2)").hide();
($(this).val() == "B") ?
$("tr:nth-child(3)").show() : $("tr:nth-child(3)").hide();
});});</script>
I think iKnowKungFoo's answer is very straightforward (it's got my vote). I noticed you said your form is generated by Django though. In case it's not straightforward for you to modify your generated HTML markup, here is another solution to your problem.
$(document).ready(function() {
var $aerialTr = $('#id_A').closest('tr').hide();
var $groundSprayTr = $('#id_B').closest('tr').hide();
$('#id_application_method').change(function() {
var selectedValue = $(this).val();
if(selectedValue === 'A') {
$aerialTr.show();
$groundSprayTr.hide();
} else if (selectedValue === 'B') {
$aerialTr.hide();
$groundSprayTr.show();
} else {
$aerialTr.hide();
$groundSprayTr.hide();
}
});
});
Here is a jsFiddle to test: http://jsfiddle.net/willslab/n54cE/2/
It should work with your existing markup. It selects the tr's based on the current IDs for the select boxes. If you change those IDs, you will need to modify the selectors accordingly.
I hope that helps!
Edit: Here is another alternative, "hybrid" approach inspired by iKnowKungFoo. His solution is very elegant, so I combined it with my own. This works without changes to HTML or CSS.
$(document).ready(function() {
$('#id_A').closest('tr').addClass('method_options').hide();
$('#id_B').closest('tr').addClass('method_options').hide();
$('#id_application_method').change(function() {
$('tr.method_options').hide();
$('#id_' + $(this).val()).closest('tr').show();
});
});
jsFiddle link: http://jsfiddle.net/willslab/6ASJu/3/
Your questions describe the right ideas. You just have to structure your HTML to take advantage of them.
JSFiddle posted here: http://jsfiddle.net/iknowkungfoo/TKamw/
HTML - I added an ID and CLASS to each TR that match the values in your primary SELECT:
<div class="articles">
<form method="get" action="_output.html">
<table align="center">
<tr>
<th><label for="id_application_method">Application method:</label></th>
<td><select name="application_method" id="id_application_method">
<option value="">Pick first</option>
<option value="A">Aerial</option>
<option value="B">Ground</option>
</select></td>
</tr>
<tr id="tr_A" class="method_options">
<th><label for="id_A">Aerial Size Dist:</label></th>
<td><select name="aerial_size_dist" id="id_A">
<option value="A1" selected="selected">A1</option>
<option value="A2">A2</option>
</select></td>
</tr>
<tr id="tr_B" class="method_options">
<th><label for="id_B">Ground spray type:</label></th>
<td><select name="ground_spray_type" id="id_B">
<option value="B1" selected="selected">B1</option>
<option value="B2">B2</option>
</select></td>
</tr>
</table>
</form>
</div>
CSS - hide those TRs by default:
tr.method_options { display: none; }
JavaScript/jQuery - When the primary SELECT changes, hide all TRs with a CLASS of "method_options". Then, Find the TR whose ID matches the value of the selected option in the primary SELECT and show it. If there is no match, then nothing is shown.
$(document).ready(function(){
$('#id_application_method').on('change', function() {
$('tr.method_options').hide();
$('#tr_' + $(this).val() ).show();
});
});
Related
I'm looking for a solution to dynamically change the name for a group of input radio buttons.
I'm creating a travel itinerary where the user selects "domestic" or "international." That selection will hide/show the appropriate state/country dropdown below. There could be multiple destinations, therefore, I need multiple state/country selectors. The problem I'm running into is that all the inputs have the same name, so only one button will display as "checked" at any given time.
The code snippet will come in via an .ssi, so I can't just hard code the input name. I need a JavaScript/jQuery method of dynamically changing it as more destinations are added. The default is "destination." I'd like it to be "destination1," "destination2," etc. for each radio button group.
Here's a very watered-down version of the HTML (Not looking for a debate on table-based layouts. My team has already hashed that out):
<table>
<tbody>
<tr>
<td colspan="2">
<input type="radio" checked="checked" name="destination" class="js-trigger" data-destination="stateForm"> Domestic
<input type="radio" name="destination" class="js-trigger" data-destination="countryForm"> International
</td>
</tr>
<tr>
<td>Destination:</td>
<td>
<form class="stateForm list">
<select name="State" id="state-selector" autofocus="autofocus" autocorrect="off" autocomplete="off">
<option value="Select State" selected="selected"></option>
<option value="Alabama" data-alternative-spellings="AL">Alabama</option>
<option value="Alaska" data-alternative-spellings="AK">Alaska</option>
<option value="Etc" data-alternative-spellings="Etc">Etc</option>
</select>
</form><!-- End State Form -->
<form class="countryForm list">
<select name="Country" id="country-selector" autofocus="autofocus" autocorrect="off" autocomplete="off">
<option value="Select Country" selected="selected"></option>
<option value="Afghanistan" data-alternative-spellings="AF افغانستان">Afghanistan</option>
<option value="Åland Islands" data-alternative-spellings="AX Aaland Aland" data-relevancy-booster="0.5">Åland Islands</option>
<option value="Etc" data-alternative-spellings="Etc">Etc</option>
</select>
</form><!-- End Country Form -->
</td>
</tr>
</tbody>
</table>
Here's my fiddle: http://jsfiddle.net/Currell/9sr5rkjy/2/
I'm a bit of a JavaScript beginner, so forgive me if my process, terminology, or my code is a bit off.
You could re-name them by adding this:
var counter = 0;
$('table').each(function(){
$(this).find('input[type=radio]').attr('name','destination'+counter);
counter++;
})
jsFiddle example
Update: I just noticed that all your select elements are duplicating name and ID attributes. To fix that you can change the code to:
var counter = 0;
$('table').each(function () {
$(this).find('input[type=radio]').attr('name', 'destination' + counter);
$(this).find('select').eq(0).attr({
'name': 'State' + counter,
'id': 'state-selector' + counter
});
$(this).find('select').eq(1).attr({
'name': 'Country' + counter,
'id': 'country-selector' + counter
});
counter++;
})
jsFiddle example
You need to change them in groups (currently grouped in TDs):
$("td:has(':radio')").each(function(index){
var $radio = $(this).find(':radio');
$radio.attr("name", $radio.attr('name') + index);
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/9sr5rkjy/5/
This will rename each set to name="destination0", name="destination1" etc.
You have duplicated ID fields too, which is invalid HTML, so you need to apply a similar fix to those. jQuery and Javascript can only find the first occurence of an ID as browsers use a fast lookup dictionary (with only one element stored against each ID value).
Here i come with two question one is on onload all listbox to be hide depend of radio button listbox had to show/hide listbox but its not working here and other one is i have to check if listbox option value contain null value or empty space if means i have to remove it. thats too not working there any mistake in code could some one help on this .
<script>
if ($('input[name=B]:checked').val() == "city") {
$("#country,#zone,#state,#Areamanager,#outlet").val('');
$("#country_value,#zone_value,#state_value,#Areamanager_value,#outlet_value").val('');
$("#city").show();
$("#country,#zone,#state,#Areamanager,#outlet").hide();
}
$.each(main, function (i, val) {
if (val == "Null Value" || val == "") {
val = null;
}
});
</script>
Refer the link
Had a look at the fiddle provided
Fiddle http://jsfiddle.net/Varinder/tHXN3/1/
It is considered bad practice to inline JS event calls.
Usualy it is a good indication to refactor if you notice the logic being repeated more than three times.
Correct me if im wrong, you're requirements are:
show a bunch or dependant fields based on the radio button selected
reset all the fields that are not related to currently active radio button
on page load strip off all the select box options that are either having "Null value" or simply an empty string.
A little bit of refactoring on HTML side of things can go a long way when traversing it via jQuery:
Heres the structure i reckon will suit your requirement ( more on this further down ). And i've simplified it a bit by only working on the first radio button row:
<table cellpadding="0" cellspacing="0" border="2">
<tr>
<td><input type="radio" name="A" data-dependson=".maingroup-section"/></td>
<td><font size="2">Main Group</font></td>
<td><input type="radio" name="A" data-dependson=".subgroup-section"/></td>
<td><font size="2">Sub Group</font></td>
<td><input type="radio" name="A" data-dependson=".itemname-section" /></td>
<td><font size="2">Item Name</font></td>
</tr>
</table>
<div class="form-row">
<div class="maingroup-section">
field values related to main group:<br />
<select id="maingroup">
<option value="Null Value">Null Value</option>
<option value="1">AA</option>
<option value="2">BB</option>
<option value="3">CC</option>
<option value="Null Value">Null Value</option>
</select>
<input type="hidden" id="maingroup_value" />
</div>
<div class="subgroup-section">
field values related subgroup:<br />
<select id="subgroup">
<option value="Null Value">Null Value</option>
<option value="1">DD</option>
<option value="2">EE</option>
<option value="3">FF</option>
<option value="Null Value">Null Value</option>
</select>
<input type="hidden" id="subgroup_value" />
</div>
<div class="itemname-section">
field values related to itemname:<br />
<select id="itemname">
<option value="Null Value">Null Value</option>
<option value="1">GG</option>
<option value="2">HH</option>
<option value="3">II</option>
<option value="Null Value">Null Value</option>
</select>
<input type="hidden" id="itemname_value" />
</div>
</div>
First things first, you'll notice the use of data-attributes in this case its data-dependson which contains class name of div containing dependant fields
JS
Start off by caching references to all the elements that will be (ab)used:
var $aGroupRadioButtons = $("input[name='A']");
var $formRow = $(".form-row");
var $allDropdowns = $formRow.find("select");
Handling FormSections ( .maingroup-section, .subgroup-section etc ) can be abstracted away in a function like below, it takes reference to currently active formsection and hides and resets the value of sibling form sections.
function handleFormSections( $formSection ) {
var $currentFormSection = $formSection.show();
var $otherFormSections = $currentFormSection.siblings().hide();
resetFormSections( $otherFormSections );
}
And resetFormSections function resets input and select elements of the form sections provided by the argument
function resetFormSections( $formSections ) {
$formSections.find("select").val("");
$formSections.find("input").val("")
}
Well, the above two functions are good enough to show dependant form section, hide and reset other form sections.
Now you can hook up those functions via event handlers, im using jQuery 1.8 so i can use $(selector).on("event", handler) syntax.
$aGroupRadioButtons.on("click", function(e) {
var $radioItem = $( this );
var dependantSectionName = $radioItem.attr("data-dependson");
var $dependantSectionElement = $( dependantSectionName );
handleFormSections( $dependantSectionElement )
});
As from the code above, its looking at the data-dependson value to identify which form section to show and which ones to hide.
And somewhere along the line you'd want to strip off empty or null values. Again, how about we create a function to handle that for us? and maybe call it removeNullOrEmptyOptionsFrom( selectBox ) which will recieve a selectBox element to work on, heres how:
function removeNullOrEmptyOptionsFrom( selectBox ) {
var $selectBoxOptions = $(selectBox).children();
$selectBoxOptions.each(function() {
var $option = $(this);
var optionValue = $option.attr("value");
if ( optionValue == "Null Value" || optionValue == "" ) {
$option.remove();
}
});
}
Now, you can call the above function on every select box in the .form-row container like below:
$allDropdowns.each(function() {
removeNullOrEmptyOptionsFrom( this );
});
I noticed in your code there is a call to combobox method, if it is a jQuery plugin then probably a good idea to call it after we've stripped off all the null or empty options:
// $allDropdowns.combobox(); // initialize combox once maybe after reseting selects?
I would like to do to auto select in check box when the selection box is selected in the same row.
Although I found this question in stackoverflow, unfortunately it didn't match my requirement. So, please give me some suggestions.
There are many rows in a table. In each row, there has one check box and one selection box in each column.If I selected something in selection box in a row, I want to do auto check in check box in the same row.
I wrote the code as the following.
<script>
$(document).ready(function() {
$('.sel_ActList_status').change(function() {
$('.sel_ActList_status').parent('td').silbings('td').find(".chk_ActList_select").checked = true;
//$('.sel_ActList_status').parent('td').silbings('td').find(".chk_ActList_select").prop("checked", true);
});
});
</script>
<table>
<tr>
<td>
<input id="chk_ActList_select[0]" class="chk_ActList_select" type="checkbox" value="true" name="chk_ActList_select[0]">
</td>
<td>xxxxx</td>
<td>
<select id="sel_ActList_status" class="sel_ActList_status" name="sel_ActList_status">
<option selected="selected" value="2">11111</option>
<option value="0">22222</option>
<option value="1">33333</option>
</select>
</td>
</tr>
<tr>
<td>
<input id="chk_ActList_select[1]" class="chk_ActList_select" type="checkbox" value="true" name="chk_ActList_select[1]">
</td>
<td>xxxxx</td>
<td>
<select id="sel_ActList_status" class="sel_ActList_status" name="sel_ActList_status">
<option value="2">11111</option>
<option selected="selected" value="0">22222</option>
<option value="1">33333</option>
</select>
</td>
</tr>
</table>
But my code is not working to auto check in checkbox when I selected something in selectbox. Is there anything wrong in my jquery code? Pls give me some guideline.
Thanks in advance.
Try This, this is helpfull for you
$('.sel_ActList_status').change(function(){
$(this).closest('tr').find('input:checkbox').prop('checked',true);
});
try this
$('.sel_ActList_status').change(function() {
$(this).parent('td').siblings().find(".chk_ActList_select").attr("checked", "true");
});
try this
$('.sel_ActList_status').change(function(){
$(this).parent().parent().find('input[type=checkbox]').attr('checked','checked');
});
At its simplest, I'd suggest:
$('select').change(function(){
$(this).closest('tr').find('input').prop('checked',true);
});
JS Fiddle demo.
Though if you enable checking by selecting, or changing the select-box, you should probably enable un-checking by the same route (just to retain a consistent UI), so I'd amend the select elements, adding a 'none' option (<option selected="selected" value="-1">None</option>), and, if that's selected, un-check the box:
$('select').change(function(){
var self = this;
$(this).closest('tr').find('input').prop('checked', self.value !== '-1');
});
JS Fiddle demo.
I'm trying to Show / Hide two elements based on a selection - a label and an input using Javascript getElementsByName. It works with getElementByID if I change things around on the label and input but for some reason Name isn't working. Here is the code:
<script language="JavaScript" type="text/javascript">
<!--
function Toggle(obj){
var val=obj.value;
if (!obj.m){ obj.m=''; }
if (!obj.m.match(val)){ obj.m+=','+val+','; }
var hide=obj.m.split(',');
for (var zxc0=0;zxc0<hide.length;zxc0++){
if (document.getElementsByName(hide[zxc0])){
document.getElementsByName(hide[zxc0]).style.display='none';
}
}
var show=val.split(',');
for (var zxc1=0;zxc1<show.length;zxc1++){
if (document.getElementsByName(show[zxc1])){
document.getElementsByName(show[zxc1]).style.display='';
}
}
}
//-->
</script>
and here are for form elements:
<div id="styled-select">
<select name="how" onchange="Toggle(this);" class="dropdown">
<option value="Internet Search">Internet Search</option>
<option value="Facebook" >Facebook</option>
<option value="Twitter" >Twitter</option>
<option value="LinkedIN" >LinkedIN</option>
<option value="Referral">Referral</option>
<option value="Other">Other</option>
</select>
</div>
<label name="Referral" style="display:none;">Referred By:</label>
<input name="Referral" style="display:none;" value="" class="hidden-txt">
When the user selects "Referal" it should display the Label and Input named "Referral". I had this working if I used getElementByID, gave the option two values separated by comma and used seperate IDs for the label and input.
Thank you for your help.
var elems = document.getElementsByName(hide[zxc0]);
if(elems) {
for(var i = 0;i < elems.length;i++) {
elems[i].style.display='none';
//Do whatever else you need to do with the element.
}
}
As mentioned by Kevin Boucher, getElementsByName returns an array. Assuming that you want to apply the display=none style to all elements with that name, the code above will achieve that. Also for performance's sake, the above code only calls document.getElementsByName() once as opposed to the 3+ times above which I'm sure will be beneficial.
It might be worth investigating JQuery for its ease of selecting elements.
UPDATE: The original question asked was answered. However, the code revealed for all. So, I've modified my question below:
So I have the following dynamically generated html via php
<div class="image-link link-posttypes mainSelector1">
<select id="wp_accordion_images[20110630022615][post_type]" name="wp_accordion_images[20110630022615][post_type]">
<option value="">default</option>
<option value="post" class="post-type">Post</option><option value="page" class="post-type">Page</option><option value="dp_menu_items" class="post-type">Menu Items</option>
<option value="wps_employees" class="post-type">Employees</option><option value="custom-link">Custom Link</option>
</select>
</div>
<div class="image-link link-pages1">
<select id="wp_accordion_images[20110630022615][page_id]" name="wp_accordion_images[20110630022615][page_id]">
<option value="50" class="level-0">About</option>
<option value="65" class="level-0">Contact</option>
<option value="2" class="level-0">Sample Page</option>
<option value="60" class="level-0">Staff</option>
</select>
</div>
<div class="image-link link-posts1">
<select onchange="javascript:dropdown_post_js(this)" id="wp_accordion_images[20110630022615][post_id]" name="wp_accordion_images[20110630022615][post_id]">
<option value="http://localhost/tomatopie/?p=1" class="level-0">Hello world!</option>
</select>
</div>
<div class="image-link link-custom1">
<input type="text" size="25" value="" name="wp_accordion_images[20110630022615][image_links_to]">
</div>
***THEN IT REPEATS four times: where the #1 goes to 2..3...4 (max to 4 at this time).
I have the ability to label div .classes, select #ids, and option classes. However, what I want to be able to do is based on the option selected from div .link-posttypes, I want to reveal .link-pages (if page is selected) or .link-posts (if post is selected) and .link-custom for all others (except the default).
So as written on the screen there should only be the initial div, and once the user selects an item, the appropriate div appears.
I have never developed anything in jQuery or javascript. This is my maiden voyage. Any help will be greatly appreciated!
***Also, this will be loaded via an external js file.
Here is the final answer that worked:
jQuery(document).ready(function($) {
$(".link-posttypes select").change(function(){
var selectedVal = $(":selected",this).val();
if(selectedVal=="post"){
$(this).parent().nextAll(".link-pages").hide();
$(this).parent().nextAll(".link-posts").slideDown('slow');
$(this).parent().nextAll(".link-custom").hide();
}else if(selectedVal=="page"){
$(this).parent().nextAll(".link-pages").slideDown('slow');
$(this).parent().nextAll(".link-posts").hide();
$(this).parent().nextAll(".link-custom").hide();
}else if(selectedVal!=""){
$(this).parent().nextAll(".link-pages").hide();
$(this).parent().nextAll(".link-posts").hide();
$(this).parent().next().nextAll(".link-custom").slideDown('slow');
}else{
$(this).parent().nextAll(".link-pages").hide();
$(this).parent().nextAll(".link-posts").hide();
$(this).parent().nextAll(".link-custom").hide();
}
});
});
jQuery(document).ready(function($) {
$(".image-content select").change(function(){
var selectedVal = $(":selected",this).val();
if(selectedVal=="content-limit"){
$(this).parent().next().nextAll(".content-limit-chars").slideDown('slow');
$(this).parent().nextAll(".content-custom").hide();
}else if(selectedVal=="custom-content"){
$(this).parent().nextAll(".content-limit-chars").hide();
$(this).parent().next().nextAll(".content-custom").slideDown('slow');
}
});
});
Thanks for your help!
Assuming that you're outputting proper IDs, you can do something like this (note I replaced the id):
$(window).load(function(){
// hide all the divs except the posttypes
$('.image-link').not('.link-posttypes').hide();
$('#wp_accordion_images_20110630022615_post_type').change(function() {
var divSelector = '.link-' + $(this).val();
$('.image-link').not('.link-posttypes').hide();
$(divSelector).show();
});
});
Also, consider changing your options like this:
<option value="posts" class="post-type">Post</option>
<option value="pages" class="post-type">Page</option>
<option value="menu_items" class="post-type">Menu Items</option>
<option value="wps_employees" class="post-type">Employees</option>
<option value="custom">Custom Link</option>
Here's a jsfiddle for this: http://jsfiddle.net/JrPeR/
There's my understandable jquery script
jQuery(document).ready(function($) {
$(".link-pages").hide();
$(".link-posts").hide();
$(".link-custom").hide();
$(".link-posttypes select").change(function(){
var selectedVal = $(":selected",this).val();
if(selectedVal=="post"){
$(".link-pages").hide();
$(".link-posts").show();
$(".link-custom").hide();
}else if(selectedVal=="page"){
$(".link-pages").show();
$(".link-posts").hide();
$(".link-custom").hide();
}else if(selectedVal!=""){
$(".link-pages").hide();
$(".link-posts").hide();
$(".link-custom").show();
}else{
$(".link-pages").hide();
$(".link-posts").hide();
$(".link-custom").hide();
}
});
});
Demo here. Take me couple minute to make you easy to understand. Have fun.
http://jsfiddle.net/JrPeR/3/
added a conditional so if its not the two variables it defaults to the custom.