I have a form in a table with the option to duplicate a certain row (thus allowing users to add more fields as needed). The cloning works fine and the events data and handlers work fine. However when the form is submitted, the cloned form field data does not post. Below is my code for cloning the fields which works fine and solves any issue of duplicate IDs. Any suggestions/help as to why the cloned field do not submit would be absolutely appreciated.
$('#btnAddNewField').click(function() {
var currLength = $('.cloneInput').length;
var newID = new Number(currLength + 1);
var clonedField = $('#field_id' + currLength).clone(true);
clonedField[0].setAttribute('id', 'field_id' + newID);
clonedField.find(':text').each(function() {
this.setAttribute('id', this.getAttribute('id') + newID);
this.setAttribute('name', this.getAttribute('name') + newID);
});
$('#field_id' + currLength).after(clonedField);
HTML:
<tr id="field_id_1">
<td>
<table>
<tr>
<td>Pick option</td>
<td>
<select name="choice_1" id="choice_1" parent="true">
<option value="null" selected="selected">Select</option>
<option value="1">option 1</option>
<option value="2">option 2</option>
<option value="3">option 3</option>
</select>
</td>
</tr>
<tr>
<td>Pick next option</td>
<td>
<select name="next_choice_1" id="next_choice_1">
<option value="null" selected="selected">Select next</option>
</select>
</td>
</tr>
<tr>
<td>Image:</td>
<td><input type="file" name="image_1" id="image_1"/></td>
</tr>
</table>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="button" value="Add New" id="btnAddNewField" />
<input type="button" value="Remove" id="btnDelField" />
</td>
</tr>
I don't see anywhere where you are changing the name property of the cloned form fields. You will need to change this in order to not have the posted data just overwritten by the additional fields.
I think you are mistaken by how post works. You should actualy create a new name for the cloned field, as that is what is used for posting the variables. Creating a new id is only nessecary to produce valid html, but has nothing to do with the actual posting.
Related
TL;DR: I want to be able to make a selection using currently-active HTML select box, when I have multiple select boxes with the same name, but only one of them is to be active at any one time.
--
My question is this - I have multiple filename select boxes, that upon submit, always send the value of the last select box that is at the bottom of HTML that has filename name in HTTP Request. I want to find a way to send only the filename that is associated with the currently-active a_XX_row box, and not any others.
i.e. I select id of 40, I should only see the box that says "A-40 Designer and Specs", and not the 800 box. When I press submit I want POST['filename'] to have the "A-40 Designer and Specs", but instead I always get the "A-800 Designer E.xlsm", because it is the last select in the HTML file.
$('#modelid').on('change', function() {
if (this.value == 40)
$('.a_40_row').show();
else
$('.a_40_row').hide();
if (this.value == 800)
$('.a_800_row').show();
else
$('.a_800_row').hide();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form><table>
<tr>
<td>
<select name="id" id="modelid">
<option value="0">--select--
<option value="40">40
<option value="800">800
</select>
</td>
</tr>
<tr class="a_40_row" style="display: none;">
<td>Version</td>
<td>
<select name="filename">
<option selected>A-40 Designer and Specs B.xlsm</option>
<option>A-40 Designer and Specs A.xlsm</option>
</select>
</td>
</tr>
<tr class="a_800_row" style="display: none;">
<td>Version</td>
<td>
<select name="filename">
<option>A-800 Designer E.xlsm</option>
</select>
</td>
</tr>
<tr>
<td><input type="submit"></td>
</tr>
</table></form>
don't show/hide selects form.
you just need to update the second select when the first is changed
the way to do that:
const
myForm = document.forms['my-form']
, filenames =
[ { model: '40', cod: 'A-40-B', fn:'A-40 Designer and Specs B.xlsm' }
, { model: '40', cod: 'A-40-A', fn:'A-40 Designer and Specs A.xlsm' }
, { model: '800', cod: 'A-800-E', fn:'A-800 Designer E.xlsm' }
]
myForm.modelid.onchange = () =>
{
myForm.filename.innerHTML = ''
filenames
.filter(x=>x.model===myForm.modelid.value)
.forEach( filename=>
{
myForm.filename.add( new Option(filename.fn,filename.cod))
}
)
}
select,
button {
display : block;
float : left;
clear : left;
margin : .3em;
}
select {
min-width : 8em;
padding : 0 .3em;
}
<form name="my-form">
<select name="modelid" >
<option value="" selected disable >--select--</option>
<option value="40" > 40 </option>
<option value="800" > 800 </option>
</select>
<select name="filename"></select>
<button type="submit">submit</button>
</form>
Two options,
Enable/disable the element as you show it.
Populate one field with what you need.
Option 1 :
$('#modelid').on('change', function() {
//Set visibility
$('.a_40_row').toggle(this.value == 40);
//Toggle disabled
$('.a_40_row [name=filename]').prop("disabled", this.value != 40);
$('.a_800_row').toggle(this.value == 800)
$('.a_800_row [name=filename]').prop("disabled", this.value != 800);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form><table>
<tr>
<td>
<select name="id" id="modelid">
<option value="0">--select--</option>
<option value="40">40</option>
<option value="800">800</option>
</select>
</td>
</tr>
<tr class="a_40_row" style="display: none;">
<td>Version</td>
<td>
<select name="filename" disabled>
<option selected>A-40 Designer and Specs B.xlsm</option>
<option>A-40 Designer and Specs A.xlsm</option>
</select>
</td>
</tr>
<tr class="a_800_row" style="display: none;">
<td>Version</td>
<td>
<select name="filename" disbled>
<option>A-800 Designer E.xlsm</option>
</select>
</td>
</tr>
<tr>
<td><input type="submit"></td>
</tr>
</table></form>
Option 2 : - This uses HTML 5 which has issues in IE 10 and less
$('#modelid').on('change', function() {
$(".row").show();
var selVal = $(this).val();
//Go through the options
$("[name=filename] option").each(function(){
//Dont use jquerys data here, it will convert to a number when it can
//Get array of values where can display from the data attribute
var arrDisplay = this.dataset.display.split(",");
//Add the hidden property if not contained in array -- wont work in IE 10 and older
$(this).prop("hidden", !arrDisplay.includes(selVal));
//Set a default
$(this).prop("selected", $(this).data("optiondefault") && !arrDisplay.includes(selVal) )
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form><table>
<tr>
<td>
<select name="id" id="modelid">
<option value="0">--select--</option>
<option value="40">40</option>
<option value="800">800</option>
</select>
</td>
</tr>
<tr class="row" style="display: none;">
<td>Version</td>
<td>
<select name="filename">
<option data-display="40" data-optiondefault="true">A-40 Designer and Specs B.xlsm</option>
<option data-display="40">A-40 Designer and Specs A.xlsm</option>
<option data-display="800" data-optiondefault="true">A-800 Designer E.xlsm</option>
<option data-display="40,800">Hybrid</option>
</select>
</td>
</tr>
<tr>
<td><input type="submit"></td>
</tr>
</table></form>
I have a sequence of checkboxes and associated select lists. If the checkbox is checked I need to take the value of the corresponding select option and then change the total, but I can't seem to reference this value. Here is a simplified version of the HTML code:
<table>
<tr>
<td>
<input type="checkbox" name="checkboxCK[]" id="checkboxAR1" class="check" />
</td>
<td>
<select name="addonR[]" class="select-colour">
<option value="50">1 ($50)</option>
<option value="100">2 ($100)</option>
<option value="150">3 ($150)</option>
<option value="200">4 ($200)</option>
</select>
</td>
</tr>
<tr>
<td>
<input type="checkbox" name="checkboxCK[]" id="checkboxAR2" class="check" />
</td>
<td>
<select name="addonR[]" class="select-colour">
<option value="50">1 ($50)</option>
<option value="100">2 ($100)</option>
<option value="150">3 ($150)</option>
<option value="200">4 ($200)</option>
</select>
</td>
</tr> <tr>
<td>
<input type="checkbox" name="checkboxCK[]" id="checkboxAR3" class="check" />
</td>
<td>
<select name="addonR[]" class="select-colour">
<option value="50">1 ($50)</option>
<option value="100">2 ($100)</option>
<option value="150">3 ($150)</option>
<option value="200">4 ($200)</option>
</select>
</td>
</tr>
<table>
$<span id="theTotalAmount">150</span>
And the javascript code:
$("input.check:checkbox").click(function(){
//run through allcheckboxes that are checked and pull corresponding select option value
for (var i = 0; i < document.getElementsByName('checkboxCK[]').length; i++)
{
//get the value of the selected option
var s = document.getElementsByName('addonR['+i+']');
var theAmount = s.options[s.selectedIndex].value;
console.log(theAmount);
//check the checkbox is checked and if so add the corresponding select value
if(document.getElementsByName('checkboxCK['+i+']').checked)
{
totalCost = totalCost+document.getElementsByName('addonR['+i+']').value;
}
}
//rewrite the html for total amount
document.getElementById("theTotalAmount").innerHTML = totalCost;
});
I am struggling to reference the s variable.. It keeps being undefined. Can anyone see why?
Or is there a better way to achieve what I am trying to do?
The names of the checkboxes don't have a number between the square brackets in the HTML. You shouldn't put one there with your JavaScript.
document.getElementsByName('addonR[]') will give you an (array-like) HTML Collection of all the elements with that name.
Write
var s = document.getElementsByName('addonR[]')[i];
I have a problem writing a function to hide two cells depending on the selected value.
The biggest problem is that the HTML is generated and there can be one such select or eight of them. And to make things more interesting, every one of this select is placed in a separate div and while one is shown, others are hidden.
Here is the function I use to toggle cells. Cells can be shown only if selected value is 'Z', otherwise they must be hidden. It works only on the first select while other are completely ignored. I was trying to use .each() function for every element with id="selector" but there was quite a mass with element indexes and it didn't work either.
$("#selector").change(function(){
if($(this).val().trim() == 'Z'){
$("#labelToHide").toggle(true);
$("#selectToHide").toggle(true);
} else {
$("#labelToHide").toggle(false);
$("#selectToHide").toggle(false);
}
});
Here is the working JSFiddle. It might look incomplete, but it is enough to simulate real situation. Bellow is the XML code I work with from which the HTML is generated.
<xh:td class="RightColumn" id="selectToHide">
<form:selectOne ...>
<!-- form code -->
</form:selectOne>
</xh:td>
Is there some way I can make this script work only for currently shown div? Or is there some other workaround?
With the multiple use of IDs it was never going to work as you were doing it. In the following I've changed all the IDs to relevant classes and modified the script to take that into account...
HTML
<div id="divOne">
<table class="gridtable">
<tr>
<td id="allwaysShown">Allways Shown</td>
<td id="allwaysShown">
<select class="selector">
<option value="Z">Z</option>
<option value="X">X</option>
</select>
</td>
<td class="toHide">Hide this</td>
<td class="toHide">
<select>
<option value="Y">Yes</option>
<option value="N">No</option>
</select>
</td>
</tr>
</table>
</div>
<div id="divTwo">
<table class="gridtable">
<tr>
<td id="allwaysShown">Allways Shown</td>
<td id="allwaysShown">
<select class="selector">
<option value="Z">Z</option>
<option value="X">X</option>
</select>
</td>
<td class="toHide">Hide this</td>
<td class="toHide">
<select>
<option value="Y">Yes</option>
<option value="N">No</option>
</select>
</td>
</tr>
</table>
</div>
Javascript
$(".selector").change(function () {
if ($(this).val().trim() == 'Z') {
$(this).closest("tr").find(".toHide").show();
} else {
$(this).closest("tr").find(".toHide").hide();
}
});
What this now does is when a select element (with the class selector) changes, it parses up the DOM to find the row that it is contained in, and then finds all the elements with the class toHide, and either hides or shows them.
Your jsfiddle, modified...
Once you fix the issue with multiple id by changing them to class, you can use the following :
$(".selector").change(function () {
if ($(this).val().trim() == 'Z') {
$(this).parent().nextAll("td").show();
} else {
$(this).parent().nextAll("td").hide();
}
});
$(".selectToHide select").change(function () {
if ($(this).val().trim() == 'Y') {
$(this).parent('td').prev().show();
} else {
$(this).parent('td').prev().hide();
}
});
Updated fiddle
You must use unique ids, use classes instead of ids to group the elements. Instead of toggle use show / hide and assign common class to both select and label e.g. toShowHide and use single call to show hide both. I have changed the html attributes just to demonstrate you should change according to your requirement by keeping in mind that ids must be unique.
Live Demo
$(".selector").change(function () {
if ($(this).val().trim() == 'Z')
$(this).parent().siblings(".toShowHide").show();
else
$(this).parent().siblings(".toShowHide").hide();
});
In HTML id's are all unique, that means on a single page of HTML there can only be one id with the same name, if you have used #selector before, you shouldn't use it again (it won't work in the first place.)
Always use a class for this.
Here's your working code as you needed it
<div id="divOne">
<table class="gridtable">
<tr>
<td class="allwaysShown">Allways Shown</td>
<td class="allwaysShown">
<select class="selector">
<option value="Z">Z</option>
<option value="X">X</option>
</select>
</td>
<td class="hide_this">Hide this</td>
<td class="hide_this">
<select>
<option value="Y">Yes</option>
<option value="N">No</option>
</select>
</td>
</tr>
</table>
</div>
<div id="divTwo">
<table class="gridtable">
<tr>
<td class="allwaysShown">Allways Shown</td>
<td class="allwaysShown">
<select class="selector">
<option value="Z">Z</option>
<option value="X">X</option>
</select>
</td>
<td class="hide_this">Hide this</td>
<td class="hide_this">
<select>
<option value="Y">Yes</option>
<option value="N">No</option>
</select>
</td>
</tr>
</table>
</div>
JQuery
$(".selector").change(function () {
if ($(this).val().trim() == 'Z') {
$(this).closest('tr').find('.hide_this').show();
} else {
$(this).closest('tr').find('.hide_this').hide();
}
});
I'd like to make a Javascript-based web form that would generate formatted output (BBcode to be exact) based on the inputs and selections done by the user. The output should be displayed on a separate text field for easy copying and usage.
I do know how to make the HTML-based form and how the result should look like, but I'm struggling with the JavaScript code needed to generate and format it.
EDIT: I have created the HTML form below, using this example.
Now I would like to know how to use JavaScript to output text and format it to suit my needs.
<form name="example" action="#" onsubmit="checkit(); return false">
<table class="form">
<tr>
<td>Your name</td>
<td><input name="yourname" /></td>
</tr>
<tr>
<td>Who did you punish?</td>
<td><input name="punishedname" /></td>
</tr>
<tr>
<td>Punishment?</td>
<td><select name="punishment">
<option value='' selected="selected">--- Select ---</option>
<option value="mute">mute</option>
<option value="kick">kick</option>
<option value="ban">ban</option>
<option value="ipban">IP-ban</option>
</select>
</td></tr>
<tr>
<td>For how long?</td>
<td><input name="time" />
<select name="timeunit">
<option value='' selected="selected">--- Select ---</option>
<option value="minutes">minutes</option>
<option value="hours">hours</option>
<option value="days">days</option>
<option value="weeks">weeks</option>
</select></td>
</tr>
<tr><td colspan="2"><input type="submit" value="Submit form" /><br />
<input type="reset" /></td></tr>
<tr><td colspan="2"><textarea cols="30" rows="7" name="output">Output will be written here</textarea></td></tr>
</table>
You need javascript/PHP or any other languages.
To do in javascript ..
First make provide id or name attribute to you input fields and other form elements.
create a function which will be called by submitting form.
Collect values from form fields to variables
var name = document.getElementById("id_attribute_value").value; //Collects value using id attribute
var name = document.getElementByName("name_attribute_value").valueOf; //Collects value using name attribute
now to display values (say in textarea)
document.getElementById("id_attribute").value = name + punishment + other_vars; //This will put all the collected values in that textarea
To do something like this in php
Follow up this link
http://www.w3schools.com/php/php_form_validation.asp
I have a table / tbody / row that, when a user clicks on "Add Product", I want that row to be cloned and pasted underneath the previous row. In other words, the user is adding journal entry items.
What I want, is that when they first click on the "Add Product" button, I want the row to be cloned and inserted underneath. I then want that first "Add Product" button to be disabled, however, the next button has to be enabled in order to allow yet another entry to be inserted, so on and so forth.
So far, I can get the button to clone and insert the row below, and disable the first button. However, the second button, although not disabled, no longer fires the function. It is just an "empty" button.
<table id="sales-journal">
<tbody>
<tr class="sales-journal-row">
<td class="grid-40">
<select id="sales-product-id" name="sales-product-id" required="required">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
</td>
<td class="grid-20">
<input type="number" step="1" id="sales-sold-qty" name="sales-sold-qty" />
</td>
<td class="grid-20">
<input type="number" step="1" id="sales-spill-qty" name="sales-spill-qty" />
</td>
<td class="grid-20">
<button class="sales-journal-add" id="sales-journal-add" />Add Product</button>
</td>
</tr>
</tbody>
</table>
And the jquery
$('.sales-journal-add').click(function() {
var clone = $('#sales-journal > tbody:last').clone()
clone.insertAfter('#sales-journal > tbody:last');
$(this).removeAttr('id').attr('disabled', 'disabled').addClass('disabled');
});
You would need to use event delegation for the new buttons. The click events are bound initially only to the buttons that existed in DOM, but not for the ones that were cloned. SO bind the event to the container for delegation to the buttons so that it gets applied for the buttons that are created in the future when you clone your new tbody.
$('#sales-journal').on('click', '.sales-journal-add' , function() {
var clone = $('#sales-journal > tbody:last').clone()
clone.insertAfter('#sales-journal > tbody:last');
$(this).removeAttr('id').prop('disabled', true).addClass('disabled');
});
You can use .on() for jquery >=1.7 or live for older versions (deprecated).
Also as my suggestion try using prop instead of attr to set the disabled property.
Fiddle
Here, try this:
<table id="sales-journal">
<tbody>
<tr class="sales-journal-row">
<td class="grid-40">
<select id="sales-product-id" name="sales-product-id" required="required">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
</td>
<td class="grid-20">
<input type="number" step="1" id="sales-sold-qty" name="sales-sold-qty" />
</td>
<td class="grid-20">
<input type="number" step="1" id="sales-spill-qty" name="sales-spill-qty" />
</td>
<td class="grid-20">
<button class="sales-journal-add" id="1" />Add Product</button>
</td>
</tr>
</tbody>
</table>
JS:
var cur_id = $(".sales-journal-add").attr('id');
var next_id = parseInt(cur_id) + 1;
$('#sales-journal').on('click',"#" +cur_id,function() {
var clone = $('#sales-journal > tbody:last').clone();
clone.insertAfter('#sales-journal > tbody:last');
$(this).attr('disabled', 'disabled').addClass('disabled');
clone.find('.sales-journal-add:last').attr('id', next_id);
cur_id = next_id;
});
$('#sales-journal').on('click',"#" +next_id,function() {
var clone = $('#sales-journal > tbody:last').clone();
clone.insertAfter('#sales-journal > tbody:last');
$(this).attr('disabled', 'disabled').addClass('disabled');
clone.find('.sales-journal-add:last').attr('id', next_id);
});
Fiddle.