HTMLCollection returning null - javascript

I have already looked at other stackoverflow posts and none of them fix my error.
Trying to get the divs inside the outer div with class name "CodeMirror-code"
I'm building a chrome extension that directly modifies the html content of a specific webpage and when I call
const variable = document.getElementsByClassName('CodeMirror-code');
console.log(variable);
console.log("Length:", variable.length);
the output is: this
Now, when I try to call the first item of HTML collection like
variable.item(0)
this returns undefined or null
Other solutions says that you should surround the code in window.onload function in order for the DOM elements to be loaded in.
I did this, and there was no change.
Is there any way I can fix this error?
Update:
This is what is inside the HTML collection

Surround your code in a set interval function within window.onLoad and add some delay (like 2000 for 2 seconds). The only thing that gives HtML collection null is the loading latency of dom elements. If adding delay is still not helping then try to retrace the parents of your div and see till what point your js code is able to catch the expected div. Then check whether its the problem with load time or scope of the code.

Related

Race condition when hooking appendChild

I've encountered a really weird race condition when hooking appendChild.
consider this code:
var RealAppend = IframeWindow.Element.prototype.appendChild;
IframeWindow.Element.prototype.appendChild = function(){
RealAppend.apply(this, arguments); //some more code here --- >};
I'm hooking some iframe appendchild that's why I'm doing "IframeWindow.Element.prototype.appendChild" with the IframeWindow as the iframe content window.
Now after I'm hooking the appendchild then I start to append nodes to the iframe , one of the nodes is a simple div element with id="somediv" , and another node is a javascript element and as soon as the javascript is executed it will use document.createElement to create an iframe and set its attributes and than it will execute document.getElementById('somediv').appendChild(CreatedIframe);
which will append the created iframe to the "somediv" , my goal here is to intercept the last appendchild and hook the appendchild of that iframe also.
now a first I thought that maybe I need to actually override the appendchild like this:
someDiv.appendChild = function(){.....
but after more tests i can see that sometimes my code does succeed and hooks the last iframe and sometimes the SomeDiv.appendChild is the native code and my code fails.
Any ideas why?
EDIT:
I think its might related to the fact that i'm using
document.createRange().createContextualFragment(strHTML);
}
to parse html as string and then append the nodes to the iframe so maybe the div (somediv) is getting a clean appendChild from there? but why sometimes it does work and sometimes not?
one other thing is that after the page loads and i'm using dev tools to get the somediv.appendchild i'm getting the hooked code every time so the problem happens only when the javascript code executes
So i managed to figure out what was the problem, so if anyone will ever encounter this here is the solution:
When i was parsing the html string to nodes so i can append them to the iframe i was first using the "DOMParser" API and i missed the fact that the DOMParser uses the document from the caller contentWindow so instead of calling DOMParser like this:
new DOMParser();
i needed to call it like that:
new HookedIframeContentWindow.DOMParser();

document.getElementById sometimes returns null

I have a line of code that is called in the onLoad event of a page, and it works fine. Inside the onload event, other functions are called, and trying the same line of code now returns null.
Code verbatim
riskInStateInputTypeElement = document.getElementById("riskInStateInputType");
Are there any instances where getElementById begins returning null after having returned the correct thing previously?
The line that works and the line that doesn't work are both in the same call stack, not separate events or threads. The Document readyStatus is 'complete' both time, so I dont think its a matter of the page not entirely loaded. Any ideas where I should look?
Did you check that it's referring to an element with that id? Maybe you misspelled id="riskInStateInputType" in your <div></div> (or whatever that id is referring to).
Are you deleting the content within that element before you call it the second time perchance?

Targeting an ID that is rendered by a script

I'm using a nifty little script called Tabifier (http://www.barelyfitz.com/projects/tabber/)
Now, long story short, this script, which I run in my head tag, creates a <ul> with <li>s containing <a>s. Also in the head tag it creates IDs for these <a>s. When I inspect the loaded site I can clearly see the ID tags present. However, I cannot call them using getElementById. I've been using
<script>
document.getElementById('rightpanelnav1').style.padding='200px';
</script>
as a sample script in different parts of my code but to no avail. I'm wondering wether it's the placement or order in which these things are defined in my code that's causing it not to recognize the ID. What do you think?
EDIT: I recieved a great answer below, but I still can't get 'rightpanelnav1' to register onclick events...? It's an , there shouldn't be a problem, right? And when I click it, the entire page has been loaded for several seconds...
Firstly, in order to access an element in the DOM, the element must be a part of the DOM (document). So if you place your <script> with getElementById in the page at a place prior to where the element is loaded, it will not see the element in the DOM.
Secondly, it is highly probable that this library you use does its modification on page load, which would mean that no matter where you place your <script> it would have no chance of seeing these elements before running.
As a result, you should have your script wait as well, and do this:
window.onload = function(){
document.getElementById('rightpanelnav1').style.padding='200px';
};
Or for a click event
window.onload = function(){
document.getElementById('rightpanelnav1').onclick = function(){
alert("clicked!");
};
};

Modifying innerHTML of an element created with innerHTML

Basically, I have a div that I insert content into with innerHTML. A segment of the HTML inserted is:
<p style="text-align:center;"><span class="bold" id="timer">00:00:00:0</span></p>
This is a timer that should increment using a setTimeout. Later, I call the following function to modify the timer block:
document.getElementById("timer").innerHTML = output;
When checking the innerHTML property with Firebug or an alert, the innerHTML of the span element is incrementing (e.g. it will say "00:00:10:6" or "00:01:01:4"). However, the page does not reflect the changes; the browser still shows 00:00:00:0.
I tried placing the span directly on the page as opposed to through modifying the div with innerHTML, and only then does it work. Is there anyway to make it work with innerHTML on the div?
EDIT: The page is -----
Try using Firebug or the Chrome console to check the follow:
document.getElementById('bunny-timer').innerHTML
EDIT 2: URL removed.
Without seeing the code, my best guess is that you're accidentally creating duplicate ids, and the element you're seeing is different than the one you're inspecting.
Look at this: http://plugins.jquery.com/project/timers. As you're already using jQuery quite a lot, why not play with their timer functions? They seem to be quite well-made.

Access $('selector').data in functions/objects

How do I access values set by $.data() inside a function or object
$('#timers').data('firsttimer', 100);
//prints 100
document.write($('#timers').data('firsttimer'));
function blah(){
//Prints nothing
document.write($('#timers').data('firsttimer'));
}
blah();
See this jsfiddle for easy access to test the code http://jsfiddle.net/JUfd8/
I'm having trouble with document.write() inside the function call for some reason, but it works fine if I use jQuery's .append().
function blah(){
$('body').append($('#timers').data('firsttimer'));
};
EDIT:
Found this stackoverflow question regarding document.write:
Why is document.write considered a "bad practice"?
An interesting sentence from one of the answers in that post:
As long as you don't try to use it after the document has loaded, document.write is not inherently evil, in my humble opinion.
So that may be the key to the trouble (or part of it, anyway).
The trouble is in "document.write()". Try to avoid it.
In this case, I believe your document.write is stomping on the DOM in some strange way, wiping out your timers div. Switching both of the document.write calls to alert calls instead (and adding a line to invoke blah()) allowed me to see both alert boxes, both showing the value 100.
<div id="timers"></div>
js code:
$('#timers').data('firsttimer', 100);
//shows 100
alert($('#timers').data('firsttimer'));
function blah(){
//Prints nothing
alert($('#timers').data('firsttimer'));
}
blah();
The behavior is not consistent across all browsers. Remember, on jsfiddle this code is already wrapped inside the window load callback since you chose the onLoad setting on the left. Once the DOM is loaded, any subsequent changes using document.write will replace the entire document.
Here's the relevant text from the HTML5 specs on document.write:
Unless called from the body of a script element while the document is being parsed, or called on a script-created document, calling this method will clear the current page first, as if document.open() had been called.
Here's how the browsers are behaving on my Mac given this code:
Chrome and Safari
Wipes out the document altogether. Even 100 isn't printed. Text nodes by themselves are being ignored here, but when wrapped inside some html tag - they show up. This code is the same as above with the values wrapped inside <b> and <i> tags respectively.
Opera and Firefox
Wipes out the document, then appends the text node "100undefined". It prints "undefined" because the node <div id="timers></div> does not exist anymore in the new document.
However, it does print "100" the first time you call document.write on Opera and Firefox
document.write($('#timers').data('firsttimer'));
because the function argument $('#timers').data('firsttimer') is evaluated first and since the original document is intact at this point, we get the value 100, which is then passed to document.write, that then recreates the entire document. Therefore, all subsequent calls to fetch the data associated with #timers returns undefined.

Categories

Resources