I'm trying to delete two table rows at the same time in a dynamic table, but I'm having trouble deleting multiple rows at the same time. I have a table which displays text and a delete button in one tr and other related text in the next tr immediately after it. When I press the delete button on the first row, the row gets deleted but the one after it does not get removed. I have tried to get the value/address of the next row using this link but it does not seem to be working for me.
Fiddle in the works: http://jsfiddle.net/DLqLW/3/
The button for deleting the row is coded this way:
<input type="button" id="<?php echo $str; ?>" class="button-add" name="butcli" value="-" onClick="deleteRow(this)"></input>
and the function that it calls is:
function deleteRow(el) {
while (el.parentNode && el.tagName.toLowerCase() != 'tr') {
el = el.parentNode;
}
if (el.parentNode && el.parentNode.rows.length > 1) {
el.parentNode.removeChild(el);
}
}
I'm struggling with how to delete the next row after it. If anyone could provide some help, that would be great!
Do you have just two rows?
You are testing:
parentNode.rows.length > 1
If you have only two rows, it will not delete the second row.
Change it to:
parentNode.rows.length > 0
Try this
http://www.w3schools.com/dom/dom_nodes_navigate.asp
function get_nextSibling(n)
{
y=n.nextSibling;
while (y.nodeType!=1)
{
y=y.nextSibling;
}
return y;
}
Alternate (simpler?) approach: Use a <div> rather than a sibling <tr>
A different approach, to keep it simple, avoid jQuery, and avoid nextSibling and related problems:
Working fiddle: http://jsfiddle.net/digitalextremist/9Zv83/3/
...using this HTML approach:
<tr>
<td>1
<div>this row should be deleted if the one above is removed.</div>
</td>
<td>
<input type="button" id="<?php echo $str; ?>" class="button-add" name="butcli" value="-" onClick="javascript:deleteRow(this)"></input>
</td>
</tr>
Also, your existing version relies on a <tr> which is short one cell. If you add colspan=2 to your sibling row, then the formatting is thrown off too... hence this approach I am proposing.
Using Jquery this is working
function deleteRow(el) {
var tr = $(el).closest('tr');
tr.css("background-color","#FF3700");
tr.fadeOut(400, function(){
tr.remove();
});
var tr2 = $(tr).closest('tr').next();
tr2.css("background-color","#FF3700");
tr2.fadeOut(400, function(){
tr.remove();
});
}
Looks pretty swanky too I used your jfiddle with jQuery 2.02
Related
<table>
<tr id="tr1">
<td id="td1"> test1 </td>
<td id="td2"> test2 </td>
<td id="td3"> test1 </td>
<td id="td4"> test3 </td>
</tr>
</table>
Here I have a table with a tr in it and 4 td's.
Now, my question is, how can I compare the td.text() with the other one?
For example:
a loop that takes the text of first td and then compare it with other td's.
If it is the same, then give that td a class.
HERE: td id="td1" should get a class
BUT:
When I'm at the 3e td, the 3e td should get a class.
This code should work for you:
var tds;
$('tr').each(function(i, item){
tds = $(this).find('td');
tds.each(function(j, elem1){
tds.each(function(k, elem2){
if($(elem1)[0] != $(elem2)[0] && $(elem1).text() == $(elem2).text()){
$(elem1).addClass('cl');
}
});
});
});
FIDDLE: https://jsfiddle.net/lmgonzalves/cqa6m6va/1/
You can use this code:
function setClasses(word) {
var tds = $("tr td");
for(var i = 0; i < tds.length; i++) {
if(tds.eq(i).text() === word) {
tds.eq(i).addClass('red');
}
}
}
setClasses("test1");
jQuery selectors will be your friend here. :)
var $container = $("#tr")
$container.children().each(function() {
if (!($(this).hasClass("td")) {
var sTextVal = $(this).text();
var $currTextGroup = $container.children(":contains('" + sTextVal + "')");
if ($currTextGroup.length > 1) {
$currTextGroup.addClass("td");
}
}
});
I'll explain the logic, and then touch on one issue to be aware of . . .
Basically, this code:
Collects all of the the children of the <tr> and loops through them one at a time
If the current child does not already have a class of "td" (if it already has a "td" class, then this text has already been checked for duplicates), it retrieves the text from inside the element and searches for all of the children of the <tr> that contain that same text value
If more than one of the children in the <tr> contain that text, all of those children are given the class of "td"
The one potential issue that this solution could run into is if the text in the current element is present as part of the text in one of its siblings. For example, if the text in one sibling is "the", and it has some siblings that have text values of "then" and "there" and "the end", they will be found by :contains.
If your text values are sufficiently "patterned" (as they are in your example), though, this should not be an issue. If it is an issue, there is a more complex way to do that "common text" selection, but I won't bother with that, unless it is necessary.
If I understand correctly, you want to select the first 'td' in a 'tr' and compare it against the other 'td' in your table. Please try the below code and let me know if it works for you.
HTML (provided by OP)
<table>
<tr id="tr1">
<td id="td1"> test1 </td>
<td id="td2"> test2 </td>
<td id="td3"> test1 </td>
<td id="td4"> test3 </td>
</tr>
</table>
CSS
.color--red { color: red; }
jQuery
$(document).ready(function(){
var first = $("#tr1 :first-child").html();
$('#tr1 :not(:first-child)').each(function() {
if(first == $(this).html()){
$(this).addClass("color--red");
}
});
});
I tried to keep it as simple as possible. The variable first pertains to that first 'td' that you want to use for comparison. Note how the each function operates on 'all elements except the first child in the tr', which clearly will omit the first variable we declared initially. From there it's all about comparing using $(this).html() to grab the value of the currently selected element, against the value obtained from the first variable.
Once this succeeds, simply add a class of your choice. For simplicity's sake, I added my own color--red class to the mix, which should show red color text for the third 'td' element as you suggested in your question post. Enjoy! Let me know if you need anything further.
I have a table with rows of data, when a user clicks on the row (tr) or the checkbox, it appends that row of data into another location. How do I make it that when a user unchecks from the original table AND the new appended row, that the row disappears?
I want it so that when the user unchecks from the original table, the appended row disappears. When the user unchecks from the appended row, only the appended row disappears.
// original table
<div id="searchsub">
<table class="showsub">
<tr class="datarow">
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
</table>
</div>
Row appends to this new table:
<table id="datarow">
</table>
Here's the jquery I have:
$(document).ready(function() {
$("#searchsub table tr").click(function(event) {
if(event.target.type !== 'checkbox') {
$(":checkbox", this).trigger("click");
}
});
$i = 1;
$("input[type='checkbox']").change(function(e) {
if($(this).is(":checked")) {
$(this).closest("tr").addClass("highlightrow");
var datarow = $(this).closest("tr.datarow");
var row = datarow.clone();
row.addClass("append" + $i);
$("#submitshipment #datarow").append(row);
$i++;
} else {
$(this).closest("tr").removeClass("highlightrow");
$(".append").closest("tr").remove();
}
})
})
Of course this way whenever the row is unchecked ALL of the rows are deleted, which isn't what I want. Please help?
EDIT: mark up of the appended row:
<tr class="datarow highlightrow append1">
<td>120093</td>
<td>G13</td>
<td><input type="checkbox" class="searchsub" name="searchsub[]" value="1"></td>
</tr>
jsFiddle:
http://jsfiddle.net/7cXqR/1/
Yes, unfortunately the non-functional jsFiddle doesn't really help ;-)
I think I've sorted out what you're trying to do though; the issue is you don't have anything (be it using jQ .data() or in markup) that relates your appended rows to your source rows. If you look at the jsFiddle I made (forked from yours) you'll see how I use the "value" attribute you have on the checkbox in the source table to find the cloned rows in the append table:
$('#datarow').find('input:checkbox[value="' + $(this).val() + '"]').closest('tr').remove();
http://jsfiddle.net/A4w59/
This approach could be modified to use any markup (stock or custom data-* attributes) or even jQ's .data() method; the key is being able to associate the source & append rows so that you can remove the appended row when unselecting it in the source table.
I'm trying to create a new use for an already implemented tool we use here at work, but I'm very sure I'm doing something wrong.
I can't figure out how to make it delete a row. And even more, I can figure out how to clone everything within .pt-entry, and have it replicated inside of the incremental .pt-entry...but without the user filled in info.
Hopefully this makes sense.
You can check out my Pen here, but here's the code breakdown for the rest of yous:
HTML:
<table class="manage-pt" id="0">
<tr class="pt-entry">
<td class="pt-toggle-group">
<input type="button" class="pt-button togPTbutton" value="?" />
<input type="button" class="pt-button addPTbutton" value="+" />
<input type="button" class="pt-button delPTbutton" value="-" />
</td>
<td class="pt-values">
<div>
<input type="text" class="vendor" placeholder="Vendor Name" />
</div>
<div>
<textarea class="ptCode" name="ptCode" placeholder="Pixel Tag Code" ></textarea>
</div>
<div class="page-select">
<select>
<option value="AllPages">All Pages</option>
<option value="HomePage">HomePage</option>
<option value="VehicleDetailsPage">VehicleDetailsPage</option>
<option value="VehicleSearchResults">VehicleSearchResults</option>
<option value="ContactUsForm">ContactUsForm</option>
</select>
</div>
<div class="area-checkboxes">
<p class="wheretosave">Where?</p>
<input type="checkbox" name="head" /><label for="head">Head</label>
<input type="checkbox" name="body" /><label for="body">Body</label>
</div>
<div class="save-pt">
<input value="SAVE" type="submit" />
</div>
</td>
</tr>
</table>
JavaScript:
// HIDES CURRENT PT & CHANGES TOGGLE BUTTON ICON WHEN CLICKED
$('.togPTbutton').click(function(){
$('.pt-values').slideToggle(25, function() {
if ($('.pt-values').is(':hidden')) {
$('input.togPTbutton').val('?');
}else{
$('input.togPTbutton').val('?');
}
});
});
$(document).ready(function () {
var table = $('.manage-pt'),
rows = $(table).find('tr'),
rowCount = $(rows).length,
addedRow = $(document.createElement('tr')),
addButton = $('.addPTbutton'),
removeButton = $('.delPTbutton');
function addRow(){
var thisRow = $(addedRow).clone(true);
$(thisRow).attr('class','.pt-entry-' + rowCount);
rowCount += 1;
$(thisRow).html('<td>row</td>');
$(table).append(thisRow);
}
function removeRow(){
var items = $(table).querySelectorAll('tr');
if (rowCount > 1) {
$(table).remove(items[rowCount - 1]);
rowCount -= 1;
}else{
alert('CANNOT DELETE LAST ROW');
}
}
addButton.click(function(e){
addRow();
});
removeButton.click(function(e){
removeRow();
});
});
Should look close to something like this mockup ...
Alright, I think I found your problem. You are trying to call $(table).querySelectorAll('tr'). .querySelectorAll is a javascript function that you are using with a JQuery selector. This is where your removeRow() function bombs. Try commenting that line out. Then, you will need to find a new way to select the last row, which can easily be done with this:
$(table).find('tr:last').remove();
Final form:
function removeRow(){
//var items = $(table).querySelectorAll('tr');
if (rowCount > 1) {
//$(table).remove(items[rowCount - 1]);
$(table).find('tr:last').remove();
rowCount -= 1;
}
else
{
alert('CANNOT DELETE LAST ROW');
}
}
If you want this to work in IE8 and older, you can use this JQuery since you have the number of rows:
$(table).find('tr').eq(rowCount - 1).remove();
in place of:
$(table).find('tr:last').remove();
JSFiddle: http://jsfiddle.net/Em8Q5/2/
EDIT: ------------------------------------------------------------------------------------
Alright, I found a solution being able to delete the current row.
First, allow a parameter into your removeRow function and switch the selector to use closest:
function removeRow(currRow){
//var items = $(table).querySelectorAll('tr');
if (rowCount > 1) {
//$(table).remove(items[rowCount - 1]);
currRow.closest('tr').remove();
rowCount -= 1;
}
else
{
alert('CANNOT DELETE LAST ROW');
}
}
Then you will need to modify your .click function so that it will change dynamically as you add/remove rows/buttons. Also, note the parameter so it knows which row's button is clicked.
//removeButton.click(function(e){
$('body').on("click", ".delPTbutton", function(e) {
removeRow($(this)); //Note the parameter that we added so it knows which row to remove
});
JSfiddle: http://jsfiddle.net/Em8Q5/3/
I check up your code using chrome developer tool and when i clicked the delPTbutton button to remove last row it showed an error in your removeRow Method , The Error Message Is :
(Uncaught TypeError: Object [object Object] has no method 'querySelectorAll')
The Issue Here Is That 'querySelectorAll' Is One Of javascript base api but you use it after a jquery object.
Consider Using $(table).find('tr') Instead .
Ok so thank you #Chad for your help. You were seriously a life saver.
I took what you did, one step further in this new version of the code:
New CodePen
However I now have a very js minor issue. I have it set to turn the ".vendor" input to read only when the relevant stack is closed, however I need to target something other than ".vendor", because it's effecting each clones ".vendor" as well.
Would it be something like:
$(this).parent().next().child().child();?
I'm developing a table in html. Every rows have a checkbox with the same attribute name as tag tr. So I want to color the row selected in yellow if that raw is the unique selected, otherwise color in blue all the rows selected. So I was developing this:
var checked = $("input[#type=checkbox]:checked");
var nbChecked = checked.size();
if(nbChecked==1){
var row = $('tr[name*="'+checked.attr("name")+'"]');
row.style.backgroundColor="#FFFF33";
}
But color doesn't change :( can you tell me why? can you help me?
<TR valign=top name="<?php echo $not[$j]['name'];?>">
<TD width=12 style="background-color:#33CCCC">
<div class="wpmd">
<div align=center>
<font color="#FF0000" class="ws7">
<input type="checkbox" name="<?php echo $not[$j]['name'];?>" onchange="analizeCheckBox()"/>
</div>
.
.
.
.
.
.
Although this code doesn't get you all they way to the funcitonality, it does do the row updating.
http://jsfiddle.net/4QKe9/5/
HEre is the Javascript:
function updateRows() {
var checked = $("input:checked");
var nbChecked = checked.size();
if (nbChecked == 1) {
checked.parent().parent().css("background", "#FFFF33");
}
}
$(function () { $("input:checkbox").click(updateRows)});
Firstly, you have got the background color on the cell not the row. You need to move it.
Here's your fixed html:
<table>
<tr style="vertical-align:top; background-color:#33CCCC">
<td style="width:12px">
<div class="wpmd">
<div class="ws7" style="text-align:center; color:#FF0000">
<input type="checkbox" />
</div>
</div>
</td>
</tr>
</table>
and then this script will work
$("td .ws7 input[type=checkbox]").bind({
click: function()
{
if ($(this).is(":checked"))
{
$(this).closest("tr").css("background-color", "#ffff33");
}
else
{
$(this).closest("tr").css("background-color", "#33CCCC");
}
}
});
change the "td .ws7" selector to match your needs.
Example.
When you call the jQuery function $() with a selector string it will return a jQuery object that is like an array even when only 1 or 0 elements matched. So your code:
row = $('tr[name*="'+checked.attr("name")+'"]');
row.style.backgroundColor="#FFFF33";
Doesn't work because row is not a DOM element with a style property, it's a jQuery object that's like an array with lots of extra methods. The individual DOM elements that matched can be accessed with array-style notation, so:
row[0].style.backgroundColor = "#FFFF33";
Will work to update the first matching DOM element. If nothing matched then row[0] will be undefined and you'll get an error. row.length will tell you how many elements matched.
In your code:
var checked = $("input[#type=checkbox]:checked");
You don't need the # symbol to match attribute names, so "input[type=checkbox]:checked" is OK, but "input:checkbox:checked" is simpler.
So getting at last to your actual requirement, which is when a single row has a checked box to set that row's background to yellow, but if multiple rows have checked checkboxes to set all those rows' backgrounds to blue, you can do this with only three lines of code:
// reset all trs to default color
$("tr").css("background-color", "yourdefaultcolorhere");
// select the checked checkboxes
var checked = $("tr input:checkbox:checked");
// set the checked checkboxes' parent tr elements' background-color
// according to how many there are
checked.closest("tr").css("background-color",
checked.length===1 ? "yellow" : "blue");
Notice that you don't need to select by the name attribute at all, because jQuery's .closest() method will let you find the tr elements that the checked checkboxes belong to.
WORKING DEMO: http://jsfiddle.net/FB9yA/
My html
<tr id="uniqueRowId">
<td>
<input class="myChk" type="checkbox" />
</td>
<td class="from">
<textarea class="fromInput" ...></textarea>
</td>
<td class="to">
<textarea ...></textarea>
</td>
</tr>
I have a table where each row is similar to the above with only one exception: not all rows will have textreas. I need to grab all rows that have textareas AND checkbox is not "checked".
Then I need to leaf through them and do some stuff.
I tried something like:
var editableRows = $("td.from .fromInput");
for (s in editableRows)
{
$s.val("test value");
}
but it didn't work.
1) how do I grab ONLY the rows that have checkboxes off AND have fromInput textareas?
2) how do I leaf through them and access the val() of both textareas?
I am sure this could be optimized, but I think it will work.
$("tr:not(:has(:checked))").each(function(i, tr) {
var from = $(tr).find("td.from textarea").val();
var to = $(tr).find("td.to textarea").val();
//now do something with "from" and "to"
});
See it working on jsFiddle: http://jsfiddle.net/RRPqb/
You can use this to select the rows:
$('tr', '#yourTable').has('input:checkbox:not(:checked)').has('textarea')
Live demo: http://jsfiddle.net/simevidas/Zk5EH/1/
As you can see in the demo, only the row that has a TEXTAREA element and a unchecked checkbox will be selected.
However, I recommend you to set classes to your rows: the TR elements that contain TEXTAREA elements should have a specific class set - like "directions". Then you could select those rows easily like so:
$('tr.directions', '#yourTable').each(function() {
if ( $(this).find('input:checkbox')[0].checked ) return;
// do your thing
});
$("tr:not(:has(:checked)):has(input.fromInput)")
Should be what you need. All the rows that don't have anything checked but that do have an input with the class 'fromInput'
If you want to loop through them to get the value of any textarea just extend your selector:
$("tr:not(:has(:checked)):has(textarea.fromInput) textarea")
Or as above if you want to be able to distinguish them:
$("tr:not(:has(:checked)):has(textarea.fromInput)")
.each(function() {
var from = $(this).find("td.from textarea").val();
var to = $(this).find("td.to textarea").val();
})
I don't know how much performance is a concern here, but if it is, then rather then writing a selector to find rows that contain a textarea you may find it helps to add a class to the row itself.
<tr class="hasTextarea">
Then you could alter your JQuery as so:
$("tr.hasTextarea:not(:has(:checked))")