I'm trying to implement an algorithm in javascript/jquery (recursive) which walks through the DOM and returns me the index of every HTML element, including parents,siblings and children. and then draws a tree of the DOM.
I need to index every element by adding an index attr to the element with the index as a string. for example:
<html>
<...>
<body>
<div index="1">
<div index="1.1">
<h2 index = "1.1.1">some text1</h2>
<h2 index = "1.1.2">some text</h2>
</div>
</div>
<div index="2">
<table index="2.1">
<tr index="2.1.1">
<td index="2.1.1.1">some cell</td>
<td> index = "2.1.1.2">some cell</td>
</tr>
<tr index="2.1.2">
<td index="2.1.2.1">some cell</td>
</tr>
</table>
</div>
<div index="3">
<h1 index="3.1">some text</h1>
</div>
</body>
</html>
what is the best way to achieve that? any ideas?
with a simple iteration you can achieve this
function loop(el, isChild){
for(var i=0; i<el.children.length;i++){
var child = el.children[i];
child.index = (isChild?(el.index + '.'):'') + (i+1);
loop(child,false);
}
}
loop(document.body);
Related
i have two functions here first one is working (but i think it is not effective approach to do this) , but second one is not giving all values in list it push only last tagname value, but i want all values in list . So is there any effective solution of this approach.
<div class="container">
<div id="main">
<label class="ac_triggers">
<label style="color: yellow;">note</label><br><br>
<table style="width: 100%">
<tr>
<td id='values1'>{{Sum_energy|floatformat:2}}</td>
<td id='values2'>{{std_energy|floatformat:1}}</td>
</tr><tr>
<td id='values4'>{{Sum_cab|floatformat:2}}</td>
<td id='values5'>{{std_cab}}</td>
</tr><tr>
<td id='values'>{{Sum_nic|floatformat:2}}</td>
<td id='values'>{{std_nic}}</td>
</tr>
</table><br><br>
</label>
<button id="submit">Submit</button>
</div>
</div>
<script>
function save(){
// var new_data = $('#values').text();
var valuesList = []
for (var i = 1; i < 6; i++) {
valuesList.push($('#values'+i).text());
}
console.log(valuesList)
}
// function save(){
// var listValue =[];
// var links = $('#values').text();
// for (var i = 0; i < links.length; i++) {
// var link = links[i];
// listValue.push(link) ;
// }
// console.log(listValue);
// }
</script>
If you want to loop the elements use class. Because id should be unique. In your second method you are targeting only the last element and that also having wrong usage of id. As per my understanding you want to loop all your td element and get the text and add it into one array.
I have given the sample how you can use the class and get the text element on it.
function save(){
var listValue =[];
$('.values').each(function(e){
listValue.push($(this).text()) ;
});
console.log(listValue);
}
save();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="container">
<div id="main">
<label class="ac_triggers">
<label style="color: yellow;">note</label><br><br>
<table style="width: 100%">
<tr>
<td class='values'>Test1</td>
<td class='values'>100</td>
</tr><tr>
<td class='values'>Test2</td>
<td class='values'>200</td>
</tr><tr>
<td class='values'>Test3</td>
<td class='values'>300</td>
</tr>
</table><br><br>
</label>
<button id="submit">Submit</button>
</div>
</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
I have a html page that has, 3 div with class name as "xyz", Now, On page load ($(document).ready(function()) for each occurance of the div "xyz" I want to introduce an inner html/child element as "<div class="childxyz###"></div>" where ### represents the position number of the occurrence of parent class xyz . For instance, the first occurrence of parent class xyz the child class name would be "childxyz1", second occurrence it would be childxyz2 and so on.
Can someone suggest a simple solution for this?
Initial page
<div class="xyz">
//appending inner html and pass value 1 as xyz is the first occurrence
</div>
<div class="xyz">
//appending inner html and pass value 2 as xyz is the first occurrence
</div>
<div class="xyz">
//appending inner html and pass value 3 as xyz is the first occurrence
</div>
The final page when the Jquery/JS script runs should look like this.
<div class="xyz">
<div class="childxyz1">
</div>
</div>
<div class="xyz">
<div class="childxyz2">
</div>
</div>
<div class="xyz">
<div class="childxyz3">
</div>
</div>
<div class="xyz">
<div class="childxyz1">
</div>
</div>
<div class="xyz">
<div class="childxyz2">
</div>
</div>
<div class="xyz">
<div class="childxyz3">
</div>
</div>
EDIT
I have included a sample code that I am working on, here I wish to replace the hard-coded value at the 0th and 1th position with a better code. Appreciate any help in this regard.
.datatableTesting0 thead tr th
.datatableTesting1 thead tr th
** What i want to achieve is a 2 Dimensional array that stores the values, such that, at the 0th position it store the content of first occurrence of class="datatableTesting" and at the 1th position the second occurrence of table with the same class name, so on and so forth.
$(".datatableTesting").each(function(i) {
$(this).addClass("datatableTesting" + i);
});
var tableArray2 = new Array(10);
var tableArray1 = new Array(10);
$('.datatableTesting0 thead tr th').each(function(i) {
var cellText = $(this).html();
tableArray1.push(cellText);
});
$('.datatableTesting1 thead tr th').each(function(i) {
var cellText = $(this).html();
tableArray2.push(cellText);
});
$('.test1').each(function(i) {
var cellText = $(this).html(tableArray1);
});
$('.test2').each(function(i) {
var cellText = $(this).html(tableArray2);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<table class="datatableTesting" cellspacing="0" width="100%">
<thead>
<tr>
<th>First name</th>
<th>Position</th>
<th>Office</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger</td>
<td>System Architect</td>
<td>Edinburgh</td>
</tr>
</tbody>
</table>
<table class="datatableTesting" cellspacing="0" width="100%">
<thead>
<tr>
<th>Last name</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Nixon</td>
<td>$320,800</td>
</tr>
</tbody>
</table>
<table class="test1" cellspacing="0" width="100%"></table>
<table class="test2" cellspacing="0" width="100%"></table>
allNodes = document.getElementsByClassName("xyz");
for(var i=0;i<allNodes.length;i++){
newNode = document.createElement("div");
newNode.className = "childxyz" + (i+1);
allNodes[i].appendChild(newNode);
}
this?
I did something like this (2D iteration.) for this custom requirement.
for (outerloop=0; outerloop < count; outerloop++){
columns=0;
var columns = $(".datatableTesting"+outerloop+" tr")[0].cells.length;
tableCount[outerloop]=new Array(columns);
$(".datatableTesting"+outerloop+" thead tr th").each(function(itrCol) {
var cellText = $(this).html();
//fillvalue in the 2 Dimensional array
tableCount[outerloop][itrCol]=cellText;
});
createDOMStr[outerloop] //initialize to empty str.
for (innerloop=0; innerloop < tableCount[outerloop].length; innerloop++){
// append the string that you want to display
createDOMStr[loopiter] = createDOMStr[loopiter] +//append the DOM string one row at at time.
}
}
I have the below two TR HTML DOM tree. I have to find the total count of id necessary is mapped only for id successDesktop.
<TR class="greybgContent" id="7">
<TD align="center">
<DIV class="necessary" id="necessary"> </DIV>
</TD>
<TD>8 Bureau Consent </TD>
<TD id="successDesktop">
<DIV class="floatLeft selectWidth15">
<DIV class="available"></DIV>
</DIV>
<DIV class="floatLeft selectWidth85 greenText">Uploaded</DIV>
</TD>
</TR>
<TR class="greybgContent" id="8">
<TD align="center">
<DIV class="necessary" id="notrequired"> </DIV>
</TD>
<TD> 9 Address Details</TD>
<TD id="successDesktop">
<DIV class="floatLeft selectWidth15">
<DIV class="available"></DIV>
</DIV>
<DIV class="floatLeft selectWidth85 greenText">Uploaded</DIV>
</TD>
</TR>
If I understand your question correctly, I believe this may be what you are trying to accomplish (I used jQuery).
$(document).ready(function(){
// set the initial count to zero
var count = 0;
// loop over all table rows
$('tr').each(function(index, obj){
// try to find an element with the id 'successDesktop'
if ($(obj).find('#successDesktop').length > 0)
{
// if 'successDesktop' exists, look for an element with id 'necessary'
if ($(obj).find('#necessary').length > 0)
{
// increase the count
count++;
}
}
});
console.log('count: ', count);
});
Additionally you may want to use classes instead of IDs for 'necessary' and 'successDesktop', because IDs are only intended to be used once per page. Classes are intended to be re-usable.
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>