deleteRow sometimes deletes the right row and sometimes not in Javascript - javascript

I have a table. At the end of each row tehere is a href "X" which deletes this row. This is pretty simple. Now when you click "X" for any row 2 it deletes row 2, but then when you click on row 3 it deleted row 4.
This is my code:
HTML
<table id="my_table" align="center" cellspacing="0" cellpadding="0" border="0">
<tr>
<td>Custom0</td>
<td><a title="my title text" id="1" href="#" class="someclass" onclick="deleteRows(0)">X</a>
</td>
</tr>
<tr>
<td>Custom1</td>
<td> <a title="my title text" id="2" href="#" class="someclass" onclick="deleteRows(1)">X</a>
</td>
</tr>
<tr>
<td>Custom2</td>
<td> <a title="my title text" id="3" href="#" class="someclass" onclick="deleteRows(2)">X</a>
</td>
</tr>
<tr>
<td>Custom3</td>
<td> <a title="my title text" id="4" href="#" class="someclass" onclick="deleteRows(3)">X</a>
</td>
</tr>
<tr>
<td>Custom4</td>
<td> <a title="my title text" id="5" href="#" class="someclass" onclick="deleteRows(4)">X</a>
</td>
</tr>
<tr>
<td>Custom5</td>
<td> <a title="my title text" id="6" href="#" class="someclass" onclick="deleteRows(5)">X</a>
</td>
</tr>
</table>
and Javascript
function deleteRows(row) {
var tbl = document.getElementById('my_table'); // table reference
tbl.deleteRow(row);
}
You can play wit it here: http://jsfiddle.net/nTJtv/13/

You have hard-coded the row numbers, so after the first deletion they are out of sync. The <table> element's .rows property is "live", so removing one means the numbers no longer line up with your HTML.
Instead, consider passing this.parentNode.parentNode to the function and using it to determine which row to delete:
<a title="my title text" id="6" href="#" class="someclass" onclick="deleteRows(this.parentNode.parentNode)">X</a>
Then use removeChild() in the function:
function deleteRows(row) {
var tbl = document.getElementById('my_table'); // table reference
tbl.getElementsByTagName("tbody")[0].removeChild(row);
}
Edit: The <tr> is a child of the <tbody> element, so that must be the parent from which it is removed.
http://jsfiddle.net/nTJtv/19/
If you would really rather do it with deleteRow(), then loop through the rows to find the one passed to the function and delete it:
function deleteRows(row) {
var tbl = document.getElementById('my_table'); // table reference
// Loop over the table .rows collection to find the one passed into the function
for (var i=0; i<tbl.rows.length; i++) {
if (row == tbl.rows[i]) {
// And delete it
tbl.deleteRow(i);
return;
}
}
}
http://jsfiddle.net/nTJtv/21/

Why not do something like this? Using jQuery isn't hard to add into existing files/sites.
HTML:
<table id="my_table" cellspacing="0" cellpadding="0">
<tr>
<td>Custom0</td>
<td><span title="my title text" id="1" class="someclass">X</span></td>
</tr>
<tr>
<td>Custom1</td>
<td><span title="my title text" id="2" class="someclass">X</span></td>
</tr>
</table>
JavaScript:
$('.someclass').on('click', function() {
$(this).parent().parent().remove();
});

Related

jQuery .html() removes all table related tags and breaking HTML

I am fetching strange problem. I am using jQuery to execute AJAX request and trying to update a div content (bootstrap popover).
The AJAX is executed successfully and it is returning the HTML as output in debug.
<a href = "javascript:void(0);" data-toggle = "popover" title = "<strong>Line Details</strong>" data-placement = "top" data-html = "true" data-content = "<table border="0" cellpadding="1" cellspacing="0" style="font-size:8pt;color:#bbb;">
<tr style="background-color:#777;">
<td style="width:40px">QTY</td>
<td style="width:180px">DESC</td>
</tr>
<tr>
<td style="border-bottom:1px solid #eee;">3</td>
<td style="border-bottom:1px solid #eee;width:40px;"><input type="text" size="8" id="itemDesc-job1-1" name="job1itemDesc" value="Test Desc" > </td>
</tr>
<tr><td> </td>
<td style="text-align: right;">
<div> <div> <div id ="action-saveLineDetails-job1" class="icon-save" style="float:right !important;" title="Save" onclick="saveJobLineDetails('job1','3' )"></div>
</td></tr> </table>" > 157|999</a>
Now, I am replacing the the div content (popover) like this:
$('#itemdetails-' + jobID).html(result.Data);
Surprisingly, it is removing all table related tags.
The page is the showing something else. Here is the code what is found in that div:
<a href="javascript:void(0);" data-toggle="popover" title="<strong>Line Details</strong>" data-placement="top" data-html="true" data-content="<table border=" 0"="" cellpadding="1" cellspacing="0" style="font-size:8pt;color:#bbb;">
QTYDESCKG
31
<input type="text" size="8" id="itemDesc-job1-1" name="job1itemDesc" value="1">
</a>
First time I am getting this type of wierd behavior of .html().
Is there anything I am missing?

add unlimited input fields with prototype

i am adding unlimited input field. below code is working fine only the one problem it is adding after the first <tr>. it is not adding the field it after the additional <tr>. if click on add option it is adding <before> or after first <tr>. ignoring the others <tr>.
my html
<table width="100%" cellspacing="0" id="orderchecklist_item_grid_servicecenters" class="data border">
<colgroup><col width="120">
<col>
<col width="100">
<col width="70">
</colgroup><thead>
<tr class="headings">
<th width="80%">Item</th>
<td width="10%" class="last"><button style="" onclick="addfield();" class="scalable add" type="button" title="Add Option" id="add_new_option_button"><span><span><span>Add Option</span></span></span></button></td>
</tr>
</thead>
<tbody id="orderchecklist_item_list">
<tr class="template" id="orderchecklist_item_template1">
<td><input type="text" value="" name="servicename[]" placeholder="check list item" class="input-text">
</td>
<td class="last"><button style="" onclick="removefield(this);" class="scalable deletefield" type="button" title="Delete" id="delete_button"><span><span><span>Delete</span></span></span></button></td>
</tr>
</tbody>
<tfoot id="extra_field" class="no-display template">
<tr class="template" id="orderchecklist_item_template">
<td><input type="text" name="item[]" placeholder="check list item" class="input-text"></td>
<td class="last"> <button style="" onclick="removefield(this);" class="scalable deletefield" type="button" title="Delete" id="delete_button"><span><span><span>Delete</span></span></span></button></td>
</tr>
</tfoot>
</table>
my js code for adding and removing field
<script type="text/javascript">
function addfield()
{
var htm= $('extra_field').innerHTML;
$$('#<?php echo $_block->getHtmlId() ?>_list').last('tr').insert({after:htm});
}
function removefield(ele)
{
var row = ele.parentNode.parentNode;
row.parentNode.removeChild(row);
}
</script>
Just insert before hidden extra field.
Code
function addfield()
{
var htm= $('extra_field').innerHTML;
$('extra_field').insert({before:htm});
}
Another Way
function addfield()
{
var htm= $('extra_field').innerHTML;
$$('#orderchecklist_item_list tr').last('tr').insert({after:htm});
}
$$('#orderchecklist_item_list').last('tr') will find tr from orderchecklist_item_list elements. So it returns '#orderchecklist_item_list' it self.
Fiddle and Fiddle 2

JavaScript insertAfter and insertBefore

I am playing around with the JavaScript functions insertAfter and insertBefore, however I am trying to insertAfter and insertBefore two elements.
For instance, consider the following HTML:
<table>
<tbody>
<tr>
<td>
Item 1
</td>
<td>
<div class="moveUpDown">
<div class="up">
</div>
<div class="down">
</div>
<div>
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<table>
<tr>
<td>
1
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
Item 2
</td>
<td>
<div class="moveUpDown">
<div class="up">
</div>
<div class="down">
</div>
<div>
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<table>
<tr>
<td>
1
</td>
</tr>
</table>
</td>
</tr>
</table>
Then I have this JavaScript code snippet:
var row = $(this).parents("tr:first");
if ($(this).is(".up")) {
row.insertBefore(row.prev());
} else {
row.insertAfter(row.next());
}
Basically when the Up class is called, the previous row is moved up and when the Down class is called, the current row is moved down one row.
What I want to do, is move the rows Up/Down 2 rows... meaning something like row.prev().prev() or row.next().next() however this does not seem to work.
Is there an easy way around this?
Would appreciate any help/suggestions.
to go up
row.prev().prev().before(row)
to go down
row.next().next().after(row)
obviously the tr must exist prev/next have to exist
NB you are caching row as the first tr element so row is changing every time the first tr element change
listen to event
$("table").on("click","tr > td > span.moveup", function() {
var row = $(this).parent().parent();
if (row.prev().prev().get(0)) row.prev().prev().before(row)
})

Jquery DIV count

I am trying to count the number of elements under a parent but its giving me an incorrect count. The result should be 2, where as its returning me 4.
My HTML structure is:
<div style="overflow: hidden;" id="parentDiv" class="scroll">
<div id="3">
<table id="t3" class="Table">
<tbody>
<tr>
<td id="b3" class="bY"><table id="inner1" width="100%" cellpadding="3">
<tbody>
<tr>
<td class="code" id="code3" width="172"></td>
<td class="Num" id="Num3" width="50"></td>
<td colspan="2" class="Name" id="Name"></td>
</tr>
<tr>
<td class="code" width="172"></td>
<td> </td>
<td class="serial" width="110"></td>
<td class="serial" width="322"></td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>
</div>
<div id="4" >
<table id="t4" class="Table">
<tbody>
<tr>
<td id="b4" class="bY"><table id="inner1" width="100%" cellpadding="3">
<tbody>
<tr>
<td class="code" id="code4" width="172"></td>
<td class="Num" id="Num4" width="50"></td>
<td colspan="2" class="Name" id="Name"></td>
</tr>
<tr>
<td class="code" width="172"> </td>
<td> </td>
<td class="serial" width="110"></td>
<td class="serial" width="322"></td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>
</div>
and the code I am using to count is:
var numofDivs = $("#parentDiv div").size();
alert(numofDivs);
and if I am using the following code, the result is coming 1 (which is incorrect too).
var numofDivs = $("#parentDiv > div").size();
alert(numofDivs);
Hi you should use the function children()
$("#parentDiv").children("div").length
the function gives you an array and ten you can get the length.
and in the children function you can specify what tags to filter, but you can also leave it blank and it will give you all the children
check the API
With the give HTML code, your code to count the elements is correct, and both ways should return two.
So, the conclusion is that the HTML code doesn't actually look the way that you describe it. A structure that would give that result could for example look like this:
<div id="parentDiv">
<div>
<div></div>
<div></div>
</div>
<p>
<div>
</div>
</p>
</div>
If you want to count the first level of div elements that you encounter, you would have to do it recursively, i.e. for each child element check if it's a div element or count the number of first level div elements it contains:
function countDivs(element) {
var cnt = 0;
$(element).children().each(function(){
cnt += this.tagName === 'DIV' ? 1 : countDivs(this);
})
return cnt;
}
$(function(){
alert(countDivs($('#parentDiv').get(0)));
});

Change CSS class based on existence

Firstly I must emphasis that the HTML is pre-generated and cannot be altered - Otherwise I would not be doing it in this way : )
So....
The script and HTML below creates a nice hide/show menu, when you click the navheader the navitem becomes visible.
However I want the css class of the navheader to change based on if navitem is directly below it.
e.g.
navheader (Change Class to linksbelow)
navitem
navheader (Change Class to NOlinksbelow)
navheader (Change Class to NOlinksbelow)
navheader (Change Class to linksbelow)
navitem
etc....
My HTML and JQUERY:
<script>
$(function() {
$('.Nav table .navitem').hide();
$('.Nav table.navheader').click(function() {
$(this).parent().parent().next().find(".navitem").slideToggle('100');
});
});
</script>
<div class="Nav">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<table class="navheader">
<tr>
<td>
<a class="navheader" href="#">Header Link 1</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>
<table class="navitem">
<tr>
<td>
<a class="navitem" href="#">Link 1</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table class="navheader">
<tr>
<td>
<a class="navheader" href="#">Header link 2</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
Ok, this specific case doesn't seem to work out when using only CSS selectors (as there's no such thing as a 'previous sibling selector'), so it'll have to be a little more complex:
$('.Nav tr:has(table.navheader)').each(function (i, elmnt) {
if($(elmnt).next().find('table.navitem').length > 0)
$(elmnt).find('table.navheader').addClass('linksbelow')
});

Categories

Resources