Internet Explorer throwing error on getElementById - javascript

I'm having trouble with some javascript which uses getElementById. It works fine in FF, Safari and Chrome, but IE(8 - haven't tried others) bails out.
The relevant bit of html is a div called topnav:
<div id="topnav">
... some HTML ...
<div>
<div id="sub_1" class="lowernav">
... some HTML ...
</div>
<div id="sub_2" class="lowernav">
... some HTML ...
</div>
In my javascript, I want to find topnav. The full code (up to where it bails) is this:
<script>
window.onload = init();
function init() {
// Show current menu
showCurrentMenu();
}
function showCurrentMenu() {
hideMenus(); // Hide all menus and then show the current one
topnav = document.getElementById('topnav');
... rest of code ...
}
function hideMenus() {
var divlist = document.getElementsByTagName('div');
for(var ii=0; ii<divlist.length; ii++) {
if(divlist[ii].className != divlist[ii].className.replace('lowernav','')) {
divlist[ii].className += ' hidden';
}
}
}
... then some other code it hasn't reached yet...
Am I doing something wrong here? It may well be something really obvious, but for the life of me, I can't see it! All advice is much appreciated.
ETA: Ok, here's the whole code, as it currently stands:
<script>
window.onload = init;
function init() {
// Show current menu
showCurrentMenu;
// Attach 'onmouseover' event to main menu items
topnav = document.getElementById('topnav');
// Get all items in list
var menulist = topnav.getElementsByTagName('a');
for(var ii=0; ii<menulist.length; ii++) {
menulist[ii].onmouseover = showMenu;
}
document.getElementById('mainHomeNav').onmouseout = restoreMenu;
}
function restoreMenu(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
if (targ.id == "mainHomeNav") {
showCurrentMenu;
}
}
function hideMenus() {
var divlist = document.getElementsByTagName('div');
for(var ii=0; ii<divlist.length; ii++) {
if(divlist[ii].className != divlist[ii].className.replace('lowernav','')) {
divlist[ii].className += ' hidden';
}
}
}
function showCurrentMenu() {
hideMenus;
topnav = document.getElementById('topnav');
// Get all items in list
var menulist = topnav.getElementsByTagName('a');
for(var ii=0; ii<menulist.length; ii++) {
if(menulist[ii].className != menulist[ii].className.replace('thisSection','')) {
var thisid = menulist[ii].id;
var thissubmenu = document.getElementById(thisid + '_sub');
thissubmenu.className = thissubmenu.className.replace(/hidden/g,'');
}
}
}
function showMenu() {
hideMenus;
// show this menu
var submenu_id = this.id + '_sub';
var submenu = document.getElementById(submenu_id);
submenu.className = submenu.className.replace(/hidden/g,'');
}
</script>

The problem is
window.onload = init();
This will call the init function immediately, and then use its return value as the page's onload function. You need:
window.onload = init;
which will call the init function only after the page has fully loaded.

I found the problem - I didn't have 'var' in front of 'topmenu'.
So instead of
topnav = document.getElementById('topnav');
it should have been
var topnav = document.getElementById('topnav');
Thanks everyone for the help.

Your problem lies in the following line:
window.onload = init(); // this will CALL init() and assign the return value
Since init doesn't return anything, window.onload will be undefined.
Now the reason for it not working in IE, but in other Browsers is that those other Browsers might already have parsed a part of the DOM and therefore the call to showCurrentMenu works.
But that could just as well break, since from a technical point of view the document is not guaranteed to be loaded, to fix that you have to assign the actual function reference to window.onload by doing:
window.onload = init;

Related

Replace All Words In Document Body Doesn't Work

Firstly sorry for my english, i have code that doesnt work when I execute it on
<script language="javascript" src="/thecode.js"></script>
I put thecode.js on footer
var msg=document.body.innerHTML;
for(var i=0;i<msg.length;i++){
var tx=document.body[i].innerHTML;
tx=tx.replace(/dog/ig,'animal');
tx=tx.replace(/apple/ig,'fruit');
tx=tx.replace(/\[VIdEo\]/ig,'Video');
tx=tx.replace(/http\:\/\/example\.com/ig,'http://thelink.com');
document.body.innerHTML=tx;}
I think i dont make any fault, but when i execute it, its doesnt work.
thank for your attention... :)
no need to iterate body element
try this:
want to change to with that js? i have used to make it
function addTitleToSurveyUrls() {
var elements = document.getElementsByTagName('a');
for(var el in elements) {
var element = elements[el];
var href = element.getAttribute("href");
if(href.indexOf('survey_')>-1) {
element.setAttribute('title', 'Some TITLE HERE');
}
}
}
function replaceBodyElements() {
var tx=document.body.innerHTML;
tx = tx.replace(/dog/ig,'animal');
tx = tx.replace(/apple/ig,'fruit');
tx = tx.replace(/\[VIdEo\]/ig,'Video');
tx = tx.replace(/http\:\/\/example\.com/ig,'http://thelink.com');
document.body.innerHTML=tx;
}
window.onload = function(){
replaceBodyElements();
addTitleToSurveyUrls();
// ... some another operations
};
also
document.onreadystatechange = function () {
var state = document.readyState;
if(state == 'complete') {
replaceBodyElements();
addTitleToSurveyUrls();
}
}​
I've used onload event because maybe document has dynamic elements and etc. so better wait while all elements get loaded and change it.
or You can replace window.onload with window.document.onload

GetElementbyID fails to fire

From my reading here I would expect this code to work, but it doesn't. I have tried two ways to add click events to a button called "lonext". Neither work. I'm not sure why this might be?
window.onload = function() {
var goSC = function() { //go to the sucess criteria section
document.getElementsByClassName("guidance1").style.display = "none";
document.getElementsByClassName("guidance2").style.display = "";
alert("button clicked");
//first try
document.getElementById("lonext").addEventListener("click", function() {
goSC();
}, false);
//second try
document.getElementById("lonext").onclick = goSC;
}
The getElementsByClassName returns an NodeList because you could have many elements in your DOM with the same class, not a single element.
So:
var goSC = function() {
var guidance1 = document.getElementsByClassName("guidance1");
for (var i = 0; i < guidance1.length; i++) {
guidance[i].style.display = "none";
}
var guidance2 = document.getElementsByClassName("guidance2");
for (var i = 0; i < guidance2.length; i++) {
guidance[i].style.display = "";
}
alert("button clicked");
});
window.onload = function() {
document.getElementById("lonext").onclick = goSC;
};
which if you used jQuery could be simplified to:
$(function() {
$('#lonext').click(function() {
$('.guidance1').hide();
$('.guidance2').show();
});
});
I would also strongly recommend you using a javascript debugging tool such as FireBug or Chrome Developer toolbar to inspect your javascript code and see potential errors with it. The Console tab will contain valuable information about possible errors in your javascript code.

Uncaught ReferenceError: X is not defined

This code is being used on a Chrome Extension.
When I call the "showOrHideYT()" function, I get a
"Uncaught ReferenceError: showOrHideYT is not defined | (anonymous
function) | onclick"
This code will search for youtube links in a page, and it will add a button (it's really a div with an event) next to the link to show the iframe with the embedded video, pretty much like Reddit Enhancement Suite. Consider the code, per se, incomplete. I just want to know what am i missing when i call the "showOrHideYT(frameZES12345)" function.
if needed, i can provide manifest.json.
Thanks
function showOrHideYT(id)
{
var YTvidWidth = 420;
var YTvidHeight = 315;
frameYT=getElementById(id);
console.log(frameYT.style.visibility);
if (frameYT.style.visibility == "hidden")
{
frameYT.style.width = YTvidWidth+"px";
frameYT.style.height = YTvidHeight+"px";
frameYT.style.visibility = "visible";
}
if (frameYT.style.visibility == "visible")
{
frameYT.style.width = "0px";
frameYT.style.height = "0px";
frameYT.style.visibility = "hidden";
}
};
// DOM utility functions
function insertAfter( referenceNode, newNode ) {
if ((typeof(referenceNode) == 'undefined') || (referenceNode == null)) {
console.log(arguments.callee.caller);
} else if ((typeof(referenceNode.parentNode) != 'undefined') && (typeof(referenceNode.nextSibling) != 'undefined')) {
if (referenceNode.parentNode == null) {
console.log(arguments.callee.caller);
} else {
referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling );
}
}
};
function createElementWithID(elementType, id, classname) {
obj = document.createElement(elementType);
if (id != null) {
obj.setAttribute('id', id);
}
if ((typeof(classname) != 'undefined') && (classname != '')) {
obj.setAttribute('class', classname);
}
return obj;
};
///////////////////////////////////////
$(document).ready(function() {
var vidWidth = 420;
var vidHeight = 315;
var linksSemID = document.getElementsByTagName("a") ;
for (var i = 0; i < linksSemID.length; i++){
if (/id=$/.test(linksSemID[i].href)) links[i].href += "1";
}
i=0;
var youTubeRegExp = /(?:v=)([\w\-]+)/g;
var forEach = Array.prototype.forEach;
var linkArray = document.getElementsByTagName('a');
forEach.call(linkArray, function(link){
linkArray.id="zes" + i++;
var linkTarget = link.getAttribute('href');
if (linkTarget!=null)
{
if (linkTarget.search(youTubeRegExp) !=-1)
{
console.log (linkTarget);
idVideo=linkTarget.match(/(?:v=)([\w\-]+)/g);
//idVideo = idVideo.replace("v=", "");
//add buton
botaoMais = document.createElement('DIV');
botaoMais.setAttribute('class','expando-button collapsed video');
botaoMais.setAttribute('onclick','showOrHideYT(frameZES'+ i +')');
insertAfter(link, botaoMais);
//add iframe
ifrm = document.createElement('IFRAME');
ifrm.setAttribute('src', 'http://www.youtube.com/embed/'+ idVideo);
ifrm.style.width = '0px';
ifrm.style.height = '0px';
ifrm.style.frameborder='0px';
ifrm.style.visibility = 'hidden';
ifrm.setAttribute('id', 'frameZES' + i);
insertAfter(link, ifrm);
}
}
});
});
When you use setAttribute with a string, the event will be executed in the context of the page. The functions which are defined in a Content script are executed in a sandboxed scope. So, you have to pass a function reference, instead of a string:
Replace:
botaoMais.setAttribute('onclick','showOrHideYT(frameZES'+ i +')');
With:
botaoMais.addEventListener('click', (function(i) {
return function() {
showOrHideYT("frameZES"+ i);
};
})(i));
Explanation of code:
(function(i) { ..})(i) is used to preserve the value of i for each event.
Inside this self-invoking function, another function is returned, used as an event listener to click.
I see that you are using jQuery in your code. I personally think if we are using a library like jQuery, then we should not mix the native javascript code and jQuery code.
You can use jQuery bind to bind your the functions you need to call on dom ready.
Read below to know more.
suppose you want to call a javascript function on a button click, Here is the HTML for the same.
<div id="clickme">
<input id= "clickmebutton" type="button" value = "clickme" />
</div>
suppose "test" is the function you need to call, here is the code for test function.
function test() {
alert("hello");
}
you now need to bind the test function on the button click.
$(document).ready(function() {
$("#clickmebutton").bind("click", function(){
// do what ever you want to do here
test();
});
});

Appending target="_blank" to links in an iframe without using <body onload>

I'm trying to change the links in an iframe to load in a new window instead of the iframe itself. Currently I use this code in head:
$(document).ready(function() {
var oIFrame = document.getElementById("iframeID");
var oDoc = (oIFrame.contentWindow || oIFrame.contentDocument);
if(oDoc.document) oDoc = oDoc.document;
var links = oDoc.getElementsByTagName("a");
for(var i=0; i<links.length; i++) { links[i].target="_blank"; }
});
However, the code above is triggered before the iframe is fully loaded with its contents. I know this code would work if it's triggered in the body onload attribute, but I'd like to avoid that method and implement it in a function or a file instead.
Try
$("#iframeid").load(function(){
// your code
});
Have a go with:
$(document).ready(function() {
var oIFrame = document.getElementById("iframeID");
var oDoc = (oIFrame.contentWindow || oIFrame.contentDocument);
if(oDoc.document) oDoc = oDoc.document;
$(oDoc).ready(function(){
var links = oDoc.getElementsByTagName("a");
for(var i=0; i<links.length; i++) { links[i].target="_blank"; }
}
});
You could set a timeout function periodically checking if
iframe.document.readyState == 'complete'

Adding onclick to div element yields "Result of expression 'document.getElementById('elem1')"[null]

is not an object" in the safari browser. The entire code is
function addLinks () {
var p0 = document.getElementById('Pic0').onclick = addLinkAction;
}
function addLinkAction () {
var el = document.getElementById('vid0');
el.style.display = "block";
el.play();
}
The functions work fine but safari continues to throw errors when the page is rendered and and on each click of the link. I'm only testing this in safari as it's a HTML5 - iPad/iPhone only media. thanks
Try this:
function addLinks () {
var p0 = document.getElementById('Pic0').onclick = function () {
var el = document.getElementById('vid0');
el.style.display = "block";
el.play();
};
}
Make sure the element exists. When you invoke addLinks do it on DOM ready or window.onload = function(){}. Alternatively, put the script before the end body tag.
assuming you call function addLinks() on document load/ready, try to add return false as last statement of this inner function
function addLinks () {
var p0 = document.getElementById('Pic0');
p0.onclick = function() {
addLinkAction();
return false;
}
}

Categories