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>
Related
I have an outer DIV containing the content I want to block. However only the inner TD has the attributes as the qualifier.
I've already got the code (From an SO user) and use TamperMonkey to implement it and it works like a charm. However it removes too little and keeps the parent DIV. I know too little of JavaScript to affect the outter DIV.
<DIV>
<Table></TABLE>
<Table>
<td attribute="desiredTarget"></td>
</TABLE>
<Table></TABLE>
</DIV>
Expected: DIV should not display based on TD content
Results: DIV still displays
Use jQuery it will better than PURE JS
$('td[attribute="X"]')
.parent() //TO TR
.parent() //TO TBODY
.parent() //TO TABLE
.parent() //TO DIV
.css("background-color", "red"); ///Your command
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
1
<table border="1">
<tr>
<td>Unnesscessary</td>
</tr>
</table>
2
<table border="1">
<tr>
<td attribute="X">xxx</td>
<td>Unnesscessary</td>
</tr>
<tr>
<td>Unnesscessary</td>
</tr>
</table>
3
<table border="1">
<tr>
<td>Unnesscessary</td>
</tr>
<tr>
<td>Unnesscessary</td>
</tr>
</table>
</div>
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
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+
I'm currently working on a set of tables and i've gotten them to expand and contract at the click of a button. I'm having problems however to create a button that expands all the tables at the same time. Please see my code.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head> <!--this first part is easy to implement-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(".toggler").click(function(e){
e.preventDefault();
$('.vis'+$(this).attr('vistoggle')).toggle();
});
});
</script>
</head>
<body>
Expand all <!--vistoggle needs to have values 1 and 2 in it-->
<table>
<tr>
<td>safeaef</td>
<td>asdfaef</td>
<td>asfead</td>
<td>Expand</td>
</tr>
<tr class="vis1" style="display:none">
<td>asdfae</td>
<td>zxcvry</td>
<td>rteyertr</td>
<td></td>
</tr>
<tr class='vis1' style='display:none'>
<td>tsersg</td>
<td>sdgfs</td>
<td>wregssdf</td>
<td></td>
</tr>
<tr class="vis1" style="display:none">
<td>sdfgrs</td>
<td>sgdfgsr</td>
<td>Cewret</td>
<td></td>
</tr>
</table>
<table>
<tr>
<td>cfasdfas</td>
<td>1adfaed</td>
<td>asdfasdfea</td>
<td>Expand</td>
</tr>
<tr class="vis2" style="display:none">
<td>asdfaefas</td>
<td>1asdf</td>
<td>Cisdfae</td>
<td>22fasdew</td>
</tr>
<tr class="vis2" style="display:none">
<td>asdfaef</td>
<td>1sefa0</td>
<td>Ciasdf 2</td>
<td></td>
</tr>
</table>
</body>
</html>
You could try building a selector like this:
$('tr[class^="vis"]')
it would select all elements, which class attributes begins with 'vis'.
But from what I see you want the first row to always stay visible, so I would propose to simply separate the table header and it's body like this:
<table>
<thead><tr>...</tr></thead>
<tbody id="table-one" class="vis">
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>
<table>
<thead><tr>...</tr></thead>
<tbody id="table-two" class="vis">
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>
and then you could use a simple:
$('tbody.vis').toggle();
to toggle all the tables, and for toggle`ing just one of them you can use:
$('tbody#tbody-one').toggle();
which is probably much better idea for performance reasons (ID is found much faster than classes).
The ID attribute of TBODY can be stored just like you store it right now (in a button's attribute).
Fiddle example:
http://jsfiddle.net/SL4UZ/3/
Edit
To make your HTML valid, you should use data-attributes or bind your events using javascript instead of simply adding customs attributes inside your button tags. For example:
<button data-toggle-id="tbody-one">Toggle</button>
I updated my fiddle.
You can check the attr that needs to be toggled and if it matches all open 1 and 2, this works if your table is not dynamic
Expand all
$(document).ready(function(){
$(".toggler").click(function(e){
e.preventDefault();
if($(this).attr('vistoggle') == "all"){
$('.vis1').toggle();
$('.vis2').toggle();
}else{
$('.vis'+$(this).attr('vistoggle')).toggle();
}
});
});
Fiddle : http://jsfiddle.net/6hpbq/
Separate your classes eg vis1 becomes vis one (two classes) Then do a conditional check on the value of the data attribute. If its set to all, toggle all elements with the class vis, else toggle the specific ones:
<script>
$(document).ready(function(){
$(".toggler").click(function(e){
e.preventDefault();
var vistog = $(this).attr('vistoggle');
if(vistog == 'all'){
$('.vis').toggle();
}else{
$('.vis.' + vistog).toggle();
}
});
});
</script>
</head>
<body>
Expand all <!--vistoggle set to all -->
<table>
<tr>
<td>safeaef</td>
<td>asdfaef</td>
<td>asfead</td>
<td>Expand</td>
</tr>
<tr class="vis one" style="display:none">
<td>asdfae</td>
<td>zxcvry</td>
<td>rteyertr</td>
<td></td>
</tr>
<tr class='vis one' style='display:none'>
<td>tsersg</td>
<td>sdgfs</td>
<td>wregssdf</td>
<td></td>
</tr>
<tr class="vis one" style="display:none">
<td>sdfgrs</td>
<td>sgdfgsr</td>
<td>Cewret</td>
<td></td>
</tr>
</table>
<table>
<tr>
<td>cfasdfas</td>
<td>1adfaed</td>
<td>asdfasdfea</td>
<td>Expand</td>
</tr>
<tr class="vis two" style="display:none">
<td>asdfaefas</td>
<td>1asdf</td>
<td>Cisdfae</td>
<td>22fasdew</td>
</tr>
<tr class="vis two" style="display:none">
<td>asdfaef</td>
<td>1sefa0</td>
<td>Ciasdf 2</td>
<td></td>
</tr>
</table>
</body>
</html>
I am trying to select all the elements with class "name" and when I click on one radio button it flips the last and first name around, so: Hanks, Tom || Tom, Hanks. Here is what I have so far:
HTML:
<h1>Address Book</h1>
<p>Show Names as:</p>
<input name="lastfirst" value="last" type="radio">First, Last
<input name="firstfirst" value="first" type="radio">Last, First
<div>
<table <thead="">
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</tbody>
<tbody>
<tr>
<td>9001</td>
<td class="name">Tom Hanks,</td>
<td>tomhanks#moviestars.com</td>
</tr>
<tr>
<td>9002</td>
<td class="name">Bruce Willis,</td>
<td>brucewillis#moviestars.com</td>
</tr>
<tr>
<td>9003</td>
<td class="name">Jim Carrey,</td>
<td>jimcarrey#moviestars.com</td>
</tr>
<tr>
<td>9004</td>
<td class="name">Tom Cruise,</td>
<td>tomcruise#moviestars.com</td>
</tr>
<script>
</script>
</tbody>
</table>
</div>
<meta charset="utf-8">
<title>Test</title>
<link rel="stylesheet" href="./webassets/style.css" media="screen" type="text/css">
<h1>Company Staff List</h1>
<div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>9001</td>
<td>Tom Hanks,</td>
</tr>
<tr>
<td>9002</td>
<td>Bruce Willis,</td>
</tr>
<tr>
<td>9003</td>
<td>Jim Carrey,</td>
</tr>
<tr>
<td>9004</td>
<td>Tom Cruise,</td>
</tr>
</tbody>
</table>
</div>
Here is my jquery. I used a filler of .hide() because other than selecting the elements I am not sure how to do this. Just some hints would help. I am not sure how to separate the first and last name. If I could figure out how to simply swap the first and last name into a variable I could definitely figure out the rest.
$(document).ready(function(){
$("input[name='lastfirst']").click(function(){
$(".name").hide();
});
$("input[name='firstfirst']").click(function(){
$(".name").hide();
});
});
DEMO
$(document).ready(function () {
$("input[name='change_last_first']:nth(0)").prop('checked', true)
$("input[name='change_last_first']").change(function () {
$(".name").text(function (_, old_txt) {
var new_txt = old_txt.split(' ').reverse();
return new_txt.toString().replace(',,', ' ') + ',';
});
});
});
HTML changed
<input name="change_last_first" value="last" type="radio">First, Last
<input name="change_last_first" value="first" type="radio">Last, First
References
.text()
.change()
.replace()
.split()
.toString()
.reverse()
Split it first using.
var splStr = input.split(/[ ,]+/);
now concatinate using input=splStr[1]+splStr[0];
you can separate the text using split function input.split(/[ ,]+/); along with a regular expression to separate each "word" within the input.
you could then assign each value to a new variable
ex:
var a = array[0], b = array[1]
From there you could concatenate the array values into any order you choose.