Selector to find closest DOM elements with attr greater than given - javascript

I have table created after AJAX which looks like that:
<tr data-level=2>
<tr data-level=3>
<tr data-level=4>
..etc.
<tr data-level=2>
<tr data-level=3>
<tr data-level=4>
..etc.
of course there may be many cells on any data-level.
I want to hide all rows greater than clicked level to row which level is smaller than clicked one. So - after I click data-level=4 I want to hide all elements with data-level > 4 till I get to row with data-level < 4.

You can use .filter()
Reduce the set of matched elements to those that match the selector or pass the function's test.
Example code
$('tr[data-level]').on('click', function(){
var level = $(this).data('level'); //Get level of clicked element
$('tr[data-level]').filter(function(){
return $(this).data('level') > level;
}).hide();
})
DEMO
Use
$('tr[data-level]').on('click', function () {
var level = $(this).data('level'); //Get level of clicked element
var arr = [];
$(this).nextAll('tr[data-level]').each(function () {
if ($(this).data('level') > level) {
arr.push($(this));
} else if ($(this).data('level') == level) {
return false;
}
});
$.each(arr, function(){
$(this).hide()
});
})
DEMO

Here's another solution
Edit: Sorry, the question wasn't clear, this solution hides all elements with greater value.
HTML
<table id="resultTable">
<tr data-level=2><td>2</td></tr>
<tr data-level=3><td>3</td></tr>
<tr data-level=4><td>4</td></tr>
<tr data-level=2><td>2</td></tr>
<tr data-level=3><td>3</td></tr>
<tr data-level=4><td>4</td></tr>
</table>
JS
$(document).ready(function () {
$("tr","#resultTable").on("click",function() {
var el = $(this);
var clickedValue = parseInt(el.attr("data-level"),10);
hideLargerThan(clickedValue);
});
var hideLargerThan = function(value) {
$("tr","#resultTable").each(function() {
var el = $(this);
var myValue = parseInt(el.attr("data-level"),10);
if(myValue > value)
el.hide();
});
};
});
http://jsfiddle.net/JKurcik/c8Q5Z/2/
you can derive from this code easily.

Related

Delete rows from table recursively using JQ

I want to write a recursive function that will delete rows from my table.
I have the number of rows to keep and after that number i want to remove all rows.
for example:
I have the number 5 so the first 5 rows need to stay and the rest need to go. (using the row id)
code:
<table id="table">
<tr id="tr1"/>
<tr id="tr2"/>
<tr id="tr3"/>
<tr id="tr4"/>
<tr id="tr5"/>
<tr id="tr6"/>
<tr id="tr7"/>
<tr id="tr8"/>
</table>
I dont know how much rows i will have, thats why i think i need a recursive solution.
You can use several different jQuery filter approaches:
var numRows=5;
$('#table tr').slice(numRows).remove();
OR
$('#table tr:gt(' + (numRows-1) + ')').remove();
DEMO
References:
slice() docs
:gt() selector docs
You can use this
$(document).ready(function(){
var deleteAfter = 5
$.each($("#table tr"),function(key,value){
//do your conditional here
if(key > deleteAfter-1){
value.remove();
}
});
alert("now the table row is "+$("#table tr").length);
});
This is working jsfiddle
I'm sorry if u want to using id as the input please use this instead
$(document).ready(function () {
//define the id first
var deleteAfter = $("#tr5");
var elementNo;
$.each($("#table tr"), function (key, value) {
if (this.id == deleteAfter.attr("id")){
elementNo = key;
}
});
$.each($("#table tr"), function (key, value) {
//do your conditional here
if (key > elementNo) {
value.remove();
}
});
alert("now the table row is " + $("#table tr").length);
});
And i updated the jsfiddle
you can use :gt() selector, it selects all the elements greater than index and then you can remove it.
$(document).ready(function () {
var index = 4; // set index 4, so want to remove 5 elements( 0 to 4)
$('#table tr:gt('+index+')').remove();
});

Script returns element that not exists on page

I have this function, that returns me path to el. However sometimes this function adds element that not exists on page. In this case:
<table>
<tr><td></td><tr>
</table>
path to td will look like table > tbody > tr > td.
Whats the problem with this function?
function getDomPath(el) {
element = el;
if (!(el instanceof Element)) return;
var path = [];
while (el.nodeType === Node.ELEMENT_NODE && el.id != "jobs") {
var selector = el.nodeName.toLowerCase();
if (el.id) {
selector += '#' + el.id;
}
else if(el.className){
console.log(el.className);
selector += '.' + el.className;
}
else {
var sib = el, nth = 1, count = 1;
while (sib.nodeType === Node.ELEMENT_NODE && (sib = sib.previousSibling) && nth++){
console.log(Node.ELEMENT_NODE)
console.log(el.previousSibling);
console.log(el);
count += $(el).prevAll().size();
};
selector += ":nth-child("+count+")";
}
path.unshift(selector);
el = el.parentNode;
}
return path.join(" > ");
};
If the problem is the tbody element, you need to know that it's not your function that adds it but the browser itself.
Look at your page using Firebug or the Web Developer tools in chrome.
Take a look at this SO answer.
There is no problem with the function, it correctly uses all the elements that does exist.
A table element always has a tbody element if there are any rows for it. The browser adds the tbody element even if you don't have any tag for it in the markup.
The browser will create complete elements, even if your markup is incomplete or if it has left out optional tags. For example, the browser will create two rows in your table, because you used <td> instead of </td> when you tried to end the first row. It will implicitly end the first row, start a new row, and implicitly end that too. The elements in your table will end up just as if you wrote your markup as:
<table>
<tbody>
<tr>
<td></td>
</tr>
<tr>
</tr>
</tbody>
</table>

Styling table according to its contents

I have the following table: http://jsfiddle.net/UfhVc/1/
I am trying to:
Get the same style on all rows who have the same ID
Highlight the differences in each on the rows with the same ID.
But right now I can't seem to figure out the logic needed for step 1). It's ok to use jQuery, I just found it easier to use plain js.
Also, I get a warning in this part of the code:
table.rows[i+1].cells[0].innerHTML
Like this?
var newColor = "#F1D0F2";
var diffColor = "#CECECE";
$('#tbl tr:gt(0)').each(function () { //Loop through the trs leaving out the header
var txt = $(this).find('td:eq(0)').text(); //get the text of the id column
var $this = $(this);
var matchingRows = $('#tbl tr').not(this).filter(function () { //get the matching rows whose id colum value is same
return $(this).find('td:eq(0)').text() == txt;
}).css('background-color', newColor); //apply css for match
matchingRows.find('td').css('background-color', function (i) { //apply background color
if ($this.find('td:eq(' + i + ')').text() != this.innerHTML) return diffColor; // to the tds of matching rows but column valud differ.
});
});
Fiddle
References:
:gt()
filter()
css()
:eq()
Edit
Based on your comment here is the update:
var allColors = ["#333333","#990099", "#1295A6", "#FFFF99"]; //Set up the colors in to an array
var diffColor = "#CECECE";
$('#tbl tr:gt(0)').each(function () {
var txt = $(this).find('td:eq(0)').text();
var $this = $(this);
if($this.is('.transformed')) //check for class transformed is present if so this has already been processed skip it.
return;
//Get the matching rows whose id column value is same
var matchingRows = $('#tbl tr').filter(function () {
return $(this).find('td:eq(0)').text() == txt;
}).css('background-color', allColors.shift()).addClass('transformed'); //Set the color and add a class to avoid latter processing
matchingRows.find('td').css('background-color', function (i) { //apply background color
var $parTd = $this.find('td:eq(' + $(this).index() + ')');
if ($.trim($parTd.text()) != $.trim(this.innerHTML)) // to the tds of matching rows but column value differ.
{
$parTd.css('background-color', diffColor);
return diffColor;
}
});
});
Fiddle
For step one:
There are a few ways you can do it, I would probably attach a class to all table cells which are of a certain type, so you can easily select them all at once for editing.
<table>
<tr>
<td class="id-cell"></td>
</tr>
</table>
Then you could simply query it with CSS like:
.id-cell {
background-color:red;
}
But you can also just use more jQuery / JavaScript to find those table cells you're looking for anyways. This fiddle uses jQuery to find all the cells which are in the "id" column, and paint the background red.
http://jsfiddle.net/8QL22/
Another way of doing it:
$("table tr:not(:first-child) td:first-child").each(function(index) {
var thisId = $(this);
$("table tr:not(:first-child) td:first-child").each(function(_index) {
if (index != _index && thisId.text() == $(this).text())
{
thisId.parent("tr").css("backgroundColor", "red");
$(this).css("backgroundColor", "red");
$(this).siblings("td").each(function(sindex) {
var other = $(thisId.siblings()[sindex]);
if (other.text() != $(this).text())
other.css("backgroundColor", "yellow");
});
}
});
});
http://jsfiddle.net/w4mvp/

Find out next <td> id by clicking on a <td>

I have a some td's like this
<td id="first">first</td>
<td id="second">second</td>
<td id="third">third</td>
<td id="fourth">fourth</td>
By clicking on one td I want to find out the id's of its next two tds.
When I click on 'first' I need to get 'second' and 'third' values.
How can I achieve this using JQuery or Javascript?
jQuery
This will alert 'undefined' if you click on the last cell.
jsFiddle
$('td').click(function () {
alert($(this).next().attr('id'));
});
JavaScript
This method is a bit hacky because .nextSibling returns a text node object (not a node) which doesn't contain an id property. It gets a list of siblings from its parentNode, we then iterate over them until we get a match, the next index is the next sibling.
jsFiddle
var tds = document.getElementsByTagName('td');
for (var i = 0; i < tds.length; i++) {
tds[i].onclick = function () {
var siblings = this.parentNode.children;
var i = 0;
while (siblings[i] != this) { i++; }
if (i < siblings.length)
alert(siblings[i + 1].id);
};
}
JQuery has sibling selectors and functions that you can use for this:
http://api.jquery.com/next-siblings-selector/
http://api.jquery.com/siblings/
$('td').click(function(e) {
e.preventDefault();
var id = $(this).next().attr('id');
if (id) alert(id);
});
You can use next() twice. You will have to check if next has brought an element or not as for second last you wont get second and for last you wont get first and second next element.
Live Demo
$('td').click(function () {
first = $(this).next('td');
second = first.next('td');
if (first.length) alert(first.text() );
else alert("No next");
if (second.length) alert(second.text());
else alert("No next");
});

jQuery select multiple table columns by index

I've seen certain questions knocking around which are similar, but not exactly the same and I'm stumped with this one.
What I'm trying to do is create a widget that takes a table, then goes through the table's td elements and sets a cursor:pointer (for now) to them, but only the ones that I allow.
This is how my code looks:
selectableGrid: function (options) {
var indexes = options.columns // this is [1,2];
return this.each(function () {
// Make the td's in the grid selectable
$(this).find("tbody td").attr("style", "cursor:pointer");
});
}
The end result I'm wanting to achieve?
<tbody>
<td>hello</td> // index 0
<td style="cursor:pointer">hello</td> //index 1
<td style="cursor:pointer">hello</td> // index 2
</tbody>
Bear in mind that I could be sending through 1,3 in my array list of columns, so lt and gt don't work for my scenario (as far as I've tried anyway).
EDIT:
In order to achieve this I went with the following code:
$(this).find("tr").each(function () {
$(this).find("td").each(function (i, el) {
if (indexes.indexOf(i) > -1) {
$(this).css("cursor", "pointer");
};
});
});
For some reason "tbody td" wouldn't work for a singular loop as it only referenced the first iteration of the tag.
Thank you once again Stack Overflow.
Loop through the td elements, and check that their index with respect to their siblings is an index contained in the options.columns array.
selectableGrid: function (options) {
var indexes = options.columns // this is [1,2];
return this.each(function () {
$(this).find("tbody td").each(function(){
var columnIndex = $(this).index();
if($.inArray(columnIndex, options.columns) != -1){
$(this).css("cursor", "pointer");
}
});
});
}
.each takes an index parameter you can reference in your code.....:
var indexes = options.columns;
this.find("tbody td").each(function(i, el) {
if ($.inArray(i,indexes)>-1) { // good idea, ggreiner
$(this).css("cursor","pointer");
};
});
loop through your indexes and use the http://api.jquery.com/eq/ to find the particular td.

Categories

Resources