appendTo - next to instead of below - javascript

<table id="tab" border="2">
<tbody>
<tr> <td>aaa</td><td>aaa</td></tr>
<tr> <td>bbb</td><td>bbb</td></tr>
<tr id="www"> <td><select id="sel">
<option value="one">One</option>
<option value="two">Two</option>
<option value="three">Three</option>
</select> </td><td>ccc</td></tr>
<tr> <td>xxx</td><td>xxx</td></tr>
<tr> <td>yyy</td><td>yyy</td></tr>
<tr> <td>zzz</td><td>zzzz</td></tr>
</tbody>
</table>
$("#sel").change(function(){
if( $(this).val() === 'three' )
$('<tr class="new"><td>new</td><td>new</td></tr>').appendTo('#www');
else
$('#tab tr.new').remove();
});
LIVE: http://jsfiddle.net/jSMBZ/7/
why this add new column next to #www instead of below? how can i fix it?

The two rows are being appended inside the #www td instead of after it. To add it after, you need to use the .after(content) jQuery Function like so:
$("#sel").change(function(){
if( $(this).val() === 'three' )
$('#www').after('<tr class="new"><td>new</td><td>new</td></tr>');
else
$('#tab tr.new').remove();
});
Here is the jsFiddle Link with the updated example which works as you have described: http://jsfiddle.net/jSMBZ/12/

I think rather than using appendTo you will want to use insertAfter. That way it should be inserted after the tag is closed instead of being appended to it before it's closed.

Use
$('#www').after('<tr class="new"><td>new</td><td>new</td></tr>');

Rather than append, use after (docs):
$('#www').after('<tr class="new"><td>new</td><td>new</td></tr>');
http://jsfiddle.net/9vKH4/

Related

JavaScript, append HTML and reference IDs in function

I have a form that shows a drop-down menu and a text field next to it:
<html>
<body>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select id="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc"></div></td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
Add another project
</td>
</tr>
</tbody>
</table>
</body>
</html>
You can select one of the values in the drop-down, and when you enter a numeric value into the text field, on each keyup, it'll display the value multiplied by the selected value. You can also click the "Add another project" link and it'll append/create another drop-down and text field. This already works, and is done with the following Jquery code:
<script type="text/javascript">
$(document).ready(function(){
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = `<tr>
<td scope="row">
<select id="test_project2" name="test_project[]" class="custom-select">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value2" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc2"></div></td>
</tr>`;
$(addProject).click(function(){
$(wrapper).append(projectHTML);
});
});
$('#test_value').keyup(function(){
$('#test_calc').text(Math.round($(this).val() * $("#test_project option:selected").val()));
});
The problem is I can't get the multiplication function to work/display the result for any newly appended lines. Above you can see I tried hardcoding the values of test_value2 and test_calc2 and then added this below:
$('#test_value2').keyup(function(){
$('#test_calc2').text(Math.round($(this).val() * $("#test_project2 option:selected").val()));
});
I would expect the result (at least for one new appended line) to appear in the same way as for the first line, but nothing seems to happen. My goal is to get the results to appear for the appended line, and then also find a way to have that keyup calculation function work for any number of appended lines (rather than hardcode 2, 3, 4, etc. values).
The ids, I think, will need to be dynamically assigned as the lines are appended, and then the name will stay the same to hold the arrays for test_array and test_value which I'm going to receive and process via PHP.
Thanks!
Remove all your IDs from the template rows, use classes or name="" instead as your selectors
Assign an ID to your TBODY, we'll use it as the .on() event delegator
Use the "input" event, not the "keydown" event. You can also copy/paste values, remember?
on "input" - refer to the parent TR using .closest() before descending back (using .find()) to find the elements specific for that row
Use parseInt() or parseFloat() to handle input strings. Also remember to always fallback to a number i.e: 0 to prevent NaN results
jQuery(function($) {
const projectHTML = `<tr>
<td>
<select name="test_project[]" class="custom-select">
<option value="" selected>Select</option>
<option value="10">10</option>
<option value="20">20</option>
</select>
</td>
<td><input name="test_value[]" type="type" placeholder="Enter value"></td>
<td><div class="result"></div></td>
</tr>`;
const $projects = $("#projects"); // assign an ID to your tbody
const $addProject = $('.add_project');
const arrRow = () => $projects.append(projectHTML);
// Create new row on click
$addProject.on("click", arrRow);
// Add the first row
arrRow();
// use a delegator which is not dymanic (the TBODY in this case),
// and use delegated events to any ":input" element:
$projects.on("input", ":input", function(ev) {
const $tr = $(this).closest("tr");
const $project = $tr.find('[name="test_project[]"]');
const $value = $tr.find('[name="test_value[]"]');
const $result = $tr.find(".result");
const project = parseInt($project.val(), 10) || 0;
const value = parseFloat($value.val()) || 0;
const result = project * value;
$result.text(result);
});
});
<table>
<tbody id="projects"></tbody>
<tbody>
<tr>
<td colspan="3">
Add another project
</td>
</tr>
</tbody>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
The IDs must be unique, instead whenever you add another row you duplicate the IDs.
Instead of IDs I changed them to class in order to combine this keyword with .closest() and .find() to get the values of interest.
Moreover, because you add new elements to the table you need to delegate the event.
If you change the select you need to calculate again, not only on typing into the input field.
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = '<tr>\
<td scope="row">\
<select class="test_project" name="test_project[]" class="custom-select">\
<option selected>Select</option>\
<option>10</option>\
<option>20</option>\
</select>\
</td>\
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>\
<td><div class="test_calc"></div></td>\
</tr>';
$(addProject).click(function () {
$(wrapper).append(projectHTML);
});
$(document).on('input', '.test_value', function (e) {
$(this).closest('tr').find('.test_calc').text(Math.round($(this).val() * $(this).closest('tr').find('.test_project option:selected').val() || 0));
});
$(document).on('change', '.test_project', function(e) {
$(this).closest('tr').find('.test_value').trigger('input');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select class="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>
<td>
<div class="test_calc"></div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
Add another project
</td>
</tr>
</tbody>
</table>

Using JavaScript to add TR+TD Content using one selection input

I have one selection input with about 5 options in it. I also have one empty table that will use this format:
<table>
<tr>
<td>X(for delete)</td>
<td>Option name</td>
<td>Value that is linked to that option name</td>
</tr>
</table>
So what I want is this: when someone chooses a option from the select menu it has to make one new <tr> element in the table with 3 <td>. The first is just a "X" or image so that I can delete the <tr>, the second one is the option name and the third one a value that is linked to that option.
So how can I make a program that will add the TR for me and the TD's. The second part is: how can I make it so that when the user prewses the X it deletes the entire <tr> parent. And if possible how can I add all the values together from the 3 TD and display it on screen?
I know this is a lot but is there anyone here that can help me out?
Thanks for your time.
Try this, hope it helps you in the right way:
$('button').click(function() {
$('table').append('<tr><td class="remove">X</td><td class="optionValue">' + $('select option:selected').text() + '</td><td class="linkedValue">' + $('select').val() + '</td></tr>');
})
$(document).on('click', '.remove', function() {
$(this).parent().remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<button type="button">Enter</button>
<br />
<br/>
<table>
<tr>
<td>X(for delete)</td>
<td>Option name</td>
<td>Value that is linked to that option name</td>
</tr>
</table>

Dynamically populate user input corresponding json data with jquery

I have a json data that is like this,
[
{
"metalTypeId": 1,
"metalTypeName": "copper"
},
{
"metalTypeId": 3,
"metalTypeName": "steel"
}
]
My html is structured like this:
<table id="lineItemTable">
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
</table>
What I want to do is when the user select one of the options in the dropdown, I want to populate the corresponding json data to the p tag in my td. And my table contains two identical rows.
So for example, if user select copper for the first table row, and select steel for the second table row, the corresponding p will populate text "1" and "3" to the html page. If user do not select both rows, only the row that is selected will populate corresponding data to the p tag.
I am green to jQuery so I wrote some js code but it does not work as expected:
the variable that stores the json data is named as jasonData:
$('select').on('change', function (e){
$.each(jasonData, function(i, v) {
if (jasonData.metalTypeName == $('select').val()) {
$('p').text(v.metalTypeId);
return;
}
}); //end each()
}); // end on()
By looking at my code I already know one issue, the p and select select both two table row fields, but I do not know how to correctly fix it. The code may have other issues, please advice.
Your code is very close to working. You just need to cache the active select when it triggers the change event so you can reference it later; compare the active object in your each (you were incorrectly referencing the whole array); and use a few selectors to find the right paragraph. However, you may want to consider using something closer to David's answer. It's a bit cleaner than this method.
var jasonData = [
{
"metalTypeId": 1,
"metalTypeName": "copper"
},
{
"metalTypeId": 3,
"metalTypeName": "steel"
}
];
$('select').on('change', function (e){
var selected = this;
$.each(jasonData, function(i, v) {
if (v.metalTypeName === selected.value) {
$(selected).closest('.row_to_clone').find('p').text(v.metalTypeId);
return;
}
}); //end each()
}); // end on()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="lineItemTable">
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
<tr class="row_to_clone">
<td>
<select>
<option>Select One Option</option>
<option>copper</option>
<option>steel</option>
</select>
</td>
<td>
<p></p>
</td>
</tr>
</table>
I really recommend you not to use selectors so general such as "select" and "p"; while you are expanding your code, you'll get into issues because of these so generalized; I recommend you using some classes to help you or ID's.
Also, if you can change the structure of that JSON you won't need to do that each, basically you're forcing a O(n) problem there when you can something easier.
Here's an example I wrote for you doing the functionality that you want
http://jsfiddle.net/6v4zzgjj/
Now, if you want to make the selection of the results easier you can try the following
//Rename this variable better IE jsonData;
var jasonData = {"copper": { "metalTypeId": 1,"metalTypeName": "copper"}, "steel": {"metalTypeId": 3,"metalTypeName": "steel"}};
//Now the selector could be something like
$('.metalSelector').on('change', function (e){
var value = $(this).val();
$('#result').text(jasonData[value].metalTypeId);
});
That easy!

JQuery set select from string

I have the following table
<table id="table_device">
<tr>
<td> First td </td>
<td> Second td </td>
<td>
<select class="base_MD">
<option>A value</option>
<option>Another value</option>
<option>And another one</option>
...
</select>
</td>
<td> The value </td>
</tr>
<tr></tr>
<tr></tr>
...
</table>
How do I set the <select> where the <option> matches with the 4th child (named 'The value') for each <tr> tag?
EDIT
I tried the following
$('#table_device').find('tr').each(function()
{
var value = $(this).find(':nth-child(4)').html();
$('select').each(function()
{
if($(this).text() == value)
{
var id = $(this).val();
}
$(this).eq(id).prop('selected', true);
})
});
But it did not work ...
I'm sure it's not that complicated but my head will explode soon
You can iterate over each select element. get the text from next td and use it to set option by text. Like this:
$('#table_device select').each(function(){
var nexttdtext = $(this).parent().next('td').text();
$(this).find("option").filter(function() {
return this.text == nexttdtext;
}).attr('selected', true);​
});
Working Demo
Bind an onchange event to the list. Find the selected option and the text inside it. And put it in the first row, last cell...
$(function() {
$('.base_MD').on('change', function() {
var value = $(this).find(':selected').text();
$('#table_device tr:first-child td:last-child').text( value );
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table_device">
<tr>
<td> First td </td>
<td> Second td </td>
<td>
<select class="base_MD">
<option>A value</option>
<option>Another value</option>
<option>And another one</option>
...
</select>
</td>
<td> The value </td>
</tr>
<tr></tr>
<tr></tr>
...
</table>

Get all selects after a current select element in a row

Let's say I have a table like this with multiple selects in very row:
<table>
<tr>
<td>
<select name="selectA" id="selectA">
....
</select>
</td>
<td>
<select name="selectB" id="selectB">
....
</select>
</td>
<td>
<select name="selectC" id="selectC">
....
</select>
</td>
</tr>
<tr>
<td>
<select name="selectA2" id="selectA2">
....
</select>
</td>
<td>
<select name="selectB2" id="selectB2">
....
</select>
</td>
<td>
<select name="selectC2" id="selectC2">
....
</select>
</td>
</tr>
<tr>
<td>
<select name="selectA3" id="selectA3">
....
</select>
</td>
<td>
<select name="selectB3" id="selectB3">
....
</select>
</td>
<td>
<select name="selectC3" id="selectC3">
....
</select>
</td>
</tr>
</table>
What I want to do is, when a select element changes, I want to get all select elements in the same row after the changed select element and change something with them as well.
So if selectA changes, I want to get selectB and selectC. If selectB changes, I want to get selectC. And so on. How to do that with jQuery?
Try this:
$('select').change(function() {
$(this).parent().nextAll().find('select')...
});
i.e. take the element's .parent() (which will be the <td>), then for all of its following siblings .nextAll(), .find() all <select> elements within them.
There are many jquery plugins that facilitate creating cascading dropdowns, which, in a nutshell, is what you want to achieve.
Here's a google search on "cascading dropdown jquery"; pretty much every result is a jQuery plugin :)
A slight modification of the Alnitak solution would be to bind the event handler on table level instead, so that you end up with only one function bound doing the job:
$('table').change(function(event) {
$(event.target).parent().nextAll().find('select')...
event.stopPropagation();
});
This will get you all the selects that are in the same row:
$("table select").change(function(){
var $select_mates=$('select', $(this).closest('tr'));
});
If you don't want the element itself:
$("table select").change(function(){
var $me=$(this);
var $select_mates=$('select', $me.closest('tr')).not($me);
});
My solution uses the jQuery Selector Context.
EDIT: Now I recognized I haven't seen after a current select element :). Let's see:
$("table select").change(function(){
var $me=$(this);
var $select_mates=$('select', $me.closest('tr'));
var $select_after_mates=$select_mates.slice($select_mates.index($me)+1);
});
Ok, this works, I've finally figured out how to do this:
$("table select").change(function(){
$(this).parent().nextUntil().find("select option:first").attr("selected", "selected");
});
i would try something like
//"obj" being your <select> HTML element
jQuery(obj).parent().find("select").not(obj);
UPDATE
I know the answer is already there but i thought for completeness I'd add a fix:
//"obj" being your <select> HTML element
// .parent().parent() gets the row
// .find("select" finds all the selects contained somewhere in that row.
// .not(obj) removes your current <select>
jQuery(obj).parent().parent().find("select").not(obj);

Categories

Resources