Ext.Loader.loadScript callback called too soon - javascript

I'm trying to draw a Bing Bird's Eye View map into an ExtJS window. I'd like to load the script just before the window is created, so I'm using Ext.Loader.loadScript like so:
Ext.Loader.loadScript({
url: 'http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0',
onLoad: function () {
console.log(Microsoft.Maps.MapTypeId.birdseye);
}
});
The problem is that the onLoad callback executes before the Microsoft Maps object is fully loaded, so Microsoft.Maps.MaptypeId is undefined. If I open a web console a few seconds later, everything is loaded.
Is this a bug?
Is there another way to delay the callback function until the url and all subsequent scripts have been loaded?

The issue is that when the Bing Maps api loads it downloads several additional files. The initially downloaded file will trigger your onLoad function while the other resources for the Bing Maps control are being downloaded, which is why your onLoad function is firing before the Microsoft.Map namespace is fully functional. There are a couple of ways to handle this. One method is to use a timeout in your onLoad function that, when fired checks to see if the Microsoft.Maps namespace is available and the Microsoft.Maps.Map object is not undefined. If these tests fail, then have the timeout fire again after a short period of time. If they are valid, then call the function you want to run to load the map.
I also put together a blog post about lazy loading the map control here: http://rbrundritt.wordpress.com/2011/11/20/bing-maps-v7-control-lazy-loader/

Related

Manipulate website which has been called from another website with Greasmonkey [duplicate]

This question already has answers here:
Fire Greasemonkey script on AJAX request
(2 answers)
Closed 7 years ago.
I have the following situation:
A website gets data from another html-file("news.html") which gets called every 10s or so
I want to manipulate the data from the news.html
I thought I could set up a greasemonkey script which manipulates the news.html and thus also the main website.
However this assumption was wrong: When I open the news.html in my browser, the news are manipulated (in terms of data - just to clarify this), but when I visit the main website the news don't get manipulated.
I think that greasemonkey does not work when the website is not opened "directly" in the browser, but with ajax/jQuery/....
Is there any known workaround for this?
Thanks in advance!
You can't change files that are on a server with greasemonkey unless the API for some reason leaves that exposed. Whatever you are changing is just local to you.
For simple pages, it's safest to wrap your greasemonkey scripts in at least an unload handler: According to the "Authoring" page at http://greasemonkey.mozdev.org/authoring.html,
User scripts are executed after the DOM is fully loaded, but before
onload occurs. This means that your scripts can begin immediately and
don't need to wait for onload. However, replacing large parts of the
DOM (e.g. using innerHTML or outerHTML) at this early stage of
rendering is known to cause Firefox some trouble. In this case, you'll
have more success if you call your code in response to the load event
instead:
window.addEventListener("load", function(e) {
document.innerHTML = "Hello, world!";
}, false);
However, if the "main site" is constructing itself via a secondary ajax call to news.html, that won't be enough, because the data you want to manipulate won't be in the DOM yet when your script runs on the main site. You'll need to delay your script's execution until after the main site has finished doing its thing, so that when you try to do your thing there'll be the thing there for you to do your thing to. So to speak.
Have your script observe the DOM and wait to run until after news.html has been injected into the main site, or be lazy and start it after a sufficiently-long setTimeout.
(A clarification based on discussion in comments: Greasemonkey will only act on the site that was actually loaded in the browser; it will not act directly on every XHR request that site makes, even if that url was #included in the script. So if site "foo.com" ajax-injects content from "bar.com/news.html", and the browser loaded "foo.com", greasemonkey will not directly modify the "bar.com/news.html" request foo.com made; it can only work with the DOM that foo.com constructs based on what it got from news.html.)

Chrome Extension API not firing onChanged event

I am using chrome.downloads.onChanged.addListener to find out when a download completes.
The callback does not fire sometimes, and there is no apparent reason for it.
The code looks like this
chrome.downloads.onChanged.addListener(function (downloadDelta) {...});
and it is in background.js and file is mentioned in background section of manifest. I added console.log(downloadDelta); at the very begining of callback, but it is not fired.
The API is mentioned here
EDIT: Test extension
Most probably this has to do with peculiarities of Event pages - something not working properly when your page gets unloaded.
This is easy to test - remove "persistent": "false" from the manifest.
That said, your test extension does not violate any Event page recommendations and chrome.downloads API does not list any incompatibilities. Therefore, 2 scenarios are possible:
It's quite possible that you are misinterpreting results due to the page being unloaded. For instance, if the page gets unloaded between the callback executing and you opening the devtools for it - the console and all local state will be wiped.
To test for that, make sure to write your diagnostics to persistent storage - chrome.storage API is one option for this.
If you are 100% sure the above is not the case, there may be a bug related to event pages and chrome.downloads. In that case, it should be reported.

Chrome App messaging and 'loadstop' vs. .load() timing

I am developing a Chrome App with webviews. Pages intended for the webviews may also run in a regular browser. If inside a webview, pages send messages to the main App, but apparently they need to get a message from the App first, in order to know where to send their messages.
No problem - the main App sends a message as soon as it sees a 'loadstop' event which tells the pages where to send messages to. If a page is not in a webview then it never gets the message.
The problem is, I need to know when a page should stop waiting for the message and assume it is NOT in a webview.
When does 'loadstop' occur, relative to events in the page such as jQuery's .ready or .load? Is there a way to trap or trigger an event guaranteed to occur after 'loadstop' MIGHT be seen in the main App and a message sent and received by the webview's JavaScript.
When does 'loadstop' occur, relative to events in the page such as jQuery's .ready or .load?
According to the documentation for the loadstop event:
Fired when all frame-level loads in a guest page (including all its subframes) have completed. This includes navigation within the current document as well as subframe document-level loads, but does not include asynchronous resource loads.
This would suggest it's more akin to jQuery's .ready(), which executes after the DOM tree is loaded, but before waiting for asset (.css, .js) downloads.
Keep an eye on that documentation page; it's already much improved since two weeks ago.
Is there a way to trap or trigger an event guaranteed to occur after 'loadstop' MIGHT be seen in the main App and a message sent and received by the webview's JavaScript?
Your manifest.json declares your my-app-main.js background script (and your webview permission) which launches your my-webview-wrapper.html which includes your <webview> tag and also inlines some javascript (or sources a my-webview-wrapper.js file) that assigns event listeners to your webview via an onload function as such:
onload = function() {
webview = document.getElementById("the-id-attribute-of-my-webview");
webview.addEventListener("<EVENT>", function() {
// the cool stuff you want to do
}
}
<EVENT> can be any of the webview DOM events listed in the documentation I linked (including loadstop). Your main app shouldn't really care that any of this is happening. (It's async! It's javascript! It's magic!)
If you're still confused, just poke around Google's webview sample on GitHub.

Dynamically load google maps api v3 with namespaced callback function

I recently ran across the following problem when lazy loading/dynamically loading the google maps api v3: In order to check whether the api has fully loaded or not, I followed the instructions on google's documentation page. Works fine with a normal function callback name like &callback=initialize in global scope. Also works fine with a function callback that is within a certain namespace like &callback=Namespace.initialize.
Now my function is placed under Namespace.foo[0].initialize ("Namespace" and "foo" are of type object). The problem now is that I can't properly access this function. I tried several ways of building the callback string, each listed below with whatever firebug tells me is not working:
&callback=Namespace.foo[0].initialize
Firebug: NetworkError: 403 Forbidden - <http://maps.googleapis.com/maps/api/js?v=3...&callback=Namespace.foo[0].initialize...>
&callback=Namespace.foo.0.initialize
Firebug: missing ; before statement
Firebug: [Break On This Error] window.Namespace.foo[0].initialize()
&callback=Namespace.foo%5B0%5D.initialize
Firebug: NetworkError: 403 Forbidden - <http://maps.googleapis.com/maps/api/js?v=3...&callback=Namespace.foo[0].initialize...>
I'm thankful for every hint and/or solution!
Background information: What I do might also be interesting. A script is dynamically loading html, css, data and the google maps api into a external webpage (within a web-widget). Now I'm using jQuery's deferred object to queue the different includes such as loading the css/javascript/html first, then receive the data and finally setup the google map within the previously loaded structure. Deferred object performs way better than handling the different steps with callbacks (and much easier too!), but when the jQuery.getScript method is done (loads the google maps api) the success event is fired and deferred.resolve gets returned. Too bad that this probably just handles the authentification (via client-key) and then asynchronously loads the google maps main.js. This pretty much sucks because I need to wait for the api to fully load...

how to fix iframe load never terminating the browser visual spinner and 'Transfer ...' status

I have pages loading json into hidden iframes from javascript.
The Firefox browser seems to never acknowledge fully receiving the iframe content, and reports 'Transferring data from ...' on the status line, and shows the twirly 'busy' icon on the tab, indefinitely.
I am using jQuery to bind the 'load' handlers, and would prefer a solution that does not involve over-riding jQuery functionality.
btw, the load handler does fire, the json received is complete, and the iframe itself gets .remove()d in the cleanup code. The browser still waits for something to signal completeness.
Ben Nadel posted a blogpost on just this topic.
It seems that Firefox acknowledges that an iframe document was completely received only after the onload handler returns. If the iframe is deleted from the DOM within the handler, Firefox never detects completion. The solution Mr Nadel suggested, and which I used, is to use the javascript timer to call a deletion function to run after a brief delay. This allows the handler to return while the iframe persists, but does not let the iframe linger around.

Categories