Comparing "this" object with Object in DOM Array - javascript

This question is the root cause for my question.
Hide all next tr td until next tr th
As already two answers being posted , I thought of trying something different
Javascript:
$(function(){
var thList = $('td');
$('td').click(function(){
for( i =0; i < thList.length;i++){
// What to do here
}
});
});
HTML:
<table border="2">
<tr>
<td> 1 </td>
<td> 2 </td>
<td> 3 </td>
</tr>
<table>
What am doing here is
Assigning click event to <TH> element. And on load , am getting all the <TH> in the DOM in an Array.
Now, my logic is. Iterate the for loop and if the clicked TH is not the one in the for loop, then hide it.
What i tried is
if ( thList[i] != $(this)) { thList[i].style.display = 'none' }
But this does not seem to be working. what code I need to put there to compare the object

Besides the fact, that you example markup does not contain any th-elements, you could try the following:
$('td').click(function(){
var $tdList = $('td').not(this); // <- get all th's and exlude the clicked element
$tdList.each(function(){this.style.display = 'none'; });
});
or even better, use jQuery, you don't need a each wrapper then:
$tdList.hide();
Since jQuery saves you a lot of work, try to use it whenever you can - use the each() instead of for-loops and use .css() (or even more dedicated methods like .hide()) instead of the native .style - this should shorten your code significantly.

You can use:
thList.click(function() {
thList.not(this).css("display", "none");
});
For performance reason you could delegate the event instead:
$("#yourtable").on("click", "th", function(event) {
thList.not(event.target).css("display", "none");
});
I didn't test it, but should works.
However I'm curious about the UI: if the TH are hidden in this way, they can't be displayed anymore after the first click of any of them.

1-You $(this) is diferent of this once is a jquery object
2-You dont have a TH element here is the code similar that you want but whit td's
$(function(){
var tdList = $('td');
$('td').click(function(){
tdList.hide();
$(this).show();
//OR tdList.not(this).hide();
});
});

When you are accessing the items in a jQuery object, you get them as DOM elements, not as new jQuery objects. So, you should compare it to the element reference directly, not wrap the element reference in a jQuery object:
for (i = 0; i < thList.length; i++) {
if ( thList[i] != this) { thList[i].style.display = 'none' }
}
You can also use the not method to get a collection without the current element:
thList.not(this).each(function(){ this.style.display = 'none'; });
Of course, using the css method it becomes even simpler:
thList.not(this).css('display', 'none');
Word of caution: The cells in tables are not really separate elements that you can just hide without affecting the other cells in the table. The table can show unexpected behaviour when you hide cells in it.

Related

Removing <tr> from table without :contains()

Okay,
This may sound easier than it is, I need to use either Javascript or jQuery to remove a <tr> from a table, I don't know what row this <tr> will be, nor do i know which <tr> I will be removing and the only way I can find out which <tr> to remove is from the text inside the child's <td>.
I cannot use the :contains() selector from jQuery as I'm using ajax to get the elements and it just seems broken.
$("td:contains(var)").parent().remove();
just gives me a DOMexception error.
Is there a way I can loop through all the <td>'s in a table and check the text contents of them?
This will check the text of each one:
$('tr').each(function() {
var $tds = $(this).find('td');
$tds.each(function() {
if ($(this).text() === "some text") {
$(this).parent().remove()
}
});
})

JQuery Table Toggle Row issue

I have table which is being dynamically created.
I would like to try not to have any more attributes in the table (like an ID field).
It is a multilevel table where all the TableRows should be expandable and collapse on click in any of the TD in each row.
$('.fylke_click').click(function () {
$(this).parent().nextUntil('.fylke').slideToggle(0);
$('.sted').hide();
});
$('.kom_click').click(function () {
$(this).parent().nextUntil('.kommune').slideToggle(0);
});
See this simplified fiddle:
http://jsfiddle.net/T2Lwn/
So it's basically 3 levels and it is a lot of problems here.
One obvious one is when you are on the second level, which is called "kommune" and if you click on the last TR it removes the "fylke" underneath. As you can see if you click on "MIDTRE GAULDAL"
This is probably because I use .Parent() and I need some sort of if check if I am on the last row?
Is it also other problems with this code? Can I specify the click method class="fylke_click" and class="kom_click" on a more general level?
For example for all <tr class="fylke"> each TD class will have class="fylke_click" and same for kommunne?
If I understand your issue correctly this may help:
Demo Fiddle:
Since you said you're going to be dynamically creating this content, I would recommend delegating off of the main table instead of making a click handler for each row. Also, since all of the stuff you want to show / hide are siblings and not nested, things get a bit tricky. You'll need to be specific with your .nextUntil() by passing a filter, and I found a :not() on the filter was necessary.
Again, since these are all siblings, it's not as easy as hiding the children of the header row, so I set up an "open" class to check if the header was open or not, and hid / showed stuff depending on if it was already open.
JS:
$('.kommune').hide();
$('.sted').hide();
$('.table').on('click', 'tr', function(){
$this = $(this);
if( $this.hasClass('fylke') ){
if ( $this.hasClass('open') ) {
$this.toggleClass('open').nextUntil('.fylke', 'tr').hide();
}
else {
$this.toggleClass('open').nextUntil('.fylke', 'tr:not(.sted)').toggle();
}
}
else if ( $this.hasClass('kommune') ){
$this.nextUntil('.kommune', 'tr:not(.fylke)').toggle();
}
});

How to use each() for all td in tr, except for the last one?

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.

Getting total length of an index in each()

I want to get an unknown (changing) # of rows from a table, between the 1st cell and the last 3. I'm using jQuery's each and don't know why $(this).length doesn't give the total length of the index.
jQuery:
$("#parent table:first tr").each(function(i){
var goodlng = $(this).parent().children("tr").length -1; //this works
var badlng = $(this).length -1; //this doesn't! (always == -1)
});
Is the goodlng good practice? it seems like a hack to have to go to parent and then back to children.
Here is a jsfiddle (have console.log()) open.
Example HTML:
<div id="parent">
<table>
<tr>
<td>unwanted 1</td>
</tr>
<tr>
<td>wanted!</td>
</tr>
<tr>
<td>unwanted2</td>
</tr>
</table>
</div>
tl;dr: Why doesn't $(this).length == $(this).parent().children("tr").length inside of an each function. and is there another better way of doing this.
Your question says "cells", but it seems like you're trying to get the number of rows.
If you really want it inside the .each(), you could use the siblings()[docs] method and the andSelf()[docs] method.
$(this).siblings().andSelf().length
But if the rows aren't changing, why do it repetitively?
Or if they are changing, I'd just use the native rows property on the table to get the length.
var table = $("#parent table:first");
table.find('tr').each(function() {
var len = table[0].rows.length;
});
Actually, this $(this).parent().children("tr").length is the correct way of handling things. this, in the context above is a reference to the tr node itself. tr.length = the length of the tr. tr.parent().children("tr"), on the other hand is a list of the node's siblings, so tr.parent().children("tr").length is the number of siblings.
This is the context of EACH element, not all of them. Therefore, this is only ONE tr at a time. That is why the length does not have all the elements.
The each() function is unaware of the collection of elements that it is working on. It is dealing with a single element at all times. Thats why when you go to the parent and ask for all children you get the right answer.
$(this)
simply refers to the current tr element that you are dealing with, not a collection of them.

remove div without an id tag

I need a solution to remove a div without an ID tag in JavaScript only. The div looks like this <div align="center">.
Here is the full structure.
<tr id="-1">
<td class="stxt">
<div align="center">
</div>
</td>
</tr>
You need to work out how to get a reference to it, once you've done that, you can remove it using:
div.parentNode.removeChild(div);
Of course the align attribute has been deprecated, but anyway, you can find the divs with align="center" using:
var divs = document.getElementsByTagName('div');
var div;
var i = divs.length;
while (i--) {
div = divs[i];
if (div.getAttribute('align') == 'center') {
div.parentNode.removeChild(div);
}
}
Which will remove every div in the document that has align="center".
Note that the object returned by getElementsByTagName is a NodeList. If you iterate over it from 0 and remove nodes, they are removed from the live list so you will skip the node following the one you remove and you will attempt to access no existant nodes at the end. Going over the list backwards avoids these pitfalls. An alternative is to turn the NodeList into an array, but that's somewhat inefficient.
Edit
Since you edited the question, here's an update answer.
You can get a reference to the TR using getElementById:
var root = document.getElementById('-1');
Now you can go down the DOM:
var cell = root.cells[0]; // First cell in the row
var div = cell.getElementsByTagName('div')[0]; // first div
cell.removeChild(div);
Which is specific to the structure you've posted.
If you can just remove the content, you can use:
var all = document.getElementsByTagName("div");
for(i=0; i < all.length; i++) {
all[i].innerHTML = ""
}
See http://jsfiddle.net/7KVkC/
You need some way to make this div tag unique. There is another javascipt function called getElementsByTagName that you can use to get an array of all of the div tags. You can then use the DOM to check whether that div tag has the property of align="center".

Categories

Resources