JQuery clone and Onchange Events - javascript

I have a table with rows and input/select form elements. At the bottom row i have a button to add a new row to the Table. Initially the table is empty with just one row with a button
Like this:
<form name="test" id="test" action="#" >
<table id="matrix">
<tr id="1">
<td><select class="parent" name="parent">
<option value="C" label="C">C</option>
<option selected="selected" value="P" label="P">P</option>
<option value="B" label="B">B</option>
</select></td>
<td><div id="my_data_1">
<span title="parent_val"></span>
</div></td>
<td> </td>
</tr>
<tr >
<td colspan="3"><input type="button" class="add_new" /></td>
</tr>
</table>
</form>
Now when i click on the button with the add_new class i clone the first row, increment its id and then insert it above the last row.
The issue is that i have an onchange event attached to the select with class parent as
$('#matrix').on('change', 'select.parent_type', function() {
var RowID = $(this).closest('tr').attr('id');
var attributes_div = $('#matrix tr#'+RowID).find('div#my_data'+RowID );
new_id = GetParentIDFormat(attributes_div, 3);
$(attributes_div +"span[title='parent_val']").html(new_id);
});
When i added two or more rows, the change function changes the Value for SPAN "parent_val" for ALL the rows rather than the specific row whose SELECT parent was changed.

There were a few errors, without the GetParentIDFormat function, I cannot provide a 100% solution, but here goes:
'select.parent_type' should be 'select.parent'
$('#matrix tr#'+RowID).find('div#my_data'); should be
$('#' + RowID).find('.my_data');.
Note that you require classes, as you cannot have multiple equivalent IDs.
$(attributes_div +"span[title='parent_val']")
Should be
$("span[title='parent_val']", attributes_div)
Resulting in:
$('#matrix').on('change', 'select.parent', function() {
var RowID = $(this).closest('tr').attr('id');
var attributes_div = $('#' + RowID).find('.my_data');
var new_id = GetParentIDFormat(attributes_div, 3);
$("span[title='parent_val']", attributes_div).html(new_id);
});

The attributes_div variable points to a jQuery object, so you can't concatenate that with a string to get a selector to select the element you want. Instead just do this:
attributes_div.find('span[title="parent_val"]').html(new_id);
That will look for the <span title="parent_val"> element inside of the specific <div> referenced by attributes_div, and therefore should be the single element you want.
However, note that if you're cloning that row, you can't use an ID of my_data on all of the <div> elements as they're supposed to be unique; consider changing to a class instead.

Related

Change name of input within specific table row

I'm using a function which I've adapted to clone table rows when a certain button is clicked (see this fiddle), and assign the new row an incremented ID (i.e. table-rows-1 to table-rows-2). After creating a new row, I want a function I'm making to find an input in a td in this row and change its name from input-text-1 to input-text-2. I'm not very confident with Javascript, and am having trouble accessing the input element within the row. Heres an example:
<table>
<tbody>
<tr class="modal-rows" id="table-rows-1">
<td>
<input type="text" class="input-text" name="input-text-1">
</td>
</tr>
<tr class="modal-rows" id="table-rows-2"> <<< DUPLICATED ROW WITH INCREMENT ID
<td>
<input type="text" class="input-text" name="input-text-1">
</td>
</tr>
</tbody>
</table>
How can I access the inner inputs of this table in order to change their name? Heres what I've tried:
var rowNum = document.getElementsByClassName("modal-rows").length
$('#table-rows-' + rowNum + ' .input-text').attr('name', 'input-text-' + rowNum);
$('#table-rows-' + rowNum).find('.input-text').attr('name', 'input-text-' + rowNum);
$('#table-rows-' + rowNum).children('.input-text').attr('name', 'input-text-' + rowNum);
Can anyone let me know where I'm going wrong?
You can use below code inside your duplicate function:
clone.children[0].setAttribute('name', 'input-text'+ ++i)

How to set index variables in filters and selectors jquery

I have the following row structure that serves as a template to clone it and add it to a table each time a user presses an "Add" button, This template is hidden:
<tr class="plantilla">
<td>
<select class="cmb_arboles" id="cmb_arboles" name="arboles[]">
</select>
</td>
<td>
<input type="text" id="txttoneladas" name="txttoneladas[]"/>
</td>
<td>
<input type="text" id="txtprecio" name="txtprecio[]"/>
</td>
<td>
<select id="cmb_destino" name="destino[]">
</select>
</td>
<td class="eliminar_fila">
Eliminar
</td>
</tr>
When the "add" button is pressed, invokes:
$("#agregar").click(function()
{
nid++;
$("#plantilla tbody tr:eq(0)").clone().attr("id",nid).appendTo("#plantilla tbody");
$("#plantilla tbody tr:eq(nid)").find("td:eq(0)").find("select").attr("id","cmb_arboles_"+nid);
});
The first line, generates the sequence of the row number. The second line clones the entire template as a new row in the table and adds an id = nid to the .
The third line, accesses the row and looks for the select to add the nid sequential to the select id, but this does not work. When doing several tests, I conclude that the problem is that "tr: eq (nid)" does not accept the nid as variable, because when changing the nid by a specific integer, for example 1, it works, adding id to select. The question here is how to put the nid as a parameter in the: eq () so that it works correctly and do what I have explained ????
The same situation happens in the following line of code:
$(document).on('change', '.cmb_arboles', function () {
var $select = $(this);
var $row = $select.closest('tr');
var idd = $row.attr('id');
var valor=$("#tabla tbody tr[id=idd]").find("td:eq(0)").find("select").val();
});
Of lines 1 to 3, you get the number of the row in which you have selected in the select component.
The last line gets the value of the select that was selected, with the information of the row number where the selection was made, but this does not work. When doing several tests, I conclude that the problem is in "tr [id = idd]", which does not correctly process the variable "idd". I made the test of changing the idd by a specific integer, for example 1 and then I generate a new line in the table with id = 1 and the line of code works correctly, returning the option that was selected in the select element.
With these two examples, I want to check if someone can tell me how to place the parameters I mentioned in the two cases, so that the functionality is executed correctly and does what is expected.
I will be enormously grateful.
the issue is you have to give
("#plantilla tbody tr:eq(nid)" as (("#plantilla tbody tr:eq('"+nid+"')"
I have created a fiddle. check it out. I didn't use jquery for the same.
<style>
#template {
display: none;
}
</style>
<table><tbody id="template">
<tr class="plantilla">
<td>
<select class="cmb_arboles" id="cmb_arboles" name="arboles[]">
</select>
</td>
<td>
<input type="text" id="txttoneladas" name="txttoneladas[]" />
</td>
<td>
<input type="text" id="txtprecio" name="txtprecio[]" />
</td>
<td>
<select id="cmb_destino" name="destino[]">
</select>
</td>
<td class="eliminar_fila">Eliminar</td>
</tr></tbody>
</table>
<input type="button" id="agregar" value="Add">
<table>
<tbody id="plantilla"></tbody>
</table>
<script>
var nid = -1;
document.getElementById('agregar').onclick = function(){
var table = document.getElementById('plantilla');
var newRow = document.getElementById('template').innerHTML;
nid++;
newRow = newRow.replace('id="cmb_arboles"', 'id="cmb_arboles_'+nid+'"');
newRow.replace('id="cmb_arboles"', 'id="cmb_arboles_'+nid+'"');
table.innerHTML += newRow;
}
</script>
https://jsfiddle.net/nugee3s6/
You are hard coding the id value in $("#tabla tbody tr[id=idd]") not using the variable above it
If you wanted to use the variable it would be:
$("#tabla tbody tr[id=" +idd +"]")
But it makes no sense to use the ID to search again for the same row since you already have that row element as $row
So change to:
$(document).on('change', '.cmb_arboles', function () {
var $select = $(this);
var $row = $select.closest('tr');
var valor=$row.find("td:eq(0) select").val();
});
Then don't worry about using ID's, you don't need them

How to extract value from table with mixture of html elements

I have a table which contains a combination of plain text, input textboxes, selects, and spans. I need to iterate through the table row by row and pull out the value in each cell. Within my table all <tr> have a particular css class.
$(".gridBody").each(function(rowindex){
$(this).find("td").each(function(cellIndex){
var cell = $(this).first()
})
In my debugger I can see what kind of object is being returned by $(this).first() but I can't find out how to get into its attributes. I have tried using jqueries html parser to turn it back into a dom element, but instead of getting, for example, a textbox, I get something like [[html inputtextbox]]. Most of the methods that work on regular dom elements are not working for me.
If I use $(this)[0].innerText it returns the correct value when the contents of the cell are plain text, but not when they are a form of input or nested in a span element. What I would really like to be able to do is get a regular html dom element back that I can then check the type of with $.is() and then vary much logic from there.
How do I get the first child element in a table cell as an html dom element that I can manipulate with jquery like any other dom element?
var collected = $("#myTable td").find("input, textarea, span").map(function(){
return this.value || this.textContent;
}).get();
console.log( collected ); // an array holding values or text
http://jsbin.com/zewixe/2/edit?html,css,js,console,output
If you want only the immediate children than use the right > selector
(">input, >textarea, >span")
Heres how I would do it:
<table>
<tr>
<td>
<h1>Some stuff.</h1>
</td>
</tr>
<tr>
<td>
<input type="text" value="1"/>
</td>
<td>
<input type="text" value="2"/>
</td>
</tr>
<tr>
<td>
<input type="text" value="3"/>
</td>
</tr>
<tr>
<td>
<input type="text" value="4"/>
</td>
</tr>
</table>
$(function() {
function getFormData(selector){
'use strict';
var formTypes = {
text: 'text',
radio: 'radio',
select: 'select'
},
values = [];
$(selector).children().each(function(idx, childNode) {
if (childNode.getAttribute('type') && formTypes[childNode.getAttribute('type')]) values.push(childNode.value);
});
return values;
}
alert(
getFormData('table tr td.someClass')
);
})();
http://codepen.io/nicholasabrams/pen/RaKGjZ

when option selected do stuff ( btw, all the elments have dynamic id)

I searched for similar questions, I found some but their solution did't help me.
For example:
First question
Second question
My problem is:
I have a table that the user can add rows dynamically, so I am creating a unique id for each row and all elements inside as well.
each row have two text fields and select with two options, and when you select one of the option the text feild should be dislpay:block and the second will be display: "none", depending on your choice.
I built here some example that will shows the general structure (JSFiddle)
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>
<input id="description-first-1" name="description-first-1" type="text" placeholder = "first">
<input id="description-second-1" name="description-second-2" type="text" placeholder = "second">
<select id="select-1">
<option>
<option id="first-opt-1">1</option>
<option id="second-opt-1">2</option>
</option>
</select>
</td>
</tr>
<tr>
<td>
<input id="description-first-2" name="description-first-1" type="text" placeholder = "first">
<input id="description-second-2" name="description-second-2" type="text" placeholder = "second">
<select id="select-2">
<option>
<option id="first-opt-2">1</option>
<option id="second-opt-2">2</option>
</option>
</select>
</td>
</tr>
$(function() {
$("#select-1").change(function() {
if ($("#first-opt-1").is(":selected")) {
$("#description-first-1").show();
$("#description-second-1").hide();
} else {
$("#description-first-1").hide();
$("#description-second-2").show();
}
}).trigger('change');
});
http://jsfiddle.net/8vz121rq/9/
In my example for that matter you can seen that there are only 2 rows but it can also be 10 rows with different id's.
How to get jquery identify which row and all the elements inside of it i'm changing if the id's of all elements is dynamic ?
First of all, you need event delegation as the rows are dynamically generated, such as:
$("table").on("change", "[id^='select']", function() {
// do your stuf
});
Or in your case:
$("table").on("change", "#select-1", function() {
// do your stuf
});
So, is this what you needed?
$(function() {
$("table").on("change", "[id^='select']", function() {
var $this = $(this);
var $row = $this.closest("tr");
var ID = this.id.replace(/^[^\-]+\-(\d+)$/gi, '$1');
var sIndex = $this.prop('selectedIndex');
var part = sIndex === 2 ? "second" : "first";
if (!sIndex) {
$row.find("input").show();
return;
}
$row.find("input").hide();
$row.find("#description-" + part + "-" + ID).show();
});
});
Demo#Fiddle
P.S. The above is purely based on your markup and ID structure!

How to manage table row associated javascript (control ID) while do clone the row

Initially, table has only one tr (label/header) and then on click of add button click , i create new tr which looks as below. and all other consequence click of add will clone the last tr.
<tr>
<script type="text/javascript">
//fetch the value of select picker control and set into hidden field.
AJS.$('#' + '${field_uid}-resourcetypepicker-new1').change(function () {
AJS.$('#' + '${field_uid}-resourcetype-new1').val(AJS.$(this).attr('value'));
});
//fetch the value of select picker control and set into hidden field.
AJS.$('#' + '${field_uid}-locationpicker-new1').change(function () {
console.log(AJS.$(this).attr('value'));
AJS.$('#' + '${field_uid}-location-new1').val(AJS.$(this).attr('value'));
});
</script>
<td>
<input id="${field_uid}-resourcetype-new1"
name="${field_uid}"
type="hidden"
value="$r.getResourceType()" />
<select id="${field_uid}-resourcetypepicker-new1">
<option value="adad" #if ($r.getResourceType() == "adad") selected="selected"#end >adad</option>
<option value="dada" #if ($r.getResourceType() == "dada") selected="selected"#end >dada</option>
<option value="aadd" #if ($r.getResourceType() == "aadd") selected="selected"#end >aadd</option>
</select>
</td>
<td>
<input id="${field_uid}-location-new1"
name="${field_uid}"
type="hidden"
value="$r.getLocation()" />
<select id="${field_uid}-locationpicker-new1">
<option value="Internal(Local)" #if ($r.getLocation() == "Internal(Local)") selected="selected"#end >Internal(Local)</option>
<option value="Contractor(Local)" #if ($r.getLocation() == "Contractor(Local)") selected="selected"#end >Contractor(Local)</option>
<option value="Contractor(Offshore)" #if ($r.getLocation() == "Contractor(Offshore)") selected="selected"#end >Contractor(Offshore)</option>
</select>
</td>
<td>
<input id="${field_uid}-rate-new1"
name="${field_uid}"
type="text"
value="$r.getRate()" /> <!-- $textutils.htmlEncode($r.getRate()) -->
</td>
<td>
<input id="${field_uid}-effort-new1"
name="${field_uid}"
type="text"
value="$r.getEffort()" />
</td>
</tr>
PROBLEM:
In above stuff, existing javascript that points to specific control id '#' + '${field_uid}-resourcetypepicker-new1' means (render ID looks like customfield-id-111-new1). Now, problem is, each clone row will have different unique ID for select/picker list control. and this javascript will points to first row control only as AJS.$('customfield-id-111-new1'). But it should be AJS.$('customfield-id-111-new2') then for next row AJS.$('customfield-id-111-new3') .
so, what is the best way to write below jquery stuff which can points to each cloned control rather then pointing to first row controls only ? any way through tr reference control or any other way.
AJS.$('#' + '${field_uid}-resourcetypepicker-new1').change(function () {
AJS.$('#' + '${field_uid}-resourcetype- new1').val(AJS.$(this).attr('value'));
});
Also, in cloned row, it did not include this javascript , do i need to append after clone ?
Please let me know if any more details need.
NOTE: AJS.$ is equal to $. it is used in velocity template file in JIRA.
Thank You
In light of the updated question, see the following code
AJS.$('[id^="${field_uid}-resourcetypepicker-"]')
This selector can be used to get any item with ID that starts with ${field_uid}-resourcetypepicker so you don't have to worry about the last part of the id i.e. new1, new2 etc.
Secondly, your change event will bind to all those elements that are present on page load. But if you create elements dynamically (clone or whatever), the events won't work. You should use
AJS.$('[id^="${field_uid}-resourcetypepicker-"]').on('change', function () {
...
});
This will work for all the elements on the page that match the selector

Categories

Resources