How to assign a different name for each radio input group - javascript

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).

Related

Increment name tag for cloned elements

I have a form with cloned elements. The method of the form is POST. When I dump the result of the POST only the final 'select' box value is shown because they are all the same. How can I change the name tag to the cloned elements?
JSFiddle: https://jsfiddle.net/hLefegxz/
HTML
<div id="employees-div">
<label for="employees">Employee(s)</label>
<div class="select-wrapper" id="select-employees">
<select id="employees" name="employees" >
<option value="" selected disabled>- Select Employee -</option>
<option value="1"> Jason Bourne </option>
<option value="2"> James Bond </option>
<option value="3"> Ethan Hunt </option>
</select>
</div>
JS for the Clone
$(function() {
$("#addMore").click(function(e) {
var newSelect = $("#select-employees").clone();
newSelect.val("123");
$("#employees-div").append(newSelect);
});
});
At the moment all fo the elements have the same name tag of employees. It obviously needs to be different to go into the $_POST array. How can I go about making them different? I was thinking maybe of incrementing and keeping a count? It Currently is like so:
Don't worry about changing the name, you can and should use an array for the name, but you should worry about the id, since ids must be unique and you are cloning elements without changing the id of the new element.
By adding the [] to the input name it will be sent to the server as an array, for example, if you're using PHP you can get them from $_GET['employees'] which will be an array you can loop thru.
$(function() {
$("#addMore").click(function(e) {
var newSelect = $('select[name="employees[]"]:first').clone();
$("#select-employees").append("<br>");
$("#select-employees").append(newSelect);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="employees-div">
<label for="employees">Employee(s)</label>
<div class="select-wrapper" id="select-employees">
<select name="employees[]" >
<option value="" selected>- Select Employee -</option>
<option value="1"> Jason Bourne </option>
<option value="2"> James Bond </option>
<option value="3"> Ethan Hunt </option>
</select>
</div>
<button id=addMore>+ Employee</button>
Instead of using a name and increasing an integer on each "new employee", you could simply name your select to employees[]. That will send every employee in an array format to your server, allowing you to use an easy loop.
Your code as another problem though. ID should be unique, so every time you clone your select, you should change the ID.

can't update siblings in HTML document

I have the following HTML
<td>
<select tabindex="1" id="global_location_id" name="global_location_id">
<option value="0">-- NONE --</option>
<option value="15" style="font-weight: bold">canada</option>
<option value="16" style="font-weight: bold">usa</option>
</select>
<input tabindex="1" id="location_id" name="location_id" value="15" type="hidden">
</td>
When the item in the drop down list changes, I want to save the value in a hidden field... that's a sibling to the drop down.
I have the following jquery code:
$("body").live("change", "#global_location_id", function(e){
console.log(e);
var list = e.target;
var selected_location_value = $(list).val();
console.log(selected_location_value);
//save this value in the sibling <input> box called name=location_id
$(this).siblings("#location_id").attr('value',selected_location_value);
});
I must have a syntax error somewhere because this code is not working. Specifically, it's the line that attempts to save to the hidden input field called location_id that is not updating.
I'm sure it's something simple I'm missing.
Thanks.
I found my mistake.
I had to replace
$(this).siblings("#location_id").attr('value',selected_location_value)
with
$(list).siblings("#location_id").attr('value',selected_location_value)

Click Event and option 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?

jQuery: Conditional show an element based on drop down box selection

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();
});
});

jQuery Selector: how can I specify one select menu when I have more than one?

I have 4 select menus, all with the same products. (User is supposed to use the select menus to add products to an invoice).
So each section is composed of a select menu, a quantity text field and a price text fields. But I have FOUR of those in the same page.
Whenever I select a product from the select menu, I want to change the quantity and price. But more specifically, I would just like to know, how to find out WHICH select menu was clicked.
if the select menus have a class of product (.product), when I select a product, ALL sections are affected. But I only want to affect that specific select menu section.
$(".product").change(function(event){
alert('product picked'); // testing
});
I can't just append a number, like this: product1, product2, product3. Because then in the javascript file i would have to write 4 different functions
$(".product1").change(function(event){,
$(".product2").change(function(event){, etc.
I know this is very basic, but I need to refresh my jQuery stuff.
This is some of the form HTML. I only included product select menu and quantity text field for simplification.
<div class="item">
<p>
Product:
<select class="product" id="invoice_line_items_attributes_0_item_id" name="invoice[line_items_attributes][0][item_id]"><option value="1" data-defaultquantity="1">WP setup</option>
<option value="2" data-defaultquantity="1">WordPress Theme Design</option>
<option value="3" data-defaultquantity="1">WHE/yr</option>
<option value="4" data-defaultquantity="1">WHE/mo</option></select>
</p>
Qty: <input class="quantity" id="invoice_line_items_attributes_0_quantity" name="invoice[line_items_attributes][0][quantity]" size="30" type="text" value="1"><br>
</div><hr>
<div class="item">
<p>
Product:
<select class="product" id="invoice_line_items_attributes_1_item_id" name="invoice[line_items_attributes][1][item_id]"><option value="1" data-defaultquantity="1">WP setup</option>
<option value="2" data-defaultquantity="1">WordPress Theme Design</option>
<option value="3" data-defaultquantity="1">WHE/yr</option>
<option value="4" data-defaultquantity="1">WHE/mo</option></select>
</p>
Qty: <input class="quantity" id="invoice_line_items_attributes_1_quantity" name="invoice[line_items_attributes][1][quantity]" size="30" type="text" value="1"><br>
</div><hr>
In your event handler, this will be bound to the relevant <select> element.
$(".product").change(function(event){
alert($(this).attr('name')); // name of <select> element changed
});
A handy trick is to use "data" attributes to relate something like that <select> to the other fields. That is, you can do something like store the "id" of the related field in a data attribute so that the handler can find the field to mess with:
<select name='whatever' data-quantity-id="whatever" data-price-id="whatever">
<option ... >
</select>
Then in the handler:
$('.product').change(function(event) {
var $quantity = $('#' + $(this).data('quantityId'));
var $price = $('#' + $(this).data('priceId'));
// ...
});
$(".product").change(function(event){
$(this).closest(".section").find(".quantity").val("somevalue");
$(this).closest(".section").find(".price").val("somevalue");
});

Categories