Targeting Auto-Generated Fields with Incremented IDs (JavaScript) - javascript

I have a starting set of HTML fields with an Add More fields button. The user can add as many sets of fields as desired.
<input id="alpha1" name="alpha1" type="text">
<input id="beta1" name="beta1" type="text" style="display:none;">
<select id="select_box1" name="select_box1">
<option value="one">one</option>
<option value="two">two</option>
</select>
The Add More option triggers JS to creatate a new set of fields and increments the id and name by one. Code exerpted to streamline, but I can post all if requested.
// [...]
next = next + 1;
// [...]
var fieldtype_1 = '<input id="alpha' + next + '" name="alpha' + next + '">'
var fieldtype_2 = '<input id="beta' + next + '" name="beta' + next + '" style="display:none;">'
var select_options = `
<option value="one">one</option>
<option value="two">two</option>
`
var fieldtype_3 = '<select id="select_box' + next + '">' + select_options + '</select>'
The beta field needs to show/hide based on user input into a select box.
$(document).ready(function () {
toggleFields();
$("#select_box1").change(function () {
toggleFields();
});
});
function toggleFields() {
if ($("#select_box1").val() == "two") {
$("#alpha1").hide();
$("#beta1").show();
}
else {
$("#alpha1").show();
$("#beta1").hide();
}
}
The above code works as intended for my default id(1) set of fields. However, I don't know how to approach targeting all the (unknown number) of additional fields the user could potentially add to this form.

add class activeSelect to every select, you are using. binding the event to the document will allow you to dynamically change the DOM and the event will be binded to every added element
$(document).ready(function () {
toggleFields(1);
$(document).on("change", ".activeSelect", function () {
toggleFields($(this).attr("id").substr(10));
});
});
function toggleFields(id) {
if ($("#select_box"+id).val() == "two") {
$("#alpha"+id).hide();
$("#beta"+id).show();
}
else {
$("#alpha"+id).show();
$("#beta"+id).hide();
}
}

jsFiddle
Use class as single identifier for fields group and wrap the group like this:
<div class="wrapper">
<input id="alpha1" class="item alpha" name="alpha1" type="text">
<input id="beta1" class="item beta" name="beta1" type="text" style="display:none;">
<select id="select_box1" name="select_box1" class="selectClass">
<option value="one">one</option>
<option value="two">two</option>
</select>
</div>
Then toggle all elements of desired class in selected section:
$('.selectClass').on('change', function(){
var classToShow = $(this).val() == "two" ? "beta" : "alpha";
$(this).closest('.wrapper').find('.item').hide();
$(this).closest('.wrapper').find('.' + classToShow).show();
});

Related

on change selects not working well

I`m trying to make a simple select which generate the next select box...
but I cant seem to make it work
so, as you can see I'm making divs that have ID and parent, when I'm clicking on the first select the value generate the next select box with the divs and the parent value.
this is the jQuery, but for some reason I cant understand why its not working.
$(document).ready(function() {
var i = 1;
var t = '#ss' + i;
$(t).change(function() {
i++;
t = '#ss' + i;
var pick = $(this).val();
$('#picks div').each(function() {
if ($(this).attr('parent') == pick) {
$('#ss' + i).append('<option value=' + $(this).text() + ' >' + $(this).text() + '</option>');
}
$('#ss' + i).removeAttr('disabled');
})
console.log(t);
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='picks'>
<div id='29' parent='26'>Pick1</div>
<div id='30' parent='29'>Pick11</div>
<div id='31' parent='26'>Pick</div>
</div>
<select id="ss1">
<option >First pick</option>
<option value="26">Angri</option>
<option value="27">lands</option>
<option value="28">tree</option>
</select>
<select id="ss2" disabled>
<option >Secound Pick</option>
</select>
<select id="ss3" disabled>
<option>Third Pick</option>
</select>
Here is a jsfiddle jsfiddle
Is this what you were shooting for? https://jsfiddle.net/6c5t8ort/
A couple things,
var t = '#ss' + i;
$(t).change(function() {
This only adds the change event to the first dropdown. If you give jQuery a selector (a class) if will add the event to all the elements though. Also the way you had your i variable set up means it would increment on every change.
The code below only attaches a change listener to the first ss ss1 so the change function is never called when you change ss2.
var i = 1;
var t = '#ss' + i;
$(t).change(function() {
You can fix this by adding a class on each select and using $(".myClass").change(function() {
or you can just attach the listener to all selects $("select").change(function() {
Also the value for the option tag does not include a "parent" number. In this case it would be Pick, Pick1, or Pick11.
$('#ss' + i).append('<option value=' + $(this).text() + ' >' + $(this).text() + '</option>');

Trying to delete Select box using jQuery remove() function

I am trying to delete select box using jQuery remove function but it does not work. The select box itself is dynamically generated one. I want to delete the same select box if the user wants to delete the dropdown after adding. My code is:
$("#dltElement").click(function() {
$("#idSelect").remove();
});
My code to add the select boxes:
$(document).ready(function() {
var count = 3;
$("#btnCompare").click(function() {
if (count > 4) {
alert("Only 4 options are allowed");
return false;
}
$("#form-group").append(
"<select name='idSelect" + count + "' id='idSelect" + count + "'>" +
"<option>--Select Product" + counter + "--</option>" +
'<option value="p1">Product 1</option>' +
'<option value="p2">Product 2</option>' +
"</select>" + '<input type="button" value=" - " id="dltElement' + count + '" class="btn-minus pull-left" />'
);
count++;
}); // Script for adding dropdown dynamically
});
#idSelect is not present you have to use #idSelect0 or #idSelect1 ... and so on. Rather than you can lookup the events using event delegation on your #form-group to delete the closest element select closest to your input button or in your case your sibling select. This ~ is a sibling selector and will select the sibling select.
A good idea would be to add a class to your select and use that instead as we have used your class .btn-minus for listening to click events, (in case if you have more than one select all will be selected)
$("form-group").on('click', '.btn-minus' , function() {
$(this).find('~select').remove();
});
Find the sibling select and remove
Edit 2
I have added a snippet using .closest() You can check it out. Closest will try to locate the parent div with class container and remove the select and the minus button
$(document).ready(function() {
$("#form-group").on('click', '.btn-minus' , function() {
$(this).closest('.container').remove();
});
$("#btnCompare").click(function() {
var count = $("#form-group > div.container").length;
if (count >= 4) {
alert("Only 4 options are allowed");
return false;
}
//you need to have data-id="number" for all div.container, add class container and data-id to all the divs having select and button
var label = $("#form-group > div.container").last().data('id')*1+1;
$("#form-group").append(
"<div class=container data-id="+label+"><select name='idSelect" + label + "' id='idSelect" + label + "'>" +
"<option>--Select Product" + label + "--</option>" +
'<option value="p1">Product 1</option>' +
'<option value="p2">Product 2</option>' +
"</select>" + ' <input type="button" value=" - " id="dltElement' + label + '" class="btn-minus pull-left" /></div>'
);
}); // Script for adding dropdown dynamically
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="form-group">
<input type=button id=btnCompare value=btnCompare />
<div class="container" data-id="1">
<select id="idSelect1" name="idSelect1">
<option>--Select Product1--</option>
<option value="p1">Product 1</option>
<option value="p2">Product 2</option>
</select>
<input disabled type="button" class="btn-minus pull-left" id="dltElement1" value=" - ">
</div>
<div class="container" data-id="2">
<select id="idSelect2" name="idSelect2">
<option>--Select Product2--</option>
<option value="p1">Product 1</option>
<option value="p2">Product 2</option>
</select>
<input disabled type="button" class="btn-minus pull-left" id="dltElement2" value=" - ">
</div>
</div>
Edit 3:
Please find updated snippet. you need to have data-id="number" for all div.container, add class container and data-id to all the divs having select and button.
It is hard to have what you want since you can delete from the middle as well. You can have an array of deleted objects and update it everytime you delete or add into that. In this code I have added to disbaled input delete for 1 and 2 so that you can add and delete other 2. You can play around the logic.
It counts the number of divs in DOM and then checks if you are trying to add more than the limit, It then picks the last added in DOM and increments the data-id to use it as a label for the next select
Currently what you are using is called a "direct" binding which will only attach to element that exist on the page at the time your code makes the event binding call.
You need to use Event Delegation using .on() delegated-events approach, when generating elements dynamically or manipulation selector (like removing and adding classes).
i.e.
$(document).on('event','selector',callback_function)
Example
As you have defined CSS class, use the to get the select element and perform removal operation.
$("#form-group").on('click', ".btn-minus", function(){
$(this).prev('select').remove();
});
$.fn.prev()
Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector.
you are assigning the <select> element an id that ends with a number, like this :
<select name='idSelect"+count+"' id='idSelect"+count+"'>
this means you end up with something like this :
<select name="idSelect1" id="idSelect1">
...
</select>
so the selector $("#idSelect") will never hit it unless it includes that number.
The part where you add the button :
'<input type="button" value=" - " id="dltElement' + count + '" class="btn-minus pull-left" />
has that same problem.
An easy way (though arguably not the best way) to achieve what you want is this :
function removeSelect(evt)
{
var selectBox = $(evt.currentTarget).parents(".group").find("select");
//do with select box as you will
}
$(document).ready(function() {
var count = 3;
$("#btnCompare").click(function() {
if (count > 4) {
alert("Only 4 options are allowed");
return false;
}
$("#form-group").append(
"<div class='group'>
"<select name='idSelect" + count + "' id='idSelect" + count + "'>" +
"<option>--Select Product" + counter + "--</option>" +
'<option value="p1">Product 1</option>' +
'<option value="p2">Product 2</option>' +
"</select>" + '<input type="button" value=" - " id="dltElement' + count + '" class="btn-minus pull-left" onclick="removeSelect(event)" /> </div>'
);
count++;
}); // Script for adding dropdown dynamically
});

Make first option of select unselectable through arrow keys in Google Chrome

I have a select with options and when a user selects an option, it is removed from the select and displayed as a button. When the button is pressed, the option goes back to my select. Everything works fine with mouse click, but if we navigate with the arrows key, the user can select my first option which is "choose fruit". How do I make it unselectable? disabled="disabled" doesn't work. Here's a jsfiddle http://jsfiddle.net/gbjcw1wp/2/. To reproduce the problem, select a fruit, then press Up arrow key on your keyboard.
EDIT : ONLY HAPPENS IN GOOGLE CHROME.
Disabling arrow keys work, but i'd like another way of accomplishing this.
HTML:
<select id="combobox" onchange="cbchange();">
<option selected="selected">Choose Fruit</option>
<option value="apple">apple</option>
<option value="pear">pear</option>
<option value="orange">orange</option>
<option value="banana">banana</option>
</select>
<br>
<br>
<div id="buttons"></div>
Javascript :
var fieldnames = [];
var valuenames = [];
function sortComboBox() {
document.getElementById("combobox").remove(0);
var my_options = $("#combobox option");
my_options.sort(function (a, b) {
if (a.text.toUpperCase() > b.text.toUpperCase()) return 1;
if (a.text.toUpperCase() < b.text.toUpperCase()) return -1;
return 0;
});
$("#combobox").empty().append('<option>Choose Fruit</option>').append(my_options);
$('#combobox option:first-child').attr("selected", "selected");
}
function cbchange() {
var index = $('#combobox').get(0).selectedIndex;
var text = $('#combobox option:selected').text();
var selectedItem = $('#combobox').val();
$('#buttons').append('<table class="ui"><tr><td class="variable">' + text + '</td><td class="icon"><span id="' + selectedItem + '" class="icon ui" value="X" onclick="addOption(\'' + text + '\',this.id)">X</span></td></tr></table>');
$('#combobox option:eq(' + index + ')').remove();
fieldnames.push(text);
valuenames.push(selectedItem);
}
function addOption(text, selectedItem) {
for (var i = valuenames.length - 1; i >= 0; i--) {
if (valuenames[i] === selectedItem) {
valuenames.splice(i, 1);
fieldnames.splice(i, 1);
}
}
$("#combobox").append($("<option></option>").val(selectedItem).text(text));
$('#' + selectedItem).parent().parent().parent().parent().remove();
sortComboBox();
}
A simple change to your code can resolve your problem.
Give the default option some weird value. Eg:
<option value="null" selected="selected">Choose Fruit</option>
And append the follow code the the start of your cbchange() function.
if($('#combobox').val()=="null"){
return false;
}
See jsfiddle example

Setting default value of <select> element

I have a table in my webpage that captures the details of a previous order history. The table has the following columns:
Order Date Review
Now, for the review, I want to have a select dropdown with some options. When user first launches the page, I want the previous rating to show up as default in the select dropdown. Here is what my code looks like:
tds.push( {
content: '<select id="clientReview" name="clientReview" value=' + obj.get("client_review") + '>' +
'<option value=1>Hate it!</option>' +
'<option value=2>Don't love it but don't hate it.</option>' +
'<option value=3>Fantastic!</option>'
});
I was expecting that setting the value in select would set the default value in the dropdown but that's not happening. I still see the first value as default. Any idea how I can fix that?
What about setting of value after inserting of HTML to document?
HTML:
<select id="dropdown">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<input id="textField" type="text" value="2" />
JavaScript:
(function() {
var dropdown$ = $('#dropdown'),
textField$ = $('#textField');
function changeVal() {
var val = parseInt(textField$.val());
if(!!val && val > 0 && val < 4) {
dropdown$.val(val);
}
}
textField$.on('keyup', changeVal);
changeVal();
})();​
DEMO
<option value="1" selected="selected">Text</option>
See:
http://www.w3.org/wiki/HTML/Elements/option#HTML_Attributes
http://www.w3schools.com/tags/att_option_selected.asp
Based on your code example I can assume that you'll use this HTML to insert somewhere later. In this case you can have something like next code:
tds.push( {
content: '<select id="clientReview" name="clientReview" data-value="' + obj.get("client_review") + '">' +
'<option value="1" >Hate it!</option>' +
'<option value="2" >Don\'t love it but don\'t hate it.</option>' +
'<option value="3" >Fantastic!</option>' +
'</select>'
});​
function insertDropdown(td$, dropdownHTML) {
var dropdown$ = $(dropdownHTML);
dropdown$.val(dropdown$.data('value'));
td$.html(dropdown$);
}
for(var i = 0, l = tds.length; i < l; i++) {
insertDropdown($('#td-' + i), tds[i].content);
}
DEMO

jquery dynamically add html fields met mysterious problems

I am using jquery to duplicate several html fields based on user's selection. However, I met an interesting problem. In general, I am asking users to select how many applications they want:
if there is only one application:
a. One need to choose application method (for simplicity, only 'aerial' is available); b. after selecting 'aerial', it will ask you for the further information, chemically application method (CAM).
if they choose two applications, jquery code will clone and rename the necessary questions for you.
My problem is when I choose there are two applications, the sub-question 'CAM' will not show up. After some trouble shoot, I found the problem could be in this javascript :$('.app_method:last').find('select').change(function(). The statement, automatically increase my loop index by one (Can anyone tell me why this will happen?), which mismatch the code.
Here is a DEMO for my code:
Below is my html code:
<div class="articles">
<table align="center">
<tr><th><label for="id_NOA">Number of applications:</label></th><td><select name="NOA" id="id_NOA">
<option value="1" selected="selected">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select></td></tr>
<tr><th><label for="id_Ap_m">Application method 1</label></th><td><select name="Ap_m" id="id_Ap_m">
<option value="" selected="selected">Select an application method</option>
<option value="1">Aerial</option>
</select></td></tr>
<tr><th><label for="id_CAM_1">Chemical application Method (CAM) 1</label></th><td><select name="CAM_1" id="id_CAM_1">
<option value="2">2-Interception based on crop canopy</option>
<option value="9">9-Linear foliar based on crop canop</option>
</select></td></tr>
</table>
</div>
​
jquery code:
$(document).ready(function() {
//this part of code controls inputs when there is only one application
$('#id_CAM_1').attr('id', 'id_1').closest('tr').addClass('method_options').hide();
$('#id_Ap_m').change(function() {
$('tr.method_options').hide();
if ($(this).val() == "1") {
$('#id_' + $(this).val()).closest('tr').show();
}
});
i = 1;
$('.articles').find('table').addClass('table');
$('#id_Ap_m').closest('tr').addClass('app_method');
$('#id_NOA').change(function() {
var total = $(this).val();
//remove all
$('.app_method').each(function(index) {
if (index != 0) $(this).remove()
});
//create new ones
for (var i = 2; i <= total; i++) {
alert('a=' + i);
$('.app_method:first').clone().appendTo('.table').find('label').text('Application method ' + i);
$('.app_method:last').find('select').attr('name', 'Ap_m' + i).attr('id', 'id_Ap_m' + i);
alert('b=' + i);
$('<tr class="method_options_1' + i + '" style="display: none;"><th><label for="id_CAM_1">Chemical application Method (CAM)' + i + '</label></th><td><select name="CAM_1_' + i + '" id="id_1_' + i + '"><option value="2">2-Interception based on crop canopy</option><option value="9">9-Linear foliar based on crop canop</option></select></td></tr>').appendTo('.table');
alert('c=' + i);
//The following statement increase the loop index by one, which causes me problems. Can
//anyone let me know why this could happen?
$('.app_method:last').find('select').change(function() {
alert('d=' + i)
$('.method_options_1').hide();
alert('e=' + i);
if ($(this).val() == "1") {
alert('e=' + i);
$('.method_options_1' + i).show();
}
})
}
})
})​
​
I think this can be done much more simply: (fiddle: http://jsfiddle.net/QaHWz/)
<!DOCTYPE html><html><head></head><body>
<table align="center"><tbody>
<tr><th></th><td>Add Application</td></tr>
</tbody></table>
<table id="template" style="display:none"><tbody>
<tr>
<th><label for="id_Ap_m_{n}">Application method {n}</label></th>
<td>
<select class="Ap_m" name="Ap_m_{n}" id="id_Ap_m_{n}" data-application="{n}">
<option value="" selected="selected">Select an application method</option>
<option value="1">Aerial</option>
</select>
</td></tr>
<tr style="display:none" class="app_{n} method_1"><th><label for="id_CAM_{n}">Chemical Application Method (CAM) {n}</label></th><td><select name="CAM_{n}" id="id_CAM_{n}">
<option value="2">2-Interception based on crop canopy</option>
<option value="9">9-Linear foliar based on crop canopy</option>
</select></td></tr>
</tbody></table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
jQuery(function($) {
var applications = 0;
$('#add_application').click(function() {
applications++;
var last_row = $(this).closest('tr');
last_row.before(jQuery('#template tbody').html().replace(/{n}/g, applications));
});
$(document).delegate('.Ap_m', 'change', function() {
var app = $(this).data('application');
$('.app_'+app).hide();
$('.app_'+app+'.method_'+this.value).show();
});
});
</script>
</body></html>
EDIT: The problem you are having with .change() is that you are using the i variable , which gets incremented before the function is run. You need to get the value of i into the function another way. Here is one possible way you can do it:
$('.app_method:last').find('select').bind('change', { row: i }, function(event) {
var i = event.data.row;
alert('d=' + i)
// ...
});
The { row: i } bit causes jQuery to attach this data to the event object which is passed to the function. Then I create var i inside the scope of the function, which will not be affected by the i outside, and assign this value to it.

Categories