<tr>
<td colspan="2">
<div>
<table id="dataTable">
<tbody>
<tr></tr>
<tr id="row_1"></tr>
<tr id="row_2"></tr>
<tr id="row_3"></tr>
</tbody>
</table>
</div>
</td>
</tr>
How can I get the value of a id in tr using jQuery? I have tried .attr but failed.
var row = jQuery('<tr>').attr("id", "row_" + item.autoID);
row.append(jQuery('<td>').append(jQuery('<input>').attr('type', 'checkbox', 'javascript:deleteChecked(' + item.autoID + ');').attr('id', 'check_id_')));
<input type="button" value="Delete" id="delete_check" disabled onclick="deleteChecked()"/>
I'm trying to get the tr attribute 'row_' + id. I have a checkbox. If you select the checkbox and then hit delete. It should delete the row with the specific id or all the checked rows.
So far I have got:
jQuery(document).on('click', '#check_id_', function(id){
jQuery('#delete_check').attr("disabled",!jQuery('#check_id_').is(":checked"));
//var row = jQuery(this).closest('tbody').find('tr').attr('id');
// console.log(row); //doesn't work
});
function deleteChecked(id){
//grab the checked row ids
}
Any help appreciated.
If I understand your requirement correctly, I would suggest approaching this problem in a slightly different way.
You simple cannot have duplicate IDs in your HTML. ID lookups use a fast lookup dictionary that can only store one element per id value so only the first is ever found.
Avoid using inline event handlers (like onclick="") at all costs in jQuery. It separates the handler registration from the handler response for no benefit and does not allow some of the additional cool event features jQuery provides (e.g. multiple handlers).
Use delegated event handler for your delete operations. This simplifies the HTML and allows for dynamic elements/rows in a far simpler way.
The way your question reads, it seems odd to use checkboxes instead of buttons for the delete. Use buttons instead unless you have good reason not to.
The rows do not need ID's unless those IDs are used for some other purpose. Just delete the row closest to the delete button that is clicked.
Use the $('<htmltag>', {'prop': 'value', 'prop2', 'value2'}) syntax to create new elements with properties. It is shorter and easier to read.
So, putting all that together, you get the following to create a new row:
var row = $('<tr>', {
"id": "row_" + item.autoID,
text: "NEW ROW"
});
row.append($('<td>').append($('<input>', {
'type': 'button',
'value': 'X',
'class': 'deleteme'
})));
$('#dataTable').append(row);
and this simple code to delete the row that has its deleteme 'X' button pressed:
$('#dataTable').on('click', '.deleteme', function(){
$(this).closest('tr').remove();
});
This is a delegated event handler. It delegates responsibility for listening for the click event to a non-changing ancestor element. When a click event bubble up to that element, it then applies the jQuery selector (in this case the class deleteme) and then runs your callback function against any matching elements that caused the event in the first place. The upshot is that the deleteme buttons only need to exist at event time for this to work.
Clean and simple.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/k5rh82cz/
Now if you actual aim is different, you need to explain how you want it to appear too :)
To iterate the rows with checked checkboxes in them and fetch their ID's, something like this should do the trick:
$('#dataTable')
.find('input[type="checkbox"]:checked')
.closest('tr')
.each(function(ind, ele){
var id = $(ele).attr('id');
//do something with the id here
});
See this demo fiddle
HTH,
-Ted
Related
I have some <tr> elements with unique IDs.
<tr id="683535">some code</tr>
<tr id="683536">some code</tr>
<tr id="683537">some code</tr>
I want users to click on <tr>, after what a js function will be called. And I need to get this ID inside of current function without using events like <tr onclick="". Is this even possible?
You could do
$('tr').on('click',function(){
var id = $(this).attr('id');
});
In your event listener you should have a variable for the event.
Example:
$("body").on("click", "tr", function(e){
var row = $(this);
console.debug(row); //Should print clicked TR
console.info(row.attr("id")); //Should print the ID
});
If you don't want events, than your only way to interact with browser is classic hyperlink with <a> tag, where you can also include js functions like do stuff with your uid so you can simply generate such hrefs for each row inside your row generator.
I am creating a responsive data table that adds a row each time I click on a add button that is in the end of the row. And the add button turns into a delete button. Here's the code I made
For the Table:
<table id="invoice_table_data">
<tr id="last_row">
<td contenteditable id="item_name"></td>
<td contenteditable id="item_code"></td>
<td contenteditable id="description"></td>
<td>
<button type="button" name="btn_add" id="btn_add" class="btn btn-xs btn-success">+</button>
</td>
</tr>
</table>
When for adding is clicked:
$("#btn_add").click(function() {
$("#invoice_table_data").append('<tr id="myTableRow'+'" ><td id="item_name'+n+'">'+item_name+'</td><td id="item_code'+n+'"> '+item_code+'</td><td id="description'+n+'">'+description+'</td><td><button type="button" name="delete_" id="delete_" data-idx="'+n+'">x</button></td></tr>');
n+=1;
And my delete function:
$('#delete_').click( function () {
var nb=$(this).data('idx');
$("#last_row"+nb).remove();
});
However when I click on delete nothing seems to happen. Can anybody help?
Identifiers in HTML must be unique, So create the element using CSS class. then Class Selecctor can be used.
Change script to render HTML as
<button type="button" class="delete_">x</button>
Currently what you are using is called a "direct" binding which will only attach to element that exist on the page at the time your code makes the event binding call.
Use .on() method with Event Delegation approach while generating elements dynamically. So change your code to
$("#invoice_table_data").on('click', ".delete_", function(){
$(this).closest('tr').remove();
});
var n = 1;
$("#btn_add").click(function() {
$("#invoice_table_data").append('<tr><td>item_name' + n + '</td><td><button type="button" class="delete_" data-idx="' + n + '">x</button></td></tr>');
n += 1;
});
$("#invoice_table_data").on('click', ".delete_", function() {
$(this).closest('tr').remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="invoice_table_data">
<tr id="last_row">
<td id="item_name"></td>
<td>
<button type="button" name="btn_add" id="btn_add" class="btn btn-xs btn-success">+</button>
</td>
</tr>
</table>
Use attribute selector and event delegation
$(document).on('click', "[id^='delete_']", function () {
var nb=$(this).data('idx');
$("#last_row"+nb).remove();
});
Try this :
$('document').on('click', '#delete_', function () {
var nb=$(this).data('idx');
$("#last_row"+nb).remove();
});
You need to use on method, since your delete button not yet been exists.
You have two separate problems.
Problem 1
You can't have the same id multiple times on the page. That's just a basic rule of HTML. You can only use it once. If you use the same id more than once, only the first time will be counted.
Solution
If you want to be able to target multiple elements, use classes, or target a single parent and grab it's children using element.firstElementChild
Problem 2
When you write .click, you are telling the browser to watch for when a user clicks on the element that you are targeting.
However, that element has to exist when the page first loads. That is because the lines of Javascript are only parsed once by the browser. It reads through your code, and if the element you want to click on doesn't exist right then, your code is skipped.
Solution
So what you have to do to address this is to add the event listener, the .click, onto an element which isn't dynamic. Remember that every click event gets passed up the chain, from the inner most element that the user clicked on, to that element's parent, to the next parent, and so on until it reaches the body element. So if you add a .click onto the parent of your list, it'll be attached correctly.
Using jQuery, it would be something like:
$('#invoice_table_data').on('click', 'button.delete', function(event){
//run code here
});
Change your script which is dynamically adding the delete button to give the button a class name of btnDelete or something similar.
$("#btn_add").click(function() {
$("#invoice_table_data").append('<tr id="myTableRow'+'" ><td id="item_name'+n+'">'
+item_name+'</td><td id="item_code'+n+'"> '
+item_code+'</td><td id="description'+n+'">'
+description+'</td><td><button type="button" class="btnDelete" name="delete_" id="delete_" data-idx="'+n+'">x</button></td></tr>');
n+=1;
});
Then the script for your delete button is:
$("body").on("click", ".btnDelete", function (e) {
var rowToDelete = $(this).closest("tr");
rowToDelete.remove();
});
http://codepen.io/ailinmcc666/pen/ZBgXBZ
I have a table that's generated through php. Whenever "bob" is the name of the person who this data belongs to, I generate a tr id to denote that:
<tr id="0bob">...</tr>
<td>...</td>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
The data inside each of the tds inside of the trs is different, and the user has to select which of these rows they want, using this checkbox:
print "<input type=\"checkbox\" id=\"check\" data-border=\"$border\" data-z=\"$z\" data-x=\"$x\" data-pn=\"$pn\" value=\"\">";
Then, in my JavaScript, I have the following line which is supposed to dim all of these lines whenever one of the checkboxes in these trs is clicked.
var pn = this.dataset.pn;
var x = this.dataset.x;
//anytime a checkbox with the id 'check' is clicked, (this is every checkbox on the page)
$('input[type="checkbox"][id="check"]').change(function() {
$( "#" + x + PN ).fadeTo( "slow" , 0.7, function() { });
}
The code, in my mind, is accurate - I'm asking for any td with the id of 0bob to be faded to 70%. The issue is that while the code "works," it only fades the first instance of this, then stops, like so:
It always fades the first instance, (red in this example,) regardless of which color the user selects, (blue, pink, or yellow).
I also can't use a tr class because I'm already using the class to change other aspects of the formatting. What am I doing wrong here?
You must use class. Ids must be unique and the browser will get angry if you duplicate them. You can pass multiple classes as follows:
<element id="some-id" class="class1 class2 class3">
From JavaScript classes can be added or removed using classList. JQuery has https://api.jquery.com/addclass/ method.
You should be using data-* attribute since ID is meant to occur once in the document. You can however work around this limitation by using an attribute selector like $('[id=0bob]'). See for example http://jsfiddle.net/Lk7dqbp6/
Your problem is that id attributes must be unique.
And the browser does that: finds the first element with that id and stops there, as it should.
Using repeated ids is invalid HTML and must be avoided like plague.
There are many alternatives for this.
I will only write the HTML structure for this.
Solution 1: a data-* attribute
You already use those, so, just use another one!
<tr data-user="bob"></tr>
These were made with the goal of providing aditional data about an element.
Solution 2: another class
You can have multiple classes per element.
Just make sure they are separated by a space:
<tr class="user-bob another-class more classes"></tr>
This may be harder to use.
Solution 3: another id schema
If you have a primary key on your SQL, you can use it to identify the user:
<tr id="user_bob_0"></tr>
<tr id="user_bob_1"></tr>
<tr id="user_bob_2"></tr>
This may be a bad idea in some situations but it will have all the data ready to use without many troubles.
Outside the scope of the answer, you have another problem:
You have this code:
var pn = this.dataset.pn;
var x = this.dataset.x;
//anytime a checkbox with the id 'check' is clicked, (this is every checkbox on the page)
$('input[type="checkbox"][id="check"]').change(function() {
$( "#" + x + PN ).fadeTo( "slow" , 0.7, function() { });
}
You see the comment?
Same problem: non-unique ids...
For this one, you would be better off using classes.
Instead of
$('input[type="checkbox"][id="check"]')
You would use
$('input.check')
Or
$('.check')
This is the right way to do it.
Also, the performance gain will be HUGE!
Attribute selectors (like [type="checkbox"] and [id="check"]) are one of the slowest selectors!
The only selectors slower than these are the pseudo-element selectors (:before, :after, ::selection, ...).
You can read more here: Is CSS faster when you are specific?
You may be thinking that this won't affect jQuery, but it will.
jQuery uses document.querySelectorAll() which runs a CSS selector in the DOM to select Javascript objects. (When it fails or isn't available, jQuery uses other methods)
Imagine your jQuery looking for over 300 elements for the selector in each of them.
Now imagine a basic table with the classes, where a few elements are connected to an entry.
See the difference?
This is the difference between your code taking 200ms and 30ms (non-measured).
so what I'm triying to achieve is that I want one element to append some other elements to div and change its ID attribute (or something similar).
i have tried something like this
$('#add3').click(function(){
$('#add3').attr("id", "add4");
$('.third_row1').append('something to append');
});
and also tried something like this:
$('#add').click(function(){
var vari = $("<div id='add2'>add another user</div>");
$('#add').remove();
$('.third_row1').append(vari);
$('.third_row1').append('something to append');
});
so clicking one button (like second example) has no effect on third, fourth ... n click
same thing with the second example
thanks in advance for help
UPD
ok, so here's how I generate selects which I want to append
<jsp:useBean id="obj1" class="com.Users" scope="page"/>
<div class="third_row1">
<select name="mySelect1" id="mySelect1">
<c:forEach var="item1" items="${obj1.items}">
<option>${item1}</option>
</c:forEach>
</select>
</div>
all I want to do is to add same select, but with different ids and names
Since elements IDs are changed dynamically, you should use delegated event handlers with .on().
For example:
$(document).on("click", "#add3", function() {
$('#add3').attr("id", "add4");
$('.third_row1').append('something to append');
});
If all these elements (#add, #add3) are inside page static element, it will be better to use this element instead of document for perfomance:
$("static_element_selector").on("click", "#add3", function() {
And just to note: since this inside event handler points to clicked DOM element, you can use this.id = "add4" instead of $('#add3').attr("id", "add4");. It is shorter and works slightly faster.
I have a 3 tables that every row have 2 \ 4 \ 6 columns , and the last column contains a edit button.
When I press the edit button, I want all the other td's will turn into a textboxes.
The script:
$(".icon-pencil").click(function () {
var row = $(this).parent('td').parent('tr');
row.find('td').each(function () {
$(this).html("hi");
});
});
a row example:
<tr>
<td>1</td>
<td>
<img src="img/couponimg.png" alt="" />
</td>
<td>1</td>
<td>A coupon for ..</td>
<td><i class="icon-pencil"></i>
</td>
<td><i class="icon-remove"></i>
</td>
</tr>
It works as I want, but it applies the change to all the <td> , and I don't want to change the last one.
How to prevent to affect to the last one?
I recommend event delegation.
$(document).on('click', '.icon-pencil', function () {
$(this).closest('tr').find('td:not(:last)').html("hi");
});
Also,
$('something').each(function() {
$(this).html("hi");
});
is equivalent to
$('something').html("hi");
Try this:
row.find('td').each(function() {
$(this).not('td:last-child').html("hi");
});
Try this and use :not(:nth-last-child(-n+2)) which will EXCLUDE the last 2 columns.
$(".icon-pencil").click(function() {
var row = $(this).closest('tr');
row.find('td:not(:nth-last-child(-n+2))').each(function() {
$(this).html("hi");
});
});
example :
http://jsbin.com/oyUvAhi/2/edit
2 changes :
closest instead of .parent('td').parent('tr')
when finding the TR - select only the relevant TD's for change.
Edit
please read #François Wahl comment - which helps shorten the code :
row.find('td:not(:nth-last-child(-n+2))').html("hi");
Since your HTML is well formed, in this particular situation, the :last CSS selector works nicely, so you can use that. I will give you a more general solution, when the element is not the last node in the parent, or perhaps not even the last node of its type in the parent (:last-of-type).
jQuery objects are collections of elements. The CSS selector usually used to create such a collection is matched on the DOM, but once you have a jQuery object you can manipulate it any way you want. If you want to eliminate the last element, you can do something like this:
var myJQueryObject = $('mySelector');
Array.prototype.splice.call(myJQueryObject, myJQueryObject.length-2, 2); // removed the last two elements
This relies on the fact that jQuery objects are Array-like objects (have a length property and numeric-like keys) and Array.prototype.* methods work on Array-like objects.