How to apply CSS to children of TR based on TD content? - javascript

I'd like to hide a <div> or <td> inside the <tr> based on the content inside that <tr>.
If Stackoverflow is found inside a <tr>, hide .buttons from that <tr>.
This is what I've got so far.
<table class="sites">
<tbody>
<tr>
<td>
<div class="name">Stackoverflow</div>
</td>
<td>
<div class="buttons">
buttons
</div>
</td>
</tr>
<tr>
<td>
<class name="">Stackexchange</class>
</td>
<td>
<div class="buttons">
buttons
</div>
</td>
</tr>
</tbody>
</table>
var t = $(".sites tr .name:contains('Stackoverflow')");
var d = t.parent('tr').children('.buttons');
d.css( "display", "none" );
I've made a fiddle: https://jsfiddle.net/3jk8e3b2/3/

Your traverses are not going to appropriate levels.
parent() is only immediate parent element, children() are only immediate child nodes
In your case parent of .name is a <td> not <tr> and the buttons are not immediate children of <tr> either.
Use closest() or parents() to allow going up more than one level. Use find() to allow going deeper than children()
Try:
var t = $(".sites tr .name:contains('Stackoverflow')");
t.closest('tr').find('.buttons').hide();
DEMO

Related

Extracting data between 2 tags in Javascript

I'm a js newbie. I'm trying to get a table from a really old and outdated webpage that is continually updated (locally) and add it to a different page.
I need to extract table 1 from the following example. Bonus points if you can explain how your solution works.
<html>
<head>
</head>
<div> This is table 1 </div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
<div> This is table 2 </div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
</html>
Thank you!
Typically you would give the target element a unique ID, and target it with document.getElementById('[target]'):
var element_1 = document.getElementById('one');
console.log(element_1);
<div id="one">This is table 1</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
<div id="two">This is table 2</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
If you don't have access to a unique ID in the HTML, but do have an applicable class, you can use document.getElementsByClassName('[target]'), which returns a collection of all elements with the desired class name:
var elements = document.getElementsByClassName('target');
console.log(elements[0]);
console.log(elements[1]);
<div class="target">This is table 1</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
<div class="target">This is table 2</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
If you don't have access to either a unique ID or but have access to jQuery, it's quite simple to tranverse the DOM with .find('div'), which returns an array of all the <div> nodes. From there you can simply specify the desired index:
var element_1 = $(document).find('div')[0];
var element_2 = $(document).find('div')[1];
console.log(element_1);
console.log(element_2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>This is table 1</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
<div>This is table 2</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
Alternatively, with raw JavaScript, it is possibly to target elements with .childNodes (made easier with .firstElementChild). You still need to work from a 'unique' point, and in this case, you'll want to work from body, or even document itself.
Note that in this example, childNodes[5] pertains to the second <div>, as each 'node' is prefaced by a descriptor of that node. As such, childNodes[1] references the first <div>, childNodes[3] references the <table>, and childNodes[5] references the second <div>.
var element_1 = document.body.firstElementChild;
var element_2 = document.body.childNodes[5];
console.log(element_1);
console.log(element_2);
<div>This is table 1</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
<div>This is table 2</div>
<table>
<tr>
<td>
<a>
</a>
</td>
</tr>
</table>
Hope this helps! :)
Another shorter way is using DOMParser.
DOMParser.parseFromString will parse your html code into DOMDocument object. DOMDocument object has body object. And in turn body has children. Your table1 is the 2nd child in that list .
let source = "..." //your html text above
// method 1: use DOMParser
let dom = (new DOMParser()).parseFromString(source, 'text/html')
let table1 = dom.body.children[1]
Try this https://codepen.io/minht/pen/EXbgXY?editors=0010#0

jQuery select all children of closest

I want to add the .red-border class to a #container div and all <td>s in the closest <tr>.
But by using .closest() I only get the elements immediate parent <td>.
Is there a way I can target all children of the closest <tr>?
My code is below.
My current erroneous JS:
$('#myelement').closest('.container, tr td').addClass('red-border');
Obviously, this only targets 1 td. I want to encompass all of them.
My HTML:
<div id="container">
<span class="myelement">element</span>
</div>
<table>
<tr>
<td></td>
<td><span class="myelement">element</span></td>
<td></td>
</tr>
</table>
Edit: normally I might use the .find() function but this wouldnt work with the or operator.
I hope this is what you are expecting. You need to iterate through each tr and add red-border class to its first td with td:first selector as below
$(document).ready(function() {
$('#container').addClass('red-border');
$('tr').each(function(){
$(this).find('td:first').addClass('red-border');
})
})
.red-border{
border:red 2px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<span class="myelement">element</span>
</div>
<table>
<tr>
<td>First row First TD</td>
<td><span class="myelement">element</span>
</td>
<td></td>
</tr>
<tr>
<td>Second row First TD</td>
<td><span class="myelement">element</span>
</td>
<td></td>
</tr>
</table>
According to your structure you can go for this:
$(".myelement").parents("#container").addClass('red-border').siblings("table").find("tr").eq(0).children().addClass('red-border');
target the parent #container using parents(). This will give nothing for the span inside td. Then target its sibling table and the first tr by using eq(0).
why do you want it in a single line? just split it to two, it will be simpler.
$('.myelement').closest('#container').addClass('red-border');
$('.myelement').closest('tr').find('td').addClass('red-border');
by the way, you called #myelement when your tag had a class myelement. It should be called using .myelement. And the container is an id so #container
Call class element using .myelement instead of #myelement
$('.myelement').closest('.container, tr td').css({"color": "red", "border": "2px solid red"});
or
$('.myelement').closest('.container, tr td').addClass('red-border');

Get element by id and change its sibling value

HTML
<table>
<tr id="1">
<td id="a">aa</td>
<td>bb</td>
</tr>
</table>
JavaScript
document.getElementById("1").children[1].innerHTML="newB" // it works as expected.
document.getElementById("a").nextSibling.innerHTML="newB" // it does not work.
How can I change td id="a" sibling value using 2nd approach?
Use nextElementSibling
document.getElementById("a").nextElementSibling.innerHTML = "newB";
nextSibling will select the empty textNode as you can see in the following demo
console.log(document.getElementById("a").nextSibling);
<table>
<tr id="1">
<td id="a">aa</td>
<td>bb</td>
</tr>
</table>
You can see that nextSibling will work as expected when you have no space between the elements. So, it'll not select the empty textNode.
document.getElementById("a").nextSibling.innerHTML = "newB";
<table>
<tr id="1">
<td id="a">aa</td><td>bb</td> <!-- No space, it works! -->
</tr>
</table>
It is because, the next sibling of the td could be a text node, you need the next element sibling.
You can use the nextElementSibling property
document.getElementById("a").nextElementSibling.innerHTML = "newB";
<table>
<tr id="1">
<td id="a">aa</td>
<td>bb</td>
</tr>
</table>
Note: supported in IE 9+

getElementsByTagName("table") - getting td on curious way

I have this simple example
<table border="1px">
<tr>
<td> </td>
<td> <input type="button" value="Click" onclick="insertText()"/> </td>
</tr>
</table>
I wanted to get the first td element of the (first) tr element, I tried:
var td = document.getElementsByTagName("table")[0].children[0].children[0];
Because it's:
var td = document.getElementsByTagName("table")[0] for the table element itself
children[0] for the tr element
and children[0] again for the first td element
That's what I thought, but apparently this returns me the tr element and only adding another .children[0]got me the td element.
var td = document.getElementsByTagName("table")[0].children[0].children[0].children[0];
Why is that, or what have I missed here?
That's because you're forgetting about the <tbody> element, which is automatically inserted into the DOM.
What your table really looks like:
<table border="1px">
<tbody>
<tr>
<td> </td>
<td> <input type="button" value="Click" onclick="insertText()"/> </td>
</tr>
</tbody>
</table>
Hence why you needed to dig down through three levels of children to target the <td> element you wanted.
Side note: If you'd like to know more about why the <tbody> element is automatically injected into <table> elements if undeclared, see this question and its answers.

fetch HTML Element object using javascript, mootools

Please check my HTML below:
<table cellpadding="0" cellpadding="0" border="0">
<tr>
<td>
<div class="toogler">Demo1</div>
</td>
</tr>
<tr>
<td>
<div class="element">Demo1 Content</div>
</td>
</tr>
<tr>
<td>
<div class="toogler">Demo1</div>
</td>
</tr>
<tr>
<td>
<div class="element">Demo1 Content</div>
</td>
</tr>
<tr>
<td>
<div class="toogler">Demo2</div>
</td>
</tr>
<tr>
<td>
<div class="element">Demo2 Content</div>
</td>
</tr>
<tr>
<td>
<div class="toogler">Demo3</div>
</td>
</tr>
<tr>
<td>
<div class="element">Demo3 Content</div>
</td>
</tr>
<tr>
<td>
<div class="toogler">Demo4</div>
</td>
</tr>
<tr>
<td>
<div class="element">Demo4 Content</div>
</td>
</tr>
</table>
Here is my JS Code:
<script type="text/javascript" language="javascript">
$$('.toogler').each(function(e){
alert(e);
// this will alert all the toogler div object
});
</script>
my problem is that how can i fetch the object of the next div with class element
if i have object of the first toogler then how can i get the object of the next first div which class 'element'
I don't want to give the ids to the elements
if you can't alter the html output and refactor as suggested by oskar (best case), this works:
e.getParent().getParent().getNext().getFirst().getFirst() - it will return you the next div but it's slow.
unfortunately, tables break .getNext("div.element") as it's not a sibling.
another way that works is this (if their lengths match) - it will be MUCH faster if the reference is put in element storage as a 1-off:
var tooglers = $$("div.toogler"), elements = $$("div.element");
tooglers.each(function(el, i) {
console.log(elements[i]);
el.store("contentEl", elements[i]);
});
i don't like either solution though, not maintainable / scalable enough.
You shall have to iterate through and check for the class one by one.
The easiest way of assigning a toggler to the toggled element:
$$('.toogler').each(function(e, index){
console.log($$('.element')[index]);
});
Here's a working example: http://jsfiddle.net/oskar/aTaBB
Also, get rid of the table.
Try using Element.getNext([match]).
<script type="text/javascript" language="javascript">
$$('.toogler').each(function(e){
alert(e);
// Get the next sibling with class element.
var nextElement = e.getNext('.element');
alert(nextElement);
});
</script>

Categories