Catch element by class using index or eq in jquery - javascript

HTML code:
<table border='1' cellpadding='5'>
<tr>
<td class="order">two</td>
<td>demo</td>
<td>last</td>
</tr>
<tr>
<td>two</td>
<td class="order">three two</td>
<td>sample</td>
</tr>
<tr>
<td>two</td>
<td class="order">five two</td>
<td>sample</td>
</tr>
<tr>
<td>five</td>
<td>quick</td>
<td class="order">nine</td>
</tr>
</table>
jQuery code:
$('.order').click(function(){
var index = $(this).index();
var text = $(".order:eq(index-1)").text();
alert(text);
});
On clicking any order class I want to get previous or next element with same order class. What iswrong with my code.
Here is my Fiddle
Thank you.

index is a variable so you have to add it to the string in jQuery like:
$(".order").click(function() {
var index = $(".order").index(this);
var text = $(".order:eq("+(index-1)+")").text();
alert(text);
});
DEMO

You need to find the index based on the collection set
var $orders = $('.order').click(function () {
var index = $orders.index(this);
if (index > 0) {
var text = $orders.eq(index - 1).text();
alert(text);
}
});
Demo: Fiddle

There are two problems with that code:
First, that form of index will tell you the index of the element relative to its siblings, not relative to other elements with the same class. So with your HTML, it'll always be 1 because all of your .order elements are the second child in their parent.
The second thing is that this line:
var text = $(".order:eq(index-1)").text();
...uses index literally, it doesn't swap in the value of your index variable.
You're on the right track with index, though, you just use a different form of it:
var orders = $(".order");
var index = orders.index(this);
Then rather than build a selector that jQuery can't hand off to the browser (because it uses a jQuery-specific :eq selector), use the eq function:
var text = orders.eq(index - 1).text();
But you'll want to handle the case where there is no previous element as well, perhaps:
var text = index > 0 ? orders.eq(index - 1).text() : "default text";
Live example:
$('.order').click(function(){
var orders = $(".order");
var index = orders.index(this);
var text = index > 0 ? orders.eq(index - 1).text() : "default text";
alert(text);
return false;
});
<table border='1' cellpadding='5'>
<tr>
<td class="order">two</td>
<td>demo</td>
<td>last</td>
</tr>
<tr>
<td>two</td>
<td class="order">three two</td>
<td>sample</td>
</tr>
<tr>
<td>two</td>
<td class="order">five two</td>
<td>sample</td>
</tr>
<tr>
<td>five</td>
<td>quick</td>
<td class="order">nine</td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Related

How to find the value from a row of table depending on the row of a button I clicked

No jQuery involve pls. I am just started learning javascript.
I want to find the class='id' of the table when I clicked on the class='detail' button.
I manage to point to class='id' but I can't get the value out of it, why?
var button = document.getElementsByClassName("detail");
for (var i in button) {
button[i].onclick = function() {
var row = this.closest("tr");
var id = row.getElementsByClassName("id");
var value = id.innerText;
console.log(id);
console.log(value); //show undefined here
}
}
<table>
<tbody>
<tr>
<td class="id">123</td>
<td class="name">abc</td>
<td><button class="detail">detail</button></td>
</tr>
<tr>
<td class="id">456</td>
<td class="name">def</td>
<td><button class="detail">detail</button></td>
</tr>
</tbody>
</table>
where would need to change? I must use class here, as the table generated through javascript. thanks.
getElementsByClassName returns HTMLCollection containing multiple matching elements. Like an array, you can access the first element in the collection with [0]
var button = document.getElementsByClassName("detail");
for (var i in button) {
button[i].onclick = function () {
var row = this.closest("tr");
var id = row.getElementsByClassName("id");
var value = id[ 0 ].innerText;
console.log(id);
console.log(value);
}
}
<table>
<tbody>
<tr>
<td class="id">123</td>
<td class="name">abc</td>
<td><button class="detail">detail</button></td>
</tr>
<tr>
<td class="id">456</td>
<td class="name">def</td>
<td><button class="detail">detail</button></td>
</tr>
</tbody>
</table>

jQuery parent or parents to get data-attribute in table th tag

I have a table that are like a grid with a horizontal list in the top with week numbers within th tags and below each week are different values in rows of tr and td tags.
I'm trying to get the data-attribute for the week when I click below in one of the td tags with the data-id attribute. But I can't get it right and wonder what I have done wrong to be able to read this value?
Some of the combinations I have tested:
var test = $(this).closest("th").attr("data-week");
var test = $(this).parents().find(".week").attr("data-week");
var test = $(this).parents("th").attr("data-week");
The HTML with data-attributes for the table:
<table>
<thead>
<tr>
<th class=""></th>
<th class="week" data-week="15">15</th>
<th class="week" data-week="16">16</th>
<th class="week" data-week="17">17</th>
<th class="week" data-week="18">18</th>
<th class="week" data-week="19">19</th>
</tr>
</thead>
<tbody>
<tr>
<td>Stina (1)</td>
<td data-id="40">10</td>
<td data-id="12">20</td>
<td data-id="13">40</td>
<td data-id="14">45</td>
<td data-id="15">40</td>
</tr>
<tr>
<td>Linda (2)</td>
<td data-id="0">0</td>
<td data-id="0">0</td>
</tr>
<tr>
<td>Lasse (3)</td>
<td data-id="21">5</td>
<td data-id="22">39</td>
<td data-id="23">40</td>
<td data-id="24">40</td>
</tr>
</tbody>
</table>
#Sean DiSanti, good one!
Here is a slightly more efficient version, without warping $ in $, by using eq method
$('td').on('click', function(e) {
var index = $(this).index() -1;
var week = $('.week').eq(index).data('week');
console.log('week', week);
});
jsfiddle
Here is a way you can find the data-week attribute of the clicked th element.
$(document).ready(function(){
$("td").on("click",function(){
$td=$(this);
$th = $td.closest('table').find('th').eq($td.index());
alert($th.attr("data-week"));
});
});
Demo: https://jsfiddle.net/7b146hor/2/
You need to find it by index. Get which child number the clicked element has and then look for same number in .weeks
Demo
$('td').on('click', function(e){
index = $(this).index();
week = $('.weeks').find(":eq("+index+")").attr('data-week');
console.log(week);
});
This worked for me
$('td').on('click', function(e) {
index = $(this).index();
week = $($('.week')[index - 1]).data('week');
console.log('week', week);
});
jsfiddle example

Search the table by cell content with jquery and relative referencing

Having such table
<table>
<thead> ... </thead>
<tbody>
<tr class="TableOdd">
<td class="TableCol0"> 1 </td>
<td class="TableCol1"> x </td>
<td class="TableCol2"> x </td>
<td class="TableCol3"> # </td>
</tr>
<tr class="TableEven">
<td>....</td>
</tr>
</tbody>
E.g. each cell has own class indicating it's column number TableCol0,1,2..N
In each row, needed compare the content of the cells in column 1 and 2 and write the result into colum3.
Managed the following script,
$(document).ready(function() {
var toterr = 0;
$('tbody tr.TableEven,tbody tr.TableOdd').each(function() {
var wanted = $(this).find('.TableCol1' ).html();
var actual = $(this).find('.TableCol2' ).html();
//console.log('wanted='+wanted+'=actual='+actual+'=');
if ( wanted == actual ) {
$(this).find('.TableCol3').text('ok');
} else {
$(this).find('.TableCol3').text('ERROR');
toterr++;
}
});
$('#totalerror').text(toterr);
});
It is probably not optimal, but works.
Now have a bit different scenario: Need compare two cells what are before a cell with a specified content (:CMP:), e.g:
<table>
<thead> ... </thead>
<tbody>
<tr class="TableOdd">
<td class="TableCol0"> x </td>
<td class="TableCol1"> x </td>
<td class="TableCol2"> :CMP: </td>
<td class="TableCol3"> etc </td>
</tr>
<tr class="TableEven">
<td class="TableCol0"> N </td>
<td class="TableCol1"> x </td>
<td class="TableCol2"> y </td>
<td class="TableCol3"> :CMP: </td>
</tr>
</tbody>
For each row, need compare cells what are before :CMP:, and replace the :CMP: with the result. e.g.
in the 1st row need compare the x and x and write ok in the cell .TableCol2
in the 2nd row need compare the x and y and write ERROR in the cell .TableCol3
I haven't idea how to modify the above script.
Can easily get the index of the cell that contains ':CMP:' and use the index to reference the previous cells. Or use traverses like prev() or use eq() once index is found.
$('tbody tr').each(function () {
var $cells = $(this).children(),
$cmp = $cells.filter(':contains(":CMP:")'),
cmpIndex = $cells.index($cmp);
// array of values of previous cells
var values = $.map($cells.slice(cmpIndex - 2, cmpIndex), function (el) {
return $.trim($(el).text());
});
// make sure we have 2 cells with values and compare
var cmpText = values.length === 2 && values[0] === values[1] ? 'OK' : 'ERROR';
$cmp.text(cmpText);
});
DEMO

jQuery: How to re-count and re-name elements

I have a list of table rows and these tr's have numbered classes for some reason (leg-1, leg-2 etc). It is already possible to delete a single tr from within this context.
After deleting a tr I need to rename the remaining tr's.
Example:
I have
<tr class="leg-1"></tr>
<tr class="leg-2"></tr>
<tr class="leg-3"></tr>
Now I delete leg-2. Remaining are:
<tr class="leg-1"></tr>
<tr class="leg-3"></tr>
Now I want to rename the remaining tr's, so that it's back to leg-1 and leg-2.
How can this be done??
Thx for any help!
EDIT:
I forgot to mention that it can have more than one tr with class "leg-1", "leg-2" ... So the right starting example would be
<tr class="leg-1"></tr>
<tr class="leg-1"></tr>
<tr class="leg-2"></tr>
<tr class="leg-3"></tr>
<tr class="leg-3"></tr>
Now when I delete leg-2 , both of the tr's with class="leg-3" have to be renamed to be class="leg-2". ..
Sorry I didn't mention this earlier!!
SEE IT IN ACTION
http://jsfiddle.net/Lynkb22n/2/
I'd suggest, at its most straightforward:
$('tr').each(function(i) {
// looking for a class-name that starts with (follows a
// word-boundary: \b) leg- followed by one or more numbers (\d+)
// followed by another word-boundary:
var matchedClass = this.className.match(/\bleg-\d+\b/);
// if a match exists:
if (matchedClass) {
// set the node's className to the same className after replacing
// the found leg-X class name with the string of 'leg-' plus the
// index of the current element in the collection plus one:
this.className = this.className.replace(matchedClass[0], 'leg-' + (i + 1));
}
});
$('tr').each(function(i) {
var matchedClass = this.className.match(/\bleg-\d+\b/);
// if a match exists:
if (matchedClass) {
this.className = this.className.replace(matchedClass[0], 'leg-' + (i + 1));
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr class="leg-2323523">
<td>1</td>
</tr>
<tr class="leg-2323523">
<td>2</td>
</tr>
<tr class="leg-2323523">
<td>3</td>
</tr>
<tr class="leg-2323523">
<td>4</td>
</tr>
</tbody>
</table>
Using an id is somewhat easier, since we don't need to preserve pre-existing concurrent ids, as we do with classes:
// selects all <tr> elements, sets their `id` property
// using the anonymous function available within prop():
$('tr').prop('id', function (i) {
// i: the index amongst the collection of <tr> elements:
return 'leg-' + (i+1);
});
$('tr').prop('id', function (i) {
return 'leg-' + (i+1);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>1</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
</tbody>
</table>
If the index/row-number is simply to be available to JavaScript, then you could just as easily use the native rowIndex property available to all HTMLTableRowElements:
// selects <tr> elements, binds the 'mouseenter' event-handler:
$('tr').on('mouseenter', function() {
// logs the HTMLTableRowElement rowIndex property
// to the console:
console.log(this.rowIndex);
});
$('tr').on('mouseenter', function() {
console.log(this.rowIndex);
});
td {
border: 1px solid #000;
width: 4em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>1</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
</tbody>
</table>
References:
JavaScript:
HTMLTableRowElement.
JavaScript Regular Expression Guide.
String.prototype.match().
String.prototype.replace().
jQuery:
each().
prop().
Updated
Based on your comment below and your updated question, here is an updated solution.
var removed = $(".leg-2"),
siblings = removed.nextAll(), // affect only next siblings to removed element
pos = ""; // store current number after "leg-"
removed.remove(); // remove element
siblings.each(function (k) {
$(this).removeClass(function (i, key) {
pos = key.split("-")[1]; // update number after "leg-"
return (key.match(/\bleg-\S+/g) || []).join(' ');
}).addClass("leg-" + (pos - 1)); // add "leg-" plus new position
});
See it working here.
You can use .removeClass() with .match() to remove class starts with leg and then add class leg plus tr's index using .addClass().
See it working here.
$("tr").each(function (k) {
k++;
$(this).removeClass(function (i, key) {
return (key.match(/\bleg-\S+/g) || []).join(' ');
}).addClass("leg-" + k);
});
Try this it will re-name the class:
$(document).ready(function(){
$("#click").click(function(){
reorder();
});
});
function reorder(){
$('#myTable > tbody > tr').each(function(index) {
console.log($(this).attr('class','leg-'+(index+1)));//avaoid starting fron 0
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<tr class="leg-1"><td>a1</td></tr>
<tr class="leg-2"><td>a2</td></tr>
<tr class="leg-3"><td>a3</td></tr>
<tr class="leg-7"><td>a4</td></tr><!--after click on button class will become class="leg-4" -->
<tr class="leg-8"><td>a5</td></tr><!--after click on button class will become class="leg-5" -->
</table>
<button id="click">CliCk</button>

Sum associative array key values and group it by key

I have table as follows :
<table>
<thead>
<th>PRODUCT</th>
<th>QUANTITY</th>
<th>AREA</th>
<th>PRICE</th>
<th>TOTAL</th>
<tr>
<td id="name">SWEETS</td>
<td id="qty">10</td>
<td id="area">250</td>
<td id="price">16.50</td>
<td id="total">160.50</td>
</tr>
<tr>
<td id="name"">DRY FOODS</td>
<td id="qty">5</td>
<td id="area">100</td>
<td id="price">10.25</td>
<td id="total">51.25</td>
</tr>
<tr>
<td id="name">FRESH</td>
<td id="qty">20</td>
<td id="area">250</td>
<td id="price">5</td>
<td id="total">100</td>
</tr>
<tr>
<td id="name">MEAT</td>
<td id="qty">10</td>
<td id="area">250</td>
<td id="price">15</td>
<td id="total">150</td>
</tr>
<tr>
<td id="name">FROZEN</td>
<td id="qty">20</td>
<td id="area">300</td>
<td id="price">10</td>
<td id="total">200</td>
</tr>
</table>
So, I want to make an array like {area:total} then grouping array values based on area and sum area values.
Like :
AREA 250 : 410.5
AREA 100 : 51.25
AREA 300 : 200
I tried as follow which I got it array but I don't know how can I grouping the areas ( I used setInterval function because employees can remove or change the area values)
setInterval(function() {
var $row = $(this).closest("tr");
var sasData = [];
$row.each(function(i) {
var sasValue = parseFloat($row.find("#area").val());
var totValue = parseFloat($row.find("#total").val());
sasData.push({sas:sasValue, tot:totValue});
console.log(sasData);
});
function compressedArray(original) {
var compressed = [];
};
}, 1500)
Could you please show me the way how can we handle this issue?
This JSFiddle should solve your problem. I've also fixed your missing thead, your double quote in the DRY FOODS td, and changes id's to classes:
http://jsfiddle.net/Q9nrf/1/
var areas = {};
$("tr").each(function() {
var area = $(this).find("td.area").text();
if (area != "") {
var total = parseFloat($(this).find("td.total").text());
if (!areas.hasOwnProperty(area)) {
areas[area] = 0;
}
areas[area] += total;
}
});
console.log(areas);
You will need to change the id values to some other attribute, say class.
Loop over the rows (use the tbody element to skip the header) and collect values from the elements with the classes you're after. You will need to use an array to store them, as you can't order the properties of an object and each property must have a unique name.
id should be unique. so change <td id="area">250</td> to <td class="area">250</td>
then just call:
o = {};
$("td.area").each(function(){
key = o[$(this).text()];
if (!key) key = 0;
key += parseFloat( $(this).closest("tr").find(".total").text());
});
then you have on object contains key-value [key=area code, value=total]

Categories