This might be a stupid question, I cannot find the answer though:
I am animating some shapes in a HTML/JS page displayed by an Android WebView. To do so I use the Javascript setInterval() method:
var animateThreadHandler;
function animateThread() {
// animate some stuff here...
}
// This function is called from the HTML page: <body onload="onBodyLoaded()">
function onBodyLoaded() {
animateThreadHandler = setInterval(animateThread, 200);
}
Later, in the code of my Android Activity this time, I switch from this HTML page to another one, keeping the same WebView:
mWebview.loadDataWithBaseURL(baseUrl, htmlContent, HTML_CONTENT_TYPE, HTML_ENCODING, null);
But I never call clearInterval(animateThreadHandler) from the Javascript. Even though this works well, I wouldn't like to drain the user's battery by doing useless Javascript function calls that would end up in errors that I couldn't see.
I monitored the behaviour of the JS animateThread() function by making it to produce logs (see comments), and the logging stops once the WebView is reloaded. But this doesn't prove the scheduler is cleared: calls to animateThread() may keep occurring - and silentely failing as the JS code was unloaded at Webview reload time.
The rationales behind this doubt reside in what the W3School says:
The setInterval() method will continue calling the function until
clearInterval() is called, or the window is closed.
I neither call clearInterval() nor I "close" the window (I'm just reloading it), so I am really not sure of the underlying behaviour of my code. Any idea?
Related
When I visit the homepage of the Rails website that I'm building, it takes a few seconds to load. Let's say after 2 seconds it has loaded the visuals after which for some reason it's busy for 2 more seconds (I think loading JavaScripts). If I scroll down between second 2 and 4, then after second 4 it automatically pops back to the top of the page. So that's a bit annoying, especially since this happens everytime you visit the homepage (not just the first time you visit it).
After trying to remove various parts of the page I found out the cause. I'm using a website template to develop my website. This template at the top of the homepage uses the following script:
<script type="application/x-javascript"> addEventListener("load", function() { setTimeout(hideURLbar, 0); }, false); function hideURLbar(){ window.scrollTo(0,1); } </script>
When I remove this script the described behaviour is gone. But I don't know what this script does and why it's there. Could someone perhaps advice if it's okay to remove it?
Let's break it down.
First, the code is adding a listener to the window. When the window is loaded it will trigger the function passed to addEventListener.
addEventListener("load", function() {
// Code here will run when the page loads
});
Then the code defines a function called hideURLbar which will scroll to one pixel from the top when called (using window.scrollTo). This appears to be for mobile devices since they show the URL bar until the user scrolls down a little. 1px must be enough. This function is not called immediately, however.
function hideURLbar(){
window.scrollTo(0,1);
}
After loading the page the function hideURLbar is passed to setTimeout with a timeout of zero milliseconds.
setTimeout(hideURLbar, 0);
Using setTimeout with a zero timeout tells the browser to call hideURLbar as soon as it can, but that it should finish whatever else its doing first. This is often used to sort of "kick" things to the background in the browser so they don't interrupt other things the browser may be doing.
The combination of waiting for the load event and using setTimeout means this code isn't triggered until your browser is done loading everything else. By that time if you have scrolled down you will be popped back to the top of the page.
This is poor code and a better approach would be to only execute something like this if the scroll position is at the very top, like this:
function hideURLbar(){
if (window.scrollY == 0) window.scrollTo(0,1);
}
I believe that is a hack for mobile devices. See, when you have a website load on the mobile, the url bar is on the top of the screen and eats up 15% of your space. This (poorly designed) hack make the web scroll automatically just a tiny bit to hide this url bar. You should remove this code, it's plain dirty and will cause some problems, like the one you mention.
This seems to be quite a common way to try and hide the address bar on mobile browsers such as iOS Safari or Chrome on Android. It waits for the page to load and then scrolls down slightly in order to trigger the auto-hide feature most touch device browsers have.
I'm 99.99% sure it doesn't do anything else so if it's causing issues for you, I'd recommend just removing it.
I'm attempting to use a QR code scanner plugin for a project I'm working on, basically I'm modifying the example posted below so that instead of just scanning the code and outputting the string value to the page, I actually want it to physically open the link using the InAppBrowser.
Now whilst the function I've added fires (as far as I can tell) the InAppBrowser doesn't get invoked, however if I click on a link pre-embedded in the index page after trying a scan, it briefly shows the page I had tried to load via scanning before then loading the contents of the pre-embedding link (if that makes sense).
Original Demo https://github.com/wildabeast/BarcodeDemo
My Fork https://github.com/desrat/BarcodeDemo
Any help would be appreciated.
EDIT: Jonus Solution works great, but what if I wanted to move the function out of the alert callback and just open the browser immediately?
I already tried re-placing the alert with
namedFunc(result.text);
and
function(){namedFunc(result.text);};
When you pass namedFunc(result.text) as callback, the function is invoked immediately and actually its result (undefined) is passed.
Try:
navigator.notification.alert(result.text, namedFunc.bind(null, result.text), 'Scan Result', 'ok')
Or:
navigator.notification.alert(result.text, function() {namedFunc(result.text);}, 'Scan Result', 'ok')
UPDATE:
Your second question is hard to answer. Using namedFunc(result.text); should be right. After some testing (with iOS) it seems to me, that the InAppBrowser is opened but not shown, because I can inspect the opened website with Safari. This is quite strange and I have no idea what the reason is. Maybe it has something to do with the closing barcode scanner.
However you can fix it by using a timeout:
window.setTimeout(namedFunc.bind(null, result.text), 1000);
or maybe you prefer:
window.setTimeout(function() {namedFunc(result.text);}, 1000);
This is surely not a really good solution because the user has to wait a second before the browser opens and I can't even guarantee that one second is always enough (e.g. on slower devices), so it's a bit risky.
This may be a bug in internet explorer (IE9), wondering if it is known or there is a workaround.
It can be reproduced by opening up the dev console, and executing each of these commands,
window.onresize = function() { alert("onresize"); }
At this point, when you resize the window, the event fires as expected. Now execute,
document.write("test");
After this point window.resize will be null.
That's probably expected since document.write calls document.open which clears everything.
However, even if you add back an event handler, it will never fire,
window.onresize = function() { alert("onresize"); }
You have to write the whole script block into the new document. For example:
document.write("<div>some html</div><script>window.onsize=function() { alert('onresize'); } </script>
This is because when you call document.write it creates a new document with an "empty" url. Where as your original document comes from a different Url (for example, "http://www.yoursite.com/Page1.aspx". The site for the empty Url is not the same as the site of the original Url. And a browser does not allow script in pages from one site calls script in pages from another site (to avoid cross site script attack). Thus it is not possible for you to call a function defined in "http://www.yoursite.com/Page1.aspx" from a page with null Url. As such you have to write the script code itself into the new document.
I work for a large website. Our marketing department asks us to add ever more web ad tracking pixels to our pages. I have no problem with tracking the effectiveness of ad campaigns, but the servers serving those pixels can be unreliable. I'm sure most of you have seen web pages that refuse to finish loading because a pixel from yieldmanager.com won't finish downloading.
If the pixel never finishes downloading, onLoad never fires, and, in our case, the page won't function without that.
We have the additional problem of Gomez. As you may know they have bots all over the world that measure site speed, and it's important for us to look good in their measurements, despite flaws in their methodology. Their bots execute onLoad handlers. So even if I use a script that runs onLoad to add the pixels to the page after everything else finishes, we can still get crappy Gomez scores if the pixel takes 80 seconds to load.
My solution was to add the pixels to the page via an onMouseMove handler, so only humans will trigger them. Do you guys have any better ideas ?
jQuery and other JavaScript frameworks can help handle the problem by using a method such as the" document ready" function, which fire when the document is ready and don't need to wait for all the images.
I'll quote direct from the jQuery tutorial:
The first thing that most Javascript programmers end up doing is adding some code to their program, similar to this:
window.onload = function(){ alert("welcome"); }
Inside of which is the code that you want to run right when the page is loaded. Problematically, however, the Javascript code isn't run until all images are finished downloading (this includes banner ads). The reason for using window.onload in the first place is due to the fact that the HTML 'document' isn't finished loading yet, when you first try to run your code.
To circumvent both problems, jQuery has a simple statement that checks the document and waits until it's ready to be manipulated, known as the ready event:
$(document).ready(function(){
// Your code here
});
You could use this event to load those problematic images.
See this link for further info.
http://docs.jquery.com/Tutorials:How_jQuery_Works
I also work for a large website and here is what we did:
Moved the ad calls to the bottom of
the page, so the content would show
up first (because JS is
synchronous).
Loaded the ads using Ajax Calls (to
allow the page to be usable while
the ads are loading) into a hidden
element.
The position is moved to the correct
place in the DOM and "unhidden."
Depending upon the page, we either
wait for the ad to finish loading
before move the position, or we move
the position immediately.
I've rewritten my family web site using JavaScript (JQuery) making Ajax calls to PHP on the back end. It's your standard "bunch of image thumbnails and one main image, and when you click on a thumbnail image the main image changes" kind of thing. Everything is working as expected when using Firefox, but on IE, when I click on a thumbnail, the main image changes to the one I clicked and then immediately changes back to the first one. I have tried MS Script Debugger to no avail; I set a breakpoint in the JavaScript code that starts the Ajax call, and when I click the thumbnail the breakpoint fires. Then I hit F5 and it continues but does not fire again. If I use Wireshark to watch the actual TCP packets over the network, I can see that we are definitely sending more than one request to the server. I cannot figure out where the second query (the one to revert back to the original image) comes from.
Any suggestions? One example of what I'm talking about is here.
Debugging through your site here's what it looks is happening:
After the first image is pocessed, the resize event is being thrown, so this code gets called:
$(window).bind("resize", function(){
ResizeWindow( 'nicholas-1' )
});
which as you know reloads your gallery. Now I can't tell you why this is occurring but this is where the trouble starts.
For future reference to debug this I used VS2008 to attach to IE. I then put a break in $ajax() at:
// Send the data
try {
xhr.send(s.data);
} catch(e) {
jQuery.handleError(s, xhr, null, e);
}
Then I simply hit F5 which is run for the first two ajax calls, then I open up the call stack window when I found the rogue ajax call and walked the call stack back up to the function I posted earlier.
Good luck.
You could use Fiddler, a free debugging proxy for Internet Explorer. It was a great help for me many times when I had to debug specific,server-related problems on IE.
Here is an Introduction to Fiddler on MSDN.
alt text http://i.msdn.microsoft.com/Bb250446.ie_introfiddler_fig04(en-us,VS.85).gif
IE is a piece of work, isn't it? Have you tried something like this?
var inProcess = 0;
function eventHandler() {
if (inProcess == 0) {
inProcess = 1;
// do stuff
setTimeout('inProcess = 0', 5000);
}
}
Cute kid, by the way.