in my Javascript code I am loading a page, and then would like to perform some functions. I tried to use solutions like window.onload, but that is after my html (blank page with just the JS) loads, I need the function to perform after the page I am reffering to is loaded.
I am using this code:
this.document.location.href = myurl;
And after this loads, I would like to call some function. Is there a way to do so?
Thanks
EDIT:
I can not edit the target page source code.
When you change the value of document.location.href, you are essentially doing a redirect.
You can either just do whatever you want to do within the loaded page itself or if you don't have cross domain issues, do xhr of the page you're wanting to load dynamically, query the body, replace content of your current body and also replace head contents i.e. style, title and scripts etc. You could then execute any script you want.
Extra note: This is quite a tricky thing to do, I've done this a few times before - and its proven quite problematic due to the fact that you don't actually get a fully parsed document object that you can just query so simply, you only receive a huge string. One hack that I've thought of using is actually just loading everything within an iframe allowing easy querying which is actually documented - extra reading here
window.load takes forever to fire because it waits for all images and assets to load on the page.
It sounds like the best solution for you would be to poll for the document to be finished loading. Here's a simple example:
(function poll(){
if(document.readyState === "complete"
{
// Your code here
}
else
setTimeout(poll,500);
})();
Place the 'window.onload = myFunction(){...}' inside the page, which will be loaded.
this.document.location.href
will open the page like you typed it into the browser address bar and your onload-script in the old page will not be executed in the new one.
By the way, you can shortcut it to document.location = myUrl
See the Document-API at Mozilla
Related
I'm creating a chrome extension that needs to hook into another script that already exists on my target web page. For simplicity's sake, I'm trying to find the following existing script element on a page and add a console.log() to it.
<script type="text/javascript">
var viewModel = new ScenePlayViewModel('', 'Ace', false);
viewModel
.load('jgWJJ2qsxx')
.then(function () {
sceneDOM = new SceneEditDOM2(viewModel.scene());
sceneDOM.init();
viewModel.isSubmitViaShareUrl(false);
viewModel.isSubmitViaUnityPackage(false);
console.log("HOOK INJECTED"); <--------------------------------------------- line to add
});
</script>
I've tried a number of solutions but none of them have seemed to work. For example, I've tried using a content script to find the script and replace the text, but it appears to run the pre-change script instead of my modified code.
// replaces javascript on website, but doesn't run new version
var scriptLoadScene = $("script:contains('new ScenePlayViewModel')"); // find the script
scriptLoadScene.text("console.log('Hello World')"); // change the text
What should I do? Basically, I'm just trying to change/add scripts to the web page to add more features.
This doesn't exactly answer your question, but hopefully will help you find a solution.
First - hopefully someone with more knowledge than me will confirm or discredit this - from my understanding, the script code is only run once, on page load, unless otherwise triggered by some event. Since Chrome extensions are triggered after the page has loaded, this script will have already been run, and anything inserted after won't run unless triggered.
I suppose you could always call the function again after you've edited it, but I don't have the knowledge or experience to predict what would happen then.
In my experience, I've just added my own '' tags with the code I wanted to run by writing them into the DOM, either into the '' or '' element.
Best of luck.
-brent
Please Help.
Question: Can I dynamically load a JS file (/scripts/banner.js) and then use one of its functions -- writeBanner(document, t1, t2, t3) -- to finish writing the page?
I've read till my eyes bleed, but:
-- Every example I find assumes the reader will call a function AFTER the page is rendered, and
-- Every example assumes blocking is bad.
Unfortunately:
-- I need to call the functions in order to finish writing the page that loaded them, and
-- Blocking is not a problem. The app is deployed as an EAR file, so no JS files need thereafter be downloaded from anywhere else.
Why try to do this?
The initial window ("TAPP") loads a dozen functions from 6 JS files. All pages use them to write HTML in the page's body element that displays a consistent banner with up to 3 paramaterized title lines.
Level-1 Pages: These are opened in the initial ("TAPP") window by each other. It already has all functions loaded – works perfectly.
Level-2 pages: These are opened in pop-up windows opened by level-1 pages. They use "this.opener", i.e. "TAPP" to call those functions – works perfectly.
Now I want to be able to open Level-2 pages both
-- as pop-ups from a level-2 page, AND
-- as free standing pages.
NOTE: All level-2 pages.jsp being with this include to write the HEAD element:
<%# include file='/jsp-pages/level-2/headers/beg.jsp' %>
That way I only need to deal with scripting for all of them, in one place, at one time.
First Step: I added this code to beg.jsp:
<script language="javascript">
var SH = "";
if (this.opener && this.opener.name == "TAPP") {
SH = this.opener; // TAPP has all required functions
} else {
//Dynamically add the required <script> elements
/************************************/
// see code I tried below
/************************************/
SH = this; // "this" now has all the functions TAPP has
// alert ("Opener is NOT TAPP: " + SH);
}
// All pages can now call SH.writeBanner(document, t1,t2, t3) with their own titles
</script>
Here's the rub. When the alert () function above is uncommented BOTH tries (DOM and document.write() below) work perfectly. When it is commented out, level-2 pages opened as pop ups work perfectly BUT when opened as free standing pages do NOT write their titles. Obviously they are being rendered before the script is loaded.
My Tries to date:
-- Give up! Skip the code above. Hard-code six additional tags in "/jsp-pages/level-2/headers/beg.jsp" that will reload the functions in the six JS files every time any level-2 page is opened Either way.
Ugly, inelegant, redundant, a waste if the page is opened as a pop-up, to be avoided at all cost.
-- When TAPP is not this.opener, use DOM to load the JS files by adding script elements at the end of
<script type="text/javascript">
function dynamicload(){
var head = document.getElementsByTagName("head")[0];
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.setAttribute("src", "/scripts/banner.js");
script.async = false; // halt rendering until writeBanner() is loaded?
head.appendChild(script);
//alert ("DL Done");
}
dynamicload();
</script>
-- When TAPP is not this.opener, use document.write() to write the six scripts.
<script type="text/javascript">
document.write('<SCR'+'IPT src="/scripts/banner.js '><\/SCR'+'IPT>');
// and six more like it
</script>
So HELP!
Is it really NOT possible to use dynamically loaded functions to finish writing the page that dynamically loaded them?
glb
You can add things to the current page using dynamically loaded code. But, you cannot use document.write() to do so. You must add DOM elements directly to the page with methods like .appendChild() or .insertBefore() or set .innerHTML on an existing DOM element.
The problem with document.write() is that once the page had been loaded (and thus the document stream closed), any future calls to document.write() will clear the current page and start writing to a new, blank page which general ruins what you are trying to do.
And, when you dynamically load code, it will load AFTER the current document has finished loading.
document.write() is intended to insert content at the current location in the document stream while the document is in the process of loading which only works when the script is present in the original HTML either as a <script> tag or it can be used on a brand new document (such as the creation of a new iframe or new window).
Simple answer. You can't.
A page cannot load JS files with functions it needs to write the rest of the page.
No matter how you script to load the JS files -- add a script element with DOM, or write it in with document.write() -- the JS files end up being loaded AFTER the page is loaded when it is too late to write the page. (See discussion with nothingnecessarey.)
However, it still bothers me that if I throw an alert() in my the script, both conditional approaches work – DOM and document.write() -- i.e. I had titles! All I can think of is the alert causes the page to re-render itself and since the alert is called after the page is loaded, the JS files are loaded.
Thanks to all for their help
AFTERTHOUGHT: I dreamed that opening an empty page with an iFrame to load my level-2 might work. If so I'll return. If not ... I give up.
I've been searching for a while now, but I can't figure out how to load an entire page via AJAX and still execute all javascript and css.
Mostly I just end up with the plain text without any CSS.
Is there a way to do this? I tried jQuery.get, jQuery.load and jQuery.ajax, but none really work like that.
I have a different solution. You may try it with an iframe. Use jQuery to append an iframe script including all relevant codes into some part of your page (like some div). This may do it for you including CSS, like;
$('<iframe src="your_page.html"/>').appendTo('#your_div');
Or you may try something like;
$('<iframe src="your_page.html"/>').load(function(){
alert('the iframe is done loading');
}).appendTo('#your_div');
I have solved similar problem as following.
Download the webpage over ajax
Iterate it over and find any <script> and </script> tags
Get content from within these tags as text
Create new <script> element and insert there the code
Append the tag to your webpage
Another thing is you will need to somehow call the script..
I have done it this way:
I set standardized function names like initAddedScript callback which I am calling after appending the script to the page. Same as I have deinitScript called when I do not need the code (and its variables,..) anymore.
I must say this is awful solution, which likely means you have bad application architecture so as I have had:)
With css is it the same, but you do not need any handlers. Just append the style tag to your documents head.
If the page you load doesn't have any style data, then the external stylesheets must have relative paths that are not correct relative to the invoking document. Remember, this isn't an iFrame - you aren't framing an external document in your document, you're combining one document into another.
Another problem is that loading your complete page will also load the doctype, html, head, and body tags - which modern browsers will cope with most of the time, but the results are undefined because it's not valid HTML to jam one document into another wholesale. And this brings me to the third reason why it won't work: CSS links outside of the head section aren't valid, and the misplaced head section caused by your haphazard document-in-document collage.
What I'd do for compliance (and correct rendering) is this, which would be implemented in the Success callback:
Copy all link elements to a new jQuery element.
Copy the contents of all script in the head section
Copy the .html() contents from the loaded document's body tag
Append the link elements (copied out in step 1) to your host document's head
Create a new script tag with your copied script contents and stick it in the head too
Done!
Complicated? Kind of, I guess, but if you really want to load an entire page using AJAX it's your only option. It's also going to cause problems with the page's JavaScript no matter what you do, particularly code that's supposed to run during the initial load. There's nothing you can do about this. If it's a problem, you need to either rewrite the source page to be more load-friendly or you could figure out how to make an iFrame suit your needs.
It's also worth considering whether it'd work to just load your external CSS in the host document in the first place.
I suppose you are looking for something like this:
your page div --> load --> www.some-site.com
After a quik search the closest solution seems to be the one by "And": Load website into DIV
You have to run a web server and create a proxy.php page with this content:
Then your JQuery load() function should be like this:
$("#your_div_id").load("proxy.php?url=http://some-site.com");
NB. I have tested this solution and it should not load all the CSS from the target page, probably you'll have to recreate them. For example the image files stored on the remote server will not loaded, I suppose due to authentication policy.
You will be also able to view only the target page without the possibility to browse the target site.
Anyway I hope this could be a step forward to your solution.
Get your entire webpage as text using ajax
document.open();
document.write(this.responseText);
document.close();
OR
document.documentElement.outerHTML = this.responseText;
But you need to change the path of css and js pages in original webpage if the resulting webpage is in another directory.
basically i have a blank html page that includes a javascript file, and in the javascript file i have this:
function doIt() {
document.writeln("asdf");
}
// could also be setTimeout
setInterval("doIt()", 5000);
When the html page loads, it waits 5 seconds and then will output "asdf" every 5 seconds to the screen. If i hit refresh or f5, nothing happens. When i view the source, the page is blank. Is there any reason why when i view source i dont even see the:
<script type="text/javascript" src="test.js"></script>
on the html page? Im assuming i cant refresh the page because of the blank source. Any ways to resolve this?
Thanks!
You cannot use document.write like this after the page finishes loading.
Instead, you should append to the text of a DOM element.
When the html page loads, it waits 5 seconds and then will output "asdf" every 5 seconds to the screen.
When the page has finished loading, the document is closed and can't be written to. So if you call document.write() after this point, it assumes you mean to call document.open() and completely replace the page. The old document is unloaded to be replaced by the new one you're about to write, which is why you can't view the source of the old page any more.
And because you don't call document.close(), the throbber will keep spinning, waiting for the new document to be completed (which will never happen).
As SLaks said, you should interact with the DOM instead of using document.write() which is generally best avoided (except in a few specific cases to do with writing initial documents to popups or iframes).
thanks guys. i was able to see what you guys meant by having to modify the DOM to add in javascript after the page has loaded. I was able to do that but ran into the same issue:
basically i needed to use setInterval to do some polling to wait for data to be sent to this iframe from the parent, once it received the data, then it would output some javascript (which i created a new script element in the DOM for). but the problem is that the src of that element is pointing to an external url from which im getting some data from, and the way that external source returns the data is by using document.write - which i have no control over.
is there any other option for doing the polling besides using setInterval? i'd like to continue polling until a max timeout, and then if the max timeout is reached, then execute the rest of the page, then i wont have to worry about the document.write issue from the external source.
is another option to make that call to the external source and parse the response and create the dom elements with my javascript?
Just an idea, didn't have chance to test it.
Have your script create blank window and inject script into there to call the external script:
var oWindow = window.open("about:blank", "dummy", "width=0,height=0");
oWindow.document.write("<html>");
oWindow.document.write("<body>");
oWindow.document.write("<" + "script" + " type=\"text/javascript\" src=\"external.js\"></" + "script>");
oWindow.document.write("</body>");
oWindow.document.write("</html>");
oWindow.document.close();
and then read the oWindow.document.body.innerHTML to see the "output" of the external script.
I'd like to embed a number from another page. The remote call is small (only returns a number) but I would like the page to keep loading while the request is out. How should I do it? I'm currently doing
<span id="target">Loading ...</span>
<script>
var cb = function(data) {
document.getElementById("target").innerHTML = data;
}
</script>
<script src="http://webnumbr.com/webnumbrs.latest.json(callback=cb)"></script>
I'm open to client side or server side changes. Just the least code for the client embed the better
The "official" recommendation (see rules) is to put all JavaScript at the very bottom of the HTML file. The contents of every tag will be evaluated before rendering continues, as the outcome of the script might affect further rendering (think of document.write()).
Honestly,
I think the best way may be to simply put it in an onLoad() instruction so it doesn't load until the document has fully rendered. It's similar to Tom's answer but in this case you will eliminate the majority of the DOM issues you're experiencing.
I believe you are using AJAX to load the content from other page on loading the current page, make sure that your AJAX call is asynchronous, and update the "webNumbr_webnumbrs" control only after successfull completion.