I have a hta app that parses some xml using xslt and populates a div within the hta page with the result. The result contains a table that has a summary of the xml with hyperlinks on the counts of xml elements - example below
There will be a button on the page, outside the "content" div that will allow the user to save the page to a static html file without the hyperlinks. I have the following javascript below, but when clicking the "Save" button the hyperlink is only removed from the first item, not the second..(there will be many more actual hyperlinks in the proper version). What am I doing wrong - I assume it is something to do with the loop....and must be done in javascript, no jquery etc - long story as to why...
function SaveContent() {
var myContent = document.getElementById("content")
var myLinks = myContent.getElementsByTagName('a')
for (var myItem = 0; myItem < myLinks.length; myItem++) {
var myChild = myLinks[myItem]
var myParent = myChild.parentNode
var myValue = myChild.innerText
myChild.parentNode.removeChild(myChild)
myParent.innerText = myValue
/*code to save to file will go here */
}
}
<div id="content">
<table>
<tr>
<td>Status</td>
<td>Count</td>
</tr>
<tr>
<td>New</td>
<td>
34
</td>
</tr>
<tr>
<td>Closed</td>
<td>
78
</td>
</tr>
</table>
</div>
Many thanks
getElementsByTagName is a live list. When you call removeChild on an item, it is removed from the list... but the index of your loop continues on!
A typical solution is:
for( var myItem = myLinks.length-1; myItem >= 0; myItem--)
ie. working from the end to the beginning. This is also good if your code might add more links, as they will not be iterated.
Try this:
function SaveContent() {
var myContent = document.getElementById("content")
var myLinks = myContent.getElementsByTagName('a')
while (myLinks.length) {
var child = myLinks[0];
var parent = child.parentNode;
var value = child.innerText;
parent.removeChild(child);
parent.innerText = value;
}
}
Related
I want to get value like in subject, from cell but that cell have element <a>1</a> and in this element is the value.
I tried something like this:
function filter(gvId) {
var table = document.getElementById(gvId);
for (var c = 1; c < table.rows[2].cells.length; c++) {
for (var r = headerNumber; r < table.rows.length; r++) {
var value = table.rows[r].cells[c].getElementsByClassName("a").innerHTML;
console.log(value); //and it should show me :
//1
//2
//3
//4
}
}
}
<table>
<tbody>
<tr>
<td><a>1</a>
</td>
<td><a>2</a>
</td>
</tr>
<tr>
<td><a>3</a>
</td>
<td><a>4</a>
</td>
</tr>
</tbody>
</table>
Everything works greate without <a> tag inside cell. But now I don't know how to get this value.
In your case, the problem is in a row:
var value = table.rows[r].cells[c].getElementsByClassName("a").innerHTML;
Because you're trying to match an element by class, but not by element tag. Link tag <a> has no className a. Your current code will work fine for: <a class="a">1</a> or <div class="a"></div>.
May be you should try something like querySelector instead? Like:
var value = table.rows[r].cells[c].querySelector('a').innerHTML;
Please, also check the MDN docs about getElementsByClassName and querySelector
UPD: All the code could be simplified:
var contentLinks = table.querySelectorAll('td a');
contentLinks.forEach(function(item) {
var value = item.innerHTML;
console.log(value);
});
Get the text content of an element with .textContent instead of .innerHTML
var value = table.rows[r].cells[c].textContent;
Documentation here and here
I am trying to get the information from my table td's, using javascript. How can i achieve this? I have tried and failed, because i do not exactly understand the JS. So far, i have managed to get one of them to work, which is 'id' but thats just getting info from the db directly, the td values ive been unable to.
echoing the vals in my php update page shows the id val being passed successfully, but none others.
EDIT
Per your last comment I can recommend you use an event listener on all <td> tags and this way you can just get the relevant text of the specific <td> that the user clicked:
var tds = document.querySelectorAll('td');
for (var i = 0; i < tds.length; i++) {
var td = tds[i];
td.addEventListener('click', function(){
console.log(this.innerText)
});
}
<table>
<tr>
<td class="awb">I am the first awb</td>
<td class="awb">I am the second awb</td>
</tr>
<tr>
<td class="differentClass">I am the first differentClass</td>
<td class="differentClass">I am the second differentClass</td>
</tr>
</table>
You are approaching this all wrong...
Instead of this:
var awbno = String(tr.querySelector(".awb").innerHTML);
Do this:
var awbno = document.querySelector(".awb").innerHTML;
Here is a snippet:
var awbno = document.querySelector(".awb").innerHTML;
console.log(awbno);
<table>
<tr>
<td class="awb">Test Text inside a td tag</td>
</tr>
</table>
in order to get the contents of any element using class
let value = document.querySelector('.className').innerHTML;
in order to get the contents of a specific TD
let value = document.querySelector('td.className');
I am trying to use java-script to export html data into excel. The funny thing is that it DOES work when I use getElementsByTagName instead of getElementById. However, I need to pinpoint id elements and thus 'getElementById' is what I need (I guess). When I debug the below code in IE it gives me:
Object doesn't support property or method 'getElementsById'
Here is what I've got:
HTML (as an idea only):
<body>
<table>
<tr>
<td>content 1</td>
<td>content 2</td>
<td id="R">content I need</td>
<td>some other content</td>
</tr>
</table>
</body>
and accompanying JS
<script type="text/javascript">
function write_to_excel()
{
str="";
var mytable = document.getElementById("R")[0];
var row_Count = mytable.rows.length;
var col_Count = mytable.getElementById("R")[0].getElementById("R").length;
var ExcelApp = new ActiveXObject("Excel.Application");
var ExcelSheet = new ActiveXObject("Excel.Sheet");
ExcelSheet.Application.Visible = true;
for(var i=0; i < row_Count ; i++)
{
for(var j=0; j < col_Count; j++)
{
str= mytable.getElementById("R")[i].getElementById("R")[j].innerHTML;
ExcelSheet.ActiveSheet.Cells(i+1,j+1).Value = str;
}
}
}
</script>
I have the feeling - it's trifle but ... Thanks in advance!)
The getElementById method returns a single DOM element (if you have more than one HTML element with the same ID then your page is buggy but browsers won't complain because 10 years ago it was a common bug that lots of people make). As such the statement:
document.getElementById("R")[0]
Makes no sense whatsoever. Instead, what you want is:
var myTD = document.getElementById("R");
If you have a page structure like this:
<table id='T'>
<tr>
<td>content 1</td>
<td>content 2</td>
<td>content I need</td>
<td>some other content</td>
</tr>
</table>
And want to iterate each column in each row, you'd do it like this:
var mytable = document.getElementById("T");
var table_rows = mytable.getElementsByTagName('tr');
for (var row=0;row<table_rows.length;row++) {
var row_columns = table_rows[row].getElementsByTagName('td');
for (var col=0;col<row_columns.length;col++) {
var item = row_columns[col];
// process item here
}
}
See the documentation of HTMLElement for more info on how to navigate the DOM: https://developer.mozilla.org/en/docs/Web/API/Element
Full documentation of the DOM API: https://developer.mozilla.org/en/docs/DOM
You may also check out the relevant docs on MSDN instead of MDN for IE specific stuff but I prefer MDN because it documents the compatibility level (what other browsers implement a feature) of the API.
IDs must be unique.
Therefore, the function you're looking for is called getElementById (singular)
I am using greasemonkey to change the functionality of an existing web page.. If you aren't familiar with greamonkey it doesn't really matter.. the main information is that the current code for the existing page looks like this:
<div id="sqlDiv" class="sqlBorderDiv" style="display: none;">
<div class="reportBorderDiv">
<table class="reportTable">
<tbody>
<tr>
<tr class="reportRow1">
<tr class="reportRow2">
<td>55555</td>
<td>Bruce Wayne</td>
<td>12456789123</td>
<td>2013-12-17</td>
<td>Batman</td>
<td>Superhero</td>
<td>Menace</td>
<td>123246</td>
<td>12456</td>
<td>123456</td>
<td></td>
</tr>
</tbody>
</table>
</div>
I want to run a script on it that will make the first cell of any reportRow into a hyperlink using the information in that cell. I am trying with a script like below, but something is going wrong and I have no idea what. ( I am really new into javascript). Thank you for any suggestions!!
var anchor = null;
var container;
var rows;
var cells;
var demoNum;
var linkString = "https://somewebsite.com/";
container = document.getElementById('sq1Div');
rows = container.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
var className = rows[i].getAttribute("class");
if ( className == "reportRow1" || className == "reportRow2" ) {
anchor = rows[i];
cells = anchor.getElementsByTagName("td");
demoNum = cells[0];
linkString = linkString + demoNum;
cells[0] = <a href = linkString > demoNum </a>;
}
}
The problem is in the line
cells[0] = <a href = linkString > demoNum </a>;
That should be in a string, like this:
cells[0]="<a href='"+linkstring+"'>"+demonum+"</a>";
To put that back in the first row of the table, you can do this
row[i].childNodes[0].innerHTML=cells[0];
Also, you have document.getElementById("sq1div"), instead of "sqlDiv"
document.getElementById('sq*1*Div');
incorrect indetifier, you are using number "1" instead of letter "l"
and of course as wrote scrblnrd3 line with new link builds incorrect
It seems to me the HTML has unmatched tags, could this somehow confuse greasemonkey?
I have a a and I would like to sort my list alphabetically (I don't want caps to matter) according to a class named "name". How would I do this?
<ul class="column">
<li>
<table>
<tr>
<td class="name" >Name of Item</td>
</tr>
<tr>
<td>Content</td>
</tr>
<tr>
<td>morecontent</td>
<td>morecontent</td>
</tr>
</table>
</li>
<li>
<table>
<tr>
<td class="name" >Another name of item</td>
</tr>
<tr>
<td>Content</td>
</tr>
<tr>
<td>morecontent</td>
<td>morecontent</td>
</tr>
</table>
</li>
</ul>
Thanks
Using jQuery, this should do it:
function sort() {
$($('ul.column>li').get().reverse()).each(function(outer) {
var sorting = this;
$($('ul.column>li').get().reverse()).each(function(inner) {
if($('td.name', this).text().localeCompare($('td.name', sorting).text()) > 0) {
this.parentNode.insertBefore(sorting.parentNode.removeChild(sorting), this);
}
});
});
}
The above is a little dense though, so if you want to understand what's going on, let's break it down line-by-line:
function sort() {
//get each <li> which is a child of <ul class="column">
//for each element in the results, execute a function
//also, we reversed the order (e.g. start at the bottom and go up
$($('ul.column>li').get().reverse()).each(function(outer) {
//this is the current <li> we're running against
var sorting = this;
//get the same set of elements again in their current state,
//so we can figure out where to put this one
$($('ul.column>li').get().reverse()).each(function(inner) {
//get the inner text of the <td class="name">
//for the item we're trying to replace,
//and for the current item in the inner loop
//use localeCompare to compare the two strings alphabetically
if($('td.name', this).text().localeCompare($('td.name', sorting).text()) > 0) {
//if the one we're trying to sort goes after the current one
//alphabetically, remove it from its current position
//and insert it after the current one
this.parentNode.insertBefore(sorting.parentNode.removeChild(sorting), this);
}
});
});
}
We can make it a little more reusable by passing in the selector for the list and the key:
sort('ul.column>li', 'td.name');
function sort(list, key) {
$($(list).get().reverse()).each(function(outer) {
var sorting = this;
$($(list).get().reverse()).each(function(inner) {
if($(key, this).text().localeCompare($(key, sorting).text()) > 0) {
this.parentNode.insertBefore(sorting.parentNode.removeChild(sorting), this);
}
});
});
}
Do keep in mind this requires jQuery, so you'll need a reference to it in your <head>:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
And this function should be called at some point in the page after the list is written in the HTML.
Mine answer is longer :p but work.
function SortLIs() {
var ColumnUL = $("ul.column");
var Columns = $(ColumnUL).children("li");
var ColumnNames = new Array();
var Columns_byName = new Array();
var Columns_Count = Columns.length;
for(var i = 0; i < Columns_Count; i++) {
var aColumn = Columns[i];
var aTD = $(aColumn).find(".name");
var aTDName = aTD.text();
ColumnNames.push(aTDName);
Columns_byName[aTDName] = aColumn;
$(aColumn).remove();
}
ColumnNames.sort(function(a, b){
return (a > b) - (a < b);
});
for(var i = 0; i < Columns_Count; i++) {
var aName = ColumnNames[i];
ColumnUL.append(Columns_byName[aName]);
}
}
EDIT: I saw you said that you are not good at JS. So here is the bigger picture for you.
(1) Add The following code to the header of the HTML. This will use jQuery library.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
(2) Add the 'sortLIs' code just right after the above code
<script>
<!--
function SortILs() {
...
}
-->
</script>
(3.1) If you want the sorting to begin at the load time. Add this right after the above code.
<script>
<!--
$(document).ready(function(){
SortILs();
});
-->
</script>
(3.2) Otherwise, you call the function from an event.
Hope this helps.
Here's another approach, stealing ideas from the other answers given so far (also requiring jQuery):
function sort(elementSelector, valueSelector, ascending) {
var sign = ascending ? -1 : 1;
var elements = jQuery(elementSelector);
elements.each(function() {
this.sortKey = jQuery(valueSelector, this).text();
});
var sorted = elements.get();
sorted.sort(function(a, b) {
var keyA = a.sortKey;
var keyB = b.sortKey;
return sign * ((keyA < keyB) - (keyA > keyB));
});
elements.parent().append(sorted);
}
sort('.column>li', '.name', true)
Just seconding the jQuery response above, have a look at this tutorial:
http://www.shopdev.co.uk/blog/sortable-lists-using-jquery-ui/
For semantics, you might be better off also placing the classname inside the actual <li> tag.
The use of a table inside a list aside though, you may want to post an example page to help further.