Javascript SetInverval() fireing only once in Firefox [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
setInterval not working (firing only once) in Google Chrome extension
This error only is a problem when document.write() is used.
I am on Mac 10.6.8 Intel.
Here is my script:
setInterval(function(){myFun()},1000);
function myFun() {
document.write('something');
}
The behavior is different in various browsers:
Firefox 12: Only happens once. The browser says "connecting" in the status bar.
Google Chrome and safari: Seems to work correctly.
Note: using setTimeout instead causes everything to behave like firefox (not working).
Using setInterval(myFun},1000), which is supposedly the source of so much error, behaves identically.

Many beginning tutorials use document.write() for "hellow world". However, this funciton is dangerous because it may mess up the script (by nuking the entire program). Here is a safe way to do debug printouts:
Before the script, in between the and in the html, add this:
<div id="myDebug"></div>
In the script, first convert it to a variable that can be called upon:
var myDebug = document.getElementById("myDebug");
When you need to show something, do this:
debug.innerHTML = "some string";
This will show the string in the browser window.

try this:
setInterval(function(){myFun()},1000);
function myFun() {
// Return all elements in document of type 'body'
// (there will only be one)
var bodyArray = document.getElementsByTagName('body');
// get the body element out of the array
var body = bodyArray[0];
// save the old html of the body element
var oldhtml=body.innerHTML;
// add something to the end
body.innerHTML=oldhtml+"somrthing";
}
As others have mentioned, using document.write() will (in some browsers) nuke the script used to update the document, writing to the body (and not the head, where the javascript should be stored) will stop this from happing.

Seems that you miss the semicolon after myFun()
setInterval(function(){myFun();},1000);
function myFun() {
document.write('something');
}
Also make sure you put the function in <body></body>

document.open() results in clearing the document. This function gets called by Firefox before document.write(). Thus your interval is lost.
see W3C Document Object Model HTML

Related

Workaround for IE's document.all.table.rows() 'function'

I have a script on a website that has been coded for IE. I can't edit the original script, so i'm trying to alter it through js and Jquery (by using a Chrome Plugin).
The script uses next line to add a row to an HTML-table, but gives errors in Chrome:
document.all.tbl.rows(i);
after some research I found out this is a function only used in IE. In Chrome an array is used.
So all these lines should be altered to the following:
document.all.tbl.rows[i]
The same problem occurs with rows[i].cells().
I've tried moving the array to rowsData and overwriting rows to a function retrieving the data from rowsData.
document.all.tbl.rowsData = document.all.tbl.rows; // This seems to work
document.all.tbl.rows = function(id) {
console.log('This function is used');
}
After checking with Chrome's devtools, I've found that rowsData does contain a copy of rows, but rows is still an array. When using document.all.tbl.rows() I still get the same error:
Uncaught TypeError: document.all.tbl.rows is not a function
The only other option is replacing the entire function (which is quite long, and not preferred because there's always a probability it can change).
I'm guessing that overriding a browser variable isn't possible.
Is there some way I can make this work?

Invoke javascript class function in firefox addon

I needed xpaths generated by Firepath (Firebug extension), to be passed to my native JavaScript class object present in DOM. So, I am modifying Firepath extension itself, now to pass the generated xpath to my JavaScript class function present in DOM, I can't figure out a way. I tried many solutions like inside the extension function, the following example works:
window.alert("hello");
But the following doesn't:
var pObj = new window.wrappedJSObject.PClass();
alert(pObj);
pObj.CalledFromAddOn();
Any help will be highly appreciated.
After doing some hard work I finally got it working, the document and window objects in Firefox extension refer to different document and window objects and not the DOM (should be obvious), so we need to find the current window to execute the function or class function, whatever. So, here is the code snippet, which you can use in your extension to invoke DOM javascript:
var doc = Application.activeWindow.activeTab.document;
var win = doc.defaultView; // will give you the DOM window object atleast on firefox and chrome
// Now call your functions or create objects
win.wrappedJSObject.hello();
var pToolObj = new win.wrappedJSObject.PTool();
alert(pToolObj.currTaskNo);

JS bookmarklet issue: Code works in console, fails in bookmarklet

Using a JS bookmarklet to set a custom field in the Wordpress Edit Post screen. The following code works well when I copy/paste it into the console (latest Chrome stable):
document.getElementById('metakeyselect').value = "foo";
document.getElementById('metavalue').value = "bar";
document.getElementById('meta-add-submit').click();
Works without a hitch; I jut paste this into the console, and a new custom var is added to the post (I have "foo" as a var name in WP already).
In bookmarklet form, this same code looks like this:
javascript:document.getElementById('metakeyselect').value = "foo";document.getElementById('metavalue').value = "bar";document.getElementById('meta-add-submit').click();
And it fails: When I click it, the Name and Value boxes are filled in, but nothing gets submitted. The console shows the following error:
Uncaught TypeError: Cannot call method 'click' of null
Any idea why? Same exact code, same browser, same page.
I had a similar problem and am quite sure that's what causes your code to break too.
My minimal example would be the following code on this website (should work afor the entire stackoverflow.com domain):
document.getElementsByName("q")[0].value="foo";
This should write "foo" to the search field (that has no id but is the only element with the name "q"). Both web console and bookmarklet will set the value as expected but the bookmarklet will also change the page to an empty header and a body containing only the word "foo" after a short delay. Assuming that this is not a random bug that only applies to me, the reason for the thrown exception in your example is that the bookmarklet sets the value "foo", then "bar" but changes the content of the web page to "foo", then "bar" before your last line terminates.
Unfortunately I don't know the reason for this behaviour (I found this question looking for that exact information) but that is what most likely causes the TypeError in your excample.
It is possible that the same code runs without any problems when used in a Greasemonkey script (e.g. as the onclick script of a button you added using Greasemonkey).
[Edit:] Apparently, if a bookmarklet evaluates to anything other than undefined, the inner html of the website is replaced by a string representation of that value. To make sure that the bookmarklet evaluates to undefined, you can just type undefined as the last line outside of any condition block. unfortunately that means it is less likely that my assumption toward OP's error is correct but at least future visitors still might find this information usefull.
It looks like the code you use in console works ok.
It seems like the method you turn console code into a bookmarklet is what might result into an error.
The basic IIFE-construction, i.e. Immediately Invoked Function Expression, looks like this:
javascript:(function () {
/*code here*/
})();
Therefore, the code that is supposed to work might be this.
javascript:(function () {
document.getElementById('metakeyselect').value = "foo";
document.getElementById('metavalue').value = "bar";
document.getElementById('meta-add-submit').click();
})();
Does it solve your problem?

Convert a command from Javascript to Greasmonkey

I am trying to add a character counter to a page, on this page i enter in three values and it returns a large string in the innerHTML of a div with the ID of 'AnswerBoxID', now i want my script to obviously count the number of characters in it to do this i have written
var submit=document.getElementsByClassName('Row3');
function countChars(){
count = document.getElementById('AnswerBoxID').innerHTML.length;
document.title ="Chars "+count+"/160";
}
Which returns a ROUGH approximate of the chars, when i then paste it into an editor or something else that counts chars i get a different result again, counting with this method gets within 5 chars of what other things are reporting (specifically notepad++).
BUT my biggest problem is I have been unable to get countChars() to update
when the value of document.getElementById('AnswerBoxID').innerHTML updates, in javascript I overcame that using the following code
var submit=document.getElementsByClassName('Row3');
for (i=0; i<submit.length; i++){
submit[i].firstChild.setAttribute('onclick','countChars()');
}
After reading GM Pitfalls 2 i then modified my approach to the following
for (i=0; i<submit.length; i++){
submit[i].firstChild.addEventListener('click',countChars(),true);
}
But it still doesnt work!
And before anyone asks yes I do define the count variable before the function. I don't really mind the mostly accurate length thing I would prefer it to be more precise but I do really want to add onclick elements that run countChars() to the submit buttons.
You seem to add the event handler wrong.
elm.setAttribute('onclick','countChars()');
would set an attribute, and eval 'countChars()' in the global scope when the element is clicked. Yet, Greasemonkey scripts run sandboxed to their own global object, and your declared function "countChars" is not available to the eval.
elm.addEventListener('click',countChars(),true);
executes the function immediately and adds the return value as a handler. To make it work, just remove the brackets and pass the function itself. See also element.addEventListener
Greasemonkey scripts run sandboxed. That means, the script runs in the page's onload event then is removed. Calling your Greasemonkey script's countChars() function when the form is submitted will return an undefined error, as your function object is no longer present in the DOM.
Here's my simplified contentEval function (based on GM wiki's Content Script Injection's function):
function contentEval(source) {
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.textContent = source;
document.head.appendChild(script);
}
You can also set the text property instead of textContent for compatibility with older IE versions, thanks RogG!
Put that function in your GM script, it will serve to append any function you need to user later to the DOM's head.
Pass your countChars function as a parameter to the contentEval function:
contentEval(function countChars() {
var count = document.getElementById('AnswerBoxID').textContent.length;
document.title ='Chars '+count+'/160';
});
This way, your countChars function will be placed inside a script element appended to the document's head, which will be accessible after the GM script's execution time ends.
If you want to check a demo of the code above, use a DOM Inspector in this fiddle. It creates a new script element which is appended to the (in JSfiddle's case, the iframe's) document's head, meaning it will be accessible whenever you need it.
You could also simply attach the function to the unsafeWindow, but you should avoid using unsafeWindow unless strictly necessary, and note that unsafeWindow is not supported in Google Chrome.
Use this page for reference: http://wiki.greasespot.net/Content_Script_Injection
Also use the .textContent method to get the text content of an element (and its descendants) as noted by RobG.
In GreaseMonkey, you should be able to use:
var count = document.getElementById('AnswerBoxID').textContent.length;

IE Object doesn't support this property or method

This is probably the beginning of many questions to come.
I have finished building my site and I was using Firefox to view and test the site. I am now IE fixing and am stuck at the first JavaScript error which only IE seems to be throwing a hissy about.
I run the IE 8 JavaScript debugger and get this:
Object doesn't support this property or method app.js, line 1 character 1
Source of app.js (first 5 lines):
var menu = {};
menu.current = "";
menu.first = true;
menu.titleBase = "";
menu.init = function(){...
I have tested the site in a Webkit browser and it works fine in that.
What can I do to fix this? The site is pretty jQuery intensive so i have given up any hope for getting it to work in IE6 but I would appreciate it working in all the others.
UPDATE: I have upload the latest version of my site to http://www.frankychanyau.com
In IE8, your code is causing jQuery to fail on this line
$("title").text(title);
in the menu.updateTitle() function. Doing a bit of research (i.e. searching with Google), it seems that you might have to use document.title with IE.
Your issue is (probably) here:
menu.updateTitle = function(hash){
var title = menu.titleBase + ": " + $(hash).data("title");
$("title").text(title); // IE fails on setting title property
};
I can't be bothered to track down why jQuery's text() method fails here, but it does. In any case, it's much simpler to not use it. There is a title property of the document object that is the content of the document's title element. It isn't marked readonly, so to set its value you can simply assign a new one:
document.title = title;
and IE is happy with that.
It is a good idea to directly access DOM properties wherever possible and not use jQuery's equivalent methods. Property access is less troublesome and (very much) faster, usually with less code.
Well, your line 1 certainly looks straight forward enough. Assuming the error line and number is not erroneous, it makes me think there is a hidden character in the first spot of your js file that is throwing IE for a fit. Try opening the file in another text editor that may support display of normally hidden characters. Sometimes copying/pasting the source into a super-basic text-editor, like Notepad, can sometimes strip out non-displayable characters and then save it back into place directly from Notepad.

Categories

Resources