I can't explain why ehn i click a button inside a table cell and try to get rowID - i see that its undefined
Here is my code
#model Onion.Web.ViewModels.CategoryViewModel
<script>
function btnEdit_Click()
{
var par = this.parentNode.parentNode;
alert(par.id);
}
</script>
<table>
<tr>
<td>ID</td>
<td>Title</td>
<td>Button</td>
</tr>
#foreach (var item in Model.lstCategoryLanguages)
{
<tr id='#item.CategoryLanguagesID'>
<td>#item.Title</td>
<td>#item.ShortDescription</td>
<td><input type="button" value="Edit" onclick='btnEdit_Click()' /></td>
</tr>
}
</table>
You need to pass the function the element you want to refer to, and then in the function use that.
This works for me:
<script>
function btnEdit_Click(elem)
{
var par = elem.parentNode.parentNode;
alert(par.id);
}
</script>
<table>
<tr>
<td>ID</td>
<td>Title</td>
<td>Button</td>
</tr>
#foreach (var item in Model.lstCategoryLanguages)
{
<tr id='#item.CategoryLanguagesID'>
<td>#item.Title</td>
<td>#item.ShortDescription</td>
<td><input type="button" value="Edit" onclick='btnEdit_Click(this)' /></td>
</tr>
}
</table>
I think this returns the wrong context there.
Try passing this in the onclick event and use the parameter instead in your function:
onclick='btnEdit_Click(this)'
I think it would be even better to bind #item.CategoryLanguagesID a second time and pass that the function to get rid of the static parentNode.parentNode reference. What if your structure changes over time? You'd always have to modify the function too.
Related
Let's say I have a button in a table which adds a new row to a table:
<td><a onclick="addRow()"></a></td></tr>...
and I want to reference $(this) or $(this).closest('tr') from the function at the bottom of the page.
function addRow(){
$(this) // contains all information from the row which pressed the button
}
Simply passing a javascript variable from the HTML will result in null (as expected). Is there a way to reference the row that pressed the button?
The RECOMMENDED way of doing this is unobtrusive and delegated - give the link a class:
var $tb = $("#someTable");
$tb.on("click", ".addRow", function(e) { // delegation to allow new rows' links to work
e.preventDefault(); // stop any click side effects
var $row = $(this).closest("tr");
$tb.append($row.clone())
});
a { text-decoration:none }
td,th { padding:3px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>Add</th>
</tr>
</thead>
<tbody id="someTable">
<tr>
<td>1st</td>
<td>2nd</td>
<td><a class="addRow" href="#">+</a></td>
</tr>
<tr>
<td>3rd</td>
<td>4th</td>
<td><a class="addRow" href="#">+</a></td>
</tr>
</tbody>
</table>
Use this
<td><a onclick="addRow(this)"></a></td></tr>
and then:
function addRow(e){
console.log($(e)) // contains all information from the row which pressed the button
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a onclick="addRow(this)">Clickme</a>
You can reference the row that you clicked using an event.
<td>Add</td>
and in javascript you can check the event
<script>
function addRow(event) {
console.log(event);
}
</script>
When it reaches the line this.parentNode.removeChild(this);
I get the error
this.parentNode is undefined
In the debugger I pause at the beginning of that statement and see that "this" is: Object[ tr#CMD01.selected ] which is exactly what I expect. How is parentNode undefined? I have done a lot of searching for similar problems here and keep finding cases where "this" is not correct, but in my case it is verified by the debugger.
$(document).ready(function() {
$.fn.deleteThisRow = function() {
this.parentNode.removeChild(this);
};
});
function deleteRow() {
$("#theList tr.selected").deleteThisRow();
}
.selected {
background-color: yellow
}
<body>
<center id='bg'>
<table id="cmdList">
<thead>
<tr id="hdrow">
<th>Col1</th>
<th>Col2</th>
<th>Col3</th>
</tr>
</thead>
<tbody id="theList">
<tr id="CMD00">
<td>A1</td>
<td>A2</td>
<td>A3</td>
</tr>
<tr id="CMD01" class="selected">
<td>B1</td>
<td>B2</td>
<td>B3</td>
</tr>
<tr id="CMD02">
<td>C1</td>
<td>C2</td>
<td>C3</td>
</tr>
</tbody>
</table>
<table id="buttons">
<tr>
<td>
<button onclick='deleteRow()'>Delete</button>
</td>
</tr>
</table>
</center>
</body>
When you implement a jQuery method, the value of this when it is called will be the jQuery object, not the DOM object. So, this.parentNode does not exist because a jQuery object does not have a property by that name.
You can either use jQuery's .parent() or you can get the actual DOM node and then use .parentNode on that.
If you only intend on ever processing a single DOM object at a time, you can do this:
$.fn.deleteThisRow = function() {
this[0].parentNode.removeChild(this[0]);
};
If your jQuery object may have multiple objects in it, then you can do this:
$.fn.deleteThisRow = function() {
this.remove();
};
Or, as you may notice, you don't even need a custom method for this. If you have a jQuery object for the row, you can just call .remove() on it directly.
function deleteRow() {
$("#theList tr.selected").remove();
}
I've a table like this:
<table>
<tr>
<td class="type">Order</td>
<td class="orderid">1002</td>
<td><button class="copy">Copy Row</button></td>
</tr>
<tr>
<td class="type">Order</td>
<td class="orderid">1004</td>
<td><button class="copy">Copy Row</button></td>
</tr>
<tr>
<td class="type">Refund</td>
<td class="orderid">1004</td>
<td><button class="copy">Copy Row</button></td>
</tr>
</table>
I've a script to copy data from a particular "#id" or ".class" element. What, I needed is to find a way to get the data of that particular row whenever, the Copy button is pressed. I want the columns 'orderid' and 'type' values of that particular row to be copied, but I'm not able to find a way to extract the data between the <td> tags with same class names.
Simple answer:
$('.copy').click(function(){
var order_id = $(this).parent().parent().find('.orderid').text();
var type = $(this).parent().parent().find('.type').text();
alert(order_id); ///this wil get you the value
});
I made the result here: http://codepad.viper-7.com/ahsVfB
check it.
<tr>
<td class="type">Refund</td>
<td class="orderid">1004</td>
<button class="copy">Copy Row</td>
</tr>
$(".copy").click(
function(event)
{
var copy=($(event.target).parent().find('.type'));
var order=($(event.target).parent().find('.orderid'));
}
);
You must paste that copied date somewhere. Make this copy and order as global variables. When you click paste, use this variable's value
take a look on this fiddle http://jsfiddle.net/3p29x2s9/11/
var buttons=document.getElementsByClassName("copy");
console.log(buttons);
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function(){
var columns = this.parentElement.parentElement.getElementsByTagName("td");
var type= columns[0].innerText;
var orderid=columns[1].innerText;
alert(type + " "+orderid);
}
}
Suppose I have already get the table with JavaScript like this:
var isert = inn.getElementsByTagName("table");
and I've got a structure like this:
<table width="100%">
<tbody>
<tr>
<td><div class="extra"></div>
</td>
</tr>
<tr>
<td><div class="extra"></div>
</td>
</tr>
<tr>
<td><div class="extra"></div>
</td>
</tr>
</tbody>
</table>
Here, how can I remove the outside Table structure, and keep the content only, so that result of the extracted code should be:
<div class="extra"></div>
<div class="extra"></div>
<div class="extra"></div>
Thanks!
I'd suggest:
function removeTo(from, what) {
if (!from || !what) {
return false;
}
else {
els = from.getElementsByTagName(what);
while (els[0]) {
from.parentNode.insertBefore(els[0],from);
}
from.parentNode.removeChild(from);
}
}
removeTo(document.getElementsByTagName('table')[0], 'div');
JS Fiddle demo.
Incidentally:
var isert = inn.getElementsByTagName("table");
Doesn't give you a reference to the table element, it gives you a nodeList of all the table elements within the inn variable (whatever that might be). To act on a particular table you need to specify which particular table you want to act upon, which is why, above, I've used document.getElementsByTagName('table')[0].
I have a table like this:
<table>
<tr>
<td>foo</td>
<td><button>delete</delete></td>
</tr>
<tr>
<td>foo</td>
<td><button>delete</delete></td>
</tr>
</table>
I want to use JQuery to install a click handler on the delete buttons such that it deletes the current row when clicked
Give a class of, for example, "delete" to the delete buttons, then use this:
$("button.delete").click(function() {
$(this).closest("tr").remove();
});
Alternatively, if you can't add the class, you can use the :contains selector:
$("button:contains('delete')").click(function() {
$(this).closest("tr").remove();
});
Update (now that the code in the question has completely changed)
Now that you have changed the code in the question to contain only one button instead of two, you don't need to bother adding the class, or using the :contains selector, you can just use the plain old button selector:
$("button").click(function() {
$(this).closest("tr").remove();
});
Try this. As a side not you should not have same id to any dom element on the page.
$("button").click(function() {
$(this).closest("tr").remove();
});
In your markup the tags are not closed properly. E.g the button tag is not closed properly so the selector will not work. Give a unique id or a class name to select the required buttons.
Something like this
<tr>
<td>foo</td>
<td>Some content</td>
<td><input type="button" class="delete" value="Delete" /></td>
</tr>
Using delegate to attach event handler only to table for better performance. This way the click event will be attached only to the table element no matter how many rows it has.
$("table").delegate("input.delete", "click", function() {
$(this).closest("tr").remove();
});
You can try soemthing like this:
<table>
<tr>
<td>row 1, cell 1</td>
<td><img class="delete" src="del.gif" /></td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td><img class="delete" src="del.gif" /></td>
</tr>
</table>
And your jQuery:
$('table td img.delete').click(function(){
$(this).parent().parent().remove();
});
First off, there's a syntax error in your HTML, and you should a class identifier for easier access to those buttons:
<table>
<tr>
<td>foo</td>
<td><button class="delete">delete</button></td>
</tr>
<tr>
<td>foo</td>
<td><button class="delete">delete</button></td>
</tr>
</table>
Next, here's the jQuery code you need:
$(function() {
$('button.delete').click(function(event) {
event.preventDefault();
$(this).closest('tr').remove();
});
});