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?
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 just started using DataTables and everything works fine when creating the table.
When I display 5, 24, 47 rows in my table, DataTables behaves as I would expect.
But I have this table that has around 700 rows and I get the error in Google Chrome,
"VM9075 dataTables.min.js:24Uncaught TypeError: Cannot set property '_DT_CellIndex' of undefined "
and in IE 9,
"SCRIPT5007: Unable to set value of the property '_DT_CellIndex': object is null or undefined
jquery-1.10.2.min.js, line 4 character 2367"
I don't have jQuery included twice btw.
I'm not sure how to proceed from here.
I tried to use the unminified version of the .js file to debug it more myself but i kept getting an "ext" method or property is undefined and couldn't fix that either.
Any help is appreciated!
I figured it out
The biggest issue was not knowing exactly what this error actually meant.
In my case it meant "the number of every <td> element in your table that is a child of a <tr> element doesn't match the number of <th> elements that are a child of the <thead> element."
My table was being generated by the server, and some of the <tr> elements had 27 <td> children (which was filling the whole width of the table up, but some of the <tr> elements only had 3, 4, or 5, ... <td> child elements which isn't a valid table.
I solved it by adding empty <td> elements in my table for the <tr> elements that lacked the correct number of <td> elements
var makeTableValidObject = {
thisWasCalled: 0,
makeTableValid: function() {
var tableToWorkOn = document.getElementById("table1");
//check the number of columns in the <thead> tag
//thead //tr //th elements
var numberOfColumnsInHeadTag = tableToWorkOn.children[1].children[0].children.length;
var numberOf_trElementsToValidate = tableToWorkOn.children[2].children.length;
//now go through each <tr> in the <tbody> and see if they all match the length of the thead columns
//tbody //all trs//all tds elements
//tableToWorkOn.children[2].children.children);
for(var i = 0; i < numberOf_trElementsToValidate; i++) {
//row my row make sure the columns have the correct number of elements
var tdColumnArray = tableToWorkOn.children[2].children[i].children
var trElementToAppendToIfNeeded = tableToWorkOn.children[2].children[i];
if(tdColumnArray.length != numberOfColumnsInHeadTag) {
//since they don't match up, make them valid
if(tdColumnArray.length < numberOfColumnsInHeadTag) {
//add the necessary number of blank <td> tags to the <tr> element to make this <tr> valid
var tdColumnArrayLength = tdColumnArray.length;
for(var j = 0; j < (numberOfColumnsInHeadTag - tdColumnArrayLength); j++) {
var blank_tdElement = document.createElement("td");
blank_tdElement.id = "validating_tdId" + i + "_" + j;
trElementToAppendToIfNeeded.appendChild(blank_tdElement);
}
}
else {
//TODO: remove <td> tags to make this <tr> valid if necessary
}
}
}
}
};
Edit 1:
It has been awhile and this question is still getting a bunch of views. I have since updated the code.
I replaced the first line of code with the second line to be more general
var numberOfColumnsInHeadTag = tableToWorkOn.children[1].children[0].children.length;
var numberOfColumnsInHeadTag = tableToWorkOn.querySelectorAll('thead')[0].querySelectorAll('th');
Pretty much where ever in the prior code you see the children.children I replaced that with the querySelectorAll(...) Function.
It uses css selectors which makes it amazingly powerful.
stay blessed
Ran into this same issue and implemented this same solution (essentially) in jquery based on Coty's. Hope this helps someone. :)
$( '.table' ).each(function( i ) {
var worktable = $(this);
var num_head_columns = worktable.find('thead tr th').length;
var rows_to_validate = worktable.find('tbody tr');
rows_to_validate.each( function (i) {
var row_columns = $(this).find('td').length;
for (i = $(this).find('td').length; i < num_head_columns; i++) {
$(this).append('<td class="hidden"></td>');
}
});
});
As answered by Coty, the problem lies in the mismatch of td elements generated in the header and body of table.
I'd like to highlight one of the reasons why it can occur (For .Net Users).
If Page numbers are being displayed at the end of gridview, they can disrupt table structure.
Remove AllowPaging="true" from your gridview to solve this.
And no worries because Datatable handles Paging.
you always keep four column but sometimes you will receive or append null td or only one td, td count always match with total column so when you does not have record then make td as following.
<th>No</th>
<th>Name</th>
<th>place</th>
<th>Price</th>
----------------------------------------
<td colspan="4">Data not found.</td>
<td style="display: none;"></td>
<td style="display: none;"></td>
<td style="display: none;"></td>
this error can also be triggered if you try to set options for the responsive extension for more columns than you have.
$( '.table' ).each(function( i ) {
var worktable = $(this);
var num_head_columns = worktable.find('thead tr th').length;
var rows_to_validate = worktable.find('tbody tr');
rows_to_validate.each( function (i) {
var row_columns = $(this).find('td').length;
for (i = $(this).find('td').length; i < num_head_columns; i++) {
$(this).append('<td class="hidden"></td>');
}
});
});
I have a Website with tables which have informations about work projects. Here's an example:
<tr valign="top" bgcolor="#FFFFA0"><td valign="top" bgcolor="#00CC00"></td>
<td valign="top">1500-779</td>
<td valign="top">140072EAL</td>
<td valign="top">125</td>
<td valign="top">DSQ ABC</td>
<td valign="top">34_FEAT-1234: Object Index: Example</td>
<td valign="top"></td>
<td valign="top">om</td>
<td valign="top">br</td>
<td valign="top"><p title = "individual task is scheduled">edit</p></td>
<td valign="top">9,7</td>
<td valign="top">2,3</td>
<td valign="top">7</td>
<td valign="top">8</td>
<td valign="top">2016 24,4</td>
<td valign="top">2016 35</td>
<td valign="top">0</td>
</tr>
Now I want to construct a dynamic Greasemonkey script which search for dynamic tags like FEAT-1234,WTS-4567,PIDT-7896 etc. and replace it with a direkt dynamic link to the entry of the Bug in the management software. This is my code so far:
var replacementRegexp = /([A-Z]+)-([0-9]{4})/; //defined regular expression
var searchvar = "";
var link = "";
for (var i = 0; i < 2; i++)
{
if(i == 0)
{
$searchvar = "FEAT";
$link = 'https://vmpolarion.dqa-ac.de/FEAT/workitem?id=FEAT-';
}
else if (i == 1)
{
$searchvar = "WTS";
$link = 'https://vmpolarion.dqa-ac.de/WTS/workitem?id=WTS-';
}
else
{
$searchvar = "PIDT";
$link = 'https://www.vpext.dsa-ac.de/PIDT/show_bug.cgi?id=PIDT-';
}
$("table td:contains('"+searchvar+"')").each(function(index, element) //looking for the tag
{
$(element).html($(element).html().replace(replacementRegexp, '$1-$2')); //replaces the text with a link to the Bugzilla entry
});
}
The search function of the tag works but the replacing still makes problems. One problem is that the links are variable and the Number of the tag that should be found must be part of the link. The most tags have their own link structure. I want to an elegant solution, which is not very long, but I think my code is not very suitable. How can I solve the problem?
PS: This is the first time that I have been working with Greasemonkey,Javascript and JQuery.
Okay i made a realy stupid mistake. I have solved the problem now. Here is the Code.
var replacementRegexp = /([A-Z]+)-([0-9]{4})/; //defined regular expression
var query = new Array();
query[0] = new Array("table td:contains('FEAT')",'$1-$2'); //search word|Link
query[1] = new Array("table td:contains('WTS')",'$1-$2');
query[2] = new Array("table td:contains('PIDT')",'$1-$2');
query[3] = new Array("table td:contains('ATH')",'$1-$2');
for (var i = 0; i <= query.length; i++)
{
$(query[i][0]).each(function(index, element) //looking for variable
{
$(element).html($(element).html().replace(replacementRegexp, query[i][1])); //replaces the text with a link to the Database entry
});
}
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;
}
}
I have a problem in my code. I want to get the b tag that has the style color silver using Javascript. I tried using the tagName === "B" but it didn't work. I figured that the B tags are not children of the rowData class.
<tr class="rowData">
<td style="padding: 0pt;">
<table><tr>
<td>
<b style="font-size: 15px; color: silver;">Mugging</b>
<br />Payout: <b style="color: green;">$200 - $300</b>
<br />Experience: +1 </td>
<td style="text-align: right;">
</td>
</tr></table>
</td>
<td style="padding: 0pt;">
<table><tr>
<td style="width: 100px;">
<b style="color: gray;">Required:</b>
<br />Energy: 1 </td>
<td style="">
</td>
</tr></table>
</td>
</td>
</tr>
I removed some part of it..
Here's some part of the Javascript code:
var jobs = {};
jobs.scan = function() {
var tagHolder = {};
var availJobs = {};
var jobContents = dom.get("app8743457343_content");
var rData = dom.getElementsByClass("rowData", jobContents, "tr");
for(var i = 0; i < rData.length; i++) {
var rChildren = rData[i].childNodes;
for(var j=0; j<rChildren.length; j++) {
if(rChildren[j].tagName === 'B') {
alert(rChildren[j]);
}
}
}
}
jobs.scan();
When I started the script it didn't alert, or responded. Maybe I need to use something to like nextSibling? Please help me figure this out.. I want the b with the style color silver. The Mugging text
You could fight the good fight and try to get that monstrosity working across all browsers....
Or, you could try jQuery! It's fun and easy, and all the cool kids are doing it!
var text = $('tr.rowData').find('b').filter(function() {
return $(this).css('color') == 'silver';
}).text();
alert(text);
Tada!
EDIT: In all seriousness, if you want to do it in raw javascript, this works for me on IE and Firefox:
var text;
var bs = document.getElementsByTagName("b");
for(var x = 0; x < bs.length; x++) {
if(bs[x].style.color == 'silver') {
text = bs[x].innerHTML;
break;
}
}
alert(text);
It is just grabbing all the bold elements in the document and checking to see which one has a color of silver. This is not super efficient, obviously, and I am not sure of your use case. I do see in your code you are first grabbing a reference to a jobContents element. I am not sure where that is coming from as you didn't post that part of the markup, but if the <b> will end up being inside this element, you can change this line:
var bs = document.getElementsByTagName("b");
To this:
var bs = jobContents.getElementsByTagName("b");
Which will then 1) speed it up, 2) make sure you get what you want.
Good luck.
Your code doesn't go down deep enough into the tree. You need at least 4 more levels of childNode "for" loops to get to the "B" tag. If you go this route then you should probably make a recursive function that searches for your "B" tag.