Change class of input elements inside cloned div with drag & drop - javascript

I have two columns. The column on the left loads with rectangular divs, which inside of these divs are 5 input elements that are loaded via PHP with data. The user can drag a div from the left column over to the right column. This will clone it and the user can begin to edit the input elements. I have been able to change the ID of the parent div once its cloned but am running into trouble changing the class names of the input elements inside the cloned div. Im going to save them via ajax and will build an array of all values that belong to each classname. The cloned class names must be different from the original as not to capture the original data.
This is an example of one of the divs that a user can drag and clone. No PHP yet.
<div class='pcaccount' draggable="true" id='account' data-id='accountid' ondragstart="drag(event)" >
<table class='tablesorter'>
<thead id='accountrow'>
<th align='center'>
<input type='text' value='hello' class='owner' >
</th>
<th align='center'>
<input type='text' value='hello' class='custodian' >
</th>
<th align='center'>
<input type='text' value='hello' class='type' >
</th>
<th align='center'>
<input type='text' value='hello' class='tax' >
</th>
<th align='center'>
<input type='text' value='hello' class='accvalue' >
</th>
</thead>
</table>
</div>
This is my current JS. It works fine for dragging, dropping, cloning, and changing the ID of the parent DIV but i can't seem to be able to change the class of the input elements within the div.
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("div", ev.target.id);
var i = 0;
}
function drop(ev) {
var newId = 'newaccount';
ev.preventDefault();
var data=ev.dataTransfer.getData("div");
var nodeCopy = document.getElementById(data).cloneNode(true);
nodeCopy.id = newId+i;
nodeCopy.class = 'newaccount';
ev.target.appendChild(nodeCopy);
i++;
}
Iv neglected to include any code I have tried to make to accomplish this as its rubbish. Any help on this would be greatly appreciated. Also it would be necessary to change the ID of the "thead" as I want to append another table header to it once it is cloned.
Many thanks in advance.

Since you tagged the question with jQuery, here is a jQuery snippet which should allow you to modify child elements of the cloned node:
$('input', nodeCopy).each(function () {
$(this).removeClass(...).addClass(...);
});
$('thead', nodeCopy).each(function () {
$(this)[0].id = ...;
});
Without jQuery, you can achieve something similar using nodeCopy.querySelector or nodeCopy.querySelectorAll.

Related

How to grab data from table with divs and inputs inside cells?

I am still new to js and jQuery. How would I iterate through the table and grab data from each cell (the date, and input "from" and "to")?
<table class="table table-striped table-bordered table-hover table-condensed" id="entryTable">
<thead>
<th>Date</th>
<th>First Shift</th>
<th>Second Shift</th>
</thead>
<tbody>
<tr>
<td>2/1/2016</td>
<td>
<div id="time" class="form-group">
From: <input type="text" id="start01">
To: <input type="text" id="end01">
</div>
</td>
<td>
<div id="time" class="form-group">
From: <input type="text" id="start02" >
To: <input type="text" id="end02">
</div>
</td>
</tr>
</tbody>
</table>
Here Is a Jsfiddle I built for you JsFiddle To Get table values
And the code I used is
var date = $('#entryTable').find('tbody td:eq(0)').text();
var From01 = $('#entryTable').find('tbody td:eq(1) input:eq(0)').val();
var To01 = $('#entryTable').find('tbody td:eq(1) input:eq(1)').val();
var From02 = $('#entryTable').find('tbody td:eq(2) input:eq(0)').val();
var To02 = $('#entryTable').find('tbody td:eq(2) input:eq(1)').val();
In the Fiddle I have put a button to fetch the value on click of the button, I am displaying the values in alert, you can change the code according to your requirement
- List item
EDIT: To loop through all the td's you can do this
$.each($('#entryTable').find('tbody td), function(){
var currentTdOfLoop = $(this);
//do your stuff here
});
in javascript you can use the method document.getElementById("tagId") for example in your case document.getElementById("time") or you can use document.getElementByClassName("tagClassName") or document.getElementByTagName("TagName") and each of them returns an array of dom elements in JQuery library it's so similar to css selectors for example
$("#elementId") to select an element by its id
$(".className") to select an elements by their class name
$("tagname") like $("p") to select all the p tags in the dom
$("div p") to select the p tags which in a div tag
and for example in your code you can grape a th element in your table using a selector like that $("#entryTable > thead th:nth-child(2)")
and I think that

Select elements in each child tables one by one

I have the following html which is basically a parent table with some child tables inside it,
<table id="roottable" class="tablemain" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td></td>
<td>
<table class="intable" align="center" border="0">
<tbody>
<tr>
<td class="chn" colspan="2" align="center">
<div>
<div class="mparent">
<div class="checkbox">
<input type="checkbox" id="ch243" name="ch243" value="243">
<label for="ch243"></label>
</div>
<div class="chtext">Category</div>
</div>
</div>
</td>
</tr>
<tr>
<td>Param two</td>
<td>
<div class="checkbox">
<input type="checkbox" id="ch244" name="ch244" value="244">
<label for="ch244"></label>
</div>
</td>
</tr>
</tbody>
</table>
......
......
<table class="intable" align="center" border="0">
......
......
What I need to do is access all checkboxes of the nested table, for each table. That is get the checkboxes inside the first nested table, perform some operations with it, move to the next nested table do the same with the checkboxes inside it.
I can access individual tables like below with their id,
$('#tableid').find('input[type="checkbox"]').each(function () {
});
This works, but the tables are auto generated from db and the id is not known beforehand, also, the number of tables may vary, so I have no option other than selecting the parent table and then look for every child tables inside it one by one ... I have tried this ...
$('table').each(function(){
$(this).find('input[type="checkbox"]').each(function () {
// DO STUFFS WITH CHECKBOXES
});
But it doesn't work... How do I go about this? Thanks.
$('table tr td').each(function(){ // this line is for main outer table
$(this).children('table').each(function () { //this will iterate all the child table
$(this).find('input:checkbox').each(function(){ //this will find checkbox inside each table
//Your Stuff
});
});
});
NOTE :- I m not using id selector here because questioner mentioned that he doesn't know id's beforehand.
Working Demo
Working Demo
Your final code block looks acceptable, except that you haven't prevented the table selector from also selecting the outer table. As written, this would cause each set of checkboxes to be considered twice - once as part of its own table and again (actually first) as descendants of the outer table.
Try a more specific selector:
$('#roottable .intable').each(...)
I would do something like this:
$('#roottable').find('.intable').each(function(index, elt) {
// operate now on each "child table"
var $childTable = $(elt);
$childTable.find('input[type="checkbox"]').each(function(i, cb){
// Do your stuff with the checkoxes of the current ".intable" table
});
});
Just use:
var tableInputs = {};
$('#roottable input[type="checkbox"]').each(function () {
var id = $(this).closest('table').attr('id');
var name = $(this).attr('name');
tableInputs[id] = {};
tableInputs[id][name] = $(this).val();
});
This will select all checkboxes that are a child of a table.
EDIT if you need to group just find the id of the closest parent table and use that as an index for an object. You end up with one large object with all the id's as properties, while using only one each loop.

Accessing different types of element

I have a table with few rows. Each rows has header, data and hidden field. Data column can have either text or textarea.
<table id="knowledgeTreeTable" class="custom">
<tbody>
....................
<tr>
<th class="">What is the name of the party?</th>
<td class="">
<textarea id="ktField_7" class="ktEdit" type="text"></textarea>
</td>
<input id="ktField_7H" type="hidden" value="Unique contested">
</tr>
<tr>
<th class="">What is the name of the opposing party?</th>
<td class="">
<input id="ktField_8" class="ktEdit" type="text" style="width: 97%;">
</td>
<input id="ktField_8H" type="hidden" value="Query">
</tr>
......................
</tbody>
</table>
I am able to read the content of header and hidden field but not sure how to read data column as it can have two different types of element.
$("#knowledgeTreeTable tr").each(function() {
alert($('th', this).text());//OK
//alert($('td > [input, textarea]', this).val()); // This is not OK.
alert($('input', this).val());//OK
});
You can't group selectors like
td > [input, textarea]
Instead, use
td > input, td > textarea
Just as you would in a CSS selector, look for both:
alert($('td > input, td > textarea', this).val());
Although since you're using the same class for both, I'd be inclined to use:
alert($('td > .ktEdit', this).val());
Whenever you're trying to access a child element in a loop like this, you need to establish what the common factors between each element is. In this case they are different tags with different names, but they both have the ktEdit class, and both have type="text" (which I don't believe is actually applicable to textareas).
In this case, the common variable is the class name, so you can use that as your selector. As long as you target your parent loop correctly, it won't matter if you use that class on other elements throughout the page:
$("#knowledgeTreeTable tr").each(function() {
alert($('.ktEdit', this).val());
});

JQuery click event to add or remove table rows

I have a table that has plus or minus glyph-icons at the top that allow the user to add or subtract rows. The code I have works but if the user clicks the minus button too many times it will eat the whole table.
What I have tried is to add an unique ID tag to the rows I add and only delete the TRs with the ID but if 2 rows are added and the minus is pressed both rows will be deleted at once, I only want to delete one row at a time. Note: the code below does not reflect this attempt.
Glyphicons:
<div class="well" style="margin-bottom:0px;" id="addrow">
<span class="glyphicon glyphicon-plus" id="add"></span>
<span class="glyphicon glyphicon-minus" id="minus"></span>
Table:
<table class="table table-bordered table-striped" style="margin-bottom:0px;" id="myTable">
<tr>
<td>Customer Master #</td>
</tr>
<tr>
<td><input type="text" class="form-control" ></td>
</tr>
</table>
JS:
$(document).ready(function(){
$("#addrow").on("click", "span#add", function(){
var tablerow = '<tr><td><input type="text" class="form-control" ></td></tr>'
$("#myTable tr:last").after(tablerow);
})
$("#addrow").on("click", "span#minus", function(){
$('#myTable tr:last').remove();
} )
});
Not sure 100% you want changed with your code, but here is a fiddle which adds or removes - but will not remove the first row (won't eat the whole table).
http://jsfiddle.net/HR5se/
$('#myTable tr .form-control').size()
Will give you how many data (input) rows there are. In this fiddle, I check to see if there's greater than one data row, and if not, the remove doesn't happen.
Note: I turned your glyphs into "+" and "-" text so I could see them here.
See if changing the onclick event to mouseup has any effect. I had a similar problem a while back.
I added an if statement to only allow a row to be taken out if the table has 3 or more rows. This preserves the last two rows that I always want to be on the page.
if ($('#myTable tr').length > 2)
This seemed to solve the problem.
Full code:
$("#addrow").on("click", "span#minus", function(){
if ($('#myTable tr').length > 2) {
$('#myTable tr:last').remove();
};
} )

Trouble cloning a set of selects dependent on each other

I am trying to create a dynamic table that allows the user to select from around 100 variables. These variables have been split into categories and I have been displaying them in a second select that depends on the user selecting a value in the first select. I have been searching the web for answers and have come up blank. I realize that the clone() call will duplicate all data and for that reason id's are a poor choice for the rows.
Here is what I currently have for HTML:
<body>
<table name='myTable' class="dynatable">
<thead>
<tr>
<th class='idCol' >ID</th>
<th>Category</th>
<th>Metric</th>
<th>Conditional</th>
<th><button class="add">Add</button></th>
</tr>
</thead>
<tbody>
<form name='myForm'>
<tr class="first">
<td class="id idCol"><input type="text" name="id[]" value="0" /></td>
<td><select name='categories' onChange='updatemetrics(this.selectedIndex)' style="width: 260px">
<option selected>--Select Category--</option>
<option value='1'>Customer Experience</option>
<option value='2'>Key Satisfaction Identifiers</option>
<option value='3'>Personnel Costs</option>
<!-- I have cut the rest out for the sake of brevity. -->
</select></td>
<!-- This is the select that populates based on the user's choice. -->
<td><select style="width: 310px"name='metrics'></select></td>
</tr>
</form>
</tbody>
</table>
</body>
The Javascript that I am working with is as follows.
$(document).ready(function() {
var id = 0;
// Add button functionality
$("table.dynatable button.add").click(function() {
id++;
var master = $(this).parents("table.dynatable");
// Get a new row based on the prototype row
var prot = master.find(".prototype").clone(true);
prot.attr("class", "")
prot.find(".id").attr("value", id);
master.find("tbody").append(prot);
});
// Remove button functionality
$("table.dynatable button.remove").live("click", function() {
$(this).parents("tr").remove();
});
});
//script for dynamically populating the metrics select
var metricCategories=document.myForm.categories;
var metricList=document.myForm.metrics;
var metrics=new Array()
metrics[0]=" "
metrics[1]=['Wait time average|waitInLine','Mystery Shopper Scores|mysteryScores']
metrics[2]=['Referral Rate|ref_rate','Facebook Shares|facebook_shares','Twitter Followers|twit_followers','Customer Complaint Calls|comp_calls']
metrics[3]=['Pension Payouts|pension_pay', 'Full Time Employees|ftes', 'Part Time Employees|ptes', 'Contractor Costs|contract_costs']
function updatemetrics(selectedMetricGroup){
metricList.options.length=0
if (selectedMetricGroup>0) {
for (i=0; i<metrics[selectedMetricGroup].length; i++)
metricList.options[metricList.options.length]=new Option(metrics[selectedMetricGroup][i].split("|")[0], metrics[selectedMetricGroup][i].split("|")[i])
}
}
Any help would be appreciated. To reiterate the reason I am asking for help, I need to add/ remove rows that hold select nodes that interact with each other. Thanks in advance.

Categories

Resources