I have to mark all rows in a table (and later change the code to delete the rows).
The table structure looks like:
<table class="table table-striped table-condensed" id="buckettable">
<thead>
...cut out
</thead>
<tbody>
<tr class="success">
<td><input class="fld-bucketno" type="checkbox" name="bucket" value="158bf61f-8f66-4dee-9ff6-b9d1f6d4b840" /></td>
<td class="text-right">
<a class="bucketNo" href="/Sim/Staging/1212">1212</a>
</td>
What I am interested in is the value of the anchor in the td - second last line.
I get a json list of id's to delete. First I mark them, then change the code to delete them. That is the idea, at least. Mind me - I know a lot of programming, but Javascript is an unknown land for me ;)
My code so far is:
success: function (resp) {
var table = $('#buckettable').find('tbody')[0];
var length = resp.length;
for (var i = 0; i < length; i++) {
var bucketNo = resp[i];
var rows = table.children.length;
for (var j = 0; j < rows; j++) {
var row = table.children[j];
var bucket = row.find('.bucketNo').text();
if (bucket == bucketNo) {
alert(bucket);
}
}
}
$('#cleanup').modal('hide');
and I fail to filter the rows. I am open to any sensible other approach - hopefully it teaches me a lot.
In the above code I manage to get the row... but then the find('.bucketNo') fails with an aexception that Object # has no method find.... which I find funny because I use that on a form earlier. Pointers to documentation VERY welcome, especially in addition to an answer.
If there is a better way to do that tell me. I was told that search by ID is faster (obviously) but somehow I am not sure - should I set a coded ID (bucket-xxx, xxx being the number) on every row?
There is a much simpler way of doing this.
var targetBucketNo = 1212;
$('#buckettable a.bucketNo')
.filter(function(item) {
return item.text() == targetBuvketNo;
})
.parent()
.remove();
To explain in more detail. The following will get the anchors with the bucketNo class that are inside your #buckettable table.
$('#buckettable a.bucketNo')
Filter will filter the results for ones that have the target bucket number
.filter(function(item) {
return item.text() == targetBuvketNo;
})
Remove will remove the elements
.remove();
You can replace .remove() with .addClass('your-class-name') if you wanted to add a class instead. This would add it to the td element so you should add .parent() before addClass.
You are accessing the native Javascript children, hence find() is not a function. However you can skip around a lot of the native functions you're using by using the jQuery filter method:
var $aTag = $('#buckettable').find('tbody td a.bucketNo').filter(function() {
return $(this).text() == bucketNo
});
alert($aTag.text());
You can also loop all links with the class "bucketNo" and then look if the ID is in your array. After this get the containing TR and delete it or add a class or something:
var resp = [2323,5656]
$('a.bucketNo').each(function() {
if( resp.indexOf( parseInt($(this).text()) ) != -1 )
$(this).closest('tr').addClass('del');
});
http://jsfiddle.net/44cEt/
Related
I am loading a webpage through a java script with the intention of pulling a single string value from that website's HTML source code to use elsewhere in my script. So the website has multiple row containers that follow this basic format:
<tr>
<td align="left">
<span class="criteria1">
<script>document.write("INFO I WANT");</script>INFO I WANT
</span>
</td>
<td align="left">1234
</td>
<td align="left">
<div class="criteria2" data-value="100" title="1642"></div>
</td>
<td align="left">
<span class="criteria3" style="font-weight:bold; font-size:10px;">North</span>
</td>
</tr>
The site has many of these row containers that I am not interested in, and a handful that I am interested in. So, I want to check each row container to see if the following criteria is met (they are in my above example):
There must be a span element with class="criteria1"
There must be a an anchor tag with "1234" somewhere in the title= attribute value
There must be a div element with class="criteria2" AND data-value="100"
There must be another span element with class="criteria3" and "North" in whatever field you see it in my example
If these criteria are met, I want to pull the "INFO I WANT" string, and save it to a variable in my script. We could pull this from within the script tags or from where it appears after the tag... what would this be, the innerHTML content of this specific span tag?
As you have gathered from this point, I am new to javascript, so I apologize in advance if any of this is stupid, easy, and/or unclear. I have done a lot of digging to try to figure out how to do this, but after a day and a half of testing with little progress I have reached a breaking point of sorts. Obviously, it will require a loop to go over each container, and then (I am guessing) use the getElementsBy methods to check the criteria.
Pardon my lack of formal training/vocabulary, and thanks in advance for any help. Just by trolling StackOverflow, you all have already helped me a GREAT deal in other ventures!! And please, by all means, correct any misuse of terminology above. Knowing the right way to express these ideas will help me greatly in future research to find answers to my questions.
This isn't a complete solution, but it should set you on the right path. Isolate each of the criteria into a method you can pass the row to. That way, you can change criteria easily later on.
// get all rows
var trs = document.getElementsByTagName('tr'),
currentRow,
i = 0;
for (; i < trs.length; i++) {
currentRow = trs[i];
if (hasClassCriteria1(currentRow)) {
if (hasAnchorWithTitle(currentRow)) {
if (hasDivWithCriteria2(currentRow)) {
console.log('continue checks until you find what you want...');
}
}
}
}
// There must be a span element with class="criteria1"
function hasClassCriteria1 (row) {
var spans = row.getElementsByTagName('span'),
i;
// Do any of these spans have the class "criteria1"?
for (i = 0; i < spans.length; i++) {
matched = spans[i].classList.contains('criteria1');
if (matched) {
return true;
}
}
}
// There must be a an anchor tag with "1234" somewhere in the title= attribute value
function hasAnchorWithTitle (row) {
var a = row.getElementsByTagName('a'),
i;
for (i = 0; i < a.length; i++) {
if (/1234/.test(a[i].getAttribute('title'))) {
return true;
}
}
}
// There must be a div element with class="criteria2" AND data-value="100"
function hasDivWithCriteria2 (row) {
var divs = row.getElementsByTagName('div'),
i;
for (i = 0; i < divs.length; i++) {
if (divs[i].classList.contains('criteria2')) {
if (divs[i].getAttribute('data-value') == 100) {
return true;
}
}
}
}
with jQuery
If you can use jQuery, the selectors will be very easy and expressive.
// There must be a span element with class="criteria1"
tr = tr.has('span.criteria1');
// There must be a an anchor tag with "1234" somewhere in the title= attribute value
tr = tr.has('a[title*="1234"]');
// There must be a div element with class="criteria2" AND data-value="100"
tr = tr.has('div.criteria2[data-value="100"]');
// There must be another span element with class="criteria3" and "North" in whatever field you see it in my example
return $('span.criteria3', tr).html() === 'North';
You can see the full example here. It finds all the rows that match your criteria, then loops through them, alerting with the value you're seeking.
jQuery is your friend. There is a ton of documentation and it's easy to get started. Don't reinvent the wheel, unless you're just trying to learn.
How to select a tag having a specific text inside it and nothing else? For example if I have the following:
<table>
<tr>
<td>Assets</td><td>Asset</td>
</tr>
<tr>
<td>Play</td><td>Players</td><td>Plays</td>
</tr>
</table>
Is there any way that I may select the <td>Asset</td> and nothing else. I tried it with contains i.e. $("table tr td:contains(Play)") but it returns all the tds in the second tr (as it should). Whereas I just want <td>Play</td>.
Is there any way to achieve this, like there's a way to select elements based on their attributes. Is there any way to select elements based on the text inside them?
How about that:
var lookup = 'Asset';
$('td:contains('+ lookup +')').filter(function() {
return $(this).text() === lookup;
});
Demo
Try before buy
Try something like this :
$("table tr td").filter(function() {
return $(this).text() === "Play";
})
If it was an input field you can specify something similar, but a little more exact with $('input[name~="Plays"]) so that it would filter out every other word, leaving the value isolated.
Other than that, the only way I know of doing this with a table is with what you had, but also throwing a conditional statement to check the text inside them.
Here is my version of accomplishing this:
http://jsfiddle.net/combizs/LD75y/3/
var play = $('table tr td:contains(Play)');
for (var i = 0, l = play.length; i < l; i++) {
if ($(play[i]).text() === "Play") {
// your script to modify below
$(play[i]).css({"color" : "red"});
}
}
What I want to do, in short, is from $(this) being a table row, find the next table row with a class of "example" (not necessarily a sibling).
I.E. use next() to find the next row with a class of "example" which isn't a sibling.
HTML:
<table>
<tr><td>One</td></tr>
<tr class="current"><td>Two</td></tr>
<tr><td>Three</td></tr>
<tr><td>Four</td></tr>
<tr class="target"><td>Five</td></tr>
<tr><td>Six</td></tr>
</table>
JavaScript:
var current = $('.current').next();
while(current.size() && !current.hasClass('target')) {
current = current.next();
}
current.css('color', '#0f0');
OR
$('.current').nextAll('.target').last().css('color', '#0f0');
If you're building those <tr>s from strings, you could do something like that:
var x = '';
for(var i = 0; i < 3; i++) {
x += '<li>Test ' + i + '</li>';
}
$(x).appendTo('#test');
So instead of inserting the table rows one by one, put them together as one string, make a jQuery object from that string and attach that to your table.
This also helps you with performance, since you edit the DOM only once.
the following question might be an easy one for most of you. But I am just beginning JavaScript and I really would appreciate if someone could point me in the right direction.
I have a normal HTML table where each row has its own id. What I want to achieve is that each time I click a link in a row the id for that row should be stored in a variable and later passed to a function. Let's say I click row#1 then id#1 should be passed and so on... How can I achieve this?
Thank you.
This should work:
var currentRowID, table = document.getElementById('your-table');
var rows = table.rows;
var row_count = rows.length;
for(var i = 0; i < row_count; i++) {
rows[i].onclick = function() {
currentRowID = this.id;
//do something with currentRowID here...
};
}
jsFiddle example
When you arrange for an event handler to respond to clicks, the browser will set things up so that you can figure out what element was clicked (the "target" of the event). In your Javascript, you could do something like this, assuming your <table> is the only table on the page:
function handleRowClicks(e) {
e = e || window.event;
if (!e.target.tagName.toLowerCase() === "tr") return;
var rowId = e.target.id;
/*
whatever you want to do goes here
*/
}
// To set up the event handler, do this in your "window.onload" or some
// other initialization point
document.getElementsByTagName("table")[0].onclick = handleRowClicks;
This is only one of a bunch of different approaches. If you were to use a Javascript framework/library, it would get a little simpler, probably, but not much.
Note that this approach handles the clicks at the level of the <table> instead of the rows themselves. That saves a little bit of initialization work.
Similar to the other example, here's how you could do this in pure JavaScript:
// Pure JavaScript:
var table = document.getElementById("table-one");
var rows = table.rows;
var length = rows.length;
for(var i = 0; i < length; i++) {
rows[i].onclick = function() {
alert(this.id);
// Do more stuff with this id.
}
}
In my opinion, this particular problem is solved very nicely by jQuery. If you're performing other operations similar to this, jQuery will save you a ton of time, and keep the complexity level of your code down. Compare the above with this:
// jQuery:
$("#table-one tr").bind("click", function() {
alert(this.id);
});
bind is a jQuery method that just, well, binds an event to a handler :)
Working sample: http://jsfiddle.net/andrewwhitaker/9HEQk/
The easiest way to do that is using jQuery framework.
// Your function
function MyFunc(rowId){
alert(rowId);
}
// Binde click event to all rows with class "ClockableRow"
// within table with class "clickableTable"
$(".clickableTable .clickableRow").click(function(){
// Call you function and pass clicked row ID there
MyFunc($(this).attr("id"));
})
You table shoul look like this:
<table class="clickableTable">
<tr id="row1" class="clickableRow"><td>row 1</td></tr>
<tr id="row2" class="clickableRow"><td>row 2</td></tr>
<tr id="row3" class="clickableRow"><td>row 3</td></tr>
<tr id="row4" class="clickableRow"><td>row 4</td></tr>
<tr id="row5" class="clickableRow"><td>row 5</td></tr>
</table>
example
Hello I have a table which has a few rows. And I have an add button in my application which allows to add rows at any rowIndex. I use insertRow method to insert rows at a specific position. So once a row in inserted, I change the table row Ids of all the rows, to arrange them in an ascending order. Now I have been developing this application in FF and it has been coming pretty well. Now I am making a few changes to the code to make it work in IE. But this just does not work in IE. I have been testing this code for the last two days, it works in FF and chrome, but not in IE. I am not sure, what is the mistake I am making. I am just recreating the situation with an example, and this is the code for that example. Please help me out and tell me what could be the mistake I am making for it not to be working in IE. Any suggestions would be a great help.
<html>
<head>
<script type = 'text/javascript'>
function getIds()
{
var elem = document.getElementsByTagName("tr");
for(var i in elem)
{
if(elem[i] && elem[i].id!=null && elem[i].id!='')
alert(elem[i].id);
}
}
function changeIds()
{
var elem = document.getElementsByTagName("tr");
for(var i in elem)
{
if(elem[i] && elem[i].id!=null && elem[i].id!='')
{ index = Number(elem[i].rowIndex)+1; elem[i].id = "tabsf_"+index;}
}
alert('change');
}
</script>
</head>
<body>
<table id="tabsf">
<tbody>
<tr id="tabsf_1"><td>1</td><td>2</td></tr>
<tr id="tabsf_2"><td>3</td><td>4</td></tr>
<tr id="tabsf_5"><td>5</td><td>6</td></tr>
<tr id="tabsf_3"><td>7</td><td>8</td></tr>
<tr id="tabsf_4"><td>9</td><td>10</td></tr>
</tbody>
</table>
<table><tr><td><input type="button" name="hach" value="getIds" onclick="getIds()" /></td>
<td><input type="button" name="hach" value="Change Ids" onclick="changeIds()" /></td></tr></table>
</body>
</html>
</code>
The problem is that for..in loop doesn't ensure order. It is one of the gotchas why you should avoid them for arrays. (there is another, see my link)
Use simple for loops instead ( for i..n )
function getIds() {
var elem = document.getElementsByTagName("tr");
for (var i = 0; i < elem.length; i++) {
if (elem[i].id) {
alert(elem[i].id);
}
}
}
function changeIds() {
var elem = document.getElementsByTagName("tr");
for (var i = 0; i < elem.length; i++) {
if (elem[i].id) {
index = Number(elem[i].rowIndex) + 1;
elem[i].id = "tabsf_" + index;
}
}
alert('change');
}
Works perfectly cross-browser.
I would say try using the setAttribute function vs the id property to change the id.
Update: Try #Spinon's idea first.
Update: It seems to in fact have been an ID collision, something IE rightly prevented from happening and the other browsers happily let through.
Original answer:
My guess is that your loop creates an id collision: An id is set twice while the loop runs. IE could (rightly) be blocking the setting of a duplicate ID.
I would try unsetting the IDs first:
for(var i in elem)
{
if(elem[i] && elem[i].id!=null && elem[i].id!='')
elem[i].id = elem[i].id + "_temp";
}
for(var i in elem)
{
if(elem[i] && elem[i].id!=null && elem[i].id!='')
{ index = Number(elem[i].rowIndex)+1;
elem[i].getElementsByTagName("td")[0].innerHTML = "tabsf_"+index;
elem[i].id = "tabsf_"+index;}
}
However, I don't understand how you use row IDs to change the sorting?