Browser-independant workaround for onload event -- making sense? - javascript

I have recently found myself playing around with events, and as there is no standard for the event indicating that a page has been loaded (like onload vs. pageshow) I wondered whether something speaks against simply putting some JavaScript at the end of the page. This code would then be executed when the page is loaded.
In this example I would add a keyUp listener to the (input) element identified by iText and assign it to the function updateText(event) (the event object will be passed on to this function).
<html><head></head><body>
<!-- content -->
<script type="text/javascript">
document.getElementById('iText').onkeyup = updateText;
</script>
</body>
</html>
Sample page here:
http://kb.granjow.net/JavaScript/onload.html
Tested in Firefox 3.5, Opera 10.10, IE 6, IE 8, working everywhere.
So, is this good or did I miss something?
Looking forward to your answers.

This would be fine for basic pages. However, if your script dealt with images that hadn't finished downloading or results from ajax requests you might run into trouble. If you're handcoding things, something like this should work:
function registerEvent(el, event, func, bCapture)
{
if (el.attachEvent)
el.attachEvent('on'+event, func);
else if (el.addEventListener)
el.addEventListener(event, func, bCapture);
}
Otherwise, the various JS libraries each have their own implementation such as jQuery's $(document).ready().

That sounds good. There's no reason to not do it that way, as long as your script is at the end of the page. As a matter of fact, ASP.NET uses this method to load it's scripts.

Related

JavaScript preventDefault also block flash scroll event in Chrome

My colleague who is responsible for Flash asks me help him block document scroll default action.
And I add the following code to help him.
<script type="text/javascript">
(function (document) {
var cancelscroll = function (e){
e.preventDefault();
};
if ('onmousewheel' in document) {
document.getElementById('container').onmousewheel = cancelscroll;
} else {
document.getElementById('container').addEventListener('DOMMouseScroll', cancelscroll, false);
}
})(document);
</script>
It works well in IE9 and Firefox, but it also blocks Flash scroll event in Chrome.
I think it is weird, the snippet should only block JavaScript event, why it also blocks Flash event.
My colleague said he registers scroll event by this snippet:
stage.addEventListener(MouseEvent.MOUSE_WHEEL, mask_wheel);
He only get the delta value in the callback, without doing other task.
I'm not familiar with Flash, and my colleague isn't familiar with JavaScript...
Anyone has this problem, too? How to fix it? Thanks.
After three days of brainstorm I finally found the solution (this problem was of utmost importance for me)
I created a small lib that helps you to take care of this "bug" in chrome browser:
Github repo
It's almost just like MouseWheelTrap, you have to call .init() function, which now requires one additional parameter - your flashObject id or name. See repo README for more info.
So here's my solution:
We listen to the scroll event in our browser and when it happens AND we have chrome browser, we call an internal function in flash which imitates user scroll (we manually dispatch an event right onto the stage) BEFORE we call event.preventDefault() function in our JS script. If we have a different browser it just calls event.preventDefault() (or returnValue = false for IE) to prevent double event lag in flash.
Cheers!

document.body.addEventListener is not working

I'm working on a screen reader project and I needed to get the paragraph under the cursor. To do that in Firefox, I wrote an extension, to which my screen reader connects through sockets and gets the text. I needed to get the current element under the cursor and the function worked fine in a sample html page written by myself (So there is no problem with the function).
But when I try to attach the function to my JS file in the extension, It seems that the function which is called by "document.body.addEventListener('mouseover',myfunc(mEvent),false);" is never called.
But if I call
document.body.addEventListener('mouseover',function(mEvent){...},true);
myfunc is called.
I'm new to javascript, so excuse me if it's a stupid question, But why the
document.body.addEventListener('mouseover',function(mEvent){...},true);
is not working?
I always appreciated your nice helps and ideas. :)
While this isn't a direct answer to your question, I hope that it is helpful nevertheless. Using an extension for a screen reader is unnecessary, in particular you might not want to update that extension regularly as the browser's user interface changes. Firefox supports a number of accessibility APIs which you can use directly from your application. These APIs have the advantage of being stable, once your implementation is done it should continue working (as far as I remember there was only one occasion where Mozilla broke compatibility with existing screen readers).
As to the actual question: you didn't tell anything about the context in which this code is executing. Normally, extensions run code in their XUL overlay meaning that the context is the browser window, not the web page. Which would explain why your code isn't working (it's a XUL document, no document.body there). What you probably mean is attaching an event listener to the <tabbrowser> element where the web pages are loaded: gBrowser.addEventListener(...). Side-note: If you really wanted to catch all events on a XUL document you should register an event listener on document or document.documentElement.
Btw, you can see error messages related to extensions in the Error Console (the article I link to explains how to enable it in the current Firefox versions).
There may be other issues here, but the syntax of your addEventListener call is incorrect and could be causing the issue you are seeing:
document.body.addEventListener('mouseover',myfunc(mEvent),false); is actually invoking "myfunc" at the same time you are invoking addEventListener and passing it as the second parameter.
You should instead be calling it this way:
document.body.addEventListener('mouseover',function() { myfunc(mEvent) },false);
Add height to a body element.
<html>
<style>
.vh {
height: 100vh;
}
</style>
<body class="vh">
<script>
document.body.addEventListener('click', () => {
console.log('mouse click');
});
</script>
</body>
</html>
I suspect that the document is not yet ready, so there is nothing to bind to. Try adding an onload="addMyEventListener();" to your <body> and see if that fixes things up. I don't know the proper way to time things, so maybe someone else can chime in with the best way to handle this.
following Wladimir Palant's advise, the follow is working:
document.addEventListener('click', function() { ... }, false);
I also had the same problem and now solved it. After closing tag, try adding an document.body.addEventListener. Parser didn't recognize DOM object of the "addEventListener" event because HTML tag of DOM object is not closed.
Refer to following. It works well.
<html>
<body>
...
</body>
<script type="text/javascript">
document.body.addEventListener('click', function() { ... });
</script>
</html>

Dynamically created iframe used to download file triggers onload with firebug but not without

EDIT: as this problem is now "solved" to the point of working, I am looking to have the information on why. For the fix, see my comment below.
I have an web application which repeatedly downloads wav files dynamically (after a timeout or as instructed by the user) into an iframe in order to trigger the a default audio player to play them. The application targets only FF 2 or 3. In order to determine when the file is downloaded completely, I am hoping to use the window.onload handler for the iframe. Based on this stackoverflow.com answer I am creating a new iframe each time. As long as firebug is enabled on the browser using the application, everything works great. Without firebug, the onload never fires. The version of firebug is 1.3.1, while I've tested Firefox 2.0.0.19 and 3.0.7. Any ideas how I can get the onload from the iframe to reliably trigger when the wav file has downloaded? Or is there another way to signal the completion of the download? Here's the pertinent code:
HTML (hidden's only attribute is display:none;):
<div id="audioContainer" class="hidden">
</div>
JavaScript (could also use jQuery, but innerHTML is faster than html() from what I've read):
waitingForFile = true; // (declared at the beginning of closure)
$("#loading").removeClass("hidden");
var content = "<iframe id='audioPlayer' name='audioPlayer' src='" +
/path/to/file.wav + "' onload='notifyLoaded()'></iframe>";
document.getElementById("audioContainer").innerHTML = content;
And the content of notifyLoaded:
function notifyLoaded() {
waitingForFile = false; // (declared at beginning of the closure)
$("#loading").addClass("hidden");
}
I have also tried creating the iframe via document.createElement, but I found the same behavior. The onload triggered each time with firebug enabled and never without it.
EDIT:
Fixed the information on how the iframe is being declared and added the callback function code. No, no console.log calls here.
Old question but for future reference:
As far as my experience onLoad is not called for file downloads. A way to solve it is to use cookies like they do here http://gruffcode.com/2010/10/28/detecting-the-file-download-dialog-in-the-browser/
Here's an example that works for me, without Firebug open (tested in FF 3.6.2 Mac): http://www.jsfiddle.net/Kukry/
I'm using the jQuery .load() event instead of onload.
var iframe = $("<iframe/>").load(function () {
alert("loaded");
}).attr({
src: "http://code.jquery.com/jquery-1.4.2.min.js"
}).appendTo($("#thediv"));
Note that I'm loading a JavaScript file, not an audio file, so that might make a difference.
Maybe you call some Firebug internal function, like console.log(), somewhere? In that case, Firefox will threw an exception which can stop the execution if Firebug is not active.

Event listeners on plugin in document.onload events in Opera

I am trying to understand an issue where event-listener registration on plugins doesn't work in Opera unless I delay them.
In particular, this doesn't work:
document.onload = function() {
plugin.addEventListener("foo", function() { alert('onFoo'); }, false);
}
while delaying the addEventListener() call somewhat through e.g. an alert() does:
document.onload = function() {
alert('onload()');
plugin.addEventListener("foo", function() { alert('onFoo'); }, false);
}
It seems that plugins are only loaded after document.onload.
As a non-web-developer, am I missing something simple here? Or is this a known Opera problem with a common work-around?
in general the timing of plugin initialisation, script execution and document event handling isn't well specified, meaning browsers are likely to do different things.
In this case it sounds like you need to make sure the plugin is initialised before you add the listener. One way to do that would be to check for a property the plugin will define (for example, if it was a Flash plugin you could check if PercentLoaded was defined to see if it is ready for scripting.) If not ready for scripting, you could use a timeout to try again a little bit later.
At Opera we've been trying to align with the majority of the other browsers in this area recently, and Opera 10.50 may be working better for you. I'm not sure if we have things fully under control yet though - it would be interesting to hear from you whether behaviour changed in 10.50.
We have further improved handling of this in Opera 10.60, so that behavior is much closer to the other browsers wrt. plug-in initialization and script readyness. I believe the original approach should work now.
I don't know much about Opera but have you tried using jquery's ready function? It's purpose is to add a function you want executed once the DOM is fully loaded and it should work cross browser.
$(document).ready(function() {
plugin.addEventListener("foo", function() { alert('onFoo'); }, false);
});
More info about the ready function can be found here

IE fails, when calling functions from external javascript?

I have a piece of code that can be simplified to this:
var s='' ;
s += "<"+"script type=\"text/javascript\" src=\"http://somehost.com/scripts/FooFunctions.js\">\n";
s += "<"+"/script>" ;
s += "<"+"script type=\"text/javascript\">\n";
s += "FooFunction(42, 'i love cats');\n";
s += "<"+"/script>" ;
document.write(s) ;
In all browsers except IE, this executes as you'd expect - functions from somehost.com/scripts/FooFunctions.js work as expected.
In Internet Explorer, this fails.
Googling this seems difficult. I've found the occasional post witht the same problem, but no solution.
(There is a valid reason that the external file needs to be included from javascript this way, and that the pgae can not have a <script src="http://somehost.com/scripts/FooFunctions.js"> inserted in it.)
To be clear, the question is: How can I make the above piece of code function the same in Internet Explorer as it does in e.g. FireFox?
Try this, it works in IE
function addJsFile(jsFileLocation){
var script=document.createElement('script');
script.type='text/javascript';
script.src=jsFileLocation;
document.getElementsByTagName("head")[0].appendChild(script);
}
addJsFile("http://code.jquery.com/jquery-latest.pack.js");
setTimeout(function(){alert(jQuery);},1000);
It looks like IE is calling FooFunction before the script is loaded. You can test this by using setTimeout("FooFunction(42, 'i love cats')", 1000); assuming one second is enough time for the script to load, this call will succeed.
If you can't use a framework like jQuery to load the scripts, which will provide you with a callback when the script loads, you might be able to hack your own with setInterval, checking for FooFunction
As soon as the document.write call is complete it will run the function in the second script tag. Regardless of whether or not the external script has loaded yet. This should not just be an IE problem but should effect all browsers. Are you sure that it is not effecting other browsers as they have the external script cached? What happens when you clear your cache and try again in another browser?
Anyways, in an ideal world you should just be able to use .onload on the script tag but I'm 99% sure that there is problems with onload not firing on script tags in IE6 so we need to resort to using onload on the window element instead. This will event will not fire until all scripts have been downloaded including external js files like above.

Categories

Resources