getElementById(...) returns null unexpectedly - javascript

EDITED: I pretty much checked dozens of articles here on this issue, but I simply can't find the problem in my code: The line (commented below) returns null, although I expect it to return the particular element I created and added above.
element2 = document.createElement("button");
element2.innerHTML = "-";
element2.text = rowCounter;
element2.style.backgroundColor = 'white';
element2.id = "kuerzer"+rowCounter; //rowCounter is an iterator variable
ell2.appendChild(element2);
console.log(document.getElementById(element2.id)); //returns null
However, I am now trying to find this element in another function like this:
function structureGantData(){
var gantData = [[]];
for(i=0; i<document.getElementById("myTable").rows.length; i++){
console.log("schleife");
gantData[i][0] = document.getElementById("kuerzer",(i+1)).text; //ISSUE
Could anyone help me? :-)
Thanks alot!
Fabian

You have not added the created element to the DOM, so it cannot be found there.
You may use say Node.appendChild (or any other similar) method to append it somewhere first.

I believe you meant to call document.getElementById("kuerzer" + (i + 1)) rather than document.getElementById("kuerzer", i + 1) in structureGantData.

Related

Storing for loop result to push into HTML

EDIT: Solved. After the helpful people here helped me solve this I realised this issue was to do with my getElementsByClassName selector. Sorry if the title is misleading. The original question is below.
I am getting the expected results from this function's for loop, but I can't get them to print to the HTML.
Could anybody help point out what I'm missing? A point in the right direction would do, I can do some legwork myself.
Any advice is much appreciated.
HTML:
<input type="text" name="searchString" class="searchString">
<span class="longestWordInput"></span>
<span class="longestWordCountInput"></span>
<button class="generate">Generate</button>
JavaScript:
function longestWordFunc() {
var stringSplit = document.querySelector(".searchString").value.split(" ");
let longestWordCount = 0;
let longestWord = "";
for(var i = 0; i < stringSplit.length; i++) {
if(stringSplit[i].length > longestWordCount) {
longestWordCount = stringSplit[i].length;
longestWord = stringSplit[i]
}
}
//Logging expected result
console.log(longestWordCount)
console.log(longestWord)
//Print to HTML not working
document.getElementsByClassName("longestWordInput").innerHTML = longestWord;
document.getElementsByClassName("longestWordCountInput").innerHTML = longestWordCount;
};
document.querySelector(".generate").addEventListener("click", longestWordFunc);
The problem is that getElementsByClassName() returns a NodeList (an array-like structure containing all elements with the specified class name) instead of a single element.
You can access your single span element like this
document.getElementsByClassName("longestWordInput")[0].innerHTML = longestWord;
or you could use querySelector() instead
document.querySelector(".longestWordInput").innerHTML = longestWord;
Hi I believe you need to use getElementsByClassName like the below
document.getElementsByClassName("longestWordInput")[0].innerHTML = longestWord;
document.getElementsByClassName("longestWordCountInput")[0].innerHTML = longestWordCount;

TypeError: document.getElementById(...)[0] is undefined

Ok, guys. I'm not sure why this doesn't work. Following an example the teacher gave us and as far as I can tell, everything is the same except for the function and variable names... Using an external JavaScript file, Dreamweaver says there's no syntax errors or anything else of the sort but debugger on Firefox says TypeError: document.getElementById(...)[0] is undefined... which I'm not exactly sure why but here is my code:
JavaScript:
var caveboyanim = new Array(6);
var curCaveBoy = 0;
for (var i = 0; i < 6; ++i) {
caveboyanim[i] = new Image();
caveboyanim[i].src = "images/caveboy" + i + ".png";
}
function caveboyanimation() {
if (curCaveBoy == 5)
curCaveBoy = 0;
else ++curCaveBoy;
document.getElementById("caveboy")[0].src = caveboyanim[curCaveBoy].src;
}
HTML:
<body onLoad="setInterval('caveboyanimation()', 1000);">
<img src="images/caveboy0.png" id="caveboy" alt="Image of a cave boy">
</body>
remove the [0] from:
document.getElementById("caveboy")[0].src = caveboyanim[curCaveBoy].src;
The index 0 is used with jQuery objects to get "real" document element. But you are not using JQuery here so it's not needed.
The return of document.getElementById() is not an array. Use:
document.getElementById("caveboy")
It's not returning an array so you can't do [0]. https://developer.mozilla.org/en-US/docs/Web/API/document.getElementById
By the way, look into jQuery.
In native javascript:
document.getElementById("caveboy").src = caveboyanim[curCaveBoy].src;
In jQuery you can do like this to get real DOM object:
$("#caveboy")[0].src = caveboyanim[curCaveBoy].src;
document.getElementById("caveboy") same as $("#caveboy")[0]

Issue with jQuery data

I'm struggling a little. I'm attempting to utilize the cool feature of assigning a custom attribute to an element. However it isn't working.
Basically, I'm trying to assign multiple elements to the TR element identifying information in that row. Here is what it looks like:
for (x=0; x< theData.length; x++)
{
// create table row
var selector = "wc_" + wID + "_row_" + x;
oRow = document.createElement("TR");
oRow.setAttribute("id", selector);
tBodyO.appendChild(oRow);
var rowCount = 0;
var identCnt = 0;
for (var index in theData[x])
{
identCnt = 0;
if (hasIdentify)
{
for (y=0; y < theIdent.length; y++)
{
console.log("ROW: "+x+" , checking: "+index+" === "+theIdent[y]["data_name"]);
if (index === theIdent[y]["data_name"])
{
myrow = $("#" + selector);
//myrow.attr("test","works");
console.log("ident Dataname: "+theIdent[y]["data_name"]+ " identify:"+theIdent[y]["identify"]+" value: "+theData[x][index]);
jQuery.data( myrow, "test", { first: 16, last: "pizza!" });
alert(myrow.data("test"));
}
}
}
}
}
I've left out some code that's not really relevant, but I hope you get the picture. What I'm trying to do is this:
I have an array that contains "identity" information about a particular row of data. It can have 0, 1 or more such identity pieces. I want to store these as a custom data attribute on the <TR> element.
Each data will have a distinct key (example: i_0_1 where 0 is the data row number and 1 is the identity counter)
However, I can't get this to work. I've tried lots of alternatives even trying to resort to .attr() with no luck. What am I doing wrong??
I'm getting an alert that says undefined. When I try the myrow.attr("test","works"); route I can see the attribute in the DOM. Why won't the data() way work for me?
I just figured out what the problem is. I guess after reading the docs on jQuery.data() I didn't see anyone really clearly come out and say:
You will not see the data info in the DOM - element when you look at the source.
To the credit of everyone here, they did tell me, I just didn't know what I was reading (now that I know what is expected)
Matt wrote:
"ill not actually set an attribute or property on the element; jQuery stores this data in an internal cache, and merely maps it to the element you selected"
Although after playing around with the .attr() and setAttribute() functions I just became more confused.
Thanks everyone!

Need help optimizing script that hides table rows

I made this Greasemonkey script:
var maxpi = 250;
var p1 = "/html/body/div/div[2]/div/div[2]/table[2]/tbody/tr[1]/td[11]";
var p2 = "/html/body/div/div[2]/div/div[2]/table[2]/tbody/tr[2]/td[11]";
..
var p25 = "/html/body/div/div[2]/div/div[2]/table[2]/tbody/tr[25]/td[11]";
var r1 = "/html/body/div/div[2]/div/div[2]/table[2]/tbody/tr[1]";
var r2 = "/html/body/div/div[2]/div/div[2]/table[2]/tbody/tr[2]";
..
var r25 = "/html/body/div/div[2]/div/div[2]/table[2]/tbody/tr[25]";
var xpathPI1 = document.evaluate(p1, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
..
var xpathPI25 = document.evaluate(p25, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
var xpathrow1 = document.evaluate(r1, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
..
var xpathrow25 = document.evaluate(r25, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
if (xpathPI1.singleNodeValue.textContent >maxpi ){
xpathrow1.singleNodeValue.style.display='none';}
..
if (xpathPI25.singleNodeValue.textContent >maxpi ){
xpathrow25.singleNodeValue.style.display='none';}
Basically, it checks a table row's 11th field and if its contents > than 250 it hides the row.
With my limited javascript knowledge took quite some time get this working.
The problem is that I have to rewrite every single line if I want to check-hide another row.
I want to make it more usable so I can use it on similar tables without rewriting the whole thing.
Maybe I need to use a different XPath type or use some kind of changing variable?
Of course, there are more ways to improve your script.
Firstly, you need to thoroughly think through WHAT exactly you want to look for. Is is every row and column? Is it rows/columns with some text, class, any other attribute? You can even select only those nodes that have their text value greater than your maxpi!
Read something about XPath, the possibly best resource is the official one.
Some random thoughts on what could be useful regarding XPath:
//table//tr[5]/td[2] ... the double slash is the deal here
//table//tr/td[number(text()) > 250] ... the number() and text() functions
When talking about JavaScript, that would be a little tougher, because there are so many things you could use!
Just for starters - you can create dynamically changing xpath expressions by String concatenation and For loop, like this:
for (var i = 1; i <= maxNumberOfRows; i++) {
var p1 = "//table/tbody/tr[" + i + "]";
// more work goes here...
}
Also, you could use arrays to store multiple nodes returned by your XPath expressions and work on them all with just a single command.
For more JavaScript, I would recommend the first chapters of some JavaScript tutorial, that will boost your productivity by a lot.
Use a loop and functions. Here's one way:
hideRowsWithLargeCellValue (
"/html/body/div/div[2]/div/div[2]/table[2]/tbody/tr[",
25,
"]/td[11]",
250
);
function hideRowsWithLargeCellValue (xpathPre, maxRows, xpathPost, maxpi) {
for (var J = maxRows; J >= 1; --J) {
var srchRez = document.evaluate (
xpathPre + J + xpathPost,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (srchRez.singleNodeValue && srchRez.singleNodeValue.textContent > maxpi) {
var rowToHide = srchRez.singleNodeValue.parentNode;
rowToHide.style.display='none';
}
}
}
Then read "Dont Repeat Yourself" (sic).

Validation for checkboxes

Hello
I have a JS function which says
for(var i = 0; i < document.calDailyBlock.selFilCheckBox.length; i++)
{
if(document.calDailyBlock.selFilCheckBox[i].checked)
{
filteredInitId += document.calDailyBlock.selFilCheckBox[i].value + ",";
alert(filteredInitId);
isProjCheck = true;
}
}
document.calDailyBlock.filteredComId.value = filteredInitId;
When there are no checkboxes on the page and I try to click on Filter button which calls this function, I receive an error "document.calDailyBlock.selFilCheckBox.length' is null or not an object"
Is there any simple thing which I can add in this function ?
Also can anyone help me how to check if there is only one checkbox on one page ?
Thanks in advance
I think you are relying on a fairly obscure (non-official) feature of some browsers which lets you get an element from the document as if it were an attribute. In other words, you are going:
document.calDailyBlock
This is searching the document for a variable calDailyBlock. Instead, you should use the standardised getElementById:
document.getElementById("calDailyBlock")
And use the same approach for getting selFilCheckBox.
This will return null if calDailyBlock or selFilCheckBox are not found. Before you go calling length on them (which gives that error), you should check to see if you got back null, and then (I suppose) fail silently (don't do anything).
to avoid the error use an if:
if(document.calDailyBlock.selFilCheckBox) {
for(var i = 0; i < document.calDailyBlock.selFilCheckBox.length; i++)
{ … }
}

Categories

Resources